@aidc-toolkit/utility 0.9.0 → 0.9.2
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/.idea/runConfigurations/build_dev.xml +12 -0
- package/eslint.config.js +1 -3
- package/package.json +13 -13
- package/src/character_set.ts +135 -144
- package/src/index.ts +2 -2
- package/src/locale/en/locale_strings.ts +6 -4
- package/src/locale/i18next.d.ts +6 -0
- package/src/record.ts +2 -4
- package/src/reg_exp.ts +3 -0
- package/src/sequencer.ts +149 -0
- package/src/string.ts +3 -3
- package/src/transformer.ts +121 -108
- package/test/character_set.test.ts +51 -22
- package/test/record.test.ts +3 -3
- package/test/reg_exp.test.ts +3 -3
- package/test/sequencer.test.ts +72 -0
- package/test/transformer.test.ts +12 -14
- package/typedoc.json +2 -1
- package/.idea/runConfigurations/Test_iteration.xml +0 -12
- package/src/iteration.ts +0 -343
- package/test/iteration.test.ts +0 -282
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<component name="ProjectRunConfigurationManager">
|
|
2
|
+
<configuration default="false" name="build-dev" type="js.build_tools.npm" nameIsGenerated="true">
|
|
3
|
+
<package-json value="$PROJECT_DIR$/package.json" />
|
|
4
|
+
<command value="run" />
|
|
5
|
+
<scripts>
|
|
6
|
+
<script value="build-dev" />
|
|
7
|
+
</scripts>
|
|
8
|
+
<node-interpreter value="project" />
|
|
9
|
+
<envs />
|
|
10
|
+
<method v="2" />
|
|
11
|
+
</configuration>
|
|
12
|
+
</component>
|
package/eslint.config.js
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import tseslint from "typescript-eslint";
|
|
2
|
-
import js from "@eslint/js";
|
|
3
2
|
import stylistic from "@stylistic/eslint-plugin";
|
|
4
3
|
import jsdoc from "eslint-plugin-jsdoc";
|
|
5
4
|
import esLintConfigLove from "eslint-config-love";
|
|
6
5
|
import { esLintConfigAIDCToolkit } from "@aidc-toolkit/dev";
|
|
7
6
|
|
|
8
7
|
export default tseslint.config(
|
|
9
|
-
js.configs.recommended,
|
|
10
8
|
...tseslint.configs.strictTypeChecked,
|
|
11
9
|
stylistic.configs["recommended-flat"],
|
|
12
10
|
jsdoc.configs["flat/recommended-typescript"],
|
|
13
11
|
esLintConfigLove,
|
|
14
|
-
esLintConfigAIDCToolkit
|
|
12
|
+
...esLintConfigAIDCToolkit
|
|
15
13
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aidc-toolkit/utility",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.2",
|
|
4
4
|
"description": "Foundational utilities for AIDC Toolkit",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -20,23 +20,23 @@
|
|
|
20
20
|
},
|
|
21
21
|
"scripts": {
|
|
22
22
|
"eslint": "eslint .",
|
|
23
|
-
"build": "tsup src/index.ts --format cjs,esm --dts",
|
|
23
|
+
"build": "tsup src/index.ts --clean --format cjs,esm --dts",
|
|
24
|
+
"build-dev": "npm run build && tsc src/index.ts --outDir dist --target esnext --moduleResolution nodenext --module nodenext --emitDeclarationOnly --declaration --declarationMap",
|
|
24
25
|
"test": "vitest run"
|
|
25
26
|
},
|
|
26
27
|
"devDependencies": {
|
|
27
|
-
"@aidc-toolkit/dev": "^0.9.
|
|
28
|
-
"@eslint
|
|
29
|
-
"
|
|
30
|
-
"eslint-
|
|
31
|
-
"eslint-plugin-jsdoc": "^50.2.2",
|
|
28
|
+
"@aidc-toolkit/dev": "^0.9.2",
|
|
29
|
+
"@stylistic/eslint-plugin": "^2.10.1",
|
|
30
|
+
"eslint-config-love": "^98.0.2",
|
|
31
|
+
"eslint-plugin-jsdoc": "^50.5.0",
|
|
32
32
|
"ts-node": "^10.9.2",
|
|
33
|
-
"tsup": "^8.
|
|
34
|
-
"typescript": "^5.
|
|
35
|
-
"typescript-eslint": "^8.
|
|
36
|
-
"vitest": "^2.
|
|
33
|
+
"tsup": "^8.3.5",
|
|
34
|
+
"typescript": "^5.6.3",
|
|
35
|
+
"typescript-eslint": "^8.14.0",
|
|
36
|
+
"vitest": "^2.1.4"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@aidc-toolkit/core": "^0.9.
|
|
40
|
-
"i18next": "^23.
|
|
39
|
+
"@aidc-toolkit/core": "^0.9.2",
|
|
40
|
+
"i18next": "^23.16.5"
|
|
41
41
|
}
|
|
42
42
|
}
|
package/src/character_set.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { IterationHelper, type IterationSource } from "./iteration.js";
|
|
2
1
|
import i18next, { utilityNS } from "./locale/i18n.js";
|
|
3
2
|
import { RegExpValidator } from "./reg_exp.js";
|
|
4
3
|
import type { StringValidation, StringValidator } from "./string.js";
|
|
5
|
-
import {
|
|
4
|
+
import { Transformer } from "./transformer.js";
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
7
|
* Exclusion options for validating and creating strings based on character sets.
|
|
@@ -29,29 +28,29 @@ export enum Exclusion {
|
|
|
29
28
|
*/
|
|
30
29
|
export interface CharacterSetValidation extends StringValidation {
|
|
31
30
|
/**
|
|
32
|
-
* Minimum length. If defined and the string is less than this length, an
|
|
31
|
+
* Minimum length. If defined and the string is less than this length, an error is thrown.
|
|
33
32
|
*/
|
|
34
33
|
minimumLength?: number | undefined;
|
|
35
34
|
|
|
36
35
|
/**
|
|
37
|
-
* Maximum length. If defined and the string is greater than this length, an
|
|
36
|
+
* Maximum length. If defined and the string is greater than this length, an error is thrown.
|
|
38
37
|
*/
|
|
39
38
|
maximumLength?: number | undefined;
|
|
40
39
|
|
|
41
40
|
/**
|
|
42
|
-
* Exclusion from the string. If defined and the string is within the exclusion range, an
|
|
41
|
+
* Exclusion from the string. If defined and the string is within the exclusion range, an error is thrown.
|
|
43
42
|
*/
|
|
44
43
|
exclusion?: Exclusion | undefined;
|
|
45
44
|
|
|
46
45
|
/**
|
|
47
46
|
* Position offset within a larger string. Strings are sometimes composed of multiple substrings; this parameter
|
|
48
|
-
* ensures that the
|
|
47
|
+
* ensures that the error notes the proper position in the string.
|
|
49
48
|
*/
|
|
50
49
|
positionOffset?: number | undefined;
|
|
51
50
|
|
|
52
51
|
/**
|
|
53
52
|
* Name of component, typically but not exclusively within a larger string. This parameter ensure that the
|
|
54
|
-
*
|
|
53
|
+
* error notes the component that triggered it. Value may be a string or a callback that returns a string, the
|
|
55
54
|
* latter allowing for localization changes.
|
|
56
55
|
*/
|
|
57
56
|
component?: string | (() => string) | undefined;
|
|
@@ -60,8 +59,17 @@ export interface CharacterSetValidation extends StringValidation {
|
|
|
60
59
|
/**
|
|
61
60
|
* Character set validator. Validates a string against a specified character set.
|
|
62
61
|
*/
|
|
63
|
-
export class CharacterSetValidator implements StringValidator {
|
|
62
|
+
export class CharacterSetValidator implements StringValidator<CharacterSetValidation> {
|
|
64
63
|
private static readonly NOT_ALL_NUMERIC_VALIDATOR = new class extends RegExpValidator {
|
|
64
|
+
/**
|
|
65
|
+
* Create an error message for an all-numeric string.
|
|
66
|
+
*
|
|
67
|
+
* @param _s
|
|
68
|
+
* String.
|
|
69
|
+
*
|
|
70
|
+
* @returns
|
|
71
|
+
* Error message.
|
|
72
|
+
*/
|
|
65
73
|
protected override createErrorMessage(_s: string): string {
|
|
66
74
|
return i18next.t("CharacterSetValidator.stringMustNotBeAllNumeric", {
|
|
67
75
|
ns: utilityNS
|
|
@@ -78,7 +86,7 @@ export class CharacterSetValidator implements StringValidator {
|
|
|
78
86
|
* Character set map, mapping each character in the character set to its index such that
|
|
79
87
|
* `_characterSetMap.get(_characterSet[index]) === index`.
|
|
80
88
|
*/
|
|
81
|
-
private readonly _characterSetMap:
|
|
89
|
+
private readonly _characterSetMap: ReadonlyMap<string, number>;
|
|
82
90
|
|
|
83
91
|
/**
|
|
84
92
|
* Exclusions supported by the character set.
|
|
@@ -98,7 +106,13 @@ export class CharacterSetValidator implements StringValidator {
|
|
|
98
106
|
constructor(characterSet: readonly string[], ...exclusionSupport: readonly Exclusion[]) {
|
|
99
107
|
this._characterSet = characterSet;
|
|
100
108
|
|
|
101
|
-
|
|
109
|
+
const characterSetMap = new Map<string, number>();
|
|
110
|
+
|
|
111
|
+
characterSet.forEach((c, index) => {
|
|
112
|
+
characterSetMap.set(c, index);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
this._characterSetMap = characterSetMap;
|
|
102
116
|
|
|
103
117
|
this._exclusionSupport = exclusionSupport;
|
|
104
118
|
}
|
|
@@ -174,16 +188,14 @@ export class CharacterSetValidator implements StringValidator {
|
|
|
174
188
|
* Component as a string or undefined.
|
|
175
189
|
*/
|
|
176
190
|
private static componentToString(component: string | (() => string) | undefined): string | undefined {
|
|
177
|
-
return
|
|
191
|
+
return typeof component === "function" ? component() : component;
|
|
178
192
|
}
|
|
179
193
|
|
|
180
194
|
/**
|
|
181
|
-
* Validate that an exclusion is supported. If not, an
|
|
195
|
+
* Validate that an exclusion is supported. If not, an error is thrown.
|
|
182
196
|
*
|
|
183
197
|
* @param exclusion
|
|
184
198
|
* Exclusion.
|
|
185
|
-
*
|
|
186
|
-
* @throws RangeError
|
|
187
199
|
*/
|
|
188
200
|
protected validateExclusion(exclusion: Exclusion): void {
|
|
189
201
|
if (exclusion !== Exclusion.None && !this._exclusionSupport.includes(exclusion)) {
|
|
@@ -196,15 +208,13 @@ export class CharacterSetValidator implements StringValidator {
|
|
|
196
208
|
|
|
197
209
|
/**
|
|
198
210
|
* Validate a string. If the string violates the character set or any of the character set validation parameters, an
|
|
199
|
-
*
|
|
211
|
+
* error is thrown.
|
|
200
212
|
*
|
|
201
213
|
* @param s
|
|
202
214
|
* String.
|
|
203
215
|
*
|
|
204
216
|
* @param validation
|
|
205
217
|
* Character set validation parameters.
|
|
206
|
-
*
|
|
207
|
-
* @throws RangeError
|
|
208
218
|
*/
|
|
209
219
|
validate(s: string, validation?: CharacterSetValidation): void {
|
|
210
220
|
const length = s.length;
|
|
@@ -259,6 +269,9 @@ export class CharacterSetValidator implements StringValidator {
|
|
|
259
269
|
this.validateExclusion(validation.exclusion);
|
|
260
270
|
|
|
261
271
|
switch (validation.exclusion) {
|
|
272
|
+
case Exclusion.None:
|
|
273
|
+
break;
|
|
274
|
+
|
|
262
275
|
case Exclusion.FirstZero:
|
|
263
276
|
if (s.startsWith("0")) {
|
|
264
277
|
throw new RangeError(i18next.t(validation.component === undefined ? "CharacterSetValidator.invalidCharacterAtPosition" : "CharacterSetValidator.invalidCharacterAtPositionOfComponent", {
|
|
@@ -353,12 +366,12 @@ export class CharacterSetCreator extends CharacterSetValidator {
|
|
|
353
366
|
/**
|
|
354
367
|
* Domains for every length for every supported {@link Exclusion}.
|
|
355
368
|
*/
|
|
356
|
-
private readonly _exclusionDomains: ReadonlyArray<readonly bigint[]
|
|
369
|
+
private readonly _exclusionDomains: ReadonlyArray<readonly bigint[]>;
|
|
357
370
|
|
|
358
371
|
/**
|
|
359
372
|
* Values that would generate all zeros in the created string.
|
|
360
373
|
*/
|
|
361
|
-
private readonly _allZerosValues: readonly bigint[]
|
|
374
|
+
private readonly _allZerosValues: readonly bigint[];
|
|
362
375
|
|
|
363
376
|
/**
|
|
364
377
|
* Constructor.
|
|
@@ -376,12 +389,20 @@ export class CharacterSetCreator extends CharacterSetValidator {
|
|
|
376
389
|
this._characterSetSizeN = BigInt(this.characterSetSize);
|
|
377
390
|
this._characterSetSizeMinusOneN = BigInt(this.characterSetSize - 1);
|
|
378
391
|
|
|
392
|
+
const exclusionDomains: Array<readonly bigint[]> = [];
|
|
393
|
+
|
|
379
394
|
const exclusionNoneDomains = CharacterSetCreator.createPowersOf(this.characterSetSize);
|
|
380
395
|
|
|
381
|
-
|
|
396
|
+
exclusionDomains[Exclusion.None] = exclusionNoneDomains;
|
|
382
397
|
|
|
383
398
|
if (exclusionSupport.includes(Exclusion.FirstZero)) {
|
|
384
|
-
|
|
399
|
+
if (characterSet[0] !== "0") {
|
|
400
|
+
throw new RangeError(i18next.t("CharacterSetValidator.firstZeroFirstCharacter", {
|
|
401
|
+
ns: utilityNS
|
|
402
|
+
}));
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
const exclusionFirstZeroDomains = new Array<bigint>(CharacterSetCreator.MAXIMUM_STRING_LENGTH + 1);
|
|
385
406
|
|
|
386
407
|
// Exclusion of first zero mathematically prohibits length of 0.
|
|
387
408
|
exclusionFirstZeroDomains[0] = 0n;
|
|
@@ -390,16 +411,30 @@ export class CharacterSetCreator extends CharacterSetValidator {
|
|
|
390
411
|
// Domain excludes zero as the first character and so works with previous exclusion none domain.
|
|
391
412
|
exclusionFirstZeroDomains[index] = this._characterSetSizeMinusOneN * exclusionNoneDomains[index - 1];
|
|
392
413
|
}
|
|
393
|
-
}
|
|
394
414
|
|
|
395
|
-
|
|
415
|
+
exclusionDomains[Exclusion.FirstZero] = exclusionFirstZeroDomains;
|
|
416
|
+
}
|
|
396
417
|
|
|
397
418
|
if (exclusionSupport.includes(Exclusion.AllNumeric)) {
|
|
398
|
-
exclusionAllNumericDomains = new Array<bigint>(CharacterSetCreator.MAXIMUM_STRING_LENGTH + 1);
|
|
419
|
+
const exclusionAllNumericDomains = new Array<bigint>(CharacterSetCreator.MAXIMUM_STRING_LENGTH + 1);
|
|
420
|
+
|
|
421
|
+
const numberIndexes = this.characterIndexes("0123456789");
|
|
422
|
+
|
|
423
|
+
let expectedNumberIndex = numberIndexes[0];
|
|
424
|
+
|
|
425
|
+
// Make sure that all numeric characters are present and in sequence.
|
|
426
|
+
for (const numberIndex of numberIndexes) {
|
|
427
|
+
if (numberIndex === undefined || numberIndex !== expectedNumberIndex) {
|
|
428
|
+
throw new RangeError(i18next.t("CharacterSetValidator.allNumericAllNumericCharacters", {
|
|
429
|
+
ns: utilityNS
|
|
430
|
+
}));
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
expectedNumberIndex = numberIndex + 1;
|
|
434
|
+
}
|
|
399
435
|
|
|
400
436
|
// Zero index is the all-zero value for a single-character string.
|
|
401
|
-
|
|
402
|
-
const zeroIndex = BigInt(this.characterIndex("0")!);
|
|
437
|
+
const zeroIndex = BigInt((numberIndexes as number[])[0]);
|
|
403
438
|
|
|
404
439
|
const allZerosValues = new Array<bigint>(CharacterSetCreator.MAXIMUM_STRING_LENGTH + 1);
|
|
405
440
|
let allZerosValue = 0n;
|
|
@@ -415,13 +450,14 @@ export class CharacterSetCreator extends CharacterSetValidator {
|
|
|
415
450
|
}
|
|
416
451
|
|
|
417
452
|
this._allZerosValues = allZerosValues;
|
|
453
|
+
|
|
454
|
+
exclusionDomains[Exclusion.AllNumeric] = exclusionAllNumericDomains;
|
|
455
|
+
} else {
|
|
456
|
+
// Empty array obviates need for non-null assertion while still forcing error if indexed due to a bug.
|
|
457
|
+
this._allZerosValues = [];
|
|
418
458
|
}
|
|
419
459
|
|
|
420
|
-
this._exclusionDomains =
|
|
421
|
-
exclusionNoneDomains,
|
|
422
|
-
exclusionFirstZeroDomains,
|
|
423
|
-
exclusionAllNumericDomains
|
|
424
|
-
];
|
|
460
|
+
this._exclusionDomains = exclusionDomains;
|
|
425
461
|
}
|
|
426
462
|
|
|
427
463
|
/**
|
|
@@ -434,8 +470,7 @@ export class CharacterSetCreator extends CharacterSetValidator {
|
|
|
434
470
|
* `characterSetSize**power`.
|
|
435
471
|
*/
|
|
436
472
|
private powerOfSize(power: number): bigint {
|
|
437
|
-
|
|
438
|
-
return this._exclusionDomains[Exclusion.None]![power];
|
|
473
|
+
return this._exclusionDomains[Exclusion.None][power];
|
|
439
474
|
}
|
|
440
475
|
|
|
441
476
|
/**
|
|
@@ -452,8 +487,6 @@ export class CharacterSetCreator extends CharacterSetValidator {
|
|
|
452
487
|
*
|
|
453
488
|
* @returns
|
|
454
489
|
* Shift required to skip all all-numeric strings.
|
|
455
|
-
*
|
|
456
|
-
* @throws RangeError
|
|
457
490
|
*/
|
|
458
491
|
private allNumericShift(shiftForward: boolean, length: number, value: bigint): bigint {
|
|
459
492
|
let shift: bigint;
|
|
@@ -491,14 +524,20 @@ export class CharacterSetCreator extends CharacterSetValidator {
|
|
|
491
524
|
}
|
|
492
525
|
|
|
493
526
|
/**
|
|
494
|
-
* Validate that a length is less than or equal to {@link MAXIMUM_STRING_LENGTH}. If not, an
|
|
527
|
+
* Validate that a length is less than or equal to {@link MAXIMUM_STRING_LENGTH}. If not, an error is thrown.
|
|
495
528
|
*
|
|
496
529
|
* @param length
|
|
497
530
|
* Length.
|
|
498
|
-
*
|
|
499
|
-
* @throws RangeError
|
|
500
531
|
*/
|
|
501
532
|
private validateLength(length: number): void {
|
|
533
|
+
if (length < 0) {
|
|
534
|
+
throw new RangeError(i18next.t("CharacterSetValidator.lengthMustBeGreaterThanOrEqualTo", {
|
|
535
|
+
ns: utilityNS,
|
|
536
|
+
length,
|
|
537
|
+
minimumLength: 0
|
|
538
|
+
}));
|
|
539
|
+
}
|
|
540
|
+
|
|
502
541
|
if (length > CharacterSetCreator.MAXIMUM_STRING_LENGTH) {
|
|
503
542
|
throw new RangeError(i18next.t("CharacterSetValidator.lengthMustBeLessThanOrEqualTo", {
|
|
504
543
|
ns: utilityNS,
|
|
@@ -508,73 +547,6 @@ export class CharacterSetCreator extends CharacterSetValidator {
|
|
|
508
547
|
}
|
|
509
548
|
}
|
|
510
549
|
|
|
511
|
-
/**
|
|
512
|
-
* Do the work for the creation methods. Undocumented parameters are as defined in the public methods.
|
|
513
|
-
*
|
|
514
|
-
* @template T
|
|
515
|
-
* Type defined by creation callback to do the work of creation (string or string[]).
|
|
516
|
-
*
|
|
517
|
-
* @param length
|
|
518
|
-
* See public methods.
|
|
519
|
-
*
|
|
520
|
-
* @param exclusion
|
|
521
|
-
* See public methods.
|
|
522
|
-
*
|
|
523
|
-
* @param tweak
|
|
524
|
-
* See public methods.
|
|
525
|
-
*
|
|
526
|
-
* @param creationCallback
|
|
527
|
-
* See public methods.
|
|
528
|
-
*
|
|
529
|
-
* @param createCallback
|
|
530
|
-
* Callback to do the work of creation, whether for a single value or a sequence. Called with the appropriate
|
|
531
|
-
* transformer and a transformation callback method to map individual transformed values to strings.
|
|
532
|
-
*
|
|
533
|
-
* @returns
|
|
534
|
-
* Created string or iterable iterator over created strings.
|
|
535
|
-
*/
|
|
536
|
-
private doCreate<T>(length: number, exclusion: Exclusion, tweak: number | bigint | undefined, creationCallback: CreationCallback | undefined, createCallback: (transformer: Transformer, transformationCallback: TransformationCallback<string>) => T): T {
|
|
537
|
-
this.validateLength(length);
|
|
538
|
-
this.validateExclusion(exclusion);
|
|
539
|
-
|
|
540
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
541
|
-
const allZerosValue = exclusion === Exclusion.AllNumeric ? this._allZerosValues![length] : undefined;
|
|
542
|
-
|
|
543
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
544
|
-
const transformer = Transformer.get(this._exclusionDomains[exclusion]![length], tweak);
|
|
545
|
-
|
|
546
|
-
return createCallback(transformer, (transformedValue, index) => {
|
|
547
|
-
let s = "";
|
|
548
|
-
|
|
549
|
-
// Empty string is valid.
|
|
550
|
-
if (length !== 0) {
|
|
551
|
-
let convertValue = transformedValue;
|
|
552
|
-
|
|
553
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
554
|
-
if (exclusion === Exclusion.AllNumeric && convertValue >= allZerosValue!) {
|
|
555
|
-
// Value to convert is shifted by the number of all-numeric strings that occur at or prior to it.
|
|
556
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
557
|
-
convertValue = convertValue + this.allNumericShift(true, length, convertValue - allZerosValue!);
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
// Build string from right to left excluding the first character.
|
|
561
|
-
for (let position = length - 1; position > 0; position--) {
|
|
562
|
-
const nextConvertValue = convertValue / this._characterSetSizeN;
|
|
563
|
-
|
|
564
|
-
// First step is effectively a modulus calculation.
|
|
565
|
-
s = this.character(Number(convertValue - nextConvertValue * this._characterSetSizeN)) + s;
|
|
566
|
-
|
|
567
|
-
convertValue = nextConvertValue;
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
// Zero is first in the character set for those that support excluding first zero.
|
|
571
|
-
s = this.character(exclusion === Exclusion.FirstZero ? Number(convertValue % this._characterSetSizeMinusOneN) + 1 : Number(convertValue % this._characterSetSizeN)) + s;
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
return creationCallback !== undefined ? creationCallback(s, index) : s;
|
|
575
|
-
});
|
|
576
|
-
}
|
|
577
|
-
|
|
578
550
|
/**
|
|
579
551
|
* Create a string by mapping a value to the equivalent characters in the character set across the length of the
|
|
580
552
|
* string.
|
|
@@ -598,68 +570,89 @@ export class CharacterSetCreator extends CharacterSetValidator {
|
|
|
598
570
|
* @returns
|
|
599
571
|
* String created from the value.
|
|
600
572
|
*/
|
|
601
|
-
create(length: number, value: number | bigint, exclusion
|
|
602
|
-
return this.doCreate(length, exclusion, tweak, creationCallback, (transformer, transformationCallback) => transformer.forward(BigInt(value), transformationCallback));
|
|
603
|
-
}
|
|
573
|
+
create(length: number, value: number | bigint, exclusion?: Exclusion, tweak?: number | bigint, creationCallback?: CreationCallback): string;
|
|
604
574
|
|
|
605
575
|
/**
|
|
606
|
-
* Create
|
|
607
|
-
*
|
|
608
|
-
* to `count - 1`.
|
|
609
|
-
*
|
|
610
|
-
* The implementation uses {@link Transformer.forwardSequence}, so the values are created only as needed.
|
|
576
|
+
* Create multiple strings by mapping each value to the equivalent characters in the character set across the length
|
|
577
|
+
* of the string. Equivalent to calling this method for each individual value.
|
|
611
578
|
*
|
|
612
579
|
* @param length
|
|
613
|
-
*
|
|
614
|
-
*
|
|
615
|
-
* @param startValue
|
|
616
|
-
* Numeric value of the first string. Strings are created from `startValue` to `startValue + count - 1`.
|
|
580
|
+
* Required string length.
|
|
617
581
|
*
|
|
618
|
-
* @param
|
|
619
|
-
*
|
|
582
|
+
* @param values
|
|
583
|
+
* Numeric values of the strings.
|
|
620
584
|
*
|
|
621
585
|
* @param exclusion
|
|
622
|
-
* See {@link
|
|
586
|
+
* Strings to be excluded from the range of outputs. See {@link Exclusion} for possible values and their meaning.
|
|
623
587
|
*
|
|
624
588
|
* @param tweak
|
|
625
|
-
*
|
|
589
|
+
* If provided, the numerical value of the strings are "tweaked" using an {@link EncryptionTransformer | encryption
|
|
590
|
+
* transformer}.
|
|
626
591
|
*
|
|
627
592
|
* @param creationCallback
|
|
628
|
-
*
|
|
593
|
+
* If provided, called after each string is constructed to create the final value.
|
|
629
594
|
*
|
|
630
595
|
* @returns
|
|
631
|
-
* Iterable iterator over created
|
|
596
|
+
* Iterable iterator over strings created from the values.
|
|
632
597
|
*/
|
|
633
|
-
|
|
634
|
-
return this.doCreate(length, exclusion, tweak, creationCallback, (transformer, transformationCallback) => transformer.forwardSequence(BigInt(startValue), count, transformationCallback));
|
|
635
|
-
}
|
|
598
|
+
create(length: number, values: Iterable<number | bigint>, exclusion?: Exclusion, tweak?: number | bigint, creationCallback?: CreationCallback): IterableIterator<string>;
|
|
636
599
|
|
|
637
600
|
/**
|
|
638
|
-
* Create multiple strings
|
|
639
|
-
*
|
|
640
|
-
*
|
|
641
|
-
* The implementation uses {@link Transformer.forwardMultiple}, so the values are created only as needed.
|
|
601
|
+
* Create a string or multiple strings. This signature exists to allow similar overloaded methods in other classes
|
|
602
|
+
* to call this method correctly.
|
|
642
603
|
*
|
|
643
604
|
* @param length
|
|
644
|
-
* See {@link create}.
|
|
645
605
|
*
|
|
646
|
-
* @param
|
|
647
|
-
* Source of values.
|
|
606
|
+
* @param valueOrValues
|
|
648
607
|
*
|
|
649
608
|
* @param exclusion
|
|
650
|
-
* See {@link create}.
|
|
651
609
|
*
|
|
652
610
|
* @param tweak
|
|
653
|
-
* See {@link create}.
|
|
654
611
|
*
|
|
655
612
|
* @param creationCallback
|
|
656
|
-
* See {@link create}.
|
|
657
613
|
*
|
|
658
614
|
* @returns
|
|
659
|
-
* Iterable iterator over created strings.
|
|
660
615
|
*/
|
|
661
|
-
|
|
662
|
-
|
|
616
|
+
create(length: number, valueOrValues: number | bigint | Iterable<number | bigint>, exclusion?: Exclusion, tweak?: number | bigint, creationCallback?: CreationCallback): string | IterableIterator<string>;
|
|
617
|
+
|
|
618
|
+
// eslint-disable-next-line jsdoc/require-jsdoc -- Implementation of overloaded signatures.
|
|
619
|
+
create(length: number, valueOrValues: number | bigint | Iterable<number | bigint>, exclusion: Exclusion = Exclusion.None, tweak?: number | bigint, creationCallback?: CreationCallback): string | IterableIterator<string> {
|
|
620
|
+
this.validateLength(length);
|
|
621
|
+
this.validateExclusion(exclusion);
|
|
622
|
+
|
|
623
|
+
// Zero value obviates need for non-null assertion.
|
|
624
|
+
const allZerosValue = exclusion === Exclusion.AllNumeric ? this._allZerosValues[length] : 0n;
|
|
625
|
+
|
|
626
|
+
const transformer = Transformer.get(this._exclusionDomains[exclusion][length], tweak);
|
|
627
|
+
|
|
628
|
+
return transformer.forward(valueOrValues, (transformedValue, index) => {
|
|
629
|
+
let s = "";
|
|
630
|
+
|
|
631
|
+
// Empty string is valid.
|
|
632
|
+
if (length !== 0) {
|
|
633
|
+
let convertValue = transformedValue;
|
|
634
|
+
|
|
635
|
+
if (exclusion === Exclusion.AllNumeric && convertValue >= allZerosValue) {
|
|
636
|
+
// Value to convert is shifted by the number of all-numeric strings that occur at or prior to it.
|
|
637
|
+
convertValue = convertValue + this.allNumericShift(true, length, convertValue - allZerosValue);
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
// Build string from right to left excluding the first character.
|
|
641
|
+
for (let position = length - 1; position > 0; position--) {
|
|
642
|
+
const nextConvertValue = convertValue / this._characterSetSizeN;
|
|
643
|
+
|
|
644
|
+
// First step is effectively a modulus calculation.
|
|
645
|
+
s = this.character(Number(convertValue - nextConvertValue * this._characterSetSizeN)) + s;
|
|
646
|
+
|
|
647
|
+
convertValue = nextConvertValue;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
// Zero is first in the character set for those that support excluding first zero.
|
|
651
|
+
s = this.character(exclusion === Exclusion.FirstZero ? Number(convertValue % this._characterSetSizeMinusOneN) + 1 : Number(convertValue % this._characterSetSizeN)) + s;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
return creationCallback !== undefined ? creationCallback(s, index) : s;
|
|
655
|
+
});
|
|
663
656
|
}
|
|
664
657
|
|
|
665
658
|
/**
|
|
@@ -678,7 +671,7 @@ export class CharacterSetCreator extends CharacterSetValidator {
|
|
|
678
671
|
* @returns
|
|
679
672
|
* Numeric value of the string.
|
|
680
673
|
*/
|
|
681
|
-
|
|
674
|
+
valueFor(s: string, exclusion: Exclusion = Exclusion.None, tweak?: number | bigint): bigint {
|
|
682
675
|
const length = s.length;
|
|
683
676
|
|
|
684
677
|
this.validateLength(length);
|
|
@@ -717,8 +710,7 @@ export class CharacterSetCreator extends CharacterSetValidator {
|
|
|
717
710
|
}, 0n);
|
|
718
711
|
|
|
719
712
|
if (exclusion === Exclusion.AllNumeric) {
|
|
720
|
-
|
|
721
|
-
const allZerosValue = this._allZerosValues![length];
|
|
713
|
+
const allZerosValue = this._allZerosValues[length];
|
|
722
714
|
|
|
723
715
|
if (value >= allZerosValue) {
|
|
724
716
|
// Call will ensure that string is not all-numeric.
|
|
@@ -726,8 +718,7 @@ export class CharacterSetCreator extends CharacterSetValidator {
|
|
|
726
718
|
}
|
|
727
719
|
}
|
|
728
720
|
|
|
729
|
-
|
|
730
|
-
return Transformer.get(this._exclusionDomains[exclusion]![length], tweak).reverse(value);
|
|
721
|
+
return Transformer.get(this._exclusionDomains[exclusion][length], tweak).reverse(value);
|
|
731
722
|
}
|
|
732
723
|
}
|
|
733
724
|
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export * from "./
|
|
1
|
+
export * from "./sequencer.js";
|
|
2
2
|
export * from "./transformer.js";
|
|
3
|
-
export * from "./string.js";
|
|
3
|
+
export type * from "./string.js";
|
|
4
4
|
export * from "./reg_exp.js";
|
|
5
5
|
export * from "./record.js";
|
|
6
6
|
export * from "./character_set.js";
|
|
@@ -2,15 +2,17 @@ export const localeStrings = {
|
|
|
2
2
|
Transformer: {
|
|
3
3
|
domainMustBeGreaterThanZero: "Domain {{domain}} must be greater than 0",
|
|
4
4
|
tweakMustBeGreaterThanOrEqualToZero: "Tweak {{tweak}} must be greater than or equal to 0",
|
|
5
|
-
valueMustBeGreaterThanOrEqualToZero: "Value {{
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
valueMustBeGreaterThanOrEqualToZero: "Value {{value}} must be greater than or equal to 0",
|
|
6
|
+
valueMustBeLessThan: "Value {{value}} must be less than {{domain}}",
|
|
7
|
+
minValueMustBeGreaterThanOrEqualToZero: "Minimum value {{minValue}} must be greater than or equal to 0",
|
|
8
|
+
maxValueMustBeLessThan: "Maximum value {{maxValue}} must be less than {{domain}}"
|
|
9
9
|
},
|
|
10
10
|
RegExpValidator: {
|
|
11
11
|
stringDoesNotMatchPattern: "String {{s}} does not match pattern"
|
|
12
12
|
},
|
|
13
13
|
CharacterSetValidator: {
|
|
14
|
+
firstZeroFirstCharacter: "Character set must support zero as first character",
|
|
15
|
+
allNumericAllNumericCharacters: "Character set must support all numeric characters in sequence",
|
|
14
16
|
stringMustNotBeAllNumeric: "String must not be all numeric",
|
|
15
17
|
lengthMustBeGreaterThanOrEqualTo: "Length {{length}} must be greater than or equal to {{minimumLength}}",
|
|
16
18
|
lengthMustBeLessThanOrEqualTo: "Length {{length}} must be less than or equal to {{maximumLength}}",
|
package/src/locale/i18next.d.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import type { localeStrings } from "./en/locale_strings.js";
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Internationalization module.
|
|
5
|
+
*/
|
|
3
6
|
declare module "i18next" {
|
|
7
|
+
/**
|
|
8
|
+
* Custom type options for this package.
|
|
9
|
+
*/
|
|
4
10
|
interface CustomTypeOptions {
|
|
5
11
|
resources: {
|
|
6
12
|
// Extract the type from the English locale strings object.
|
package/src/record.ts
CHANGED
|
@@ -2,8 +2,8 @@ import i18next, { utilityNS } from "./locale/i18n.js";
|
|
|
2
2
|
import type { StringValidator } from "./string.js";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* Record validator. Validation is performed against a record with a string key type and throws an
|
|
6
|
-
*
|
|
5
|
+
* Record validator. Validation is performed against a record with a string key type and throws an error if the key is
|
|
6
|
+
* not found.
|
|
7
7
|
*/
|
|
8
8
|
export class RecordValidator<T> implements StringValidator {
|
|
9
9
|
/**
|
|
@@ -49,8 +49,6 @@ export class RecordValidator<T> implements StringValidator {
|
|
|
49
49
|
*
|
|
50
50
|
* @param key
|
|
51
51
|
* Record key.
|
|
52
|
-
*
|
|
53
|
-
* @throws RangeError
|
|
54
52
|
*/
|
|
55
53
|
validate(key: string): void {
|
|
56
54
|
if (this.record[key] === undefined) {
|