removing stream interface

This commit is contained in:
balzack 2024-10-28 21:41:47 -07:00
parent 1aec4d3894
commit 7fd1f4db31
8 changed files with 200 additions and 215 deletions

View File

@ -3,7 +3,7 @@ import {DatabagSDK, Session} from 'databag-client-sdk';
import {SessionStore} from '../SessionStore';
import {NativeCrypto} from '../NativeCrypto';
import {LocalStore} from '../LocalStore';
const DATABAG_DB = 'db_v214.db';
const DATABAG_DB = 'db_v215.db';
const SETTINGS_DB = 'ls_v001.db';
const databag = new DatabagSDK(

View File

@ -122,14 +122,10 @@ Automate allocates the Bot interface for ia specific communication channel
```Session::getAttribute(): Attribute```
Account content channels are managed through the Content Interface
Account and Contact channels are managed through the Content Interface
```Session::getContent(): Content```
An aggregation of content channels provided by contacts is managed through the Stream Interface
```Session::getStream(): Stream```
WebRTC calling is managed through the Ring Interface
```Session::getRing(): Ring```

View File

@ -1,8 +1,7 @@
import { EventEmitter } from 'eventemitter3';
import type { Content } from '../src/api';
import type { Channel, Topic, Asset, Tag, Participant } from '../src/types';
export class MockContentModule implements Content {
export class MockStreamModule {
public revision: number;
private emitter: EventEmitter;

View File

@ -5,7 +5,7 @@ import { MockConnection } from '../__mocks__/connection';
import { MockSettingsModule } from '../__mocks__/settings';
import { MockIdentityModule } from '../__mocks__/identity';
import { MockAliasModule } from '../__mocks__/alias';
import { MockContentModule } from '../__mocks__/content';
import { MockStreamModule } from '../__mocks__/stream';
import { MockContactModule } from '../__mocks__/contact';
import { MockAttributeModule } from '../__mocks__/attribute';
import { MockRingModule } from '../__mocks__/ring';
@ -49,11 +49,11 @@ jest.mock('../src/identity', () => {
}
})
const mockContent = new MockContentModule();
jest.mock('../src/content', () => {
const mockStream = new MockStreamModule();
jest.mock('../src/stream', () => {
return {
ContentModule: jest.fn().mockImplementation(() => {
return mockContent;
StreamModule: jest.fn().mockImplementation(() => {
return mockStream;
})
}
})
@ -109,7 +109,7 @@ test('allocates session correctly', async () => {
await waitFor(() => (mockRing.call?.callId === 'test'));
await waitFor(() => (mockSettings.revision == 3));
await waitFor(() => (mockIdentity.revision == 3));
await waitFor(() => (mockContent.revision == 3));
await waitFor(() => (mockStream.revision == 3));
await waitFor(() => (mockContact.revision == 3));
await waitFor(() => (mockAttribute.revision == 3));
await waitFor(() => (mockAlias.revision == 3));

View File

@ -6,7 +6,7 @@ export interface Session {
getContact(): Contact;
getAlias(): Alias;
getAttribute(): Attribute;
getStream(): Stream;
getContent(): Content;
getRing(): Ring;
setFocus(cardId: string | null, channelId: string): Promise<Focus>;
@ -93,23 +93,6 @@ export interface Content {
setChannelSubject(channelId: string, subject: string): Promise<void>;
setChannelCard(channelId: string, cardId: string): Promise<void>;
clearChannelCard(channelId: string, cardId: string): Promise<void>;
setBlockedChannel(channelId: string, blocked: boolean): Promise<void>;
getBlockedChannels(): Promise<Channel[]>;
flagChannel(channelId: string): Promise<void>;
getChannelNotifications(channelId: string): Promise<boolean>;
setChannelNotifications(channelId: string, enabled: boolean): Promise<void>;
setUnreadChannel(channelId: string, unread: boolean): Promise<void>;
addChannelListener(ev: (arg: { channels: Channel[], cardId: string | null }) => void): void;
removeChannelListener(ev: (arg: { channels: Channel[], cardId: string | null }) => void): void;
}
export interface Stream {
addChannel(sealed: boolean, type: string, subject: string, cardIds: string[]): Promise<string>;
removeChannel(channelId: string): Promise<void>;
setChannelSubject(channelId: string, subject: string): Promise<void>;
setChannelCard(channelId: string, cardId: string): Promise<void>;
clearChannelCard(channelId: string, cardId: string): Promise<void>;
leaveChannel(cardId: string, channelId: string): Promise<void>;

View File

@ -1,121 +1,92 @@
import { EventEmitter } from 'eventemitter3';
import type { Content, Logging, Focus } from './api';
import { FocusModule } from './focus';
import type { ChannelItem } from './items';
import type { Channel, Topic, Asset, Tag, Participant } from './types';
import { Store } from './store';
import { Crypto } from './crypto';
import type { Content } from './api';
import type { Channel } from './types';
import { ContactModule } from './contact';
import { StreamModule } from './stream';
import { Logging } from './logging';
export class ContentModule implements Content {
private log: Logging;
private store: Store;
private crypto: Crypto | null;
private guid: string;
private token: string;
private node: string;
private secure: boolean;
private emitter: EventEmitter;
private focus: Focus | null;
private revision: number;
private syncing: boolean;
private closing: boolean;
private nextRevision: number | null;
private contact: ContactModule;
private stream: StreamModule;
// view of channels
private channelEntries: Map<string, { item: ChannelItem; channel: Channel }>;
constructor(log: Logging, store: Store, crypto: Crypto | null, guid: string, token: string, node: string, secure: boolean) {
this.guid = guid;
this.token = token;
this.node = node;
this.secure = secure;
constructor(log: Logging, contact: ContactModule, stream: StreamModule) {
this.contact = contact;
this.stream = stream;
this.log = log;
this.store = store;
this.crypto = crypto;
this.focus = null;
this.emitter = new EventEmitter();
this.channelEntries = new Map<string, { item: ChannelItem; channel: Channel }>();
this.revision = 0;
this.syncing = true;
this.closing = false;
this.nextRevision = null;
this.init();
}
private async init() { }
private async sync() { }
public addChannelListener(ev: (arg: { channels: Channel[], cardId: string | null }) => void): void {
this.emitter.on('channel', ev);
const channels = Array.from(this.channelEntries, ([channelId, entry]) => entry.channel);
ev({ channels, cardId: null });
}
public removeChannelListener(ev: (arg: { channels: Channel[], cardId: string | null }) => void): void {
this.emitter.off('channel', ev);
}
private emitChannels() {
const channels = Array.from(this.channelEntries, ([channelId, entry]) => entry.channel);
this.emitter.emit('channel', { channels, cardId: null });
}
public async close(): void {}
public async setRevision(rev: number): Promise<void> {
console.log('set content revision:', rev);
}
public async addChannel(sealed: boolean, type: string, subject: string, cardIds: string[]): Promise<string> {
return '';
return await this.stream.addChannel(sealed, type, subject, cardIds);
}
public async removeChannel(channelId: string): Promise<void> { }
setChannelSubject(channelId: string, subject: string): Promise<void> { }
setChannelCard(channelId: string, cardId: string): Promise<void> { }
clearChannelCard(channelId: string, cardId: string): Promise<void> { }
setBlockedChannel(channelId: string, blocked: boolean): Promise<void> { }
getBlockedChannels(): Promise<Channel[]> {
return [];
public async removeChannel(channelId: string): Promise<void> {
return await this.stream.removeChannel(channelId);
}
flagChannel(channelId: string): Promise<void> { }
getChannelNotifications(channelId: string): Promise<boolean> {
return false;
public async setChannelSubject(channelId: string, subject: string): Promise<void> {
return await this.stream.setChannelSubject(channelId, subject);
}
setChannelNotifications(channelId: string, enabled: boolean): Promise<void> { }
public async setChannelCard(channelId: string, cardId: string): Promise<void> {
return await this.stream.setChannelCard(channelId, cardId);
}
setUnreadChannel(channelId: string, unread: boolean): Promise<void> { }
public async clearChannelCard(channelId: string, cardId: string): Promise<void> {
return await this.stream.clearChannelCard(channelId, cardId);
}
public async setFocus(chanenlId: string): Promise<Focus> {
const { node, secure, token, focus } = this;
if (focus) {
await focus.close();
public async leaveChannel(cardId: string, channelId: string): Promise<void> {
return await this.contact.leaveChannel(cardId, channelId)
}
public async getChannelNotifications(cardId: string | null, channelId: string): Promise<boolean> {
if (cardId) {
return await this.contact.getChannelNotifications(cardId, channelId);
}
this.focus = new FocusModule(this.log, this.store, this.crypto, null, channelId, { node, secure, token });
return this.focus;
return await this.stream.getChannelNotifications(channelId)
}
public async clearFocus() {
if (this.focus) {
await this.focus.close();
public async setChannelNotifications(cardId: string | null, channelId: string, enabled: boolean): Promise<void> {
if (cardId) {
return await this.contact.setChannelNotifications(cardId, channelId, enabled)
}
this.focus = null;
return await this.stream.setChannelNotifications(channelId, enabled);
}
public async setSeal(seal: { privateKey: string; publicKey: string } | null) {
this.seal = seal;
this.unsealAll = true;
await this.sync();
public async setUnreadChannel(cardId: string | null, channelId: string, unread: boolean): Promise<void> {
if (cardId) {
return await this.contact.setUnreadChannel(cardId, channelId, unread);
}
return await this.stream.setUnreadChannel(channelId, unread);
}
public async flagChannel(cardId: string, channelId: string): Promise<void> {
if (cardId) {
return await this.contact.flagChannel(cardId, channelId);
}
return await this.stream.flagChannel(channelId);
}
public async setBlockedChannel(cardId: string | null, channelId: string, blocked: boolean): Promise<void> {
if (cardId) {
return await this.contact.setBlockedChannel(cardId, channelId, blocked);
}
return await this.stream.setBlockedChannel(channelId, blocked);
}
public async getBlockedChannels(): Promise<Channel[]> {
const channels = await this.stream.getBlockedChannels();
const cardChannels = await this.contact.getBlockedChannels();
return channels.concat(cardChannels);
}
public addChannelListener(ev: (arg: { channels: Channel[], cardId: string | null }) => void): void {
this.stream.addChannelListener(ev);
this.contact.addChannelListener(ev);
}
public removeChannelListener(ev: (arg: { channels: Channel[], cardId: string | null }) => void): void {
this.stream.removeChannelListener(ev);
this.contact.removeChannelListener(ev);
}
}

View File

@ -12,7 +12,7 @@ import { RingModule } from './ring';
import { Connection } from './connection';
import type { Session, Settings, Identity, Contact, Ring, Alias, Attribute, Content, Stream, Focus } from './api';
import type { Session, Settings, Identity, Contact, Ring, Alias, Attribute, Content, Focus } from './api';
import { Revision } from './entities';
import { Call } from './types';
import { Store } from './store';
@ -63,8 +63,8 @@ export class SessionModule implements Session {
this.contact = new ContactModule(log, this.store, this.crypto, guid, token, node, secure, channelTypes, articleTypes);
this.alias = new AliasModule(log, this.settings, this.store, guid, token, node, secure);
this.attribute = new AttributeModule(log, this.settings, this.store, guid, token, node, secure);
this.content = new ContentModule(log, this.store, this.crypto, guid, token, node, secure);
this.stream = new StreamModule(log, this.contact, this.content);
this.stream = new StreamModule(log, this.store, this.crypto, guid, token, node, secure);
this.content = new ContentModule(log, this.contact, this.stream);
this.ring = new RingModule(log);
this.connection = new Connection(log, token, node, secure);
@ -75,7 +75,7 @@ export class SessionModule implements Session {
const onSeal = (seal: { privateKey: string; publicKey: string } | null) => {
this.contact.setSeal(seal);
this.content.setSeal(seal);
this.stream.setSeal(seal);
};
const onRevision = async (ev: Revision) => {
@ -84,7 +84,7 @@ export class SessionModule implements Session {
await this.contact.setRevision(ev.card);
await this.attribute.setRevision(ev.article);
await this.alias.setRevision(ev.group);
await this.content.setRevision(ev.channel);
await this.stream.setRevision(ev.channel);
};
const onRing = (ev: Call) => {
@ -115,7 +115,7 @@ export class SessionModule implements Session {
}
public async close(): Promise<void> {
await this.content.close();
await this.stream.close();
await this.attribute.close();
await this.alias.close();
await this.contact.close();
@ -144,8 +144,8 @@ export class SessionModule implements Session {
return this.attribute;
}
public getStream(): Stream {
return this.stream;
public getContent(): Content {
return this.content;
}
public getRing(): Ring {
@ -156,11 +156,11 @@ export class SessionModule implements Session {
if (cardId) {
return await this.contact.setFocus(cardId, channelId);
}
return await this.content.setFocus(channelId);
return await this.stream.setFocus(channelId);
}
public async clearFocus(): Promise<void> {
await this.contact.clearFocus();
await this.content.clearFocus();
await this.stream.clearFocus();
}
}

View File

@ -1,90 +1,126 @@
import type { Contact, Content, Stream } from './api';
import type { Channel } from './types';
import { EventEmitter } from 'eventemitter3';
import type { Content, Focus } from './api';
import { Logging } from './logging';
import { FocusModule } from './focus';
import type { ChannelItem } from './items';
import type { Channel, Topic, Asset, Tag, Participant } from './types';
import { Store } from './store';
import { Crypto } from './crypto';
export class StreamModule implements Stream {
export class StreamModule {
private log: Logging;
private contact: Contact;
private content: Content;
private store: Store;
private crypto: Crypto | null;
private guid: string;
private token: string;
private node: string;
private secure: boolean;
private emitter: EventEmitter;
private focus: FocusModule | null;
private revision: number;
private syncing: boolean;
private closing: boolean;
private nextRevision: number | null;
private seal: { privateKey: string; publicKey: string } | null;
private unsealAll: boolean;
constructor(log: Logging, contact: Contact, content: Content) {
this.contact = contact;
this.content = content;
// view of channels
private channelEntries: Map<string, { item: ChannelItem; channel: Channel }>;
constructor(log: Logging, store: Store, crypto: Crypto | null, guid: string, token: string, node: string, secure: boolean) {
this.guid = guid;
this.token = token;
this.node = node;
this.secure = secure;
this.log = log;
this.store = store;
this.crypto = crypto;
this.focus = null;
this.seal = null;
this.unsealAll = false;
this.emitter = new EventEmitter();
this.channelEntries = new Map<string, { item: ChannelItem; channel: Channel }>();
this.revision = 0;
this.syncing = true;
this.closing = false;
this.nextRevision = null;
this.init();
}
public async addChannel(sealed: boolean, type: string, subject: string, cardIds: string[]): Promise<string> {
return await this.content.addChannel(sealed, type, subject, cardIds);
}
private async init() { }
public async removeChannel(channelId: string): Promise<void> {
return await this.content.removeChannel(channelId);
}
public async setChannelSubject(channelId: string, subject: string): Promise<void> {
return await this.content.setChannelSubject(channelId, subject);
}
public async setChannelCard(channelId: string, cardId: string): Promise<void> {
return await this.content.setChannelCard(channelId, cardId);
}
public async clearChannelCard(channelId: string, cardId: string): Promise<void> {
return await this.content.clearChannelCard(channelId, cardId);
}
public async leaveChannel(cardId: string, channelId: string): Promise<void> {
return await this.contact.leaveChannel(cardId, channelId)
}
public async getChannelNotifications(cardId: string | null, channelId: string): Promise<boolean> {
if (cardId) {
return await this.contact.getChannelNotifications(cardId, channelId);
}
return await this.content.getChannelNotifications(channelId)
}
public async setChannelNotifications(cardId: string | null, channelId: string, enabled: boolean): Promise<void> {
if (cardId) {
return await this.contact.setChannelNotifications(cardId, channelId, enabled)
}
return await this.content.setChannelNotifications(channelId, enabled);
}
public async setUnreadChannel(cardId: string | null, channelId: string, unread: boolean): Promise<void> {
if (cardId) {
return await this.contact.setUnreadChannel(cardId, channelId, unread);
}
return await this.content.setUnreadChannel(channelId, unread);
}
public async flagChannel(cardId: string, channelId: string): Promise<void> {
if (cardId) {
return await this.contact.flagChannel(cardId, channelId);
}
return await this.content.flagChannel(channelId);
}
public async setBlockedChannel(cardId: string | null, channelId: string, blocked: boolean): Promise<void> {
if (cardId) {
return await this.contact.setBlockedChannel(cardId, channelId, blocked);
}
return await this.content.setBlockedChannel(channelId, blocked);
}
public async getBlockedChannels(): Promise<Channel[]> {
const channels = await this.content.getBlockedChannels();
const cardChannels = await this.contact.getBlockedChannels();
return channels.concat(cardChannels);
}
private async sync() { }
public addChannelListener(ev: (arg: { channels: Channel[], cardId: string | null }) => void): void {
this.content.addChannelListener(ev);
this.contact.addChannelListener(ev);
this.emitter.on('channel', ev);
const channels = Array.from(this.channelEntries, ([channelId, entry]) => entry.channel);
ev({ channels, cardId: null });
}
public removeChannelListener(ev: (arg: { channels: Channel[], cardId: string | null }) => void): void {
this.content.removeChannelListener(ev);
this.contact.removeChannelListener(ev);
this.emitter.off('channel', ev);
}
private emitChannels() {
const channels = Array.from(this.channelEntries, ([channelId, entry]) => entry.channel);
this.emitter.emit('channel', { channels, cardId: null });
}
public async close(): Promise<void> {}
public async setRevision(rev: number): Promise<void> {
console.log('set content revision:', rev);
}
public async addChannel(sealed: boolean, type: string, subject: string, cardIds: string[]): Promise<string> {
return '';
}
public async removeChannel(channelId: string): Promise<void> { }
public async setChannelSubject(channelId: string, subject: string): Promise<void> { }
public async setChannelCard(channelId: string, cardId: string): Promise<void> { }
public async clearChannelCard(channelId: string, cardId: string): Promise<void> { }
public async setBlockedChannel(channelId: string, blocked: boolean): Promise<void> { }
public async getBlockedChannels(): Promise<Channel[]> {
return [];
}
public async flagChannel(channelId: string): Promise<void> { }
public async getChannelNotifications(channelId: string): Promise<boolean> {
return false;
}
public async setChannelNotifications(channelId: string, enabled: boolean): Promise<void> { }
public async setUnreadChannel(channelId: string, unread: boolean): Promise<void> { }
public async setFocus(channelId: string): Promise<Focus> {
const { node, secure, token, focus } = this;
if (focus) {
await focus.close();
}
this.focus = new FocusModule(this.log, this.store, this.crypto, null, channelId, this.guid, { node, secure, token });
return this.focus;
}
public async clearFocus() {
if (this.focus) {
await this.focus.close();
}
this.focus = null;
}
public async setSeal(seal: { privateKey: string; publicKey: string } | null) {
this.seal = seal;
this.unsealAll = true;
await this.sync();
}
}