@aidc-toolkit/app-extension 1.0.31-beta → 1.0.33-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.
- package/dist/index.cjs +1 -3709
- package/dist/index.d.cts +607 -333
- package/dist/index.d.ts +607 -333
- package/dist/index.js +1 -3683
- package/package.json +12 -13
- package/src/app-extension.ts +141 -93
- package/src/app-helper-proxy.ts +326 -0
- package/src/descriptor.ts +75 -7
- package/src/generator/generator.ts +118 -96
- package/src/generator/locale-resources-generator.ts +56 -42
- package/src/gs1/character-set-proxy.ts +8 -8
- package/src/gs1/check-proxy.ts +26 -25
- package/src/gs1/gtin-creator-proxy.ts +14 -28
- package/src/gs1/gtin-descriptor.ts +2 -23
- package/src/gs1/gtin-validator-proxy.ts +45 -48
- package/src/gs1/identifier-creator-proxy.ts +63 -53
- package/src/gs1/identifier-descriptor.ts +15 -0
- package/src/gs1/identifier-type.ts +37 -0
- package/src/gs1/identifier-validator-proxy.ts +59 -27
- package/src/gs1/index.ts +8 -0
- package/src/gs1/non-gtin-creator-proxy.ts +22 -33
- package/src/gs1/non-gtin-validator-proxy.ts +22 -33
- package/src/gs1/prefix-definition-descriptor.ts +2 -2
- package/src/gs1/prefix-manager-proxy.ts +164 -9
- package/src/gs1/service-proxy.ts +57 -0
- package/src/gs1/variable-measure-proxy.ts +62 -0
- package/src/index.ts +6 -1
- package/src/lib-proxy.ts +112 -70
- package/src/locale/en/locale-resources.ts +173 -47
- package/src/locale/fr/locale-resources.ts +173 -47
- package/src/locale/i18n.ts +8 -10
- package/src/locale/i18next.d.ts +2 -0
- package/src/proxy.ts +140 -140
- package/src/streaming.ts +13 -0
- package/src/type.ts +8 -7
- package/src/utility/character-set-descriptor.ts +2 -2
- package/src/utility/character-set-proxy.ts +39 -38
- package/src/utility/reg-exp-proxy.ts +12 -11
- package/src/utility/string-descriptor.ts +2 -2
- package/src/utility/string-proxy.ts +7 -7
- package/src/utility/transformer-descriptor.ts +5 -5
- package/src/utility/transformer-proxy.ts +25 -18
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/src/app-utility-proxy.ts +0 -273
package/src/proxy.ts
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type AbstractConstructor,
|
|
3
3
|
type Constructor,
|
|
4
|
-
|
|
5
|
-
type LogLevel,
|
|
6
|
-
LogLevels,
|
|
4
|
+
loggableValue,
|
|
7
5
|
omit,
|
|
8
6
|
type TypedAbstractConstructor
|
|
9
7
|
} from "@aidc-toolkit/core";
|
|
10
8
|
import type { Logger } from "tslog";
|
|
11
9
|
import type { AppExtension } from "./app-extension.js";
|
|
12
|
-
import
|
|
13
|
-
ClassDescriptor,
|
|
14
|
-
ExtendsParameterDescriptor,
|
|
15
|
-
MethodDescriptor,
|
|
16
|
-
|
|
10
|
+
import {
|
|
11
|
+
type ClassDescriptor,
|
|
12
|
+
type ExtendsParameterDescriptor,
|
|
13
|
+
type MethodDescriptor,
|
|
14
|
+
Multiplicities,
|
|
15
|
+
type ParameterDescriptor,
|
|
16
|
+
type ReplacementParameterDescriptor
|
|
17
17
|
} from "./descriptor.js";
|
|
18
18
|
import { LibProxy } from "./lib-proxy.js";
|
|
19
19
|
import type { ErrorExtends } from "./type.js";
|
|
@@ -21,7 +21,7 @@ import type { ErrorExtends } from "./type.js";
|
|
|
21
21
|
/**
|
|
22
22
|
* Remaining parameters past first parameter in constructor.
|
|
23
23
|
*/
|
|
24
|
-
type
|
|
24
|
+
type RemainingConstructorParameters<TConstructor extends TypedAbstractConstructor<TConstructor>> =
|
|
25
25
|
TConstructor extends abstract new (arg0: infer _P0, ...args: infer P) => InstanceType<TConstructor> ? P : never;
|
|
26
26
|
|
|
27
27
|
/**
|
|
@@ -38,13 +38,13 @@ type RemainingParameters<TConstructor extends TypedAbstractConstructor<TConstruc
|
|
|
38
38
|
* Proxy class constructor type.
|
|
39
39
|
*/
|
|
40
40
|
type ProxyClassConstructor<
|
|
41
|
-
ThrowError extends boolean, TError extends ErrorExtends<ThrowError>, TInvocationContext, TBigInt,
|
|
42
|
-
T extends LibProxy<ThrowError, TError, TInvocationContext, TBigInt>,
|
|
41
|
+
ThrowError extends boolean, TError extends ErrorExtends<ThrowError>, TInvocationContext, TStreamingInvocationContext, TBigInt,
|
|
42
|
+
T extends LibProxy<ThrowError, TError, TInvocationContext, TStreamingInvocationContext, TBigInt>,
|
|
43
43
|
IsAbstract extends boolean,
|
|
44
44
|
TConstructor extends TypedAbstractConstructor<TConstructor>
|
|
45
45
|
> = IsAbstract extends true ?
|
|
46
|
-
AbstractConstructor<[appExtension: AppExtension<ThrowError, TError, TInvocationContext, TBigInt>, ...args:
|
|
47
|
-
Constructor<[appExtension: AppExtension<ThrowError, TError, TInvocationContext, TBigInt>], T>;
|
|
46
|
+
AbstractConstructor<[appExtension: AppExtension<ThrowError, TError, TInvocationContext, TStreamingInvocationContext, TBigInt>, ...args: RemainingConstructorParameters<TConstructor>], T> :
|
|
47
|
+
Constructor<[appExtension: AppExtension<ThrowError, TError, TInvocationContext, TStreamingInvocationContext, TBigInt>], T>;
|
|
48
48
|
|
|
49
49
|
/**
|
|
50
50
|
* Class decorator type. Defines the parameters passed to a class decorator function and the return type as identical to
|
|
@@ -63,11 +63,11 @@ type ProxyClassConstructor<
|
|
|
63
63
|
* Narrowed proxy class constructor type.
|
|
64
64
|
*/
|
|
65
65
|
type ClassDecorator<
|
|
66
|
-
ThrowError extends boolean, TError extends ErrorExtends<ThrowError>, TInvocationContext, TBigInt,
|
|
67
|
-
T extends LibProxy<ThrowError, TError, TInvocationContext, TBigInt>,
|
|
66
|
+
ThrowError extends boolean, TError extends ErrorExtends<ThrowError>, TInvocationContext, TStreamingInvocationContext, TBigInt,
|
|
67
|
+
T extends LibProxy<ThrowError, TError, TInvocationContext, TStreamingInvocationContext, TBigInt>,
|
|
68
68
|
IsAbstract extends boolean,
|
|
69
69
|
TConstructor extends TypedAbstractConstructor<TConstructor>,
|
|
70
|
-
TProxyClassConstructor extends ProxyClassConstructor<ThrowError, TError, TInvocationContext, TBigInt, T, IsAbstract, TConstructor>
|
|
70
|
+
TProxyClassConstructor extends ProxyClassConstructor<ThrowError, TError, TInvocationContext, TStreamingInvocationContext, TBigInt, T, IsAbstract, TConstructor>
|
|
71
71
|
> = (Target: TProxyClassConstructor, context: ClassDecoratorContext<TProxyClassConstructor>) => TProxyClassConstructor;
|
|
72
72
|
|
|
73
73
|
/**
|
|
@@ -88,21 +88,22 @@ type InterimMethodDescriptor = Omit<MethodDescriptor, "functionName" | "namespac
|
|
|
88
88
|
/**
|
|
89
89
|
* Subset of method descriptor used in call to decorator.
|
|
90
90
|
*/
|
|
91
|
-
|
|
91
|
+
interface DecoratorMethodDescriptor extends Omit<InterimMethodDescriptor, "name" | "parameterDescriptors"> {
|
|
92
92
|
parameterDescriptors: Array<ParameterDescriptor | ExtendsParameterDescriptor>;
|
|
93
|
-
}
|
|
93
|
+
}
|
|
94
94
|
|
|
95
95
|
/**
|
|
96
96
|
* Subset of class descriptor used during decoration process.
|
|
97
97
|
*/
|
|
98
|
-
|
|
99
|
-
|
|
98
|
+
interface InterimClassDescriptor extends Omit<ClassDescriptor, "name" | "category" | "namespaceClassName" | "objectName" | "methodDescriptors"> {
|
|
99
|
+
readonly category?: string;
|
|
100
|
+
}
|
|
100
101
|
|
|
101
102
|
/**
|
|
102
103
|
* Subset of class descriptor used in call to decorator.
|
|
103
104
|
*/
|
|
104
|
-
interface DecoratorClassDescriptor extends Omit<InterimClassDescriptor, "
|
|
105
|
-
readonly
|
|
105
|
+
interface DecoratorClassDescriptor extends Omit<InterimClassDescriptor, "replacementParameterDescriptors"> {
|
|
106
|
+
readonly replacementParameterDescriptors?: ReadonlyArray<Omit<ReplacementParameterDescriptor, "replacement"> & {
|
|
106
107
|
readonly replacement: ParameterDescriptor | ExtendsParameterDescriptor;
|
|
107
108
|
}>;
|
|
108
109
|
}
|
|
@@ -145,10 +146,12 @@ interface Interim {
|
|
|
145
146
|
*/
|
|
146
147
|
interface TargetLogger {
|
|
147
148
|
/**
|
|
148
|
-
*
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
149
|
+
* Logger.
|
|
150
|
+
*/
|
|
151
|
+
readonly logger: Logger<object>;
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Build a function that returns a loggable value for a method call.
|
|
152
155
|
*
|
|
153
156
|
* @param methodName
|
|
154
157
|
* Method name.
|
|
@@ -159,7 +162,7 @@ interface TargetLogger {
|
|
|
159
162
|
* @param result
|
|
160
163
|
* Output result.
|
|
161
164
|
*/
|
|
162
|
-
|
|
165
|
+
callBuilder: (methodName: string, args: unknown[], result: unknown) => () => unknown;
|
|
163
166
|
}
|
|
164
167
|
|
|
165
168
|
/**
|
|
@@ -167,71 +170,26 @@ interface TargetLogger {
|
|
|
167
170
|
*/
|
|
168
171
|
export class Proxy {
|
|
169
172
|
/**
|
|
170
|
-
*
|
|
173
|
+
* Abstract class descriptors map, keyed on declaration class. Abstract classes are not used directly by target
|
|
174
|
+
* applications.
|
|
171
175
|
*/
|
|
172
|
-
|
|
173
|
-
// TODO Change this to LogLevels.Trace when configuration available.
|
|
174
|
-
readonly #logger: Logger<unknown> = getLogger(LogLevels.Info);
|
|
176
|
+
readonly #abstractClassDescriptorsMap = new Map<typeof LibProxy, ClassDescriptor>();
|
|
175
177
|
|
|
176
178
|
/**
|
|
177
|
-
*
|
|
178
|
-
* applications.
|
|
179
|
+
* Concrete class descriptors map, keyed on declaration class.
|
|
179
180
|
*/
|
|
180
|
-
readonly #
|
|
181
|
+
readonly #concreteClassDescriptorsMap = new Map<typeof LibProxy, ClassDescriptor>();
|
|
181
182
|
|
|
182
183
|
/**
|
|
183
|
-
*
|
|
184
|
+
* Namespace class names set for duplicate detection.
|
|
184
185
|
*/
|
|
185
|
-
readonly #
|
|
186
|
+
readonly #namespaceClassNamesSet = new Set<string>();
|
|
186
187
|
|
|
187
188
|
/**
|
|
188
189
|
* Interim object.
|
|
189
190
|
*/
|
|
190
191
|
#interim: Interim | undefined = undefined;
|
|
191
192
|
|
|
192
|
-
/**
|
|
193
|
-
* Get the proper JSON representation of a value.
|
|
194
|
-
*
|
|
195
|
-
* @param value
|
|
196
|
-
* Value.
|
|
197
|
-
*
|
|
198
|
-
* @returns
|
|
199
|
-
* Replacement value.
|
|
200
|
-
*/
|
|
201
|
-
static #jsonValue(value: unknown): unknown {
|
|
202
|
-
let replacementValue: unknown;
|
|
203
|
-
|
|
204
|
-
switch (typeof value) {
|
|
205
|
-
case "string":
|
|
206
|
-
case "number":
|
|
207
|
-
case "boolean":
|
|
208
|
-
case "undefined":
|
|
209
|
-
replacementValue = value;
|
|
210
|
-
break;
|
|
211
|
-
|
|
212
|
-
case "bigint":
|
|
213
|
-
// Big integers not supported in JSON.
|
|
214
|
-
replacementValue = value >= Number.MIN_SAFE_INTEGER && value <= Number.MAX_SAFE_INTEGER ? Number(value) : value.toString(10);
|
|
215
|
-
break;
|
|
216
|
-
|
|
217
|
-
case "object":
|
|
218
|
-
if (value === null) {
|
|
219
|
-
replacementValue = value;
|
|
220
|
-
} else if (Array.isArray(value)) {
|
|
221
|
-
replacementValue = value.map(entry => Proxy.#jsonValue(entry));
|
|
222
|
-
} else {
|
|
223
|
-
replacementValue = Object.fromEntries(Object.entries(value).map(([k, v]) => [k, Proxy.#jsonValue(v)]));
|
|
224
|
-
}
|
|
225
|
-
break;
|
|
226
|
-
|
|
227
|
-
case "symbol":
|
|
228
|
-
case "function":
|
|
229
|
-
throw new Error(`Unsupported ${typeof value} value type`);
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
return replacementValue;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
193
|
/**
|
|
236
194
|
* Describe a proxy class.
|
|
237
195
|
*
|
|
@@ -257,17 +215,17 @@ export class Proxy {
|
|
|
257
215
|
* Function with which to decorate the class.
|
|
258
216
|
*/
|
|
259
217
|
describeClass<
|
|
260
|
-
ThrowError extends boolean, TError extends ErrorExtends<ThrowError>, TInvocationContext, TBigInt,
|
|
261
|
-
T extends LibProxy<ThrowError, TError, TInvocationContext, TBigInt>,
|
|
218
|
+
ThrowError extends boolean, TError extends ErrorExtends<ThrowError>, TInvocationContext, TStreamingInvocationContext, TBigInt,
|
|
219
|
+
T extends LibProxy<ThrowError, TError, TInvocationContext, TStreamingInvocationContext, TBigInt>,
|
|
262
220
|
IsAbstract extends boolean,
|
|
263
221
|
TConstructor extends TypedAbstractConstructor<TConstructor>,
|
|
264
|
-
TProxyClassConstructor extends ProxyClassConstructor<ThrowError, TError, TInvocationContext, TBigInt, T, IsAbstract, TConstructor>
|
|
265
|
-
>(isAbstract: IsAbstract, decoratorClassDescriptor: DecoratorClassDescriptor = {}): ClassDecorator<ThrowError, TError, TInvocationContext, TBigInt, T, IsAbstract, TConstructor, TProxyClassConstructor> {
|
|
266
|
-
const interimClassDescriptor: InterimClassDescriptor = decoratorClassDescriptor.
|
|
267
|
-
omit(decoratorClassDescriptor, "
|
|
222
|
+
TProxyClassConstructor extends ProxyClassConstructor<ThrowError, TError, TInvocationContext, TStreamingInvocationContext, TBigInt, T, IsAbstract, TConstructor>
|
|
223
|
+
>(isAbstract: IsAbstract, decoratorClassDescriptor: DecoratorClassDescriptor = {}): ClassDecorator<ThrowError, TError, TInvocationContext, TStreamingInvocationContext, TBigInt, T, IsAbstract, TConstructor, TProxyClassConstructor> {
|
|
224
|
+
const interimClassDescriptor: InterimClassDescriptor = decoratorClassDescriptor.replacementParameterDescriptors === undefined ?
|
|
225
|
+
omit(decoratorClassDescriptor, "replacementParameterDescriptors") :
|
|
268
226
|
{
|
|
269
227
|
...decoratorClassDescriptor,
|
|
270
|
-
|
|
228
|
+
replacementParameterDescriptors: decoratorClassDescriptor.replacementParameterDescriptors.map(replaceParameterDescriptor => ({
|
|
271
229
|
...replaceParameterDescriptor,
|
|
272
230
|
replacement: expandParameterDescriptor(replaceParameterDescriptor.replacement)
|
|
273
231
|
}))
|
|
@@ -281,44 +239,41 @@ export class Proxy {
|
|
|
281
239
|
this.#interim = interim;
|
|
282
240
|
|
|
283
241
|
return (Target: TProxyClassConstructor, context: ClassDecoratorContext<TProxyClassConstructor>) => {
|
|
284
|
-
const
|
|
242
|
+
const className = context.name;
|
|
285
243
|
|
|
286
244
|
// Validate that class descriptor is applied within an appropriate class.
|
|
287
|
-
if (
|
|
288
|
-
throw new Error(
|
|
245
|
+
if (className === undefined) {
|
|
246
|
+
throw new Error("Class has no name");
|
|
289
247
|
}
|
|
290
248
|
|
|
291
|
-
const namespacePrefix = decoratorClassDescriptor.namespace === undefined ? "" : `${decoratorClassDescriptor.namespace}.`;
|
|
292
|
-
const namespaceClassName = `${namespacePrefix}${name}`;
|
|
293
|
-
|
|
294
249
|
const abstractClassDescriptorsMap = this.#abstractClassDescriptorsMap;
|
|
295
250
|
const concreteClassDescriptorsMap = this.#concreteClassDescriptorsMap;
|
|
296
251
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Class hierarchy is known.
|
|
302
|
-
let baseClassType: typeof LibProxy = Target as unknown as typeof LibProxy;
|
|
252
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Target is known to be of type LibProxy.
|
|
253
|
+
const targetClassType = Target as unknown as typeof LibProxy;
|
|
254
|
+
let baseClassType = targetClassType;
|
|
303
255
|
let baseClassDescriptor: ClassDescriptor | undefined;
|
|
304
256
|
|
|
305
257
|
do {
|
|
306
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Class hierarchy is known.
|
|
258
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Class hierarchy is known to stop at LibProxy.
|
|
307
259
|
baseClassType = Object.getPrototypeOf(baseClassType) as typeof LibProxy;
|
|
308
260
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
// Look first within the namespace and then in no namespace, in both abstract class descriptors map and concrete class descriptors map.
|
|
312
|
-
baseClassDescriptor =
|
|
313
|
-
abstractClassDescriptorsMap.get(namespaceBaseClassName) ?? abstractClassDescriptorsMap.get(baseClassType.name) ??
|
|
314
|
-
concreteClassDescriptorsMap.get(namespaceBaseClassName) ?? concreteClassDescriptorsMap.get(baseClassType.name);
|
|
261
|
+
// Look in both abstract class descriptors map and concrete class descriptors map.
|
|
262
|
+
baseClassDescriptor = abstractClassDescriptorsMap.get(baseClassType) ?? concreteClassDescriptorsMap.get(baseClassType);
|
|
315
263
|
} while (baseClassType !== LibProxy && baseClassDescriptor === undefined);
|
|
316
264
|
|
|
265
|
+
let namespace = interimClassDescriptor.namespace;
|
|
266
|
+
let category = interimClassDescriptor.category;
|
|
267
|
+
|
|
317
268
|
let interimMethodDescriptors: InterimMethodDescriptor[];
|
|
318
269
|
|
|
319
270
|
if (baseClassDescriptor !== undefined) {
|
|
271
|
+
// Inherit namespace and category from base class if not explicitly defined.
|
|
272
|
+
namespace ??= baseClassDescriptor.namespace;
|
|
273
|
+
category ??= baseClassDescriptor.category;
|
|
274
|
+
|
|
320
275
|
const baseClassMethodDescriptors = baseClassDescriptor.methodDescriptors;
|
|
321
|
-
const replaceParameterDescriptors = decoratorClassDescriptor.
|
|
276
|
+
const replaceParameterDescriptors = decoratorClassDescriptor.replacementParameterDescriptors;
|
|
322
277
|
|
|
323
278
|
if (replaceParameterDescriptors !== undefined) {
|
|
324
279
|
const replacementParameterDescriptorsMap = new Map(replaceParameterDescriptors.map(replaceParameterDescriptor => [replaceParameterDescriptor.name, expandParameterDescriptor(replaceParameterDescriptor.replacement)]));
|
|
@@ -335,6 +290,19 @@ export class Proxy {
|
|
|
335
290
|
interimMethodDescriptors = [];
|
|
336
291
|
}
|
|
337
292
|
|
|
293
|
+
const namespacePrefix = namespace === undefined ? "" : `${namespace}.`;
|
|
294
|
+
const namespaceClassName = `${namespacePrefix}${className}`;
|
|
295
|
+
|
|
296
|
+
if (this.#namespaceClassNamesSet.has(namespaceClassName)) {
|
|
297
|
+
throw new Error(`Duplicate class ${namespaceClassName}`);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
if (category === undefined) {
|
|
301
|
+
throw new Error(`Missing category for ${namespaceClassName}`);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
this.#namespaceClassNamesSet.add(namespaceClassName);
|
|
305
|
+
|
|
338
306
|
// Replace base class method descriptors with matching names or append new method descriptor.
|
|
339
307
|
for (const classInterimMethodDescriptor of interim.methodDescriptors) {
|
|
340
308
|
const existingIndex = interimMethodDescriptors.findIndex(interimMethodDescriptor => interimMethodDescriptor.name === classInterimMethodDescriptor.name);
|
|
@@ -395,21 +363,23 @@ export class Proxy {
|
|
|
395
363
|
// Third capture group, separated by optional period, is:
|
|
396
364
|
// - single uppercase letter followed by zero or more characters (remainder of string); or
|
|
397
365
|
// - zero characters (empty string).
|
|
398
|
-
const objectNameGroups = /^(?<namespaceFirstWord>[A-Z]+[0-9]*|[A-Z][^A-Z.]*)(?<namespaceRemaining>[A-Z][^.]*|)\.?(?<className>[A-Z].*|)
|
|
366
|
+
const objectNameGroups = /^(?<namespaceFirstWord>[A-Z]+[0-9]*|[A-Z][^A-Z.]*)(?<namespaceRemaining>[A-Z][^.]*|)\.?(?<className>[A-Z].*|)$/u.exec(namespaceClassName)?.groups;
|
|
399
367
|
|
|
400
368
|
if (objectNameGroups === undefined) {
|
|
401
369
|
throw new Error(`${namespaceClassName} is not a valid namespace-qualified class name`);
|
|
402
370
|
}
|
|
403
371
|
|
|
404
372
|
const classDescriptor: ClassDescriptor = {
|
|
405
|
-
name,
|
|
406
373
|
...interimClassDescriptor,
|
|
374
|
+
name: className,
|
|
375
|
+
namespace,
|
|
376
|
+
category,
|
|
407
377
|
namespaceClassName,
|
|
408
378
|
objectName: `${objectNameGroups["namespaceFirstWord"].toLowerCase()}${objectNameGroups["namespaceRemaining"]}${objectNameGroups["className"]}`,
|
|
409
379
|
methodDescriptors
|
|
410
380
|
};
|
|
411
381
|
|
|
412
|
-
(isAbstract ? abstractClassDescriptorsMap : concreteClassDescriptorsMap).set(
|
|
382
|
+
(isAbstract ? abstractClassDescriptorsMap : concreteClassDescriptorsMap).set(targetClassType, classDescriptor);
|
|
413
383
|
|
|
414
384
|
const methodDescriptorsMap = new Map<string, MethodDescriptor>();
|
|
415
385
|
|
|
@@ -419,30 +389,35 @@ export class Proxy {
|
|
|
419
389
|
|
|
420
390
|
this.#interim = undefined;
|
|
421
391
|
|
|
422
|
-
const logger = this.#logger;
|
|
423
|
-
|
|
424
392
|
return class extends Target implements TargetLogger {
|
|
393
|
+
/**
|
|
394
|
+
* Get the logger.
|
|
395
|
+
*/
|
|
396
|
+
get logger(): Logger<object> {
|
|
397
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Type hierarchy is known.
|
|
398
|
+
return (this as unknown as T).appExtension.logger;
|
|
399
|
+
}
|
|
400
|
+
|
|
425
401
|
/**
|
|
426
402
|
* @inheritDoc
|
|
427
403
|
*/
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
}, null, 2));
|
|
404
|
+
callBuilder(methodName: string, args: unknown[], result: unknown): () => unknown {
|
|
405
|
+
return () => {
|
|
406
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- Method name is known to be valid at this point.
|
|
407
|
+
const methodDescriptor = methodDescriptorsMap.get(methodName)!;
|
|
408
|
+
|
|
409
|
+
return {
|
|
410
|
+
namespace,
|
|
411
|
+
className,
|
|
412
|
+
methodName,
|
|
413
|
+
functionName: methodDescriptor.functionName,
|
|
414
|
+
parameters: methodDescriptor.parameterDescriptors.map((parameterDescriptor, index) => ({
|
|
415
|
+
name: parameterDescriptor.name,
|
|
416
|
+
value: loggableValue(args[index])
|
|
417
|
+
})),
|
|
418
|
+
result: loggableValue(result)
|
|
419
|
+
};
|
|
420
|
+
};
|
|
446
421
|
}
|
|
447
422
|
};
|
|
448
423
|
};
|
|
@@ -464,9 +439,14 @@ export class Proxy {
|
|
|
464
439
|
return (target: (this: TThis, ...args: TArguments) => TReturn, context: ClassMethodDecoratorContext<TThis>): (this: TThis, ...args: TArguments) => TReturn => {
|
|
465
440
|
const name = context.name;
|
|
466
441
|
|
|
467
|
-
// Validate that method descriptor is applied within an appropriate class
|
|
468
|
-
if (this.#interim === undefined
|
|
469
|
-
throw new Error(
|
|
442
|
+
// Validate that method descriptor is applied within an appropriate class.
|
|
443
|
+
if (this.#interim === undefined) {
|
|
444
|
+
throw new Error(`Class for method ${String(name)} does not have a descriptor`);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// Validate that method descriptor has a valid name and is neither static nor private.
|
|
448
|
+
if (typeof name !== "string" || context.static || context.private) {
|
|
449
|
+
throw new Error(`Method ${String(name)} has an invalid name, is static, or is private`);
|
|
470
450
|
}
|
|
471
451
|
|
|
472
452
|
let anyOptional = false;
|
|
@@ -474,19 +454,24 @@ export class Proxy {
|
|
|
474
454
|
// Expand all parameter descriptors.
|
|
475
455
|
const parameterDescriptors = decoratorMethodDescriptor.parameterDescriptors.map((decoratorParameterDescriptor) => {
|
|
476
456
|
const parameterDescriptor = expandParameterDescriptor(decoratorParameterDescriptor);
|
|
457
|
+
const parameterName = parameterDescriptor.name;
|
|
477
458
|
|
|
478
459
|
if (!parameterDescriptor.isRequired) {
|
|
479
460
|
anyOptional = true;
|
|
480
461
|
} else if (anyOptional) {
|
|
481
|
-
throw new Error(`Parameter ${
|
|
462
|
+
throw new Error(`Parameter ${parameterName} descriptor of method ${name} is required but prior parameter descriptor is optional`);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
if ((parameterDescriptor.multiplicity === Multiplicities.Array || parameterDescriptor.multiplicity === Multiplicities.Matrix) && decoratorMethodDescriptor.multiplicity !== Multiplicities.Matrix) {
|
|
466
|
+
throw new Error(`Parameter ${parameterName} descriptor of method ${name} is array or matrix but method descriptor is not matrix`);
|
|
482
467
|
}
|
|
483
468
|
|
|
484
469
|
return parameterDescriptor;
|
|
485
470
|
});
|
|
486
471
|
|
|
487
472
|
this.#interim.methodDescriptors.push({
|
|
488
|
-
name,
|
|
489
473
|
...decoratorMethodDescriptor,
|
|
474
|
+
name,
|
|
490
475
|
parameterDescriptors
|
|
491
476
|
});
|
|
492
477
|
|
|
@@ -499,10 +484,25 @@ export class Proxy {
|
|
|
499
484
|
try {
|
|
500
485
|
result = target.call(this, ...args);
|
|
501
486
|
|
|
502
|
-
//
|
|
503
|
-
|
|
487
|
+
// Stream methods are responsible for their own logging.
|
|
488
|
+
if (decoratorMethodDescriptor.isStream !== true) {
|
|
489
|
+
if (!(result instanceof Promise)) {
|
|
490
|
+
targetLogger.logger.trace(targetLogger.callBuilder(name, args, result));
|
|
491
|
+
} else {
|
|
492
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Promise interception pattern.
|
|
493
|
+
result = result.then((promisedResult: unknown) => {
|
|
494
|
+
targetLogger.logger.trace(targetLogger.callBuilder(name, args, promisedResult));
|
|
495
|
+
|
|
496
|
+
return promisedResult;
|
|
497
|
+
}).catch((e: unknown) => {
|
|
498
|
+
targetLogger.logger.error(targetLogger.callBuilder(name, args, e));
|
|
499
|
+
|
|
500
|
+
throw e;
|
|
501
|
+
}) as TReturn;
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
504
|
} catch (e: unknown) {
|
|
505
|
-
targetLogger.
|
|
505
|
+
targetLogger.logger.error(targetLogger.callBuilder(name, args, e));
|
|
506
506
|
|
|
507
507
|
throw e;
|
|
508
508
|
}
|
|
@@ -513,10 +513,10 @@ export class Proxy {
|
|
|
513
513
|
}
|
|
514
514
|
|
|
515
515
|
/**
|
|
516
|
-
* Get the class descriptors
|
|
516
|
+
* Get the class descriptors.
|
|
517
517
|
*/
|
|
518
|
-
get
|
|
519
|
-
return this.#concreteClassDescriptorsMap;
|
|
518
|
+
get classDescriptors(): MapIterator<ClassDescriptor> {
|
|
519
|
+
return this.#concreteClassDescriptorsMap.values();
|
|
520
520
|
}
|
|
521
521
|
}
|
|
522
522
|
|
package/src/streaming.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ErrorExtends, MatrixResult } from "./type.js";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Streaming consumer callback, returned by application extension implementation.
|
|
5
|
+
*/
|
|
6
|
+
export type StreamingConsumerCallback<TResult, ThrowError extends boolean, TError extends ErrorExtends<ThrowError>> =
|
|
7
|
+
(result: MatrixResult<TResult, ThrowError, TError>) => void;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Streaming cancelled callback, passed to application extension implementation.
|
|
11
|
+
*/
|
|
12
|
+
export type StreamingCancelledCallback =
|
|
13
|
+
() => void;
|
package/src/type.ts
CHANGED
|
@@ -68,8 +68,9 @@ export interface SheetRange extends Sheet, Range {
|
|
|
68
68
|
export type Matrix<T> = T[][];
|
|
69
69
|
|
|
70
70
|
/**
|
|
71
|
-
* Function
|
|
72
|
-
* value, the result is the union of the
|
|
71
|
+
* Function singleton return, possibly including an error return. If the application extension reports errors through
|
|
72
|
+
* the return value, the result is the union of the return type and the error type; otherwise, it's just the return
|
|
73
|
+
* type.
|
|
73
74
|
*
|
|
74
75
|
* @template TResult
|
|
75
76
|
* Result type.
|
|
@@ -80,12 +81,12 @@ export type Matrix<T> = T[][];
|
|
|
80
81
|
* @template TError
|
|
81
82
|
* Error type.
|
|
82
83
|
*/
|
|
83
|
-
export type
|
|
84
|
+
export type SingletonResult<TResult, ThrowError extends boolean, TError extends ErrorExtends<ThrowError>> = ThrowError extends false ? TResult | TError : TResult;
|
|
84
85
|
|
|
85
86
|
/**
|
|
86
|
-
* Function
|
|
87
|
-
* errors through the return value, the individual element result is the union of the
|
|
88
|
-
* otherwise, it's just the
|
|
87
|
+
* Function matrix return, possibly including an error return in each element. If the application extension reports
|
|
88
|
+
* errors through the return value, the individual element result is the union of the return type and the error type;
|
|
89
|
+
* otherwise, it's just the return type.
|
|
89
90
|
*
|
|
90
91
|
* @template TResult
|
|
91
92
|
* Result type.
|
|
@@ -96,4 +97,4 @@ export type ResultError<TResult, ThrowError extends boolean, TError extends Erro
|
|
|
96
97
|
* @template TError
|
|
97
98
|
* Error type.
|
|
98
99
|
*/
|
|
99
|
-
export type
|
|
100
|
+
export type MatrixResult<TResult, ThrowError extends boolean, TError extends ErrorExtends<ThrowError>> = Matrix<SingletonResult<TResult, ThrowError, TError>>;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { type ExtendsParameterDescriptor, type ParameterDescriptor, Types } from "../descriptor.js";
|
|
1
|
+
import { type ExtendsParameterDescriptor, Multiplicities, type ParameterDescriptor, Types } from "../descriptor.js";
|
|
2
2
|
|
|
3
3
|
const exclusionParameterDescriptor: ParameterDescriptor = {
|
|
4
4
|
name: "exclusion",
|
|
5
5
|
type: Types.Number,
|
|
6
|
-
|
|
6
|
+
multiplicity: Multiplicities.Singleton,
|
|
7
7
|
isRequired: false
|
|
8
8
|
};
|
|
9
9
|
|