@aidc-toolkit/app-extension 0.9.19-beta → 0.9.21-beta

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 (77) hide show
  1. package/README.md +1 -1
  2. package/app-extension.iml +3 -1
  3. package/dist/app-utility-proxy.js +6 -6
  4. package/dist/app-utility-proxy.js.map +1 -1
  5. package/dist/descriptor.d.ts +10 -6
  6. package/dist/descriptor.d.ts.map +1 -1
  7. package/dist/descriptor.js +6 -7
  8. package/dist/descriptor.js.map +1 -1
  9. package/dist/generator/descriptor.d.ts +107 -0
  10. package/dist/generator/descriptor.d.ts.map +1 -0
  11. package/dist/generator/descriptor.js +2 -0
  12. package/dist/generator/descriptor.js.map +1 -0
  13. package/dist/generator/generator.d.ts +120 -0
  14. package/dist/generator/generator.d.ts.map +1 -0
  15. package/dist/generator/generator.js +213 -0
  16. package/dist/generator/generator.js.map +1 -0
  17. package/dist/generator/index.d.ts +3 -0
  18. package/dist/generator/index.d.ts.map +1 -0
  19. package/dist/generator/index.js +2 -0
  20. package/dist/generator/index.js.map +1 -0
  21. package/dist/gs1/check-proxy.js +8 -8
  22. package/dist/gs1/check-proxy.js.map +1 -1
  23. package/dist/gs1/{idkey-proxy.d.ts → identifier-proxy.d.ts} +44 -43
  24. package/dist/gs1/identifier-proxy.d.ts.map +1 -0
  25. package/dist/gs1/{idkey-proxy.js → identifier-proxy.js} +113 -110
  26. package/dist/gs1/identifier-proxy.js.map +1 -0
  27. package/dist/gs1/index.d.ts +1 -1
  28. package/dist/gs1/index.d.ts.map +1 -1
  29. package/dist/gs1/index.js +1 -1
  30. package/dist/gs1/index.js.map +1 -1
  31. package/dist/index.d.ts +1 -0
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +1 -0
  34. package/dist/index.js.map +1 -1
  35. package/dist/locale/en/locale-strings.d.ts +3 -3
  36. package/dist/locale/en/locale-strings.js +11 -11
  37. package/dist/locale/en/locale-strings.js.map +1 -1
  38. package/dist/locale/fr/locale-strings.d.ts +3 -3
  39. package/dist/locale/fr/locale-strings.js +4 -4
  40. package/dist/locale/fr/locale-strings.js.map +1 -1
  41. package/dist/utility/character-set-descriptor.d.ts.map +1 -1
  42. package/dist/utility/character-set-descriptor.js +2 -2
  43. package/dist/utility/character-set-descriptor.js.map +1 -1
  44. package/dist/utility/character-set-proxy.js +7 -7
  45. package/dist/utility/character-set-proxy.js.map +1 -1
  46. package/dist/utility/reg-exp-proxy.js +5 -5
  47. package/dist/utility/reg-exp-proxy.js.map +1 -1
  48. package/dist/utility/string-descriptor.d.ts.map +1 -1
  49. package/dist/utility/string-descriptor.js +2 -2
  50. package/dist/utility/string-descriptor.js.map +1 -1
  51. package/dist/utility/transformer-descriptor.d.ts.map +1 -1
  52. package/dist/utility/transformer-descriptor.js +3 -3
  53. package/dist/utility/transformer-descriptor.js.map +1 -1
  54. package/dist/utility/transformer-proxy.js +6 -6
  55. package/dist/utility/transformer-proxy.js.map +1 -1
  56. package/package.json +1 -1
  57. package/src/app-utility-proxy.ts +6 -6
  58. package/src/descriptor.ts +11 -6
  59. package/src/generator/descriptor.ts +122 -0
  60. package/src/generator/generator.ts +287 -0
  61. package/src/generator/index.ts +2 -0
  62. package/src/generator/locale-strings-generator.ts +358 -0
  63. package/src/generator/logger.ts +45 -0
  64. package/src/gs1/check-proxy.ts +8 -8
  65. package/src/gs1/{idkey-proxy.ts → identifier-proxy.ts} +125 -120
  66. package/src/gs1/index.ts +1 -1
  67. package/src/index.ts +1 -0
  68. package/src/locale/en/locale-strings.ts +11 -11
  69. package/src/locale/fr/locale-strings.ts +4 -4
  70. package/src/utility/character-set-descriptor.ts +2 -2
  71. package/src/utility/character-set-proxy.ts +7 -7
  72. package/src/utility/reg-exp-proxy.ts +5 -5
  73. package/src/utility/string-descriptor.ts +2 -2
  74. package/src/utility/transformer-descriptor.ts +3 -3
  75. package/src/utility/transformer-proxy.ts +6 -6
  76. package/dist/gs1/idkey-proxy.d.ts.map +0 -1
  77. package/dist/gs1/idkey-proxy.js.map +0 -1
@@ -0,0 +1,358 @@
1
+ import type { LocaleStrings } from "@aidc-toolkit/core";
2
+ import * as fs from "node:fs";
3
+ import * as path from "node:path";
4
+ import { expandParameterDescriptor, type ParameterDescriptor } from "../descriptor.js";
5
+ import type { ProxyFunctionDescriptor } from "./descriptor.js";
6
+ import { Generator } from "./generator.js";
7
+ import { logger } from "./logger.js";
8
+
9
+ /**
10
+ * Parameters sequencer entry.
11
+ */
12
+ interface ParametersSequencerEntry {
13
+ /**
14
+ * Parameters sequence or null if automatic.
15
+ */
16
+ parametersSequencerOrNull: ParametersSequencer | null;
17
+
18
+ /**
19
+ * Parameter descriptor.
20
+ */
21
+ parameterDescriptor: ParameterDescriptor;
22
+
23
+ /**
24
+ * True if parameter is actually used and not just a base.
25
+ */
26
+ isUsed: boolean;
27
+ }
28
+
29
+ /**
30
+ * Parameters sequencer for keeping similar (extended) parameters together.
31
+ */
32
+ type ParametersSequencer = Record<string, ParametersSequencerEntry>;
33
+
34
+ /**
35
+ * Format of locale strings module.
36
+ */
37
+ interface LocaleStringsModule {
38
+ /**
39
+ * Locale strings.
40
+ */
41
+ localeStrings: LocaleStrings;
42
+ }
43
+
44
+ /**
45
+ * Locale strings generator.
46
+ */
47
+ class LocaleStringsGenerator extends Generator {
48
+ /**
49
+ * Locale strings import path.
50
+ */
51
+ private static readonly IMPORT_PATH = "../app-extension/src/locale";
52
+
53
+ /**
54
+ * Parameters sequencer.
55
+ */
56
+ private readonly _parametersSequencer: ParametersSequencer = {};
57
+
58
+ /**
59
+ * Parameters locale strings.
60
+ */
61
+ private readonly _parametersLocaleStrings: LocaleStrings = {};
62
+
63
+ /**
64
+ * Functions locale strings.
65
+ */
66
+ private readonly _functionsLocaleStrings: LocaleStrings = {};
67
+
68
+ /**
69
+ * Locale strings.
70
+ */
71
+ private readonly _localeStrings: LocaleStrings = {
72
+ Parameters: this._parametersLocaleStrings,
73
+ Functions: this._functionsLocaleStrings
74
+ };
75
+
76
+ /**
77
+ * Constructor.
78
+ */
79
+ constructor() {
80
+ super(false);
81
+ }
82
+
83
+ /**
84
+ * @inheritDoc
85
+ */
86
+ protected initialize(): void {
87
+ }
88
+
89
+ /**
90
+ * @inheritDoc
91
+ */
92
+ protected createProxyObject(): void {
93
+ }
94
+
95
+ /**
96
+ * Save a parameter descriptor in the appropriate spot in the sequence.
97
+ *
98
+ * @param parameterDescriptor
99
+ * Parameter descriptor.
100
+ *
101
+ * @param isUsed
102
+ * True if parameter descriptor is actually used and not just a base.
103
+ *
104
+ * @returns
105
+ * Parameters sequencer entry.
106
+ */
107
+ private saveParameterSequence(parameterDescriptor: ParameterDescriptor, isUsed: boolean): ParametersSequencerEntry {
108
+ let parametersSequencerEntry: ParametersSequencerEntry;
109
+
110
+ if (!("extendsDescriptor" in parameterDescriptor)) {
111
+ const parameterName = parameterDescriptor.name;
112
+
113
+ // Create entry if it doesn't exist, otherwise pick up where last call left off.
114
+ if (!(parameterName in this._parametersSequencer)) {
115
+ parametersSequencerEntry = {
116
+ parametersSequencerOrNull: null,
117
+ parameterDescriptor,
118
+ isUsed
119
+ };
120
+
121
+ this._parametersSequencer[parameterName] = parametersSequencerEntry;
122
+ } else {
123
+ parametersSequencerEntry = this._parametersSequencer[parameterName];
124
+ }
125
+ } else {
126
+ const baseParametersSequencerEntry = this.saveParameterSequence(parameterDescriptor.extendsDescriptor, false);
127
+
128
+ const expandedParameterDescriptor = expandParameterDescriptor(parameterDescriptor);
129
+ const parameterName = expandedParameterDescriptor.name;
130
+
131
+ if (parameterName !== expandParameterDescriptor(parameterDescriptor.extendsDescriptor).name) {
132
+ // Make sure that base parameters sequencer entry refers to a record type.
133
+ baseParametersSequencerEntry.parametersSequencerOrNull ??= {};
134
+
135
+ if (!(parameterName in baseParametersSequencerEntry.parametersSequencerOrNull)) {
136
+ parametersSequencerEntry = {
137
+ parametersSequencerOrNull: null,
138
+ parameterDescriptor,
139
+ isUsed
140
+ };
141
+
142
+ baseParametersSequencerEntry.parametersSequencerOrNull[parameterName] = parametersSequencerEntry;
143
+ } else {
144
+ parametersSequencerEntry = baseParametersSequencerEntry.parametersSequencerOrNull[parameterName];
145
+ }
146
+ } else {
147
+ // If name is the same, which means that parameter descriptor modified type information only.
148
+ parametersSequencerEntry = baseParametersSequencerEntry;
149
+ }
150
+ }
151
+
152
+ return parametersSequencerEntry;
153
+ }
154
+
155
+ /**
156
+ * @inheritDoc
157
+ */
158
+ protected createProxyFunction(proxyFunctionDescriptor: ProxyFunctionDescriptor): void {
159
+ const {
160
+ namespace,
161
+ functionName,
162
+ methodDescriptor
163
+ } = proxyFunctionDescriptor;
164
+
165
+ // Add any parameters that are not already known.
166
+ for (const parameterDescriptor of methodDescriptor.parameterDescriptors) {
167
+ this.saveParameterSequence(parameterDescriptor, true);
168
+ }
169
+
170
+ let functionsLocaleStrings = this._functionsLocaleStrings;
171
+
172
+ if (namespace !== undefined) {
173
+ if (!(namespace in functionsLocaleStrings)) {
174
+ const namespaceFunctionsLocaleStrings: LocaleStrings = {};
175
+
176
+ // Add namespace and navigate to it.
177
+ functionsLocaleStrings[namespace] = namespaceFunctionsLocaleStrings;
178
+ functionsLocaleStrings = namespaceFunctionsLocaleStrings;
179
+ } else {
180
+ // Navigate to namespace.
181
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Entry is never a string.
182
+ functionsLocaleStrings = functionsLocaleStrings[namespace] as LocaleStrings;
183
+ }
184
+ }
185
+
186
+ if (functionName in functionsLocaleStrings) {
187
+ throw new Error(`Duplicate function "${functionName}"`);
188
+ }
189
+
190
+ // Add function.
191
+ functionsLocaleStrings[functionName] = {
192
+ name: functionName,
193
+ description: "*** LOCALIZATION REQUIRED ***"
194
+ };
195
+ }
196
+
197
+ /**
198
+ * Merge source locale strings into existing destination locale strings.
199
+ *
200
+ * @param logChanges
201
+ * If true, changes are logged. Limits output when processing multiple sources.
202
+ *
203
+ * @param parentKey
204
+ * Parent key for logging purposes.
205
+ *
206
+ * @param sourceLocaleStrings
207
+ * Source locale strings.
208
+ *
209
+ * @param destinationLocaleStrings
210
+ * Destination locale strings.
211
+ *
212
+ * @param addMissing
213
+ * Add missing if true; applies to locale strings that are not regional.
214
+ *
215
+ * @returns
216
+ * Merged locale strings.
217
+ */
218
+ private static merge(logChanges: boolean, parentKey: string, sourceLocaleStrings: LocaleStrings, destinationLocaleStrings: LocaleStrings, addMissing: boolean): LocaleStrings {
219
+ // Some entries at the top are not part of the generator output.
220
+ const deleteMissing = parentKey.length !== 0;
221
+
222
+ const newDestinationLocaleStrings: LocaleStrings = {};
223
+
224
+ // Copy over or delete any destination keys that are not in source.
225
+ for (const [key, destinationValue] of Object.entries(destinationLocaleStrings)) {
226
+ if (!(key in sourceLocaleStrings)) {
227
+ if (!deleteMissing) {
228
+ newDestinationLocaleStrings[key] = destinationValue;
229
+ } else if (logChanges) {
230
+ logger.info(`Deleting ${parentKey}${key}...`);
231
+ }
232
+ }
233
+ }
234
+
235
+ for (const [key, sourceValue] of Object.entries(sourceLocaleStrings)) {
236
+ if (!(key in destinationLocaleStrings)) {
237
+ if (addMissing) {
238
+ if (logChanges) {
239
+ logger.info(`Adding ${parentKey}${key}...`);
240
+ }
241
+
242
+ newDestinationLocaleStrings[key] = sourceValue;
243
+ }
244
+ } else {
245
+ const destinationValue = destinationLocaleStrings[key];
246
+
247
+ if (typeof sourceValue === "object" && typeof destinationValue === "object") {
248
+ newDestinationLocaleStrings[key] = LocaleStringsGenerator.merge(logChanges, `${parentKey}${key}.`, sourceValue, destinationValue, addMissing);
249
+ } else if (typeof sourceValue === "string" && typeof destinationValue === "string") {
250
+ newDestinationLocaleStrings[key] = destinationValue;
251
+ } else {
252
+ throw new Error(`Mismatched types at ${parentKey}${key}`);
253
+ }
254
+ }
255
+ }
256
+
257
+ return newDestinationLocaleStrings;
258
+ }
259
+
260
+ /**
261
+ * Build parameters locale strings by going through parameters sequencer.
262
+ *
263
+ * @param parametersSequencer
264
+ * Parameters sequencer.
265
+ */
266
+ private buildParametersLocaleStrings(parametersSequencer: ParametersSequencer): void {
267
+ const entries = Object.entries(parametersSequencer);
268
+
269
+ // Sort the entries as defined by the descriptors.
270
+ entries.sort((entry1, entry2) => {
271
+ let result: number;
272
+
273
+ const parameterDescriptor1 = entry1[1].parameterDescriptor;
274
+ const parameterDescriptor2 = entry2[1].parameterDescriptor;
275
+
276
+ if ("sortOrder" in parameterDescriptor1) {
277
+ if ("sortOrder" in parameterDescriptor2) {
278
+ result = parameterDescriptor1.sortOrder - parameterDescriptor2.sortOrder;
279
+ } else {
280
+ // Parameter descriptors with undefined sort order to go the end.
281
+ result = -parameterDescriptor1.sortOrder;
282
+ }
283
+ } else {
284
+ // eslint-disable-next-line no-lonely-if -- Matches structure in "then" clause.
285
+ if ("sortOrder" in parameterDescriptor2) {
286
+ // Parameter descriptors with undefined sort order to go the end.
287
+ result = parameterDescriptor2.sortOrder;
288
+ } else {
289
+ result = 0;
290
+ }
291
+ }
292
+
293
+ return result;
294
+ });
295
+
296
+ for (const [parameterName, parametersSequencerEntry] of entries) {
297
+ if (parametersSequencerEntry.isUsed) {
298
+ this._parametersLocaleStrings[parameterName] = {
299
+ name: parameterName,
300
+ description: "*** LOCALIZATION REQUIRED ***"
301
+ };
302
+ }
303
+
304
+ if (parametersSequencerEntry.parametersSequencerOrNull !== null) {
305
+ this.buildParametersLocaleStrings(parametersSequencerEntry.parametersSequencerOrNull);
306
+ }
307
+ }
308
+ }
309
+
310
+ /**
311
+ * Build output to be written back to source file.
312
+ *
313
+ * @param prefix
314
+ * Line prefix.
315
+ *
316
+ * @param value
317
+ * Line value.
318
+ *
319
+ * @param indentLevel
320
+ * Indent level.
321
+ *
322
+ * @returns
323
+ * Output string.
324
+ */
325
+ private static buildOutput(prefix: string, value: LocaleStrings | string, indentLevel: number): string {
326
+ return `${" ".repeat(indentLevel)}${prefix} ${typeof value === "object" ?
327
+ `{\n${
328
+ Object.entries(value).map(entry => LocaleStringsGenerator.buildOutput(`${entry[0]}:`, entry[1], indentLevel + 1)).join(",\n")
329
+ }\n${" ".repeat(indentLevel)}}` :
330
+ // JSON.stringify() will apply quotes as appropriate.
331
+ JSON.stringify(value)
332
+ }`;
333
+ }
334
+
335
+ /**
336
+ * @inheritDoc
337
+ */
338
+ protected async finalize(success: boolean): Promise<void> {
339
+ if (success) {
340
+ this.buildParametersLocaleStrings(this._parametersSequencer);
341
+
342
+ await Promise.all(fs.readdirSync(LocaleStringsGenerator.IMPORT_PATH, {
343
+ withFileTypes: true
344
+ }).filter(entry => entry.isDirectory()).map(async (entry) => {
345
+ const localeStringsSource = path.resolve(LocaleStringsGenerator.IMPORT_PATH, entry.name, "locale-strings.ts");
346
+
347
+ await import(localeStringsSource).then((module) => {
348
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Module format is known.
349
+ const localeStrings = LocaleStringsGenerator.merge(entry.name === "en", "", this._localeStrings, (module as LocaleStringsModule).localeStrings, !entry.name.includes("-"));
350
+
351
+ fs.writeFileSync(localeStringsSource, `${LocaleStringsGenerator.buildOutput("export const localeStrings =", localeStrings, 0)};\n`);
352
+ });
353
+ }));
354
+ }
355
+ }
356
+ }
357
+
358
+ await new LocaleStringsGenerator().generate();
@@ -0,0 +1,45 @@
1
+ import { Logger } from "tslog";
2
+
3
+ /**
4
+ * Log levels.
5
+ */
6
+ export const LogLevels = {
7
+ Silly: 0,
8
+ Trace: 1,
9
+ Debug: 2,
10
+ Info: 3,
11
+ Warn: 4,
12
+ Error: 5,
13
+ Fatal: 6
14
+ } as const;
15
+
16
+ /**
17
+ * Log level.
18
+ */
19
+ export type LogLevel = typeof LogLevels[keyof typeof LogLevels];
20
+
21
+ /**
22
+ * Logger with a default minimum level of Info.
23
+ */
24
+ export const logger = new Logger({
25
+ minLevel: LogLevels.Info
26
+ });
27
+
28
+ /**
29
+ * Set the log level.
30
+ *
31
+ * @param logLevel
32
+ * Log level as enumeration value or string.
33
+ */
34
+ export function setLogLevel(logLevel: string | number): void {
35
+ if (typeof logLevel === "string") {
36
+ if (logLevel in LogLevels) {
37
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- String exists as a key.
38
+ logger.settings.minLevel = LogLevels[logLevel as keyof typeof LogLevels];
39
+ } else {
40
+ logger.error(`Unknown log level ${logLevel}`);
41
+ }
42
+ } else {
43
+ logger.settings.minLevel = logLevel;
44
+ }
45
+ }
@@ -6,13 +6,13 @@ import {
6
6
  isValidPriceOrWeightCheckDigit,
7
7
  priceOrWeightCheckDigit
8
8
  } from "@aidc-toolkit/gs1";
9
- import { type ParameterDescriptor, ProxyClass, ProxyMethod, ProxyParameter, Type } from "../descriptor.js";
9
+ import { type ParameterDescriptor, ProxyClass, ProxyMethod, ProxyParameter, Types } from "../descriptor.js";
10
10
  import { LibProxy } from "../lib-proxy.js";
11
11
  import type { ErrorExtends, Matrix, MatrixResultError, ResultError } from "../types.js";
12
12
 
13
13
  const checkSParameterDescriptor: ParameterDescriptor = {
14
14
  name: "checkS",
15
- type: Type.String,
15
+ type: Types.String,
16
16
  isMatrix: true,
17
17
  isRequired: true
18
18
  };
@@ -57,7 +57,7 @@ const ai82SWithCheckCharacterPairParameterDescriptor: ParameterDescriptor = {
57
57
  })
58
58
  export class CheckProxy<ThrowError extends boolean, TError extends ErrorExtends<ThrowError>, TInvocationContext, TBigInt> extends LibProxy<ThrowError, TError, TInvocationContext, TBigInt> {
59
59
  @ProxyMethod({
60
- type: Type.String,
60
+ type: Types.String,
61
61
  isMatrix: true
62
62
  })
63
63
  checkDigit(
@@ -67,7 +67,7 @@ export class CheckProxy<ThrowError extends boolean, TError extends ErrorExtends<
67
67
  }
68
68
 
69
69
  @ProxyMethod({
70
- type: Type.String,
70
+ type: Types.String,
71
71
  isMatrix: true
72
72
  })
73
73
  hasValidCheckDigit(
@@ -77,7 +77,7 @@ export class CheckProxy<ThrowError extends boolean, TError extends ErrorExtends<
77
77
  }
78
78
 
79
79
  @ProxyMethod({
80
- type: Type.String,
80
+ type: Types.String,
81
81
  isMatrix: true
82
82
  })
83
83
  priceOrWeightCheckDigit(
@@ -87,7 +87,7 @@ export class CheckProxy<ThrowError extends boolean, TError extends ErrorExtends<
87
87
  }
88
88
 
89
89
  @ProxyMethod({
90
- type: Type.String,
90
+ type: Types.String,
91
91
  isMatrix: false
92
92
  })
93
93
  isValidPriceOrWeightCheckDigit(
@@ -101,7 +101,7 @@ export class CheckProxy<ThrowError extends boolean, TError extends ErrorExtends<
101
101
  }
102
102
 
103
103
  @ProxyMethod({
104
- type: Type.String,
104
+ type: Types.String,
105
105
  isMatrix: true
106
106
  })
107
107
  checkCharacterPair(
@@ -111,7 +111,7 @@ export class CheckProxy<ThrowError extends boolean, TError extends ErrorExtends<
111
111
  }
112
112
 
113
113
  @ProxyMethod({
114
- type: Type.String,
114
+ type: Types.String,
115
115
  isMatrix: true
116
116
  })
117
117
  hasValidCheckCharacterPair(