add more packages to compile workbench

Signed-off-by: Andrey Platov <andrey@hardcoreeng.com>
This commit is contained in:
Andrey Platov 2021-08-06 12:18:50 +02:00
parent c3737b1f0f
commit ad325a1d07
No known key found for this signature in database
GPG Key ID: C8787EFEB4B64AF0
31 changed files with 894 additions and 15 deletions

View File

@ -2,6 +2,7 @@ lockfileVersion: 5.3
specifiers:
'@microsoft/api-extractor': ^7.18.4
'@rush-temp/client': file:./projects/client.tgz
'@rush-temp/core': file:./projects/core.tgz
'@rush-temp/dev-server': file:./projects/dev-server.tgz
'@rush-temp/dev-storage': file:./projects/dev-storage.tgz
@ -12,11 +13,13 @@ specifiers:
'@rush-temp/platform-rig': file:./projects/platform-rig.tgz
'@rush-temp/presentation': file:./projects/presentation.tgz
'@rush-temp/prod': file:./projects/prod.tgz
'@rush-temp/query': file:./projects/query.tgz
'@rush-temp/server': file:./projects/server.tgz
'@rush-temp/server-core': file:./projects/server-core.tgz
'@rush-temp/server-ws': file:./projects/server-ws.tgz
'@rush-temp/theme': file:./projects/theme.tgz
'@rush-temp/ui': file:./projects/ui.tgz
'@rush-temp/view': file:./projects/view.tgz
'@rush-temp/workbench': file:./projects/workbench.tgz
'@rush-temp/workbench-resources': file:./projects/workbench-resources.tgz
'@rushstack/heft': ^0.35.0
@ -57,6 +60,7 @@ specifiers:
dependencies:
'@microsoft/api-extractor': 7.18.4
'@rush-temp/client': file:projects/client.tgz_6c259fadfeb3a4b20890aefe87070b8b
'@rush-temp/core': file:projects/core.tgz_6c259fadfeb3a4b20890aefe87070b8b
'@rush-temp/dev-server': file:projects/dev-server.tgz_6c259fadfeb3a4b20890aefe87070b8b
'@rush-temp/dev-storage': file:projects/dev-storage.tgz_6c259fadfeb3a4b20890aefe87070b8b
@ -67,11 +71,13 @@ dependencies:
'@rush-temp/platform-rig': file:projects/platform-rig.tgz_6ab28797e7a22071465f7d680ae81ae5
'@rush-temp/presentation': file:projects/presentation.tgz_c38cf1a7a413db8918b0b4754c21e4c5
'@rush-temp/prod': file:projects/prod.tgz_sass@1.37.5+typescript@4.3.5
'@rush-temp/query': file:projects/query.tgz_6c259fadfeb3a4b20890aefe87070b8b
'@rush-temp/server': file:projects/server.tgz_6c259fadfeb3a4b20890aefe87070b8b
'@rush-temp/server-core': file:projects/server-core.tgz_6c259fadfeb3a4b20890aefe87070b8b
'@rush-temp/server-ws': file:projects/server-ws.tgz_6c259fadfeb3a4b20890aefe87070b8b
'@rush-temp/theme': file:projects/theme.tgz_c38cf1a7a413db8918b0b4754c21e4c5
'@rush-temp/ui': file:projects/ui.tgz_c38cf1a7a413db8918b0b4754c21e4c5
'@rush-temp/view': file:projects/view.tgz_6c259fadfeb3a4b20890aefe87070b8b
'@rush-temp/workbench': file:projects/workbench.tgz_6c259fadfeb3a4b20890aefe87070b8b
'@rush-temp/workbench-resources': file:projects/workbench-resources.tgz_c38cf1a7a413db8918b0b4754c21e4c5
'@rushstack/heft': 0.35.0
@ -7680,6 +7686,24 @@ packages:
commander: 2.20.3
dev: false
file:projects/client.tgz_6c259fadfeb3a4b20890aefe87070b8b:
resolution: {integrity: sha512-8YJou7AitxzzH2roWCno/zgd27SiQXlqrdDVyhAAvZrBZY7KGbxw4OxGkI+6eVK+Lk/zajS2FkGZ+oyZ+Bxe6g==, tarball: file:projects/client.tgz}
id: file:projects/client.tgz
name: '@rush-temp/client'
version: 0.0.0
dependencies:
'@types/heft-jest': 1.0.2
'@typescript-eslint/eslint-plugin': 4.28.5_a8e83fcad666e1ba86be4b2e27a20aea
eslint: 7.32.0
eslint-plugin-import: 2.23.4_eslint@7.32.0
eslint-plugin-node: 11.1.0_eslint@7.32.0
eslint-plugin-promise: 4.3.1
transitivePeerDependencies:
- '@typescript-eslint/parser'
- supports-color
- typescript
dev: false
file:projects/core.tgz_6c259fadfeb3a4b20890aefe87070b8b:
resolution: {integrity: sha512-H49oedby3HV+eR2uQZAI0kIJ8Yxh8uIR+sLg4Ox0JAy4UJtfP5AmyWltddqaUdQIcfYrb2BrhDSDSxddlDWhpg==, tarball: file:projects/core.tgz}
id: file:projects/core.tgz
@ -7827,7 +7851,7 @@ packages:
dev: false
file:projects/presentation.tgz_c38cf1a7a413db8918b0b4754c21e4c5:
resolution: {integrity: sha512-y4BqVd0TM1NHy74NaREi5s26qWOro+kn+dVogNYFm3mkuVEqHwv/ZzivbLI9X7Ti7IbuG8FeCy2N1r9Cs6XUJg==, tarball: file:projects/presentation.tgz}
resolution: {integrity: sha512-v1qRQGQrWDFfME4IEpK6bM0E3IQljeG2+Ft/YVPM/Fbf/y3e+28AvI3nyvLn+1N6gY+5faEAHLE4M9vBbR+A1A==, tarball: file:projects/presentation.tgz}
id: file:projects/presentation.tgz
name: '@rush-temp/presentation'
version: 0.0.0
@ -7887,6 +7911,25 @@ packages:
- utf-8-validate
dev: false
file:projects/query.tgz_6c259fadfeb3a4b20890aefe87070b8b:
resolution: {integrity: sha512-9CUYPnThJmot4jmOsi6R7ugG/yTz+6emWtPfhSTK+1hqr3hXaYSXIXuYirvqpa6a434uRTUAe362U5VuNi4xdA==, tarball: file:projects/query.tgz}
id: file:projects/query.tgz
name: '@rush-temp/query'
version: 0.0.0
dependencies:
'@types/heft-jest': 1.0.2
'@typescript-eslint/eslint-plugin': 4.28.5_a8e83fcad666e1ba86be4b2e27a20aea
eslint: 7.32.0
eslint-plugin-import: 2.23.4_eslint@7.32.0
eslint-plugin-node: 11.1.0_eslint@7.32.0
eslint-plugin-promise: 4.3.1
simplytyped: 3.3.0_typescript@4.3.5
transitivePeerDependencies:
- '@typescript-eslint/parser'
- supports-color
- typescript
dev: false
file:projects/server-core.tgz_6c259fadfeb3a4b20890aefe87070b8b:
resolution: {integrity: sha512-lHE4PAWrX+WKdM9/Yy1rYZW6rCacwLMkSUIJakrXZeyGlNytXXSvH20bgfocVn73grez3Zjy6qlNm7H7EClgDQ==, tarball: file:projects/server-core.tgz}
id: file:projects/server-core.tgz
@ -7997,8 +8040,26 @@ packages:
- typescript
dev: false
file:projects/view.tgz_6c259fadfeb3a4b20890aefe87070b8b:
resolution: {integrity: sha512-BQgcAfVRNy1QO/Z8ATfQZbm090HU2b7jl5r38stX7rjzF0udaYKci9yDb9xECP1oYCEPWXbayUPlF/AwRqxZ4g==, tarball: file:projects/view.tgz}
id: file:projects/view.tgz
name: '@rush-temp/view'
version: 0.0.0
dependencies:
'@types/heft-jest': 1.0.2
'@typescript-eslint/eslint-plugin': 4.28.5_a8e83fcad666e1ba86be4b2e27a20aea
eslint: 7.32.0
eslint-plugin-import: 2.23.4_eslint@7.32.0
eslint-plugin-node: 11.1.0_eslint@7.32.0
eslint-plugin-promise: 4.3.1
transitivePeerDependencies:
- '@typescript-eslint/parser'
- supports-color
- typescript
dev: false
file:projects/workbench-resources.tgz_c38cf1a7a413db8918b0b4754c21e4c5:
resolution: {integrity: sha512-LMzBHdlTssEH28+ttT/0/eeghU3OWwwJ7AWksnnJsabUEgfjaYNZqTfsLiD6CCjMJXMVU/kUvUjBmlpB8HWUpg==, tarball: file:projects/workbench-resources.tgz}
resolution: {integrity: sha512-UZMkx/Mq9SBiSR6JFaCmJ548KfR1cSser177G9y196X9ot7EYLYHSZ0Teo9hZTwUgDU1TDkk2KW2sxuFN71naA==, tarball: file:projects/workbench-resources.tgz}
id: file:projects/workbench-resources.tgz
name: '@rush-temp/workbench-resources'
version: 0.0.0

View File

@ -20,7 +20,6 @@ import type { Storage, DocumentQuery, FindOptions, FindResult } from './storage'
import { Hierarchy } from './hierarchy'
import { ModelDb } from './memdb'
import { DOMAIN_MODEL } from './classes'
import { TxProcessor } from './tx'
import core from './component'
@ -36,9 +35,8 @@ export interface Client extends Storage {
getHierarchy: () => Hierarchy
}
class ClientImpl extends TxProcessor implements Storage, Client {
class ClientImpl implements Storage, Client {
constructor (private readonly hierarchy: Hierarchy, private readonly model: ModelDb, private readonly conn: Storage) {
super()
}
getHierarchy (): Hierarchy { return this.hierarchy }

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

View File

@ -19,7 +19,11 @@
"svelte-preprocess":"^4.7.4"
},
"dependencies": {
"@anticrm/platform": "~0.6.0",
"@anticrm/core": "~0.6.0",
"@anticrm/query": "~0.6.0",
"@anticrm/ui": "~0.6.0",
"@anticrm/view": "~0.6.0",
"svelte": "^3.37.0"
}
}

View File

@ -16,17 +16,20 @@
import { getContext, setContext, onDestroy } from 'svelte'
import type { Doc, Ref, Class, DocumentQuery, FindOptions } from '@anticrm/core'
import type { Connection } from '@anticrm/client'
import type { Doc, Ref, Class, DocumentQuery, FindOptions, Client } from '@anticrm/core'
import { LiveQuery as LQ } from '@anticrm/query'
const CLIENT_CONEXT = 'workbench.context.Client'
export function getClient(): Connection {
return getContext<Connection>(CLIENT_CONEXT)
let liveQuery: LQ
export function getClient(): Client {
return getContext<Client>(CLIENT_CONEXT)
}
export function setClient(client: Connection) {
export function setClient(client: Client) {
setContext(CLIENT_CONEXT, client)
liveQuery = new LQ(client)
}
class LiveQuery {
@ -39,7 +42,7 @@ class LiveQuery {
query<T extends Doc>(_class: Ref<Class<T>>, query: DocumentQuery<T>, callback: (result: T[]) => void, options?: FindOptions<T>) {
this.unsubscribe()
this.unsubscribe = this.client.query(_class, query, callback, options)
this.unsubscribe = liveQuery.query(_class, query, callback, options)
}
}

View File

@ -0,0 +1,6 @@
module.exports = {
extends: ['./node_modules/@anticrm/platform-rig/profiles/default/config/eslint.config.json'],
parserOptions: {
project: './tsconfig.json'
}
}

View File

@ -0,0 +1,4 @@
*
!/lib/**
!CHANGELOG.md
/lib/**/__tests__/

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"
}

View File

@ -0,0 +1,25 @@
{
"name": "@anticrm/query",
"version": "0.6.0",
"main": "lib/index.js",
"author": "Anticrm Platform Contributors",
"license": "EPL-2.0",
"scripts": {
"build": "heft build",
"lint:fix": "eslint --fix src"
},
"devDependencies": {
"@anticrm/platform-rig":"~0.6.0",
"@types/heft-jest":"^1.0.2",
"@typescript-eslint/eslint-plugin":"4",
"eslint-plugin-import":"2",
"eslint-plugin-promise":"4",
"eslint-plugin-node":"11",
"eslint":"^7.32.0",
"simplytyped": "^3.3.0"
},
"dependencies": {
"@anticrm/platform": "~0.6.3",
"@anticrm/core": "~0.6.3"
}
}

View File

@ -0,0 +1,50 @@
//
// Copyright © 2020 Anticrm Platform Contributors.
//
// 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 type { Tx, Storage, Ref, Doc, Class, DocumentQuery, FindResult } from '@anticrm/core'
import core, { ModelDb, TxDb, Hierarchy, DOMAIN_TX } from '@anticrm/core'
import { genMinModel } from '@anticrm/core/src/__tests__/minmodel'
export async function connect (handler: (tx: Tx) => void): Promise<Storage> {
const txes = genMinModel()
const hierarchy = new Hierarchy()
for (const tx of txes) hierarchy.tx(tx)
const transactions = new TxDb(hierarchy)
const model = new ModelDb(hierarchy)
for (const tx of txes) {
await transactions.tx(tx)
await model.tx(tx)
}
async function findAll<T extends Doc> (_class: Ref<Class<T>>, query: DocumentQuery<T>): Promise<FindResult<T>> {
const domain = hierarchy.getClass(_class).domain
if (domain === DOMAIN_TX) return await transactions.findAll(_class, query)
return await model.findAll(_class, query)
}
return {
findAll,
tx: async (tx: Tx): Promise<void> => {
if (tx.objectSpace === core.space.Model) {
hierarchy.tx(tx)
}
await Promise.all([model.tx(tx), transactions.tx(tx)])
handler(tx)
}
}
}

View File

@ -0,0 +1,263 @@
//
// Copyright © 2021 Anticrm Platform Contributors.
//
// 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 type { Class, Client, Doc, DocumentQuery, FindOptions, FindResult, Obj, Ref, Space, Tx, TxCreateDoc } from '@anticrm/core'
import core, { createClient, DOMAIN_TX, Hierarchy, ModelDb, TxDb, withOperations, SortingOrder } from '@anticrm/core'
import { genMinModel as getModel } from '@anticrm/core/src/__tests__/minmodel'
import { LiveQuery } from '..'
import { connect } from './connection'
interface Channel extends Space {
x: number
}
describe('query', () => {
it('findAll', async () => {
const client = await getClient()
const query = withOperations(core.account.System, new LiveQuery(client))
const result = await query.findAll<Space>(core.class.Space, {})
expect(result).toHaveLength(2)
})
it('query with param', async (done) => {
const storage = await getClient()
let expectedLength = 0
const txes = await getModel()
for (let i = 0; i < txes.length; i++) {
if (storage.getHierarchy().isDerived((txes[i] as TxCreateDoc<Doc>).objectClass, core.class.Space)) {
expectedLength++
}
}
const query = new LiveQuery(storage)
query.query<Space>(core.class.Space, { private: false }, (result) => {
expect(result).toHaveLength(expectedLength)
done()
})
})
it('query should be live', async (done) => {
const storage = await getClient()
let expectedLength = 0
const txes = await getModel()
for (let i = 0; i < txes.length; i++) {
if (storage.getHierarchy().isDerived((txes[i] as TxCreateDoc<Doc>).objectClass, core.class.Space)) {
expectedLength++
}
}
let attempt = 0
const query = withOperations(core.account.System, new LiveQuery(storage))
query.query<Space>(core.class.Space, { private: false }, (result) => {
expect(result).toHaveLength(expectedLength + attempt)
if (attempt > 0) {
expect((result[expectedLength + attempt - 1] as any).x).toBe(attempt)
}
if (attempt++ === 3) {
// check underlying storage received all data.
storage
.findAll<Space>(core.class.Space, { private: false })
.then((result) => {
expect(result).toHaveLength(expectedLength + attempt - 1)
done()
})
.catch((err) => expect(err).toBeUndefined())
}
})
await query.createDoc<Channel>(core.class.Space, core.space.Model, {
private: false,
name: '#1',
description: '',
members: [],
x: 1
})
await query.createDoc<Channel>(core.class.Space, core.space.Model, {
private: false,
name: '#2',
description: '',
members: [],
x: 2
})
await query.createDoc<Channel>(core.class.Space, core.space.Model, {
private: false,
name: '#3',
description: '',
members: [],
x: 3
})
})
it('unsubscribe query', async () => {
const storage = await getClient()
let expectedLength = 0
const txes = await getModel()
for (let i = 0; i < txes.length; i++) {
if (storage.getHierarchy().isDerived((txes[i] as TxCreateDoc<Doc>).objectClass, core.class.Space)) {
expectedLength++
}
}
const query = withOperations(core.account.System, new LiveQuery(storage))
const unsubscribe = query.query<Space>(core.class.Space, { private: false }, (result) => {
expect(result).toHaveLength(expectedLength)
})
unsubscribe()
await query.createDoc(core.class.Space, core.space.Model, {
private: false,
name: '#1',
description: '',
members: []
})
await query.createDoc(core.class.Space, core.space.Model, {
private: false,
name: '#2',
description: '',
members: []
})
await query.createDoc(core.class.Space, core.space.Model, {
private: false,
name: '#3',
description: '',
members: []
})
})
it('query against core client', async (done) => {
const client = await createClient(connect)
const expectedLength = 2
let attempt = 0
const query = withOperations(core.account.System, new LiveQuery(client))
query.query<Space>(core.class.Space, { private: false }, (result) => {
expect(result).toHaveLength(expectedLength + attempt)
if (attempt > 0) {
expect((result[expectedLength + attempt - 1] as any).x).toBe(attempt)
}
if (attempt++ === 1) done()
})
await query.createDoc<Channel>(core.class.Space, core.space.Model, {
x: 1,
private: false,
name: '#1',
description: '',
members: []
})
await query.createDoc<Channel>(core.class.Space, core.space.Model, {
x: 2,
private: false,
name: '#2',
description: '',
members: []
})
await query.createDoc<Channel>(core.class.Space, core.space.Model, {
x: 3,
private: false,
name: '#3',
description: '',
members: []
})
})
it('limit and sorting', async (done) => {
const storage = await getClient()
const limit = 1
let attempt = 0
let doneCount = 0
const query = withOperations(core.account.System, new LiveQuery(storage))
query.query<Space>(core.class.Space, { private: true }, (result) => {
if (attempt > 0 && result.length > 0) {
expect(result.length).toEqual(limit)
expect(result[0].name).toMatch('0')
}
if (attempt === 1) doneCount++
if (doneCount === 2) done()
}, { limit: limit, sort: { name: SortingOrder.Ascending } })
query.query<Space>(core.class.Space, { private: true }, (result) => {
if (attempt > 0 && result.length > 0) {
expect(result.length).toEqual(limit)
expect(result[0].name).toMatch(attempt.toString())
}
if (attempt === 10) doneCount++
if (doneCount === 2) done()
}, { limit: limit, sort: { name: SortingOrder.Descending } })
for (let i = 0; i < 10; i++) {
attempt++
await query.createDoc(core.class.Space, core.space.Model, {
private: true,
name: i.toString(),
description: '',
members: []
})
}
})
it('remove', async (done) => {
const client = await createClient(connect)
const expectedLength = 2
let attempt = 0
const query = withOperations(core.account.System, new LiveQuery(client))
query.query<Space>(core.class.Space, { private: false }, (result) => {
expect(result).toHaveLength(expectedLength - attempt)
if (attempt++ === expectedLength) done()
})
const spaces = await query.findAll(core.class.Space, {})
for (const space of spaces) {
await query.removeDoc(space._class, space.space, space._id)
}
})
})
class ClientImpl implements Client {
constructor (
private readonly hierarchy: Hierarchy,
private readonly model: ModelDb,
private readonly transactions: TxDb
) {}
async tx (tx: Tx): Promise<void> {
await Promise.all([this.model.tx(tx), this.transactions.tx(tx)])
}
getHierarchy(): Hierarchy {
return this.hierarchy
}
async findAll<T extends Doc>(_class: Ref<Class<T>>, query: DocumentQuery<T>, options?: FindOptions<T>): Promise<FindResult<T>> {
const domain = this.hierarchy.getClass(_class).domain
if (domain === DOMAIN_TX) return await this.transactions.findAll(_class, query, options)
return await this.model.findAll(_class, query, options)
}
}
async function getClient (): Promise<Client> {
const hierarchy = new Hierarchy()
const transactions = new TxDb(hierarchy)
const model = new ModelDb(hierarchy)
const txes = await getModel()
for (const tx of txes) hierarchy.tx(tx)
for (const tx of txes) await model.tx(tx)
return new ClientImpl(hierarchy, model, transactions)
}

202
packages/query/src/index.ts Normal file
View File

@ -0,0 +1,202 @@
//
// Copyright © 2020, 2021 Anticrm Platform Contributors.
//
// 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 {
Ref, Class, Doc, Tx, DocumentQuery, TxCreateDoc, TxRemoveDoc, Client,
FindOptions, TxUpdateDoc, _getOperator, TxProcessor, resultSort, SortingQuery,
FindResult, Hierarchy, Refs, WithLookup, LookupData
} from '@anticrm/core'
interface Query {
_class: Ref<Class<Doc>>
query: DocumentQuery<Doc>
result: Doc[] | Promise<Doc[]>
options?: FindOptions<Doc>
callback: (result: FindResult<Doc>) => void
}
export class LiveQuery extends TxProcessor implements Client {
private readonly client: Client
private readonly queries: Query[] = []
constructor (client: Client) {
super()
this.client = client
}
getHierarchy (): Hierarchy {
return this.client.getHierarchy()
}
private match (q: Query, doc: Doc): boolean {
if (!this.getHierarchy().isDerived(doc._class, q._class)) {
return false
}
for (const key in q.query) {
const value = (q.query as any)[key]
if ((doc as any)[key] !== value) {
return false
}
}
return true
}
async findAll<T extends Doc>(_class: Ref<Class<T>>, query: DocumentQuery<T>, options?: FindOptions<T>): Promise<FindResult<T>> {
return await this.client.findAll(_class, query, options)
}
query<T extends Doc>(_class: Ref<Class<T>>, query: DocumentQuery<T>, callback: (result: T[]) => void, options?: FindOptions<T>): () => void {
const result = this.client.findAll(_class, query, options)
const q: Query = {
_class,
query,
result,
options,
callback: callback as (result: Doc[]) => void
}
this.queries.push(q)
result
.then((result) => {
q.callback(result)
})
.catch((err) => {
console.log('failed to update Live Query: ', err)
})
return () => {
this.queries.splice(this.queries.indexOf(q), 1)
}
}
async txUpdateDoc (tx: TxUpdateDoc<Doc>): Promise<void> {
for (const q of this.queries) {
if (q.result instanceof Promise) {
q.result = await q.result
}
const updatedDoc = q.result.find(p => p._id === tx.objectId)
if (updatedDoc !== undefined) {
await this.__updateDoc(updatedDoc, tx)
this.sort(q, tx)
await this.callback(updatedDoc, q)
}
}
}
private async lookup (doc: Doc, lookup: Refs<Doc>): Promise<void> {
const result: LookupData<Doc> = {}
for (const key in lookup) {
const _class = (lookup as any)[key] as Ref<Class<Doc>>
const _id = (doc as any)[key] as Ref<Doc>
(result as any)[key] = (await this.client.findAll(_class, { _id }))[0]
}
(doc as WithLookup<Doc>).$lookup = result
}
async txCreateDoc (tx: TxCreateDoc<Doc>): Promise<void> {
for (const q of this.queries) {
const doc = TxProcessor.createDoc2Doc(tx)
if (this.match(q, doc)) {
if (q.result instanceof Promise) {
q.result = await q.result
}
if (q.options?.lookup !== undefined) await this.lookup(doc, q.options.lookup)
q.result.push(doc)
if (q.options?.sort !== undefined) resultSort(q.result, q.options?.sort)
if (q.options?.limit !== undefined && q.result.length > q.options.limit) {
if (q.result.pop()?._id !== doc._id) {
q.callback(q.result)
}
} else {
q.callback(q.result)
}
}
}
}
async txRemoveDoc (tx: TxRemoveDoc<Doc>): Promise<void> {
for (const q of this.queries) {
if (q.result instanceof Promise) {
q.result = await q.result
}
const index = q.result.findIndex(p => p._id === tx.objectId)
if (index > -1) {
q.result.splice(index, 1)
q.callback(q.result)
}
}
}
async tx (tx: Tx): Promise<void> {
await this.client.tx(tx)
await super.tx(tx)
}
async __updateDoc (updatedDoc: Doc, tx: TxUpdateDoc<Doc>): Promise<void> {
const ops = tx.operations as any
for (const key in ops) {
if (key.startsWith('$')) {
const operator = _getOperator(key)
operator(updatedDoc, ops[key])
} else {
(updatedDoc as any)[key] = ops[key]
}
}
updatedDoc.modifiedBy = tx.modifiedBy
updatedDoc.modifiedOn = tx.modifiedOn
}
private sort (q: Query, tx: TxUpdateDoc<Doc>): void {
const sort = q.options?.sort
if (sort === undefined) return
let needSort = sort.modifiedBy !== undefined || sort.modifiedOn !== undefined
if (!needSort) needSort = this.checkNeedSort(sort, tx)
if (needSort) resultSort(q.result as Doc[], sort)
}
private checkNeedSort (sort: SortingQuery<Doc>, tx: TxUpdateDoc<Doc>): boolean {
const ops = tx.operations as any
for (const key in ops) {
if (key.startsWith('$')) {
for (const opKey in ops[key]) {
if (opKey in sort) return true
}
} else {
if (key in sort) return true
}
}
return false
}
async callback (updatedDoc: Doc, q: Query): Promise<void> {
q.result = q.result as Doc[]
if (q.options?.limit !== undefined && q.result.length > q.options.limit) {
if (q.result[q.options?.limit]._id === updatedDoc._id) {
const res = await this.findAll(q._class, q.query, q.options)
q.result = res
q.callback(res)
return
}
if (q.result.pop()?._id !== updatedDoc._id) q.callback(q.result)
} else {
q.callback(q.result)
}
}
}

View File

@ -0,0 +1,8 @@
{
"extends": "./node_modules/@anticrm/platform-rig/profiles/default/tsconfig.json",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./lib"
}
}

View File

@ -0,0 +1,6 @@
module.exports = {
extends: ['./node_modules/@anticrm/platform-rig/profiles/default/config/eslint.config.json'],
parserOptions: {
project: './tsconfig.json'
}
}

View File

@ -0,0 +1,4 @@
*
!/lib/**
!CHANGELOG.md
/lib/**/__tests__/

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"
}

View File

@ -0,0 +1,24 @@
{
"name": "@anticrm/client",
"version": "0.6.0",
"main": "lib/index.js",
"author": "Anticrm Platform Contributors",
"license": "EPL-2.0",
"scripts": {
"build": "heft build",
"lint:fix": "eslint --fix src"
},
"devDependencies": {
"@anticrm/platform-rig":"~0.6.0",
"@types/heft-jest":"^1.0.2",
"@typescript-eslint/eslint-plugin":"4",
"eslint-plugin-import":"2",
"eslint-plugin-promise":"4",
"eslint-plugin-node":"11",
"eslint":"^7.32.0"
},
"dependencies": {
"@anticrm/platform":"~0.6.3",
"@anticrm/core":"~0.6.0"
}
}

View File

@ -0,0 +1,37 @@
//
// Copyright © 2020 Anticrm Platform Contributors.
//
// 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 { plugin } from '@anticrm/platform'
import type { Metadata, Plugin, Resource } from '@anticrm/platform'
import type { Client } from '@anticrm/core'
// import type { LiveQuery } from '@anticrm/query'
// export type Connection = Client & LiveQuery & TxOperations
/**
* @public
*/
export const clientId = 'client' as Plugin
export default plugin(clientId,
{
function: {
GetClient: '' as Resource<() => Promise<Client>>
},
metadata: {
ClientUrl: '' as Metadata<string>
}
}
)

View File

@ -0,0 +1,9 @@
{
"extends": "./node_modules/@anticrm/platform-rig/profiles/default/tsconfig.json",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./lib",
"lib": ["esnext", "dom"]
}
}

View File

@ -0,0 +1,6 @@
module.exports = {
extends: ['./node_modules/@anticrm/platform-rig/profiles/default/config/eslint.config.json'],
parserOptions: {
project: './tsconfig.json'
}
}

4
plugins/view/.npmignore Normal file
View File

@ -0,0 +1,4 @@
*
!/lib/**
!CHANGELOG.md
/lib/**/__tests__/

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"
}

25
plugins/view/package.json Normal file
View File

@ -0,0 +1,25 @@
{
"name": "@anticrm/view",
"version": "0.6.0",
"main": "lib/index.js",
"author": "Anticrm Platform Contributors",
"license": "EPL-2.0",
"scripts": {
"build": "heft build",
"lint:fix": "eslint --fix src"
},
"devDependencies": {
"@anticrm/platform-rig":"~0.6.0",
"@types/heft-jest":"^1.0.2",
"@typescript-eslint/eslint-plugin":"4",
"eslint-plugin-import":"2",
"eslint-plugin-promise":"4",
"eslint-plugin-node":"11",
"eslint":"^7.32.0"
},
"dependencies": {
"@anticrm/platform":"~0.6.3",
"@anticrm/core":"~0.6.0",
"@anticrm/ui":"~0.6.0"
}
}

60
plugins/view/src/index.ts Normal file
View File

@ -0,0 +1,60 @@
//
// Copyright © 2020, 2021 Anticrm Platform Contributors.
// Copyright © 2021 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 type { Plugin, Asset } from '@anticrm/platform'
import { plugin } from '@anticrm/platform'
import type { Ref, Mixin, UXObject, Space, FindOptions, Class, Doc } from '@anticrm/core'
import type { AnyComponent } from '@anticrm/ui'
export interface AttributeEditor extends Class<Doc> {
editor: AnyComponent
}
export interface AttributePresenter extends Class<Doc> {
presenter: AnyComponent
}
export interface ViewletDescriptor extends Doc, UXObject {
component: AnyComponent
}
export interface Viewlet extends Doc {
attachTo: Ref<Class<Space>>
descriptor: Ref<ViewletDescriptor>
open: AnyComponent
options?: FindOptions<Doc>
config: any
}
export const viewId = 'view' as Plugin
export default plugin(viewId, {
mixin: {
AttributeEditor: '' as Ref<Mixin<AttributeEditor>>,
AttributePresenter: '' as Ref<Mixin<AttributePresenter>>
},
class: {
ViewletDescriptor: '' as Ref<Class<ViewletDescriptor>>,
Viewlet: '' as Ref<Class<Viewlet>>
},
viewlet: {
Table: '' as Ref<ViewletDescriptor>
},
icon: {
Table: '' as Asset
}
})

View File

@ -0,0 +1,9 @@
{
"extends": "./node_modules/@anticrm/platform-rig/profiles/default/tsconfig.json",
"compilerOptions": {
"rootDir": "./src",
"outDir": "./lib",
"lib": ["esnext", "dom"]
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 957 B

View File

@ -22,8 +22,10 @@
"svelte": "^3.37.0",
"@anticrm/platform": "~0.6.0",
"@anticrm/core": "~0.6.0",
"@anticrm/client": "~0.6.0",
"@anticrm/workbench": "~0.6.0",
"@anticrm/ui": "~0.6.0",
"@anticrm/view": "~0.6.0",
"@anticrm/presentation": "~0.6.0"
}
}

View File

@ -16,12 +16,12 @@
<script lang="ts">
import { getResource } from '@anticrm/platform'
import type { Connection } from '@anticrm/client'
import type { Client } from '@anticrm/core'
import client from '@anticrm/client'
import Workbench from './Workbench.svelte'
async function connect(): Promise<Connection> {
async function connect(): Promise<Client> {
const getClient = await getResource(client.function.GetClient)
return getClient()
}

View File

@ -16,9 +16,9 @@
import type { Ref, Obj, Class, WithLookup } from '@anticrm/core'
import type { Asset, IntlString } from '@anticrm/platform'
import type { Connection } from '@anticrm/client'
import type { Client } from '@anticrm/core'
export function classIcon(client: Connection, _class: Ref<Class<Obj>>): Asset | undefined {
export function classIcon(client: Client, _class: Ref<Class<Obj>>): Asset | undefined {
return client.getHierarchy().getClass(_class).icon
}

View File

@ -531,5 +531,20 @@
"projectFolder": "packages/presentation",
"shouldPublish": true
},
{
"packageName": "@anticrm/client",
"projectFolder": "plugins/client",
"shouldPublish": true
},
{
"packageName": "@anticrm/query",
"projectFolder": "packages/query",
"shouldPublish": true
},
{
"packageName": "@anticrm/view",
"projectFolder": "plugins/view",
"shouldPublish": true
},
]
}