libmodulor 0.23.0 → 0.25.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 (132) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +154 -2
  3. package/dist/esm/apps/Helper/src/lib/project.js +6 -6
  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/Validation.d.ts +2 -2
  10. package/dist/esm/dt/base/TBase.d.ts +2 -0
  11. package/dist/esm/dt/base/TBase.js +3 -0
  12. package/dist/esm/dt/base/TObject.d.ts +6 -4
  13. package/dist/esm/dt/base/TObject.js +5 -6
  14. package/dist/esm/dt/base/TString.d.ts +2 -1
  15. package/dist/esm/dt/base/TString.js +22 -0
  16. package/dist/esm/dt/final/TFile.d.ts +13 -4
  17. package/dist/esm/dt/final/TFile.js +70 -8
  18. package/dist/esm/dt/final/TFileExtension.d.ts +1 -1
  19. package/dist/esm/dt/final/TFileMimeType.d.ts +2 -6
  20. package/dist/esm/dt/final/TFileMimeType.js +0 -6
  21. package/dist/esm/dt/final/TFilePath.d.ts +7 -0
  22. package/dist/esm/dt/final/TFilePath.js +5 -1
  23. package/dist/esm/dt/index.d.ts +1 -1
  24. package/dist/esm/i18n/WordingManager.d.ts +2 -1
  25. package/dist/esm/i18n/WordingManager.js +23 -2
  26. package/dist/esm/i18n/index.d.ts +1 -1
  27. package/dist/esm/i18n/locales/de.d.ts +2 -0
  28. package/dist/esm/i18n/locales/de.js +62 -0
  29. package/dist/esm/i18n/locales/en.js +8 -0
  30. package/dist/esm/i18n/locales/es.d.ts +2 -0
  31. package/dist/esm/i18n/locales/es.js +62 -0
  32. package/dist/esm/i18n/locales/fr.js +8 -0
  33. package/dist/esm/i18n/types.d.ts +5 -4
  34. package/dist/esm/index.babel.d.ts +1 -0
  35. package/dist/esm/index.babel.js +1 -0
  36. package/dist/esm/index.node-stricli-cli.d.ts +2 -0
  37. package/dist/esm/index.node-stricli-cli.js +2 -0
  38. package/dist/esm/index.vite.d.ts +1 -1
  39. package/dist/esm/index.vite.js +1 -1
  40. package/dist/esm/index.webpack.d.ts +1 -0
  41. package/dist/esm/index.webpack.js +1 -0
  42. package/dist/esm/std/FSManager.d.ts +7 -5
  43. package/dist/esm/std/FSManager.js +5 -6
  44. package/dist/esm/std/FormDataBuilder.d.ts +2 -1
  45. package/dist/esm/std/I18nManager.d.ts +12 -0
  46. package/dist/esm/std/impl/NodeFSManager.js +4 -3
  47. package/dist/esm/std/impl/SimpleMapI18nManager.d.ts +6 -1
  48. package/dist/esm/std/impl/SimpleMapI18nManager.js +41 -12
  49. package/dist/esm/target/lib/react/StyleContextProvider.d.ts +1 -0
  50. package/dist/esm/target/lib/react/form.d.ts +1 -1
  51. package/dist/esm/target/lib/react/form.js +1 -0
  52. package/dist/esm/target/lib/react/useAction.d.ts +1 -1
  53. package/dist/esm/target/lib/react/useAction.js +13 -12
  54. package/dist/esm/target/lib/server/AuthenticationChecker.js +1 -1
  55. package/dist/esm/target/lib/server/PublicApiKeyChecker.js +1 -1
  56. package/dist/esm/target/lib/server/ServerRequestHandler.js +2 -2
  57. package/dist/esm/target/lib/server-express/funcs.js +4 -3
  58. package/dist/esm/target/lib/server-hono/funcs.js +2 -2
  59. package/dist/esm/target/lib/server-node/funcs.js +1 -1
  60. package/dist/esm/target/lib/web/input.d.ts +1 -0
  61. package/dist/esm/target/lib/web/input.js +5 -1
  62. package/dist/esm/target/node-stricli-cli/NodeStricliCLIManager.d.ts +12 -0
  63. package/dist/esm/target/node-stricli-cli/NodeStricliCLIManager.js +118 -0
  64. package/dist/esm/target/react-native-pure/UCFormField.js +2 -1
  65. package/dist/esm/target/react-native-pure/UCFormFieldControl.js +6 -4
  66. package/dist/esm/target/react-native-pure/UCFormFieldErr.d.ts +1 -1
  67. package/dist/esm/target/react-native-pure/UCFormFieldErr.js +4 -1
  68. package/dist/esm/target/react-native-pure/UCFormFieldHelp.d.ts +4 -0
  69. package/dist/esm/target/react-native-pure/UCFormFieldHelp.js +15 -0
  70. package/dist/esm/target/react-web-pure/UCFormField.js +2 -1
  71. package/dist/esm/target/react-web-pure/UCFormFieldErr.d.ts +1 -1
  72. package/dist/esm/target/react-web-pure/UCFormFieldErr.js +4 -1
  73. package/dist/esm/target/react-web-pure/UCFormFieldHelp.d.ts +4 -0
  74. package/dist/esm/target/react-web-pure/UCFormFieldHelp.js +14 -0
  75. package/dist/esm/testing/AppTester.js +4 -5
  76. package/dist/esm/testing/UCDefASTParser.d.ts +24 -6
  77. package/dist/esm/testing/impl/SimpleAppDocsEmitter/SimpleAppDocsEmitter.d.ts +7 -0
  78. package/dist/esm/testing/impl/SimpleAppDocsEmitter/SimpleAppDocsEmitter.js +59 -0
  79. package/dist/esm/testing/impl/SimpleAppDocsEmitter/markdown.d.ts +2 -0
  80. package/dist/esm/testing/impl/SimpleAppDocsEmitter/markdown.js +10 -0
  81. package/dist/esm/testing/impl/SimpleAppDocsEmitter/sequence-diagram.d.ts +2 -0
  82. package/dist/esm/testing/impl/SimpleAppDocsEmitter/sequence-diagram.js +92 -0
  83. package/dist/esm/testing/impl/SimpleAppDocsEmitter/tech-summary.d.ts +2 -0
  84. package/dist/esm/testing/impl/SimpleAppDocsEmitter/tech-summary.js +27 -0
  85. package/dist/esm/testing/impl/SimpleAppDocsEmitter/uc-summary.d.ts +2 -0
  86. package/dist/esm/testing/impl/SimpleAppDocsEmitter/uc-summary.js +63 -0
  87. package/dist/esm/testing/impl/SimpleAppDocsEmitter.js +4 -5
  88. package/dist/esm/testing/impl/TypeScriptLibUCDefASTParser.js +38 -11
  89. package/dist/esm/testing/impl/VitestAppTestSuiteRunner.d.ts +1 -1
  90. package/dist/esm/testing/impl/VitestAppTestSuiteRunner.js +17 -2
  91. package/dist/esm/testing/impl/newNodeAppTester.js +1 -1
  92. package/dist/esm/testing/opts.js +1 -1
  93. package/dist/esm/testing/uc-input.js +5 -2
  94. package/dist/esm/testing/workers/AppTestSuiteRunner.d.ts +2 -0
  95. package/dist/esm/testing/workers/UCExecutor.js +1 -1
  96. package/dist/esm/testing/workers/checkers/AppI18nChecker.d.ts +8 -2
  97. package/dist/esm/testing/workers/checkers/AppI18nChecker.js +44 -2
  98. package/dist/esm/testing/workers/checkers/UCDefSourcesChecker.js +12 -12
  99. package/dist/esm/uc/exec.d.ts +42 -21
  100. package/dist/esm/uc/exec.js +48 -13
  101. package/dist/esm/uc/impl/HTTPUCTransporter.js +2 -2
  102. package/dist/esm/uc/impl/KnexUCDataStore.js +2 -2
  103. package/dist/esm/uc/index.d.ts +0 -1
  104. package/dist/esm/uc/index.js +0 -1
  105. package/dist/esm/uc/input-field.d.ts +6 -4
  106. package/dist/esm/uc/input-field.js +4 -5
  107. package/dist/esm/uc/side-effect.d.ts +10 -8
  108. package/dist/esm/uc/side-effect.js +5 -6
  109. package/dist/esm/uc/workers/UCExecChecker.js +1 -1
  110. package/dist/esm/uc/workers/UCInputFilesProcessor.js +3 -3
  111. package/dist/esm/uc/workers/UCInputValidator.js +2 -1
  112. package/dist/esm/uc/workers/UCOutputFilesProcessor.js +1 -1
  113. package/dist/esm/utils/bundling/babel/plugin.d.ts +2 -0
  114. package/dist/esm/utils/bundling/babel/plugin.js +38 -0
  115. package/dist/esm/utils/bundling/funcs.d.ts +6 -0
  116. package/dist/esm/utils/bundling/funcs.js +20 -0
  117. package/dist/esm/utils/bundling/typescript.d.ts +3 -0
  118. package/dist/esm/utils/bundling/typescript.js +61 -0
  119. package/dist/esm/utils/bundling/vite/plugin.d.ts +6 -0
  120. package/dist/esm/utils/bundling/vite/plugin.js +17 -0
  121. package/dist/esm/utils/bundling/webpack/loader.d.ts +2 -0
  122. package/dist/esm/utils/bundling/webpack/loader.js +12 -0
  123. package/dist/esm/utils/http/HTTPRequestBuilder.js +1 -1
  124. package/dist/esm/utils/index.d.ts +1 -1
  125. package/dist/esm/utils/ioc/bindCommon.js +1 -1
  126. package/dist/esm/utils/terminal/fmt.js +1 -1
  127. package/dist/esm/utils/types/utility-types.d.ts +4 -0
  128. package/package.json +36 -12
  129. package/pnpm-workspace.yaml +1 -4
  130. package/tsconfig.build.examples.json +8 -0
  131. package/tsconfig.json +1 -0
  132. package/vitest.config.ts +16 -0
@@ -1,54 +1,55 @@
1
1
  import { useEffect, useState } from 'react';
2
+ import { UCExecRes, UCExecState } from '../../../uc/index.js';
2
3
  import { sleep } from '../../../utils/index.js';
3
4
  export function useAction({ action, autoExec = false, confirm, onError, onInit, onStart, sleepInMs, }) {
4
5
  const [errMsg, setErrMsg] = useState(null);
5
6
  const [execRes, setExecRes] = useState(null);
6
- const [execState, setExecState] = useState(onInit ? 'initializing' : 'idle');
7
+ const [execState, setExecState] = useState(onInit ? UCExecState.INITIALIZING : UCExecState.IDLE);
7
8
  // biome-ignore lint/correctness/useExhaustiveDependencies : must run only once
8
9
  useEffect(() => {
9
10
  (async () => {
10
- if (execState === 'initializing') {
11
+ if (execState === UCExecState.INITIALIZING) {
11
12
  await onInit?.();
12
13
  }
13
14
  if (autoExec) {
14
15
  await exec();
15
16
  }
16
17
  else {
17
- setExecState('idle');
18
+ setExecState(UCExecState.IDLE);
18
19
  }
19
20
  })();
20
21
  }, []);
21
22
  const exec = async () => {
22
23
  setErrMsg(null);
23
24
  setExecRes(null);
24
- setExecState('submitting');
25
+ setExecState(UCExecState.SUBMITTING);
25
26
  await onStart?.();
26
27
  const confirmed = confirm ? await confirm?.() : true;
27
28
  if (!confirmed) {
28
- setExecState('idle');
29
- setExecRes('aborted');
30
- return 'aborted';
29
+ setExecState(UCExecState.IDLE);
30
+ setExecRes(UCExecRes.ABORTED);
31
+ return UCExecRes.ABORTED;
31
32
  }
32
33
  if (sleepInMs !== undefined) {
33
34
  await sleep(sleepInMs);
34
35
  }
35
36
  try {
36
37
  await action();
37
- setExecRes('succeeded');
38
- return 'succeeded';
38
+ setExecRes(UCExecRes.SUCCEEDED);
39
+ return UCExecRes.SUCCEEDED;
39
40
  }
40
41
  catch (err) {
41
- setExecRes('failed');
42
+ setExecRes(UCExecRes.FAILED);
42
43
  if (onError) {
43
44
  await onError?.(err);
44
45
  }
45
46
  else {
46
47
  setErrMsg(err.message);
47
48
  }
48
- return 'failed';
49
+ return UCExecRes.FAILED;
49
50
  }
50
51
  finally {
51
- setExecState('idle');
52
+ setExecState(UCExecState.IDLE);
52
53
  }
53
54
  };
54
55
  return { errMsg, exec, execRes, execState };
@@ -80,7 +80,7 @@ let AuthenticationChecker = class AuthenticationChecker {
80
80
  }
81
81
  break;
82
82
  default:
83
- ((_) => { })(authType);
83
+ authType;
84
84
  }
85
85
  uc.auth = output.auth;
86
86
  const { allowed } = await policy.exec({ uc });
@@ -39,7 +39,7 @@ let PublicApiKeyChecker = class PublicApiKeyChecker {
39
39
  }
40
40
  break;
41
41
  default:
42
- ((_) => { })(checkType);
42
+ checkType;
43
43
  }
44
44
  if (!allowed) {
45
45
  throw new UnauthorizedError();
@@ -127,7 +127,7 @@ let ServerRequestHandler = class ServerRequestHandler {
127
127
  uc.fill((await req.bodyFromQueryParams()));
128
128
  break;
129
129
  default:
130
- ((_) => { })(envelope);
130
+ envelope;
131
131
  }
132
132
  }
133
133
  async applySideEffects(res, ucd, output) {
@@ -154,7 +154,7 @@ let ServerRequestHandler = class ServerRequestHandler {
154
154
  await this.applySetAuthSideEffect(res, item);
155
155
  break;
156
156
  default:
157
- ((_) => { })(type);
157
+ (type);
158
158
  }
159
159
  }
160
160
  return { status: undefined };
@@ -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;
@@ -97,8 +97,9 @@ export function mountHandler(contract, express, handler) {
97
97
  export function toFile(f) {
98
98
  return {
99
99
  name: f.name,
100
- path: f.tempFilePath,
100
+ size: f.size,
101
101
  type: f.mimetype,
102
+ uri: f.tempFilePath,
102
103
  };
103
104
  }
104
105
  export function toReq(req) {
@@ -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) {
@@ -34,6 +34,7 @@ export interface HTMLInputDef {
34
34
  * @see node_modules/@types/react/index.d.ts `InputHTMLAttributes`
35
35
  */
36
36
  spec?: {
37
+ accept?: string | undefined;
37
38
  'aria-errormessage'?: string | undefined;
38
39
  'aria-invalid'?: boolean | undefined;
39
40
  disabled?: boolean | undefined;
@@ -1,4 +1,4 @@
1
- import { TBoolean, TNumber, TString, } from '../../../dt/index.js';
1
+ import { TBoolean, TFile, TNumber, TString, } from '../../../dt/index.js';
2
2
  import { ucifHint, ucifId, ucifIsMandatory, } from '../../../uc/index.js';
3
3
  export function htmlInputDef(field, disabled, errMsg) {
4
4
  const def = {
@@ -34,6 +34,10 @@ export function htmlInputDef(field, disabled, errMsg) {
34
34
  else if (fType instanceof TBoolean) {
35
35
  def.internal.checked = fType.getInitialValue() === true;
36
36
  }
37
+ else if (fType instanceof TFile) {
38
+ const constraints = fType.getFileConstraints();
39
+ def.spec.accept = constraints.accept.join(',');
40
+ }
37
41
  if (!(fType instanceof TBoolean)) {
38
42
  def.internal.value = fType.getInitialValue()?.toString() || '';
39
43
  }
@@ -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 };
@@ -7,6 +7,7 @@ import { useStyleContext } from '../lib/react/StyleContextProvider.js';
7
7
  import { UCFormFieldControl } from './UCFormFieldControl.js';
8
8
  import { UCFormFieldDesc } from './UCFormFieldDesc.js';
9
9
  import { UCFormFieldErr } from './UCFormFieldErr.js';
10
+ import { UCFormFieldHelp } from './UCFormFieldHelp.js';
10
11
  import { UCFormFieldLabel } from './UCFormFieldLabel.js';
11
12
  export function UCFormField({ disabled, execState, f, only, }) {
12
13
  const { i18nManager } = useDIContext();
@@ -16,5 +17,5 @@ export function UCFormField({ disabled, execState, f, only, }) {
16
17
  setErrMsg(validateFormField(i18nManager, f));
17
18
  };
18
19
  const elements = only ?? UC_FORM_FIELD_ELEMENTS;
19
- return (_jsxs(View, { style: formField?.style, children: [elements.includes('label') && _jsx(UCFormFieldLabel, { f: f }), elements.includes('control') && (_jsx(UCFormFieldControl, { disabled: disabled, execState: execState, f: f, onChange: onChange })), elements.includes('err') && errMsg && (_jsx(UCFormFieldErr, { errMsg: errMsg })), elements.includes('desc') && _jsx(UCFormFieldDesc, { f: f })] }));
20
+ return (_jsxs(View, { style: formField?.style, children: [elements.includes('label') && _jsx(UCFormFieldLabel, { f: f }), elements.includes('control') && (_jsx(UCFormFieldControl, { disabled: disabled, execState: execState, f: f, onChange: onChange })), elements.includes('desc') && _jsx(UCFormFieldDesc, { f: f }), elements.includes('help') && _jsx(UCFormFieldHelp, { f: f }), elements.includes('err') && _jsx(UCFormFieldErr, { errMsg: errMsg })] }));
20
21
  }
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useEffect, useState } from 'react';
3
3
  import { FlatList, Pressable, StyleSheet, Switch, Text, TextInput, } from 'react-native';
4
- import { TBoolean } from '../../dt/index.js';
4
+ import { TBoolean, TFile } from '../../dt/index.js';
5
5
  import { ucifRepeatability } from '../../uc/index.js';
6
6
  import { isBlank } from '../../utils/index.js';
7
7
  import { styleDef, useStyleContext, } from '../lib/react/StyleContextProvider.js';
@@ -11,7 +11,7 @@ const MULTIPLE_VALUES_SEPARATOR = ',';
11
11
  export function UCFormFieldControl({ disabled, errMsg = null, execState, f, onChange: onChangeBase, }) {
12
12
  const { colors, formFieldControl, renderFormFieldControl } = useStyleContext();
13
13
  const [internalValue, setInternalValue] = useState(f.getValue());
14
- // biome-ignore lint/correctness/useExhaustiveDependencies: false positive : It is actually necessary (only `f` does not trigger the effect)
14
+ // biome-ignore lint/correctness/useExhaustiveDependencies: It is actually necessary because only `f` or `f.getValue` does not trigger the effect
15
15
  useEffect(() => {
16
16
  setInternalValue(f.getValue());
17
17
  }, [f.getValue()]);
@@ -25,6 +25,10 @@ export function UCFormFieldControl({ disabled, errMsg = null, execState, f, onCh
25
25
  if (component) {
26
26
  return component;
27
27
  }
28
+ const { type } = f.def;
29
+ if (type instanceof TFile) {
30
+ return (_jsx(Text, { style: { color: 'red' }, children: "Generic file picker not available in RN" }));
31
+ }
28
32
  const onChangeText = (value) => {
29
33
  const [isRepeatable] = ucifRepeatability(f.def);
30
34
  if (isRepeatable && typeof value === 'string') {
@@ -58,7 +62,6 @@ export function UCFormFieldControl({ disabled, errMsg = null, execState, f, onCh
58
62
  setInternalValue(value);
59
63
  };
60
64
  const attrs = rnInputDef(f, disabled, errMsg);
61
- const { type } = f.def;
62
65
  const options = type.getOptions();
63
66
  if (options) {
64
67
  // TODO : Handle type.hasStrictOptions() => display an input text alongside the options
@@ -72,7 +75,6 @@ export function UCFormFieldControl({ disabled, errMsg = null, execState, f, onCh
72
75
  },
73
76
  ], children: _jsx(Text, { children: item.label }) })), showsHorizontalScrollIndicator: false, style: styles.select }));
74
77
  }
75
- // TODO : Implement picker for TFile (requires a dependency...)
76
78
  if (type instanceof TBoolean) {
77
79
  const { style } = styleDef(formFieldControl, 'Switch');
78
80
  return (_jsx(Switch, { disabled: !attrs.spec?.editable, onValueChange: onValueChange, style: style, trackColor: { true: colors?.primary }, value: internalValue }));
@@ -1,3 +1,3 @@
1
1
  import type { ReactElement } from 'react';
2
2
  import type { UCFormFieldErrProps } from '../lib/react/form.js';
3
- export declare function UCFormFieldErr({ errMsg }: UCFormFieldErrProps): ReactElement;
3
+ export declare function UCFormFieldErr({ errMsg, }: UCFormFieldErrProps): ReactElement | null;
@@ -1,7 +1,10 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Text } from 'react-native';
3
3
  import { useStyleContext } from '../lib/react/StyleContextProvider.js';
4
- export function UCFormFieldErr({ errMsg }) {
4
+ export function UCFormFieldErr({ errMsg, }) {
5
5
  const { formFieldErr } = useStyleContext();
6
+ if (!errMsg) {
7
+ return null;
8
+ }
6
9
  return _jsx(Text, { style: formFieldErr?.style, children: errMsg });
7
10
  }
@@ -0,0 +1,4 @@
1
+ import type { ReactElement } from 'react';
2
+ import type { DataType } from '../../dt/index.js';
3
+ import type { UCFormFieldDescProps } from '../lib/react/form.js';
4
+ export declare function UCFormFieldHelp<T extends DataType>({ f, }: UCFormFieldDescProps<T>): ReactElement | null;
@@ -0,0 +1,15 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Text } from 'react-native';
3
+ import { useDIContext } from '../../index.react.js';
4
+ import { useStyleContext } from '../lib/react/StyleContextProvider.js';
5
+ export function UCFormFieldHelp({ f, }) {
6
+ const { wordingManager } = useDIContext();
7
+ const { formFieldHelp } = useStyleContext();
8
+ const { def: { type }, } = f;
9
+ const parts = wordingManager.dtConstr(type);
10
+ if (!parts) {
11
+ return null;
12
+ }
13
+ const text = parts.join(' - ');
14
+ return _jsx(Text, { style: formFieldHelp?.style, children: text });
15
+ }
@@ -6,6 +6,7 @@ import { useStyleContext } from '../lib/react/StyleContextProvider.js';
6
6
  import { UCFormFieldControl } from './UCFormFieldControl.js';
7
7
  import { UCFormFieldDesc } from './UCFormFieldDesc.js';
8
8
  import { UCFormFieldErr } from './UCFormFieldErr.js';
9
+ import { UCFormFieldHelp } from './UCFormFieldHelp.js';
9
10
  import { UCFormFieldLabel } from './UCFormFieldLabel.js';
10
11
  export function UCFormField({ disabled, execState, f, only, }) {
11
12
  const { i18nManager } = useDIContext();
@@ -15,5 +16,5 @@ export function UCFormField({ disabled, execState, f, only, }) {
15
16
  setErrMsg(validateFormField(i18nManager, f));
16
17
  };
17
18
  const elements = only ?? UC_FORM_FIELD_ELEMENTS;
18
- return (_jsxs("div", { className: formField?.className, style: formField?.style, children: [elements.includes('label') && _jsx(UCFormFieldLabel, { f: f }), elements.includes('control') && (_jsx(UCFormFieldControl, { disabled: disabled, execState: execState, f: f, onChange: onChange })), elements.includes('err') && errMsg && (_jsx(UCFormFieldErr, { errMsg: errMsg })), elements.includes('desc') && _jsx(UCFormFieldDesc, { f: f })] }));
19
+ return (_jsxs("div", { className: formField?.className, style: formField?.style, children: [elements.includes('label') && _jsx(UCFormFieldLabel, { f: f }), elements.includes('control') && (_jsx(UCFormFieldControl, { disabled: disabled, execState: execState, f: f, onChange: onChange })), elements.includes('desc') && _jsx(UCFormFieldDesc, { f: f }), elements.includes('help') && _jsx(UCFormFieldHelp, { f: f }), elements.includes('err') && _jsx(UCFormFieldErr, { errMsg: errMsg })] }));
19
20
  }
@@ -1,3 +1,3 @@
1
1
  import type { ReactElement } from 'react';
2
2
  import type { UCFormFieldErrProps } from '../lib/react/form.js';
3
- export declare function UCFormFieldErr({ errMsg }: UCFormFieldErrProps): ReactElement;
3
+ export declare function UCFormFieldErr({ errMsg, }: UCFormFieldErrProps): ReactElement | null;
@@ -1,6 +1,9 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useStyleContext } from '../lib/react/StyleContextProvider.js';
3
- export function UCFormFieldErr({ errMsg }) {
3
+ export function UCFormFieldErr({ errMsg, }) {
4
4
  const { formFieldErr } = useStyleContext();
5
+ if (!errMsg) {
6
+ return null;
7
+ }
5
8
  return (_jsx("div", { className: formFieldErr?.className, style: formFieldErr?.style, children: errMsg }));
6
9
  }
@@ -0,0 +1,4 @@
1
+ import type { ReactElement } from 'react';
2
+ import type { DataType } from '../../dt/index.js';
3
+ import type { UCFormFieldDescProps } from '../lib/react/form.js';
4
+ export declare function UCFormFieldHelp<T extends DataType>({ f, }: UCFormFieldDescProps<T>): ReactElement | null;
@@ -0,0 +1,14 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useDIContext } from '../../index.react.js';
3
+ import { useStyleContext } from '../lib/react/StyleContextProvider.js';
4
+ export function UCFormFieldHelp({ f, }) {
5
+ const { wordingManager } = useDIContext();
6
+ const { formFieldHelp } = useStyleContext();
7
+ const { def: { type }, } = f;
8
+ const parts = wordingManager.dtConstr(type);
9
+ if (!parts) {
10
+ return null;
11
+ }
12
+ const text = parts.join(' - ');
13
+ return (_jsx("div", { className: formFieldHelp?.className, style: formFieldHelp?.style, children: text }));
14
+ }
@@ -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 {
@@ -0,0 +1,7 @@
1
+ import type { FSManager } from '../../../std/index.js';
2
+ import type { AppDocsEmitter, Input, Output } from '../../workers/AppDocsEmitter.js';
3
+ export declare class SimpleAppDocsEmitter implements AppDocsEmitter {
4
+ private fsManager;
5
+ constructor(fsManager: FSManager);
6
+ exec({ appPath, ucDefSourcesCheckerOutput, }: Input): Promise<Output>;
7
+ }
@@ -0,0 +1,59 @@
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 { inject, injectable } from 'inversify';
14
+ import { APP_DOCS_FILE_NAME } from '../../../convention.js';
15
+ import { techSummary } from './tech-summary.js';
16
+ import { ucSummary } from './uc-summary.js';
17
+ let SimpleAppDocsEmitter = class SimpleAppDocsEmitter {
18
+ fsManager;
19
+ constructor(fsManager) {
20
+ this.fsManager = fsManager;
21
+ }
22
+ async exec({ appPath, ucDefSourcesCheckerOutput, }) {
23
+ const outPath = this.fsManager.path(appPath, APP_DOCS_FILE_NAME);
24
+ const tpl = template(ucDefSourcesCheckerOutput.items);
25
+ await this.fsManager.touch(outPath, tpl);
26
+ return {
27
+ outPath,
28
+ };
29
+ }
30
+ };
31
+ SimpleAppDocsEmitter = __decorate([
32
+ injectable(),
33
+ __param(0, inject('FSManager')),
34
+ __metadata("design:paramtypes", [Object])
35
+ ], SimpleAppDocsEmitter);
36
+ export { SimpleAppDocsEmitter };
37
+ // For now, we can have it here. When it becomes harder to maintain, we can introduce some kind of template engine.
38
+ // Be aware that this will introduce complexities on building the lib.
39
+ // We'll need to include these templates in the build and make them accessible via package.json "exports" or any other mechanism.
40
+ // Hence the choice to keep it simple for now.
41
+ // Defined it as function in case we need to pass args.
42
+ // Using --- for the comment to make it compatible with pandoc
43
+ // See https://stackoverflow.com/a/4829998/1259118
44
+ const template = (items) => `<!---
45
+ All this code has been auto generated.
46
+ DO NOT EDIT.
47
+ Or be prepared to see all your changes erased at the next generation.
48
+ -->
49
+
50
+ # App
51
+
52
+ ## Use Cases
53
+
54
+ ${items.map(ucSummary).join('\n\n')}
55
+
56
+ ## Technical Summary
57
+
58
+ ${techSummary(items)}
59
+ `;
@@ -0,0 +1,2 @@
1
+ export declare function pre(val: string | null | undefined): string;
2
+ export declare function thead(cols: string[]): string;