@aidc-toolkit/utility 0.9.7-beta → 0.9.9-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 +0 -27
- package/README.md +14 -0
- package/dist/index.cjs +163 -533
- package/dist/index.d.cts +156 -89
- package/dist/index.d.ts +156 -89
- package/dist/index.js +145 -528
- package/package.json +8 -7
- package/src/{character_set.ts → character-set.ts} +18 -37
- package/src/index.ts +20 -6
- package/src/locale/en/{locale_strings.ts → locale-strings.ts} +2 -2
- package/src/locale/fr/{locale_strings.ts → locale-strings.ts} +2 -2
- package/src/locale/i18n.ts +38 -6
- package/src/locale/i18next.d.ts +3 -3
- package/src/record.ts +3 -4
- package/src/{reg_exp.ts → reg-exp.ts} +2 -3
- package/src/sequence.ts +107 -0
- package/src/transformer.ts +156 -87
- package/test/{character_set.test.ts → character-set.test.ts} +7 -6
- package/test/record.test.ts +3 -3
- package/test/{reg_exp.test.ts → reg-exp.test.ts} +3 -3
- package/test/sequence.test.ts +61 -0
- package/test/transformer.test.ts +38 -11
- package/src/iterator_proxy.ts +0 -517
- package/src/sequencer.ts +0 -149
- package/src/types.ts +0 -46
- package/test/iterator_proxy.test.ts +0 -252
- package/test/sequencer.test.ts +0 -72
package/src/transformer.ts
CHANGED
|
@@ -1,7 +1,86 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { i18nextUtility } from "./locale/i18n.js";
|
|
2
|
+
import { Sequence } from "./sequence.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Transformer primitive type.
|
|
6
|
+
*/
|
|
7
|
+
export type TransformerPrimitive = string | number | bigint | boolean;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Transformer input type, one of:
|
|
11
|
+
*
|
|
12
|
+
* - TInput (primitive type)
|
|
13
|
+
* - Iterable<TInput>
|
|
14
|
+
*
|
|
15
|
+
* @template TInput
|
|
16
|
+
* Transformer input primitive type.
|
|
17
|
+
*/
|
|
18
|
+
export type TransformerInput<TInput extends TransformerPrimitive> = TInput | Iterable<TInput>;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Transformer callback, used to convert transformed value to its final value.
|
|
22
|
+
*
|
|
23
|
+
* @template TInput
|
|
24
|
+
* Transformer input primitive type.
|
|
25
|
+
*
|
|
26
|
+
* @template TOutput
|
|
27
|
+
* Transformer output type.
|
|
28
|
+
*
|
|
29
|
+
* @param input
|
|
30
|
+
* Input value.
|
|
31
|
+
*
|
|
32
|
+
* @param index
|
|
33
|
+
* Index in sequence (0 for single transformation).
|
|
34
|
+
*
|
|
35
|
+
* @returns
|
|
36
|
+
* Output value.
|
|
37
|
+
*/
|
|
38
|
+
export type TransformerCallback<TInput extends TransformerPrimitive, TOutput> = (input: TInput, index: number) => TOutput;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Transformer output, based on transformer input:
|
|
42
|
+
*
|
|
43
|
+
* - If type TTransformerInput is primitive, result is type TOutput.
|
|
44
|
+
* - If type TTransformerInput is Iterable, result is type Iterable<TOutput>.
|
|
45
|
+
*
|
|
46
|
+
* @template TTransformerInput
|
|
47
|
+
* Transformer input type.
|
|
48
|
+
*
|
|
49
|
+
* @template TOutput
|
|
50
|
+
* Output base type.
|
|
51
|
+
*/
|
|
52
|
+
export type TransformerOutput<TTransformerInput extends TransformerInput<TransformerPrimitive>, TOutput> =
|
|
53
|
+
TTransformerInput extends (TTransformerInput extends TransformerInput<infer TInput> ? TInput : never) ? TOutput : Iterable<TOutput>;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Transform an input iterable to an output iterable that applies a transformer callback to each value in the input.
|
|
57
|
+
*
|
|
58
|
+
* @param values
|
|
59
|
+
* Input values iterable.
|
|
60
|
+
*
|
|
61
|
+
* @param transformerCallback
|
|
62
|
+
* Callback to transform input value to output value.
|
|
63
|
+
*
|
|
64
|
+
* @returns
|
|
65
|
+
* Output values iterable.
|
|
66
|
+
*/
|
|
67
|
+
export function transformIterable<TInput extends TransformerPrimitive, TOutput>(values: Iterable<TInput>, transformerCallback: TransformerCallback<TInput, TOutput>): Iterable<TOutput> {
|
|
68
|
+
return {
|
|
69
|
+
/**
|
|
70
|
+
* Iterable implementation.
|
|
71
|
+
*
|
|
72
|
+
* @yields
|
|
73
|
+
* Next output value.
|
|
74
|
+
*/
|
|
75
|
+
* [Symbol.iterator](): Generator<TOutput> {
|
|
76
|
+
let index = 0;
|
|
77
|
+
|
|
78
|
+
for (const value of values) {
|
|
79
|
+
yield transformerCallback(value, index++);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
}
|
|
5
84
|
|
|
6
85
|
/**
|
|
7
86
|
* Transformer that transforms values in a numeric domain to values in a range equal to the domain or to another range
|
|
@@ -41,8 +120,7 @@ export abstract class Transformer {
|
|
|
41
120
|
this._domain = BigInt(domain);
|
|
42
121
|
|
|
43
122
|
if (this._domain <= 0n) {
|
|
44
|
-
throw new RangeError(
|
|
45
|
-
ns: utilityNS,
|
|
123
|
+
throw new RangeError(i18nextUtility.t("Transformer.domainMustBeGreaterThanZero", {
|
|
46
124
|
domain
|
|
47
125
|
}));
|
|
48
126
|
}
|
|
@@ -100,15 +178,13 @@ export abstract class Transformer {
|
|
|
100
178
|
*/
|
|
101
179
|
private validate(value: bigint): void {
|
|
102
180
|
if (value < 0n) {
|
|
103
|
-
throw new RangeError(
|
|
104
|
-
ns: utilityNS,
|
|
181
|
+
throw new RangeError(i18nextUtility.t("Transformer.valueMustBeGreaterThanOrEqualToZero", {
|
|
105
182
|
value
|
|
106
183
|
}));
|
|
107
184
|
}
|
|
108
185
|
|
|
109
186
|
if (value >= this.domain) {
|
|
110
|
-
throw new RangeError(
|
|
111
|
-
ns: utilityNS,
|
|
187
|
+
throw new RangeError(i18nextUtility.t("Transformer.valueMustBeLessThan", {
|
|
112
188
|
value,
|
|
113
189
|
domain: this.domain
|
|
114
190
|
}));
|
|
@@ -126,32 +202,68 @@ export abstract class Transformer {
|
|
|
126
202
|
*/
|
|
127
203
|
protected abstract doForward(value: bigint): bigint;
|
|
128
204
|
|
|
205
|
+
/**
|
|
206
|
+
* Validate that a value is within the domain and do the work of transforming it forward.
|
|
207
|
+
*
|
|
208
|
+
* @param value
|
|
209
|
+
* Value.
|
|
210
|
+
*
|
|
211
|
+
* @returns
|
|
212
|
+
* Transformed value.
|
|
213
|
+
*/
|
|
214
|
+
private validateDoForward(value: number | bigint): bigint {
|
|
215
|
+
const valueN = BigInt(value);
|
|
216
|
+
|
|
217
|
+
this.validate(valueN);
|
|
218
|
+
|
|
219
|
+
return this.doForward(valueN);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Validate that a value is within the domain, do the work of transforming it forward, and apply a callback.
|
|
224
|
+
*
|
|
225
|
+
* @param transformerCallback
|
|
226
|
+
* Called after each value is transformed to convert it to its final value.
|
|
227
|
+
*
|
|
228
|
+
* @param value
|
|
229
|
+
* Value.
|
|
230
|
+
*
|
|
231
|
+
* @param index
|
|
232
|
+
* Index in sequence (0 for single transformation).
|
|
233
|
+
*
|
|
234
|
+
* @returns
|
|
235
|
+
* Transformed value.
|
|
236
|
+
*/
|
|
237
|
+
private validateDoForwardCallback<TOutput>(transformerCallback: TransformerCallback<bigint, TOutput>, value: number | bigint, index: number): TOutput {
|
|
238
|
+
return transformerCallback(this.validateDoForward(value), index);
|
|
239
|
+
};
|
|
240
|
+
|
|
129
241
|
/**
|
|
130
242
|
* Transform value(s) forward.
|
|
131
243
|
*
|
|
132
|
-
* @template
|
|
244
|
+
* @template TTransformerInput
|
|
133
245
|
* Value(s) input type.
|
|
134
246
|
*
|
|
135
247
|
* @param valueOrValues
|
|
136
|
-
* Value(s). If this is an instance of {@link
|
|
248
|
+
* Value(s). If this is an instance of {@link Sequence}, the minimum and maximum values are validated prior to
|
|
137
249
|
* transformation. Otherwise, the individual value(s) is/are validated at the time of transformation.
|
|
138
250
|
*
|
|
139
251
|
* @returns
|
|
140
252
|
* Transformed value(s).
|
|
141
253
|
*/
|
|
142
|
-
forward<
|
|
254
|
+
forward<TTransformerInput extends TransformerInput<number | bigint>>(valueOrValues: TTransformerInput): TransformerOutput<TTransformerInput, bigint>;
|
|
143
255
|
|
|
144
256
|
/**
|
|
145
257
|
* Transform value(s) forward, optionally applying a transformation.
|
|
146
258
|
*
|
|
147
|
-
* @template
|
|
259
|
+
* @template TTransformerInput
|
|
148
260
|
* Value(s) input type.
|
|
149
261
|
*
|
|
150
|
-
* @template
|
|
262
|
+
* @template TOutput
|
|
151
263
|
* Transformation callback output type.
|
|
152
264
|
*
|
|
153
265
|
* @param valueOrValues
|
|
154
|
-
* Value(s). If this is an instance of {@link
|
|
266
|
+
* Value(s). If this is an instance of {@link Sequence}, the minimum and maximum values are validated prior to
|
|
155
267
|
* transformation. Otherwise, the individual value(s) is/are validated at the time of transformation.
|
|
156
268
|
*
|
|
157
269
|
* @param transformerCallback
|
|
@@ -160,60 +272,36 @@ export abstract class Transformer {
|
|
|
160
272
|
* @returns
|
|
161
273
|
* Transformed value(s).
|
|
162
274
|
*/
|
|
163
|
-
forward<
|
|
275
|
+
forward<TTransformerInput extends TransformerInput<number | bigint>, TOutput>(valueOrValues: TTransformerInput, transformerCallback: TransformerCallback<bigint, TOutput>): TransformerOutput<TTransformerInput, TOutput>;
|
|
164
276
|
|
|
165
277
|
// eslint-disable-next-line jsdoc/require-jsdoc -- Implementation of overloaded signatures.
|
|
166
|
-
forward<
|
|
278
|
+
forward<TTransformerInput extends TransformerInput<number | bigint>, TOutput>(valueOrValues: TTransformerInput, transformerCallback?: TransformerCallback<bigint, TOutput>): TransformerOutput<TTransformerInput, TOutput> {
|
|
167
279
|
// TODO Refactor type when https://github.com/microsoft/TypeScript/pull/56941 released.
|
|
168
|
-
let result: bigint |
|
|
280
|
+
let result: bigint | TOutput | Iterable<bigint> | Iterable<TOutput>;
|
|
169
281
|
|
|
170
282
|
if (typeof valueOrValues !== "object") {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
result = transformerCallback === undefined ? transformedValue : transformerCallback(transformedValue, 0);
|
|
178
|
-
} else if (valueOrValues instanceof Sequencer) {
|
|
179
|
-
if (valueOrValues.minValue < 0n) {
|
|
180
|
-
throw new RangeError(i18next.t("Transformer.minValueMustBeGreaterThanOrEqualToZero", {
|
|
181
|
-
ns: utilityNS,
|
|
182
|
-
minValue: valueOrValues.minValue
|
|
283
|
+
result = transformerCallback === undefined ? this.validateDoForward(valueOrValues) : this.validateDoForwardCallback(transformerCallback, valueOrValues, 0);
|
|
284
|
+
} else if (valueOrValues instanceof Sequence) {
|
|
285
|
+
if (valueOrValues.minimumValue < 0n) {
|
|
286
|
+
throw new RangeError(i18nextUtility.t("Transformer.minimumValueMustBeGreaterThanOrEqualToZero", {
|
|
287
|
+
minimumValue: valueOrValues.minimumValue
|
|
183
288
|
}));
|
|
184
289
|
}
|
|
185
290
|
|
|
186
|
-
if (valueOrValues.
|
|
187
|
-
throw new RangeError(
|
|
188
|
-
|
|
189
|
-
maxValue: valueOrValues.maxValue,
|
|
291
|
+
if (valueOrValues.maximumValue >= this.domain) {
|
|
292
|
+
throw new RangeError(i18nextUtility.t("Transformer.maximumValueMustBeLessThan", {
|
|
293
|
+
maximumValue: valueOrValues.maximumValue,
|
|
190
294
|
domain: this.domain
|
|
191
295
|
}));
|
|
192
296
|
}
|
|
193
297
|
|
|
194
|
-
result = transformerCallback === undefined ?
|
|
195
|
-
IteratorProxy.from(valueOrValues).map(value => this.doForward(value)) :
|
|
196
|
-
IteratorProxy.from(valueOrValues).map((value, index) => transformerCallback(this.doForward(value), index));
|
|
298
|
+
result = transformerCallback === undefined ? transformIterable(valueOrValues, value => this.doForward(value)) : transformIterable(valueOrValues, (value, index) => transformerCallback(this.doForward(value), index));
|
|
197
299
|
} else {
|
|
198
|
-
result = transformerCallback === undefined ?
|
|
199
|
-
IteratorProxy.from(valueOrValues).map((value) => {
|
|
200
|
-
const valueN = BigInt(value);
|
|
201
|
-
|
|
202
|
-
this.validate(valueN);
|
|
203
|
-
|
|
204
|
-
return this.doForward(valueN);
|
|
205
|
-
}) :
|
|
206
|
-
IteratorProxy.from(valueOrValues).map((value, index) => {
|
|
207
|
-
const valueN = BigInt(value);
|
|
208
|
-
|
|
209
|
-
this.validate(valueN);
|
|
210
|
-
|
|
211
|
-
return transformerCallback(this.doForward(valueN), index);
|
|
212
|
-
});
|
|
300
|
+
result = transformerCallback === undefined ? transformIterable(valueOrValues, value => this.validateDoForward(value)) : transformIterable(valueOrValues, (value, index) => this.validateDoForwardCallback(transformerCallback, value, index));
|
|
213
301
|
}
|
|
214
302
|
|
|
215
303
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Type determination is handled above.
|
|
216
|
-
return result as TransformerOutput<
|
|
304
|
+
return result as TransformerOutput<TTransformerInput, TOutput>;
|
|
217
305
|
}
|
|
218
306
|
|
|
219
307
|
/**
|
|
@@ -265,10 +353,11 @@ export class IdentityTransformer extends Transformer {
|
|
|
265
353
|
}
|
|
266
354
|
|
|
267
355
|
/**
|
|
268
|
-
* Encryption transformer. Values are transformed using repeated shuffle and xor operations
|
|
269
|
-
*
|
|
270
|
-
*
|
|
271
|
-
*
|
|
356
|
+
* Encryption transformer. Values are transformed using repeated shuffle and xor operations, similar to those found in
|
|
357
|
+
* many cryptography algorithms, particularly AES. While sufficient for obfuscation of numeric sequences (e.g., serial
|
|
358
|
+
* number generation, below), if true format-preserving encryption is required, a more robust algorithm such as
|
|
359
|
+
* {@link https://doi.org/10.6028/NIST.SP.800-38Gr1-draft | FF1} is recommended. Furthermore, no work has been done to
|
|
360
|
+
* mitigate {@link https://timing.attacks.cr.yp.to/index.html | timing attacks} for key detection.
|
|
272
361
|
*
|
|
273
362
|
* The purpose of the encryption transformer is to generate pseudo-random values in a deterministic manner to obscure
|
|
274
363
|
* the sequence of values generated over time. A typical example is for serial number generation, where knowledge of the
|
|
@@ -304,11 +393,6 @@ export class EncryptionTransformer extends Transformer {
|
|
|
304
393
|
*/
|
|
305
394
|
private readonly _domainBytes: number;
|
|
306
395
|
|
|
307
|
-
/**
|
|
308
|
-
* Tweak.
|
|
309
|
-
*/
|
|
310
|
-
private readonly _tweak: bigint;
|
|
311
|
-
|
|
312
396
|
/**
|
|
313
397
|
* Xor bytes array generated from the domain and tweak.
|
|
314
398
|
*/
|
|
@@ -342,8 +426,7 @@ export class EncryptionTransformer extends Transformer {
|
|
|
342
426
|
super(domain);
|
|
343
427
|
|
|
344
428
|
if (tweak < 0n) {
|
|
345
|
-
throw new RangeError(
|
|
346
|
-
ns: utilityNS,
|
|
429
|
+
throw new RangeError(i18nextUtility.t("Transformer.tweakMustBeGreaterThanOrEqualToZero", {
|
|
347
430
|
tweak
|
|
348
431
|
}));
|
|
349
432
|
}
|
|
@@ -351,26 +434,23 @@ export class EncryptionTransformer extends Transformer {
|
|
|
351
434
|
let domainBytes = 0;
|
|
352
435
|
|
|
353
436
|
// The number of bytes in the domain determines the size of the shuffle and xor operations.
|
|
354
|
-
for (let reducedDomainMinusOne = this.domain - 1n; reducedDomainMinusOne !== 0n; reducedDomainMinusOne
|
|
437
|
+
for (let reducedDomainMinusOne = this.domain - 1n; reducedDomainMinusOne !== 0n; reducedDomainMinusOne >>= 8n) {
|
|
355
438
|
domainBytes++;
|
|
356
439
|
}
|
|
357
440
|
|
|
358
441
|
this._domainBytes = domainBytes;
|
|
359
|
-
this._tweak = BigInt(tweak);
|
|
360
442
|
|
|
361
443
|
const xorBytes = new Array<number>();
|
|
362
444
|
const bits = new Array<number>();
|
|
363
445
|
const inverseBits = new Array<number>();
|
|
364
446
|
|
|
365
447
|
// Key is the product of domain, tweak, and an 8-digit prime to force at least four rounds.
|
|
366
|
-
for (let reducedKey = this.domain *
|
|
367
|
-
// Extract least
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
xorBytes.unshift(keyByte);
|
|
448
|
+
for (let reducedKey = this.domain * BigInt(tweak) * 603868999n; reducedKey !== 0n; reducedKey >>= 8n) {
|
|
449
|
+
// Extract the least significant byte.
|
|
450
|
+
xorBytes.unshift(Number(BigInt.asUintN(8, reducedKey)));
|
|
371
451
|
|
|
372
|
-
// Bit number is the key
|
|
373
|
-
const bitNumber =
|
|
452
|
+
// Bit number is the reduced key mod 8.
|
|
453
|
+
const bitNumber = Number(BigInt.asUintN(3, reducedKey));
|
|
374
454
|
|
|
375
455
|
// Bits are applied in reverse order so that they don't correlate directly with the key bytes at the same index.
|
|
376
456
|
bits.push(EncryptionTransformer.BITS[bitNumber]);
|
|
@@ -399,13 +479,6 @@ export class EncryptionTransformer extends Transformer {
|
|
|
399
479
|
}
|
|
400
480
|
}
|
|
401
481
|
|
|
402
|
-
/**
|
|
403
|
-
* Get the tweak.
|
|
404
|
-
*/
|
|
405
|
-
get tweak(): bigint {
|
|
406
|
-
return this._tweak;
|
|
407
|
-
}
|
|
408
|
-
|
|
409
482
|
/**
|
|
410
483
|
* Convert a value to a byte array big enough to handle the entire domain.
|
|
411
484
|
*
|
|
@@ -418,13 +491,9 @@ export class EncryptionTransformer extends Transformer {
|
|
|
418
491
|
private valueToBytes(value: bigint): Uint8Array {
|
|
419
492
|
const bytes = new Uint8Array(this._domainBytes);
|
|
420
493
|
|
|
421
|
-
let reducedValue = value;
|
|
422
|
-
|
|
423
494
|
// Build byte array in reverse order to get as big-endian.
|
|
424
|
-
for (let index = this._domainBytes - 1; index >= 0; index
|
|
425
|
-
bytes[index] = Number(reducedValue
|
|
426
|
-
|
|
427
|
-
reducedValue = reducedValue >> 8n;
|
|
495
|
+
for (let index = this._domainBytes - 1, reducedValue = value; index >= 0 && reducedValue !== 0n; index--, reducedValue >>= 8n) {
|
|
496
|
+
bytes[index] = Number(BigInt.asUintN(8, reducedValue));
|
|
428
497
|
}
|
|
429
498
|
|
|
430
499
|
return bytes;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { I18NEnvironment
|
|
1
|
+
import { I18NEnvironment } from "@aidc-toolkit/core";
|
|
2
2
|
import { describe, expect, test } from "vitest";
|
|
3
3
|
import {
|
|
4
4
|
ALPHABETIC_CREATOR,
|
|
@@ -6,11 +6,12 @@ import {
|
|
|
6
6
|
CharacterSetCreator,
|
|
7
7
|
Exclusion,
|
|
8
8
|
HEXADECIMAL_CREATOR,
|
|
9
|
+
i18nUtilityInit,
|
|
9
10
|
NUMERIC_CREATOR,
|
|
10
|
-
|
|
11
|
+
Sequence
|
|
11
12
|
} from "../src/index.js";
|
|
12
13
|
|
|
13
|
-
await
|
|
14
|
+
await i18nUtilityInit(I18NEnvironment.CLI);
|
|
14
15
|
|
|
15
16
|
function testCharacterSetCreator(name: string, characterSetCreator: CharacterSetCreator, characterSetSize: number, length: number, excludeFirstZero: boolean, excludeAllNumeric: boolean): void {
|
|
16
17
|
describe(name, () => {
|
|
@@ -64,7 +65,7 @@ function testCharacterSetCreator(name: string, characterSetCreator: CharacterSet
|
|
|
64
65
|
break;
|
|
65
66
|
}
|
|
66
67
|
|
|
67
|
-
const sequence = Iterator.from(characterSetCreator.create(length, new
|
|
68
|
+
const sequence = Iterator.from(characterSetCreator.create(length, new Sequence(0n, domain), exclusion));
|
|
68
69
|
|
|
69
70
|
let previousS = "";
|
|
70
71
|
|
|
@@ -85,7 +86,7 @@ function testCharacterSetCreator(name: string, characterSetCreator: CharacterSet
|
|
|
85
86
|
|
|
86
87
|
expect(() => characterSetCreator.create(length, domain, exclusion)).toThrow(`Value ${domain} must be less than ${domain}`);
|
|
87
88
|
|
|
88
|
-
const sparseSequence = Iterator.from(characterSetCreator.create(length, new
|
|
89
|
+
const sparseSequence = Iterator.from(characterSetCreator.create(length, new Sequence(domain - 1, -domain), exclusion, 123456n));
|
|
89
90
|
|
|
90
91
|
let sequential = true;
|
|
91
92
|
previousS = "~";
|
|
@@ -95,7 +96,7 @@ function testCharacterSetCreator(name: string, characterSetCreator: CharacterSet
|
|
|
95
96
|
sequenceCount = 0;
|
|
96
97
|
|
|
97
98
|
sparseSequence.forEach((s, index) => {
|
|
98
|
-
sequential
|
|
99
|
+
sequential &&= s < previousS;
|
|
99
100
|
previousS = s;
|
|
100
101
|
|
|
101
102
|
expect(s.length).toBe(length);
|
package/test/record.test.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { I18NEnvironment
|
|
1
|
+
import { I18NEnvironment } from "@aidc-toolkit/core";
|
|
2
2
|
import { describe, expect, test } from "vitest";
|
|
3
|
-
import { RecordValidator } from "../src/index.js";
|
|
3
|
+
import { i18nUtilityInit, RecordValidator } from "../src/index.js";
|
|
4
4
|
|
|
5
|
-
await
|
|
5
|
+
await i18nUtilityInit(I18NEnvironment.CLI);
|
|
6
6
|
|
|
7
7
|
describe("Record validator", () => {
|
|
8
8
|
enum StringEnum {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { I18NEnvironment
|
|
1
|
+
import { I18NEnvironment } from "@aidc-toolkit/core";
|
|
2
2
|
import { describe, expect, test } from "vitest";
|
|
3
|
-
import { RegExpValidator } from "../src/index.js";
|
|
3
|
+
import { i18nUtilityInit, RegExpValidator } from "../src/index.js";
|
|
4
4
|
|
|
5
|
-
await
|
|
5
|
+
await i18nUtilityInit(I18NEnvironment.CLI);
|
|
6
6
|
|
|
7
7
|
describe("Regular expression validator", () => {
|
|
8
8
|
test("Validation", () => {
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { I18NEnvironment } from "@aidc-toolkit/core";
|
|
2
|
+
import { describe, expect, test } from "vitest";
|
|
3
|
+
import { i18nUtilityInit, Sequence } from "../src/index.js";
|
|
4
|
+
|
|
5
|
+
await i18nUtilityInit(I18NEnvironment.CLI);
|
|
6
|
+
|
|
7
|
+
describe("Sequence", () => {
|
|
8
|
+
const sequence1 = new Sequence(10, 20);
|
|
9
|
+
const sequence2 = new Sequence(29, -20);
|
|
10
|
+
|
|
11
|
+
test("Structure", () => {
|
|
12
|
+
expect(sequence1.startValue).toBe(10n);
|
|
13
|
+
expect(sequence1.endValue).toBe(30n);
|
|
14
|
+
expect(sequence1.count).toBe(20);
|
|
15
|
+
expect(sequence1.minimumValue).toBe(10n);
|
|
16
|
+
expect(sequence1.maximumValue).toBe(29n);
|
|
17
|
+
|
|
18
|
+
expect(sequence2.startValue).toBe(29n);
|
|
19
|
+
expect(sequence2.endValue).toBe(9n);
|
|
20
|
+
expect(sequence2.count).toBe(-20);
|
|
21
|
+
expect(sequence2.minimumValue).toBe(10n);
|
|
22
|
+
expect(sequence2.maximumValue).toBe(29n);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
function iterate(): void {
|
|
26
|
+
let expectedValue: bigint;
|
|
27
|
+
let count: number;
|
|
28
|
+
|
|
29
|
+
expectedValue = 10n;
|
|
30
|
+
count = 0;
|
|
31
|
+
|
|
32
|
+
for (const value of Iterator.from(sequence1)) {
|
|
33
|
+
expect(value).toBe(expectedValue);
|
|
34
|
+
|
|
35
|
+
expectedValue++;
|
|
36
|
+
count++;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
expect(count).toBe(20);
|
|
40
|
+
|
|
41
|
+
expectedValue = 29n;
|
|
42
|
+
count = 0;
|
|
43
|
+
|
|
44
|
+
for (const value of Iterator.from(sequence2)) {
|
|
45
|
+
expect(value).toBe(expectedValue);
|
|
46
|
+
|
|
47
|
+
expectedValue--;
|
|
48
|
+
count++;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
expect(count).toBe(20);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
test("Iteration", () => {
|
|
55
|
+
iterate();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test("Repeat", () => {
|
|
59
|
+
iterate();
|
|
60
|
+
});
|
|
61
|
+
});
|
package/test/transformer.test.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { I18NEnvironment
|
|
1
|
+
import { I18NEnvironment } from "@aidc-toolkit/core";
|
|
2
2
|
import { describe, expect, test } from "vitest";
|
|
3
|
-
import { EncryptionTransformer, IdentityTransformer,
|
|
3
|
+
import { EncryptionTransformer, i18nUtilityInit, IdentityTransformer, Sequence, Transformer } from "../src/index.js";
|
|
4
4
|
|
|
5
|
-
await
|
|
5
|
+
await i18nUtilityInit(I18NEnvironment.CLI);
|
|
6
6
|
|
|
7
7
|
function testTransformer(domain: number, tweak?: number, callback?: (value: bigint, forwardValue: bigint) => void): void {
|
|
8
8
|
const transformer = Transformer.get(domain, tweak);
|
|
@@ -11,7 +11,7 @@ function testTransformer(domain: number, tweak?: number, callback?: (value: bigi
|
|
|
11
11
|
|
|
12
12
|
const transformedValuesSet = new Set<bigint>();
|
|
13
13
|
|
|
14
|
-
Iterator.from(transformer.forward(new
|
|
14
|
+
Iterator.from(transformer.forward(new Sequence(0n, domain))).forEach((transformedValue, index) => {
|
|
15
15
|
const indexN = BigInt(index);
|
|
16
16
|
|
|
17
17
|
if (sequential && transformedValue !== indexN) {
|
|
@@ -43,11 +43,11 @@ function testTransformer(domain: number, tweak?: number, callback?: (value: bigi
|
|
|
43
43
|
expect(Array.from(transformer.forward(randomValues))).toStrictEqual(transformedRandomValues);
|
|
44
44
|
|
|
45
45
|
expect(() => transformer.forward(domain)).toThrow(`Value ${domain} must be less than ${domain}`);
|
|
46
|
-
expect(() => transformer.forward(new
|
|
47
|
-
expect(() => transformer.forward(new
|
|
48
|
-
expect(() => transformer.forward(new
|
|
49
|
-
expect(() => transformer.forward(new
|
|
50
|
-
expect(() => transformer.forward(new
|
|
46
|
+
expect(() => transformer.forward(new Sequence(domain, 0))).not.toThrow(RangeError);
|
|
47
|
+
expect(() => transformer.forward(new Sequence(domain - 1, 1))).not.toThrow(RangeError);
|
|
48
|
+
expect(() => transformer.forward(new Sequence(domain, 1))).toThrow(`Maximum value ${domain} must be less than ${domain}`);
|
|
49
|
+
expect(() => transformer.forward(new Sequence(0, -1))).not.toThrow(RangeError);
|
|
50
|
+
expect(() => transformer.forward(new Sequence(-1, -1))).toThrow("Minimum value -1 must be greater than or equal to 0");
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
describe("Identity", () => {
|
|
@@ -83,7 +83,6 @@ describe("Encryption", () => {
|
|
|
83
83
|
expect(Transformer.get(1000n, 1234n)).toBe(transformer);
|
|
84
84
|
|
|
85
85
|
expect(transformer.domain).toBe(BigInt(1000n));
|
|
86
|
-
expect((transformer as EncryptionTransformer).tweak).toBe(BigInt(1234n));
|
|
87
86
|
|
|
88
87
|
const transformer0 = Transformer.get(1000, 0);
|
|
89
88
|
|
|
@@ -129,7 +128,7 @@ describe("Encryption", () => {
|
|
|
129
128
|
});
|
|
130
129
|
|
|
131
130
|
test("Tweak variation", () => {
|
|
132
|
-
expect(Array.from(Transformer.get(1000, 1235).forward(new
|
|
131
|
+
expect(Array.from(Transformer.get(1000, 1235).forward(new Sequence(0n, 1000)))).not.toStrictEqual(Array.from(Transformer.get(1000, 1234).forward(new Sequence(0n, 1000))));
|
|
133
132
|
});
|
|
134
133
|
|
|
135
134
|
test("Consistency", () => {
|
|
@@ -139,3 +138,31 @@ describe("Encryption", () => {
|
|
|
139
138
|
expect(Transformer.get(1000000n, 1234567n).forward(987654n)).toBe(639402n);
|
|
140
139
|
});
|
|
141
140
|
});
|
|
141
|
+
|
|
142
|
+
describe("Non-sequence", () => {
|
|
143
|
+
function testIterables(sequence: Sequence): void {
|
|
144
|
+
const nonSequence = Array.from(sequence);
|
|
145
|
+
|
|
146
|
+
const transformer = Transformer.get(1000n, 1234n);
|
|
147
|
+
|
|
148
|
+
const sequenceForward = transformer.forward(sequence);
|
|
149
|
+
const nonSequenceForward = transformer.forward(nonSequence);
|
|
150
|
+
|
|
151
|
+
const nonSequenceIterator = nonSequenceForward[Symbol.iterator]();
|
|
152
|
+
|
|
153
|
+
for (const sequenceValue of sequenceForward) {
|
|
154
|
+
const nonSequenceNext = nonSequenceIterator.next();
|
|
155
|
+
|
|
156
|
+
expect(nonSequenceNext.done).not.toBe(true);
|
|
157
|
+
expect(nonSequenceNext.value).toBe(sequenceValue);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
test("Ascending", () => {
|
|
162
|
+
testIterables(new Sequence(0, 10));
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
test("Descending", () => {
|
|
166
|
+
testIterables(new Sequence(9, -10));
|
|
167
|
+
});
|
|
168
|
+
});
|