TxCollectionCUD

Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
Andrey Sobolev 2021-11-17 01:34:20 +07:00
parent 8ef4b49800
commit b6fac06d2b
15 changed files with 1196 additions and 1089 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -14,7 +14,7 @@
// //
import type { IntlString } from '@anticrm/platform' import type { IntlString } from '@anticrm/platform'
import type { Account, AnyAttribute, Class, ClassifierKind, Doc, Domain, Mixin, Obj, Ref, Space, Timestamp, Type } from '@anticrm/core' import type { Account, AnyAttribute, AttachedDoc, Class, ClassifierKind, Doc, Domain, Mixin, Obj, Ref, Space, Timestamp, Type } from '@anticrm/core'
import { DOMAIN_MODEL } from '@anticrm/core' import { DOMAIN_MODEL } from '@anticrm/core'
import { Model, Prop, TypeTimestamp } from '@anticrm/model' import { Model, Prop, TypeTimestamp } from '@anticrm/model'
import core from './component' import core from './component'
@ -36,6 +36,12 @@ export class TDoc extends TObj implements Doc {
modifiedBy!: Ref<Account> modifiedBy!: Ref<Account>
} }
@Model(core.class.AttachedDoc, core.class.Doc)
export class TAttachedDoc extends TDoc implements AttachedDoc {
attachedTo!: Ref<Doc>
attachedToClass!: Ref<Class<Doc>>
}
@Model(core.class.Class, core.class.Doc, DOMAIN_MODEL) @Model(core.class.Class, core.class.Doc, DOMAIN_MODEL)
export class TClass extends TDoc implements Class<Obj> { export class TClass extends TDoc implements Class<Obj> {
kind!: ClassifierKind kind!: ClassifierKind

View File

@ -15,9 +15,9 @@
import { Builder } from '@anticrm/model' import { Builder } from '@anticrm/model'
import core from './component' import core from './component'
import { TAttribute, TClass, TDoc, TMixin, TObj, TType, TTypeString, TTypeBoolean, TTypeTimestamp } from './core' import { TAttribute, TClass, TDoc, TMixin, TObj, TType, TTypeString, TTypeBoolean, TTypeTimestamp, TAttachedDoc } from './core'
import { TSpace, TAccount, TState, TSpaceWithStates, TDocWithState } from './security' import { TSpace, TAccount, TState, TSpaceWithStates, TDocWithState } from './security'
import { TTx, TTxCreateDoc, TTxMixin, TTxUpdateDoc, TTxCUD, TTxPutBag, TTxRemoveDoc, TTxBulkWrite, TTxAddCollection } from './tx' import { TTx, TTxCreateDoc, TTxMixin, TTxUpdateDoc, TTxCUD, TTxPutBag, TTxRemoveDoc, TTxBulkWrite, TTxCollectionCUD } from './tx'
export * from './core' export * from './core'
export * from './security' export * from './security'
@ -33,7 +33,8 @@ export function createModel (builder: Builder): void {
TTx, TTx,
TTxCUD, TTxCUD,
TTxCreateDoc, TTxCreateDoc,
TTxAddCollection, TAttachedDoc,
TTxCollectionCUD,
TTxPutBag, TTxPutBag,
TTxMixin, TTxMixin,
TTxUpdateDoc, TTxUpdateDoc,

View File

@ -14,25 +14,25 @@
// //
import type { import type {
AttachedDoc,
Class, Class,
Data, Data,
Doc, Doc,
DocumentUpdate, DocumentUpdate,
ExtendedAttributes,
Mixin,
PropertyType,
Ref, Ref,
Space, Space,
Tx, Tx,
TxCUD,
TxCreateDoc,
TxRemoveDoc,
TxUpdateDoc,
TxMixin,
Mixin,
ExtendedAttributes,
PropertyType,
TxPutBag,
TxBulkWrite, TxBulkWrite,
AttachedDoc, TxCollectionCUD,
TxAddCollection TxCreateDoc,
TxCUD,
TxMixin,
TxPutBag,
TxRemoveDoc,
TxUpdateDoc
} from '@anticrm/core' } from '@anticrm/core'
import { DOMAIN_TX } from '@anticrm/core' import { DOMAIN_TX } from '@anticrm/core'
import { Model } from '@anticrm/model' import { Model } from '@anticrm/model'
@ -57,11 +57,10 @@ export class TTxCreateDoc<T extends Doc> extends TTxCUD<T> implements TxCreateDo
attributes!: Data<T> attributes!: Data<T>
} }
@Model(core.class.TxAddCollection, core.class.TxCreateDoc) @Model(core.class.TxCollectionCUD, core.class.TxCUD)
export class TTxAddCollection<T extends AttachedDoc> extends TTxCreateDoc<T> implements TxAddCollection<T> { export class TTxCollectionCUD<T extends Doc, P extends AttachedDoc> extends TTxCUD<T> implements TxCollectionCUD<T, P> {
collection!: string collection!: string
attachedTo!: Ref<Doc> tx!: TxCUD<P>
attachedToClass!: Ref<Class<Doc>>
} }
@Model(core.class.TxPutBag, core.class.TxCUD) @Model(core.class.TxPutBag, core.class.TxCUD)

View File

@ -13,7 +13,7 @@
// limitations under the License. // limitations under the License.
// //
import type { Class, Obj, Ref } from '../classes' import type { Class, Obj, Ref, Doc } from '../classes'
import core from '../component' import core from '../component'
import { Hierarchy } from '../hierarchy' import { Hierarchy } from '../hierarchy'
import { ModelDb, TxDb } from '../memdb' import { ModelDb, TxDb } from '../memdb'
@ -23,24 +23,37 @@ import { genMinModel, test, TestMixin } from './minmodel'
const txes = genMinModel() const txes = genMinModel()
async function createModel (): Promise<{ model: ModelDb, hierarchy: Hierarchy }> { async function createModel (): Promise<{ model: ModelDb, hierarchy: Hierarchy, txDb: TxDb }> {
const hierarchy = new Hierarchy() const hierarchy = new Hierarchy()
for (const tx of txes) hierarchy.tx(tx) for (const tx of txes) {
hierarchy.tx(tx)
}
const model = new ModelDb(hierarchy) const model = new ModelDb(hierarchy)
for (const tx of txes) await model.tx(tx) for (const tx of txes) {
return { model, hierarchy } await model.tx(tx)
}
const txDb = new TxDb(hierarchy)
for (const tx of txes) await txDb.tx(tx)
return { model, hierarchy, txDb }
} }
describe('memdb', () => { describe('memdb', () => {
it('should save all tx', async () => { it('should save all tx', async () => {
const hierarchy = new Hierarchy() const { txDb } = await createModel()
for (const tx of txes) hierarchy.tx(tx)
const txDb = new TxDb(hierarchy)
for (const tx of txes) await txDb.tx(tx)
const result = await txDb.findAll(core.class.Tx, {}) const result = await txDb.findAll(core.class.Tx, {})
expect(result.length).toBe(txes.filter((tx) => tx._class === core.class.TxCreateDoc).length) expect(result.length).toBe(txes.filter((tx) => tx._class === core.class.TxCreateDoc).length)
}) })
it('should query model', async () => {
const { model } = await createModel()
const result = await model.findAll(core.class.Class, {})
expect(result.length).toBeGreaterThan(5)
const result2 = await model.findAll('class:workbench.Application' as Ref<Class<Doc>>, { _id: undefined })
expect(result2).toHaveLength(0)
})
it('should create space', async () => { it('should create space', async () => {
const { model } = await createModel() const { model } = await createModel()
@ -65,7 +78,8 @@ describe('memdb', () => {
it('should query model', async () => { it('should query model', async () => {
const { model } = await createModel() const { model } = await createModel()
const result = await model.findAll(core.class.Class, {}) const result = await model.findAll(core.class.Class, {})
expect(result.length).toBe(10) const names = result.map(d => d._id)
expect(names.includes(core.class.Class)).toBe(true)
const result2 = await model.findAll(core.class.Class, { _id: undefined }) const result2 = await model.findAll(core.class.Class, { _id: undefined })
expect(result2.length).toBe(0) expect(result2.length).toBe(0)
}) })
@ -103,10 +117,7 @@ describe('memdb', () => {
}) })
it('should query model with params', async () => { it('should query model with params', async () => {
const hierarchy = new Hierarchy() const { model } = await createModel()
for (const tx of txes) hierarchy.tx(tx)
const model = new ModelDb(hierarchy)
for (const tx of txes) await model.tx(tx)
const first = await model.findAll(core.class.Class, { const first = await model.findAll(core.class.Class, {
_id: txes[1].objectId as Ref<Class<Obj>>, _id: txes[1].objectId as Ref<Class<Obj>>,
kind: 0 kind: 0
@ -132,10 +143,7 @@ describe('memdb', () => {
}) })
it('should query model like params', async () => { it('should query model like params', async () => {
const hierarchy = new Hierarchy() const { model } = await createModel()
for (const tx of txes) hierarchy.tx(tx)
const model = new ModelDb(hierarchy)
for (const tx of txes) await model.tx(tx)
const expectedLength = txes.filter((tx) => tx.objectSpace === core.space.Model).length const expectedLength = txes.filter((tx) => tx.objectSpace === core.space.Model).length
const without = await model.findAll(core.class.Doc, { const without = await model.findAll(core.class.Doc, {
space: { $like: core.space.Model } space: { $like: core.space.Model }
@ -205,34 +213,17 @@ describe('memdb', () => {
expect(numberSort[0].modifiedOn).toBeLessThanOrEqual(numberSort[numberSortDesc.length - 1].modifiedOn) expect(numberSort[0].modifiedOn).toBeLessThanOrEqual(numberSort[numberSortDesc.length - 1].modifiedOn)
}) })
// it('should throw error', async () => { it('should add attached document', async () => {
// expect.assertions(1) const { model } = await createModel()
// const errorTx: TxAddCollection<Doc, Emb> = {
// _id: '60b73133d22498e666800cd2' as Ref<TxAddCollection<Doc, Emb>>,
// _class: 'class:core.TxAddCollection' as Ref<Class<TxAddCollection<Doc, Emb>>>,
// space: core.space.Tx,
// modifiedBy: 'xxx' as Ref<Account>,
// modifiedOn: 0,
// objectId: 'class:test.MyClass' as Ref<Doc>,
// objectSpace: core.space.Model,
// itemClass: 'class:core.Attribute' as Ref<Class<Doc>>,
// collection: 'attributes',
// localId: 'name',
// attributes: {
// _class: 'class:core.Attribute' as Ref<Class<Doc>>,
// // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
// __embedded: {
// _class: 'class:core.Attribute' as Ref<Class<Doc>>
// } as Emb
// }
// }
// const hierarchy = new Hierarchy() const client = new TxOperations(model, core.account.System)
// for (const tx of txes) hierarchy.tx(tx) const result = await client.findAll(core.class.Space, {})
// const model = new ModelDb(hierarchy) expect(result).toHaveLength(2)
// await model.tx(errorTx).catch((error: Error) => { await client.addCollection(test.class.TestComment, core.space.Model, result[0]._id, result[0]._class, 'comments', {
// expect(error.message).toBe('ERROR: status:core.ObjectNotFound') message: 'msg'
// }) })
// }) const result2 = await client.findAll(test.class.TestComment, {})
expect(result2).toHaveLength(1)
})
}) })

View File

@ -13,12 +13,12 @@
// limitations under the License. // limitations under the License.
// //
import type { Plugin, IntlString } from '@anticrm/platform' import type { IntlString, Plugin } from '@anticrm/platform'
import { plugin } from '@anticrm/platform' import { plugin } from '@anticrm/platform'
import type { Class, Data, Doc, Obj, Ref, Mixin, Arr } from '../classes' import type { Arr, Class, Data, Doc, Mixin, Obj, Ref } from '../classes'
import { ClassifierKind, DOMAIN_MODEL } from '../classes' import { AttachedDoc, ClassifierKind, DOMAIN_MODEL } from '../classes'
import type { TxCUD, TxCreateDoc } from '../tx'
import core from '../component' import core from '../component'
import type { TxCreateDoc, TxCUD } from '../tx'
import { DOMAIN_TX, TxFactory } from '../tx' import { DOMAIN_TX, TxFactory } from '../tx'
const txFactory = new TxFactory(core.account.System) const txFactory = new TxFactory(core.account.System)
@ -35,9 +35,16 @@ export interface TestMixin extends Doc {
arr: Arr<string> arr: Arr<string>
} }
export interface AttachedComment extends AttachedDoc {
message: string
}
export const test = plugin('test' as Plugin, { export const test = plugin('test' as Plugin, {
mixin: { mixin: {
TestMixin: '' as Ref<Mixin<TestMixin>> TestMixin: '' as Ref<Mixin<TestMixin>>
},
class: {
TestComment: '' as Ref<Class<AttachedComment>>
} }
}) })
@ -50,17 +57,22 @@ export function genMinModel (): TxCUD<Doc>[] {
// Fill Tx'es with basic model classes. // Fill Tx'es with basic model classes.
txes.push(createClass(core.class.Obj, { label: 'Obj' as IntlString, kind: ClassifierKind.CLASS })) txes.push(createClass(core.class.Obj, { label: 'Obj' as IntlString, kind: ClassifierKind.CLASS }))
txes.push(createClass(core.class.Doc, { label: 'Doc' as IntlString, extends: core.class.Obj, kind: ClassifierKind.CLASS })) txes.push(createClass(core.class.Doc, { label: 'Doc' as IntlString, extends: core.class.Obj, kind: ClassifierKind.CLASS }))
txes.push(createClass(core.class.AttachedDoc, { label: 'AttachedDoc' as IntlString, extends: core.class.Doc, kind: ClassifierKind.MIXIN }))
txes.push(createClass(core.class.Class, { label: 'Class' as IntlString, extends: core.class.Doc, kind: ClassifierKind.CLASS, domain: DOMAIN_MODEL })) txes.push(createClass(core.class.Class, { label: 'Class' as IntlString, extends: core.class.Doc, kind: ClassifierKind.CLASS, domain: DOMAIN_MODEL }))
txes.push(createClass(core.class.Space, { label: 'Space' as IntlString, extends: core.class.Doc, kind: ClassifierKind.CLASS, domain: DOMAIN_MODEL })) txes.push(createClass(core.class.Space, { label: 'Space' as IntlString, extends: core.class.Doc, kind: ClassifierKind.CLASS, domain: DOMAIN_MODEL }))
txes.push(createClass(core.class.Account, { label: 'Account' as IntlString, extends: core.class.Doc, kind: ClassifierKind.CLASS, domain: DOMAIN_MODEL })) txes.push(createClass(core.class.Account, { label: 'Account' as IntlString, extends: core.class.Doc, kind: ClassifierKind.CLASS, domain: DOMAIN_MODEL }))
txes.push(createClass(core.class.Tx, { label: 'Tx' as IntlString, extends: core.class.Doc, kind: ClassifierKind.CLASS, domain: DOMAIN_TX })) txes.push(createClass(core.class.Tx, { label: 'Tx' as IntlString, extends: core.class.Doc, kind: ClassifierKind.CLASS, domain: DOMAIN_TX }))
txes.push(createClass(core.class.TxCreateDoc, { label: 'TxCreateDoc' as IntlString, extends: core.class.Tx, kind: ClassifierKind.CLASS })) txes.push(createClass(core.class.TxCUD, { label: 'TxCUD' as IntlString, extends: core.class.Tx, kind: ClassifierKind.CLASS, domain: DOMAIN_TX }))
txes.push(createClass(core.class.TxUpdateDoc, { label: 'TxUpdateDoc' as IntlString, extends: core.class.Tx, kind: ClassifierKind.CLASS })) txes.push(createClass(core.class.TxCreateDoc, { label: 'TxCreateDoc' as IntlString, extends: core.class.TxCUD, kind: ClassifierKind.CLASS }))
txes.push(createClass(core.class.TxRemoveDoc, { label: 'TxRemoveDoc' as IntlString, extends: core.class.Tx, kind: ClassifierKind.CLASS })) txes.push(createClass(core.class.TxUpdateDoc, { label: 'TxUpdateDoc' as IntlString, extends: core.class.TxCUD, kind: ClassifierKind.CLASS }))
txes.push(createClass(core.class.TxRemoveDoc, { label: 'TxRemoveDoc' as IntlString, extends: core.class.TxCUD, kind: ClassifierKind.CLASS }))
txes.push(createClass(core.class.TxCollectionCUD, { label: 'TxCollectionCUD' as IntlString, extends: core.class.TxCUD, kind: ClassifierKind.CLASS }))
txes.push(createClass(test.mixin.TestMixin, { label: 'TestMixin' as IntlString, extends: core.class.Doc, kind: ClassifierKind.MIXIN })) txes.push(createClass(test.mixin.TestMixin, { label: 'TestMixin' as IntlString, extends: core.class.Doc, kind: ClassifierKind.MIXIN }))
txes.push(createClass(test.class.TestComment, { label: 'TestComment' as IntlString, extends: core.class.AttachedDoc, kind: ClassifierKind.CLASS }))
txes.push( txes.push(
createDoc(core.class.Space, { createDoc(core.class.Space, {
name: 'Sp1', name: 'Sp1',

View File

@ -15,7 +15,7 @@
import type { Plugin, StatusCode } from '@anticrm/platform' import type { Plugin, StatusCode } from '@anticrm/platform'
import { plugin } from '@anticrm/platform' import { plugin } from '@anticrm/platform'
import type { Account, Class, Doc, Obj, Ref, Space, AnyAttribute, State, Type, PropertyType, SpaceWithStates, Timestamp, DocWithState, AttachedDoc } from './classes' import type { Account, Class, Doc, Obj, Ref, Space, AnyAttribute, State, Type, PropertyType, SpaceWithStates, Timestamp, DocWithState, AttachedDoc } from './classes'
import type { Tx, TxAddCollection, TxBulkWrite, TxCreateDoc, TxCUD, TxMixin, TxPutBag, TxRemoveDoc, TxUpdateDoc } from './tx' import type { Tx, TxCollectionCUD, TxBulkWrite, TxCreateDoc, TxCUD, TxMixin, TxPutBag, TxRemoveDoc, TxUpdateDoc } from './tx'
/** /**
* @public * @public
@ -26,13 +26,14 @@ export default plugin(coreId, {
class: { class: {
Obj: '' as Ref<Class<Obj>>, Obj: '' as Ref<Class<Obj>>,
Doc: '' as Ref<Class<Doc>>, Doc: '' as Ref<Class<Doc>>,
AttachedDoc: '' as Ref<Class<AttachedDoc>>,
Class: '' as Ref<Class<Class<Obj>>>, Class: '' as Ref<Class<Class<Obj>>>,
Attribute: '' as Ref<Class<AnyAttribute>>, Attribute: '' as Ref<Class<AnyAttribute>>,
Tx: '' as Ref<Class<Tx>>, Tx: '' as Ref<Class<Tx>>,
TxBulkWrite: '' as Ref<Class<TxBulkWrite>>, TxBulkWrite: '' as Ref<Class<TxBulkWrite>>,
TxCUD: '' as Ref<Class<TxCUD<Doc>>>, TxCUD: '' as Ref<Class<TxCUD<Doc>>>,
TxCreateDoc: '' as Ref<Class<TxCreateDoc<Doc>>>, TxCreateDoc: '' as Ref<Class<TxCreateDoc<Doc>>>,
TxAddCollection: '' as Ref<Class<TxAddCollection<AttachedDoc>>>, TxCollectionCUD: '' as Ref<Class<TxCollectionCUD<Doc, AttachedDoc>>>,
TxMixin: '' as Ref<Class<TxMixin<Doc, Doc>>>, TxMixin: '' as Ref<Class<TxMixin<Doc, Doc>>>,
TxUpdateDoc: '' as Ref<Class<TxUpdateDoc<Doc>>>, TxUpdateDoc: '' as Ref<Class<TxUpdateDoc<Doc>>>,
TxRemoveDoc: '' as Ref<Class<TxRemoveDoc<Doc>>>, TxRemoveDoc: '' as Ref<Class<TxRemoveDoc<Doc>>>,

View File

@ -42,12 +42,14 @@ export interface TxCreateDoc<T extends Doc> extends TxCUD<T> {
} }
/** /**
*
* Will perform create/update/delete of attached documents.
*
* @public * @public
*/ */
export interface TxAddCollection<T extends AttachedDoc> extends TxCreateDoc<T> { export interface TxCollectionCUD<T extends Doc, P extends AttachedDoc> extends TxCUD<T> {
collection: string collection: string
attachedTo: Ref<Doc> tx: TxCUD<P>
attachedToClass: Ref<Class<Doc>>
} }
/** /**
@ -193,8 +195,8 @@ export abstract class TxProcessor implements WithTx {
switch (tx._class) { switch (tx._class) {
case core.class.TxCreateDoc: case core.class.TxCreateDoc:
return await this.txCreateDoc(tx as TxCreateDoc<Doc>) return await this.txCreateDoc(tx as TxCreateDoc<Doc>)
case core.class.TxAddCollection: case core.class.TxCollectionCUD:
return await this.txAddCollection(tx as TxAddCollection<AttachedDoc>) return await this.txCollectionCUD(tx as TxCollectionCUD<Doc, AttachedDoc>)
case core.class.TxUpdateDoc: case core.class.TxUpdateDoc:
return await this.txUpdateDoc(tx as TxUpdateDoc<Doc>) return await this.txUpdateDoc(tx as TxUpdateDoc<Doc>)
case core.class.TxRemoveDoc: case core.class.TxRemoveDoc:
@ -209,7 +211,7 @@ export abstract class TxProcessor implements WithTx {
throw new Error('TxProcessor: unhandled transaction class: ' + tx._class) throw new Error('TxProcessor: unhandled transaction class: ' + tx._class)
} }
static createDoc2Doc<T extends Doc> (tx: TxCreateDoc<T>): T { static createDoc2Doc<T extends Doc>(tx: TxCreateDoc<T>): T {
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
return { return {
_id: tx.objectId, _id: tx.objectId,
@ -227,15 +229,25 @@ export abstract class TxProcessor implements WithTx {
protected abstract txRemoveDoc (tx: TxRemoveDoc<Doc>): Promise<TxResult> protected abstract txRemoveDoc (tx: TxRemoveDoc<Doc>): Promise<TxResult>
protected abstract txMixin (tx: TxMixin<Doc, Doc>): Promise<TxResult> protected abstract txMixin (tx: TxMixin<Doc, Doc>): Promise<TxResult>
protected txAddCollection (tx: TxAddCollection<AttachedDoc>): Promise<TxResult> { protected txCollectionCUD (tx: TxCollectionCUD<Doc, AttachedDoc>): Promise<TxResult> {
const createTx: TxCreateDoc<Doc> = { ...tx } // We need update only create transactions to contain attached, attachedToClass.
createTx.attributes = { ...tx.attributes, attachedTo: tx.attachedTo, attachedToClass: tx.attachedToClass } if (tx.tx._class === core.class.TxCreateDoc) {
return this.txCreateDoc(createTx) const createTx = tx.tx as TxCreateDoc<AttachedDoc>
const d: TxCreateDoc<AttachedDoc> = {
...createTx,
attributes: {
...createTx.attributes,
attachedTo: tx.objectId,
attachedToClass: tx.objectClass
}
}
return this.txCreateDoc(d)
}
return this.tx(tx.tx)
} }
protected async txBulkWrite (bulkTx: TxBulkWrite): Promise<TxResult> { protected async txBulkWrite (bulkTx: TxBulkWrite): Promise<TxResult> {
for (const tx of bulkTx.txes) { for (const tx of bulkTx.txes) {
console.log('bulk', tx)
await this.tx(tx) await this.tx(tx)
} }
return {} return {}
@ -275,16 +287,42 @@ export class TxOperations implements Storage {
return tx.objectId return tx.objectId
} }
async addCollection<T extends AttachedDoc> ( async addCollection<T extends Doc, P extends AttachedDoc>(
_class: Ref<Class<T>>, _class: Ref<Class<P>>,
space: Ref<Space>, space: Ref<Space>,
attachedTo: Ref<Doc>, attachedTo: Ref<T>,
attachedToClass: Ref<Class<Doc>>, attachedToClass: Ref<Class<T>>,
collection: string, collection: string,
attributes: AttachedData<T>, attributes: AttachedData<P>,
id?: Ref<T> id?: Ref<P>
): Promise<Ref<T>> { ): Promise<Ref<T>> {
const tx = this.txFactory.createTxAddCollection(_class, space, attributes, attachedTo, attachedToClass, collection, id) const tx = this.txFactory.createTxCollectionCUD<T, P>(
attachedToClass,
attachedTo,
space,
collection,
this.txFactory.createTxCreateDoc<P>(_class, space, attributes as unknown as Data<P>, id)
)
await this.storage.tx(tx)
return tx.objectId
}
async updateCollection<T extends Doc, P extends AttachedDoc>(
_class: Ref<Class<P>>,
space: Ref<Space>,
attachedTo: Ref<T>,
attachedToClass: Ref<Class<T>>,
collection: string,
objectId: Ref<P>,
operations: DocumentUpdate<P>
): Promise<Ref<T>> {
const tx = this.txFactory.createTxCollectionCUD(
attachedToClass,
attachedTo,
space,
collection,
this.txFactory.createTxUpdateDoc(_class, space, objectId, operations)
)
await this.storage.tx(tx) await this.storage.tx(tx)
return tx.objectId return tx.objectId
} }
@ -352,20 +390,24 @@ export class TxFactory {
} }
} }
createTxAddCollection<T extends AttachedDoc>(_class: Ref<Class<T>>, space: Ref<Space>, attributes: AttachedData<T>, attachedTo: Ref<Doc>, attachedToClass: Ref<Class<Doc>>, collection: string, objectId?: Ref<T>): TxAddCollection<T> { createTxCollectionCUD<T extends Doc, P extends AttachedDoc>(
_class: Ref<Class<T>>,
objectId: Ref<T>,
space: Ref<Space>,
collection: string,
tx: TxCUD<P>
): TxCollectionCUD<T, P> {
return { return {
_id: generateId(), _id: generateId(),
_class: core.class.TxAddCollection, _class: core.class.TxCollectionCUD,
space: core.space.Tx, space: core.space.Tx,
objectId: objectId ?? generateId(), objectId,
objectClass: _class, objectClass: _class,
objectSpace: space, objectSpace: space,
modifiedOn: Date.now(), modifiedOn: Date.now(),
modifiedBy: this.account, modifiedBy: this.account,
attributes: attributes as Data<T>,
collection, collection,
attachedTo, tx
attachedToClass
} }
} }

View File

@ -14,7 +14,7 @@
// limitations under the License. // limitations under the License.
// //
import type { Tx, TxCreateDoc, Data, Ref, Doc, TxFactory, Class } from '@anticrm/core' import type { Tx, TxCreateDoc, Data, Ref, Doc, TxFactory, Class, TxCollectionCUD, AttachedDoc } from '@anticrm/core'
import type { FindAll } from '@anticrm/server-core' import type { FindAll } from '@anticrm/server-core'
import type { Message, Backlink } from '@anticrm/chunter' import type { Message, Backlink } from '@anticrm/chunter'
import { parse, Node, HTMLElement } from 'node-html-parser' import { parse, Node, HTMLElement } from 'node-html-parser'
@ -48,6 +48,9 @@ function getBacklinks (backlinkId: Ref<Doc>, content: string): Data<Backlink>[]
* @public * @public
*/ */
export async function OnMessage (tx: Tx, txFactory: TxFactory): Promise<Tx[]> { export async function OnMessage (tx: Tx, txFactory: TxFactory): Promise<Tx[]> {
if (tx._class === core.class.TxCollectionCUD) {
tx = (tx as TxCollectionCUD<Doc, AttachedDoc>).tx
}
if (tx._class === core.class.TxCreateDoc) { if (tx._class === core.class.TxCreateDoc) {
const createTx = tx as TxCreateDoc<Message> const createTx = tx as TxCreateDoc<Message>
if (createTx.objectClass === chunter.class.Message) { if (createTx.objectClass === chunter.class.Message) {

View File

@ -14,7 +14,7 @@
// limitations under the License. // limitations under the License.
// //
import type { ServerStorage, Domain, Tx, TxCUD, Doc, Ref, Class, DocumentQuery, FindResult, FindOptions, Storage, TxBulkWrite, TxResult, TxAddCollection, AttachedDoc } from '@anticrm/core' import type { ServerStorage, Domain, Tx, TxCUD, Doc, Ref, Class, DocumentQuery, FindResult, FindOptions, Storage, TxBulkWrite, TxResult, TxCollectionCUD, AttachedDoc } from '@anticrm/core'
import core, { Hierarchy, DOMAIN_TX, ModelDb, TxFactory } from '@anticrm/core' import core, { Hierarchy, DOMAIN_TX, ModelDb, TxFactory } from '@anticrm/core'
import type { FullTextAdapterFactory, FullTextAdapter } from './types' import type { FullTextAdapterFactory, FullTextAdapter } from './types'
import { FullTextIndex } from './fulltext' import { FullTextIndex } from './fulltext'
@ -107,13 +107,16 @@ class TServerStorage implements ServerStorage {
} }
async processCollection (tx: Tx): Promise<Tx[]> { async processCollection (tx: Tx): Promise<Tx[]> {
if (tx._class === core.class.TxAddCollection) { if (tx._class === core.class.TxCollectionCUD) {
const createTx = tx as TxAddCollection<AttachedDoc> const colTx = tx as TxCollectionCUD<Doc, AttachedDoc>
const _id = createTx.attachedTo const _id = colTx.objectId
const _class = createTx.attachedToClass const _class = colTx.objectClass
const attachedTo = (await this.findAll(_class, { _id }))[0] let attachedTo: Doc | undefined
const txFactory = new TxFactory(tx.modifiedBy) if (colTx.tx._class === core.class.TxCreateDoc) {
return [txFactory.createTxUpdateDoc(_class, attachedTo.space, _id, { $inc: { [createTx.collection]: 1 } })] attachedTo = (await this.findAll(_class, { _id }))[0]
const txFactory = new TxFactory(tx.modifiedBy)
return [txFactory.createTxUpdateDoc(_class, attachedTo.space, _id, { $inc: { [colTx.collection]: 1 } })]
}
} }
return [] return []
} }

View File

@ -14,7 +14,7 @@
// limitations under the License. // limitations under the License.
// //
import type { Tx, Doc, TxCreateDoc, Ref, Account, Hierarchy } from '@anticrm/core' import type { Tx, Doc, TxCreateDoc, Ref, Account, Hierarchy, TxCollectionCUD, AttachedDoc } from '@anticrm/core'
import core, { TxFactory } from '@anticrm/core' import core, { TxFactory } from '@anticrm/core'
import { getResource } from '@anticrm/platform' import { getResource } from '@anticrm/platform'
@ -29,6 +29,9 @@ export class Triggers {
private readonly triggers: TriggerFunc[] = [] private readonly triggers: TriggerFunc[] = []
async tx (tx: Tx): Promise<void> { async tx (tx: Tx): Promise<void> {
if (tx._class === core.class.TxCollectionCUD) {
tx = (tx as TxCollectionCUD<Doc, AttachedDoc>).tx
}
if (tx._class === core.class.TxCreateDoc) { if (tx._class === core.class.TxCreateDoc) {
const createTx = tx as TxCreateDoc<Doc> const createTx = tx as TxCreateDoc<Doc>
if (createTx.objectClass === serverCore.class.Trigger) { if (createTx.objectClass === serverCore.class.Trigger) {

View File

@ -19,9 +19,9 @@
"eslint":"^7.32.0" "eslint":"^7.32.0"
}, },
"dependencies": { "dependencies": {
"@anticrm/core": "~0.6.11", "@anticrm/core": "~0.6.12",
"@anticrm/platform": "~0.6.5", "@anticrm/platform": "~0.6.5",
"@anticrm/server-core": "~0.6.0", "@anticrm/server-core": "~0.6.1",
"@anticrm/view": "~0.6.0" "@anticrm/view": "~0.6.0"
} }
} }

View File

@ -14,7 +14,7 @@
// limitations under the License. // limitations under the License.
// //
import type { Tx, TxFactory, Doc, TxCreateDoc, DocWithState, State, TxRemoveDoc } from '@anticrm/core' import type { Tx, TxFactory, Doc, TxCreateDoc, DocWithState, State, TxRemoveDoc, TxCollectionCUD, AttachedDoc } from '@anticrm/core'
import type { FindAll } from '@anticrm/server-core' import type { FindAll } from '@anticrm/server-core'
import core, { Hierarchy } from '@anticrm/core' import core, { Hierarchy } from '@anticrm/core'
@ -24,6 +24,10 @@ import view, { Kanban } from '@anticrm/view'
* @public * @public
*/ */
export async function OnDocWithState (tx: Tx, txFactory: TxFactory, findAll: FindAll<Doc>, hierarchy: Hierarchy): Promise<Tx[]> { export async function OnDocWithState (tx: Tx, txFactory: TxFactory, findAll: FindAll<Doc>, hierarchy: Hierarchy): Promise<Tx[]> {
if (tx._class === core.class.TxCollectionCUD) {
tx = (tx as TxCollectionCUD<Doc, AttachedDoc>).tx
}
if (hierarchy.isDerived(tx._class, core.class.TxCreateDoc)) { if (hierarchy.isDerived(tx._class, core.class.TxCreateDoc)) {
const createTx = tx as TxCreateDoc<DocWithState> const createTx = tx as TxCreateDoc<DocWithState>
if (hierarchy.isDerived(createTx.objectClass, core.class.DocWithState)) { if (hierarchy.isDerived(createTx.objectClass, core.class.DocWithState)) {

File diff suppressed because it is too large Load Diff