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.
@@ -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
- let importedFilepath = '';
577
- const getExistedFileName = () => {
578
- if ((0, fs_1.existsSync)(`${importedFilepath}.ts`)) {
579
- return `${importedFilepath}.ts`;
580
- }
581
- else if ((0, fs_1.existsSync)(`${importedFilepath}.d.ts`)) {
582
- return `${importedFilepath}.d.ts`;
583
- }
584
- return '';
585
- };
586
- if (fileSpecifierPath.startsWith('.')) {
587
- importedFilepath = path_1.default.join(path, fileSpecifierPath);
588
- const importedFilename = getExistedFileName();
589
- (0, assert_1.default)(importedFilename, `「${filename}」中import路径${fileSpecifierPath}找不到对应的声明`);
590
- return importedFilename;
591
- }
592
- else {
593
- const cwd = process.cwd();
594
- const fileSpecifierPaths = fileSpecifierPath.split('/');
595
- const moduleName = fileSpecifierPaths[0] || fileSpecifierPaths[1];
596
- (0, assert_1.default)(moduleName);
597
- // 从path向外找package.json -> node_modules直至找到fileSpecifier
598
- const paths = path.split('/');
599
- for (let iter = paths.length; iter >= 0; iter--) {
600
- const paths2 = paths.slice(0, iter);
601
- const pkgJsonPath = path_1.default.join(cwd, ...paths2, 'package.json');
602
- if ((0, fs_1.existsSync)(pkgJsonPath)) {
603
- const pkgJson = require(pkgJsonPath);
604
- if (pkgJson.dependencies?.hasOwnProperty(moduleName)) {
605
- const dependentPath = pkgJson.dependencies[moduleName];
606
- if (dependentPath.trimStart().startsWith('file:')) {
607
- const dependentFilePath = dependentPath.trimStart().slice(5);
608
- importedFilepath = path_1.default.join(pkgJsonPath, '..', dependentFilePath, ...(fileSpecifierPaths[0] ? fileSpecifierPaths.slice(1) : (fileSpecifierPaths.slice(2))));
609
- }
610
- else {
611
- importedFilepath = path_1.default.join(pkgJsonPath, '..', 'node_modules', fileSpecifierPath);
612
- }
613
- const importedFilename = getExistedFileName();
614
- if (importedFilename) {
615
- return importedFilename;
616
- }
617
- }
618
- }
619
- }
620
- }
621
- (0, assert_1.default)(false, `「${filename}」中import路径${fileSpecifierPath}找不到对应的声明`);
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
- const importedFilename = getImportedFilePath(path, from, filename);
651
- const sourceFile = program.getSourceFile(importedFilename);
652
- (0, assert_1.default)(sourceFile, `「${filename}」找不到相应的sourceFile:${importedFilename}`);
653
- const relativeFilename = path_1.default.relative(process.cwd(), importedFilename);
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
  }
@@ -4,7 +4,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
4
4
  const entityDesc = {
5
5
  locales: {
6
6
  zh_CN: {
7
- name: '用户授权',
7
+ name: 'i18n',
8
8
  attr: {
9
9
  module: '模块',
10
10
  position: '文件位置',
@@ -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
- // 目前框架在operation时,一定会将ids记录在operation当中(见CascadeStore中的doUpdateSingleRowAsync函数
257
- (0, assert_1.default)(record && record.a !== 'c');
258
- const { f } = record;
259
- ids = f.id.$in;
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
- (0, assert_1.default)(ids.length > 0);
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 {
@@ -362,41 +362,25 @@ exports.logTriggers = [
362
362
  return (result.oper?.remove || 0) + (result2.log?.remove || 0);
363
363
  }
364
364
  },
365
- // 在删除log时,解除与此log关联的oper
365
+ // 在删除log时,删除与此log关联的oper
366
366
  {
367
- name: '当删除log时,解除与此log关联的oper',
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 logs = await context.select('log', {
376
- data: {
377
- id: 1,
378
- oper$log: {
379
- $entity: 'oper',
380
- data: {
381
- id: 1,
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
- const operIds = logs.flatMap(log => log.oper$log.map(oper => oper.id));
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
  ];
@@ -42,4 +42,5 @@ export interface Connector<ED extends EntityDict & BaseEntityDict, FrontCxt exte
42
42
  getFullData: (keys?: (keyof ED)[]) => Promise<{
43
43
  [T in keyof ED]?: ED[T]['OpSchema'][];
44
44
  }>;
45
+ getCorsHeader: () => string[];
45
46
  }
@@ -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);
@@ -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: Record<string, string>;
22
+ headers: {
23
+ 'oak-cxt': string;
24
+ 'oak-aspect': string;
25
+ };
22
26
  body: FormData;
23
27
  } | {
24
- headers: HeadersInit;
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oak-domain",
3
- "version": "5.1.7",
3
+ "version": "5.1.8",
4
4
  "author": {
5
5
  "name": "XuChang"
6
6
  },
@@ -13,7 +13,7 @@ export interface Schema extends EntityShape {
13
13
  const entityDesc: EntityDesc<Schema> = {
14
14
  locales: {
15
15
  zh_CN: {
16
- name: '用户授权',
16
+ name: 'i18n',
17
17
  attr: {
18
18
  module: '模块',
19
19
  position: '文件位置',