@aidc-toolkit/app-extension 0.9.19-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/LICENSE +174 -0
- package/README.md +17 -0
- package/app-extension.iml +9 -0
- package/dist/app-extension.d.ts +169 -0
- package/dist/app-extension.d.ts.map +1 -0
- package/dist/app-extension.js +148 -0
- package/dist/app-extension.js.map +1 -0
- package/dist/app-utility-proxy.d.ts +66 -0
- package/dist/app-utility-proxy.d.ts.map +1 -0
- package/dist/app-utility-proxy.js +233 -0
- package/dist/app-utility-proxy.js.map +1 -0
- package/dist/descriptor.d.ts +168 -0
- package/dist/descriptor.d.ts.map +1 -0
- package/dist/descriptor.js +175 -0
- package/dist/descriptor.js.map +1 -0
- package/dist/gs1/character-set-proxy.d.ts +10 -0
- package/dist/gs1/character-set-proxy.d.ts.map +1 -0
- package/dist/gs1/character-set-proxy.js +47 -0
- package/dist/gs1/character-set-proxy.js.map +1 -0
- package/dist/gs1/check-proxy.d.ts +11 -0
- package/dist/gs1/check-proxy.d.ts.map +1 -0
- package/dist/gs1/check-proxy.js +120 -0
- package/dist/gs1/check-proxy.js.map +1 -0
- package/dist/gs1/idkey-proxy.d.ts +135 -0
- package/dist/gs1/idkey-proxy.d.ts.map +1 -0
- package/dist/gs1/idkey-proxy.js +779 -0
- package/dist/gs1/idkey-proxy.js.map +1 -0
- package/dist/gs1/index.d.ts +4 -0
- package/dist/gs1/index.d.ts.map +1 -0
- package/dist/gs1/index.js +4 -0
- package/dist/gs1/index.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/lib-proxy.d.ts +135 -0
- package/dist/lib-proxy.d.ts.map +1 -0
- package/dist/lib-proxy.js +235 -0
- package/dist/lib-proxy.js.map +1 -0
- package/dist/locale/en/locale-strings.d.ts +616 -0
- package/dist/locale/en/locale-strings.d.ts.map +1 -0
- package/dist/locale/en/locale-strings.js +616 -0
- package/dist/locale/en/locale-strings.js.map +1 -0
- package/dist/locale/fr/locale-strings.d.ts +616 -0
- package/dist/locale/fr/locale-strings.d.ts.map +1 -0
- package/dist/locale/fr/locale-strings.js +616 -0
- package/dist/locale/fr/locale-strings.js.map +1 -0
- package/dist/locale/i18n.d.ts +27 -0
- package/dist/locale/i18n.d.ts.map +1 -0
- package/dist/locale/i18n.js +39 -0
- package/dist/locale/i18n.js.map +1 -0
- package/dist/types.d.ts +127 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +13 -0
- package/dist/types.js.map +1 -0
- package/dist/utility/character-set-descriptor.d.ts +6 -0
- package/dist/utility/character-set-descriptor.d.ts.map +1 -0
- package/dist/utility/character-set-descriptor.js +28 -0
- package/dist/utility/character-set-descriptor.js.map +1 -0
- package/dist/utility/character-set-proxy.d.ts +26 -0
- package/dist/utility/character-set-proxy.d.ts.map +1 -0
- package/dist/utility/character-set-proxy.js +167 -0
- package/dist/utility/character-set-proxy.js.map +1 -0
- package/dist/utility/index.d.ts +4 -0
- package/dist/utility/index.d.ts.map +1 -0
- package/dist/utility/index.js +4 -0
- package/dist/utility/index.js.map +1 -0
- package/dist/utility/reg-exp-proxy.d.ts +7 -0
- package/dist/utility/reg-exp-proxy.d.ts.map +1 -0
- package/dist/utility/reg-exp-proxy.js +61 -0
- package/dist/utility/reg-exp-proxy.js.map +1 -0
- package/dist/utility/string-descriptor.d.ts +4 -0
- package/dist/utility/string-descriptor.d.ts.map +1 -0
- package/dist/utility/string-descriptor.js +12 -0
- package/dist/utility/string-descriptor.js.map +1 -0
- package/dist/utility/string-proxy.d.ts +8 -0
- package/dist/utility/string-proxy.d.ts.map +1 -0
- package/dist/utility/string-proxy.js +12 -0
- package/dist/utility/string-proxy.js.map +1 -0
- package/dist/utility/transformer-descriptor.d.ts +6 -0
- package/dist/utility/transformer-descriptor.d.ts.map +1 -0
- package/dist/utility/transformer-descriptor.js +24 -0
- package/dist/utility/transformer-descriptor.js.map +1 -0
- package/dist/utility/transformer-proxy.d.ts +8 -0
- package/dist/utility/transformer-proxy.d.ts.map +1 -0
- package/dist/utility/transformer-proxy.js +74 -0
- package/dist/utility/transformer-proxy.js.map +1 -0
- package/eslint.config.ts +21 -0
- package/package.json +37 -0
- package/src/app-extension.ts +244 -0
- package/src/app-utility-proxy.ts +266 -0
- package/src/descriptor.ts +314 -0
- package/src/gs1/character-set-proxy.ts +41 -0
- package/src/gs1/check-proxy.ts +122 -0
- package/src/gs1/idkey-proxy.ts +815 -0
- package/src/gs1/index.ts +3 -0
- package/src/index.ts +24 -0
- package/src/lib-proxy.ts +256 -0
- package/src/locale/en/locale-strings.ts +615 -0
- package/src/locale/fr/locale-strings.ts +615 -0
- package/src/locale/i18n.ts +48 -0
- package/src/locale/i18next.d.ts +20 -0
- package/src/types.ts +144 -0
- package/src/utility/character-set-descriptor.ts +32 -0
- package/src/utility/character-set-proxy.ts +185 -0
- package/src/utility/index.ts +3 -0
- package/src/utility/reg-exp-proxy.ts +51 -0
- package/src/utility/string-descriptor.ts +13 -0
- package/src/utility/string-proxy.ts +15 -0
- package/src/utility/transformer-descriptor.ts +27 -0
- package/src/utility/transformer-proxy.ts +72 -0
- package/tsconfig.json +6 -0
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import { type ParameterDescriptor, ProxyClass, ProxyMethod, ProxyParameter, Type } from "./descriptor.js";
|
|
2
|
+
import { LibProxy } from "./lib-proxy.js";
|
|
3
|
+
import { i18nextAppExtension } from "./locale/i18n.js";
|
|
4
|
+
import { type ErrorExtends, isNullish, type Matrix, type NonNullishable, type Nullishable } from "./types.js";
|
|
5
|
+
|
|
6
|
+
const spillMatrix: ParameterDescriptor = {
|
|
7
|
+
name: "spillMatrix",
|
|
8
|
+
type: Type.Any,
|
|
9
|
+
isMatrix: true,
|
|
10
|
+
isRequired: true
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const spillMaximumParameterDescriptor: ParameterDescriptor = {
|
|
14
|
+
name: "spillMaximum",
|
|
15
|
+
type: Type.Number,
|
|
16
|
+
isMatrix: false,
|
|
17
|
+
isRequired: false
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const spillMaximumWidthParameterDescriptor: ParameterDescriptor = {
|
|
21
|
+
extendsDescriptor: spillMaximumParameterDescriptor,
|
|
22
|
+
sortOrder: 0,
|
|
23
|
+
name: "spillMaximumWidth"
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const spillMaximumHeightParameterDescriptor: ParameterDescriptor = {
|
|
27
|
+
extendsDescriptor: spillMaximumParameterDescriptor,
|
|
28
|
+
sortOrder: 1,
|
|
29
|
+
name: "spillMaximumHeight"
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Maximum dimensions.
|
|
34
|
+
*/
|
|
35
|
+
interface MaximumDimensions {
|
|
36
|
+
/**
|
|
37
|
+
* Optional maximum width.
|
|
38
|
+
*/
|
|
39
|
+
width: Nullishable<number>;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Optional maximum height.
|
|
43
|
+
*/
|
|
44
|
+
height: Nullishable<number>;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Application utilities.
|
|
49
|
+
*/
|
|
50
|
+
@ProxyClass()
|
|
51
|
+
export class AppUtilityProxy<ThrowError extends boolean, TError extends ErrorExtends<ThrowError>, TInvocationContext, TBigInt> extends LibProxy<ThrowError, TError, TInvocationContext, TBigInt> {
|
|
52
|
+
/**
|
|
53
|
+
* Get the version.
|
|
54
|
+
*
|
|
55
|
+
* @returns
|
|
56
|
+
* Version.
|
|
57
|
+
*/
|
|
58
|
+
@ProxyMethod({
|
|
59
|
+
type: Type.String,
|
|
60
|
+
isMatrix: false
|
|
61
|
+
})
|
|
62
|
+
version(): string {
|
|
63
|
+
return this.appExtension.version;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Provide default values for maximum width and height if required.
|
|
68
|
+
*
|
|
69
|
+
* @param maximumDimensions
|
|
70
|
+
* Maximum dimensions provided to function.
|
|
71
|
+
*
|
|
72
|
+
* @param invocationContext
|
|
73
|
+
* Invocation context.
|
|
74
|
+
*
|
|
75
|
+
* @returns
|
|
76
|
+
* Array of maximum width and maximum height.
|
|
77
|
+
*/
|
|
78
|
+
private async defaultMaximums(maximumDimensions: MaximumDimensions, invocationContext: Nullishable<TInvocationContext>): Promise<NonNullishable<MaximumDimensions>> {
|
|
79
|
+
if (isNullish(invocationContext)) {
|
|
80
|
+
// Application error; no localization necessary.
|
|
81
|
+
throw new Error("Invocation context not provided by application");
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const maximumWidth = maximumDimensions.width;
|
|
85
|
+
const maximumHeight = maximumDimensions.height;
|
|
86
|
+
|
|
87
|
+
let definedMaximumWidth: number;
|
|
88
|
+
let definedMaximumHeight: number;
|
|
89
|
+
|
|
90
|
+
// Skip any extra work if both values are provided.
|
|
91
|
+
if (isNullish(maximumWidth) || isNullish(maximumHeight)) {
|
|
92
|
+
const sheetAddress = await this.appExtension.getSheetAddress(invocationContext);
|
|
93
|
+
|
|
94
|
+
definedMaximumWidth = maximumWidth ?? await this.appExtension.maximumWidth() - sheetAddress.columnIndex;
|
|
95
|
+
definedMaximumHeight = maximumHeight ?? await this.appExtension.maximumHeight() - sheetAddress.rowIndex;
|
|
96
|
+
} else {
|
|
97
|
+
definedMaximumWidth = maximumWidth;
|
|
98
|
+
definedMaximumHeight = maximumHeight;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return {
|
|
102
|
+
width: definedMaximumWidth,
|
|
103
|
+
height: definedMaximumHeight
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Spill a horizontal matrix vertically to fit within a maximum width and height.
|
|
109
|
+
*
|
|
110
|
+
* @param hMatrixValues
|
|
111
|
+
* Horizontal matrix values. Matrix has length 1 and contains a single array with the values.
|
|
112
|
+
*
|
|
113
|
+
* @param maximumWidth
|
|
114
|
+
* Maximum width.
|
|
115
|
+
*
|
|
116
|
+
* @param maximumHeight
|
|
117
|
+
* Maximum height.
|
|
118
|
+
*
|
|
119
|
+
* @param invocationContext
|
|
120
|
+
* Invocation context.
|
|
121
|
+
*
|
|
122
|
+
* @returns
|
|
123
|
+
* Matrix spilled within maximum width and maximum height.
|
|
124
|
+
*/
|
|
125
|
+
@ProxyMethod({
|
|
126
|
+
requiresContext: true,
|
|
127
|
+
type: Type.Any,
|
|
128
|
+
isMatrix: true
|
|
129
|
+
})
|
|
130
|
+
async vSpill(
|
|
131
|
+
@ProxyParameter(spillMatrix) hMatrixValues: Matrix<unknown>,
|
|
132
|
+
@ProxyParameter(spillMaximumWidthParameterDescriptor) maximumWidth: Nullishable<number>,
|
|
133
|
+
@ProxyParameter(spillMaximumHeightParameterDescriptor) maximumHeight: Nullishable<number>,
|
|
134
|
+
invocationContext: Nullishable<TInvocationContext>
|
|
135
|
+
): Promise<Matrix<unknown>> {
|
|
136
|
+
let result: Matrix<unknown>;
|
|
137
|
+
|
|
138
|
+
if (hMatrixValues.length !== 1) {
|
|
139
|
+
throw new RangeError(i18nextAppExtension.t("Proxy.vSpillMustBeHorizontalArray"));
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const maximumDimensions = await this.defaultMaximums({
|
|
143
|
+
width: maximumWidth,
|
|
144
|
+
height: maximumHeight
|
|
145
|
+
}, invocationContext);
|
|
146
|
+
|
|
147
|
+
const hArrayValues = hMatrixValues[0];
|
|
148
|
+
const hLength = hArrayValues.length;
|
|
149
|
+
const maximumArea = maximumDimensions.width * maximumDimensions.height;
|
|
150
|
+
|
|
151
|
+
// Lengths 0 and 1 are valid and require no special processing.
|
|
152
|
+
if (hLength > 1 && hLength <= maximumArea) {
|
|
153
|
+
// Make spill as square as possible.
|
|
154
|
+
let spillWidth = Math.min(Math.ceil(Math.sqrt(maximumArea)), maximumDimensions.width);
|
|
155
|
+
|
|
156
|
+
// Array that has a length of a power of 10 is treated specially.
|
|
157
|
+
if (Number.isInteger(Math.log10(hLength))) {
|
|
158
|
+
// Try spill width that is a power of 10.
|
|
159
|
+
const spillWidth10 = Math.pow(10, Math.floor(Math.log10(spillWidth)));
|
|
160
|
+
|
|
161
|
+
// Keep default if not enough space for power of 10 matrix.
|
|
162
|
+
if (hLength / spillWidth10 <= maximumDimensions.height) {
|
|
163
|
+
spillWidth = spillWidth10;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
result = [];
|
|
168
|
+
|
|
169
|
+
let hStartIndex = 0;
|
|
170
|
+
|
|
171
|
+
do {
|
|
172
|
+
const hEndIndex = hStartIndex + spillWidth;
|
|
173
|
+
|
|
174
|
+
result.push(hArrayValues.slice(hStartIndex, hEndIndex));
|
|
175
|
+
|
|
176
|
+
hStartIndex = hEndIndex;
|
|
177
|
+
} while (hStartIndex < hLength);
|
|
178
|
+
} else {
|
|
179
|
+
// Return matrix unmodified and let application handle spill error if any.
|
|
180
|
+
result = hMatrixValues;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return result;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Spill a vertical matrix horizontally to fit within a maximum width and height.
|
|
188
|
+
*
|
|
189
|
+
* @param vMatrixValues
|
|
190
|
+
* Vertical matrix values. Matrix contains arrays of length 1 with the values.
|
|
191
|
+
*
|
|
192
|
+
* @param maximumHeight
|
|
193
|
+
* Maximum height.
|
|
194
|
+
*
|
|
195
|
+
* @param maximumWidth
|
|
196
|
+
* Maximum width.
|
|
197
|
+
*
|
|
198
|
+
* @param invocationContext
|
|
199
|
+
* Invocation context.
|
|
200
|
+
*
|
|
201
|
+
* @returns
|
|
202
|
+
* Matrix spilled within maximum height and maximum width.
|
|
203
|
+
*/
|
|
204
|
+
@ProxyMethod({
|
|
205
|
+
requiresContext: true,
|
|
206
|
+
type: Type.Any,
|
|
207
|
+
isMatrix: true
|
|
208
|
+
})
|
|
209
|
+
async hSpill(
|
|
210
|
+
@ProxyParameter(spillMatrix) vMatrixValues: Matrix<unknown>,
|
|
211
|
+
@ProxyParameter(spillMaximumHeightParameterDescriptor) maximumHeight: Nullishable<number>,
|
|
212
|
+
@ProxyParameter(spillMaximumWidthParameterDescriptor) maximumWidth: Nullishable<number>,
|
|
213
|
+
invocationContext: Nullishable<TInvocationContext>
|
|
214
|
+
): Promise<Matrix<unknown>> {
|
|
215
|
+
let result: Matrix<unknown>;
|
|
216
|
+
|
|
217
|
+
for (const hArrayValues of vMatrixValues) {
|
|
218
|
+
// This test should be necessary only once but account for zero-size matrix and misuse of method.
|
|
219
|
+
if (hArrayValues.length !== 1) {
|
|
220
|
+
throw new RangeError(i18nextAppExtension.t("Proxy.hSpillMustBeVerticalArray"));
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const maximumDimensions = await this.defaultMaximums({
|
|
225
|
+
width: maximumWidth,
|
|
226
|
+
height: maximumHeight
|
|
227
|
+
}, invocationContext);
|
|
228
|
+
|
|
229
|
+
const vLength = vMatrixValues.length;
|
|
230
|
+
const maximumArea = maximumDimensions.width * maximumDimensions.height;
|
|
231
|
+
|
|
232
|
+
// Lengths 0 and 1 are valid and require no special processing.
|
|
233
|
+
if (vLength > 1 && vLength <= maximumArea) {
|
|
234
|
+
// Make spill as square as possible.
|
|
235
|
+
let spillHeight = Math.min(Math.ceil(Math.sqrt(maximumArea)), maximumDimensions.height);
|
|
236
|
+
|
|
237
|
+
// Array that has a length of a power of 10 is treated specially.
|
|
238
|
+
if (Number.isInteger(Math.log10(vLength))) {
|
|
239
|
+
// Try spill height that is a power of 10.
|
|
240
|
+
const spillHeight10 = Math.pow(10, Math.floor(Math.log10(spillHeight)));
|
|
241
|
+
|
|
242
|
+
// Keep default if not enough space for power of 10 matrix.
|
|
243
|
+
if (vLength / spillHeight10 <= maximumDimensions.width) {
|
|
244
|
+
spillHeight = spillHeight10;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
result = [];
|
|
249
|
+
|
|
250
|
+
for (let rowIndex = 0; rowIndex < spillHeight; rowIndex++) {
|
|
251
|
+
const row = new Array<unknown>();
|
|
252
|
+
|
|
253
|
+
for (let cellIndex = rowIndex; cellIndex < vLength; cellIndex++) {
|
|
254
|
+
row.push(vMatrixValues[cellIndex][0]);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
result.push(row);
|
|
258
|
+
}
|
|
259
|
+
} else {
|
|
260
|
+
// Return matrix unmodified and let application handle spill error if any.
|
|
261
|
+
result = vMatrixValues;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return result;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import type { AppExtension } from "./app-extension.js";
|
|
2
|
+
import { LibProxy } from "./lib-proxy.js";
|
|
3
|
+
import type { ErrorExtends, TypedFunction } from "./types.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Core descriptor.
|
|
7
|
+
*/
|
|
8
|
+
interface Descriptor {
|
|
9
|
+
readonly name: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Types supported by proxy methods.
|
|
14
|
+
*/
|
|
15
|
+
export enum Type {
|
|
16
|
+
/**
|
|
17
|
+
* String.
|
|
18
|
+
*/
|
|
19
|
+
String,
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Number or enumeration.
|
|
23
|
+
*/
|
|
24
|
+
Number,
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Boolean.
|
|
28
|
+
*/
|
|
29
|
+
Boolean,
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Any.
|
|
33
|
+
*/
|
|
34
|
+
Any
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Type descriptor.
|
|
39
|
+
*/
|
|
40
|
+
interface TypeDescriptor extends Descriptor {
|
|
41
|
+
/**
|
|
42
|
+
* Type.
|
|
43
|
+
*/
|
|
44
|
+
readonly type: Type;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* True if type is a matrix (method accepts or returns a two-dimensional array).
|
|
48
|
+
*/
|
|
49
|
+
readonly isMatrix: boolean;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Base parameter descriptor; all attributes required.
|
|
54
|
+
*/
|
|
55
|
+
export interface BaseParameterDescriptor extends TypeDescriptor {
|
|
56
|
+
/**
|
|
57
|
+
* True if required.
|
|
58
|
+
*/
|
|
59
|
+
readonly isRequired: boolean;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Extends parameter descriptor; extends a parameter descriptor and overrides select attributes.
|
|
64
|
+
*/
|
|
65
|
+
export interface ExtendsParameterDescriptor extends Partial<BaseParameterDescriptor> {
|
|
66
|
+
/**
|
|
67
|
+
* Base parameter descriptor that this one extends.
|
|
68
|
+
*/
|
|
69
|
+
readonly extendsDescriptor: ParameterDescriptor;
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Sort order within base parameter descriptor if applicable.
|
|
73
|
+
*/
|
|
74
|
+
readonly sortOrder?: number;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Parameter descriptor, either base or extends.
|
|
79
|
+
*/
|
|
80
|
+
export type ParameterDescriptor = BaseParameterDescriptor | ExtendsParameterDescriptor;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Expand a parameter descriptor to its full form with all required attributes.
|
|
84
|
+
*
|
|
85
|
+
* @param parameterDescriptor
|
|
86
|
+
* Parameter descriptor.
|
|
87
|
+
*
|
|
88
|
+
* @returns
|
|
89
|
+
* Parameter descriptor in its full form.
|
|
90
|
+
*/
|
|
91
|
+
export function expandParameterDescriptor(parameterDescriptor: ParameterDescriptor): BaseParameterDescriptor {
|
|
92
|
+
return !("extendsDescriptor" in parameterDescriptor) ?
|
|
93
|
+
parameterDescriptor :
|
|
94
|
+
{
|
|
95
|
+
...expandParameterDescriptor(parameterDescriptor.extendsDescriptor),
|
|
96
|
+
...parameterDescriptor
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Method descriptor.
|
|
102
|
+
*/
|
|
103
|
+
export interface MethodDescriptor extends TypeDescriptor {
|
|
104
|
+
/**
|
|
105
|
+
* If true, application-specific invocation context is required.
|
|
106
|
+
*/
|
|
107
|
+
readonly requiresContext?: boolean;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* If true, method infix is ignored.
|
|
111
|
+
*/
|
|
112
|
+
readonly ignoreInfix?: boolean;
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* String before which method infix appears. If undefined, infix is appended to the method name. Ignored if
|
|
116
|
+
* `ignoreInfix` is true.
|
|
117
|
+
*/
|
|
118
|
+
readonly infixBefore?: string;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Parameter descriptors.
|
|
122
|
+
*/
|
|
123
|
+
readonly parameterDescriptors: readonly ParameterDescriptor[];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Class descriptor.
|
|
128
|
+
*/
|
|
129
|
+
export interface ClassDescriptor extends Descriptor {
|
|
130
|
+
/**
|
|
131
|
+
* Class namespace. If not provided, class is at the top level.
|
|
132
|
+
*/
|
|
133
|
+
readonly namespace?: string;
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Method infix. If undefined, method name is generated verbatim.
|
|
137
|
+
*/
|
|
138
|
+
readonly methodInfix?: string;
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Replace parameter descriptors for class hierarchies where enumeration parameter descriptors can change.
|
|
142
|
+
*/
|
|
143
|
+
readonly replaceParameterDescriptors?: ReadonlyArray<{
|
|
144
|
+
readonly name: string;
|
|
145
|
+
readonly replacement: ParameterDescriptor;
|
|
146
|
+
}>;
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Method descriptors.
|
|
150
|
+
*/
|
|
151
|
+
readonly methodDescriptors: readonly MethodDescriptor[];
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Proxy class type with fixed constructor.
|
|
156
|
+
*/
|
|
157
|
+
type ProxyClassType<ThrowError extends boolean, TError extends ErrorExtends<ThrowError>, TInvocationContext, TBigInt, T extends LibProxy<ThrowError, TError, TInvocationContext, TBigInt>> = (new(appExtension: AppExtension<ThrowError, TError, TInvocationContext, TBigInt>) => T) & typeof LibProxy;
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Pending parameter descriptors, consumed and reset when method is described.
|
|
161
|
+
*/
|
|
162
|
+
let pendingParameterDescriptors: ParameterDescriptor[] = [];
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Class method descriptors, keyed on declaration class name and method name.
|
|
166
|
+
*/
|
|
167
|
+
const classMethodsDescriptorsMap = new Map<string, MethodDescriptor[]>();
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Class descriptors, keyed on declaration class name.
|
|
171
|
+
*/
|
|
172
|
+
const classDescriptorsMap = new Map<string, ClassDescriptor>();
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Proxy parameter decorator.
|
|
176
|
+
*
|
|
177
|
+
* @param parameterDescriptor
|
|
178
|
+
* Parameter descriptor.
|
|
179
|
+
*
|
|
180
|
+
* @returns
|
|
181
|
+
* Function defining metadata for the parameter.
|
|
182
|
+
*/
|
|
183
|
+
export function ProxyParameter<ThrowError extends boolean, TError extends ErrorExtends<ThrowError>, TInvocationContext, TBigInt, T extends LibProxy<ThrowError, TError, TInvocationContext, TBigInt>>(parameterDescriptor: ParameterDescriptor): ((target: T, propertyKey: string, parameterIndex: number) => void) {
|
|
184
|
+
return (_target: T, _propertyKey: string, parameterIndex: number) => {
|
|
185
|
+
pendingParameterDescriptors[parameterIndex] = parameterDescriptor;
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Proxy method decorator.
|
|
191
|
+
*
|
|
192
|
+
* @param methodDescriptor
|
|
193
|
+
* Method descriptor.
|
|
194
|
+
*
|
|
195
|
+
* @returns
|
|
196
|
+
* Function defining metadata for the method.
|
|
197
|
+
*/
|
|
198
|
+
export function ProxyMethod<ThrowError extends boolean, TError extends ErrorExtends<ThrowError>, TInvocationContext, TBigInt, T extends LibProxy<ThrowError, TError, TInvocationContext, TBigInt>>(methodDescriptor: Omit<MethodDescriptor, "name" | "parameterDescriptors">): ((target: T, propertyKey: string, propertyDescriptor: PropertyDescriptor) => void) {
|
|
199
|
+
return (target: T, propertyKey: string, propertyDescriptor: PropertyDescriptor) => {
|
|
200
|
+
const declarationClassName = target.constructor.name;
|
|
201
|
+
|
|
202
|
+
// Validate that method descriptor is applied to a function.
|
|
203
|
+
if (typeof propertyDescriptor.value !== "function") {
|
|
204
|
+
throw new Error(`${declarationClassName}.${propertyKey} is not a method`);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Known to be a method.
|
|
208
|
+
const parameterCount = (propertyDescriptor.value as TypedFunction<(...args: unknown[]) => unknown>).length - (!(methodDescriptor.requiresContext ?? false) ? 0 : 1);
|
|
209
|
+
|
|
210
|
+
let anyOptional = false;
|
|
211
|
+
|
|
212
|
+
// Validate that all parameters have descriptors.
|
|
213
|
+
for (let index = 0; index < parameterCount; index++) {
|
|
214
|
+
const parameterDescriptor = expandParameterDescriptor(pendingParameterDescriptors[index]);
|
|
215
|
+
|
|
216
|
+
if (typeof parameterDescriptor === "undefined") {
|
|
217
|
+
throw new Error(`Missing parameter descriptor at index ${index} of ${declarationClassName}.${propertyKey}`);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (!parameterDescriptor.isRequired) {
|
|
221
|
+
anyOptional = true;
|
|
222
|
+
} else if (anyOptional) {
|
|
223
|
+
throw new Error(`Parameter descriptor ${parameterDescriptor.name} at index ${index} of ${declarationClassName}.${propertyKey} is required but prior parameter descriptor ${pendingParameterDescriptors[index - 1].name} is optional`);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
let methodDescriptors = classMethodsDescriptorsMap.get(declarationClassName);
|
|
228
|
+
if (methodDescriptors === undefined) {
|
|
229
|
+
methodDescriptors = [];
|
|
230
|
+
classMethodsDescriptorsMap.set(declarationClassName, methodDescriptors);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Method descriptors array is constructed in reverse order so that final result is in the correct order.
|
|
234
|
+
methodDescriptors.push({
|
|
235
|
+
name: propertyKey,
|
|
236
|
+
...methodDescriptor,
|
|
237
|
+
parameterDescriptors: pendingParameterDescriptors
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
pendingParameterDescriptors = [];
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Proxy class decorator.
|
|
246
|
+
*
|
|
247
|
+
* @param classDescriptor
|
|
248
|
+
* Class descriptor.
|
|
249
|
+
*
|
|
250
|
+
* @returns
|
|
251
|
+
* Function defining metadata for the class.
|
|
252
|
+
*/
|
|
253
|
+
export function ProxyClass<ThrowError extends boolean, TError extends ErrorExtends<ThrowError>, TInvocationContext, TBigInt, T extends LibProxy<ThrowError, TError, TInvocationContext, TBigInt>>(classDescriptor: Omit<ClassDescriptor, "name" | "methodDescriptors"> = {}): ((classType: ProxyClassType<ThrowError, TError, TInvocationContext, TBigInt, T>) => void) {
|
|
254
|
+
return (classType: ProxyClassType<ThrowError, TError, TInvocationContext, TBigInt, T>) => {
|
|
255
|
+
const methodDescriptorsMap = new Map<string, MethodDescriptor>();
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Build method descriptors map from every class in hierarchy until LibProxy class is reached.
|
|
259
|
+
*
|
|
260
|
+
* @param classType
|
|
261
|
+
* Class type.
|
|
262
|
+
*/
|
|
263
|
+
function buildMethodDescriptorsMap(classType: typeof LibProxy): void {
|
|
264
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Class hierarchy is known.
|
|
265
|
+
const baseClassType = Object.getPrototypeOf(classType) as typeof LibProxy;
|
|
266
|
+
|
|
267
|
+
// Start with class furthest up the hierarchy.
|
|
268
|
+
if (baseClassType !== LibProxy) {
|
|
269
|
+
buildMethodDescriptorsMap(baseClassType);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const classMethodDescriptors = classMethodsDescriptorsMap.get(classType.name);
|
|
273
|
+
|
|
274
|
+
if (classMethodDescriptors !== undefined) {
|
|
275
|
+
for (const classMethodDescriptor of classMethodDescriptors) {
|
|
276
|
+
// If any class overrides a base class method, it will appear in the same position as the base class method.
|
|
277
|
+
methodDescriptorsMap.set(classMethodDescriptor.name, classMethodDescriptor);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
buildMethodDescriptorsMap(classType);
|
|
283
|
+
|
|
284
|
+
let methodDescriptors: MethodDescriptor[];
|
|
285
|
+
|
|
286
|
+
if (classDescriptor.replaceParameterDescriptors !== undefined) {
|
|
287
|
+
const replacementParameterDescriptorsMap = new Map(classDescriptor.replaceParameterDescriptors.map(replaceParameterDescriptor => [replaceParameterDescriptor.name, replaceParameterDescriptor.replacement]));
|
|
288
|
+
|
|
289
|
+
// Method descriptors for class have to be built as copies due to possible mutation of parameter descriptors.
|
|
290
|
+
methodDescriptors = Array.from(methodDescriptorsMap.values()).map(methodDescriptor => ({
|
|
291
|
+
...methodDescriptor,
|
|
292
|
+
parameterDescriptors: methodDescriptor.parameterDescriptors.map(parameterDescriptor => replacementParameterDescriptorsMap.get(expandParameterDescriptor(parameterDescriptor).name) ?? parameterDescriptor)
|
|
293
|
+
}));
|
|
294
|
+
} else {
|
|
295
|
+
methodDescriptors = Array.from(methodDescriptorsMap.values());
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
classDescriptorsMap.set(classType.name, {
|
|
299
|
+
name: classType.name,
|
|
300
|
+
...classDescriptor,
|
|
301
|
+
methodDescriptors
|
|
302
|
+
});
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Get class descriptors.
|
|
308
|
+
*
|
|
309
|
+
* @returns
|
|
310
|
+
* Class descriptors.
|
|
311
|
+
*/
|
|
312
|
+
export function getClassDescriptors(): ReadonlyMap<string, ClassDescriptor> {
|
|
313
|
+
return classDescriptorsMap;
|
|
314
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { AI39_CREATOR, AI82_CREATOR } from "@aidc-toolkit/gs1";
|
|
2
|
+
import type { AppExtension } from "../app-extension.js";
|
|
3
|
+
import { expandParameterDescriptor, ProxyClass } from "../descriptor.js";
|
|
4
|
+
import type { ErrorExtends } from "../types.js";
|
|
5
|
+
import {
|
|
6
|
+
exclusionAllNumericParameterDescriptor,
|
|
7
|
+
exclusionNoneParameterDescriptor
|
|
8
|
+
} from "../utility/character-set-descriptor.js";
|
|
9
|
+
import { CharacterSetProxy } from "../utility/character-set-proxy.js";
|
|
10
|
+
|
|
11
|
+
@ProxyClass({
|
|
12
|
+
namespace: "GS1",
|
|
13
|
+
methodInfix: "AI82",
|
|
14
|
+
replaceParameterDescriptors: [
|
|
15
|
+
{
|
|
16
|
+
name: expandParameterDescriptor(exclusionNoneParameterDescriptor).name,
|
|
17
|
+
replacement: exclusionAllNumericParameterDescriptor
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
})
|
|
21
|
+
export class AI82Proxy<ThrowError extends boolean, TError extends ErrorExtends<ThrowError>, TInvocationContext, TBigInt> extends CharacterSetProxy<ThrowError, TError, TInvocationContext, TBigInt> {
|
|
22
|
+
constructor(appExtension: AppExtension<ThrowError, TError, TInvocationContext, TBigInt>) {
|
|
23
|
+
super(appExtension, AI82_CREATOR);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@ProxyClass({
|
|
28
|
+
namespace: "GS1",
|
|
29
|
+
methodInfix: "AI39",
|
|
30
|
+
replaceParameterDescriptors: [
|
|
31
|
+
{
|
|
32
|
+
name: expandParameterDescriptor(exclusionNoneParameterDescriptor).name,
|
|
33
|
+
replacement: exclusionAllNumericParameterDescriptor
|
|
34
|
+
}
|
|
35
|
+
]
|
|
36
|
+
})
|
|
37
|
+
export class AI39Proxy<ThrowError extends boolean, TError extends ErrorExtends<ThrowError>, TInvocationContext, TBigInt> extends CharacterSetProxy<ThrowError, TError, TInvocationContext, TBigInt> {
|
|
38
|
+
constructor(appExtension: AppExtension<ThrowError, TError, TInvocationContext, TBigInt>) {
|
|
39
|
+
super(appExtension, AI39_CREATOR);
|
|
40
|
+
}
|
|
41
|
+
}
|