This commit is contained in:
Xu Chang 2022-03-21 20:59:50 +08:00
parent 52d97b2574
commit 1bc53f24f7
15 changed files with 169 additions and 186 deletions

View File

@ -1,7 +1,6 @@
import { EntityDef } from "oak-domain/lib/types/Entity";
import { TriggerEntityShape } from "oak-domain/lib/types/Trigger";
import { Context as BaseContext } from 'oak-debug-store';
export declare class Context<E extends string, ED extends {
[K in E]: EntityDef<E, ED, K, SH>;
}, SH extends TriggerEntityShape = TriggerEntityShape> extends BaseContext<E, ED, SH> {
export declare class Context<ED extends {
[E: string]: EntityDef;
}> extends BaseContext<ED> {
}

View File

@ -1,12 +1,11 @@
import { DebugStore } from 'oak-debug-store';
import { EntityDef } from "oak-domain/lib/types/Entity";
import { StorageSchema } from 'oak-domain/lib/types/Storage';
import { TriggerEntityShape } from "oak-domain/lib/types/Trigger";
export declare function createDebugStore<E extends string, ED extends {
[K in E]: EntityDef<E, ED, K, SH>;
}, SH extends TriggerEntityShape = TriggerEntityShape>(storageSchema: StorageSchema, initialData?: {
[T in E]?: {
export declare function createDebugStore<ED extends {
[E: string]: EntityDef;
}>(storageSchema: StorageSchema<ED>, initialData?: {
[T in keyof ED]?: {
[ID: string]: ED[T]['OpSchema'];
};
}): DebugStore<E, ED, SH>;
}): DebugStore<ED>;
export * from './context';

View File

@ -1,7 +1,11 @@
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];

View File

@ -1,4 +1,19 @@
declare const dataSlice: import("@reduxjs/toolkit").Slice<number, {
refreshSentry: (state: number) => void;
}, "sentry">;
export default dataSlice;
import { Slice, ThunkAction } from '@reduxjs/toolkit';
import { EntityDef, OperationResult, SelectionResult } from 'oak-domain/lib/types/Entity';
import { StorageSchema } from 'oak-domain/lib/types/Storage';
import { Trigger } from 'oak-domain/lib/types/Trigger';
import { Context } from '../dataStore/debugStore';
export declare function initialize<ED extends {
[K: string]: EntityDef;
}>(storageSchema: StorageSchema<ED>, triggers?: Array<Trigger<ED, keyof ED>>): {
slice: Slice<number, {
refreshSentry: (state: number) => void;
}, "sentry">;
actions: {
operate<T extends keyof ED>(entity: T, operation: ED[T]["Operation"], context: Context<ED>, params?: Object | undefined): ThunkAction<Promise<any>, any, any, {
payload: undefined;
type: string;
}>;
};
selectData<T_1 extends keyof ED>(entity: T_1, selection: ED[T_1]["Selection"], context: Context<ED>, params?: Object | undefined): Promise<SelectionResult<ED, T_1>>;
};

View File

@ -1,17 +1,43 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.initialize = void 0;
const toolkit_1 = require("@reduxjs/toolkit");
const debugStore_1 = require("../dataStore/debugStore");
// Define the initial state using that type
const initialState = 0;
const dataSlice = (0, toolkit_1.createSlice)({
name: 'sentry',
// `createSlice` will infer the state type from the `initialState` argument
initialState,
reducers: {
// Use the PayloadAction type to declare the contents of `action.payload`
refreshSentry: (state) => {
state = state + 1;
},
function initialize(storageSchema, triggers) {
const dataStore = (0, debugStore_1.createDebugStore)(storageSchema);
if (triggers) {
for (const trigger of triggers) {
dataStore.registerTrigger(trigger);
}
}
});
exports.default = dataSlice;
const slice = (0, toolkit_1.createSlice)({
name: 'sentry',
// `createSlice` will infer the state type from the `initialState` argument
initialState,
reducers: {
// Use the PayloadAction type to declare the contents of `action.payload`
refreshSentry: (state) => {
state = state + 1;
},
}
});
const actions = {
operate(entity, operation, context, params) {
return async (dispatch) => {
const result = await dataStore.operate(entity, operation, context, params);
dispatch(slice.actions.refreshSentry());
return result;
};
},
};
return {
slice,
actions,
selectData(entity, selection, context, params) {
return dataStore.select(entity, selection, context, params);
},
};
}
exports.initialize = initialize;

View File

@ -1,6 +1,11 @@
import { PayloadAction } from '@reduxjs/toolkit';
export declare const tokenSlice: import("@reduxjs/toolkit").Slice<string, {
setToken: (state: string, action: PayloadAction<string>) => void;
unsetToken: (state: string) => void;
}, "token">;
export default tokenSlice;
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 { Feature } from '../types/Feature';
import { FrontContext } from '../FrontContext';
export declare class Token<ED extends EntityDict & BaseEntityDict, AD extends Record<string, Aspect<ED>>> extends Feature<ED, AD> {
tokenValue?: string;
get(context: FrontContext<ED, AD>): Promise<void>;
action(context: FrontContext<ED, AD>, type: string, payload?: any): Promise<void>;
getTokenValue(): string | undefined;
}

View File

@ -1,21 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.tokenSlice = void 0;
const toolkit_1 = require("@reduxjs/toolkit");
// Define the initial state using that type
const initialState = '';
exports.tokenSlice = (0, toolkit_1.createSlice)({
name: 'token',
// `createSlice` will infer the state type from the `initialState` argument
initialState,
reducers: {
// Use the PayloadAction type to declare the contents of `action.payload`
setToken: (state, action) => {
state = action.payload;
},
unsetToken: (state) => {
state = '';
}
exports.Token = void 0;
const Feature_1 = require("../types/Feature");
class Token extends Feature_1.Feature {
tokenValue;
async get(context) {
throw new Error('Method not implemented.');
}
});
exports.default = exports.tokenSlice;
async action(context, type, payload) {
throw new Error('Method not implemented.');
}
getTokenValue() {
return this.tokenValue;
}
}
exports.Token = Token;

40
lib/index.d.ts vendored
View File

@ -1,29 +1,13 @@
import { EntityDef } from "oak-domain/lib/types/Entity";
import { StorageSchema } from 'oak-domain/lib/types/Storage';
import { Trigger, TriggerEntityShape } from "oak-domain/lib/types/Trigger";
import { Context as DebugContext } from './dataStore/debugStore';
declare type RootState = ReturnType<(ReturnType<typeof initialize>)['store']['getState']>;
export declare const getToken: (state: RootState) => string;
export declare const getSentry: (state: RootState) => number;
export declare function initialize<E extends string, ED extends {
[K in E]: EntityDef<E, ED, K, SH>;
}, SH extends TriggerEntityShape = TriggerEntityShape>(storageSchema: StorageSchema, triggers?: Array<Trigger<E, ED, E, SH>>, initialState?: Object, isDebug?: boolean): {
store: import("@reduxjs/toolkit").EnhancedStore<{
t: string;
s: number;
}, import("redux").AnyAction, [import("redux-thunk").ThunkMiddleware<{
t: string;
s: number;
}, import("redux").AnyAction, null> | import("redux-thunk").ThunkMiddleware<{
t: string;
s: number;
}, import("redux").AnyAction, undefined>]>;
actions: {
operate: <T extends E>(entity: T, operation: ED[T]["Operation"], context: DebugContext<E, ED, SH>, params?: Object | undefined) => Promise<void>;
select: <T_1 extends E>(entity: T_1, selection: ED[T_1]["Selection"], context: DebugContext<E, ED, SH>, params?: Object | undefined) => Promise<SelectionResult<E_1, ED_1, T_2, SH_1>>;
count: <T_3 extends E>(entity: T_3, selection: ED[T_3]["Selection"], context: DebugContext<E, ED, SH>, params?: Object | undefined) => any;
setToken: import("@reduxjs/toolkit").ActionCreatorWithPayload<string, string>;
unsetToken: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<string>;
};
};
export {};
import { Trigger } from "oak-domain/lib/types/Trigger";
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-domain/EntityDict';
import { Aspect } from 'oak-domain/lib/types/Aspect';
import { Feature } from './types/Feature';
import { EntityDict } from 'oak-domain/lib/types/Entity';
export declare function initialize<ED extends EntityDict & BaseEntityDict, AD extends Record<string, Aspect<ED>>, FD extends Record<string, new <P extends EntityDict & BaseEntityDict, Q extends Record<string, Aspect<P>>>() => Feature<P, Q>>>(storageSchema: StorageSchema<ED>, applicationId: string, featureClazzDict?: FD, triggers?: Array<Trigger<ED, keyof ED>>, aspectDict?: AD, initialData?: {
[T in keyof ED]?: Array<ED[T]['OpSchema']>;
}): Promise<{
subscribe: <F extends "token" | keyof FD>(features: F[], callback: () => void) => () => void;
getFeature: <F_1 extends "token" | keyof FD>(f: F_1, params?: Parameters<InstanceType<FD[F_1]>["get"]>[1] | undefined) => ReturnType<InstanceType<FD[F_1]>["get"]>;
actionFeature: <F_2 extends "token" | keyof FD>(f: F_2, t: Parameters<InstanceType<FD[F_2]>["action"]>[1], p?: Parameters<InstanceType<FD[F_2]>["action"]>[2] | undefined) => ReturnType<InstanceType<FD[F_2]>["action"]>;
}>;

View File

@ -1,42 +1,55 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.initialize = exports.getSentry = exports.getToken = void 0;
const toolkit_1 = require("@reduxjs/toolkit");
const token_1 = __importDefault(require("./features/token"));
const sentry_1 = __importDefault(require("./features/sentry"));
const debugStore_1 = require("./dataStore/debugStore");
const reducer = {
t: token_1.default.reducer,
s: sentry_1.default.reducer,
};
const getToken = (state) => state.t;
exports.getToken = getToken;
const getSentry = (state) => state.s;
exports.getSentry = getSentry;
function initialize(storageSchema, triggers = [], initialState = {}, isDebug = true) {
const store = (0, toolkit_1.configureStore)({
reducer,
preloadedState: initialState,
});
const dataStore = (0, debugStore_1.createDebugStore)(storageSchema);
for (const trigger of triggers) {
dataStore.registerTrigger(trigger);
exports.initialize = void 0;
const token_1 = require("./features/token");
const lodash_1 = require("lodash");
const FrontContext_1 = require("./FrontContext");
function populateFeatures(featureClazzDict) {
const result = {};
for (const k in featureClazzDict) {
(0, lodash_1.assign)(result, {
[k]: new featureClazzDict[k](),
});
}
return result;
}
async function initialize(storageSchema, applicationId, featureClazzDict, triggers, aspectDict, initialData) {
const token = new token_1.Token();
// todo default triggers
const frontContext = new FrontContext_1.FrontContext(storageSchema, triggers, applicationId, () => token.getTokenValue(), aspectDict, initialData);
const featureDict = {
token: token_1.Token,
};
function ppf() {
return populateFeatures(featureClazzDict);
}
if (featureClazzDict) {
(0, lodash_1.assign)(featureDict, ppf());
}
const featureDict2 = featureDict;
const subscribe = (features, callback) => {
const unsubscribes = features.map((f) => {
const feature = featureDict2[f];
return feature.subscribe(callback);
});
return () => {
unsubscribes.forEach(ele => ele());
};
};
const getFeature = (f, params) => {
// const context = new FrontContext<ED, typeof aspectDict2>(store, aspectProxy) as any;
const feature = featureDict2[f];
return feature.get(frontContext, params); // 这里有个类型的转换暂时写不出来因为populateFeatures没法传递generic types在返回值里
};
const actionFeature = (f, t, p) => {
// const context = new FrontContext<ED, typeof aspectDict2>(store, aspectProxy) as any;
const feature = featureDict2[f];
return feature.action(frontContext, t, p);
};
return {
store,
actions: {
...token_1.default.actions,
operate: (entity, operation, context, params) => {
const result = dataStore.operate(entity, operation, context, params);
sentry_1.default.actions.refreshSentry();
return result;
},
select: (entity, selection, context, params) => dataStore.select(entity, selection, context, params),
count: (entity, selection, context, params) => dataStore.count(entity, selection, context, params)
},
subscribe,
getFeature,
actionFeature,
};
}
exports.initialize = initialize;

View File

@ -26,7 +26,7 @@ class DebugRunningContext<ED extends EntityDict> extends Context<ED> implements
}
};
export async function createAspectProxy<ED extends EntityDict, AD extends Record<string, Aspect<ED>>>(
export async function createAspectProxy<ED extends BaseEntityDict & EntityDict, AD extends Record<string, Aspect<ED>>>(
cacheStore: CacheStore<ED>,
storageSchema: StorageSchema<ED>,
triggers: Array<Trigger<ED, keyof ED>>,
@ -49,7 +49,7 @@ export async function createAspectProxy<ED extends EntityDict, AD extends Record
);
const context = new Context(debugStore);
const { result: [application] } = await (<DebugStore<BaseEntityDict>><unknown>debugStore).select('application', {
const { result: [application] } = await debugStore.select('application', {
data: {
id: 1,
systemId: 1,
@ -60,7 +60,7 @@ export async function createAspectProxy<ED extends EntityDict, AD extends Record
filter: {
id: applicationId,
}
}, <Context<BaseEntityDict>><unknown>context);
}, context);
const getApplication = () => application as Application;
const FullAspectProxy = assign(BaseAspectProxy, aspectDict);
@ -71,7 +71,7 @@ export async function createAspectProxy<ED extends EntityDict, AD extends Record
const tokenValue = getTokenValue();
let token: Token | undefined;
if (tokenValue) {
const { result } = await (<DebugStore<BaseEntityDict>><unknown>debugStore).select('token', {
const { result } = await debugStore.select('token', {
data: {
id: 1,
userId: 1,
@ -80,7 +80,7 @@ export async function createAspectProxy<ED extends EntityDict, AD extends Record
filter: {
id: tokenValue,
}
}, <Context<BaseEntityDict>><unknown>context2);
}, context2);
token = result[0] as Token;
// todo 判断 token的合法性
}
@ -91,7 +91,7 @@ export async function createAspectProxy<ED extends EntityDict, AD extends Record
}
}
export class FrontContext<ED extends EntityDict, AD extends Record<string, Aspect<ED>>> extends BaseContext<ED> {
export class FrontContext<ED extends EntityDict & BaseEntityDict, AD extends Record<string, Aspect<ED>>> extends BaseContext<ED> {
getAspectProxy: () => Promise<AspectProxy<ED, AD & typeof BaseAspectProxy>>;
constructor(

View File

@ -1,9 +1,10 @@
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 { Feature } from '../types/Feature';
import { FrontContext } from '../FrontContext';
export class Data<ED extends EntityDict, AD extends Record<string, Aspect<ED>>> extends Feature<ED, AD> {
export class Data<ED extends EntityDict & BaseEntityDict, AD extends Record<string, Aspect<ED>>> extends Feature<ED, AD> {
async get<T extends keyof ED>(context: FrontContext<ED, AD>, params: { entity: T, selection: ED[T]['Selection'] }) {
const { result } = await context.rowStore.select(params.entity, params.selection, context);
return result;

View File

@ -1,60 +0,0 @@
import { createSlice, PayloadAction, Slice, ThunkAction } from '@reduxjs/toolkit';
import { EntityDef, OperationResult, SelectionResult } from 'oak-domain/lib/types/Entity';
import { StorageSchema } from 'oak-domain/lib/types/Storage';
import { Trigger } from 'oak-domain/lib/types/Trigger';
import { Context, createDebugStore } from '../dataStore/debugStore';
// Define the initial state using that type
const initialState: number = 0;
export function initialize<ED extends {
[K: string]: EntityDef;
}>(storageSchema: StorageSchema<ED>, triggers?: Array<Trigger<ED, keyof ED>>) {
const dataStore = createDebugStore<ED>(storageSchema);
if (triggers) {
for (const trigger of triggers) {
dataStore.registerTrigger(trigger);
}
}
const slice = createSlice({
name: 'sentry',
// `createSlice` will infer the state type from the `initialState` argument
initialState,
reducers: {
// Use the PayloadAction type to declare the contents of `action.payload`
refreshSentry: (state) => {
state = state + 1;
},
}
});
const actions = {
operate<T extends keyof ED>(
entity: T,
operation: ED[T]['Operation'],
context: Context<ED>,
params?: Object
): ThunkAction<Promise<OperationResult<ED>>, any, any, ReturnType<typeof slice.actions.refreshSentry>> {
return async (dispatch) => {
const result = await dataStore.operate(entity, operation, context, params);
dispatch(slice.actions.refreshSentry());
return result;
};
},
};
return {
slice,
actions,
selectData<T extends keyof ED>(
entity: T,
selection: ED[T]['Selection'],
context: Context<ED>,
params?: Object
) {
return dataStore.select(entity, selection, context, params);
},
}
}

View File

@ -1,9 +1,10 @@
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 { Feature } from '../types/Feature';
import { FrontContext } from '../FrontContext';
export class Token<ED extends EntityDict, AD extends Record<string, Aspect<ED>>> extends Feature<ED, AD> {
export class Token<ED extends EntityDict & BaseEntityDict, AD extends Record<string, Aspect<ED>>> extends Feature<ED, AD> {
tokenValue?: string;
async get(context: FrontContext<ED, AD>) {
throw new Error('Method not implemented.');

View File

@ -1,6 +1,6 @@
import { StorageSchema } from 'oak-domain/lib/types/Storage';
import { Trigger } from "oak-domain/lib/types/Trigger";
import { EntityDict as BaseEntityDict } from 'oak-domain/src/base-domain/EntityDict';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-domain/EntityDict';
import { Aspect } from 'oak-domain/lib/types/Aspect';
import { Feature } from './types/Feature';
@ -11,7 +11,7 @@ import { EntityDict } from 'oak-domain/lib/types/Entity';
import { FrontContext } from './FrontContext';
function populateFeatures<ED extends EntityDict, AD extends Record<string, Aspect<ED>>, FD extends Record<string, new <P extends EntityDict, Q extends Record<string, Aspect<P>>>() => Feature<P, Q>>>(featureClazzDict: FD)
function populateFeatures<ED extends EntityDict & BaseEntityDict, AD extends Record<string, Aspect<ED>>, FD extends Record<string, new <P extends EntityDict & BaseEntityDict, Q extends Record<string, Aspect<P>>>() => Feature<P, Q>>>(featureClazzDict: FD)
: {
[T in keyof FD]: InstanceType<FD[T]>;
} {
@ -25,9 +25,9 @@ function populateFeatures<ED extends EntityDict, AD extends Record<string, Aspec
return result as any;
}
export async function initialize<ED extends EntityDict,
export async function initialize<ED extends EntityDict & BaseEntityDict,
AD extends Record<string, Aspect<ED>>,
FD extends Record<string, new <P extends EntityDict, Q extends Record<string, Aspect<P>>>() => Feature<P, Q>>>(
FD extends Record<string, new <P extends EntityDict & BaseEntityDict, Q extends Record<string, Aspect<P>>>() => Feature<P, Q>>>(
storageSchema: StorageSchema<ED>,
applicationId: string,
featureClazzDict?: FD,

View File

@ -4,7 +4,7 @@ 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<ED extends EntityDict, AD extends Record<string, Aspect<ED>>> {
export abstract class Feature<ED extends EntityDict & BaseEntityDict, AD extends Record<string, Aspect<ED>>> {
private callbackSet: Array<() => void>;
constructor() {
this.callbackSet = [];