diff --git a/dev/storage/src/storage.ts b/dev/storage/src/storage.ts index 864ed2e507..6f98b9d19f 100644 --- a/dev/storage/src/storage.ts +++ b/dev/storage/src/storage.ts @@ -46,7 +46,7 @@ class InMemoryTxAdapter implements TxAdapter { } class InMemoryAdapter implements DbAdapter { - private readonly modeldb: TxDb + private readonly modeldb: ModelDb constructor (hierarchy: Hierarchy) { this.modeldb = new ModelDb(hierarchy) diff --git a/packages/core/src/component.ts b/packages/core/src/component.ts index 481a4ca470..4abd0a5fce 100644 --- a/packages/core/src/component.ts +++ b/packages/core/src/component.ts @@ -14,8 +14,8 @@ // import type { Plugin, StatusCode } from '@anticrm/platform' import { plugin } from '@anticrm/platform' -import type { Account, Class, Doc, Obj, Ref, Space, AnyAttribute, State, Type } from './classes' -import type { Tx, TxCreateDoc, TxCUD, TxMixin, TxRemoveDoc, TxUpdateDoc } from './tx' +import type { Account, Class, Doc, Obj, Ref, Space, AnyAttribute, State, Type, PropertyType } from './classes' +import type { Tx, TxCreateDoc, TxCUD, TxMixin, TxPutBag, TxRemoveDoc, TxUpdateDoc } from './tx' /** * @public @@ -34,6 +34,7 @@ export default plugin(coreId, { TxMixin: '' as Ref>>, TxUpdateDoc: '' as Ref>>, TxRemoveDoc: '' as Ref>>, + TxPutBag: '' as Ref>>, Space: '' as Ref>, Account: '' as Ref>, State: '' as Ref>, diff --git a/packages/core/src/memdb.ts b/packages/core/src/memdb.ts index d294287aa3..41799b252f 100644 --- a/packages/core/src/memdb.ts +++ b/packages/core/src/memdb.ts @@ -15,7 +15,7 @@ import { PlatformError, Severity, Status } from '@anticrm/platform' import type { Class, Doc, Ref } from './classes' -import type { Tx, TxCreateDoc, TxMixin, TxRemoveDoc, TxUpdateDoc } from './tx' +import type { Tx, TxCreateDoc, TxMixin, TxPutBag, TxRemoveDoc, TxUpdateDoc } from './tx' import core from './component' import type { Hierarchy } from './hierarchy' import { _getOperator } from './operator' @@ -26,7 +26,7 @@ import { TxProcessor } from './tx' /** * @public */ -export class MemDb extends TxProcessor { +export abstract class MemDb extends TxProcessor { protected readonly hierarchy: Hierarchy private readonly objectsByClass = new Map>, Doc[]>() private readonly objectById = new Map, Doc>() @@ -147,6 +147,26 @@ export class MemDb extends TxProcessor { * @public */ export class TxDb extends MemDb implements Storage { + protected txCreateDoc (tx: TxCreateDoc): Promise { + throw new Error('Method not implemented.') + } + + protected txPutBag (tx: TxPutBag): Promise { + throw new Error('Method not implemented.') + } + + protected txUpdateDoc (tx: TxUpdateDoc): Promise { + throw new Error('Method not implemented.') + } + + protected txRemoveDoc (tx: TxRemoveDoc): Promise { + throw new Error('Method not implemented.') + } + + protected txMixin (tx: TxMixin): Promise { + throw new Error('Method not implemented.') + } + async tx (tx: Tx): Promise { this.addDoc(tx) } @@ -158,7 +178,18 @@ export class TxDb extends MemDb implements Storage { * @public */ export class ModelDb extends MemDb implements Storage { - protected async txCreateDoc (tx: TxCreateDoc): Promise { + protected override async txPutBag (tx: TxPutBag): Promise { + const doc = this.getObject(tx.objectId) as any + let bag = doc[tx.bag] + if (bag === undefined) { + doc[tx.bag] = bag = {} + } + bag[tx.key] = tx.value + doc.modifiedBy = tx.modifiedBy + doc.modifiedOn = tx.modifiedOn + } + + protected override async txCreateDoc (tx: TxCreateDoc): Promise { this.addDoc(TxProcessor.createDoc2Doc(tx)) } diff --git a/packages/core/src/tx.ts b/packages/core/src/tx.ts index dd1eb4f765..a9c211af6a 100644 --- a/packages/core/src/tx.ts +++ b/packages/core/src/tx.ts @@ -14,7 +14,7 @@ // import type { KeysByType } from 'simplytyped' -import type { Class, Data, Doc, Domain, Ref, Account, Space, Arr, Mixin } from './classes' +import type { Class, Data, Doc, Domain, Ref, Account, Space, Arr, Mixin, PropertyType } from './classes' import { DocumentQuery, FindOptions, FindResult, Storage, WithLookup } from './storage' import core from './component' import { generateId } from './utils' @@ -41,6 +41,15 @@ export interface TxCreateDoc extends TxCUD { attributes: Data } +/** + * @public + */ +export interface TxPutBag extends TxCUD { + bag: string + key: string + value: T +} + /** * @public */ @@ -116,7 +125,7 @@ export interface WithTx { /** * @public */ -export class TxProcessor implements WithTx { +export abstract class TxProcessor implements WithTx { async tx (tx: Tx): Promise { switch (tx._class) { case core.class.TxCreateDoc: @@ -127,6 +136,8 @@ export class TxProcessor implements WithTx { return await this.txRemoveDoc(tx as TxRemoveDoc) case core.class.TxMixin: return await this.txMixin(tx as TxMixin) + case core.class.TxPutBag: + return await this.txPutBag(tx as TxPutBag) } throw new Error('TxProcessor: unhandled transaction class: ' + tx._class) } @@ -143,10 +154,11 @@ export class TxProcessor implements WithTx { } as T } - protected async txCreateDoc (tx: TxCreateDoc): Promise {} - protected async txUpdateDoc (tx: TxUpdateDoc): Promise {} - protected async txRemoveDoc (tx: TxRemoveDoc): Promise {} - protected async txMixin (tx: TxMixin): Promise {} + protected abstract txCreateDoc (tx: TxCreateDoc): Promise + protected abstract txPutBag (tx: TxPutBag): Promise + protected abstract txUpdateDoc (tx: TxUpdateDoc): Promise + protected abstract txRemoveDoc (tx: TxRemoveDoc): Promise + protected abstract txMixin (tx: TxMixin): Promise } /** @@ -182,6 +194,18 @@ export class TxOperations implements Storage { return tx.objectId } + putBag

( + _class: Ref>, + space: Ref, + objectId: Ref, + bag: string, + key: string, + value: P + ): Promise { + const tx = this.txFactory.createTxPutBag(_class, space, objectId, bag, key, value) + return this.storage.tx(tx) + } + updateDoc ( _class: Ref>, space: Ref, @@ -232,6 +256,29 @@ export class TxFactory { } } + createTxPutBag

( + _class: Ref>, + space: Ref, + objectId: Ref, + bag: string, + key: string, + value: P + ): TxPutBag

{ + return { + _id: generateId(), + _class: core.class.TxUpdateDoc, + space: core.space.Tx, + modifiedBy: this.account, + modifiedOn: Date.now(), + objectId, + objectClass: _class, + objectSpace: space, + bag, + key, + value + } + } + createTxUpdateDoc ( _class: Ref>, space: Ref, diff --git a/packages/query/src/index.ts b/packages/query/src/index.ts index 97412ff0bd..aeb0a85011 100644 --- a/packages/query/src/index.ts +++ b/packages/query/src/index.ts @@ -16,7 +16,7 @@ import { Ref, Class, Doc, Tx, DocumentQuery, TxCreateDoc, TxRemoveDoc, Client, FindOptions, TxUpdateDoc, _getOperator, TxProcessor, resultSort, SortingQuery, - FindResult, Hierarchy, Refs, WithLookup, LookupData + FindResult, Hierarchy, Refs, WithLookup, LookupData, TxMixin, TxPutBag } from '@anticrm/core' interface Query { @@ -87,6 +87,14 @@ export class LiveQuery extends TxProcessor implements Client { } } + protected txPutBag (tx: TxPutBag): Promise { + throw new Error('Method not implemented.') + } + + protected txMixin (tx: TxMixin): Promise { + throw new Error('Method not implemented.') + } + protected async txUpdateDoc (tx: TxUpdateDoc): Promise { for (const q of this.queries) { if (q.result instanceof Promise) { diff --git a/server/core/src/fulltext.ts b/server/core/src/fulltext.ts index 0fb25ed9ad..b587ac659e 100644 --- a/server/core/src/fulltext.ts +++ b/server/core/src/fulltext.ts @@ -14,7 +14,7 @@ // limitations under the License. // -import core, { Hierarchy, AnyAttribute, Storage, DocumentQuery, FindOptions, FindResult, TxProcessor } from '@anticrm/core' +import core, { Hierarchy, AnyAttribute, Storage, DocumentQuery, FindOptions, FindResult, TxProcessor, TxMixin, TxPutBag, TxRemoveDoc } from '@anticrm/core' import type { AttachedDoc, TxUpdateDoc, TxCreateDoc, Doc, Ref, Class, Obj } from '@anticrm/core' import type { IndexedDoc, FullTextAdapter, WithFind } from './types' @@ -33,6 +33,18 @@ export class FullTextIndex extends TxProcessor implements Storage { super() } + protected txPutBag (tx: TxPutBag): Promise { + throw new Error('Method not implemented.') + } + + protected txRemoveDoc (tx: TxRemoveDoc): Promise { + throw new Error('Method not implemented.') + } + + protected txMixin (tx: TxMixin): Promise { + throw new Error('Method not implemented.') + } + async findAll (_class: Ref>, query: DocumentQuery, options?: FindOptions): Promise> { console.log('search', query) const docs = await this.adapter.search(query) diff --git a/server/mongo/src/storage.ts b/server/mongo/src/storage.ts index 6b08e07532..50bd766774 100644 --- a/server/mongo/src/storage.ts +++ b/server/mongo/src/storage.ts @@ -13,8 +13,8 @@ // limitations under the License. // -import type { Tx, Ref, Doc, Class, DocumentQuery, FindResult, FindOptions, TxCreateDoc, TxUpdateDoc } from '@anticrm/core' -import core, { TxProcessor, Hierarchy, DOMAIN_TX, SortingOrder } from '@anticrm/core' +import core, { Tx, Ref, Doc, Class, DocumentQuery, FindResult, FindOptions, TxCreateDoc, TxUpdateDoc, TxMixin, TxPutBag, TxRemoveDoc, TxProcessor, Hierarchy, DOMAIN_TX, SortingOrder } from '@anticrm/core' + import type { DbAdapter, TxAdapter } from '@anticrm/server-core' import { MongoClient, Db, Filter, Document, Sort } from 'mongodb' @@ -92,6 +92,18 @@ abstract class MongoAdapterBase extends TxProcessor { } class MongoAdapter extends MongoAdapterBase { + protected txPutBag (tx: TxPutBag): Promise { + throw new Error('Method not implemented.') + } + + protected txRemoveDoc (tx: TxRemoveDoc): Promise { + throw new Error('Method not implemented.') + } + + protected txMixin (tx: TxMixin): Promise { + throw new Error('Method not implemented.') + } + protected override async txCreateDoc (tx: TxCreateDoc): Promise { const doc = TxProcessor.createDoc2Doc(tx) const domain = this.hierarchy.getDomain(doc._class) @@ -106,6 +118,26 @@ class MongoAdapter extends MongoAdapterBase { } class MongoTxAdapter extends MongoAdapterBase implements TxAdapter { + protected txCreateDoc (tx: TxCreateDoc): Promise { + throw new Error('Method not implemented.') + } + + protected txPutBag (tx: TxPutBag): Promise { + throw new Error('Method not implemented.') + } + + protected txUpdateDoc (tx: TxUpdateDoc): Promise { + throw new Error('Method not implemented.') + } + + protected txRemoveDoc (tx: TxRemoveDoc): Promise { + throw new Error('Method not implemented.') + } + + protected txMixin (tx: TxMixin): Promise { + throw new Error('Method not implemented.') + } + override async tx (tx: Tx): Promise { console.log('mongotx', tx) await this.db.collection(DOMAIN_TX).insertOne(translateDoc(tx))