oak-domain 5.1.7 → 5.1.8
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/schemalBuilder.js +63 -55
- package/lib/entities/I18n.js +1 -1
- package/lib/store/IntrinsicCheckers.js +1 -0
- package/lib/store/TriggerExecutor.js +9 -6
- package/lib/store/triggers.js +11 -27
- package/lib/types/Connector.d.ts +1 -0
- package/lib/types/Exception.d.ts +3 -1
- package/lib/types/Exception.js +11 -3
- package/lib/utils/SimpleConnector.d.ts +6 -2
- package/lib/utils/SimpleConnector.js +7 -0
- package/package.json +1 -1
- package/src/entities/I18n.ts +1 -1
|
@@ -173,7 +173,8 @@ function checkActionDefNameConsistent(filename, actionDefNode) {
|
|
|
173
173
|
const adfName = name.text.slice(0, name.text.length - 9);
|
|
174
174
|
const aName = actionNode.typeName.text.slice(0, actionNode.typeName.text.length - 6);
|
|
175
175
|
const sName = stateNode.typeName.text.slice(0, stateNode.typeName.text.length - 5);
|
|
176
|
-
(0, assert_1.default)(adfName === aName && aName === sName, `文件${filename}中的ActionDef${name.text}中ActionDef, Action和State
|
|
176
|
+
(0, assert_1.default)(adfName === aName && aName === sName, `文件${filename}中的ActionDef${name.text}中ActionDef, Action和State的命名规则不一致, 需要
|
|
177
|
+
${adfName}ActionDef, ${adfName}Action, ${adfName}State`);
|
|
177
178
|
}
|
|
178
179
|
function checkStringLiteralLegal(filename, obj, text, ele) {
|
|
179
180
|
(0, assert_1.default)(ts.isLiteralTypeNode(ele) && ts.isStringLiteral(ele.literal), `${filename}中引用的${obj} ${text}中存在不是stringliteral的类型`);
|
|
@@ -279,7 +280,7 @@ function tryGetStringLiteralValues(moduleName, filename, obj, node, program) {
|
|
|
279
280
|
}).filter(ele => !!ele));
|
|
280
281
|
}
|
|
281
282
|
if (['state', 'action'].includes(obj)) {
|
|
282
|
-
(0, assert_1.default)(values.length > 0);
|
|
283
|
+
(0, assert_1.default)(values.length > 0, `${filename}中的${obj} ${node.typeName.getText()}未定义`);
|
|
283
284
|
const importDeclartion = declaration.parent.parent.parent;
|
|
284
285
|
(0, assert_1.default)(ts.isImportDeclaration(importDeclartion));
|
|
285
286
|
addImportedFrom(moduleName, declaration.name.text, importDeclartion);
|
|
@@ -572,54 +573,54 @@ function analyzeImportDeclaration(node, referencedSchemas, additionalImports, fi
|
|
|
572
573
|
* @param filename
|
|
573
574
|
* @returns
|
|
574
575
|
*/
|
|
575
|
-
function getImportedFilePath(path, fileSpecifierPath, filename) {
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
}
|
|
576
|
+
// function getImportedFilePath(path: string, fileSpecifierPath: string, filename: string) {
|
|
577
|
+
// let importedFilepath = '';
|
|
578
|
+
// const getExistedFileName = () => {
|
|
579
|
+
// if (existsSync(`${importedFilepath}.ts`)) {
|
|
580
|
+
// return `${importedFilepath}.ts`;
|
|
581
|
+
// }
|
|
582
|
+
// else if (existsSync(`${importedFilepath}.d.ts`)) {
|
|
583
|
+
// return `${importedFilepath}.d.ts`;
|
|
584
|
+
// }
|
|
585
|
+
// return '';
|
|
586
|
+
// };
|
|
587
|
+
// if (fileSpecifierPath.startsWith('.')) {
|
|
588
|
+
// importedFilepath = PathLib.join(path, fileSpecifierPath);
|
|
589
|
+
// const importedFilename = getExistedFileName();
|
|
590
|
+
// assert(importedFilename, `「${filename}」中import路径${fileSpecifierPath}找不到对应的声明`);
|
|
591
|
+
// return importedFilename;
|
|
592
|
+
// }
|
|
593
|
+
// else {
|
|
594
|
+
// const cwd = process.cwd();
|
|
595
|
+
// const fileSpecifierPaths = fileSpecifierPath.split('/');
|
|
596
|
+
// const moduleName = fileSpecifierPaths[0] || fileSpecifierPaths[1];
|
|
597
|
+
// assert(moduleName);
|
|
598
|
+
// // 从path向外找package.json -> node_modules直至找到fileSpecifier
|
|
599
|
+
// const paths = path.split('/');
|
|
600
|
+
// for (let iter = paths.length; iter >= 0; iter--) {
|
|
601
|
+
// const paths2 = paths.slice(0, iter);
|
|
602
|
+
// const pkgJsonPath = PathLib.join(cwd, ...paths2, 'package.json');
|
|
603
|
+
// if (existsSync(pkgJsonPath)) {
|
|
604
|
+
// const pkgJson = require(pkgJsonPath);
|
|
605
|
+
// if (pkgJson.dependencies?.hasOwnProperty(moduleName)) {
|
|
606
|
+
// const dependentPath = pkgJson.dependencies[moduleName] as string;
|
|
607
|
+
// if (dependentPath.trimStart().startsWith('file:')) {
|
|
608
|
+
// const dependentFilePath = dependentPath.trimStart().slice(5);
|
|
609
|
+
// importedFilepath = PathLib.join(pkgJsonPath, '..', dependentFilePath, ...(fileSpecifierPaths[0] ? fileSpecifierPaths.slice(1) : (fileSpecifierPaths.slice(2))));
|
|
610
|
+
// }
|
|
611
|
+
// else {
|
|
612
|
+
// importedFilepath = PathLib.join(pkgJsonPath, '..', 'node_modules', fileSpecifierPath);
|
|
613
|
+
// }
|
|
614
|
+
// const importedFilename = getExistedFileName();
|
|
615
|
+
// if (importedFilename) {
|
|
616
|
+
// return importedFilename;
|
|
617
|
+
// }
|
|
618
|
+
// }
|
|
619
|
+
// }
|
|
620
|
+
// }
|
|
621
|
+
// }
|
|
622
|
+
// assert(false, `「${filename}」中import路径${fileSpecifierPath}找不到对应的声明`);
|
|
623
|
+
// }
|
|
623
624
|
function analyzeSchemaDefinition(node, moduleName, filename, path, program, referencedSchemas, schemaAttrs, enumAttributes, importAttrFrom, relativePath) {
|
|
624
625
|
let hasEntityAttr = false;
|
|
625
626
|
let hasEntityIdAttr = false;
|
|
@@ -647,10 +648,17 @@ function analyzeSchemaDefinition(node, moduleName, filename, path, program, refe
|
|
|
647
648
|
(0, assert_1.default)(ts.isStringLiteral(moduleSpecifier));
|
|
648
649
|
const { text: from } = moduleSpecifier;
|
|
649
650
|
extendsFrom.push(from);
|
|
650
|
-
|
|
651
|
-
const
|
|
652
|
-
|
|
653
|
-
const
|
|
651
|
+
// 创建编译器主机
|
|
652
|
+
const compilerHost = ts.createCompilerHost(program.getCompilerOptions());
|
|
653
|
+
// 解析模块
|
|
654
|
+
const resolvedModule = ts.resolveModuleName(from, filename, program.getCompilerOptions(), compilerHost);
|
|
655
|
+
(0, assert_1.default)(resolvedModule.resolvedModule, "找不到module定义");
|
|
656
|
+
const resolvedFileName = resolvedModule.resolvedModule.resolvedFileName;
|
|
657
|
+
const sourceFile = program.getSourceFile(resolvedFileName);
|
|
658
|
+
// const importedFilename = getImportedFilePath(path, from, filename);
|
|
659
|
+
// const sourceFile = program.getSourceFile(importedFilename);
|
|
660
|
+
(0, assert_1.default)(sourceFile, `「${filename}」找不到相应的sourceFile:${resolvedFileName}`);
|
|
661
|
+
const relativeFilename = path_1.default.relative(process.cwd(), resolvedFileName);
|
|
654
662
|
const result = analyzeReferenceSchemaFile(moduleName, path_1.default.basename(relativeFilename), path_1.default.dirname(relativeFilename), sourceFile, program, referencedSchemas, schemaAttrs, enumAttributes, importAttrFrom, path_1.default.join(from, '..'));
|
|
655
663
|
return result;
|
|
656
664
|
}).filter(ele => !!ele);
|
|
@@ -3458,7 +3466,7 @@ function outputLocale(outputDir, printer) {
|
|
|
3458
3466
|
]), sourceFile);
|
|
3459
3467
|
const data = Function(result)();
|
|
3460
3468
|
const filename = path_1.default.join(outputDir, entity, 'locales', `${lng}.json`);
|
|
3461
|
-
(0, fs_1.writeFileSync)(filename, JSON.stringify(data), { flag: 'w' });
|
|
3469
|
+
(0, fs_1.writeFileSync)(filename, JSON.stringify(data, null, 2), { flag: 'w' });
|
|
3462
3470
|
if (locales[lng]) {
|
|
3463
3471
|
locales[lng].push(entity);
|
|
3464
3472
|
}
|
package/lib/entities/I18n.js
CHANGED
|
@@ -331,6 +331,7 @@ function createAttrUpdateCheckers(schema, attrUpdateMatrix) {
|
|
|
331
331
|
const actions = condition.map(ele => ele?.actions).filter(ele => !!ele);
|
|
332
332
|
const a = actions.length > 0 && (0, lodash_1.intersection)(actions.flat());
|
|
333
333
|
if (a) {
|
|
334
|
+
(0, assert_1.default)(action);
|
|
334
335
|
if (!a.includes(action)) {
|
|
335
336
|
// 找到不满足的那个attr
|
|
336
337
|
const attrsIllegal = attrs.filter((attr) => matrix[attr]?.actions && !matrix[attr]?.actions?.includes(action));
|
|
@@ -253,10 +253,13 @@ class TriggerExecutor {
|
|
|
253
253
|
cxtStr2 = data.$$triggerData$$?.cxtStr;
|
|
254
254
|
}
|
|
255
255
|
const record = opRecords.find(ele => ele.id === operation.id);
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
256
|
+
if (record) {
|
|
257
|
+
// 目前框架在operation时,一定会将ids记录在operation当中(见CascadeStore中的doUpdateSingleRowAsync函数
|
|
258
|
+
// 但也有一种可能,此operation没有更新任何一行。by Xc 20241022
|
|
259
|
+
(0, assert_1.default)(record.a !== 'c');
|
|
260
|
+
const { f } = record;
|
|
261
|
+
ids = f.id.$in;
|
|
262
|
+
}
|
|
260
263
|
}
|
|
261
264
|
// 此时项目的上下文,和执行此trigger时的上下文可能不一致(rootMode),采用当时的上下文cxtStr来执行
|
|
262
265
|
this.onVolatileTrigger(entity, trigger, ids, cxtStr2, option);
|
|
@@ -348,12 +351,12 @@ class TriggerExecutor {
|
|
|
348
351
|
async execVolatileTrigger(entity, name, ids, context, option) {
|
|
349
352
|
const trigger = this.triggerNameMap[name];
|
|
350
353
|
(0, assert_1.default)(trigger && trigger.when === 'commit');
|
|
351
|
-
|
|
354
|
+
// assert(ids.length > 0);
|
|
352
355
|
const { fn } = trigger;
|
|
353
356
|
const closeRoot = trigger.asRoot && context.openRootMode();
|
|
354
357
|
try {
|
|
355
358
|
const callback = await fn({ ids }, context, option);
|
|
356
|
-
if (trigger.strict === 'makeSure') {
|
|
359
|
+
if (trigger.strict === 'makeSure' && ids.length) {
|
|
357
360
|
// 这里开root模式,否则还可能有权限问题
|
|
358
361
|
const closeRoot2 = context.openRootMode();
|
|
359
362
|
try {
|
package/lib/store/triggers.js
CHANGED
|
@@ -362,41 +362,25 @@ exports.logTriggers = [
|
|
|
362
362
|
return (result.oper?.remove || 0) + (result2.log?.remove || 0);
|
|
363
363
|
}
|
|
364
364
|
},
|
|
365
|
-
// 在删除log
|
|
365
|
+
// 在删除log时,删除与此log关联的oper
|
|
366
366
|
{
|
|
367
|
-
name: '当删除log
|
|
367
|
+
name: '当删除log时,删除与此log关联的oper',
|
|
368
368
|
entity: 'log',
|
|
369
369
|
action: 'remove',
|
|
370
370
|
when: 'before',
|
|
371
371
|
fn: async ({ operation }, context) => {
|
|
372
372
|
const { filter } = operation;
|
|
373
373
|
(0, assert_1.default)(filter);
|
|
374
|
-
// 查询这次删除操作涉及到的所有log
|
|
375
|
-
const
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
},
|
|
383
|
-
},
|
|
384
|
-
},
|
|
385
|
-
filter,
|
|
374
|
+
// 查询这次删除操作涉及到的所有log
|
|
375
|
+
const result = await context.operate('oper', {
|
|
376
|
+
id: "dummy",
|
|
377
|
+
action: 'remove',
|
|
378
|
+
data: {},
|
|
379
|
+
filter: {
|
|
380
|
+
log: filter,
|
|
381
|
+
}
|
|
386
382
|
}, {});
|
|
387
|
-
|
|
388
|
-
let result = 0;
|
|
389
|
-
for (const operId of operIds) {
|
|
390
|
-
const result2 = await context.operate('oper', {
|
|
391
|
-
id: operId,
|
|
392
|
-
action: 'update',
|
|
393
|
-
data: {
|
|
394
|
-
logId: null,
|
|
395
|
-
},
|
|
396
|
-
}, {});
|
|
397
|
-
result += result2.oper?.update || 0;
|
|
398
|
-
}
|
|
399
|
-
return result;
|
|
383
|
+
return result.oper?.remove || 0;
|
|
400
384
|
}
|
|
401
385
|
},
|
|
402
386
|
];
|
package/lib/types/Connector.d.ts
CHANGED
package/lib/types/Exception.d.ts
CHANGED
|
@@ -72,6 +72,8 @@ export declare class OakNetworkException<ED extends EntityDict & BaseEntityDict>
|
|
|
72
72
|
}
|
|
73
73
|
export declare class OakServerProxyException<ED extends EntityDict & BaseEntityDict> extends OakException<ED> {
|
|
74
74
|
}
|
|
75
|
+
export declare class OakClockDriftException<ED extends EntityDict & BaseEntityDict> extends OakException<ED> {
|
|
76
|
+
}
|
|
75
77
|
/**
|
|
76
78
|
* 数据不一致异常,系统认为现有的数据不允许相应的动作时抛此异常
|
|
77
79
|
*
|
|
@@ -128,7 +130,7 @@ export declare class OakUnloggedInException<ED extends EntityDict & BaseEntityDi
|
|
|
128
130
|
constructor(message?: string);
|
|
129
131
|
}
|
|
130
132
|
/**
|
|
131
|
-
*
|
|
133
|
+
* 行数据被锁抛的异常
|
|
132
134
|
*/
|
|
133
135
|
export declare class OakRowLockedException<ED extends EntityDict & BaseEntityDict> extends OakUserException<ED> {
|
|
134
136
|
constructor(message?: string);
|
package/lib/types/Exception.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.makeException = exports.OakSocketConnectException = exports.OakExternalException = exports.OakPreConditionUnsetException = exports.OakDeadlock = exports.OakCongruentRowExists = exports.OakRowLockedException = exports.OakUnloggedInException = exports.OakUserInvisibleException = exports.OakUserUnpermittedException = exports.OakAttrCantUpdateException = exports.OakAttrNotNullException = exports.OakInputIllegalException = exports.OakRowInconsistencyException = exports.OakServerProxyException = exports.OakNetworkException = exports.OakImportDataParseException = exports.OakUniqueViolationException = exports.OakUserException = exports.OakRowUnexistedException = exports.OakOperExistedException = exports.OakNoRelationDefException = exports.OakDataException = exports.OakPartialSuccess = exports.OakMakeSureByMySelfException = exports.OakException = void 0;
|
|
3
|
+
exports.makeException = exports.OakSocketConnectException = exports.OakExternalException = exports.OakPreConditionUnsetException = exports.OakDeadlock = exports.OakCongruentRowExists = exports.OakRowLockedException = exports.OakUnloggedInException = exports.OakUserInvisibleException = exports.OakUserUnpermittedException = exports.OakAttrCantUpdateException = exports.OakAttrNotNullException = exports.OakInputIllegalException = exports.OakRowInconsistencyException = exports.OakClockDriftException = exports.OakServerProxyException = exports.OakNetworkException = exports.OakImportDataParseException = exports.OakUniqueViolationException = exports.OakUserException = exports.OakRowUnexistedException = exports.OakOperExistedException = exports.OakNoRelationDefException = exports.OakDataException = exports.OakPartialSuccess = exports.OakMakeSureByMySelfException = exports.OakException = void 0;
|
|
4
4
|
const relation_1 = require("../store/relation");
|
|
5
5
|
const lodash_1 = require("../utils/lodash");
|
|
6
6
|
class OakException extends Error {
|
|
@@ -173,10 +173,14 @@ exports.OakImportDataParseException = OakImportDataParseException;
|
|
|
173
173
|
class OakNetworkException extends OakException {
|
|
174
174
|
}
|
|
175
175
|
exports.OakNetworkException = OakNetworkException;
|
|
176
|
-
//
|
|
176
|
+
// 请求未到达应用服务程序
|
|
177
177
|
class OakServerProxyException extends OakException {
|
|
178
178
|
}
|
|
179
179
|
exports.OakServerProxyException = OakServerProxyException;
|
|
180
|
+
// 时钟漂移过久(重放攻击)
|
|
181
|
+
class OakClockDriftException extends OakException {
|
|
182
|
+
}
|
|
183
|
+
exports.OakClockDriftException = OakClockDriftException;
|
|
180
184
|
// 在系统更新数据时,以下三个异常应按规范依次抛出。
|
|
181
185
|
/**
|
|
182
186
|
* 数据不一致异常,系统认为现有的数据不允许相应的动作时抛此异常
|
|
@@ -294,7 +298,7 @@ class OakUnloggedInException extends OakUserException {
|
|
|
294
298
|
exports.OakUnloggedInException = OakUnloggedInException;
|
|
295
299
|
;
|
|
296
300
|
/**
|
|
297
|
-
*
|
|
301
|
+
* 行数据被锁抛的异常
|
|
298
302
|
*/
|
|
299
303
|
class OakRowLockedException extends OakUserException {
|
|
300
304
|
constructor(message) {
|
|
@@ -479,6 +483,10 @@ function makeException(data) {
|
|
|
479
483
|
e = new OakNetworkException(data.message);
|
|
480
484
|
break;
|
|
481
485
|
}
|
|
486
|
+
case 'OakClockDriftException': {
|
|
487
|
+
e = new OakClockDriftException(data.message);
|
|
488
|
+
break;
|
|
489
|
+
}
|
|
482
490
|
case 'OakServerProxyException': {
|
|
483
491
|
e = new OakServerProxyException(data.message);
|
|
484
492
|
break;
|
|
@@ -17,11 +17,15 @@ export default class SimpleConnector<ED extends EntityDict & BaseEntityDict, Fro
|
|
|
17
17
|
private configuration;
|
|
18
18
|
private makeException;
|
|
19
19
|
constructor(configuration: AccessConfiguration, makeException: (exceptionData: any) => OakException<ED>);
|
|
20
|
+
getCorsHeader(): string[];
|
|
20
21
|
protected makeHeadersAndBody(name: string, data: any, context?: FrontCxt): Promise<{
|
|
21
|
-
headers:
|
|
22
|
+
headers: {
|
|
23
|
+
'oak-cxt': string;
|
|
24
|
+
'oak-aspect': string;
|
|
25
|
+
};
|
|
22
26
|
body: FormData;
|
|
23
27
|
} | {
|
|
24
|
-
headers:
|
|
28
|
+
headers: Record<string, string>;
|
|
25
29
|
body: string;
|
|
26
30
|
}>;
|
|
27
31
|
protected parseAspectResult(response: Response): Promise<{
|
|
@@ -41,6 +41,12 @@ class SimpleConnector {
|
|
|
41
41
|
SimpleConnector.SUBSCRIBE_POINT_ROUTER}`;
|
|
42
42
|
this.makeException = makeException;
|
|
43
43
|
}
|
|
44
|
+
getCorsHeader() {
|
|
45
|
+
return [
|
|
46
|
+
'oak-cxt',
|
|
47
|
+
'oak-aspect'
|
|
48
|
+
];
|
|
49
|
+
}
|
|
44
50
|
async makeHeadersAndBody(name, data, context) {
|
|
45
51
|
const cxtStr = context ? await context.toString() : '{}';
|
|
46
52
|
const headers = {
|
|
@@ -48,6 +54,7 @@ class SimpleConnector {
|
|
|
48
54
|
'oak-aspect': name,
|
|
49
55
|
};
|
|
50
56
|
if (process.env.OAK_PLATFORM !== 'wechatMp') {
|
|
57
|
+
// 小程序环境下没有FormData,跑到这里会挂
|
|
51
58
|
if (data instanceof FormData) {
|
|
52
59
|
return {
|
|
53
60
|
headers,
|
package/package.json
CHANGED