适配domain的改动
This commit is contained in:
parent
d52bcb4d9d
commit
e84c024c5d
|
|
@ -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>;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
140
lib/store.js
140
lib/store.js
|
|
@ -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;
|
||||
|
|
|
|||
59
src/store.ts
59
src/store.ts
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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/`);
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue