libmodulor 0.23.0 → 0.24.0

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.
Files changed (70) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +154 -2
  3. package/dist/esm/apps/Helper/src/lib/project.js +3 -3
  4. package/dist/esm/apps/Helper/src/ucds/TestAppUCD.d.ts +2 -1
  5. package/dist/esm/apps/Helper/src/ucds/TestAppUCD.js +8 -0
  6. package/dist/esm/convention.d.ts +3 -0
  7. package/dist/esm/convention.js +3 -0
  8. package/dist/esm/dt/DataTypes.d.ts +1 -2
  9. package/dist/esm/dt/base/TObject.js +1 -1
  10. package/dist/esm/i18n/index.d.ts +1 -1
  11. package/dist/esm/i18n/locales/de.d.ts +2 -0
  12. package/dist/esm/i18n/locales/de.js +54 -0
  13. package/dist/esm/i18n/locales/es.d.ts +2 -0
  14. package/dist/esm/i18n/locales/es.js +54 -0
  15. package/dist/esm/i18n/types.d.ts +3 -2
  16. package/dist/esm/index.babel.d.ts +1 -0
  17. package/dist/esm/index.babel.js +1 -0
  18. package/dist/esm/index.node-stricli-cli.d.ts +2 -0
  19. package/dist/esm/index.node-stricli-cli.js +2 -0
  20. package/dist/esm/index.vite.d.ts +1 -1
  21. package/dist/esm/index.vite.js +1 -1
  22. package/dist/esm/index.webpack.d.ts +1 -0
  23. package/dist/esm/index.webpack.js +1 -0
  24. package/dist/esm/std/I18nManager.d.ts +12 -0
  25. package/dist/esm/std/impl/NodeFSManager.js +1 -1
  26. package/dist/esm/std/impl/SimpleMapI18nManager.d.ts +6 -1
  27. package/dist/esm/std/impl/SimpleMapI18nManager.js +41 -12
  28. package/dist/esm/target/lib/server/AuthenticationChecker.js +1 -1
  29. package/dist/esm/target/lib/server/PublicApiKeyChecker.js +1 -1
  30. package/dist/esm/target/lib/server/ServerRequestHandler.js +2 -2
  31. package/dist/esm/target/lib/server-express/funcs.js +2 -2
  32. package/dist/esm/target/lib/server-hono/funcs.js +2 -2
  33. package/dist/esm/target/lib/server-node/funcs.js +1 -1
  34. package/dist/esm/target/node-stricli-cli/NodeStricliCLIManager.d.ts +12 -0
  35. package/dist/esm/target/node-stricli-cli/NodeStricliCLIManager.js +118 -0
  36. package/dist/esm/testing/AppTester.js +4 -5
  37. package/dist/esm/testing/UCDefASTParser.d.ts +24 -6
  38. package/dist/esm/testing/impl/SimpleAppDocsEmitter.js +4 -5
  39. package/dist/esm/testing/impl/TypeScriptLibUCDefASTParser.js +38 -11
  40. package/dist/esm/testing/impl/VitestAppTestSuiteRunner.d.ts +1 -1
  41. package/dist/esm/testing/impl/VitestAppTestSuiteRunner.js +17 -2
  42. package/dist/esm/testing/opts.js +1 -1
  43. package/dist/esm/testing/workers/AppTestSuiteRunner.d.ts +2 -0
  44. package/dist/esm/testing/workers/UCExecutor.js +1 -1
  45. package/dist/esm/testing/workers/checkers/AppI18nChecker.d.ts +8 -2
  46. package/dist/esm/testing/workers/checkers/AppI18nChecker.js +44 -2
  47. package/dist/esm/testing/workers/checkers/UCDefSourcesChecker.js +12 -12
  48. package/dist/esm/uc/impl/HTTPUCTransporter.js +2 -2
  49. package/dist/esm/uc/impl/KnexUCDataStore.js +2 -2
  50. package/dist/esm/uc/index.d.ts +0 -1
  51. package/dist/esm/uc/index.js +0 -1
  52. package/dist/esm/uc/workers/UCExecChecker.js +1 -1
  53. package/dist/esm/utils/bundling/babel/plugin.d.ts +2 -0
  54. package/dist/esm/utils/bundling/babel/plugin.js +38 -0
  55. package/dist/esm/utils/bundling/funcs.d.ts +6 -0
  56. package/dist/esm/utils/bundling/funcs.js +20 -0
  57. package/dist/esm/utils/bundling/typescript.d.ts +3 -0
  58. package/dist/esm/utils/bundling/typescript.js +61 -0
  59. package/dist/esm/utils/bundling/vite/plugin.d.ts +6 -0
  60. package/dist/esm/utils/bundling/vite/plugin.js +17 -0
  61. package/dist/esm/utils/bundling/webpack/loader.d.ts +2 -0
  62. package/dist/esm/utils/bundling/webpack/loader.js +12 -0
  63. package/dist/esm/utils/http/HTTPRequestBuilder.js +1 -1
  64. package/dist/esm/utils/ioc/bindCommon.js +1 -1
  65. package/dist/esm/utils/terminal/fmt.js +1 -1
  66. package/package.json +30 -8
  67. package/pnpm-workspace.yaml +1 -4
  68. package/tsconfig.build.examples.json +8 -0
  69. package/tsconfig.json +1 -0
  70. package/vitest.config.ts +16 -0
@@ -38,7 +38,7 @@ export function buildHandler(appManifest, ucd, contract, serverRequestHandler, u
38
38
  break;
39
39
  }
40
40
  default:
41
- ((_) => { })(transportType);
41
+ transportType;
42
42
  }
43
43
  const { body, status } = await serverRequestHandler.exec({
44
44
  appManifest,
@@ -67,7 +67,7 @@ export function buildHandler(appManifest, ucd, contract, serverRequestHandler, u
67
67
  return;
68
68
  }
69
69
  default:
70
- ((_) => { })(transportType);
70
+ transportType;
71
71
  }
72
72
  };
73
73
  return handler;
@@ -51,7 +51,7 @@ export function buildHandler(appManifest, ucd, contract, serverRequestHandler, u
51
51
  break;
52
52
  }
53
53
  default:
54
- ((_) => { })(transportType);
54
+ transportType;
55
55
  }
56
56
  const { body, status } = await serverRequestHandler.exec({
57
57
  appManifest,
@@ -80,7 +80,7 @@ export function buildHandler(appManifest, ucd, contract, serverRequestHandler, u
80
80
  });
81
81
  }
82
82
  default:
83
- ((_) => { })(transportType);
83
+ transportType;
84
84
  }
85
85
  return c.json(body, status);
86
86
  };
@@ -23,7 +23,7 @@ export async function stop(server, settingsManager) {
23
23
  case 'patient':
24
24
  break;
25
25
  default:
26
- ((_) => { })(mode);
26
+ mode;
27
27
  }
28
28
  server.close((err) => {
29
29
  if (err) {
@@ -0,0 +1,12 @@
1
+ import { WordingManager } from '../../i18n/index.js';
2
+ import { type ProductManifest, ProductUCsLoader } from '../../product/index.js';
3
+ import type { CLIManager, Input, Output } from '../lib/cli/CLIManager.js';
4
+ import { CommandExecutor } from '../lib/cli/CommandExecutor.js';
5
+ export declare class NodeStricliCLIManager implements CLIManager {
6
+ private commandExecutor;
7
+ private productManifest;
8
+ private productUCsLoader;
9
+ private wordingManager;
10
+ constructor(commandExecutor: CommandExecutor, productManifest: ProductManifest, productUCsLoader: ProductUCsLoader, wordingManager: WordingManager);
11
+ handleCommand({ appsRootPath, srcImporter, }: Input): Promise<Output>;
12
+ }
@@ -0,0 +1,118 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
+ return function (target, key) { decorator(target, key, paramIndex); }
12
+ };
13
+ import { buildApplication, buildCommand, buildRouteMap, run, } from '@stricli/core';
14
+ import { inject, injectable } from 'inversify';
15
+ import { WordingManager } from '../../i18n/index.js';
16
+ import { ProductUCsLoader } from '../../product/index.js';
17
+ import { ucifHint, ucifIsMandatory, ucifRepeatability, ucMountingPoint, } from '../../uc/index.js';
18
+ import { CommandExecutor } from '../lib/cli/CommandExecutor.js';
19
+ let NodeStricliCLIManager = class NodeStricliCLIManager {
20
+ commandExecutor;
21
+ productManifest;
22
+ productUCsLoader;
23
+ wordingManager;
24
+ constructor(commandExecutor, productManifest, productUCsLoader, wordingManager) {
25
+ this.commandExecutor = commandExecutor;
26
+ this.productManifest = productManifest;
27
+ this.productUCsLoader = productUCsLoader;
28
+ this.wordingManager = wordingManager;
29
+ }
30
+ async handleCommand({ appsRootPath, srcImporter, }) {
31
+ const ucs = await this.productUCsLoader.exec({
32
+ appsRootPath,
33
+ srcImporter,
34
+ });
35
+ const routes = {};
36
+ for (const uc of ucs) {
37
+ const mountingPoint = uc.def.ext?.cmd?.mountAt ?? ucMountingPoint(uc);
38
+ routes[mountingPoint] = buildCommand({
39
+ docs: {
40
+ brief: this.wordingManager.uc(uc.def).desc ?? '',
41
+ },
42
+ func: async (flags) => {
43
+ uc.fill(flags);
44
+ await this.commandExecutor.exec({ uc });
45
+ },
46
+ parameters: {
47
+ flags: {},
48
+ },
49
+ });
50
+ const { flags } = routes[mountingPoint].parameters;
51
+ if (!flags) {
52
+ throw new Error('Init the flags first');
53
+ }
54
+ for (const f of this.commandExecutor.fieldsForFlags(uc)) {
55
+ const { def } = f;
56
+ const { desc, label } = this.wordingManager.ucif(f);
57
+ const brief = desc ?? label;
58
+ const defaultValue = def.type.getDefaultValue();
59
+ const [isRepeatable, _max] = ucifRepeatability(def);
60
+ const options = def.type.getOptions();
61
+ const hasOptions = options && options.length > 0;
62
+ const hint = ucifHint(def);
63
+ const common = {
64
+ brief,
65
+ default: defaultValue,
66
+ optional: !ucifIsMandatory(def),
67
+ placeholder: hint ?? '',
68
+ variadic: isRepeatable,
69
+ };
70
+ if (hasOptions) {
71
+ flags[f.key] = {
72
+ ...common,
73
+ kind: 'enum',
74
+ values: options?.map((o) => o.value),
75
+ };
76
+ }
77
+ else {
78
+ flags[f.key] = {
79
+ ...common,
80
+ kind: 'parsed',
81
+ parse: (raw) => {
82
+ def.type.assign(raw);
83
+ const val = def.type.val();
84
+ def.type.clear();
85
+ return val;
86
+ },
87
+ };
88
+ }
89
+ }
90
+ }
91
+ const { desc, slogan } = this.wordingManager.p();
92
+ const root = buildRouteMap({
93
+ docs: {
94
+ brief: desc ?? slogan ?? '',
95
+ },
96
+ routes,
97
+ });
98
+ const app = buildApplication(root, {
99
+ name: this.productManifest.name,
100
+ versionInfo: {
101
+ currentVersion: await this.commandExecutor.version(),
102
+ },
103
+ });
104
+ await run(app, process.argv.slice(2), {
105
+ process: process,
106
+ });
107
+ }
108
+ };
109
+ NodeStricliCLIManager = __decorate([
110
+ injectable(),
111
+ __param(0, inject(CommandExecutor)),
112
+ __param(1, inject('ProductManifest')),
113
+ __param(2, inject(ProductUCsLoader)),
114
+ __param(3, inject(WordingManager)),
115
+ __metadata("design:paramtypes", [CommandExecutor, Object, ProductUCsLoader,
116
+ WordingManager])
117
+ ], NodeStricliCLIManager);
118
+ export { NodeStricliCLIManager };
@@ -12,7 +12,6 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
12
  };
13
13
  import { inject, injectable } from 'inversify';
14
14
  import { I18nEN } from '../i18n/locales/en.js';
15
- import { I18nFR } from '../i18n/locales/fr.js';
16
15
  import { FAKE_USER_ADMIN, UCBuilder, ucHTTPContract, } from '../uc/index.js';
17
16
  // We inject directly the implementation because we'll generate all the reports and not only the one that is bound to the interface.
18
17
  // We can plan a setting à la Vitest where we specify the types of reports to generate though.
@@ -88,9 +87,13 @@ let AppTester = class AppTester {
88
87
  }
89
88
  }
90
89
  async checkAppI18n() {
90
+ if (!this.ucDefSourcesCheckerOutput) {
91
+ throw new Error('checkUCDSources must be called before checkAppI18n');
92
+ }
91
93
  const { errors } = await this.appI18nChecker.exec({
92
94
  appI18n: this.ctx.appI18n,
93
95
  appManifest: this.ctx.appManifest,
96
+ ucDefSourcesCheckerOutput: this.ucDefSourcesCheckerOutput,
94
97
  });
95
98
  if (errors.length > 0) {
96
99
  throw new Error(errors[0]);
@@ -302,15 +305,11 @@ let AppTester = class AppTester {
302
305
  const appLangCodes = Object.keys(appI18n);
303
306
  const coreI18n = {
304
307
  en: I18nEN,
305
- fr: I18nFR,
306
308
  };
307
309
  const productI18n = {
308
310
  en: {
309
311
  ...I18nEN,
310
312
  },
311
- fr: {
312
- ...I18nFR,
313
- },
314
313
  };
315
314
  for (const l of appLangCodes) {
316
315
  if (!(l in coreI18n)) {
@@ -1,21 +1,39 @@
1
1
  import type { ErrorMessage, FilePath } from '../dt/index.js';
2
2
  import type { UCDefLifecycle, UCMetadata, UCOutputPartIdx } from '../uc/index.js';
3
3
  import type { AppTesterOptsAllSet } from './opts.js';
4
- export interface OutputItemField<T extends string = string> {
4
+ export interface OutputItemField<T = string> {
5
5
  err: ErrorMessage | null;
6
6
  value: T;
7
7
  }
8
+ export type OutputItemFieldIOField = OutputItemField<{
9
+ /**
10
+ * @example `FreeTextShort`
11
+ */
12
+ dataType: string | null;
13
+ /**
14
+ * @example `name`
15
+ */
16
+ name: string | null;
17
+ /**
18
+ * @example `name: UCInputField<FreeTextShort>`
19
+ */
20
+ raw: string | null;
21
+ /**
22
+ * @example `UCInputField<FreeTextShort>`
23
+ */
24
+ type: string | null;
25
+ }>;
8
26
  export interface OutputItem {
9
27
  constName: OutputItemField | null;
10
28
  externalImports: OutputItemField[] | null;
11
29
  filePath: OutputItemField | null;
12
30
  internalImports: OutputItemField[] | null;
13
31
  ioI: OutputItemField | null;
14
- ioIFields: OutputItemField[] | null;
32
+ ioIFields: OutputItemFieldIOField[] | null;
15
33
  ioOPI0: OutputItemField | null;
16
- ioOPI0Fields: OutputItemField[] | null;
34
+ ioOPI0Fields: OutputItemFieldIOField[] | null;
17
35
  ioOPI1: OutputItemField | null;
18
- ioOPI1Fields: OutputItemField[] | null;
36
+ ioOPI1Fields: OutputItemFieldIOField[] | null;
19
37
  lifecycleClientPolicy: OutputItemField | null;
20
38
  lifecycleClientSteps: OutputItemField[] | null;
21
39
  lifecycleServerPolicy: OutputItemField | null;
@@ -29,10 +47,10 @@ export interface OutputItem {
29
47
  }
30
48
  export declare const OUTPUT_ITEM_FIELDS: (keyof OutputItem)[];
31
49
  export type OnImport = (name: string) => void;
32
- export type OnInputType = (name: string, fields: OutputItemField[]) => void;
50
+ export type OnInputType = (name: string, fields: OutputItemFieldIOField[]) => void;
33
51
  export type OnMainStep = (lifecycle: UCDefLifecycle, step: string) => void;
34
52
  export type OnMetadata = (metadata: UCMetadata) => void;
35
- export type OnOPIType = (name: string, fields: OutputItemField[], idx: UCOutputPartIdx) => void;
53
+ export type OnOPIType = (name: string, fields: OutputItemFieldIOField[], idx: UCOutputPartIdx) => void;
36
54
  export type OnPolicy = (lifecycle: UCDefLifecycle, name: string) => void;
37
55
  export type OnVariable = (name: string) => void;
38
56
  export interface UCDefASTParser {
@@ -11,7 +11,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
11
  return function (target, key) { decorator(target, key, paramIndex); }
12
12
  };
13
13
  import { inject, injectable } from 'inversify';
14
- import { APP_DOCS_FILE_NAME, UC_INPUT_FIELD_PATTERN, UC_MAIN_STEP_PREFIX_REGULAR, } from '../../convention.js';
14
+ import { APP_DOCS_FILE_NAME, UC_MAIN_STEP_PREFIX_REGULAR, } from '../../convention.js';
15
15
  import { OUTPUT_ITEM_FIELDS, } from '../UCDefASTParser.js';
16
16
  let SimpleAppDocsEmitter = class SimpleAppDocsEmitter {
17
17
  fsManager;
@@ -142,9 +142,8 @@ function diagramUCClientConfirm(participant, caller) {
142
142
  ];
143
143
  }
144
144
  function diagramUCFields(fields) {
145
- return (fields
146
- ?.map((f) => f.value.replace(new RegExp(UC_INPUT_FIELD_PATTERN.slice(1)), '$1'))
147
- .join(LB) || '');
145
+ return (fields?.map((f) => `${f.value.name}: ${f.value.dataType}`).join(LB) ||
146
+ '');
148
147
  }
149
148
  function diagramUCMainSteps(participant, field) {
150
149
  return field.map((f) => `${participant}->>${participant}: ${f.value.replace(UC_MAIN_STEP_PREFIX_REGULAR, '').trim()}`);
@@ -171,7 +170,7 @@ function fmtTechSummaryField(field) {
171
170
  }
172
171
  function fmtTechSummaryFieldVal(field) {
173
172
  const { err, value } = field;
174
- let res = value;
173
+ let res = (typeof value === 'string' ? value : value.raw) ?? '';
175
174
  if (err) {
176
175
  res += `❌ ${err}`;
177
176
  }
@@ -11,7 +11,8 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
11
  return function (target, key) { decorator(target, key, paramIndex); }
12
12
  };
13
13
  import { inject, injectable } from 'inversify';
14
- import typescript, { isClassDeclaration, isObjectLiteralExpression, isPropertyAssignment, } from 'typescript';
14
+ import typescript, { isClassDeclaration, isObjectLiteralExpression, isPropertyAssignment, SyntaxKind, } from 'typescript';
15
+ // https://ts-ast-viewer.com
15
16
  // To avoid the following error when used in a consumer :
16
17
  // SyntaxError: Named export 'ModuleKind' not found. The requested module 'typescript' is a CommonJS module, which may not support all module.exports as named exports.
17
18
  // CommonJS modules can always be imported via the default export
@@ -99,20 +100,46 @@ let TypeScriptLibUCDefASTParser = class TypeScriptLibUCDefASTParser {
99
100
  }
100
101
  getTypeFields(node) {
101
102
  const type = this.typeChecker.getTypeAtLocation(node);
102
- const fields = type.getProperties().map((p) => {
103
+ const fields = type
104
+ .getProperties()
105
+ .map((p) => {
103
106
  const field = {
104
107
  err: null,
105
- value: p.getName(),
108
+ value: {
109
+ dataType: null,
110
+ name: null,
111
+ raw: null,
112
+ type: null,
113
+ },
106
114
  };
107
115
  const declarations = p.getDeclarations();
108
- if (declarations) {
109
- const [first] = declarations;
110
- if (first && isPropertySignature(first)) {
111
- field.value = first
112
- .getText()
113
- .replaceAll('\n', '')
114
- .replaceAll(';', '');
115
- }
116
+ if (!declarations) {
117
+ return field;
118
+ }
119
+ const [first] = declarations;
120
+ if (first && isPropertySignature(first)) {
121
+ field.value.raw = first
122
+ .getText()
123
+ .replaceAll('\n', '')
124
+ .replaceAll(';', '')
125
+ .replaceAll(/\s+/g, ' ');
126
+ first.forEachChild((node1) => {
127
+ if (isIdentifier(node1)) {
128
+ field.value.name = node1.getText();
129
+ }
130
+ else if (isTypeReferenceNode(node1)) {
131
+ field.value.type = node1.getText();
132
+ node1.forEachChild((node2) => {
133
+ if (isIdentifier(node2) ||
134
+ isTypeReferenceNode(node2) ||
135
+ node2.kind === SyntaxKind.BooleanKeyword ||
136
+ node2.kind === SyntaxKind.NumberKeyword ||
137
+ node2.kind === SyntaxKind.StringKeyword) {
138
+ field.value.dataType = node2.getText();
139
+ }
140
+ });
141
+ }
142
+ });
116
143
  }
117
144
  return field;
118
145
  });
@@ -5,7 +5,7 @@ export declare class VitestAppTestSuiteRunner implements AppTestSuiteRunner {
5
5
  private fsManager;
6
6
  private shellCommandExecutor;
7
7
  constructor(fsManager: FSManager, shellCommandExecutor: ShellCommandExecutor);
8
- exec({ appPath, skipCoverage, updateSnapshots, }: Input): Promise<void>;
8
+ exec({ appPath, only, skipCoverage, updateSnapshots, }: Input): Promise<void>;
9
9
  coverageReportEntrypointPath(appPath: FilePath): Promise<FilePath>;
10
10
  private coverageReportPath;
11
11
  }
@@ -19,18 +19,33 @@ let VitestAppTestSuiteRunner = class VitestAppTestSuiteRunner {
19
19
  this.fsManager = fsManager;
20
20
  this.shellCommandExecutor = shellCommandExecutor;
21
21
  }
22
- async exec({ appPath, skipCoverage, updateSnapshots, }) {
22
+ async exec({ appPath, only, skipCoverage, updateSnapshots, }) {
23
23
  const testPath = this.fsManager.path(appPath, APP_TEST_DIR_NAME);
24
24
  const args = [
25
25
  'run',
26
26
  '--color',
27
+ // https://vitest.dev/guide/cli.html#dir
27
28
  '--dir',
28
29
  appPath,
29
30
  ];
31
+ if (only) {
32
+ args.push(
33
+ // https://vitest.dev/guide/cli.html#testnamepattern
34
+ '--testNamePattern', only);
35
+ }
30
36
  if (!skipCoverage) {
31
- args.push('--coverage.enabled', '--coverage.exclude', testPath, '--coverage.include', appPath, '--coverage.reportsDirectory', this.coverageReportPath(appPath));
37
+ args.push(
38
+ // https://vitest.dev/guide/cli.html#coverage-enabled
39
+ '--coverage.enabled',
40
+ // https://vitest.dev/guide/cli.html#coverage-exclude
41
+ '--coverage.exclude', testPath,
42
+ // https://vitest.dev/guide/cli.html#coverage-include
43
+ '--coverage.include', appPath,
44
+ // https://vitest.dev/guide/cli.html#coverage-reportsdirectory
45
+ '--coverage.reportsDirectory', this.coverageReportPath(appPath));
32
46
  }
33
47
  if (updateSnapshots) {
48
+ // https://vitest.dev/guide/cli.html#update
34
49
  args.push('--update');
35
50
  }
36
51
  await this.shellCommandExecutor.exec({
@@ -4,7 +4,7 @@ export const DEFAULT_APP_TESTER_OPTS = {
4
4
  imports: {
5
5
  external: {
6
6
  aliasPrefix: '@',
7
- allowed: ['inversify', 'libmodulor'],
7
+ allowed: ['libmodulor', 'inversify'],
8
8
  },
9
9
  internal: {
10
10
  maxDepth: '../../',
@@ -1,7 +1,9 @@
1
1
  import type { FilePath } from '../../dt/index.js';
2
2
  import type { Worker } from '../../std/index.js';
3
+ import type { UCName } from '../../uc/index.js';
3
4
  export interface Input {
4
5
  appPath: FilePath;
6
+ only: UCName | null;
5
7
  skipCoverage: boolean;
6
8
  updateSnapshots: boolean;
7
9
  }
@@ -104,7 +104,7 @@ let UCExecutor = class UCExecutor {
104
104
  break;
105
105
  }
106
106
  default:
107
- ((_) => { })(transportType);
107
+ transportType;
108
108
  }
109
109
  if (!ucor) {
110
110
  throw new Error(ERR_CLIENT_EXPECTED_UCOR(name));
@@ -1,10 +1,12 @@
1
1
  import type { AppManifest } from '../../../app/index.js';
2
2
  import type { ErrorMessage } from '../../../dt/index.js';
3
- import type { I18n } from '../../../i18n/index.js';
3
+ import { type I18n } from '../../../i18n/index.js';
4
4
  import type { Worker } from '../../../std/index.js';
5
+ import type { Output as UCDefSourcesCheckerOutput } from './UCDefSourcesChecker.js';
5
6
  export interface Input {
6
7
  appI18n: I18n;
7
8
  appManifest: Pick<AppManifest, 'languageCodes'>;
9
+ ucDefSourcesCheckerOutput: UCDefSourcesCheckerOutput;
8
10
  }
9
11
  export interface Output {
10
12
  errors: ErrorMessage[];
@@ -13,7 +15,11 @@ export declare class AppI18nChecker implements Worker<Input, Promise<Output>> {
13
15
  private static I18N_KEY_PATTERN;
14
16
  private output;
15
17
  constructor();
16
- exec({ appI18n, appManifest }: Input): Promise<Output>;
18
+ exec({ appI18n, appManifest, ucDefSourcesCheckerOutput, }: Input): Promise<Output>;
17
19
  private makeSureLanguagesAreConsistent;
18
20
  private makeSureKeysAndLabelsAreValid;
21
+ private makeSureNonDefaultLanguagesAreFullyTranslated;
22
+ private checkUC;
23
+ private checkIOFields;
24
+ private checkKey;
19
25
  }
@@ -9,9 +9,11 @@ var __metadata = (this && this.__metadata) || function (k, v) {
9
9
  };
10
10
  var AppI18nChecker_1;
11
11
  import { injectable } from 'inversify';
12
+ import { I18N_DEFAULT_LANG, } from '../../../i18n/index.js';
12
13
  const ERR_I18N_MISMATCH = () => 'The languageCodes in app manifest must match with the keys in i18n';
13
14
  const ERR_I18N_KEY_INVALID = (key) => `The i18n key '${key}' must respect the i18n key pattern`;
14
- const ERR_I18N_LABEL_NO_DOT = (key) => `The i18n key '${key}' is a label, thus should not ends with a dot`;
15
+ const ERR_I18N_LABEL_NO_DOT = (key) => `The i18n key '${key}' is a label, thus it should not end with a dot`;
16
+ const ERR_I18N_MISSING_TRANS = (key, lang) => `The i18n key '${key}' is missing for lang '${lang}'`;
15
17
  let AppI18nChecker = class AppI18nChecker {
16
18
  static { AppI18nChecker_1 = this; }
17
19
  static I18N_KEY_PATTERN = /(dt_([A-Z][A-Za-z0-9]+)_([A-Za-z0-9]+)_(desc|label))|(err_([A-Za-z_]+))|(uc_([A-Z][A-Za-z0-9]+)_(client_confirm_(cancel|confirm|message|title)|desc|label|i_submit_(changing|idle|initializing|submitting)|op_(0|1)_(empty|label)))|(ucif_([a-z]([A-Za-z0-9]+)?)_(desc|label))|(ucof_([a-z]([A-Za-z0-9]+)?)_(desc|label))|(validation_([a-z]+)_([A-Z][A-Za-z0-9]+))/;
@@ -19,9 +21,10 @@ let AppI18nChecker = class AppI18nChecker {
19
21
  constructor() {
20
22
  this.output = { errors: [] };
21
23
  }
22
- async exec({ appI18n, appManifest }) {
24
+ async exec({ appI18n, appManifest, ucDefSourcesCheckerOutput, }) {
23
25
  this.makeSureLanguagesAreConsistent(appI18n, appManifest);
24
26
  this.makeSureKeysAndLabelsAreValid(appI18n);
27
+ this.makeSureNonDefaultLanguagesAreFullyTranslated(appI18n, ucDefSourcesCheckerOutput);
25
28
  return this.output;
26
29
  }
27
30
  makeSureLanguagesAreConsistent(appI18n, appManifest) {
@@ -44,6 +47,45 @@ let AppI18nChecker = class AppI18nChecker {
44
47
  }
45
48
  }
46
49
  }
50
+ makeSureNonDefaultLanguagesAreFullyTranslated(i18n, ucDefSourcesCheckerOutput) {
51
+ for (const [lang, translations] of Object.entries(i18n)) {
52
+ if (lang === I18N_DEFAULT_LANG) {
53
+ // We assume the code is in English so it's fine not to have all the translations in this language.
54
+ // For instance, a field named "name" will be humanized as "Name", which is totally ok.
55
+ continue;
56
+ }
57
+ for (const { metadataName, ioIFields, ioOPI0Fields, ioOPI1Fields, } of ucDefSourcesCheckerOutput.items) {
58
+ this.checkUC(lang, translations, 'label', metadataName);
59
+ for (const [prefix, fields] of [
60
+ ['ucif', ioIFields],
61
+ ['ucof', ioOPI0Fields],
62
+ ['ucof', ioOPI1Fields],
63
+ ]) {
64
+ this.checkIOFields(lang, translations, prefix, 'label', fields);
65
+ }
66
+ }
67
+ }
68
+ }
69
+ checkUC(lang, translations, suffix, metadataName) {
70
+ if (!metadataName) {
71
+ return;
72
+ }
73
+ this.checkKey(lang, translations, `uc_${metadataName.value}_${suffix}`);
74
+ }
75
+ checkIOFields(lang, translations, prefix, suffix, fields) {
76
+ if (!fields) {
77
+ return;
78
+ }
79
+ for (const f of fields) {
80
+ this.checkKey(lang, translations, `${prefix}_${f.value.name}_${suffix}`);
81
+ }
82
+ }
83
+ checkKey(lang, translations, key) {
84
+ if (key in translations) {
85
+ return;
86
+ }
87
+ this.output.errors.push(ERR_I18N_MISSING_TRANS(key, lang));
88
+ }
47
89
  };
48
90
  AppI18nChecker = AppI18nChecker_1 = __decorate([
49
91
  injectable(),
@@ -18,7 +18,7 @@ const ERR_UCD_CONST_NAME = (name) => `The UCD const name '${name}' must follow t
18
18
  const ERR_UCD_FILE_SUFFIX = (fileName) => `The file '${fileName}' must end with ${UC_DEF_FILE_NAME_SUFFIX}`;
19
19
  const ERR_UCD_IMPORTS_EXTERNAL_ALLOWED = (aliasPrefix, allowed, text) => `External imports must be an alias '${aliasPrefix}*' or be one of ${allowed} (Got ${text})`;
20
20
  const ERR_UCD_IMPORTS_INTERNAL_MAX_DEPTH = (maxDepth) => `Internal imports must not be deeper than ${maxDepth}`;
21
- const ERR_UCD_INPUT_FIELD_PATTERN = () => `The input field def must match ${UC_INPUT_FIELD_PATTERN}`;
21
+ const ERR_UCD_INPUT_FIELD_DECLARATION = (raw) => `The input field def must match 'name: UCInputFieldValue<DataType>' (Got '${raw}')`;
22
22
  const ERR_UCD_INPUT_TYPE_NAME = (ucName) => `The input type must be named ${ucName}${UC_INPUT_SUFFIX}`;
23
23
  const ERR_UCD_OPI_TYPE_NAME = (ucName, idx) => `The OPI must be named ${ucName}${UC_OPI_SUFFIX}${idx}`;
24
24
  // TODO : Improve the check* methods that look a little bit hacky
@@ -93,16 +93,16 @@ let UCDefSourcesChecker = class UCDefSourcesChecker {
93
93
  };
94
94
  item.ioIFields = fields;
95
95
  for (const f of item.ioIFields) {
96
- const parts = f.value.split(':');
97
- if (parts.length !== 2) {
98
- continue;
96
+ const { dataType, name, raw, type } = f.value;
97
+ if (dataType &&
98
+ name &&
99
+ raw &&
100
+ type &&
101
+ type.match(new RegExp(UC_INPUT_FIELD_PATTERN)) !== null) {
102
+ }
103
+ else {
104
+ f.err = ERR_UCD_INPUT_FIELD_DECLARATION(raw);
99
105
  }
100
- const [_name, type] = parts;
101
- // trim because we process `name: Type` if the code is linted correctly
102
- f.err =
103
- type?.trim().match(new RegExp(UC_INPUT_FIELD_PATTERN)) !== null
104
- ? null
105
- : ERR_UCD_INPUT_FIELD_PATTERN();
106
106
  }
107
107
  }
108
108
  checkMainStep(lifecycle, step, item) {
@@ -120,7 +120,7 @@ let UCDefSourcesChecker = class UCDefSourcesChecker {
120
120
  item.lifecycleServerSteps.push({ err: null, value: step });
121
121
  break;
122
122
  default:
123
- ((_) => { })(lifecycle);
123
+ lifecycle;
124
124
  }
125
125
  }
126
126
  checkMetadata(metadata, item) {
@@ -177,7 +177,7 @@ let UCDefSourcesChecker = class UCDefSourcesChecker {
177
177
  };
178
178
  break;
179
179
  default:
180
- ((_) => { })(lifecycle);
180
+ lifecycle;
181
181
  }
182
182
  }
183
183
  async processFiles(appPath, paths) {
@@ -51,7 +51,7 @@ let HTTPUCTransporter = class HTTPUCTransporter {
51
51
  break;
52
52
  }
53
53
  default:
54
- ((_) => { })(publicApiKeyCheckType);
54
+ publicApiKeyCheckType;
55
55
  }
56
56
  if (auth) {
57
57
  switch (authType) {
@@ -86,7 +86,7 @@ let HTTPUCTransporter = class HTTPUCTransporter {
86
86
  break;
87
87
  }
88
88
  default:
89
- ((_) => { })(authType);
89
+ authType;
90
90
  }
91
91
  }
92
92
  const res = await this.httpAPICaller.exec({
@@ -112,7 +112,7 @@ let KnexUCDataStore = class KnexUCDataStore {
112
112
  case 'sqlite3':
113
113
  return [];
114
114
  default:
115
- ((_) => { })(type);
115
+ (type);
116
116
  return [];
117
117
  }
118
118
  }
@@ -156,7 +156,7 @@ let KnexUCDataStore = class KnexUCDataStore {
156
156
  this.fillConfigForSQLite3();
157
157
  break;
158
158
  default:
159
- ((_) => { })(type);
159
+ (type);
160
160
  }
161
161
  }
162
162
  fillConfigForPG() {
@@ -48,7 +48,6 @@ export * from './utils/fmtVal.js';
48
48
  export * from './utils/recIs.js';
49
49
  export * from './utils/rInput.js';
50
50
  export * from './utils/rVal.js';
51
- export * from './utils/stripUCDLifecycleServer.js';
52
51
  export * from './utils/ucHTTPContract.js';
53
52
  export * from './utils/ucMountingPoint.js';
54
53
  export * from './value.js';
@@ -48,7 +48,6 @@ export * from './utils/fmtVal.js';
48
48
  export * from './utils/recIs.js';
49
49
  export * from './utils/rInput.js';
50
50
  export * from './utils/rVal.js';
51
- export * from './utils/stripUCDLifecycleServer.js';
52
51
  export * from './utils/ucHTTPContract.js';
53
52
  export * from './utils/ucMountingPoint.js';
54
53
  export * from './value.js';