oak-domain 5.0.8 → 5.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/compiler/localeBuilder.js +7 -1
- package/lib/compiler/schemalBuilder.js +6 -6
- package/lib/store/CascadeStore.js +1 -0
- package/lib/store/TriggerExecutor.js +58 -27
- package/lib/store/checker.js +6 -0
- package/lib/types/Trigger.d.ts +1 -0
- package/lib/types/Watcher.d.ts +2 -1
- package/lib/utils/projection.d.ts +1 -0
- package/lib/utils/projection.js +21 -1
- package/package.json +1 -1
|
@@ -124,7 +124,13 @@ class LocaleBuilder {
|
|
|
124
124
|
const content = fs_1.default.readFileSync(filepath, {
|
|
125
125
|
encoding: 'utf-8',
|
|
126
126
|
});
|
|
127
|
-
|
|
127
|
+
try {
|
|
128
|
+
return JSON.parse(content);
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
console.error(`parse ${filepath} error`, err);
|
|
132
|
+
throw err;
|
|
133
|
+
}
|
|
128
134
|
}
|
|
129
135
|
parseFile(module, namespace, position, filename, filepath, watch) {
|
|
130
136
|
const language = (filename.split('.')[0]).replace('_', '-'); // 历史原因,会命名成zh_CN.json
|
|
@@ -584,7 +584,7 @@ function getImportedFilePath(path, fileSpecifierPath, filename) {
|
|
|
584
584
|
return '';
|
|
585
585
|
};
|
|
586
586
|
if (fileSpecifierPath.startsWith('.')) {
|
|
587
|
-
importedFilepath = path_1.default.join(
|
|
587
|
+
importedFilepath = path_1.default.join(path, fileSpecifierPath);
|
|
588
588
|
const importedFilename = getExistedFileName();
|
|
589
589
|
(0, assert_1.default)(importedFilename, `「${filename}」中import路径${fileSpecifierPath}找不到对应的声明`);
|
|
590
590
|
return importedFilename;
|
|
@@ -2236,7 +2236,7 @@ function constructOperations(statements, entity) {
|
|
|
2236
2236
|
}
|
|
2237
2237
|
if (manyToOneSet) {
|
|
2238
2238
|
for (const one of manyToOneSet) {
|
|
2239
|
-
if (
|
|
2239
|
+
if (one[1] !== 'entity') {
|
|
2240
2240
|
foreignKeyAttr.push(`${one[1]}Id`);
|
|
2241
2241
|
}
|
|
2242
2242
|
}
|
|
@@ -2260,7 +2260,7 @@ function constructOperations(statements, entity) {
|
|
|
2260
2260
|
*/
|
|
2261
2261
|
const upsertOneNodes = [];
|
|
2262
2262
|
for (const one of manyToOneSet) {
|
|
2263
|
-
if (
|
|
2263
|
+
if (one[1] !== 'entity') {
|
|
2264
2264
|
const oneEntity = one[0];
|
|
2265
2265
|
const cascadeCreateNode = factory.createTypeLiteralNode([
|
|
2266
2266
|
factory.createPropertySignature(undefined, factory.createIdentifier(`${one[1]}Id`), factory.createToken(ts.SyntaxKind.QuestionToken), factory.createKeywordTypeNode(ts.SyntaxKind.NeverKeyword)),
|
|
@@ -2472,7 +2472,7 @@ function constructOperations(statements, entity) {
|
|
|
2472
2472
|
}
|
|
2473
2473
|
if (manyToOneSet) {
|
|
2474
2474
|
for (const one of manyToOneSet) {
|
|
2475
|
-
if (
|
|
2475
|
+
if (one[1] !== 'entity') {
|
|
2476
2476
|
foreignKeyAttr.push(`${one[1]}Id`);
|
|
2477
2477
|
}
|
|
2478
2478
|
}
|
|
@@ -2494,7 +2494,7 @@ function constructOperations(statements, entity) {
|
|
|
2494
2494
|
*/
|
|
2495
2495
|
const upsertOneNodes = [];
|
|
2496
2496
|
for (const one of manyToOneSet) {
|
|
2497
|
-
if (
|
|
2497
|
+
if (one[1] !== 'entity') {
|
|
2498
2498
|
const cascadeCreateNode = factory.createTypeLiteralNode([
|
|
2499
2499
|
factory.createPropertySignature(undefined, factory.createIdentifier(one[1]), factory.createToken(ts.SyntaxKind.QuestionToken), factory.createTypeReferenceNode(createForeignRef(entity, one[0], 'CreateSingleOperation'))),
|
|
2500
2500
|
factory.createPropertySignature(undefined, factory.createIdentifier(`${one[1]}Id`), factory.createToken(ts.SyntaxKind.QuestionToken), factory.createKeywordTypeNode(ts.SyntaxKind.NeverKeyword)),
|
|
@@ -2777,7 +2777,7 @@ function constructOperations(statements, entity) {
|
|
|
2777
2777
|
*/
|
|
2778
2778
|
const upsertOneNodes = [];
|
|
2779
2779
|
for (const one of manyToOneSet) {
|
|
2780
|
-
if (
|
|
2780
|
+
if (one[1] !== 'entity') {
|
|
2781
2781
|
if (!Schema[one[0]].static) {
|
|
2782
2782
|
switch (Schema[one[0]].actionType) {
|
|
2783
2783
|
case 'crud': {
|
|
@@ -304,9 +304,17 @@ class TriggerExecutor {
|
|
|
304
304
|
return execPreTrigger(idx + 1);
|
|
305
305
|
}
|
|
306
306
|
}
|
|
307
|
-
const
|
|
308
|
-
|
|
309
|
-
|
|
307
|
+
const closeRoot = trigger.asRoot && context.openRootMode();
|
|
308
|
+
try {
|
|
309
|
+
const number = await trigger.fn({ operation: operation }, context, option);
|
|
310
|
+
if (number > 0 && process.env.NODE_ENV === 'development') {
|
|
311
|
+
this.logger.info(`前触发器「${trigger.name}」成功触发了「${number}」行数据更改`);
|
|
312
|
+
}
|
|
313
|
+
closeRoot && closeRoot();
|
|
314
|
+
}
|
|
315
|
+
catch (err) {
|
|
316
|
+
closeRoot && closeRoot();
|
|
317
|
+
throw err;
|
|
310
318
|
}
|
|
311
319
|
return execPreTrigger(idx + 1);
|
|
312
320
|
};
|
|
@@ -338,26 +346,41 @@ class TriggerExecutor {
|
|
|
338
346
|
(0, assert_1.default)(trigger && trigger.when === 'commit');
|
|
339
347
|
(0, assert_1.default)(ids.length > 0);
|
|
340
348
|
const { fn } = trigger;
|
|
341
|
-
const
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
349
|
+
const closeRoot = trigger.asRoot && context.openRootMode();
|
|
350
|
+
try {
|
|
351
|
+
const callback = await fn({ ids }, context, option);
|
|
352
|
+
if (trigger.strict === 'makeSure') {
|
|
353
|
+
// 这里开root模式,否则还可能有权限问题
|
|
354
|
+
const closeRoot2 = context.openRootMode();
|
|
355
|
+
try {
|
|
356
|
+
await context.operate(entity, {
|
|
357
|
+
id: await (0, uuid_1.generateNewIdAsync)(),
|
|
358
|
+
action: 'update',
|
|
359
|
+
data: {
|
|
360
|
+
[Entity_1.TriggerDataAttribute]: null,
|
|
361
|
+
[Entity_1.TriggerUuidAttribute]: null,
|
|
362
|
+
},
|
|
363
|
+
filter: {
|
|
364
|
+
id: {
|
|
365
|
+
$in: ids,
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}, { includedDeleted: true, blockTrigger: true });
|
|
369
|
+
closeRoot2 && closeRoot2();
|
|
370
|
+
}
|
|
371
|
+
catch (err2) {
|
|
372
|
+
closeRoot2 && closeRoot2();
|
|
373
|
+
throw err2;
|
|
356
374
|
}
|
|
357
|
-
}
|
|
375
|
+
}
|
|
376
|
+
if (typeof callback === 'function') {
|
|
377
|
+
await callback(context, option);
|
|
378
|
+
}
|
|
379
|
+
closeRoot && closeRoot();
|
|
358
380
|
}
|
|
359
|
-
|
|
360
|
-
|
|
381
|
+
catch (err) {
|
|
382
|
+
closeRoot && closeRoot();
|
|
383
|
+
throw err;
|
|
361
384
|
}
|
|
362
385
|
}
|
|
363
386
|
/**
|
|
@@ -407,12 +430,20 @@ class TriggerExecutor {
|
|
|
407
430
|
return;
|
|
408
431
|
}
|
|
409
432
|
const trigger = postTriggers[idx];
|
|
410
|
-
const
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
433
|
+
const closeRoot = trigger.asRoot && context.openRootMode();
|
|
434
|
+
try {
|
|
435
|
+
const number = await trigger.fn({
|
|
436
|
+
operation: operation,
|
|
437
|
+
result: result,
|
|
438
|
+
}, context, option);
|
|
439
|
+
if (number > 0 && process.env.NODE_ENV === 'development') {
|
|
440
|
+
this.logger.info(`后触发器「${trigger.name}」成功触发了「${number}」行数据更改`);
|
|
441
|
+
}
|
|
442
|
+
closeRoot && closeRoot();
|
|
443
|
+
}
|
|
444
|
+
catch (err) {
|
|
445
|
+
closeRoot && closeRoot();
|
|
446
|
+
throw err;
|
|
416
447
|
}
|
|
417
448
|
return execPostTrigger(idx + 1);
|
|
418
449
|
};
|
package/lib/store/checker.js
CHANGED
|
@@ -48,6 +48,9 @@ function translateCheckerInAsyncContext(checker, schema) {
|
|
|
48
48
|
const fn = (async ({ operation }, context, option) => {
|
|
49
49
|
const { filter: operationFilter, data, action, bornAt } = operation;
|
|
50
50
|
const filter2 = typeof filter === 'function' ? await filter(operation, context, option) : filter;
|
|
51
|
+
if (!filter2) {
|
|
52
|
+
return 0;
|
|
53
|
+
}
|
|
51
54
|
if (['select', 'count', 'stat'].includes(action)) {
|
|
52
55
|
operation.filter = (0, filter_1.combineFilters)(entity, context.getSchema(), [operationFilter, filter2]);
|
|
53
56
|
return 0;
|
|
@@ -142,6 +145,9 @@ function translateCheckerInSyncContext(checker, schema) {
|
|
|
142
145
|
const fn = (operation, context, option) => {
|
|
143
146
|
const { filter: operationFilter, data, action, bornAt } = operation;
|
|
144
147
|
const filter2 = typeof filter === 'function' ? filter(operation, context, option) : filter;
|
|
148
|
+
if (!filter2) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
145
151
|
let operationFilter2 = operationFilter;
|
|
146
152
|
if (action === 'create') {
|
|
147
153
|
if (data) {
|
package/lib/types/Trigger.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ interface TriggerBase<ED extends EntityDict, T extends keyof ED> {
|
|
|
21
21
|
checkerType?: CheckerType;
|
|
22
22
|
entity: T;
|
|
23
23
|
name: string;
|
|
24
|
+
asRoot?: true;
|
|
24
25
|
priority?: number;
|
|
25
26
|
}
|
|
26
27
|
export interface CreateTriggerBase<ED extends EntityDict, T extends keyof ED, Cxt extends AsyncContext<ED> | SyncContext<ED>> extends TriggerBase<ED, T> {
|
package/lib/types/Watcher.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ReadOnlyAction } from "../actions/action";
|
|
1
2
|
import { AsyncContext } from "../store/AsyncRowStore";
|
|
2
3
|
import { EntityDict, OperationResult } from "./Entity";
|
|
3
4
|
type ActionData<ED extends EntityDict, T extends keyof ED> = ED[T]['Update']['data'] | ED[T]['Remove']['data'];
|
|
@@ -5,7 +6,7 @@ export interface BBWatcher<ED extends EntityDict, T extends keyof ED> {
|
|
|
5
6
|
name: string;
|
|
6
7
|
entity: T;
|
|
7
8
|
filter: ED[T]['Selection']['filter'] | (() => ED[T]['Selection']['filter']);
|
|
8
|
-
action: ED[T]['
|
|
9
|
+
action: Omit<ED[T]['Action'], 'create' | ReadOnlyAction>;
|
|
9
10
|
actionData: ActionData<ED, T> | (() => Promise<ActionData<ED, T>>);
|
|
10
11
|
}
|
|
11
12
|
export interface WBWatcher<ED extends EntityDict, T extends keyof ED, Cxt extends AsyncContext<ED>> {
|
|
@@ -2,3 +2,4 @@ import { EntityDict } from '../types/Entity';
|
|
|
2
2
|
import { EntityDict as BaseEntityDict } from '../base-app-domain';
|
|
3
3
|
import { StorageSchema } from '../types/Storage';
|
|
4
4
|
export declare function makeProjection<ED extends BaseEntityDict & EntityDict, T extends keyof ED>(entity: T, schema: StorageSchema<ED>): ED[T]["Selection"]["data"];
|
|
5
|
+
export declare function traverseProjection<ED extends BaseEntityDict & EntityDict, T extends keyof ED>(entity: T, schema: StorageSchema<ED>, projection: ED[T]['Selection']['data'], callback: <T2 extends keyof ED>(entity2: T2, projection2: ED[T2]['Selection']['data']) => void): void;
|
package/lib/utils/projection.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.makeProjection = void 0;
|
|
3
|
+
exports.traverseProjection = exports.makeProjection = void 0;
|
|
4
4
|
const Entity_1 = require("../types/Entity");
|
|
5
|
+
const relation_1 = require("../store/relation");
|
|
5
6
|
function makeProjection(entity, schema) {
|
|
6
7
|
const { attributes } = schema[entity];
|
|
7
8
|
const attrs = Object.keys(attributes);
|
|
@@ -13,3 +14,22 @@ function makeProjection(entity, schema) {
|
|
|
13
14
|
return projection;
|
|
14
15
|
}
|
|
15
16
|
exports.makeProjection = makeProjection;
|
|
17
|
+
function traverseProjection(entity, schema, projection, callback) {
|
|
18
|
+
const access = (entity2, proj) => {
|
|
19
|
+
callback(entity2, proj);
|
|
20
|
+
for (const attr in proj) {
|
|
21
|
+
const rel = (0, relation_1.judgeRelation)(schema, entity2, attr);
|
|
22
|
+
if (rel === 2) {
|
|
23
|
+
access(attr, proj[attr]);
|
|
24
|
+
}
|
|
25
|
+
else if (typeof rel === 'string') {
|
|
26
|
+
access(rel, proj[attr]);
|
|
27
|
+
}
|
|
28
|
+
else if (rel instanceof Array) {
|
|
29
|
+
access(rel[0], proj[attr].data);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
access(entity, projection);
|
|
34
|
+
}
|
|
35
|
+
exports.traverseProjection = traverseProjection;
|