mirror of
https://github.com/hcengineering/platform.git
synced 2024-12-23 03:22:19 +03:00
add core
docs
Signed-off-by: Andrey Platov <andrey@hardcoreeng.com>
This commit is contained in:
parent
748099568c
commit
df20992b09
19
cloud/dev-server/app/index.js
Normal file
19
cloud/dev-server/app/index.js
Normal file
@ -0,0 +1,19 @@
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
const start = require('@anticrm/dev-server')
|
||||
|
||||
start (3333)
|
126
cloud/dev-server/app/package-lock.json
generated
Normal file
126
cloud/dev-server/app/package-lock.json
generated
Normal file
@ -0,0 +1,126 @@
|
||||
{
|
||||
"name": "@anticrm/dev-server-app",
|
||||
"version": "0.6.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@anticrm/core": {
|
||||
"version": "0.6.4",
|
||||
"resolved": "https://registry.npmjs.org/@anticrm/core/-/core-0.6.4.tgz",
|
||||
"integrity": "sha512-R4sy4iOJn+7mTLOmeS03KTLmDlPFLvT4gLAIo7VWSStpslVex+YoyRXulnhTIbBZikQFW88nAvAm5e4fhoiVgA==",
|
||||
"requires": {
|
||||
"@anticrm/platform": "~0.6.1",
|
||||
"simplytyped": "^3.3.0"
|
||||
}
|
||||
},
|
||||
"@anticrm/dev-server": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@anticrm/dev-server/-/dev-server-0.6.1.tgz",
|
||||
"integrity": "sha512-Zh04YOsHprDMjCybAzizImZtRntEmuyS7ko8gdTZKgmHq3Bypf4jRIai0WF8sjULVrcOKRAGEAVqdPBhwkwz2Q==",
|
||||
"requires": {
|
||||
"@anticrm/core": "~0.6.1",
|
||||
"@anticrm/dev-storage": "~0.6.1",
|
||||
"@anticrm/platform": "~0.6.1",
|
||||
"@anticrm/server-ws": "~0.6.1"
|
||||
}
|
||||
},
|
||||
"@anticrm/dev-storage": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@anticrm/dev-storage/-/dev-storage-0.6.1.tgz",
|
||||
"integrity": "sha512-MSmHqp6O50FMYtisuDZdVFds6wslHYhypMZ4QN+DqRaDYWa+rkEIETW3FKs3YLaMvrPCHphcHI8ZCsHL3eX3ew==",
|
||||
"requires": {
|
||||
"@anticrm/core": "~0.6.1",
|
||||
"@anticrm/platform": "~0.6.1"
|
||||
}
|
||||
},
|
||||
"@anticrm/platform": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@anticrm/platform/-/platform-0.6.1.tgz",
|
||||
"integrity": "sha512-Ay/deCr9NH5SgztB9CuNOMX2pJSy8GR9JAQbGZXTl9KpzGJhlXyRnCKvPyEeY0mHiVk72jLymRo3+Uis8grNoA==",
|
||||
"requires": {
|
||||
"intl-messageformat": "^9.7.1"
|
||||
}
|
||||
},
|
||||
"@anticrm/server-ws": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@anticrm/server-ws/-/server-ws-0.6.1.tgz",
|
||||
"integrity": "sha512-hQpDfPeLpia3f2SlITtI+iJ1vXW5JL/U6eKjkufCjQtLzUKtz08FO9MnoFxb3xSPLiHpy/C/d6oPMOMNMgg/Mg==",
|
||||
"requires": {
|
||||
"@anticrm/platform": "~0.6.1",
|
||||
"jwt-simple": "^0.5.6",
|
||||
"ws": "^8.0.0"
|
||||
}
|
||||
},
|
||||
"@formatjs/ecma402-abstract": {
|
||||
"version": "1.9.5",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-1.9.5.tgz",
|
||||
"integrity": "sha512-cGpEBzrf9bL2lTMEuRZ3gjLrEUEucxAXDIdX4tNqNdNZO81ZN558BfjiFfyPgrhILEuJU/+sgLwWxddSn6usHw==",
|
||||
"requires": {
|
||||
"@formatjs/intl-localematcher": "0.2.18",
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"@formatjs/fast-memoize": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-1.1.1.tgz",
|
||||
"integrity": "sha512-mIqBr5uigIlx13eZTOPSEh2buDiy3BCdMYUtewICREQjbb4xarDiVWoXSnrERM7NanZ+0TAHNXSqDe6HpEFQUg=="
|
||||
},
|
||||
"@formatjs/icu-messageformat-parser": {
|
||||
"version": "2.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.0.8.tgz",
|
||||
"integrity": "sha512-fZlQ7ls3eQswO4RFB0lSi+ritPvud0Z2EQB6SU8qI5+MIS4qU4AHjq/dFJNvhdEdmJqLWHe31K4yHaRdavkSQQ==",
|
||||
"requires": {
|
||||
"@formatjs/ecma402-abstract": "1.9.5",
|
||||
"@formatjs/icu-skeleton-parser": "1.2.9",
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"@formatjs/icu-skeleton-parser": {
|
||||
"version": "1.2.9",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.2.9.tgz",
|
||||
"integrity": "sha512-cx8Ug1gxRtv0rRddWd6dt5Sn/BhnhktSHvokbmLUVOEp2dy/6Ehvv2e00wow28AaSIzvBvM6ew1Qwe9wzDzcOw==",
|
||||
"requires": {
|
||||
"@formatjs/ecma402-abstract": "1.9.5",
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"@formatjs/intl-localematcher": {
|
||||
"version": "0.2.18",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.2.18.tgz",
|
||||
"integrity": "sha512-xI9X+mi7wbucbh35GNTY+C0+oMJXAp8ueC73SOyJlBpRNjLuOlSwgw3yJaCZxy3WpjcRBCP0laJ5zlpITO0QpA==",
|
||||
"requires": {
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"intl-messageformat": {
|
||||
"version": "9.8.1",
|
||||
"resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-9.8.1.tgz",
|
||||
"integrity": "sha512-2rSZQu8GmLOlxNiehRvxWjkIqzemW833zm8ZS63JNvSpSuGnpqSWRqqwqv1kEBto/97/UBjtWy14m/CIdwVqFg==",
|
||||
"requires": {
|
||||
"@formatjs/fast-memoize": "1.1.1",
|
||||
"@formatjs/icu-messageformat-parser": "2.0.8",
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"jwt-simple": {
|
||||
"version": "0.5.6",
|
||||
"resolved": "https://registry.npmjs.org/jwt-simple/-/jwt-simple-0.5.6.tgz",
|
||||
"integrity": "sha512-40aUybvhH9t2h71ncA1/1SbtTNCVZHgsTsTgqPUxGWDmUDrXyDf2wMNQKEbdBjbf4AI+fQhbECNTV6lWxQKUzg=="
|
||||
},
|
||||
"simplytyped": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/simplytyped/-/simplytyped-3.3.0.tgz",
|
||||
"integrity": "sha512-mz4RaNdKTZiaKXgi6P1k/cdsxV3gz+y1Wh2NXHWD40dExktLh4Xx/h6MFakmQWODZHj/2rKe59acacpL74ZhQA=="
|
||||
},
|
||||
"tslib": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
|
||||
"integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
|
||||
},
|
||||
"ws": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.0.0.tgz",
|
||||
"integrity": "sha512-6AcSIXpBlS0QvCVKk+3cWnWElLsA6SzC0lkQ43ciEglgXJXiCWK3/CGFEJ+Ybgp006CMibamAsqOlxE9s4AvYA=="
|
||||
}
|
||||
}
|
||||
}
|
12
cloud/dev-server/app/package.json
Normal file
12
cloud/dev-server/app/package.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "@anticrm/dev-server-app",
|
||||
"version": "0.6.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "node ./index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@anticrm/dev-server": "^0.6.1"
|
||||
}
|
||||
}
|
@ -14,4 +14,4 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
export { start } from './server'
|
||||
export { start as default } from './server'
|
||||
|
@ -23,8 +23,14 @@ import { TxProcessor } from './tx'
|
||||
|
||||
import core from './component'
|
||||
|
||||
type TxHander = (tx: Tx) => void
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export type TxHander = (tx: Tx) => void
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface Client extends Storage {
|
||||
getHierarchy: () => Hierarchy
|
||||
}
|
||||
@ -53,6 +59,9 @@ class ClientImpl extends TxProcessor implements Storage, Client {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export async function createClient (
|
||||
connect: (txHandler: TxHander) => Promise<Storage>,
|
||||
notify?: (tx: Tx) => void
|
||||
|
@ -17,6 +17,9 @@ import { plugin } from '@anticrm/platform'
|
||||
import type { Account, Class, Doc, Obj, Ref, Space, AnyAttribute, Tx, TxCreateDoc, TxMixin } from './classes'
|
||||
import type { TxRemoveDoc, TxUpdateDoc } from './tx'
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const coreId = 'core' as Plugin
|
||||
|
||||
export default plugin(coreId, {
|
||||
|
@ -17,13 +17,16 @@ import { PlatformError, Severity, Status } from '@anticrm/platform'
|
||||
import type { Class, Doc, Ref, Tx, TxCreateDoc, TxMixin } from './classes'
|
||||
import core from './component'
|
||||
import type { Hierarchy } from './hierarchy'
|
||||
import { getOperator } from './operator'
|
||||
import { _getOperator } from './operator'
|
||||
import { findProperty, resultSort } from './query'
|
||||
import type { DocumentQuery, FindOptions, FindResult, Storage, WithLookup, LookupData, Refs } from './storage'
|
||||
import type { TxRemoveDoc, TxUpdateDoc } from './tx'
|
||||
import { TxProcessor } from './tx'
|
||||
|
||||
class MemDb extends TxProcessor {
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export class MemDb extends TxProcessor {
|
||||
protected readonly hierarchy: Hierarchy
|
||||
private readonly objectsByClass = new Map<Ref<Class<Doc>>, Doc[]>()
|
||||
private readonly objectById = new Map<Ref<Doc>, Doc>()
|
||||
@ -138,7 +141,7 @@ class MemDb extends TxProcessor {
|
||||
|
||||
/**
|
||||
* Hold transactions
|
||||
*
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export class TxDb extends MemDb implements Storage {
|
||||
@ -149,7 +152,7 @@ export class TxDb extends MemDb implements Storage {
|
||||
|
||||
/**
|
||||
* Hold model objects and classes
|
||||
*
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export class ModelDb extends MemDb implements Storage {
|
||||
@ -162,7 +165,7 @@ export class ModelDb extends MemDb implements Storage {
|
||||
const ops = tx.operations as any
|
||||
for (const key in ops) {
|
||||
if (key.startsWith('$')) {
|
||||
const operator = getOperator(key)
|
||||
const operator = _getOperator(key)
|
||||
operator(doc, ops[key])
|
||||
} else {
|
||||
doc[key] = ops[key]
|
||||
|
@ -16,7 +16,10 @@
|
||||
|
||||
import type { Doc, PropertyType } from './classes'
|
||||
|
||||
type OperatorFunc = (doc: Doc, op: object) => void
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export type _OperatorFunc = (doc: Doc, op: object) => void
|
||||
|
||||
function $push (document: Doc, keyval: Record<string, PropertyType>): void {
|
||||
const doc = document as any
|
||||
@ -30,11 +33,16 @@ function $push (document: Doc, keyval: Record<string, PropertyType>): void {
|
||||
}
|
||||
}
|
||||
|
||||
const operators: Record<string, OperatorFunc> = {
|
||||
const operators: Record<string, _OperatorFunc> = {
|
||||
$push
|
||||
}
|
||||
|
||||
export function getOperator (name: string): OperatorFunc {
|
||||
/**
|
||||
* @internal
|
||||
* @param name -
|
||||
* @returns
|
||||
*/
|
||||
export function _getOperator (name: string): _OperatorFunc {
|
||||
const operator = operators[name]
|
||||
if (operator === undefined) throw new Error('unknown operator: ' + name)
|
||||
return operator
|
||||
|
@ -2,14 +2,23 @@ import { Doc } from './classes'
|
||||
import { createPredicates, isPredicate } from './predicate'
|
||||
import { SortingQuery } from './storage'
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const likeSymbol = '%'
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export function checkLikeQuery (value: string, query: string): boolean {
|
||||
const searchString = query.split(likeSymbol).join('.*')
|
||||
const regex = RegExp(`^${searchString}$`)
|
||||
return regex.test(value)
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export function findProperty (objects: Doc[], propertyKey: string, value: any): Doc[] {
|
||||
if (isPredicate(value)) {
|
||||
const preds = createPredicates(value, propertyKey)
|
||||
@ -27,6 +36,9 @@ export function findProperty (objects: Doc[], propertyKey: string, value: any):
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export function resultSort<T extends Doc> (result: T[], sortOptions: SortingQuery<T>): void {
|
||||
const sortFunc = (a: any, b: any): number => {
|
||||
for (const key in sortOptions) {
|
||||
|
@ -16,20 +16,35 @@
|
||||
import type { KeysByType } from 'simplytyped'
|
||||
import type { Class, Doc, Ref, Tx } from './classes'
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
||||
export type QuerySelector<T> = {
|
||||
$in?: T[]
|
||||
$like?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export type ObjQueryType<T> = T | QuerySelector<T>
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export type DocumentQuery<T extends Doc> = {
|
||||
[P in keyof T]?: ObjQueryType<T[P]>
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export type Refs<T extends Doc> = Partial<Pick<T, KeysByType<T, Ref<Doc>>>>
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
|
||||
export type FindOptions<T extends Doc> = {
|
||||
limit?: number
|
||||
@ -37,29 +52,53 @@ export type FindOptions<T extends Doc> = {
|
||||
lookup?: Refs<T>
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export type SortingQuery<T extends Doc> = {
|
||||
[P in keyof T]?: T[P] extends object ? never : SortingOrder
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export enum SortingOrder {
|
||||
Ascending = 1,
|
||||
Descending = -1
|
||||
}
|
||||
|
||||
type RefsAsDocs<T extends Doc> = {
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export type RefsAsDocs<T extends Doc> = {
|
||||
[P in keyof T]: T[P] extends Ref<infer X> ? X : never
|
||||
}
|
||||
|
||||
type RemoveNever<T extends object> = Omit<T, KeysByType<T, never>>
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export type RemoveNever<T extends object> = Omit<T, KeysByType<T, never>>
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export type LookupData<T extends Doc> = Partial<RemoveNever<RefsAsDocs<T>>>
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export type WithLookup<T extends Doc> = T & {
|
||||
$lookup?: LookupData<T>
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export type FindResult<T extends Doc> = WithLookup<T>[]
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface Storage {
|
||||
findAll: <T extends Doc>(
|
||||
_class: Ref<Class<T>>,
|
||||
|
@ -18,31 +18,58 @@ import type { Class, Data, Doc, Domain, Ref, Account, Space, Arr, Mixin, Tx, TxC
|
||||
import core from './component'
|
||||
import { generateId } from './utils'
|
||||
|
||||
type ArrayAsElement<T extends Doc> = {
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export type ArrayAsElement<T extends Doc> = {
|
||||
[P in keyof T]: T[P] extends Arr<infer X> ? X : never
|
||||
}
|
||||
|
||||
type OmitNever<T extends object> = Omit<T, KeysByType<T, never>>
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export type OmitNever<T extends object> = Omit<T, KeysByType<T, never>>
|
||||
|
||||
interface PushOptions<T extends Doc> {
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface PushOptions<T extends Doc> {
|
||||
$push?: Partial<OmitNever<ArrayAsElement<T>>>
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export type DocumentUpdate<T extends Doc> = Partial<Data<T>> & PushOptions<T>
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface TxUpdateDoc<T extends Doc> extends Tx<T> {
|
||||
operations: DocumentUpdate<T>
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface TxRemoveDoc<T extends Doc> extends Tx<T> {
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const DOMAIN_TX = 'tx' as Domain
|
||||
|
||||
interface WithTx {
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface WithTx {
|
||||
tx: (tx: Tx) => Promise<void>
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export class TxProcessor implements WithTx {
|
||||
async tx (tx: Tx): Promise<void> {
|
||||
switch (tx._class) {
|
||||
@ -75,6 +102,9 @@ export class TxProcessor implements WithTx {
|
||||
protected async txMixin (tx: TxMixin<Doc, Doc>): Promise<void> {}
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface TxOperations {
|
||||
createDoc: <T extends Doc>(_class: Ref<Class<T>>, space: Ref<Space>, attributes: Data<T>) => Promise<T>
|
||||
updateDoc: <T extends Doc>(
|
||||
@ -86,6 +116,9 @@ export interface TxOperations {
|
||||
removeDoc: <T extends Doc>(_class: Ref<Class<T>>, space: Ref<Space>, objectId: Ref<T>) => Promise<void>
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export function withOperations<T extends WithTx> (user: Ref<Account>, storage: T): T & TxOperations {
|
||||
const result = storage as T & TxOperations
|
||||
|
||||
@ -150,6 +183,9 @@ export function withOperations<T extends WithTx> (user: Ref<Account>, storage: T
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export class DefaultTxFactory implements TxFactory {
|
||||
constructor (readonly account: Ref<Account>) {}
|
||||
|
||||
|
@ -36,6 +36,10 @@ function count (): string {
|
||||
return toHex(val, 6)
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @returns
|
||||
*/
|
||||
export function generateId<T extends Doc> (): Ref<T> {
|
||||
return (timestamp() + random + count()) as Ref<T>
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user