From bd4b3461357dc387f05cecf33fbf94cf2d709c65 Mon Sep 17 00:00:00 2001 From: Xc Date: Thu, 17 Mar 2022 19:41:01 +0800 Subject: [PATCH] =?UTF-8?q?base=E7=9A=84=E6=95=B4=E4=BD=93=E6=9E=B6?= =?UTF-8?q?=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/FrontContext.ts | 110 ++++++++++++++++++++++++++++++++++++ src/aspect.ts | 42 -------------- src/aspects/index.ts | 6 +- src/aspects/token.ts | 4 +- src/dataStore/CacheStore.ts | 9 +-- src/features/data | 0 src/features/data.ts | 14 +++++ src/features/token.ts | 18 +++--- src/index.ts | 85 ++++++++++++++++++++++++---- src/types/AspectProxy.ts | 7 ++- src/types/Feature.ts | 12 ++-- src/types/FrontContext.ts | 6 -- 12 files changed, 231 insertions(+), 82 deletions(-) create mode 100644 src/FrontContext.ts delete mode 100644 src/aspect.ts delete mode 100644 src/features/data create mode 100644 src/features/data.ts delete mode 100644 src/types/FrontContext.ts diff --git a/src/FrontContext.ts b/src/FrontContext.ts new file mode 100644 index 00000000..de5b7ffa --- /dev/null +++ b/src/FrontContext.ts @@ -0,0 +1,110 @@ +import { EntityDict } from 'oak-domain/lib/types/entity'; +import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-domain/EntityDict'; +import { Aspect } from 'oak-domain/lib/types/Aspect'; +import { Context as BaseContext } from 'oak-memory-tree-store'; +import { TriggerExecutor } from "oak-trigger-executor"; +import { AspectProxy } from './types/AspectProxy'; +import { CacheStore } from './dataStore/CacheStore'; +import BaseAspectProxy from './aspects/index'; +import { assign } from 'lodash'; +import { StorageSchema } from 'oak-domain/lib/types/Storage'; +import { Trigger } from 'oak-domain/lib/types/Trigger'; +import { RunningContext } from "oak-domain/lib/types/Context"; +import { DebugStore, Context } from 'oak-debug-store'; +import { Schema as Token } from 'oak-domain/lib/base-domain/Token/Schema'; +import { Schema as Application } from "oak-domain/lib/base-domain/Application/Schema"; + + +class DebugRunningContext extends Context implements RunningContext { + getApplication: () => Application; + getToken: () => Token | undefined; + + constructor(store: DebugStore, ga: () => Application, gt: () => Token | undefined) { + super(store); + this.getApplication = ga; + this.getToken = gt; + } +}; + +export async function createAspectProxy>>( + storageSchema: StorageSchema, + triggers: Array>, + applicationId: string, + getTokenValue: () => string | undefined, + aspectDict?: AD, + initialData?: { + [T in keyof ED]?: Array; + }): Promise> { + if (process.env.NODE_ENV === 'production') { + // todo 发请求到后台获取数据 + throw new Error('method not implemented'); + } + else { + // todo initialData + const executor = new TriggerExecutor(); + const debugStore = new DebugStore(executor, storageSchema); + triggers.forEach( + (trigger) => debugStore.registerTrigger(trigger) + ); + const context = new Context(debugStore); + + const { result: [application] } = await (>debugStore).select('application', { + data: { + id: 1, + systemId: 1, + system: { + id: 1, + }, + }, + filter: { + id: applicationId, + } + }, >context); + const getApplication = () => application as Application; + const FullAspectProxy = assign(BaseAspectProxy, aspectDict); + + return async (name, params) => { + const aspect = FullAspectProxy[name]; + const context2 = new Context(debugStore); + + const tokenValue = getTokenValue(); + let token: Token | undefined; + if (tokenValue) { + const { result } = await (>debugStore).select('token', { + data: { + id: 1, + userId: 1, + playerId: 1, + }, + filter: { + id: tokenValue, + } + }, >context2); + token = result[0] as Token; + // todo 判断 token的合法性 + } + const getToken = () => token; + const runningContext = new DebugRunningContext(debugStore, getApplication, getToken); + return aspect(params, runningContext); + } + } +} + +export class FrontContext>> extends BaseContext { + getAspectProxy: () => Promise>; + + constructor( + storageSchema: StorageSchema, + triggers: Array>, + applicationId: string, + getTokenValue: () => string | undefined, + aspectDict?: AD, + initialData?: { + [T in keyof ED]?: Array; + }) { + super(new CacheStore(storageSchema)); + + const ap = createAspectProxy(storageSchema, triggers, applicationId, getTokenValue, aspectDict, initialData); + this.getAspectProxy = () => ap; + } +}; \ No newline at end of file diff --git a/src/aspect.ts b/src/aspect.ts deleted file mode 100644 index f9453e5f..00000000 --- a/src/aspect.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { DebugStore, Context } from "oak-debug-store"; -import { Aspect } from "oak-domain/lib/types/Aspect"; -import { RunningContext } from "oak-domain/lib/types/Context"; -import { EntityDef } from "oak-domain/lib/types/Entity"; - -import { loginMp } from './aspects/token'; - -export function makeAspectDict(aspects: Array>, store: DebugStore) { - if (process.env.NODE_ENV === 'production') { - // 生产环境调服务器端函数 - } - else { - const runningContext: RunningContext = { - application: { - name: "", - description: "", - type: "web", - system: { - name: "", - description: "", - config: undefined - }, - dd: [] - }, - rowStore: store, - on: function (event: "commit" | "rollback", callback: (context: Context) => Promise): void { - throw new Error("Function not implemented."); - }, - begin: function (options?: object): Promise { - throw new Error("Function not implemented."); - }, - commit: function (): Promise { - throw new Error("Function not implemented."); - }, - rollback: function (): Promise { - throw new Error("Function not implemented."); - } - } - } -} \ No newline at end of file diff --git a/src/aspects/index.ts b/src/aspects/index.ts index bfe1110c..047d666e 100644 --- a/src/aspects/index.ts +++ b/src/aspects/index.ts @@ -1,6 +1,8 @@ import { loginMp, loginByPassword } from './token'; -export const AspectDict = { +const AspectDict = { loginMp, loginByPassword, -}; \ No newline at end of file +}; + +export default AspectDict; \ No newline at end of file diff --git a/src/aspects/token.ts b/src/aspects/token.ts index 31268940..f963c34a 100644 --- a/src/aspects/token.ts +++ b/src/aspects/token.ts @@ -1,6 +1,8 @@ import { RunningContext } from 'oak-domain/lib/types/Context'; import { Schema as Token } from 'oak-domain/lib/entities/Token'; -import { EntityDict } from 'oak-domain/lib/base-domain/EntityDict'; +import { EntityDict as BaseEntityDict} from 'oak-domain/lib/base-domain/EntityDict'; +import { EntityDict } from 'oak-domain/lib/types/Entity'; +import { Aspect } from 'oak-domain/lib/types/Aspect'; export async function loginMp (params: { code: string }, context: RunningContext): Promise { const { rowStore } = context; diff --git a/src/dataStore/CacheStore.ts b/src/dataStore/CacheStore.ts index df3ab9e8..ee595257 100644 --- a/src/dataStore/CacheStore.ts +++ b/src/dataStore/CacheStore.ts @@ -1,6 +1,7 @@ -import { EntityDict } from "oak-domain/lib/base-domain/EntityDict"; +import { EntityDict as BaseEntityDict } from "oak-domain/lib/base-domain/EntityDict"; +import { EntityDict } from 'oak-domain/lib/types/Entity'; import { StorageSchema } from "oak-domain/lib/types/Storage"; -import { TreeStore, Context as BaseContext } from 'oak-memory-tree-store'; +import { TreeStore } from 'oak-memory-tree-store'; export class CacheStore extends TreeStore { constructor(storageSchema: StorageSchema) { @@ -9,7 +10,3 @@ export class CacheStore extends TreeStore { // todo } - -export class Context extends BaseContext { - -}; \ No newline at end of file diff --git a/src/features/data b/src/features/data deleted file mode 100644 index e69de29b..00000000 diff --git a/src/features/data.ts b/src/features/data.ts new file mode 100644 index 00000000..e94dc277 --- /dev/null +++ b/src/features/data.ts @@ -0,0 +1,14 @@ +import { EntityDict } from 'oak-domain/lib/types/Entity'; +import { Aspect } from 'oak-domain/lib/types/Aspect'; +import { Feature } from '../types/Feature'; +import { FrontContext } from '../FrontContext'; + +export class Data>> extends Feature { + async get(context: FrontContext, params: { entity: T, selection: ED[T]['Selection'] }) { + const { result } = await context.rowStore.select(params.entity, params.selection, context); + return result; + } + async action(context: FrontContext, type: string, payload?: any) { + throw new Error('Method not implemented.'); + } +} diff --git a/src/features/token.ts b/src/features/token.ts index a883ae23..6a92a6e4 100644 --- a/src/features/token.ts +++ b/src/features/token.ts @@ -1,14 +1,18 @@ -import { EntityDict } from 'oak-domain/lib/base-domain/EntityDict'; +import { EntityDict } from 'oak-domain/lib/types/Entity'; +import { Aspect } from 'oak-domain/lib/types/Aspect'; import { Feature } from '../types/Feature'; -import { FrontContext } from '../types/FrontContext'; +import { FrontContext } from '../FrontContext'; -export class Token extends Feature { - get(params?: any) { +export class Token>> extends Feature { + tokenValue?: string; + async get(context: FrontContext) { throw new Error('Method not implemented.'); } - action(context: FrontContext, type: string, payload?: any) { + async action(context: FrontContext, type: string, payload?: any) { throw new Error('Method not implemented.'); } + + getTokenValue() { + return this.tokenValue; + } } - -console.log(Token.name); \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 6269b1a0..57393655 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,22 +1,87 @@ import { StorageSchema } from 'oak-domain/lib/types/Storage'; import { Trigger } from "oak-domain/lib/types/Trigger"; -import { EntityDict } from 'oak-domain/src/base-domain/EntityDict'; +import { EntityDict as BaseEntityDict } from 'oak-domain/src/base-domain/EntityDict'; import { Aspect } from 'oak-domain/lib/types/Aspect'; import { Feature } from './types/Feature'; -import { CacheStore } from './dataStore/CacheStore'; -import { loginMp } from './aspects/token'; import { Token } from './features/token'; -const FEATURES: Array() => Feature> = [Token]; +import { assign } from 'lodash'; +import { EntityDict } from 'oak-domain/lib/types/Entity'; +import { FrontContext } from './FrontContext'; -export function initialize(storageSchema: StorageSchema, - features?: Array>, - triggers?: Array>, - initialData?: Object, - aspects?: Array>) { - const store = new CacheStore(storageSchema); +function populateFeatures>, FD extends Record>>() => Feature>>(featureClazzDict: FD) +: { + [T in keyof FD]: InstanceType; +} { + const result = {}; + for (const k in featureClazzDict) { + assign(result, { + [k]: new featureClazzDict[k](), + }); + } + return result as any; } +export async function initialize>, + FD extends Record>>() => Feature>>( + storageSchema: StorageSchema, + applicationId: string, + featureClazzDict?: FD, + triggers?: Array>, + aspectDict?: AD, + initialData?: { + [T in keyof ED]? : Array; + }) { + + const token = new Token(); + // todo default triggers + const frontContext = new FrontContext(storageSchema, triggers!, applicationId, () => token.getTokenValue(), aspectDict, initialData); + + const featureDict = { + token: Token, + }; + function ppf() { + return populateFeatures(featureClazzDict!); + } + if (featureClazzDict) { + assign(featureDict, ppf()); + } + + const featureDict2 = featureDict as typeof featureDict & ReturnType; + + const subscribe = (features: F[], callback: () => void) => { + const unsubscribes = features.map( + (f) => { + const feature = featureDict2[f]; + return feature.subscribe(callback); + } + ); + return () => { + unsubscribes.forEach( + ele => ele() + ); + }; + }; + + const getFeature = (f: F, params?: Parameters['get']>[1]): ReturnType['get']> => { + // const context = new FrontContext(store, aspectProxy) as any; + const feature = featureDict2[f]; + return feature.get(frontContext as any, params) as any; // 这里有个类型的转换暂时写不出来,因为populateFeatures没法传递generic types在返回值里 + }; + + const actionFeature = (f: F, t: Parameters['action']>[1], p?: Parameters['action']>[2]): ReturnType['action']> => { + // const context = new FrontContext(store, aspectProxy) as any; + const feature = featureDict2[f]; + return feature.action(frontContext as any, t, p) as any; + }; + + return { + subscribe, + getFeature, + actionFeature, + }; +} diff --git a/src/types/AspectProxy.ts b/src/types/AspectProxy.ts index ce6a38fc..02b4a396 100644 --- a/src/types/AspectProxy.ts +++ b/src/types/AspectProxy.ts @@ -1,6 +1,7 @@ import { Aspect } from "oak-domain/lib/types/Aspect"; -import { EntityDef } from "oak-domain/lib/types/Entity"; +import { EntityDict } from "oak-domain/lib/types/Entity"; +import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-domain/EntityDict'; -export interface AspectProxy, AD extends Record>> { - (name: T, params: Parameters[0]): ReturnType; +export interface AspectProxy>> { + (name: T, params: Parameters[0]): Promise>; }; diff --git a/src/types/Feature.ts b/src/types/Feature.ts index 43ff8ca9..85dd813c 100644 --- a/src/types/Feature.ts +++ b/src/types/Feature.ts @@ -1,8 +1,10 @@ import { pull } from 'lodash'; -import { EntityDef } from 'oak-domain/lib/types/entity'; -import { FrontContext } from './FrontContext'; +import { Aspect } from 'oak-domain/lib/types/Aspect'; +import { EntityDict } from 'oak-domain/lib/types/entity'; +import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-domain/EntityDict'; +import { FrontContext } from '../FrontContext'; -export abstract class Feature> { +export abstract class Feature>> { private callbackSet: Array<() => void>; constructor() { this.callbackSet = []; @@ -21,7 +23,7 @@ export abstract class Feature> { ); } - abstract get(params?: any): any; + abstract get(context: FrontContext, params?: any): Promise; - abstract action(context: FrontContext, type: string, payload?: any): any; + abstract action(context: FrontContext, type: string, payload?: any): Promise; } \ No newline at end of file diff --git a/src/types/FrontContext.ts b/src/types/FrontContext.ts deleted file mode 100644 index 48f96156..00000000 --- a/src/types/FrontContext.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { EntityDef } from 'oak-domain/lib/types/entity'; -import { Aspect } from 'oak-domain/lib/types/Aspect'; -import { Context as BaseContext } from 'oak-memory-tree-store'; - -export class FrontContext> extends BaseContext { -}; \ No newline at end of file