Server remove cascade (#1189)

Signed-off-by: Denis Bykhov <80476319+BykhovDenis@users.noreply.github.com>
This commit is contained in:
Denis Bykhov
2022-03-22 16:10:10 +07:00
committed by GitHub
parent 1db0417e85
commit 3246d3277c
45 changed files with 608 additions and 145 deletions
+72 -4
View File
@@ -74,6 +74,7 @@ specifiers:
'@rush-temp/model-server-notification': file:./projects/model-server-notification.tgz
'@rush-temp/model-server-recruit': file:./projects/model-server-recruit.tgz
'@rush-temp/model-server-setting': file:./projects/model-server-setting.tgz
'@rush-temp/model-server-tags': file:./projects/model-server-tags.tgz
'@rush-temp/model-server-task': file:./projects/model-server-task.tgz
'@rush-temp/model-setting': file:./projects/model-setting.tgz
'@rush-temp/model-tags': file:./projects/model-tags.tgz
@@ -116,6 +117,8 @@ specifiers:
'@rush-temp/server-recruit-resources': file:./projects/server-recruit-resources.tgz
'@rush-temp/server-setting': file:./projects/server-setting.tgz
'@rush-temp/server-setting-resources': file:./projects/server-setting-resources.tgz
'@rush-temp/server-tags': file:./projects/server-tags.tgz
'@rush-temp/server-tags-resources': file:./projects/server-tags-resources.tgz
'@rush-temp/server-task': file:./projects/server-task.tgz
'@rush-temp/server-task-resources': file:./projects/server-task-resources.tgz
'@rush-temp/server-token': file:./projects/server-token.tgz
@@ -321,6 +324,7 @@ dependencies:
'@rush-temp/model-server-notification': file:projects/model-server-notification.tgz_typescript@4.5.4
'@rush-temp/model-server-recruit': file:projects/model-server-recruit.tgz_typescript@4.5.4
'@rush-temp/model-server-setting': file:projects/model-server-setting.tgz_typescript@4.5.4
'@rush-temp/model-server-tags': file:projects/model-server-tags.tgz_typescript@4.5.4
'@rush-temp/model-server-task': file:projects/model-server-task.tgz_typescript@4.5.4
'@rush-temp/model-setting': file:projects/model-setting.tgz_typescript@4.5.4
'@rush-temp/model-tags': file:projects/model-tags.tgz_typescript@4.5.4
@@ -363,6 +367,8 @@ dependencies:
'@rush-temp/server-recruit-resources': file:projects/server-recruit-resources.tgz
'@rush-temp/server-setting': file:projects/server-setting.tgz
'@rush-temp/server-setting-resources': file:projects/server-setting-resources.tgz
'@rush-temp/server-tags': file:projects/server-tags.tgz
'@rush-temp/server-tags-resources': file:projects/server-tags-resources.tgz
'@rush-temp/server-task': file:projects/server-task.tgz
'@rush-temp/server-task-resources': file:projects/server-task-resources.tgz
'@rush-temp/server-token': file:projects/server-token.tgz
@@ -12416,7 +12422,7 @@ packages:
dev: false
file:projects/model-all.tgz_typescript@4.5.4:
resolution: {integrity: sha512-LprNHSPgySvlj/zl9bkeSZ7Uh1wWyPPkQBW6knjBBD3cizpFpxPGBrSQnhDe/RP0uj6azKRYWWUcAPFOYe4TvQ==, tarball: file:projects/model-all.tgz}
resolution: {integrity: sha512-CTYZ52iBQ2S06DVd6jUK+PHCpgLDvO7lrujkMWxCO3RUn+77uyDZBGK43n+7UF1HZNSHvYAhyA8fBTvp1kOylw==, tarball: file:projects/model-all.tgz}
id: file:projects/model-all.tgz
name: '@rush-temp/model-all'
version: 0.0.0
@@ -12901,6 +12907,27 @@ packages:
- typescript
dev: false
file:projects/model-server-tags.tgz_typescript@4.5.4:
resolution: {integrity: sha512-TYTWiR2rFc1OE3D4m0DpKSridJKWeLfJmpK0SB0+6ibWEFUu+f9Yhs5N7j3/w1UMGKbSZ5Ere6PYVMTP3fTT5g==, tarball: file:projects/model-server-tags.tgz}
id: file:projects/model-server-tags.tgz
name: '@rush-temp/model-server-tags'
version: 0.0.0
dependencies:
'@rushstack/heft': 0.41.8
'@types/heft-jest': 1.0.2
'@typescript-eslint/eslint-plugin': 5.7.0_c25e8c1f4f4f7aaed27aa6f9ce042237
'@typescript-eslint/parser': 5.7.0_eslint@7.32.0+typescript@4.5.4
eslint: 7.32.0
eslint-config-standard-with-typescript: 21.0.1_ce2fa0c4dfa1c256100cababd749a13a
eslint-plugin-import: 2.25.3_eslint@7.32.0
eslint-plugin-node: 11.1.0_eslint@7.32.0
eslint-plugin-promise: 5.2.0_eslint@7.32.0
prettier: 2.5.1
transitivePeerDependencies:
- supports-color
- typescript
dev: false
file:projects/model-server-task.tgz_typescript@4.5.4:
resolution: {integrity: sha512-U7EJ1CuyupONpf97J8SfeRZT07aBNFQ3R1Wlyv7ssR6V8W4pkfjazFsfFA//pWh8ot5oWUy+8wccF7Q8TjkJWQ==, tarball: file:projects/model-server-task.tgz}
id: file:projects/model-server-task.tgz
@@ -13367,7 +13394,7 @@ packages:
dev: false
file:projects/prod.tgz_a07ec81d4d975778878ca12202ea119e:
resolution: {integrity: sha512-mxkGGtPp108JHMkmnEgKKPNVrihu3xVv1wZqY/HTWhZ+v8Ct5RG92+Yg6NBhEsLmqCBBPTAHY/JapGi1oF9bWg==, tarball: file:projects/prod.tgz}
resolution: {integrity: sha512-HHCNzvjIf/tNB1Wr5Fk4HGuoP66fHONafJd6DPh4kpTC7T8Vc5Y/UlneWS3cUjhCsB9jgYejEbu1Osp0DPXCZA==, tarball: file:projects/prod.tgz}
id: file:projects/prod.tgz
name: '@rush-temp/prod'
version: 0.0.0
@@ -13897,6 +13924,47 @@ packages:
- supports-color
dev: false
file:projects/server-tags-resources.tgz:
resolution: {integrity: sha512-XrVBmPPIJCLM2reTQorx5k+xtwc6pJApXeVSksk+DeP2+lVHQBIcJwRLUHkRNBVn7kU571mw6F6J6JvCSkYhJQ==, tarball: file:projects/server-tags-resources.tgz}
name: '@rush-temp/server-tags-resources'
version: 0.0.0
dependencies:
'@rushstack/heft': 0.41.8
'@types/heft-jest': 1.0.2
'@typescript-eslint/eslint-plugin': 5.7.0_c25e8c1f4f4f7aaed27aa6f9ce042237
'@typescript-eslint/parser': 5.7.0_eslint@7.32.0+typescript@4.5.4
eslint: 7.32.0
eslint-config-standard-with-typescript: 21.0.1_ce2fa0c4dfa1c256100cababd749a13a
eslint-plugin-import: 2.25.3_eslint@7.32.0
eslint-plugin-node: 11.1.0_eslint@7.32.0
eslint-plugin-promise: 5.2.0_eslint@7.32.0
prettier: 2.5.1
typescript: 4.5.4
transitivePeerDependencies:
- supports-color
dev: false
file:projects/server-tags.tgz:
resolution: {integrity: sha512-iDt1UvOkk+mT3l2/R0MFjgNHnGnZztfW5nuD39yeMoTIihWIfxOTO4PBCnu3dNtRL+2xIlU4pADEdyDp9AS3lg==, tarball: file:projects/server-tags.tgz}
name: '@rush-temp/server-tags'
version: 0.0.0
dependencies:
'@rushstack/heft': 0.41.8
'@types/heft-jest': 1.0.2
'@types/node': 16.11.14
'@typescript-eslint/eslint-plugin': 5.7.0_c25e8c1f4f4f7aaed27aa6f9ce042237
'@typescript-eslint/parser': 5.7.0_eslint@7.32.0+typescript@4.5.4
eslint: 7.32.0
eslint-config-standard-with-typescript: 21.0.1_ce2fa0c4dfa1c256100cababd749a13a
eslint-plugin-import: 2.25.3_eslint@7.32.0
eslint-plugin-node: 11.1.0_eslint@7.32.0
eslint-plugin-promise: 5.2.0_eslint@7.32.0
prettier: 2.5.1
typescript: 4.5.4
transitivePeerDependencies:
- supports-color
dev: false
file:projects/server-task-resources.tgz:
resolution: {integrity: sha512-OHpVWSAp1YyQ1LqJoXGRzqA8yY1BXZ5xI/P+fLUi5nk3Pz4a82H+YGw/FsNBuPWG4U25Hnnwopzl0trIXIB9jQ==, tarball: file:projects/server-task-resources.tgz}
name: '@rush-temp/server-task-resources'
@@ -14017,7 +14085,7 @@ packages:
dev: false
file:projects/server.tgz:
resolution: {integrity: sha512-1nC7oRGVjZGZ8I5tviFWIAu6++qbQ6k450Fe0fhi45pxMPuclCotH+NSS789RRpj2AhtiaghrpBZdc3CtgZOUw==, tarball: file:projects/server.tgz}
resolution: {integrity: sha512-Gx/PoIoObAiRX21Fo+Z/y7tqqgHW8URVudDz8azH/0hW25pRfR03xPw7oR0GsuF2IBZ4S8nyH1U2HSPpE76W7g==, tarball: file:projects/server.tgz}
name: '@rush-temp/server'
version: 0.0.0
dependencies:
@@ -14536,7 +14604,7 @@ packages:
dev: false
file:projects/tool.tgz:
resolution: {integrity: sha512-HzyyP6uYXNTmHkn7FiZJ3vf6Oq7KzAGYWsul1AT8B54rJqZ4mTZtBhnRGdVBqEmNIUNO2Ukr5ywdvAhJfDj+Mg==, tarball: file:projects/tool.tgz}
resolution: {integrity: sha512-F3Px6/29RVwqI/G3FsImf5dKvi53Tz7R/LSRyeG81NIN0WMGEsuOB6iWE9GD8PS/W7qSnKsFC8+VWVvJN+gVeQ==, tarball: file:projects/tool.tgz}
name: '@rush-temp/tool'
version: 0.0.0
dependencies:
+2
View File
@@ -118,6 +118,8 @@
"@anticrm/server-lead-resources": "~0.6.0",
"@anticrm/server-recruit": "~0.6.0",
"@anticrm/server-recruit-resources": "~0.6.0",
"@anticrm/server-tags": "~0.6.0",
"@anticrm/server-tags-resources": "~0.6.0",
"@anticrm/server-task": "~0.6.0",
"@anticrm/server-task-resources": "~0.6.0",
"@anticrm/calendar": "~0.6.0",
+2
View File
@@ -26,6 +26,7 @@ import { serverInventoryId } from '@anticrm/server-inventory'
import { serverLeadId } from '@anticrm/server-lead'
import { serverRecruitId } from '@anticrm/server-recruit'
import { serverTaskId } from '@anticrm/server-task'
import { serverTagsId } from '@anticrm/server-tags'
import { setMetadata } from '@anticrm/platform'
@@ -47,6 +48,7 @@ export function configurePlatformDev() {
addLocation(serverLeadId, () => import(/* webpackChunkName: "server-lead" */ '@anticrm/server-lead-resources'))
addLocation(serverRecruitId, () => import(/* webpackChunkName: "server-recruit" */ '@anticrm/server-recruit-resources'))
addLocation(serverTaskId, () => import/* webpackChunkName: "server-task" */ ('@anticrm/server-task-resources'))
addLocation(serverTagsId, () => import/* webpackChunkName: "server-tags" */ ('@anticrm/server-tags-resources'))
// Set devmodel to hook client to be able to present all activity
enableDevModel()
}
+2
View File
@@ -90,6 +90,8 @@
"@anticrm/server-recruit-resources": "~0.6.0",
"@anticrm/server-task": "~0.6.0",
"@anticrm/server-task-resources": "~0.6.0",
"@anticrm/server-tags": "~0.6.0",
"@anticrm/server-tags-resources": "~0.6.0",
"@anticrm/rekoni": "~0.6.0",
"request": "~2.88.2",
"@anticrm/tags": "~0.6.0"
+2
View File
@@ -56,6 +56,7 @@ import { serverInventoryId } from '@anticrm/server-inventory'
import { serverLeadId } from '@anticrm/server-lead'
import { serverRecruitId } from '@anticrm/server-recruit'
import { serverTaskId } from '@anticrm/server-task'
import { serverTagsId } from '@anticrm/server-tags'
import { Client as ElasticClient } from '@elastic/elasticsearch'
import { Client } from 'minio'
import { Db, MongoClient } from 'mongodb'
@@ -118,6 +119,7 @@ export class ElasticTool {
addLocation(serverRecruitId, () => import(/* webpackChunkName: "server-recruit" */ '@anticrm/server-recruit-resources'))
addLocation(serverSettingId, () => import(/* webpackChunkName: "server-recruit" */ '@anticrm/server-setting-resources'))
addLocation(serverTaskId, () => import/* webpackChunkName: "server-task" */ ('@anticrm/server-task-resources'))
addLocation(serverTagsId, () => import/* webpackChunkName: "server-tags" */ ('@anticrm/server-tags-resources'))
this.mongoClient = new MongoClient(mongoUrl)
}
+1
View File
@@ -49,6 +49,7 @@
"@anticrm/model-server-setting": "~0.6.0",
"@anticrm/model-server-chunter": "~0.6.0",
"@anticrm/model-server-task": "~0.6.0",
"@anticrm/model-server-tags": "~0.6.0",
"@anticrm/model-server-recruit": "~0.6.0",
"@anticrm/model-server-lead": "~0.6.0",
"@anticrm/model-server-inventory": "~0.6.0",
+2
View File
@@ -35,6 +35,7 @@ import { createModel as serverChunterModel } from '@anticrm/model-server-chunter
import { createModel as serverInventoryModel } from '@anticrm/model-server-inventory'
import { createModel as serverLeadModel } from '@anticrm/model-server-lead'
import { createModel as serverTaskModel } from '@anticrm/model-server-task'
import { createModel as serverTagsModel } from '@anticrm/model-server-tags'
import { createModel as serveSettingModel } from '@anticrm/model-server-setting'
import { createModel as serverRecruitModel } from '@anticrm/model-server-recruit'
import { createModel as serverCoreModel } from '@anticrm/model-server-core'
@@ -82,6 +83,7 @@ const builders = [
serverChunterModel,
serverInventoryModel,
serverLeadModel,
serverTagsModel,
serverTaskModel,
serverRecruitModel,
createDemo
+1 -6
View File
@@ -18,12 +18,11 @@ import type { Backlink, Channel, Comment, Message } from '@anticrm/chunter'
import type { Class, Doc, Domain, Ref } from '@anticrm/core'
import { IndexKind } from '@anticrm/core'
import { Builder, Collection, Index, Model, Prop, TypeMarkup, UX } from '@anticrm/model'
import attachment from '@anticrm/model-attachment'
import core, { TAttachedDoc, TDoc, TSpace } from '@anticrm/model-core'
import view from '@anticrm/model-view'
import workbench from '@anticrm/model-workbench'
import { ObjectDDParticipant } from '@anticrm/view'
import chunter from './plugin'
import attachment from '@anticrm/model-attachment'
export const DOMAIN_CHUNTER = 'chunter' as Domain
export const DOMAIN_COMMENT = 'comment' as Domain
@@ -104,10 +103,6 @@ export function createModel (builder: Builder): void {
presenter: chunter.component.CommentPresenter
})
builder.mixin<Class<Doc>, ObjectDDParticipant>(chunter.class.Comment, core.class.Class, view.mixin.ObjectDDParticipant, {
collectDocs: chunter.action.CommentRemove
})
builder.createDoc(activity.class.TxViewlet, core.space.Model, {
objectClass: chunter.class.Comment,
icon: chunter.icon.Chunter,
+2 -5
View File
@@ -16,8 +16,8 @@
import type { TxViewlet } from '@anticrm/activity'
import { Channel, chunterId } from '@anticrm/chunter'
import chunter from '@anticrm/chunter-resources/src/plugin'
import type { Doc, Ref, TxOperations } from '@anticrm/core'
import type { IntlString, Resource } from '@anticrm/platform'
import type { Ref } from '@anticrm/core'
import type { IntlString } from '@anticrm/platform'
import { mergeIds } from '@anticrm/platform'
import type { AnyComponent } from '@anticrm/ui'
import type { ViewletDescriptor } from '@anticrm/view'
@@ -53,8 +53,5 @@ export default mergeIds(chunterId, chunter, {
space: {
General: '' as Ref<Channel>,
Random: '' as Ref<Channel>
},
action: {
CommentRemove: '' as Resource<(doc: Doc, client: TxOperations) => Promise<Doc[]>>
}
})
+6 -1
View File
@@ -15,9 +15,10 @@
import { Builder } from '@anticrm/model'
import core from '@anticrm/core'
import core, { Class, Doc } from '@anticrm/core'
import chunter from '@anticrm/chunter'
import view from '@anticrm/view'
import serverCore, { ObjectDDParticipant } from '@anticrm/server-core'
import serverChunter from '@anticrm/server-chunter'
export function createModel (builder: Builder): void {
@@ -28,4 +29,8 @@ export function createModel (builder: Builder): void {
builder.mixin(chunter.class.Channel, core.class.Class, view.mixin.TextPresenter, {
presenter: serverChunter.function.ChannelTextPresenter
})
builder.mixin<Class<Doc>, ObjectDDParticipant>(chunter.class.Comment, core.class.Class, serverCore.mixin.ObjectDDParticipant, {
collectDocs: serverChunter.function.CommentRemove
})
}
+10 -5
View File
@@ -16,10 +16,10 @@
import { Model, Builder } from '@anticrm/model'
import type { Resource } from '@anticrm/platform'
import { TDoc } from '@anticrm/model-core'
import { TClass, TDoc } from '@anticrm/model-core'
import type { Trigger, TriggerFunc } from '@anticrm/server-core'
import core, { DOMAIN_MODEL } from '@anticrm/core'
import type { ObjectDDParticipant, Trigger, TriggerFunc } from '@anticrm/server-core'
import core, { Class, Doc, DocumentQuery, DOMAIN_MODEL, FindOptions, FindResult, Hierarchy, Ref } from '@anticrm/core'
import serverCore from '@anticrm/server-core'
@Model(serverCore.class.Trigger, core.class.Doc, DOMAIN_MODEL)
@@ -27,6 +27,11 @@ export class TTrigger extends TDoc implements Trigger {
trigger!: Resource<TriggerFunc>
}
export function createModel (builder: Builder): void {
builder.createModel(TTrigger)
@Model(serverCore.mixin.ObjectDDParticipant, core.class.Class)
export class TObjectDDParticipant extends TClass implements ObjectDDParticipant {
collectDocs!: Resource<(doc: Doc, hiearachy: Hierarchy, findAll: <T extends Doc>(clazz: Ref<Class<T>>, query: DocumentQuery<T>, options?: FindOptions<T>) => Promise<FindResult<T>>) => Promise<Doc[]>>
}
export function createModel (builder: Builder): void {
builder.createModel(TTrigger, TObjectDDParticipant)
}
+7
View File
@@ -0,0 +1,7 @@
module.exports = {
extends: ['./node_modules/@anticrm/model-rig/profiles/default/config/eslint.config.json'],
parserOptions: {
tsconfigRootDir: __dirname,
project: './tsconfig.json'
}
}
+4
View File
@@ -0,0 +1,4 @@
*
!/lib/**
!CHANGELOG.md
/lib/**/__tests__/
+18
View File
@@ -0,0 +1,18 @@
// The "rig.json" file directs tools to look for their config files in an external package.
// Documentation for this system: https://www.npmjs.com/package/@rushstack/rig-package
{
"$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json",
/**
* (Required) The name of the rig package to inherit from.
* It should be an NPM package name with the "-rig" suffix.
*/
"rigPackageName": "@anticrm/model-rig"
/**
* (Optional) Selects a config profile from the rig package. The name must consist of
* lowercase alphanumeric words separated by hyphens, for example "sample-profile".
* If omitted, then the "default" profile will be used."
*/
// "rigProfile": "your-profile-name"
}
+35
View File
@@ -0,0 +1,35 @@
{
"name": "@anticrm/model-server-tags",
"version": "0.6.0",
"main": "lib/index.js",
"author": "Anticrm Platform Contributors",
"license": "EPL-2.0",
"scripts": {
"build": "heft build",
"build:watch": "tsc",
"lint:fix": "eslint --fix src",
"lint": "eslint src",
"format": "prettier --write src && eslint --fix src"
},
"devDependencies": {
"@anticrm/model-rig": "~0.6.0",
"@typescript-eslint/eslint-plugin": "^5.4.0",
"eslint-plugin-import": "^2.25.3",
"eslint-plugin-promise": "^5.1.1",
"eslint-plugin-node": "^11.1.0",
"eslint": "^7.32.0",
"@types/heft-jest": "^1.0.2",
"@typescript-eslint/parser": "^5.4.0",
"eslint-config-standard-with-typescript": "^21.0.1",
"prettier": "^2.4.1",
"@rushstack/heft": "^0.41.1"
},
"dependencies": {
"@anticrm/core": "~0.6.16",
"@anticrm/model": "~0.6.0",
"@anticrm/platform": "~0.6.5",
"@anticrm/server-tags": "~0.6.0",
"@anticrm/server-core": "~0.6.1",
"@anticrm/tags": "~0.6.0"
}
}
+26
View File
@@ -0,0 +1,26 @@
//
// Copyright © 2022 Hardcore Engineering Inc.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
import core, { Class, Doc } from '@anticrm/core'
import { Builder } from '@anticrm/model'
import serverCore, { ObjectDDParticipant } from '@anticrm/server-core'
import serverTags from '@anticrm/server-tags'
import tags from '@anticrm/tags'
export function createModel (builder: Builder): void {
builder.mixin<Class<Doc>, ObjectDDParticipant>(tags.class.TagElement, core.class.Class, serverCore.mixin.ObjectDDParticipant, {
collectDocs: serverTags.function.TagElementRemove
})
}
+8
View File
@@ -0,0 +1,8 @@
{
"extends": "./node_modules/@anticrm/model-rig/profiles/default/tsconfig.json",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./lib",
}
}
+2 -5
View File
@@ -15,14 +15,14 @@
import { Class, Doc, Domain, IndexKind, Ref } from '@anticrm/core'
import { Builder, Collection, Index, Model, Prop, TypeRef, TypeString, UX } from '@anticrm/model'
import core, { TAttachedDoc, TDoc } from '@anticrm/model-core'
import view, { ObjectDDParticipant } from '@anticrm/model-view'
import view from '@anticrm/model-view'
import { Asset, IntlString } from '@anticrm/platform'
import type { TagCategory, TagElement, TagReference } from '@anticrm/tags'
import tags from './plugin'
export { TagCategory, TagElement, TagReference } from '@anticrm/tags'
export { tagsOperation } from './migration'
export { tags as default }
export { TagElement, TagReference, TagCategory } from '@anticrm/tags'
export const DOMAIN_TAGS = 'tags' as Domain
@@ -94,7 +94,4 @@ export function createModel (builder: Builder): void {
builder.mixin(tags.class.TagElement, core.class.Class, view.mixin.AttributePresenter, {
presenter: tags.component.TagElementPresenter
})
builder.mixin<Class<Doc>, ObjectDDParticipant>(tags.class.TagElement, core.class.Class, view.mixin.ObjectDDParticipant, {
collectDocs: tags.dd.DeleteTagElement
})
}
+2 -5
View File
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { Doc, Ref, TxOperations } from '@anticrm/core'
import { IntlString, mergeIds, Resource } from '@anticrm/platform'
import { Ref } from '@anticrm/core'
import { IntlString, mergeIds } from '@anticrm/platform'
import { TagCategory, tagsId } from '@anticrm/tags'
import tags from '@anticrm/tags-resources/src/plugin'
import type { AnyComponent } from '@anticrm/ui'
@@ -42,9 +42,6 @@ export default mergeIds(tagsId, tags, {
CategoryTagsLabel: '' as IntlString,
DefaultLabel: '' as IntlString
},
dd: {
DeleteTagElement: '' as Resource<(doc: Doc, client: TxOperations) => Promise<Doc[]>>
},
category: {
Category: '' as Ref<TagCategory>
}
-7
View File
@@ -25,7 +25,6 @@ import type {
AttributeEditor,
AttributePresenter,
IgnoreActions,
ObjectDDParticipant,
ObjectEditor,
ObjectEditorHeader,
ObjectFactory,
@@ -37,7 +36,6 @@ import type {
} from '@anticrm/view'
import view from './plugin'
export { ObjectDDParticipant } from '@anticrm/view'
export { viewOperation } from './migration'
@Mixin(view.mixin.AttributeEditor, core.class.Class)
@@ -69,10 +67,6 @@ export class TObjectValidator extends TClass implements ObjectValidator {
export class TObjectFactory extends TClass implements ObjectFactory {
component!: AnyComponent
}
@Mixin(view.mixin.ObjectDDParticipant, core.class.Class)
export class TObjectDDParticipant extends TClass implements ObjectDDParticipant {
collectDocs!: Resource<(doc: Doc) => Promise<Doc[]>>
}
@Model(view.class.ViewletDescriptor, core.class.Doc, DOMAIN_MODEL)
export class TViewletDescriptor extends TDoc implements ViewletDescriptor {
@@ -128,7 +122,6 @@ export function createModel (builder: Builder): void {
TObjectValidator,
TObjectFactory,
TObjectEditorHeader,
TObjectDDParticipant,
THTMLPresenter,
TTextPresenter,
TIgnoreActions
@@ -102,13 +102,3 @@ export async function updateBacklinks (client: TxOperations, backlinkId: Ref<Doc
await client.addCollection(chunter.class.Backlink, chunter.space.Backlinks, attachedTo, attachedToClass, collection, adata)
}
}
export async function collectBacklinks (doc: Doc, client: TxOperations): Promise<Doc[]> {
if (!client.getHierarchy().isDerived(doc._class, chunter.class.Comment)) {
return []
}
const comment = doc as Comment
const result = await client.findAll(chunter.class.Backlink, { backlinkId: comment.attachedTo, backlinkClass: comment.attachedToClass, attachedDocId: comment._id })
return result
}
+1 -10
View File
@@ -13,11 +13,7 @@
// limitations under the License.
//
import { Channel } from '@anticrm/chunter'
import { Doc } from '@anticrm/core'
import login from '@anticrm/login'
import { getMetadata, Resources } from '@anticrm/platform'
import { collectBacklinks } from './backlinks'
import { Resources } from '@anticrm/platform'
import TxBacklinkCreate from './components/activity/TxBacklinkCreate.svelte'
import TxBacklinkReference from './components/activity/TxBacklinkReference.svelte'
import TxCommentCreate from './components/activity/TxCommentCreate.svelte'
@@ -27,8 +23,6 @@ import CommentInput from './components/CommentInput.svelte'
import CommentPresenter from './components/CommentPresenter.svelte'
import CommentsPresenter from './components/CommentsPresenter.svelte'
import CreateChannel from './components/CreateChannel.svelte'
import chunter from './plugin'
import workbench from '@anticrm/workbench'
export { CommentsPresenter }
@@ -45,8 +39,5 @@ export default async (): Promise<Resources> => ({
TxCommentCreate,
TxBacklinkCreate,
TxBacklinkReference
},
action: {
CommentRemove: collectBacklinks
}
})
-7
View File
@@ -25,10 +25,6 @@ import CategoryPresenter from './components/CategoryPresenter.svelte'
import tags from './plugin'
import TagsCategoryBar from './components/CategoryBar.svelte'
async function DeleteTagElement (doc: TagElement, client: TxOperations): Promise<Doc[]> {
return await client.findAll(tags.class.TagReference, { tag: doc._id })
}
export default async (): Promise<Resources> => ({
component: {
Tags,
@@ -40,8 +36,5 @@ export default async (): Promise<Resources> => ({
TagsItemPresenter,
CategoryPresenter,
TagsCategoryBar
},
dd: {
DeleteTagElement
}
})
+3 -60
View File
@@ -34,7 +34,7 @@ import type { IntlString } from '@anticrm/platform'
import { getResource } from '@anticrm/platform'
import { getAttributePresenterClass, KeyedAttribute } from '@anticrm/presentation'
import { ErrorPresenter, getPlatformColorForText } from '@anticrm/ui'
import type { Action, ActionTarget, BuildModelOptions, ObjectDDParticipant } from '@anticrm/view'
import type { Action, ActionTarget, BuildModelOptions } from '@anticrm/view'
import view, { AttributeModel, BuildModelKey } from '@anticrm/view'
import plugin from './plugin'
@@ -220,66 +220,9 @@ export async function deleteObject (client: TxOperations, object: Doc): Promise<
const promises: Array<Promise<any>> = []
if (client.getHierarchy().isDerived(object._class, core.class.AttachedDoc)) {
const adoc = object as AttachedDoc
promises.push(client.removeCollection(object._class, object.space, adoc._id, adoc.attachedTo, adoc.attachedToClass, adoc.collection).catch(err => console.error(err)))
await client.removeCollection(object._class, object.space, adoc._id, adoc.attachedTo, adoc.attachedToClass, adoc.collection).catch(err => console.error(err))
} else {
promises.push(client.removeDoc(object._class, object.space, object._id).catch(err => console.error(err)))
}
promises.push(deleteClassCollections(client, object._class, object))
const mixins = getMixins(hierarchy, object._class, object)
for (const mixin of mixins) {
promises.push(deleteClassCollections(client, mixin, object))
}
promises.push(deleteRelatedDocuments(hierarchy, object, client))
await Promise.all(promises)
}
async function deleteClassCollections (client: TxOperations, _class: Ref<Class<Doc>>, object: Doc): Promise<void> {
const hierarchy = client.getHierarchy()
const attributes = hierarchy.getAllAttributes(_class)
for (const [name, attribute] of attributes) {
if (hierarchy.isDerived(attribute.type._class, core.class.Collection)) {
const collection = attribute.type as Collection<AttachedDoc>
const allAttached = await client.findAll(collection.of, { attachedTo: object._id })
for (const attached of allAttached) {
await deleteObject(client, attached).catch(err => console.log('failed to delete', name, err))
}
}
}
}
function getParentClass (hierarchy: Hierarchy, _class: Ref<Class<Doc>>): Ref<Class<Doc>> {
const baseDomain = hierarchy.getDomain(_class)
const ancestors = hierarchy.getAncestors(_class)
let result: Ref<Class<Doc>> = _class
for (const ancestor of ancestors) {
try {
const domain = hierarchy.getClass(ancestor).domain
if (domain === baseDomain) {
result = ancestor
}
} catch {}
}
return result
}
function getMixins (hierarchy: Hierarchy, _class: Ref<Class<Doc>>, object: Doc): Array<Ref<Mixin<Doc>>> {
const parentClass = getParentClass(hierarchy, _class)
const descendants = hierarchy.getDescendants(parentClass)
return descendants.filter(
(m) => hierarchy.getClass(m).kind === ClassifierKind.MIXIN && hierarchy.hasMixin(object, m)
)
}
async function deleteRelatedDocuments (hierarchy: Hierarchy, object: Doc, client: TxOperations): Promise<void> {
const objectClass = hierarchy.getClass(object._class)
if (hierarchy.hasMixin(objectClass, view.mixin.ObjectDDParticipant)) {
const removeParticipand: ObjectDDParticipant = hierarchy.as(objectClass, view.mixin.ObjectDDParticipant)
const collector = await getResource(removeParticipand.collectDocs)
const docs = await collector(object, client)
for (const d of docs) {
await deleteObject(client, d)
}
await client.removeDoc(object._class, object.space, object._id).catch(err => console.error(err))
}
}
+1 -11
View File
@@ -14,7 +14,7 @@
// limitations under the License.
//
import type { AnyAttribute, Class, Client, Doc, DocumentQuery, FindOptions, Mixin, Obj, Ref, Space, TxOperations, UXObject } from '@anticrm/core'
import type { AnyAttribute, Class, Client, Doc, DocumentQuery, FindOptions, Mixin, Obj, Ref, Space, UXObject } from '@anticrm/core'
import type { Asset, IntlString, Plugin, Resource, Status } from '@anticrm/platform'
import { plugin } from '@anticrm/platform'
import type { AnyComponent, AnySvelteComponent } from '@anticrm/ui'
@@ -167,15 +167,6 @@ export interface ObjectFactory extends Class<Obj> {
component: AnyComponent
}
/**
* Allow to contribute and find all derived objects for document.
* @public
*/
export interface ObjectDDParticipant extends Class<Obj> {
// Collect more items to be deleted if parent document is deleted.
collectDocs: Resource<(doc: Doc, client: TxOperations) => Promise<Doc[]>>
}
/**
* @public
*/
@@ -187,7 +178,6 @@ const view = plugin(viewId, {
ObjectEditorHeader: '' as Ref<Mixin<ObjectEditorHeader>>,
ObjectValidator: '' as Ref<Mixin<ObjectValidator>>,
ObjectFactory: '' as Ref<Mixin<ObjectFactory>>,
ObjectDDParticipant: '' as Ref<ObjectDDParticipant>,
IgnoreActions: '' as Ref<Mixin<IgnoreActions>>,
HTMLPresenter: '' as Ref<Mixin<HTMLPresenter>>,
TextPresenter: '' as Ref<Mixin<TextPresenter>>
+15
View File
@@ -1151,5 +1151,20 @@
"projectFolder": "models/calendar",
"shouldPublish": true
},
{
"packageName": "@anticrm/server-tags",
"projectFolder": "server-plugins/tags",
"shouldPublish": true
},
{
"packageName": "@anticrm/model-server-tags",
"projectFolder": "models/server-tags",
"shouldPublish": true
},
{
"packageName": "@anticrm/server-tags-resources",
"projectFolder": "server-plugins/tags-resources",
"shouldPublish": true
},
]
}
+16 -2
View File
@@ -13,8 +13,8 @@
// limitations under the License.
//
import chunter, { Channel } from '@anticrm/chunter'
import { Doc } from '@anticrm/core'
import chunter, { Comment, Channel } from '@anticrm/chunter'
import { Class, Doc, DocumentQuery, FindOptions, FindResult, Hierarchy, Ref } from '@anticrm/core'
import login from '@anticrm/login'
import { getMetadata } from '@anticrm/platform'
import workbench from '@anticrm/workbench'
@@ -36,9 +36,23 @@ export function channelTextPresenter (doc: Doc): string {
return `${channel.name}`
}
/**
* @public
*/
export async function CommentRemove (doc: Doc, hiearachy: Hierarchy, findAll: <T extends Doc> (clazz: Ref<Class<T>>, query: DocumentQuery<T>, options?: FindOptions<T>) => Promise<FindResult<T>>): Promise<Doc[]> {
if (!hiearachy.isDerived(doc._class, chunter.class.Comment)) {
return []
}
const comment = doc as Comment
const result = await findAll(chunter.class.Backlink, { backlinkId: comment.attachedTo, backlinkClass: comment.attachedToClass, attachedDocId: comment._id })
return result
}
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export default async () => ({
function: {
CommentRemove,
ChannelHTMLPresenter: channelHTMLPresenter,
ChannelTextPresenter: channelTextPresenter
}
+3 -2
View File
@@ -13,9 +13,9 @@
// limitations under the License.
//
import type { Resource, Plugin } from '@anticrm/platform'
import { Class, Doc, DocumentQuery, FindOptions, FindResult, Hierarchy, Ref } from '@anticrm/core'
import type { Plugin, Resource } from '@anticrm/platform'
import { plugin } from '@anticrm/platform'
import { Doc } from '@anticrm/core'
/**
* @public
@@ -27,6 +27,7 @@ export const serverChunterId = 'server-chunter' as Plugin
*/
export default plugin(serverChunterId, {
function: {
CommentRemove: '' as Resource<(doc: Doc, hiearachy: Hierarchy, findAll: <T extends Doc> (clazz: Ref<Class<T>>, query: DocumentQuery<T>, options?: FindOptions<T>) => Promise<FindResult<T>>) => Promise<Doc[]>>,
ChannelHTMLPresenter: '' as Resource<(doc: Doc) => string>,
ChannelTextPresenter: '' as Resource<(doc: Doc) => string>
}
@@ -0,0 +1,7 @@
module.exports = {
extends: ['./node_modules/@anticrm/platform-rig/profiles/default/config/eslint.config.json'],
parserOptions: {
tsconfigRootDir: __dirname,
project: './tsconfig.json'
}
}
+4
View File
@@ -0,0 +1,4 @@
*
!/lib/**
!CHANGELOG.md
/lib/**/__tests__/
@@ -0,0 +1,18 @@
// The "rig.json" file directs tools to look for their config files in an external package.
// Documentation for this system: https://www.npmjs.com/package/@rushstack/rig-package
{
"$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json",
/**
* (Required) The name of the rig package to inherit from.
* It should be an NPM package name with the "-rig" suffix.
*/
"rigPackageName": "@anticrm/platform-rig"
/**
* (Optional) Selects a config profile from the rig package. The name must consist of
* lowercase alphanumeric words separated by hyphens, for example "sample-profile".
* If omitted, then the "default" profile will be used."
*/
// "rigProfile": "your-profile-name"
}
@@ -0,0 +1,34 @@
{
"name": "@anticrm/server-tags-resources",
"version": "0.6.0",
"main": "lib/index.js",
"author": "Anticrm Platform Contributors",
"license": "EPL-2.0",
"scripts": {
"build": "heft build",
"build:watch": "tsc",
"lint:fix": "eslint --fix src",
"lint": "eslint src",
"format": "prettier --write src && eslint --fix src"
},
"devDependencies": {
"@anticrm/platform-rig": "~0.6.0",
"@types/heft-jest": "^1.0.2",
"@typescript-eslint/eslint-plugin": "^5.4.0",
"eslint-plugin-import": "^2.25.3",
"eslint-plugin-promise": "^5.1.1",
"eslint-plugin-node": "^11.1.0",
"eslint": "^7.32.0",
"@typescript-eslint/parser": "^5.4.0",
"eslint-config-standard-with-typescript": "^21.0.1",
"prettier": "^2.4.1",
"@rushstack/heft": "^0.41.1",
"typescript": "^4.3.5"
},
"dependencies": {
"@anticrm/core": "~0.6.16",
"@anticrm/platform": "~0.6.5",
"@anticrm/server-core": "~0.6.1",
"@anticrm/tags": "~0.6.0"
}
}
@@ -0,0 +1,32 @@
//
// Copyright © 2022 Hardcore Engineering Inc.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
import { Class, Doc, DocumentQuery, FindOptions, FindResult, Hierarchy, Ref } from '@anticrm/core'
import tags, { TagElement } from '@anticrm/tags'
/**
* @public
*/
export async function TagElementRemove (doc: Doc, hiearachy: Hierarchy, findAll: <T extends Doc> (clazz: Ref<Class<T>>, query: DocumentQuery<T>, options?: FindOptions<T>) => Promise<FindResult<T>>): Promise<Doc[]> {
if (hiearachy.isDerived(doc._class, tags.class.TagElement)) return []
return await findAll(tags.class.TagReference, { tag: doc._id as Ref<TagElement> })
}
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export default async () => ({
function: {
TagElementRemove
}
})
@@ -0,0 +1,8 @@
{
"extends": "./node_modules/@anticrm/platform-rig/profiles/default/tsconfig.json",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./lib"
}
}
+7
View File
@@ -0,0 +1,7 @@
module.exports = {
extends: ['./node_modules/@anticrm/platform-rig/profiles/default/config/eslint.config.json'],
parserOptions: {
tsconfigRootDir: __dirname,
project: './tsconfig.json'
}
}
+4
View File
@@ -0,0 +1,4 @@
*
!/lib/**
!CHANGELOG.md
/lib/**/__tests__/
+18
View File
@@ -0,0 +1,18 @@
// The "rig.json" file directs tools to look for their config files in an external package.
// Documentation for this system: https://www.npmjs.com/package/@rushstack/rig-package
{
"$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json",
/**
* (Required) The name of the rig package to inherit from.
* It should be an NPM package name with the "-rig" suffix.
*/
"rigPackageName": "@anticrm/platform-rig"
/**
* (Optional) Selects a config profile from the rig package. The name must consist of
* lowercase alphanumeric words separated by hyphens, for example "sample-profile".
* If omitted, then the "default" profile will be used."
*/
// "rigProfile": "your-profile-name"
}
+34
View File
@@ -0,0 +1,34 @@
{
"name": "@anticrm/server-tags",
"version": "0.6.0",
"main": "lib/index.js",
"author": "Anticrm Platform Contributors",
"license": "EPL-2.0",
"scripts": {
"build": "heft build",
"build:watch": "tsc",
"lint:fix": "eslint --fix src",
"lint": "eslint src",
"format": "prettier --write src && eslint --fix src"
},
"devDependencies": {
"@anticrm/platform-rig": "~0.6.0",
"@types/heft-jest": "^1.0.2",
"@types/node": "~16.11.12",
"@typescript-eslint/eslint-plugin": "^5.4.0",
"eslint-plugin-import": "^2.25.3",
"eslint-plugin-promise": "^5.1.1",
"eslint-plugin-node": "^11.1.0",
"eslint": "^7.32.0",
"@typescript-eslint/parser": "^5.4.0",
"eslint-config-standard-with-typescript": "^21.0.1",
"prettier": "^2.4.1",
"@rushstack/heft": "^0.41.1",
"typescript": "^4.3.5"
},
"dependencies": {
"@anticrm/core": "~0.6.16",
"@anticrm/platform": "~0.6.5",
"@anticrm/server-core": "~0.6.1"
}
}
+32
View File
@@ -0,0 +1,32 @@
//
// Copyright © 2022 Hardcore Engineering Inc.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
import { Class, Doc, Hierarchy, Ref, FindResult, FindOptions, DocumentQuery } from '@anticrm/core'
import type { Plugin, Resource } from '@anticrm/platform'
import { plugin } from '@anticrm/platform'
/**
* @public
*/
export const serverTagsId = 'server-tags' as Plugin
/**
* @public
*/
export default plugin(serverTagsId, {
function: {
TagElementRemove: '' as Resource<(doc: Doc, hiearachy: Hierarchy, findAll: <T extends Doc> (clazz: Ref<Class<T>>, query: DocumentQuery<T>, options?: FindOptions<T>) => Promise<FindResult<T>>) => Promise<Doc[]>>
}
})
+9
View File
@@ -0,0 +1,9 @@
{
"extends": "./node_modules/@anticrm/platform-rig/profiles/default/tsconfig.json",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./lib",
"esModuleInterop": true
}
}
+4 -1
View File
@@ -18,7 +18,7 @@ import type { Plugin } from '@anticrm/platform'
import { plugin } from '@anticrm/platform'
import type { Ref, Class } from '@anticrm/core'
import type { Trigger } from './types'
import type { ObjectDDParticipant, Trigger } from './types'
/**
* @public
@@ -31,6 +31,9 @@ export const serverCoreId = 'server-core' as Plugin
const serverCore = plugin(serverCoreId, {
class: {
Trigger: '' as Ref<Class<Trigger>>
},
mixin: {
ObjectDDParticipant: '' as Ref<ObjectDDParticipant>
}
})
+140 -3
View File
@@ -17,6 +17,8 @@
import core, {
AttachedDoc,
Class,
ClassifierKind,
Collection,
Doc,
DocumentQuery,
Domain,
@@ -25,21 +27,28 @@ import core, {
FindOptions,
FindResult,
Hierarchy,
MeasureContext, ModelDb,
MeasureContext, Mixin, ModelDb,
Ref,
ServerStorage,
Storage,
Tx,
TxBulkWrite,
TxCollectionCUD,
TxCreateDoc,
TxCUD,
TxFactory,
TxResult
TxMixin,
TxProcessor,
TxRemoveDoc,
TxResult,
TxUpdateDoc
} from '@anticrm/core'
import { getResource } from '@anticrm/platform'
import type { Client as MinioClient } from 'minio'
import { FullTextIndex } from './fulltext'
import serverCore from './plugin'
import { Triggers } from './triggers'
import type { FullTextAdapter, FullTextAdapterFactory } from './types'
import type { FullTextAdapter, FullTextAdapterFactory, ObjectDDParticipant } from './types'
/**
* @public
@@ -197,6 +206,133 @@ class TServerStorage implements ServerStorage {
})
}
getParentClass (_class: Ref<Class<Doc>>): Ref<Class<Doc>> {
const baseDomain = this.hierarchy.getDomain(_class)
const ancestors = this.hierarchy.getAncestors(_class)
let result: Ref<Class<Doc>> = _class
for (const ancestor of ancestors) {
try {
const domain = this.hierarchy.getClass(ancestor).domain
if (domain === baseDomain) {
result = ancestor
}
} catch {}
}
return result
}
getMixins (_class: Ref<Class<Doc>>, object: Doc): Array<Ref<Mixin<Doc>>> {
const parentClass = this.getParentClass(_class)
const descendants = this.hierarchy.getDescendants(parentClass)
return descendants.filter(
(m) => this.hierarchy.getClass(m).kind === ClassifierKind.MIXIN && this.hierarchy.hasMixin(object, m)
)
}
async buildRemovedDoc (ctx: MeasureContext, tx: TxRemoveDoc<Doc>): Promise<Doc | undefined> {
const txes = await this.findAll(ctx, core.class.TxCUD, { objectId: tx.objectId }, { sort: { modifiedOn: 1 } })
let doc: Doc
let createTx = txes.find((tx) => tx._class === core.class.TxCreateDoc)
if (createTx === undefined) {
const collectionTxes = txes.filter((tx) => tx._class === core.class.TxCollectionCUD) as TxCollectionCUD<Doc, AttachedDoc>[]
createTx = collectionTxes.find((p) => p.tx._class === core.class.TxCreateDoc)
}
if (createTx === undefined) return
doc = TxProcessor.createDoc2Doc(createTx as TxCreateDoc<Doc>)
for (const tx of txes) {
if (tx._class === core.class.TxUpdateDoc) {
doc = TxProcessor.updateDoc2Doc(doc, tx as TxUpdateDoc<Doc>)
} else if (tx._class === core.class.TxMixin) {
const mixinTx = tx as TxMixin<Doc, Doc>
doc = TxProcessor.updateMixin4Doc(doc, mixinTx.mixin, mixinTx.attributes)
}
}
return doc
}
extractTx (tx: Tx): Tx {
if (tx._class === core.class.TxCollectionCUD) {
const ctx = (tx as TxCollectionCUD<Doc, AttachedDoc>)
return ctx.tx
}
return tx
}
async processRemove (ctx: MeasureContext, tx: Tx): Promise<Tx[]> {
const actualTx = this.extractTx(tx)
if (!this.hierarchy.isDerived(actualTx._class, core.class.TxRemoveDoc)) return []
const rtx = actualTx as TxRemoveDoc<Doc>
const result: Tx[] = []
const object = await this.buildRemovedDoc(ctx, rtx)
if (object === undefined) return []
result.push(...await this.deleteClassCollections(ctx, object._class, rtx.objectId))
const mixins = this.getMixins(object._class, object)
for (const mixin of mixins) {
result.push(...await this.deleteClassCollections(ctx, mixin, rtx.objectId))
}
result.push(...await this.deleteRelatedDocuments(ctx, object))
return result
}
async deleteClassCollections (ctx: MeasureContext, _class: Ref<Class<Doc>>, objectId: Ref<Doc>): Promise<Tx[]> {
const attributes = this.hierarchy.getAllAttributes(_class)
const result: Tx[] = []
for (const attribute of attributes) {
if (this.hierarchy.isDerived(attribute[1].type._class, core.class.Collection)) {
const collection = attribute[1].type as Collection<AttachedDoc>
const allAttached = await this.findAll(ctx, collection.of, { attachedTo: objectId })
for (const attached of allAttached) {
result.push(...await this.deleteObject(ctx, attached))
}
}
}
return result
}
async deleteObject (ctx: MeasureContext, object: Doc): Promise<Tx[]> {
const result: Tx[] = []
const factory = new TxFactory(core.account.System)
if (this.hierarchy.isDerived(object._class, core.class.AttachedDoc)) {
const adoc = object as AttachedDoc
const nestedTx = factory.createTxRemoveDoc(object._class, object.space, adoc._id) as TxRemoveDoc<AttachedDoc>
const tx = factory.createTxCollectionCUD(
adoc.attachedToClass,
adoc.attachedTo,
object.space,
adoc.collection,
nestedTx
)
result.push(tx)
} else {
result.push(factory.createTxRemoveDoc(object._class, object.space, object._id))
}
result.push(...await this.deleteClassCollections(ctx, object._class, object._id))
const mixins = this.getMixins(object._class, object)
for (const mixin of mixins) {
result.push(...await this.deleteClassCollections(ctx, mixin, object._id))
}
result.push(...await this.deleteRelatedDocuments(ctx, object))
return result
}
async deleteRelatedDocuments (ctx: MeasureContext, object: Doc): Promise<Tx[]> {
const result: Tx[] = []
const objectClass = this.hierarchy.getClass(object._class)
if (this.hierarchy.hasMixin(objectClass, serverCore.mixin.ObjectDDParticipant)) {
const removeParticipand: ObjectDDParticipant = this.hierarchy.as(objectClass, serverCore.mixin.ObjectDDParticipant)
const collector = await getResource(removeParticipand.collectDocs)
const docs = await collector(object, this.hierarchy, async (_class, query, options) => {
return await this.findAll(ctx, _class, query, options)
})
for (const d of docs) {
result.push(...await this.deleteObject(ctx, d))
}
}
return result
}
async tx (ctx: MeasureContext, tx: Tx): Promise<[TxResult, Tx[]]> {
// store tx
const _class = txClass(tx)
@@ -227,6 +363,7 @@ class TServerStorage implements ServerStorage {
// invoke triggers and store derived objects
derived = [
...(await ctx.with('process-collection', { _class }, () => this.processCollection(ctx, tx))),
...(await ctx.with('process-remove', { _class }, () => this.processRemove(ctx, tx))),
...(await ctx.with('process-triggers', {}, (ctx) =>
this.triggers.apply(tx.modifiedBy, tx, {
fx: triggerFx.fx,
+10 -1
View File
@@ -15,7 +15,7 @@
//
import type { Client as MinioClient } from 'minio'
import type { Tx, Ref, Doc, Class, Storage, Space, Timestamp, Account, FindResult, DocumentQuery, FindOptions, TxResult, MeasureContext, ModelDb } from '@anticrm/core'
import type { Tx, Ref, Doc, Class, Storage, Space, Timestamp, Account, FindResult, DocumentQuery, FindOptions, TxResult, MeasureContext, ModelDb, Obj } from '@anticrm/core'
import { TxFactory, Hierarchy } from '@anticrm/core'
import type { Resource } from '@anticrm/platform'
@@ -83,3 +83,12 @@ export type FullTextAdapterFactory = (url: string, workspace: string) => Promise
export interface WithFind {
findAll: <T extends Doc> (ctx: MeasureContext, clazz: Ref<Class<T>>, query: DocumentQuery<T>, options?: FindOptions<T>) => Promise<FindResult<T>>
}
/**
* Allow to contribute and find all derived objects for document.
* @public
*/
export interface ObjectDDParticipant extends Class<Obj> {
// Collect more items to be deleted if parent document is deleted.
collectDocs: Resource<(doc: Doc, hiearachy: Hierarchy, findAll: <T extends Doc> (clazz: Ref<Class<T>>, query: DocumentQuery<T>, options?: FindOptions<T>) => Promise<FindResult<T>>) => Promise<Doc[]>>
}
+2
View File
@@ -63,6 +63,8 @@
"@anticrm/server-recruit-resources": "~0.6.0",
"@anticrm/server-task": "~0.6.0",
"@anticrm/server-task-resources": "~0.6.0",
"@anticrm/server-tags": "~0.6.0",
"@anticrm/server-tags-resources": "~0.6.0",
"@anticrm/server-token": "~0.6.0"
}
}
+2
View File
@@ -32,6 +32,7 @@ import { serverInventoryId } from '@anticrm/server-inventory'
import { serverLeadId } from '@anticrm/server-lead'
import { serverRecruitId } from '@anticrm/server-recruit'
import { serverTaskId } from '@anticrm/server-task'
import { serverTagsId } from '@anticrm/server-tags'
import { metricsContext } from './metrics'
@@ -68,6 +69,7 @@ export function start (dbUrl: string, fullTextUrl: string, minioConf: MinioConfi
addLocation(serverLeadId, () => import('@anticrm/server-lead-resources'))
addLocation(serverRecruitId, () => import('@anticrm/server-recruit-resources'))
addLocation(serverTaskId, () => import('@anticrm/server-task-resources'))
addLocation(serverTagsId, () => import('@anticrm/server-tags-resources'))
return startJsonRpc(metricsContext, (workspace: string) => {
const conf: DbConfiguration = {