适配domain的改动

This commit is contained in:
Xu Chang 2022-04-14 18:31:36 +08:00
parent d52bcb4d9d
commit e84c024c5d
7 changed files with 123 additions and 104 deletions

1
lib/context.d.ts vendored
View File

@ -6,7 +6,6 @@ export declare class Context<ED extends EntityDict> implements ContextInterface<
uuid?: string;
opRecords: OpRecord<ED>[];
constructor(store: TreeStore<ED>);
on(event: 'commit' | 'rollback', callback: (context: ContextInterface<ED>) => Promise<void>): void;
begin(options?: object): Promise<void>;
commit(): Promise<void>;
rollback(): Promise<void>;

View File

@ -10,9 +10,6 @@ class Context {
this.rowStore = store;
this.opRecords = [];
}
on(event, callback) {
throw new Error('not implemented here!');
}
async begin(options) {
if (!this.uuid) {
const random = await getRandomValues(16);

9
lib/store.d.ts vendored
View File

@ -1,10 +1,9 @@
import { SelectionResult, DeduceCreateSingleOperation, DeduceRemoveOperation, DeduceUpdateOperation, OperationResult, OperateParams, OpRecord, EntityDict } from "oak-domain/lib/types/Entity";
import { SelectionResult2, DeduceCreateSingleOperation, DeduceRemoveOperation, DeduceUpdateOperation, OperationResult, OperateParams, OpRecord, EntityDict } from "oak-domain/lib/types/Entity";
import { CascadeStore } from 'oak-domain/lib/store/CascadeStore';
import { StorageSchema } from 'oak-domain/lib/types/Storage';
import { Context } from "./context";
import { NodeDict, RowNode } from "./types/type";
export default class TreeStore<ED extends EntityDict> extends CascadeStore<ED> {
countextends: any;
store: {
[T in keyof ED]?: {
[ID: string]: RowNode;
@ -61,13 +60,13 @@ export default class TreeStore<ED extends EntityDict> extends CascadeStore<ED> {
* @param context
*/
private addToResultSelections;
protected selectAbjointRow<T extends keyof ED>(entity: T, selection: Omit<ED[T]['Selection'], 'indexFrom' | 'count' | 'data' | 'sorter'>, context: Context<ED>, params?: Object): Promise<SelectionResult<ED, T>['result']>;
protected selectAbjointRow<T extends keyof ED>(entity: T, selection: Omit<ED[T]['Selection'], 'indexFrom' | 'count' | 'data' | 'sorter'>, context: Context<ED>, params?: Object): Promise<Array<ED[T]['OpSchema']>>;
protected updateAbjointRow<T extends keyof ED>(entity: T, operation: DeduceCreateSingleOperation<ED[T]['Schema']> | DeduceUpdateOperation<ED[T]['Schema']> | DeduceRemoveOperation<ED[T]['Schema']>, context: Context<ED>, params?: OperateParams): Promise<void>;
private doOperation;
operate<T extends keyof ED>(entity: T, operation: ED[T]['Operation'], context: Context<ED>, params?: OperateParams): Promise<OperationResult>;
protected formProjection<T extends keyof ED>(entity: T, row: Partial<ED[T]['OpSchema']>, data: ED[T]['Selection']['data'], result: Partial<ED[T]['Schema']>, nodeDict: NodeDict, context: Context<ED>): Promise<void>;
protected formProjection<T extends keyof ED>(entity: T, row: Partial<ED[T]['OpSchema']>, data: ED[T]['Selection']['data'], result: object, nodeDict: NodeDict, context: Context<ED>): Promise<void>;
private formResult;
select<T extends keyof ED>(entity: T, selection: ED[T]['Selection'], context: Context<ED>, params?: Object): Promise<SelectionResult<ED, T>>;
select<T extends keyof ED, S extends ED[T]['Selection']>(entity: T, selection: S, context: Context<ED>, params?: Object): Promise<SelectionResult2<ED[T]['Schema'], S['data']>>;
count<T extends keyof ED>(entity: T, selection: Omit<ED[T]['Selection'], "action" | "data" | "sorter">, context: Context<ED>, params?: Object): Promise<number>;
private addToTxnNode;
begin(uuid: string): void;

View File

@ -15,12 +15,14 @@ const Expression_1 = require("oak-domain/lib/types/Expression");
;
;
class TreeStore extends CascadeStore_1.CascadeStore {
countextends;
store;
immutable;
activeTxnDict;
setInitialData(data) {
for (const entity in data) {
if (!this.store[entity]) {
this.store[entity] = {};
}
for (const rowId in data[entity]) {
(0, lodash_1.set)(this.store, `${entity}.${rowId}.#current`, data[entity][rowId]);
}
@ -29,6 +31,7 @@ class TreeStore extends CascadeStore_1.CascadeStore {
getCurrentData() {
const result = {};
for (const entity in this.store) {
result[entity] = {};
for (const rowId in this.store[entity]) {
(0, lodash_1.set)(result, `${entity}.${rowId}`, this.store[entity][rowId]['$current']);
}
@ -423,7 +426,7 @@ class TreeStore extends CascadeStore_1.CascadeStore {
const fn = await this.translateFilter(attr, filter[attr], context, params);
fns.push(async (node, nodeDict, exprResolveFns) => {
const row = this.constructRow(node, context);
if (row.entity !== attr) {
if (row.entity !== attr || row.entityId) {
return false;
}
const node2 = (0, lodash_1.get)(this.store, `${attr}.${row.entityId}`);
@ -437,9 +440,12 @@ class TreeStore extends CascadeStore_1.CascadeStore {
const fn = await this.translateFilter(relation, filter[attr], context, params);
fns.push(async (node, nodeDict, exprResolveFns) => {
const row = this.constructRow(node, context);
const node2 = (0, lodash_1.get)(this.store, `${relation}.${row[`${attr}Id`]}`);
(0, assert_1.default)(node2);
return fn(node2, nodeDict, exprResolveFns);
if (row[`${attr}Id`]) {
const node2 = (0, lodash_1.get)(this.store, `${relation}.${row[`${attr}Id`]}`);
(0, assert_1.default)(node2);
return fn(node2, nodeDict, exprResolveFns);
}
return false;
});
}
}
@ -637,6 +643,9 @@ class TreeStore extends CascadeStore_1.CascadeStore {
$next: data2,
$path: `${entity}.${id}`,
};
if (!this.store[entity]) {
this.store[entity] = {};
}
(0, lodash_1.set)(this.store, `${entity}.${id}`, node2);
this.addToTxnNode(node2, context, 'create');
if (!params || !params.notCollect) {
@ -807,15 +816,16 @@ class TreeStore extends CascadeStore_1.CascadeStore {
async formResult(entity, rows, selection, context, nodeDict) {
const { data, sorter, indexFrom, count } = selection;
// 先计算projection
const rows2 = await Promise.all(rows.map(async (row) => {
const rows2 = [];
for (const row of rows) {
const result = {};
const nodeDict2 = {};
if (nodeDict) {
(0, lodash_1.assign)(nodeDict2, nodeDict);
}
await this.formProjection(entity, row, data, result, nodeDict2, context);
return result;
}));
rows2.push(result);
}
// 再计算sorter
if (sorter) {
const sorterFn = this.translateSorter(entity, sorter, context);
@ -932,59 +942,75 @@ class TreeStore extends CascadeStore_1.CascadeStore {
}
// 将输入的OpRecord同步到数据中
async sync(opRecords, context) {
for (const record of opRecords) {
switch (record.a) {
case 'c': {
const { e, d } = record;
await this.doOperation(e, {
action: 'create',
data: d,
}, context, {
notCollect: true,
});
break;
}
case 'u': {
const { e, d, f } = record;
await this.doOperation(e, {
action: 'update',
data: d,
filter: f,
}, context, {
notCollect: true,
});
break;
}
case 'r': {
const { e, f } = record;
await this.doOperation(e, {
action: 'remove',
data: {},
filter: f,
}, context, {
notCollect: true,
});
break;
}
case 's': {
const { d } = record;
for (const entity in d) {
for (const id in d[entity]) {
await this.doOperation(entity, {
action: 'create',
data: d[entity][id],
}, context, {
notCollect: true,
});
}
let autoCommit = false;
if (!context.uuid) {
await context.begin();
autoCommit = true;
}
try {
for (const record of opRecords) {
switch (record.a) {
case 'c': {
const { e, d } = record;
await this.doOperation(e, {
action: 'create',
data: d,
}, context, {
notCollect: true,
});
break;
}
case 'u': {
const { e, d, f } = record;
await this.doOperation(e, {
action: 'update',
data: d,
filter: f,
}, context, {
notCollect: true,
});
break;
}
case 'r': {
const { e, f } = record;
await this.doOperation(e, {
action: 'remove',
data: {},
filter: f,
}, context, {
notCollect: true,
});
break;
}
case 's': {
const { d } = record;
for (const entity in d) {
for (const id in d[entity]) {
await this.doOperation(entity, {
action: 'create',
data: d[entity][id],
}, context, {
notCollect: true,
});
}
}
break;
}
default: {
(0, assert_1.default)(false);
}
break;
}
default: {
(0, assert_1.default)(false);
}
}
}
catch (err) {
if (autoCommit) {
await context.rollback();
}
throw err;
}
if (autoCommit) {
await context.commit();
}
}
}
exports.default = TreeStore;

View File

@ -1,6 +1,6 @@
import { assign, cloneDeep, get, last, set, unset } from 'lodash';
import assert from 'assert';
import { EntityDef, SelectionResult, DeduceCreateSingleOperation, DeduceFilter, DeduceSelection, EntityShape, DeduceRemoveOperation, DeduceUpdateOperation, DeduceSorter, DeduceSorterAttr, OperationResult, OperateParams, OpRecord, DeduceCreateOperationData, DeduceUpdateOperationData, UpdateOpResult, RemoveOpResult, SelectOpResult, EntityDict } from "oak-domain/lib/types/Entity";
import { EntityDef, SelectionResult2, DeduceCreateSingleOperation, DeduceFilter, DeduceSelection, EntityShape, DeduceRemoveOperation, DeduceUpdateOperation, DeduceSorter, DeduceSorterAttr, OperationResult, OperateParams, OpRecord, DeduceCreateOperationData, DeduceUpdateOperationData, UpdateOpResult, RemoveOpResult, SelectOpResult, EntityDict, SelectRowShape } from "oak-domain/lib/types/Entity";
import { ExpressionKey, EXPRESSION_PREFIX, NodeId, RefAttr } from 'oak-domain/lib/types/Demand';
import { CascadeStore } from 'oak-domain/lib/store/CascadeStore';
import { StorageSchema } from 'oak-domain/lib/types/Storage';
@ -544,7 +544,7 @@ export default class TreeStore<ED extends EntityDict> extends CascadeStore<ED> {
return false;
}
const node2 = get(this.store, `${attr}.${(row as any).entityId}`);
assert(node2);
assert(node2);
return fn(node2, nodeDict, exprResolveFns);
}
);
@ -589,10 +589,10 @@ export default class TreeStore<ED extends EntityDict> extends CascadeStore<ED> {
}
private translateSorter<T extends keyof ED>(entity: T, sorter: DeduceSorter<ED[T]['Schema']>, context: Context<ED>):
(row1: Partial<EntityShape>, row2: Partial<EntityShape>) => number {
(row1: object | null | undefined, row2: object | null | undefined) => number {
const compare = <T2 extends keyof ED>(
row1: Partial<ED[T2]['Schema']> | null | undefined,
row2: Partial<ED[T2]['Schema']> | null | undefined,
row1: object | null | undefined,
row2: object | null | undefined,
entity2: T2,
sortAttr: DeduceSorterAttr<ED[T2]['Schema']>, direction?: 'asc' | 'desc'): number => {
const row11 = row1 as any;
@ -706,7 +706,7 @@ export default class TreeStore<ED extends EntityDict> extends CascadeStore<ED> {
};
opRecords.push(lastOperation);
}
const entityBranch = {};
rows.forEach(
(row) => {
@ -725,7 +725,7 @@ export default class TreeStore<ED extends EntityDict> extends CascadeStore<ED> {
entity: T,
selection: Omit<ED[T]['Selection'], 'indexFrom' | 'count' | 'data' | 'sorter'>,
context: Context<ED>,
params: Object = {}): Promise<SelectionResult<ED, T>['result']> {
params: Object = {}): Promise<Array<ED[T]['OpSchema']>> {
const { filter } = selection;
const { nodeDict } = params as {
nodeDict: NodeDict;
@ -863,11 +863,11 @@ export default class TreeStore<ED extends EntityDict> extends CascadeStore<ED> {
const { action } = operation;
if (action === 'select') {
const rows = await this.cascadeSelect(entity, operation as any, context, params);
const result = await this.formResult(entity, rows, operation as any, context);
const ids = result.map(
(ele) => ele.id!
);
) as string[];
return { ids };
}
else {
@ -901,7 +901,7 @@ export default class TreeStore<ED extends EntityDict> extends CascadeStore<ED> {
entity: T,
row: Partial<ED[T]['OpSchema']>,
data: ED[T]['Selection']['data'],
result: Partial<ED[T]['Schema']>,
result: object,
nodeDict: NodeDict,
context: Context<ED>) {
const row2 = row as any;
@ -985,27 +985,24 @@ export default class TreeStore<ED extends EntityDict> extends CascadeStore<ED> {
}
}
private async formResult<T extends keyof ED>(
private async formResult<T extends keyof ED, S extends ED[T]['Selection']>(
entity: T,
rows: Array<Partial<ED[T]['Schema']>>,
selection: Omit<ED[T]['Selection'], 'filter'>,
selection: Omit<S, 'filter'>,
context: Context<ED>,
nodeDict?: NodeDict) {
const { data, sorter, indexFrom, count } = selection;
// 先计算projection
const rows2 = await Promise.all(
rows.map(
async (row) => {
const result: Partial<ED[T]['Schema']> = {};
const nodeDict2: NodeDict = {};
if (nodeDict) {
assign(nodeDict2, nodeDict);
}
await this.formProjection(entity, row, data, result, nodeDict2, context);
return result;
}
)
);
const rows2: Array<SelectRowShape<ED[T]['Schema'], S['data']>> = [];
for (const row of rows) {
const result = {};
const nodeDict2: NodeDict = {};
if (nodeDict) {
assign(nodeDict2, nodeDict);
}
await this.formProjection(entity, row, data, result, nodeDict2, context);
rows2.push(result as SelectRowShape<ED[T]['Schema'], S['data']>);
}
// 再计算sorter
if (sorter) {
@ -1022,7 +1019,11 @@ export default class TreeStore<ED extends EntityDict> extends CascadeStore<ED> {
}
}
async select<T extends keyof ED>(entity: T, selection: ED[T]['Selection'], context: Context<ED>, params?: Object): Promise<SelectionResult<ED, T>> {
async select<T extends keyof ED, S extends ED[T]['Selection']>(
entity: T,
selection: S,
context: Context<ED>,
params?: Object): Promise<SelectionResult2<ED[T]['Schema'], S['data']>> {
let autoCommit = false;
let result;
if (!context.uuid) {
@ -1031,7 +1032,7 @@ export default class TreeStore<ED extends EntityDict> extends CascadeStore<ED> {
}
try {
const rows = await this.cascadeSelect(entity, selection, context, params);
result = await this.formResult(entity, rows, selection, context);
} catch (err) {
if (autoCommit) {
@ -1192,9 +1193,9 @@ export default class TreeStore<ED extends EntityDict> extends CascadeStore<ED> {
}
}
}
catch(err) {
catch (err) {
if (autoCommit) {
await context.rollback();
await context.rollback();
}
throw err;
}

View File

@ -2,8 +2,5 @@ import { unset } from 'lodash';
import { analyzeEntities, buildSchema } from 'oak-domain/src/compiler/schemalBuilder';
process.env.NODE_ENV = 'development';
process.env.COMPILING_BASE_DOMAIN = 'yes';
analyzeEntities(`${__dirname}/../node_modules/oak-domain/src/entities`);
unset(process.env, 'COMPILING_BASE_DOMAIN');
buildSchema(`${__dirname}/app-domain/`);
process.env.IN_OAK_DOMAIN = undefined;
analyzeEntities(`${__dirname}/../../oak-general-business/src/entities`);
buildSchema(`${__dirname}/app-domain/`);

View File

@ -407,12 +407,12 @@ describe('基础测试', function () {
assert(applications.result.length === 2);
applications.result.forEach(
(app) => {
assert(app.id === 'aaa' && app.system!.$expr === false
assert(app.id === 'aaa' && app.system!.$expr === false
|| app.id === 'aaa2' && app.system!.$expr === true);
}
);
applications = await store.select('application', {
const applications2 = await store.select('application', {
data: {
$expr: {
$eq: [
@ -434,9 +434,9 @@ describe('基础测试', function () {
}
},
}, context);
console.log(applications);
console.log(applications2);
// assert(applications.length === 2);
applications.result.forEach(
applications2.result.forEach(
(app) => {
assert(app.id === 'aaa' && app.$expr === false
|| app.id === 'aaa2' && app.$expr === true);