diff --git a/packages/datastore/src/datastore.ts b/packages/datastore/src/datastore.ts index f2e31149e..8316f69e6 100644 --- a/packages/datastore/src/datastore.ts +++ b/packages/datastore/src/datastore.ts @@ -60,7 +60,7 @@ import { * diverging state between peers. */ export -class Datastore implements IIterable>, IMessageHandler, IDisposable { +class Datastore> implements IIterable>, IMessageHandler, IDisposable { /** * Create a new datastore. @@ -71,7 +71,7 @@ class Datastore implements IIterable>, IMessageHandler, IDisposabl * * @throws An exception if any of the schema definitions are invalid. */ - static create(options: Datastore.IOptions): Datastore { + static create>(options: Datastore.IOptions): Datastore { const {schemas} = options; // Throws an error for invalid schemas: Private.validateSchemas(schemas); @@ -85,7 +85,7 @@ class Datastore implements IIterable>, IMessageHandler, IDisposabl patch: {}, }; - const tables = new BPlusTree>(Private.recordCmp); + const tables = new BPlusTree>(Private.recordCmp); if (options.restoreState) { // If passed state to restore, pass the intital state to recreate each // table @@ -132,7 +132,7 @@ class Datastore implements IIterable>, IMessageHandler, IDisposabl * #### Complexity * `O(1)` */ - get changed(): ISignal { + get changed(): ISignal, Datastore.IChangedArgs> { return this._changed; } @@ -179,7 +179,7 @@ class Datastore implements IIterable>, IMessageHandler, IDisposabl * * @returns An iterator. */ - iter(): IIterator> { + iter(): IIterator> { return this._tables.iter(); } @@ -195,7 +195,7 @@ class Datastore implements IIterable>, IMessageHandler, IDisposabl * #### Complexity * `O(log32 n)` */ - get(schema: S): Table { + get(schema: S): Table { const t = this._tables.get(schema.id, Private.recordIdCmp); if (t === undefined) { throw new Error(`No table found for schema with id: ${schema.id}`); @@ -239,7 +239,7 @@ class Datastore implements IIterable>, IMessageHandler, IDisposabl if (this.broadcastHandler && !Private.isPatchEmpty(patch)) { MessageLoop.sendMessage( this.broadcastHandler, - new Datastore.TransactionMessage({ + new Datastore.TransactionMessage({ id: transactionId, storeId, patch, @@ -260,7 +260,7 @@ class Datastore implements IIterable>, IMessageHandler, IDisposabl switch (msg.type) { // External messages: case 'datastore-transaction': - const m = msg as Datastore.TransactionMessage; + const m = msg as Datastore.TransactionMessage; this._applyTransaction(m.transaction); break; @@ -341,8 +341,8 @@ class Datastore implements IIterable>, IMessageHandler, IDisposabl * @param tables - The tables of the datastore. */ private constructor( - context: Datastore.Context, - tables: BPlusTree>, + context: Datastore.Context, + tables: BPlusTree>, broadcastHandler?: IMessageHandler, transactionIdFactory?: Datastore.TransactionIdFactory ) { @@ -363,7 +363,7 @@ class Datastore implements IIterable>, IMessageHandler, IDisposabl * #### Notes * If changes are made, the `changed` signal will be emitted. */ - private _applyTransaction(transaction: Datastore.Transaction, fromQueue=false): void { + private _applyTransaction(transaction: Datastore.Transaction, fromQueue=false): void { if (!this._transactionQueue.isEmpty && !fromQueue) { // We have queued transactions waiting to be applied. // As we need to retain causal order of incoming transactions, @@ -381,7 +381,7 @@ class Datastore implements IIterable>, IMessageHandler, IDisposabl this._queueTransaction(transaction); return; } - const change: Datastore.MutableChange = {}; + const change: Datastore.MutableChange = {}; try { each(iterItems(patch), ([schemaId, tablePatch]) => { const table = this._tables.get(schemaId, Private.recordIdCmp); @@ -415,7 +415,7 @@ class Datastore implements IIterable>, IMessageHandler, IDisposabl * @throws An exception if a transaction is already in progress. */ private _initTransaction(id: string, newVersion: number): void { - const context = this._context as Private.MutableContext; + const context = this._context as Private.MutableContext; if (context.inTransaction) { throw new Error(`Already in a transaction: ${this._context.transactionId}`); } @@ -432,7 +432,7 @@ class Datastore implements IIterable>, IMessageHandler, IDisposabl * @throws An exception if no transaction is in progress. */ private _finalizeTransaction(): void { - const context = this._context as Private.MutableContext; + const context = this._context as Private.MutableContext; if (!context.inTransaction) { throw new Error('No transaction in progress.'); } @@ -444,7 +444,7 @@ class Datastore implements IIterable>, IMessageHandler, IDisposabl * * @param transaction - The transaction to queue. */ - private _queueTransaction(transaction: Datastore.Transaction): void { + private _queueTransaction(transaction: Datastore.Transaction): void { this._transactionQueue.addLast(transaction); MessageLoop.postMessage(this, new ConflatableMessage('queued-transaction')); } @@ -482,11 +482,11 @@ class Datastore implements IIterable>, IMessageHandler, IDisposabl private _broadcastHandler: IMessageHandler | null; private _disposed = false; - private _tables: BPlusTree>; - private _context: Datastore.Context; - private _changed = new Signal(this); + private _tables: BPlusTree>; + private _context: Datastore.Context; + private _changed = new Signal, Datastore.IChangedArgs>(this); private _transactionIdFactory: Datastore.TransactionIdFactory; - private _transactionQueue = new LinkedList(); + private _transactionQueue = new LinkedList>(); } @@ -499,7 +499,7 @@ namespace Datastore { * An options object for initializing a datastore. */ export - interface IOptions { + interface IOptions> { /** * The unique id of the datastore. */ @@ -508,7 +508,7 @@ namespace Datastore { /** * The table schemas of the datastore. */ - schemas: ReadonlyArray; + schemas: T; /** * An optional handler for broadcasting transactions to peers. @@ -530,7 +530,7 @@ namespace Datastore { * The arguments object for the store `changed` signal. */ export - interface IChangedArgs { + interface IChangedArgs { /** * Whether the change was generated by transaction, undo, or redo. */ @@ -549,46 +549,46 @@ namespace Datastore { /** * A mapping of schema id to table change set. */ - readonly change: Change; + readonly change: Change; } /** * A type alias for a store change. */ export - type Change = { - readonly [schemaId: string]: Table.Change; + type Change = { + readonly [schemaId: string]: Table.Change; }; /** * A type alias for a store patch. */ export - type Patch = { - readonly [schemaId: string]: Table.Patch; + type Patch = { + readonly [schemaId: string]: Table.Patch; }; /** * @internal */ export - type MutableChange = { - [schemaId: string]: Table.MutableChange; + type MutableChange = { + [schemaId: string]: Table.MutableChange; }; /** * @internal */ export - type MutablePatch = { - [schemaId: string]: Table.MutablePatch; + type MutablePatch = { + [schemaId: string]: Table.MutablePatch; }; /** * An object representing a datastore transaction. */ export - type Transaction = { + type Transaction = { /** * The id of the transaction. @@ -603,7 +603,7 @@ namespace Datastore { /** * The patch data of the transaction. */ - readonly patch: Patch; + readonly patch: Patch; /** * The version of the source datastore. @@ -615,15 +615,15 @@ namespace Datastore { * A message of a datastore transaction. */ export - class TransactionMessage extends Message { - constructor(transaction: Transaction) { + class TransactionMessage extends Message { + constructor(transaction: Transaction) { super('datastore-transaction'); this.transaction = transaction; } /** * The transaction associated with the change. */ - readonly transaction: Transaction; + readonly transaction: Transaction; readonly type: 'datastore-transaction'; } @@ -632,7 +632,7 @@ namespace Datastore { * @internal */ export - type Context = Readonly; + type Context = Readonly>; /** * A factory function for generating a unique transaction id. @@ -677,7 +677,7 @@ namespace Private { } export - type MutableContext = { + type MutableContext = { /** * Whether the datastore currently in a transaction. */ @@ -701,19 +701,19 @@ namespace Private { /** * The current change object of the transaction. */ - change: Datastore.MutableChange; + change: Datastore.MutableChange; /** * The current patch object of the transaction. */ - patch: Datastore.MutablePatch; + patch: Datastore.MutablePatch; } /** * Checks if a patch is empty. */ export - function isPatchEmpty(patch: Datastore.Patch): boolean { + function isPatchEmpty(patch: Datastore.Patch): boolean { return Object.keys(patch).length === 0; } @@ -721,7 +721,7 @@ namespace Private { * Checks if a change is empty. */ export - function isChangeEmpty(change: Datastore.Change): boolean { + function isChangeEmpty(change: Datastore.Change): boolean { return Object.keys(change).length === 0; } } diff --git a/packages/datastore/src/table.ts b/packages/datastore/src/table.ts index 02095fe8b..1572b2973 100644 --- a/packages/datastore/src/table.ts +++ b/packages/datastore/src/table.ts @@ -42,7 +42,7 @@ class Table implements IIterable> { * * @returns A new datastore table. */ - static create(schema: U, context: Datastore.Context): Table { + static create(schema: U, context: Datastore.Context): Table { return new Table(schema, context); } @@ -57,7 +57,7 @@ class Table implements IIterable> { * * @returns A new datastore table. */ - static recreate(schema: U, context: Datastore.Context, records: IterableOrArrayLike>): Table { + static recreate(schema: U, context: Datastore.Context, records: IterableOrArrayLike>): Table { return new Table(schema, context, records); } @@ -213,7 +213,7 @@ class Table implements IIterable> { * * @param context - The datastore context. */ - private constructor(schema: S, context: Datastore.Context, records?: IterableOrArrayLike>) { + private constructor(schema: S, context: Datastore.Context, records?: IterableOrArrayLike>) { this.schema = schema; this._context = context; if (records) { @@ -221,7 +221,7 @@ class Table implements IIterable> { } } - private _context: Datastore.Context; + private _context: Datastore.Context; private _records = new BPlusTree>(Private.recordCmp); } @@ -341,7 +341,7 @@ namespace Private { * @returns A new record with the update applied. */ export - function applyUpdate(schema: S, record: Record, update: Record.Update, context: Datastore.Context): Record { + function applyUpdate(schema: S, record: Record, update: Record.Update, context: Datastore.Context): Record { // Fetch the version and store id. let version = context.version; let storeId = context.storeId; diff --git a/packages/datastore/tests/src/datastore.spec.ts b/packages/datastore/tests/src/datastore.spec.ts index 65acf3a41..8a440663d 100644 --- a/packages/datastore/tests/src/datastore.spec.ts +++ b/packages/datastore/tests/src/datastore.spec.ts @@ -10,7 +10,7 @@ import { } from 'chai'; import { - Datastore, Fields, ListField, RegisterField, TextField + Datastore, Fields, ListField, RegisterField, TextField, Schema } from '@phosphor/datastore'; import { @@ -78,21 +78,21 @@ class LoggingMessageHandler implements IMessageHandler { processMessage(msg: Message): void { switch(msg.type) { case 'datastore-transaction': - this.transactions.push((msg as Datastore.TransactionMessage).transaction); + this.transactions.push((msg as Datastore.TransactionMessage).transaction); break; default: throw Error('Unexpected message'); break; } } - transactions: Datastore.Transaction[] = []; + transactions: Datastore.Transaction[] = []; } describe('@phosphor/datastore', () => { describe('Datastore', () => { - let datastore: Datastore; + let datastore: Datastore<[typeof schema1, typeof schema2]>; let broadcastHandler: LoggingMessageHandler; const DATASTORE_ID = 1234; beforeEach(() => { diff --git a/packages/datastore/tests/src/table.spec.ts b/packages/datastore/tests/src/table.spec.ts index 520f71996..713b1eed3 100644 --- a/packages/datastore/tests/src/table.spec.ts +++ b/packages/datastore/tests/src/table.spec.ts @@ -45,7 +45,7 @@ let schema: TestSchema = { /** * Remove readonly guards from Context for testing purposes. */ -type MutableContext = { -readonly [K in keyof Datastore.Context]: Datastore.Context[K] }; +type MutableContext = { -readonly [K in keyof Datastore.Context]: Datastore.Context[K] }; describe('@phosphor/datastore', () => {