@aidc-toolkit/gs1 0.9.1 → 0.9.3

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.
@@ -0,0 +1,12 @@
1
+ <component name="ProjectRunConfigurationManager">
2
+ <configuration default="false" name="eslint" type="js.build_tools.npm" nameIsGenerated="true">
3
+ <package-json value="$PROJECT_DIR$/package.json" />
4
+ <command value="run" />
5
+ <scripts>
6
+ <script value="eslint" />
7
+ </scripts>
8
+ <node-interpreter value="project" />
9
+ <envs />
10
+ <method v="2" />
11
+ </configuration>
12
+ </component>
package/eslint.config.js CHANGED
@@ -1,18 +1,3 @@
1
- import tseslint from "typescript-eslint";
2
- import js from "@eslint/js";
3
- import stylistic from "@stylistic/eslint-plugin";
4
- import jsdoc from "eslint-plugin-jsdoc";
5
- import esLintConfigLove from "eslint-config-love";
6
1
  import { esLintConfigAIDCToolkit } from "@aidc-toolkit/dev";
7
2
 
8
- export default tseslint.config(
9
- {
10
- ignores: ["eslint.config.js", "dist"]
11
- },
12
- js.configs.recommended,
13
- ...tseslint.configs.strictTypeChecked,
14
- stylistic.configs["recommended-flat"],
15
- jsdoc.configs["flat/recommended-typescript"],
16
- esLintConfigLove,
17
- esLintConfigAIDCToolkit
18
- );
3
+ export default esLintConfigAIDCToolkit;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aidc-toolkit/gs1",
3
- "version": "0.9.1",
3
+ "version": "0.9.3",
4
4
  "description": "GS1 AIDC Toolkit",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -21,25 +21,21 @@
21
21
  "scripts": {
22
22
  "eslint": "eslint .",
23
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
+ "build-doc": "npm run build && tsc src/index.ts --outDir dist --target esnext --moduleResolution nodenext --module nodenext --emitDeclarationOnly --declaration --declarationMap",
25
25
  "test": "vitest run"
26
26
  },
27
27
  "devDependencies": {
28
- "@aidc-toolkit/dev": "^0.9.1",
29
- "@eslint/js": "^9.11.1",
30
- "@stylistic/eslint-plugin": "^2.8.0",
31
- "eslint-config-love": "^71.0.0",
32
- "eslint-plugin-jsdoc": "^50.3.0",
28
+ "@aidc-toolkit/dev": "^0.9.3",
29
+ "eslint": "^9.14.0",
33
30
  "ts-node": "^10.9.2",
34
- "tsup": "^8.3.0",
35
- "typescript": "^5.6.2",
36
- "typescript-eslint": "^8.7.0",
37
- "vitest": "^2.1.1"
31
+ "tsup": "^8.3.5",
32
+ "typescript": "^5.6.3",
33
+ "vitest": "^2.1.5"
38
34
  },
39
35
  "dependencies": {
40
- "@aidc-toolkit/core": "^0.9.1",
41
- "@aidc-toolkit/utility": "^0.9.1",
42
- "i18next": "^23.15.1",
36
+ "@aidc-toolkit/core": "^0.9.3",
37
+ "@aidc-toolkit/utility": "^0.9.3",
38
+ "i18next": "^23.16.5",
43
39
  "ts-mixer": "^6.0.4"
44
40
  }
45
41
  }
package/src/check.ts CHANGED
@@ -55,17 +55,15 @@ export function checkDigitSum(exchangeWeights: boolean, s: string): number {
55
55
  let weight3 = (s.length + Number(exchangeWeights)) % 2 === 0;
56
56
 
57
57
  // Calculate sum of each character value multiplied by the weight at its position.
58
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
59
- return NUMERIC_CREATOR.characterIndexes(s).reduce((accumulator, characterIndex, index) => {
58
+ return NUMERIC_CREATOR.characterIndexes(s).reduce<number>((accumulator, characterIndex, index) => {
60
59
  if (characterIndex === undefined) {
61
60
  throw new RangeError(`Invalid character '${s.charAt(index)}' at position ${index + 1}`);
62
61
  }
63
62
 
64
63
  weight3 = !weight3;
65
64
 
66
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
67
- return accumulator! + (weight3 ? THREE_WEIGHT_RESULTS[characterIndex] : characterIndex);
68
- }, 0)!;
65
+ return accumulator + (weight3 ? THREE_WEIGHT_RESULTS[characterIndex] : characterIndex);
66
+ }, 0);
69
67
  }
70
68
 
71
69
  /**
@@ -118,16 +116,14 @@ function priceWeightSum(weightsResults: ReadonlyArray<readonly number[]>, s: str
118
116
  const characterIndexes = NUMERIC_CREATOR.characterIndexes(s);
119
117
 
120
118
  // Calculate sum of each weight result for each digit at its position.
121
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
122
- return characterIndexes.reduce((accumulator, characterIndex, index) => {
119
+ return characterIndexes.reduce<number>((accumulator, characterIndex, index) => {
123
120
  if (characterIndex === undefined) {
124
121
  throw new RangeError(`Invalid character '${s.charAt(index)}' at position ${index + 1}`);
125
122
  }
126
123
 
127
124
  // Add the weight result of the character index to the accumulator.
128
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
129
- return accumulator! + weightsResults[index][characterIndex];
130
- }, 0)!;
125
+ return accumulator + weightsResults[index][characterIndex];
126
+ }, 0);
131
127
  }
132
128
 
133
129
  /**
@@ -196,15 +192,13 @@ export function checkCharacterPair(s: string): string {
196
192
  }
197
193
 
198
194
  // Calculate sum of each character value multiplied by the weight at its position, mod 1021.
199
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
200
- const checkCharacterPairSum = AI82_CREATOR.characterIndexes(s).reduce((accumulator, characterIndex, index) => {
195
+ const checkCharacterPairSum = AI82_CREATOR.characterIndexes(s).reduce<number>((accumulator, characterIndex, index) => {
201
196
  if (characterIndex === undefined) {
202
197
  throw new RangeError(`Invalid character '${s.charAt(index)}' at position ${index + 1}`);
203
198
  }
204
199
 
205
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
206
- return accumulator! + characterIndex * CHECK_CHARACTER_WEIGHTS[weightIndexStart + index];
207
- }, 0)! % 1021;
200
+ return accumulator + characterIndex * CHECK_CHARACTER_WEIGHTS[weightIndexStart + index];
201
+ }, 0) % 1021;
208
202
 
209
203
  const checkCharacterPairSumMod32 = checkCharacterPairSum % 32;
210
204
 
package/src/idkey.ts CHANGED
@@ -131,7 +131,7 @@ export enum CharacterSet {
131
131
  export interface IdentificationKeyValidation extends StringValidation {
132
132
  /**
133
133
  * Position offset within a larger string. Strings are sometimes composed of multiple substrings; this parameter
134
- * ensures that the exception notes the proper position in the string.
134
+ * ensures that the error notes the proper position in the string.
135
135
  */
136
136
  positionOffset?: number | undefined;
137
137
  }
@@ -170,7 +170,7 @@ export interface IdentificationKeyValidator<V extends IdentificationKeyValidatio
170
170
  get referenceValidator(): CharacterSetValidator;
171
171
 
172
172
  /**
173
- * Validate an identification key and throw an exception if validation fails.
173
+ * Validate an identification key and throw an error if validation fails.
174
174
  *
175
175
  * @param identificationKey
176
176
  * Identification key.
@@ -185,6 +185,10 @@ export interface IdentificationKeyValidator<V extends IdentificationKeyValidatio
185
185
  * Abstract identification key validator. Implements common functionality for an identification key validator.
186
186
  */
187
187
  abstract class AbstractIdentificationKeyValidator<V extends IdentificationKeyValidation = IdentificationKeyValidation> implements IdentificationKeyValidator<V> {
188
+ private static readonly CHARACTER_SET_CREATORS = [
189
+ NUMERIC_CREATOR, AI82_CREATOR, AI39_CREATOR
190
+ ];
191
+
188
192
  /**
189
193
  * Identification key type.
190
194
  */
@@ -206,7 +210,7 @@ abstract class AbstractIdentificationKeyValidator<V extends IdentificationKeyVal
206
210
  private readonly _referenceCharacterSet: CharacterSet;
207
211
 
208
212
  /**
209
- * Character set validator.
213
+ * Reference validator.
210
214
  */
211
215
  private readonly _referenceValidator: CharacterSetValidator;
212
216
 
@@ -220,23 +224,7 @@ abstract class AbstractIdentificationKeyValidator<V extends IdentificationKeyVal
220
224
  * Character set validator.
221
225
  */
222
226
  protected static validatorFor(characterSet: CharacterSet): CharacterSetValidator {
223
- let characterSetValidator: CharacterSetValidator;
224
-
225
- switch (characterSet) {
226
- case CharacterSet.Numeric:
227
- characterSetValidator = NUMERIC_CREATOR;
228
- break;
229
-
230
- case CharacterSet.AI82:
231
- characterSetValidator = AI82_CREATOR;
232
- break;
233
-
234
- case CharacterSet.AI39:
235
- characterSetValidator = AI39_CREATOR;
236
- break;
237
- }
238
-
239
- return characterSetValidator;
227
+ return AbstractIdentificationKeyValidator.CHARACTER_SET_CREATORS[characterSet];
240
228
  }
241
229
 
242
230
  /**
@@ -298,7 +286,7 @@ abstract class AbstractIdentificationKeyValidator<V extends IdentificationKeyVal
298
286
  }
299
287
 
300
288
  /**
301
- * Pad an identification key on the left with zeroes for validation purposes. This is done to align an
289
+ * Pad an identification key on the left with zero-value character for validation purposes. This is done to align an
302
290
  * identification key with a position offset for any error message that may be thrown by the reference validator.
303
291
  *
304
292
  * @param identificationKey
@@ -310,9 +298,9 @@ abstract class AbstractIdentificationKeyValidator<V extends IdentificationKeyVal
310
298
  * @returns
311
299
  * Padded identification key.
312
300
  */
313
- protected static padIdentificationKey(identificationKey: string, validation: IdentificationKeyValidation | undefined): string {
301
+ protected padIdentificationKey(identificationKey: string, validation: IdentificationKeyValidation | undefined): string {
314
302
  // Identification key is returned as is if position offset is undefined.
315
- return validation?.positionOffset === undefined ? identificationKey : "0".repeat(validation.positionOffset).concat(identificationKey);
303
+ return validation?.positionOffset === undefined ? identificationKey : this.referenceValidator.character(0).repeat(validation.positionOffset).concat(identificationKey);
316
304
  }
317
305
 
318
306
  /**
@@ -427,7 +415,7 @@ abstract class AbstractNumericIdentificationKeyValidator extends AbstractIdentif
427
415
  }
428
416
 
429
417
  // Validating the check digit will also validate the characters.
430
- if (!hasValidCheckDigit(AbstractIdentificationKeyValidator.padIdentificationKey(identificationKey, validation))) {
418
+ if (!hasValidCheckDigit(this.padIdentificationKey(identificationKey, validation))) {
431
419
  throw new RangeError(i18next.t("IdentificationKey.invalidCheckDigit", {
432
420
  ns: gs1NS
433
421
  }));
@@ -711,7 +699,7 @@ export class SerializableNumericIdentificationKeyValidator extends NonGTINNumeri
711
699
  private readonly _serialComponentCharacterSet: CharacterSet;
712
700
 
713
701
  /**
714
- * Serial component character set validation parameters.
702
+ * Serial component validation parameters.
715
703
  */
716
704
  private readonly _serialComponentValidation: CharacterSetValidation;
717
705
 
@@ -855,7 +843,7 @@ export class NonNumericIdentificationKeyValidator extends AbstractIdentification
855
843
  }
856
844
 
857
845
  /**
858
- * Validate a non-numeric identification key and throw an exception if validation fails.
846
+ * Validate a non-numeric identification key and throw an error if validation fails.
859
847
  *
860
848
  * @param identificationKey
861
849
  * Identification key.
@@ -874,7 +862,7 @@ export class NonNumericIdentificationKeyValidator extends AbstractIdentification
874
862
  positionOffset: validation?.positionOffset
875
863
  });
876
864
  // Validating the check character pair will also validate the characters.
877
- } else if (!hasValidCheckCharacterPair(AbstractIdentificationKeyValidator.padIdentificationKey(identificationKey, validation))) {
865
+ } else if (!hasValidCheckCharacterPair(this.padIdentificationKey(identificationKey, validation))) {
878
866
  throw new RangeError(i18next.t("IdentificationKey.invalidCheckCharacterPair", {
879
867
  ns: gs1NS
880
868
  }));
@@ -1002,12 +990,12 @@ abstract class AbstractIdentificationKeyCreator implements IdentificationKeyCrea
1002
990
  /**
1003
991
  * Prefix manager.
1004
992
  */
1005
- private _prefixManager?: PrefixManager;
993
+ private _prefixManager!: PrefixManager;
1006
994
 
1007
995
  /**
1008
996
  * Reference length.
1009
997
  */
1010
- private _referenceLength?: number;
998
+ private _referenceLength!: number;
1011
999
 
1012
1000
  /**
1013
1001
  * Initialize the prefix manager. This method is in lieu of a constructor due to the mixin architecture.
@@ -1022,12 +1010,6 @@ abstract class AbstractIdentificationKeyCreator implements IdentificationKeyCrea
1022
1010
  * Number of characters to allow for check digit or check character pair.
1023
1011
  */
1024
1012
  protected init(prefixManager: PrefixManager, prefix: string, checkAllowance: number): void {
1025
- // Verify that prefix manager has not already been assigned.
1026
- if (this._prefixManager !== undefined) {
1027
- // Should never get here.
1028
- throw new Error("Not supported");
1029
- }
1030
-
1031
1013
  this._prefixManager = prefixManager;
1032
1014
 
1033
1015
  // Reference length allows for prefix and optionally check digit or check character pair.
@@ -1055,9 +1037,7 @@ abstract class AbstractIdentificationKeyCreator implements IdentificationKeyCrea
1055
1037
  * @inheritDoc
1056
1038
  */
1057
1039
  get prefixManager(): PrefixManager {
1058
- // Prefix manager is expected to have been initialized by this point.
1059
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1060
- return this._prefixManager!;
1040
+ return this._prefixManager;
1061
1041
  }
1062
1042
 
1063
1043
  /**
@@ -1071,8 +1051,7 @@ abstract class AbstractIdentificationKeyCreator implements IdentificationKeyCrea
1071
1051
  * @inheritDoc
1072
1052
  */
1073
1053
  get referenceLength(): number {
1074
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1075
- return this._referenceLength!;
1054
+ return this._referenceLength;
1076
1055
  }
1077
1056
 
1078
1057
  abstract validate(identificationKey: string, validation?: IdentificationKeyValidation): void;
@@ -1138,7 +1117,7 @@ abstract class AbstractNumericIdentificationKeyCreator extends AbstractIdentific
1138
1117
  /**
1139
1118
  * Capacity.
1140
1119
  */
1141
- private _capacity?: number;
1120
+ private _capacity!: number;
1142
1121
 
1143
1122
  /**
1144
1123
  * Tweak for sparse creation.
@@ -1167,8 +1146,7 @@ abstract class AbstractNumericIdentificationKeyCreator extends AbstractIdentific
1167
1146
  * @inheritDoc
1168
1147
  */
1169
1148
  get capacity(): number {
1170
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
1171
- return this._capacity!;
1149
+ return this._capacity;
1172
1150
  }
1173
1151
 
1174
1152
  /**
@@ -1210,7 +1188,7 @@ abstract class AbstractNumericIdentificationKeyCreator extends AbstractIdentific
1210
1188
  */
1211
1189
  create(values: Iterable<number | bigint>, sparse?: boolean): IterableIterator<string>;
1212
1190
 
1213
- // eslint-disable-next-line jsdoc/require-jsdoc
1191
+ // eslint-disable-next-line jsdoc/require-jsdoc -- Implementation of overloaded signatures.
1214
1192
  create(valueOrValues: number | bigint | Iterable<number | bigint>, sparse = false): string | IterableIterator<string> {
1215
1193
  return NUMERIC_CREATOR.create(this.referenceLength, valueOrValues, Exclusion.None, sparse ? this.tweak : undefined, reference => this.buildIdentificationKey(reference));
1216
1194
  }
@@ -1368,7 +1346,7 @@ export class GTINCreator extends Mixin(GTINValidator, AbstractNumericIdentificat
1368
1346
  */
1369
1347
  createGTIN14(indicatorDigit: string, values: Iterable<number | bigint>, sparse?: boolean): IterableIterator<string>;
1370
1348
 
1371
- // eslint-disable-next-line jsdoc/require-jsdoc
1349
+ // eslint-disable-next-line jsdoc/require-jsdoc -- Implementation of overloaded signatures.
1372
1350
  createGTIN14(indicatorDigit: string, valueOrValues: number | bigint | Iterable<number | bigint>, sparse = false): string | IterableIterator<string> {
1373
1351
  NUMERIC_CREATOR.validate(indicatorDigit, GTINCreator.REQUIRED_INDICATOR_DIGIT_VALIDATION);
1374
1352
 
@@ -1492,7 +1470,7 @@ export class GTINCreator extends Mixin(GTINValidator, AbstractNumericIdentificat
1492
1470
  break;
1493
1471
 
1494
1472
  case GTINType.GTIN8 as number:
1495
- if (gtin.charAt(0) !== "0") {
1473
+ if (!gtin.startsWith("0")) {
1496
1474
  // GTIN is GTIN-8.
1497
1475
  normalizedGTIN = gtin;
1498
1476
  } else {
@@ -1625,7 +1603,7 @@ export class SerializableNumericIdentificationKeyCreator extends Mixin(Serializa
1625
1603
  */
1626
1604
  private concatenateValidated(baseIdentificationKey: string, serialComponents: Iterable<string>): IterableIterator<string>;
1627
1605
 
1628
- // eslint-disable-next-line jsdoc/require-jsdoc
1606
+ // eslint-disable-next-line jsdoc/require-jsdoc -- Implementation of overloaded signatures.
1629
1607
  private concatenateValidated(baseIdentificationKey: string, serialComponent: string | Iterable<string>): string | IterableIterator<string> {
1630
1608
  let result: string | IterableIterator<string>;
1631
1609
 
@@ -1676,7 +1654,7 @@ export class SerializableNumericIdentificationKeyCreator extends Mixin(Serializa
1676
1654
  */
1677
1655
  createSerialized(value: number, serialComponents: Iterable<string>, sparse?: boolean): IterableIterator<string>;
1678
1656
 
1679
- // eslint-disable-next-line jsdoc/require-jsdoc
1657
+ // eslint-disable-next-line jsdoc/require-jsdoc -- Implementation of overloaded signatures.
1680
1658
  createSerialized(value: number, serialComponent: string | Iterable<string>, sparse = false): string | IterableIterator<string> {
1681
1659
  return this.concatenateValidated(this.create(value, sparse), serialComponent);
1682
1660
  }
@@ -1709,7 +1687,7 @@ export class SerializableNumericIdentificationKeyCreator extends Mixin(Serializa
1709
1687
  */
1710
1688
  concatenate(baseIdentificationKey: string, serialComponents: Iterable<string>): IterableIterator<string>;
1711
1689
 
1712
- // eslint-disable-next-line jsdoc/require-jsdoc
1690
+ // eslint-disable-next-line jsdoc/require-jsdoc -- Implementation of overloaded signatures.
1713
1691
  concatenate(baseIdentificationKey: string, serialComponent: string | Iterable<string>): string | IterableIterator<string> {
1714
1692
  this.validate(baseIdentificationKey);
1715
1693
 
@@ -1722,7 +1700,7 @@ export class SerializableNumericIdentificationKeyCreator extends Mixin(Serializa
1722
1700
  */
1723
1701
  export class NonNumericIdentificationKeyCreator extends Mixin(NonNumericIdentificationKeyValidator, AbstractIdentificationKeyCreator) {
1724
1702
  /**
1725
- * Reference character set validation parameters.
1703
+ * Reference validation parameters.
1726
1704
  */
1727
1705
  private readonly _referenceValidation: CharacterSetValidation;
1728
1706
 
@@ -1782,7 +1760,7 @@ export class NonNumericIdentificationKeyCreator extends Mixin(NonNumericIdentifi
1782
1760
  */
1783
1761
  create(references: Iterable<string>): IterableIterator<string>;
1784
1762
 
1785
- // eslint-disable-next-line jsdoc/require-jsdoc
1763
+ // eslint-disable-next-line jsdoc/require-jsdoc -- Implementation of overloaded signatures.
1786
1764
  create(referenceOrReferences: string | Iterable<string>): string | IterableIterator<string> {
1787
1765
  let result: string | IterableIterator<string>;
1788
1766
 
@@ -1800,6 +1778,26 @@ export class NonNumericIdentificationKeyCreator extends Mixin(NonNumericIdentifi
1800
1778
  }
1801
1779
  }
1802
1780
 
1781
+ /**
1782
+ * Prefix validation parameters.
1783
+ */
1784
+ interface PrefixValidation extends CharacterSetValidation {
1785
+ /**
1786
+ * Minimum length.
1787
+ */
1788
+ minimumLength: number;
1789
+
1790
+ /**
1791
+ * Maximum length.
1792
+ */
1793
+ maximumLength: number;
1794
+
1795
+ /**
1796
+ * Callback to localized prefix type name.
1797
+ */
1798
+ component: () => string;
1799
+ }
1800
+
1803
1801
  /**
1804
1802
  * Prefix manager. This is the core class for identification key creation.
1805
1803
  *
@@ -1860,7 +1858,7 @@ export class PrefixManager {
1860
1858
  /**
1861
1859
  * Validation parameters for GS1 Company Prefix.
1862
1860
  */
1863
- private static readonly GS1_COMPANY_PREFIX_VALIDATION: CharacterSetValidation = {
1861
+ private static readonly GS1_COMPANY_PREFIX_VALIDATION: PrefixValidation = {
1864
1862
  minimumLength: PrefixManager.GS1_COMPANY_PREFIX_MINIMUM_LENGTH,
1865
1863
  maximumLength: PrefixManager.GS1_COMPANY_PREFIX_MAXIMUM_LENGTH,
1866
1864
  component: () => i18next.t("Prefix.gs1CompanyPrefix", {
@@ -1871,7 +1869,7 @@ export class PrefixManager {
1871
1869
  /**
1872
1870
  * Validation parameters for U.P.C. Company Prefix expressed as GS1 Company Prefix.
1873
1871
  */
1874
- private static readonly UPC_COMPANY_PREFIX_AS_GS1_COMPANY_PREFIX_VALIDATION: CharacterSetValidation = {
1872
+ private static readonly UPC_COMPANY_PREFIX_AS_GS1_COMPANY_PREFIX_VALIDATION: PrefixValidation = {
1875
1873
  minimumLength: PrefixManager.UPC_COMPANY_PREFIX_MINIMUM_LENGTH + 1,
1876
1874
  maximumLength: PrefixManager.UPC_COMPANY_PREFIX_MAXIMUM_LENGTH + 1,
1877
1875
  component: () => i18next.t("Prefix.gs1CompanyPrefix", {
@@ -1882,7 +1880,7 @@ export class PrefixManager {
1882
1880
  /**
1883
1881
  * Validation parameters for GS1-8 Prefix expressed as GS1 Company Prefix.
1884
1882
  */
1885
- private static readonly GS1_8_PREFIX_AS_GS1_COMPANY_PREFIX_VALIDATION: CharacterSetValidation = {
1883
+ private static readonly GS1_8_PREFIX_AS_GS1_COMPANY_PREFIX_VALIDATION: PrefixValidation = {
1886
1884
  minimumLength: PrefixManager.GS1_8_PREFIX_MINIMUM_LENGTH + 5,
1887
1885
  maximumLength: PrefixManager.GS1_8_PREFIX_MAXIMUM_LENGTH + 5,
1888
1886
  component: () => i18next.t("Prefix.gs1CompanyPrefix", {
@@ -1893,7 +1891,7 @@ export class PrefixManager {
1893
1891
  /**
1894
1892
  * Validation parameters for U.P.C. Company Prefix.
1895
1893
  */
1896
- private static readonly UPC_COMPANY_PREFIX_VALIDATION: CharacterSetValidation = {
1894
+ private static readonly UPC_COMPANY_PREFIX_VALIDATION: PrefixValidation = {
1897
1895
  minimumLength: PrefixManager.UPC_COMPANY_PREFIX_MINIMUM_LENGTH,
1898
1896
  maximumLength: PrefixManager.UPC_COMPANY_PREFIX_MAXIMUM_LENGTH,
1899
1897
  component: () => i18next.t("Prefix.upcCompanyPrefix", {
@@ -1904,7 +1902,7 @@ export class PrefixManager {
1904
1902
  /**
1905
1903
  * Validation parameters for GS1-8 Prefix.
1906
1904
  */
1907
- private static readonly GS1_8_PREFIX_VALIDATION: CharacterSetValidation = {
1905
+ private static readonly GS1_8_PREFIX_VALIDATION: PrefixValidation = {
1908
1906
  minimumLength: PrefixManager.GS1_8_PREFIX_MINIMUM_LENGTH,
1909
1907
  maximumLength: PrefixManager.GS1_8_PREFIX_MAXIMUM_LENGTH,
1910
1908
  component: () => i18next.t("Prefix.gs18Prefix", {
@@ -1916,7 +1914,7 @@ export class PrefixManager {
1916
1914
  * Creator tweak factors. Different numeric identification key types have different tweak factors so that sparse
1917
1915
  * creation generates different sequences for each.
1918
1916
  */
1919
- private static readonly CREATOR_TWEAK_FACTORS_MAP = new Map<IdentificationKeyType, bigint>([
1917
+ private static readonly CREATOR_TWEAK_FACTORS_MAP: ReadonlyMap<IdentificationKeyType, bigint> = new Map([
1920
1918
  [IdentificationKeyType.GTIN, 1987n],
1921
1919
  [IdentificationKeyType.GLN, 4241n],
1922
1920
  [IdentificationKeyType.SSCC, 8087n],
@@ -2058,9 +2056,9 @@ export class PrefixManager {
2058
2056
  if (this._tweakFactor !== tweakFactor) {
2059
2057
  this._tweakFactor = tweakFactor;
2060
2058
 
2061
- this._identificationKeyCreatorsMap.forEach((creator) => {
2059
+ for (const creator of this._identificationKeyCreatorsMap.values()) {
2062
2060
  this.setCreatorTweak(creator);
2063
- });
2061
+ }
2064
2062
  }
2065
2063
  }
2066
2064
 
@@ -2138,7 +2136,7 @@ export class PrefixManager {
2138
2136
  * Position offset within a larger string.
2139
2137
  */
2140
2138
  static validatePrefix(prefixType: PrefixType, allowUPCCompanyPrefix: boolean, allowGS18Prefix: boolean, prefix: string, isFromIdentificationKey = false, isNumericIdentificationKey = false, positionOffset?: number): void {
2141
- let baseValidation: CharacterSetValidation;
2139
+ let baseValidation: PrefixValidation;
2142
2140
 
2143
2141
  // Validate the prefix type and determine the prefix validation parameters.
2144
2142
  switch (prefixType) {
@@ -2189,7 +2187,7 @@ export class PrefixManager {
2189
2187
  break;
2190
2188
  }
2191
2189
 
2192
- const mergedValidation: CharacterSetValidation = {
2190
+ const mergedValidation: PrefixValidation = {
2193
2191
  ...baseValidation,
2194
2192
  positionOffset
2195
2193
  };
@@ -2199,8 +2197,7 @@ export class PrefixManager {
2199
2197
  NUMERIC_CREATOR.validate(prefix, mergedValidation);
2200
2198
  } else if (!isNumericIdentificationKey) {
2201
2199
  // Validate only the minimum length, allowing at least one character for the (possibly non-numeric) reference.
2202
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
2203
- NUMERIC_CREATOR.validate(prefix.substring(0, Math.min(mergedValidation.minimumLength!, prefix.length - 1)), mergedValidation);
2200
+ NUMERIC_CREATOR.validate(prefix.substring(0, Math.min(mergedValidation.minimumLength, prefix.length - 1)), mergedValidation);
2204
2201
  }
2205
2202
  }
2206
2203
 
@@ -2230,6 +2227,8 @@ export class PrefixManager {
2230
2227
  creator = constructorCallback();
2231
2228
 
2232
2229
  this.setCreatorTweak(creator);
2230
+
2231
+ this._identificationKeyCreatorsMap.set(identificationKeyType, creator);
2233
2232
  }
2234
2233
 
2235
2234
  return creator;
@@ -0,0 +1,34 @@
1
+ export const localeStrings = {
2
+ Check: {
3
+ lengthOfStringForCheckCharacterPairMustBeLessThanOrEqualTo: "La longueur {{length}} de la chaîne pour la paire de caractères de vérification doit être inférieure ou égale à {{maximum Length}}"
4
+ },
5
+ IdentificationKey: {
6
+ identificationKeyTypeLength: "{{identificationKeyType}} doit comporter {{length}} chiffres",
7
+ invalidCheckDigit: "Chiffre de contrôle non valide",
8
+ invalidGTINLength: "Le GTIN doit comporter 13, 12, 8 ou 14 chiffres",
9
+ invalidGTIN14Length: "Le GTIN doit comporter 14 chiffres",
10
+ invalidZeroSuppressedGTIN12: "Code GTIN-12 non valide avec zéro supprimé",
11
+ invalidZeroSuppressibleGTIN12: "Le GTIN-12 ne peut pas être supprimé par zéro",
12
+ invalidZeroSuppressedGTIN12AsGTIN13: "GTIN-12 non valide avec zéro supprimé en tant que GTIN-13",
13
+ invalidZeroSuppressedGTIN12AsGTIN14: "GTIN-12 non valide avec zéro supprimé en tant que GTIN-14",
14
+ invalidGTIN13AtRetail: "Le GTIN-13 au niveau des articles de consommation au détail ne peut pas commencer par zéro",
15
+ invalidGTINAtRetail: "Le GTIN n'est pas pris en charge au niveau des articles de consommation au détail",
16
+ invalidGTINAtOtherThanRetail: "Le GTIN n'est pas pris en charge à d'autres niveaux que ceux des articles de consommation au détail",
17
+ indicatorDigit: "chiffre indicateur",
18
+ serialComponent: "composant série",
19
+ reference: "référence",
20
+ referenceCantBeAllNumeric: "La référence ne peut pas être entièrement numérique",
21
+ invalidCheckCharacterPair: "Paire de caractères de contrôle non valide"
22
+ },
23
+ Prefix: {
24
+ gs1CompanyPrefix: "Préfixe de l'entreprise GS1",
25
+ upcCompanyPrefix: "Préfixe de l'entreprise U.P.C.",
26
+ gs18Prefix: "Préfixe GS1-8",
27
+ gs1CompanyPrefixCantStartWith0: "Le préfixe de l'entreprise GS1 ne peut pas commencer par \"0\"",
28
+ gs1CompanyPrefixCantStartWith00000: "Le préfixe de l'entreprise GS1 ne peut pas commencer par \"00000\"",
29
+ gs1CompanyPrefixCantStartWith000000: "Le préfixe de l'entreprise GS1 ne peut pas commencer par \"000000\"",
30
+ upcCompanyPrefixCantStartWith0000: "Le préfixe de l'entreprise U.P.C. ne peut pas commencer par \"0000\"",
31
+ gs18PrefixCantStartWith0: "Le préfixe GS1-8 ne peut pas commencer par \"0\"",
32
+ identificationKeyTypeNotSupportedByGS18Prefix: "{{identificationKeyType}} non pris en charge par le préfixe GS1-8"
33
+ }
34
+ } as const;
@@ -1,8 +1,12 @@
1
- import { i18nAddResourceBundle, i18next } from "@aidc-toolkit/core";
1
+ import { i18nAddResourceBundle, i18nAssertValidResources, i18next } from "@aidc-toolkit/core";
2
2
  import { localeStrings as enLocaleStrings } from "./en/locale_strings.js";
3
+ import { localeStrings as frLocaleStrings } from "./fr/locale_strings.js";
3
4
 
4
5
  export const gs1NS = "aidct_gs1";
5
6
 
7
+ i18nAssertValidResources(enLocaleStrings, "fr", frLocaleStrings);
8
+
6
9
  i18nAddResourceBundle("en", gs1NS, enLocaleStrings);
10
+ i18nAddResourceBundle("fr", gs1NS, frLocaleStrings);
7
11
 
8
12
  export default i18next;
@@ -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.
@@ -40,48 +40,42 @@ describe("Check digit", () => {
40
40
  });
41
41
 
42
42
  describe("Price/weight check digit", () => {
43
- // eslint-disable-next-line jsdoc/require-jsdoc
44
43
  function weight2Minus(characterIndex: number): number {
45
44
  const product = characterIndex * 2;
46
45
 
47
46
  return (product - Math.trunc(product / 10)) % 10;
48
47
  }
49
48
 
50
- // eslint-disable-next-line jsdoc/require-jsdoc
51
49
  function weight3(characterIndex: number): number {
52
50
  return characterIndex * 3 % 10;
53
51
  }
54
52
 
55
- // eslint-disable-next-line jsdoc/require-jsdoc
56
53
  function weight5Plus(characterIndex: number): number {
57
54
  const product = characterIndex * 5;
58
55
 
59
56
  return (product + Math.trunc(product / 10)) % 10;
60
57
  }
61
58
 
62
- // eslint-disable-next-line jsdoc/require-jsdoc
63
59
  function weight5Minus(characterIndex: number): number {
64
60
  const product = characterIndex * 5;
65
61
 
66
62
  return (product - Math.trunc(product / 10)) % 10;
67
63
  }
68
64
 
69
- // eslint-disable-next-line jsdoc/require-jsdoc
70
65
  function testFourDigitPriceWeightCheckDigit(s: string): void {
71
- const characterIndexes = NUMERIC_CREATOR.characterIndexes(s);
66
+ // All character indexes are known to be defined.
67
+ const characterIndexes = NUMERIC_CREATOR.characterIndexes(s) as number[];
72
68
 
73
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
74
- const sum = weight2Minus(characterIndexes[0]!) + weight2Minus(characterIndexes[1]!) + weight3(characterIndexes[2]!) + weight5Minus(characterIndexes[3]!);
69
+ const sum = weight2Minus(characterIndexes[0]) + weight2Minus(characterIndexes[1]) + weight3(characterIndexes[2]) + weight5Minus(characterIndexes[3]);
75
70
 
76
71
  expect(fourDigitPriceWeightCheckDigit(s)).toBe(NUMERIC_CREATOR.character(sum * 3 % 10));
77
72
  }
78
73
 
79
- // eslint-disable-next-line jsdoc/require-jsdoc
80
74
  function testFiveDigitPriceWeightCheckDigit(s: string): void {
81
- const characterIndexes = NUMERIC_CREATOR.characterIndexes(s);
75
+ // All character indexes are known to be defined.
76
+ const characterIndexes = NUMERIC_CREATOR.characterIndexes(s) as number[];
82
77
 
83
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
84
- const sum = weight5Plus(characterIndexes[0]!) + weight2Minus(characterIndexes[1]!) + weight5Minus(characterIndexes[2]!) + weight5Plus(characterIndexes[3]!) + weight2Minus(characterIndexes[4]!);
78
+ const sum = weight5Plus(characterIndexes[0]) + weight2Minus(characterIndexes[1]) + weight5Minus(characterIndexes[2]) + weight5Plus(characterIndexes[3]) + weight2Minus(characterIndexes[4]);
85
79
 
86
80
  expect(weight5Minus(Number(fiveDigitPriceWeightCheckDigit(s)))).toBe(9 - (sum + 9) % 10);
87
81
  }
@@ -17,7 +17,8 @@ import {
17
17
  GSRN_VALIDATOR,
18
18
  GTIN12_VALIDATOR,
19
19
  GTIN13_VALIDATOR,
20
- GTIN8_VALIDATOR, GTIN_VALIDATORS,
20
+ GTIN8_VALIDATOR,
21
+ GTIN_VALIDATORS,
21
22
  GTINCreator,
22
23
  GTINLevel,
23
24
  GTINType,
@@ -42,7 +43,6 @@ import {
42
43
 
43
44
  await i18nInit(I18NEnvironment.CLI, true);
44
45
 
45
- // eslint-disable-next-line jsdoc/require-jsdoc
46
46
  function creatorFor(characterSet: CharacterSet): CharacterSetCreator {
47
47
  let creator: CharacterSetCreator;
48
48
 
@@ -63,14 +63,12 @@ function creatorFor(characterSet: CharacterSet): CharacterSetCreator {
63
63
  return creator;
64
64
  }
65
65
 
66
- // eslint-disable-next-line jsdoc/require-jsdoc
67
66
  function validateIdentificationKeyValidator(creator: IdentificationKeyValidator, identificationKeyType: IdentificationKeyType, prefixType: PrefixType, length: number): void {
68
67
  expect(creator.identificationKeyType).toBe(identificationKeyType);
69
68
  expect(creator.prefixType).toBe(prefixType);
70
69
  expect(creator.length).toBe(length);
71
70
  }
72
71
 
73
- // eslint-disable-next-line jsdoc/require-jsdoc
74
72
  function validateNumericIdentificationKeyValidator(validator: NumericIdentificationKeyValidator, isCreator: boolean, identificationKeyType: IdentificationKeyType, prefixType: PrefixType, length: number, leaderType: LeaderType): void {
75
73
  validateIdentificationKeyValidator(validator, identificationKeyType, prefixType, length);
76
74
 
@@ -83,7 +81,6 @@ function validateNumericIdentificationKeyValidator(validator: NumericIdentificat
83
81
  }
84
82
  }
85
83
 
86
- // eslint-disable-next-line jsdoc/require-jsdoc
87
84
  function validateGTINValidator(validator: GTINValidator, isCreator: boolean, gtinType: GTINType): void {
88
85
  let prefixType: PrefixType;
89
86
 
@@ -109,12 +106,10 @@ function validateGTINValidator(validator: GTINValidator, isCreator: boolean, gti
109
106
  expect(validator.gtinType).toBe(gtinType);
110
107
  }
111
108
 
112
- // eslint-disable-next-line jsdoc/require-jsdoc
113
109
  function validateNonGTINNumericIdentificationKeyValidator<T extends NonGTINNumericIdentificationKeyValidator>(validator: T, isCreator: boolean, identificationKeyType: IdentificationKeyType, length: number, leaderType: LeaderType): void {
114
110
  validateNumericIdentificationKeyValidator(validator, isCreator, identificationKeyType, PrefixType.GS1CompanyPrefix, length, leaderType);
115
111
  }
116
112
 
117
- // eslint-disable-next-line jsdoc/require-jsdoc
118
113
  function validateSerializableNumericIdentificationKeyValidator(validator: SerializableNumericIdentificationKeyValidator, isCreator: boolean, identificationKeyType: IdentificationKeyType, length: number, leaderType: LeaderType, serialLength: number, serialCharacterSet: CharacterSet): void {
119
114
  validateNonGTINNumericIdentificationKeyValidator(validator, isCreator, identificationKeyType, length, leaderType);
120
115
 
@@ -129,7 +124,6 @@ function validateSerializableNumericIdentificationKeyValidator(validator: Serial
129
124
  }
130
125
  }
131
126
 
132
- // eslint-disable-next-line jsdoc/require-jsdoc
133
127
  function validateNonNumericIdentificationKeyValidator(validator: NonNumericIdentificationKeyValidator, isCreator: boolean, identificationKeyType: IdentificationKeyType, length: number, referenceCharacterSet: CharacterSet, requiresCheckCharacterPair: boolean): void {
134
128
  validateIdentificationKeyValidator(validator, identificationKeyType, PrefixType.GS1CompanyPrefix, length);
135
129
 
@@ -169,7 +163,6 @@ describe("Validators", () => {
169
163
  });
170
164
  });
171
165
 
172
- // eslint-disable-next-line jsdoc/require-jsdoc
173
166
  function validateIdentificationKeyCreators(prefixManager: PrefixManager): void {
174
167
  let gtinType: GTINType;
175
168
 
@@ -190,9 +183,23 @@ function validateIdentificationKeyCreators(prefixManager: PrefixManager): void {
190
183
  break;
191
184
  }
192
185
 
186
+ expect(prefixManager.gtinCreator).toBe(prefixManager.gtinCreator);
187
+
193
188
  validateGTINValidator(prefixManager.gtinCreator, true, gtinType);
194
189
 
195
190
  if (prefixManager.prefixType !== PrefixType.GS18Prefix) {
191
+ expect(prefixManager.glnCreator).toBe(prefixManager.glnCreator);
192
+ expect(prefixManager.ssccCreator).toBe(prefixManager.ssccCreator);
193
+ expect(prefixManager.graiCreator).toBe(prefixManager.graiCreator);
194
+ expect(prefixManager.giaiCreator).toBe(prefixManager.giaiCreator);
195
+ expect(prefixManager.gsrnCreator).toBe(prefixManager.gsrnCreator);
196
+ expect(prefixManager.gdtiCreator).toBe(prefixManager.gdtiCreator);
197
+ expect(prefixManager.gincCreator).toBe(prefixManager.gincCreator);
198
+ expect(prefixManager.gsinCreator).toBe(prefixManager.gsinCreator);
199
+ expect(prefixManager.gcnCreator).toBe(prefixManager.gcnCreator);
200
+ expect(prefixManager.cpidCreator).toBe(prefixManager.cpidCreator);
201
+ expect(prefixManager.gmnCreator).toBe(prefixManager.gmnCreator);
202
+
196
203
  validateNonGTINNumericIdentificationKeyValidator(prefixManager.glnCreator, true, IdentificationKeyType.GLN, 13, LeaderType.None);
197
204
  validateNonGTINNumericIdentificationKeyValidator(prefixManager.ssccCreator, true, IdentificationKeyType.SSCC, 18, LeaderType.ExtensionDigit);
198
205
  validateSerializableNumericIdentificationKeyValidator(prefixManager.graiCreator, true, IdentificationKeyType.GRAI, 13, LeaderType.None, 16, CharacterSet.AI82);
@@ -222,7 +229,6 @@ function validateIdentificationKeyCreators(prefixManager: PrefixManager): void {
222
229
  describe("Prefix manager", () => {
223
230
  let prefixManager: PrefixManager;
224
231
 
225
- // eslint-disable-next-line jsdoc/require-jsdoc
226
232
  function validateGTINStartsWithPrefix(length: number): void {
227
233
  expect(prefixManager.gtinCreator.length).toBe(length);
228
234
 
@@ -237,7 +243,6 @@ describe("Prefix manager", () => {
237
243
  expect(gtin14.length).toBe(14);
238
244
  }
239
245
 
240
- // eslint-disable-next-line jsdoc/require-jsdoc
241
246
  function validateNonGTINStartsWithGS1CompanyPrefix(): void {
242
247
  const gln = prefixManager.glnCreator.create(0);
243
248
 
@@ -383,14 +388,12 @@ describe("Sparse creation", () => {
383
388
  prefixManager.resetTweakFactor();
384
389
  });
385
390
 
386
- // eslint-disable-next-line jsdoc/require-jsdoc
387
391
  function testIdentificationKeyCreatorCallback(callback?: () => void): void {
388
392
  if (callback !== undefined) {
389
393
  callback();
390
394
  }
391
395
  }
392
396
 
393
- // eslint-disable-next-line jsdoc/require-jsdoc
394
397
  function testNumericIdentificationKeyCreator(creator: NumericIdentificationKeyCreator, preTestCallback?: () => void, postTestCallback?: () => void): void {
395
398
  describe(creator.identificationKeyType === IdentificationKeyType.GTIN ? `${creator.identificationKeyType}-${creator.length}` : creator.identificationKeyType, () => {
396
399
  testIdentificationKeyCreatorCallback(preTestCallback);
@@ -405,7 +408,6 @@ function testNumericIdentificationKeyCreator(creator: NumericIdentificationKeyCr
405
408
  const referenceSubstringStart = prefixSubstringEnd;
406
409
  const referenceSubstringEnd = referenceSubstringStart + referenceLength - prefixSubstringStart;
407
410
 
408
- // eslint-disable-next-line jsdoc/require-jsdoc
409
411
  function validate(identificationKey: string, index: number, sparse: boolean): void {
410
412
  expect(() => {
411
413
  creator.validate(identificationKey);
@@ -505,11 +507,18 @@ function testNumericIdentificationKeyCreator(creator: NumericIdentificationKeyCr
505
507
  }).toThrow("Invalid character 'O' at position 3");
506
508
  });
507
509
 
510
+ test("Position offset", () => {
511
+ expect(() => {
512
+ creator.validate(creator.create(0), {
513
+ positionOffset: 4
514
+ });
515
+ }).not.toThrow(RangeError);
516
+ });
517
+
508
518
  testIdentificationKeyCreatorCallback(postTestCallback);
509
519
  });
510
520
  }
511
521
 
512
- // eslint-disable-next-line jsdoc/require-jsdoc
513
522
  function testGTINCreator(creator: GTINCreator): void {
514
523
  testNumericIdentificationKeyCreator(creator, () => {
515
524
  test("Length", () => {
@@ -538,7 +547,6 @@ function testGTINCreator(creator: GTINCreator): void {
538
547
  const referenceSubstringStart = prefixSubstringEnd;
539
548
  const referenceSubstringEnd = referenceSubstringStart + referenceLength;
540
549
 
541
- // eslint-disable-next-line jsdoc/require-jsdoc
542
550
  function validate(gtin: string, index: number, sparse: boolean): void {
543
551
  expect(() => {
544
552
  GTINCreator.validateGTIN14(gtin);
@@ -746,7 +754,6 @@ function testGTINCreator(creator: GTINCreator): void {
746
754
  });
747
755
  }
748
756
 
749
- // eslint-disable-next-line jsdoc/require-jsdoc
750
757
  function testGTINValidationAndNormalization(): void {
751
758
  describe("GTIN validation and normalization", () => {
752
759
  test("Validation", () => {
@@ -861,12 +868,10 @@ function testGTINValidationAndNormalization(): void {
861
868
  });
862
869
  }
863
870
 
864
- // eslint-disable-next-line jsdoc/require-jsdoc
865
871
  function testNonGTINNumericIdentificationKeyCreator(creator: NonGTINNumericIdentificationKeyCreator, preTestCallback?: () => void, postTestCallback?: () => void): void {
866
872
  testNumericIdentificationKeyCreator(creator, preTestCallback, postTestCallback);
867
873
  }
868
874
 
869
- // eslint-disable-next-line jsdoc/require-jsdoc
870
875
  function testSerializableNumericIdentificationKeyCreator(creator: SerializableNumericIdentificationKeyCreator): void {
871
876
  testNonGTINNumericIdentificationKeyCreator(creator, undefined, () => {
872
877
  test("Serialization", () => {
@@ -922,7 +927,6 @@ function testSerializableNumericIdentificationKeyCreator(creator: SerializableNu
922
927
 
923
928
  const TEST_REFERENCE_LENGTH = 2;
924
929
 
925
- // eslint-disable-next-line jsdoc/require-jsdoc
926
930
  function testNonNumericIdentificationKeyCreator<T extends NonNumericIdentificationKeyCreator>(creator: T): void {
927
931
  describe(creator.identificationKeyType, () => {
928
932
  const prefix = creator.prefix;
@@ -983,6 +987,14 @@ function testNonNumericIdentificationKeyCreator<T extends NonNumericIdentificati
983
987
  expect(sequenceCount).toBe(referenceCount);
984
988
  });
985
989
 
990
+ test("Position offset", () => {
991
+ expect(() => {
992
+ creator.validate(creator.create("ABC123"), {
993
+ positionOffset: 4
994
+ });
995
+ }).not.toThrow(RangeError);
996
+ });
997
+
986
998
  test("Not all numeric", () => {
987
999
  expect(() => {
988
1000
  creator.validate(creator.create("01234"), {