@aidc-toolkit/gs1 0.9.14-beta → 0.9.16-beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/idkey.js ADDED
@@ -0,0 +1,1809 @@
1
+ import { CharacterSetCreator, Exclusion, NUMERIC_CREATOR, RegExpValidator, transformIterable } from "@aidc-toolkit/utility";
2
+ import { Mixin } from "ts-mixer";
3
+ import { AI39_CREATOR, AI82_CREATOR } from "./character-set.js";
4
+ import { checkCharacterPair, checkDigit, checkDigitSum, hasValidCheckCharacterPair, hasValidCheckDigit } from "./check.js";
5
+ import { i18nextGS1 } from "./locale/i18n.js";
6
+ /**
7
+ * Identification key type.
8
+ */
9
+ export var IdentificationKeyType;
10
+ (function (IdentificationKeyType) {
11
+ /**
12
+ * Global Trade Item Number.
13
+ */
14
+ IdentificationKeyType["GTIN"] = "GTIN";
15
+ /**
16
+ * Global Location Number.
17
+ */
18
+ IdentificationKeyType["GLN"] = "GLN";
19
+ /**
20
+ * Serial Shipping Container Code.
21
+ */
22
+ IdentificationKeyType["SSCC"] = "SSCC";
23
+ /**
24
+ * Global Returnable Asset Identifier.
25
+ */
26
+ IdentificationKeyType["GRAI"] = "GRAI";
27
+ /**
28
+ * Global Individual Asset Identifier.
29
+ */
30
+ IdentificationKeyType["GIAI"] = "GIAI";
31
+ /**
32
+ * Global Service Relation Number.
33
+ */
34
+ IdentificationKeyType["GSRN"] = "GSRN";
35
+ /**
36
+ * Global Document Type Identifier.
37
+ */
38
+ IdentificationKeyType["GDTI"] = "GDTI";
39
+ /**
40
+ * Global Identification Number for Consignment.
41
+ */
42
+ IdentificationKeyType["GINC"] = "GINC";
43
+ /**
44
+ * Global Shipment Identification Number.
45
+ */
46
+ IdentificationKeyType["GSIN"] = "GSIN";
47
+ /**
48
+ * Global Coupon Number.
49
+ */
50
+ IdentificationKeyType["GCN"] = "GCN";
51
+ /**
52
+ * Component/Part Identifier.
53
+ */
54
+ IdentificationKeyType["CPID"] = "CPID";
55
+ /**
56
+ * Global Model Number.
57
+ */
58
+ IdentificationKeyType["GMN"] = "GMN";
59
+ })(IdentificationKeyType || (IdentificationKeyType = {}));
60
+ /**
61
+ * Prefix type.
62
+ */
63
+ export var PrefixType;
64
+ (function (PrefixType) {
65
+ /**
66
+ * GS1 Company Prefix.
67
+ */
68
+ PrefixType[PrefixType["GS1CompanyPrefix"] = 0] = "GS1CompanyPrefix";
69
+ /**
70
+ * U.P.C. Company Prefix.
71
+ */
72
+ PrefixType[PrefixType["UPCCompanyPrefix"] = 1] = "UPCCompanyPrefix";
73
+ /**
74
+ * GS1-8 Prefix.
75
+ */
76
+ PrefixType[PrefixType["GS18Prefix"] = 2] = "GS18Prefix";
77
+ })(PrefixType || (PrefixType = {}));
78
+ /**
79
+ * Character set supported by the reference portion of an identification key or the serial component of a numeric
80
+ * identification key.
81
+ */
82
+ export var ContentCharacterSet;
83
+ (function (ContentCharacterSet) {
84
+ /**
85
+ * Numeric.
86
+ */
87
+ ContentCharacterSet[ContentCharacterSet["Numeric"] = 0] = "Numeric";
88
+ /**
89
+ * GS1 AI encodable character set 82.
90
+ */
91
+ ContentCharacterSet[ContentCharacterSet["AI82"] = 1] = "AI82";
92
+ /**
93
+ * GS1 AI encodable character set 39.
94
+ */
95
+ ContentCharacterSet[ContentCharacterSet["AI39"] = 2] = "AI39";
96
+ })(ContentCharacterSet || (ContentCharacterSet = {}));
97
+ /**
98
+ * Abstract identification key validator. Implements common functionality for an identification key validator.
99
+ */
100
+ class AbstractIdentificationKeyValidator {
101
+ static CHARACTER_SET_CREATORS = [
102
+ NUMERIC_CREATOR, AI82_CREATOR, AI39_CREATOR
103
+ ];
104
+ /**
105
+ * Identification key type.
106
+ */
107
+ _identificationKeyType;
108
+ /**
109
+ * Prefix type.
110
+ */
111
+ _prefixType;
112
+ /**
113
+ * Length.
114
+ */
115
+ _length;
116
+ /**
117
+ * Reference character set.
118
+ */
119
+ _referenceCharacterSet;
120
+ /**
121
+ * Reference creator.
122
+ */
123
+ _referenceCreator;
124
+ /**
125
+ * Get the character set creator for a character set.
126
+ *
127
+ * @param characterSet
128
+ * Character set.
129
+ *
130
+ * @returns
131
+ * Character set creator.
132
+ */
133
+ static creatorFor(characterSet) {
134
+ return AbstractIdentificationKeyValidator.CHARACTER_SET_CREATORS[characterSet];
135
+ }
136
+ /**
137
+ * Constructor.
138
+ *
139
+ * @param identificationKeyType
140
+ * Identification key type.
141
+ *
142
+ * @param prefixType
143
+ * Prefix type.
144
+ *
145
+ * @param length
146
+ * Length.
147
+ *
148
+ * @param referenceCharacterSet
149
+ * Reference character set.
150
+ */
151
+ constructor(identificationKeyType, prefixType, length, referenceCharacterSet) {
152
+ this._identificationKeyType = identificationKeyType;
153
+ this._prefixType = prefixType;
154
+ this._length = length;
155
+ this._referenceCharacterSet = referenceCharacterSet;
156
+ this._referenceCreator = AbstractIdentificationKeyValidator.creatorFor(referenceCharacterSet);
157
+ }
158
+ /**
159
+ * @inheritDoc
160
+ */
161
+ get identificationKeyType() {
162
+ return this._identificationKeyType;
163
+ }
164
+ /**
165
+ * @inheritDoc
166
+ */
167
+ get prefixType() {
168
+ return this._prefixType;
169
+ }
170
+ /**
171
+ * @inheritDoc
172
+ */
173
+ get length() {
174
+ return this._length;
175
+ }
176
+ /**
177
+ * @inheritDoc
178
+ */
179
+ get referenceCharacterSet() {
180
+ return this._referenceCharacterSet;
181
+ }
182
+ /**
183
+ * @inheritDoc
184
+ */
185
+ get referenceCreator() {
186
+ return this._referenceCreator;
187
+ }
188
+ /**
189
+ * Pad an identification key on the left with zero-value character for validation purposes. This is done to align an
190
+ * identification key with a position offset for any error message that may be thrown by the reference validator.
191
+ *
192
+ * @param identificationKey
193
+ * Identification key.
194
+ *
195
+ * @param validation
196
+ * Identification key validation parameters.
197
+ *
198
+ * @returns
199
+ * Padded identification key.
200
+ */
201
+ padIdentificationKey(identificationKey, validation) {
202
+ // Identification key is returned as is if position offset is undefined.
203
+ return validation?.positionOffset === undefined ? identificationKey : this.referenceCreator.character(0).repeat(validation.positionOffset).concat(identificationKey);
204
+ }
205
+ /**
206
+ * Validate the prefix within an identification key.
207
+ *
208
+ * @param partialIdentificationKey
209
+ * Partial identification key.
210
+ *
211
+ * @param positionOffset
212
+ * Position offset within a larger string.
213
+ */
214
+ validatePrefix(partialIdentificationKey, positionOffset) {
215
+ // Delegate to prefix manager with support for U.P.C. Company Prefix but not GS1-8 Prefix.
216
+ PrefixManager.validatePrefix(this.prefixType, true, false, partialIdentificationKey, true, this.referenceCharacterSet === ContentCharacterSet.Numeric, positionOffset);
217
+ }
218
+ }
219
+ /**
220
+ * Leader type.
221
+ */
222
+ export var LeaderType;
223
+ (function (LeaderType) {
224
+ /**
225
+ * No leader.
226
+ */
227
+ LeaderType[LeaderType["None"] = 0] = "None";
228
+ /**
229
+ * Indicator digit (GTIN only).
230
+ */
231
+ LeaderType[LeaderType["IndicatorDigit"] = 1] = "IndicatorDigit";
232
+ /**
233
+ * Extension digit (SSCC only).
234
+ */
235
+ LeaderType[LeaderType["ExtensionDigit"] = 2] = "ExtensionDigit";
236
+ })(LeaderType || (LeaderType = {}));
237
+ /**
238
+ * Abstract numeric identification key validator. Implements common functionality for a numeric identification key
239
+ * validator.
240
+ */
241
+ class AbstractNumericIdentificationKeyValidator extends AbstractIdentificationKeyValidator {
242
+ /**
243
+ * Leader type.
244
+ */
245
+ _leaderType;
246
+ /**
247
+ * Prefix position, determined by the leader type.
248
+ */
249
+ _prefixPosition;
250
+ /**
251
+ * Constructor.
252
+ *
253
+ * @param identificationKeyType
254
+ * Identification key type.
255
+ *
256
+ * @param prefixType
257
+ * Prefix type.
258
+ *
259
+ * @param length
260
+ * Length.
261
+ *
262
+ * @param leaderType
263
+ * Leader type.
264
+ */
265
+ constructor(identificationKeyType, prefixType, length, leaderType) {
266
+ super(identificationKeyType, prefixType, length, ContentCharacterSet.Numeric);
267
+ this._leaderType = leaderType;
268
+ this._prefixPosition = Number(this.leaderType === LeaderType.ExtensionDigit);
269
+ }
270
+ /**
271
+ * @inheritDoc
272
+ */
273
+ get leaderType() {
274
+ return this._leaderType;
275
+ }
276
+ /**
277
+ * @inheritDoc
278
+ */
279
+ validate(identificationKey, validation) {
280
+ // Validate the prefix, with care taken for its position within the identification key.
281
+ if (this._prefixPosition === 0) {
282
+ super.validatePrefix(identificationKey, validation?.positionOffset);
283
+ }
284
+ else {
285
+ super.validatePrefix(identificationKey.substring(this._prefixPosition), validation?.positionOffset === undefined ? this._prefixPosition : validation.positionOffset + this._prefixPosition);
286
+ }
287
+ // Validate the length.
288
+ if (identificationKey.length !== this.length) {
289
+ throw new RangeError(i18nextGS1.t("IdentificationKey.identificationKeyTypeLength", {
290
+ identificationKeyType: this.identificationKeyType,
291
+ length: this.length
292
+ }));
293
+ }
294
+ // Validating the check digit will also validate the characters.
295
+ if (!hasValidCheckDigit(this.padIdentificationKey(identificationKey, validation))) {
296
+ throw new RangeError(i18nextGS1.t("IdentificationKey.invalidCheckDigit"));
297
+ }
298
+ }
299
+ }
300
+ /**
301
+ * GTIN type. The numeric values of this enumeration are equal to the lengths of the GTIN types.
302
+ */
303
+ export var GTINType;
304
+ (function (GTINType) {
305
+ /**
306
+ * GTIN-13.
307
+ */
308
+ GTINType[GTINType["GTIN13"] = 13] = "GTIN13";
309
+ /**
310
+ * GTIN-12.
311
+ */
312
+ GTINType[GTINType["GTIN12"] = 12] = "GTIN12";
313
+ /**
314
+ * GTIN-8.
315
+ */
316
+ GTINType[GTINType["GTIN8"] = 8] = "GTIN8";
317
+ /**
318
+ * GTIN-14.
319
+ */
320
+ GTINType[GTINType["GTIN14"] = 14] = "GTIN14";
321
+ })(GTINType || (GTINType = {}));
322
+ /**
323
+ * Level at which GTIN is to be validated.
324
+ */
325
+ export var GTINLevel;
326
+ (function (GTINLevel) {
327
+ /**
328
+ * Any level (level is ignored).
329
+ */
330
+ GTINLevel[GTINLevel["Any"] = 0] = "Any";
331
+ /**
332
+ * Retail consumer trade item level, supporting GTIN-13, GTIN-12 (optionally zero-suppressed), and GTIN-8.
333
+ */
334
+ GTINLevel[GTINLevel["RetailConsumer"] = 1] = "RetailConsumer";
335
+ /**
336
+ * Other than retail consumer trade item level, supporting GTIN-13, GTIN-12 (not zero-suppressed), and GTIN-14.
337
+ */
338
+ GTINLevel[GTINLevel["OtherThanRetailConsumer"] = 2] = "OtherThanRetailConsumer";
339
+ })(GTINLevel || (GTINLevel = {}));
340
+ /**
341
+ * GTIN validator.
342
+ */
343
+ export class GTINValidator extends AbstractNumericIdentificationKeyValidator {
344
+ /**
345
+ * Validation parameters for optional indicator digit.
346
+ */
347
+ static OPTIONAL_INDICATOR_DIGIT_VALIDATION = {
348
+ minimumLength: 0,
349
+ maximumLength: 1,
350
+ component: () => i18nextGS1.t("IdentificationKey.indicatorDigit")
351
+ };
352
+ /**
353
+ * Validation parameters for zero-suppressed GTIN-12.
354
+ */
355
+ static ZERO_SUPPRESSED_GTIN12_VALIDATION = {
356
+ minimumLength: 8,
357
+ maximumLength: 8
358
+ };
359
+ /**
360
+ * Constructor.
361
+ *
362
+ * @param gtinType
363
+ * GTIN type.
364
+ */
365
+ constructor(gtinType) {
366
+ let prefixType;
367
+ // Determine the prefix type based on the GTIN type.
368
+ switch (gtinType) {
369
+ case GTINType.GTIN13:
370
+ prefixType = PrefixType.GS1CompanyPrefix;
371
+ break;
372
+ case GTINType.GTIN12:
373
+ prefixType = PrefixType.UPCCompanyPrefix;
374
+ break;
375
+ case GTINType.GTIN8:
376
+ prefixType = PrefixType.GS18Prefix;
377
+ break;
378
+ default:
379
+ // Should never get here.
380
+ throw new Error("Not supported");
381
+ }
382
+ super(IdentificationKeyType.GTIN, prefixType, gtinType, LeaderType.IndicatorDigit);
383
+ }
384
+ /**
385
+ * @inheritDoc
386
+ */
387
+ get gtinType() {
388
+ // Length maps to GTIN type enumeration.
389
+ return this.length;
390
+ }
391
+ /**
392
+ * @inheritDoc
393
+ */
394
+ validatePrefix(partialIdentificationKey, positionOffset) {
395
+ // Delegate to prefix manager requiring exact match for prefix type.
396
+ PrefixManager.validatePrefix(this.prefixType, false, false, partialIdentificationKey, true, true, positionOffset);
397
+ }
398
+ /**
399
+ * Zero suppress a GTIN-12.
400
+ *
401
+ * @param gtin12
402
+ * GTIN-12.
403
+ *
404
+ * @returns
405
+ * Zero-suppressed GTIN-12.
406
+ */
407
+ static zeroSuppress(gtin12) {
408
+ GTIN12_VALIDATOR.validate(gtin12);
409
+ // Convert to individual digits.
410
+ const d = Array.from(gtin12);
411
+ let zeroSuppressedGTIN12;
412
+ // All rules require that digits in positions 1, 5, and 6 be zero.
413
+ if (d[0] === "0" && d[6] === "0" && d[7] === "0") {
414
+ if (d[10] >= "5" && d[8] === "0" && d[9] === "0" && d[5] !== "0") {
415
+ zeroSuppressedGTIN12 = `0${d[1]}${d[2]}${d[3]}${d[4]}${d[5]}${d[10]}${d[11]}`;
416
+ }
417
+ else if (d[5] === "0" && d[8] === "0" && d[9] === "0" && d[4] !== "0") {
418
+ zeroSuppressedGTIN12 = `0${d[1]}${d[2]}${d[3]}${d[4]}${d[10]}4${d[11]}`;
419
+ }
420
+ else if (d[3] <= "2" && d[4] === "0" && d[5] === "0") {
421
+ zeroSuppressedGTIN12 = `0${d[1]}${d[2]}${d[8]}${d[9]}${d[10]}${d[3]}${d[11]}`;
422
+ }
423
+ else if (d[3] >= "3" && d[4] === "0" && d[5] === "0" && d[8] === "0") {
424
+ zeroSuppressedGTIN12 = `0${d[1]}${d[2]}${d[3]}${d[9]}${d[10]}3${d[11]}`;
425
+ }
426
+ }
427
+ if (zeroSuppressedGTIN12 === undefined) {
428
+ throw new RangeError(i18nextGS1.t("IdentificationKey.invalidZeroSuppressibleGTIN12"));
429
+ }
430
+ return zeroSuppressedGTIN12;
431
+ }
432
+ /**
433
+ * Zero expand a zero-suppressed GTIN-12.
434
+ *
435
+ * @param zeroSuppressedGTIN12
436
+ * Zero-suppressed GTIN-12.
437
+ *
438
+ * @returns
439
+ * GTIN-12.
440
+ */
441
+ static zeroExpand(zeroSuppressedGTIN12) {
442
+ NUMERIC_CREATOR.validate(zeroSuppressedGTIN12, GTINValidator.ZERO_SUPPRESSED_GTIN12_VALIDATION);
443
+ // Convert to individual digits.
444
+ const d = Array.from(zeroSuppressedGTIN12);
445
+ let gtin12;
446
+ // Zero-suppressed GTIN-12 always starts with 0.
447
+ if (d[0] === "0") {
448
+ if (d[6] >= "5" && d[5] !== "0") {
449
+ gtin12 = `0${d[1]}${d[2]}${d[3]}${d[4]}${d[5]}0000${d[6]}${d[7]}`;
450
+ }
451
+ else if (d[6] === "4" && d[4] !== "0") {
452
+ gtin12 = `0${d[1]}${d[2]}${d[3]}${d[4]}00000${d[5]}${d[7]}`;
453
+ }
454
+ else if (d[6] <= "2") {
455
+ gtin12 = `0${d[1]}${d[2]}${d[6]}0000${d[3]}${d[4]}${d[5]}${d[7]}`;
456
+ }
457
+ else if (d[6] === "3" && d[3] >= "3") {
458
+ gtin12 = `0${d[1]}${d[2]}${d[3]}00000${d[4]}${d[5]}${d[7]}`;
459
+ }
460
+ }
461
+ if (gtin12 === undefined) {
462
+ throw new RangeError(i18nextGS1.t("IdentificationKey.invalidZeroSuppressedGTIN12"));
463
+ }
464
+ // Make sure that resulting GTIN-12 is valid.
465
+ GTIN12_VALIDATOR.validate(gtin12);
466
+ return gtin12;
467
+ }
468
+ /**
469
+ * Convert a GTIN of any length to a GTIN-14 with an optional indicator digit.
470
+ *
471
+ * @param indicatorDigit
472
+ * Indicator digit. If blank, assumes "0" if the GTIN is not already a GTIN-14.
473
+ *
474
+ * @param gtin
475
+ * GTIN.
476
+ *
477
+ * @returns
478
+ * GTIN-14.
479
+ */
480
+ static convertToGTIN14(indicatorDigit, gtin) {
481
+ GTINCreator.validateAny(gtin);
482
+ NUMERIC_CREATOR.validate(indicatorDigit, GTINValidator.OPTIONAL_INDICATOR_DIGIT_VALIDATION);
483
+ const gtinLength = gtin.length;
484
+ // Check digit doesn't change by prepending zeros.
485
+ let gtin14 = "0".repeat(GTINType.GTIN14 - gtinLength) + gtin;
486
+ // If indicator digit provided and is different, recalculate the check digit.
487
+ if (indicatorDigit.length !== 0 && indicatorDigit !== gtin14.charAt(0)) {
488
+ const partialGTIN14 = indicatorDigit + gtin14.substring(1, GTINType.GTIN14 - 1);
489
+ gtin14 = partialGTIN14 + checkDigit(partialGTIN14);
490
+ }
491
+ return gtin14;
492
+ }
493
+ /**
494
+ * Normalize a GTIN of any length.
495
+ * - A GTIN-14 that starts with six zeros or a GTIN-13 that starts with five zeros is normalized to GTIN-8.
496
+ * - A GTIN-14 that starts with two zeros or a GTIN-13 that starts with one zero is normalized to GTIN-12.
497
+ * - A GTIN-14 that starts with one zero is normalized to GTIN-13.
498
+ * - Otherwise, the GTIN is unchanged.
499
+ *
500
+ * @param gtin
501
+ * GTIN.
502
+ *
503
+ * @returns
504
+ * Normalized GTIN.
505
+ */
506
+ static normalize(gtin) {
507
+ const gtinLength = gtin.length;
508
+ let normalizedGTIN;
509
+ switch (gtinLength) {
510
+ case GTINType.GTIN13:
511
+ if (!gtin.startsWith("0")) {
512
+ // GTIN is GTIN-13.
513
+ normalizedGTIN = gtin;
514
+ }
515
+ else if (!gtin.startsWith("00000")) {
516
+ // GTIN is GTIN-12.
517
+ normalizedGTIN = gtin.substring(1);
518
+ }
519
+ else if (!gtin.startsWith("000000")) {
520
+ // GTIN is GTIN-8.
521
+ normalizedGTIN = gtin.substring(5);
522
+ }
523
+ else {
524
+ throw new RangeError(i18nextGS1.t("IdentificationKey.invalidZeroSuppressedGTIN12AsGTIN13"));
525
+ }
526
+ break;
527
+ case GTINType.GTIN12:
528
+ // GTIN is GTIN-12.
529
+ normalizedGTIN = gtin;
530
+ break;
531
+ case GTINType.GTIN8:
532
+ if (!gtin.startsWith("0")) {
533
+ // GTIN is GTIN-8.
534
+ normalizedGTIN = gtin;
535
+ }
536
+ else {
537
+ // GTIN is zero-suppressed GTIN-12.
538
+ normalizedGTIN = GTINValidator.zeroExpand(gtin);
539
+ }
540
+ break;
541
+ case GTINType.GTIN14:
542
+ if (!gtin.startsWith("0")) {
543
+ // GTIN is GTIN-14.
544
+ normalizedGTIN = gtin;
545
+ }
546
+ else if (!gtin.startsWith("00")) {
547
+ // GTIN is GTIN-13.
548
+ normalizedGTIN = gtin.substring(1);
549
+ }
550
+ else if (!gtin.startsWith("000000")) {
551
+ // GTIN is GTIN-12.
552
+ normalizedGTIN = gtin.substring(2);
553
+ }
554
+ else if (!gtin.startsWith("0000000")) {
555
+ // GTIN is GTIN-8.
556
+ normalizedGTIN = gtin.substring(6);
557
+ }
558
+ else {
559
+ throw new RangeError(i18nextGS1.t("IdentificationKey.invalidZeroSuppressedGTIN12AsGTIN14"));
560
+ }
561
+ break;
562
+ default:
563
+ throw new RangeError(i18nextGS1.t("IdentificationKey.invalidGTINLength"));
564
+ }
565
+ // Validation applies to the normalized GTIN.
566
+ GTINCreator.validateAny(normalizedGTIN);
567
+ return normalizedGTIN;
568
+ }
569
+ /**
570
+ * Validate any GTIN, optionally against a level.
571
+ *
572
+ * @param gtin
573
+ * GTIN.
574
+ *
575
+ * @param gtinLevel
576
+ * Level at which GTIN is to be validated.
577
+ */
578
+ static validateAny(gtin, gtinLevel = GTINLevel.Any) {
579
+ // Assume length-validated GTIN is the GTIN (true for all except zero-suppressed GTIN-12).
580
+ let lengthValidatedGTIN = gtin;
581
+ let gtinLevelRestriction;
582
+ switch (gtin.length) {
583
+ case GTINType.GTIN13:
584
+ if (gtin.startsWith("0")) {
585
+ throw new RangeError(i18nextGS1.t("IdentificationKey.invalidGTIN13AtRetail"));
586
+ }
587
+ // Validate prefix requiring exact match for prefix type.
588
+ PrefixManager.validatePrefix(PrefixType.GS1CompanyPrefix, false, false, gtin, true, true);
589
+ gtinLevelRestriction = GTINLevel.Any;
590
+ break;
591
+ case GTINType.GTIN12:
592
+ // Validate prefix requiring exact match for prefix type.
593
+ PrefixManager.validatePrefix(PrefixType.UPCCompanyPrefix, false, false, gtin, true, true);
594
+ gtinLevelRestriction = GTINLevel.Any;
595
+ break;
596
+ case GTINType.GTIN8:
597
+ // Zero-suppressed GTIN-12 always starts with 0.
598
+ if (!gtin.startsWith("0")) {
599
+ // Validate prefix requiring exact match for prefix type.
600
+ PrefixManager.validatePrefix(PrefixType.GS18Prefix, false, false, gtin, true, true);
601
+ }
602
+ else {
603
+ lengthValidatedGTIN = GTINValidator.zeroExpand(gtin);
604
+ }
605
+ gtinLevelRestriction = GTINLevel.RetailConsumer;
606
+ break;
607
+ case GTINType.GTIN14:
608
+ // Validate prefix supporting any prefix type.
609
+ PrefixManager.validatePrefix(PrefixType.GS1CompanyPrefix, true, true, gtin.substring(1), true, true);
610
+ gtinLevelRestriction = GTINLevel.OtherThanRetailConsumer;
611
+ break;
612
+ default:
613
+ throw new RangeError(i18nextGS1.t("IdentificationKey.invalidGTINLength"));
614
+ }
615
+ // Validating the check digit will also validate the characters.
616
+ if (!hasValidCheckDigit(lengthValidatedGTIN)) {
617
+ throw new RangeError(i18nextGS1.t("IdentificationKey.invalidCheckDigit"));
618
+ }
619
+ // Validate against level if required.
620
+ if (gtinLevel !== GTINLevel.Any && gtinLevelRestriction !== GTINLevel.Any && gtinLevelRestriction !== gtinLevel) {
621
+ throw new RangeError(i18nextGS1.t(gtinLevel === GTINLevel.RetailConsumer ? "IdentificationKey.invalidGTINAtRetail" : "IdentificationKey.invalidGTINAtOtherThanRetail"));
622
+ }
623
+ }
624
+ /**
625
+ * Validate a GTIN-14.
626
+ *
627
+ * @param gtin14
628
+ * GTIN-14.
629
+ */
630
+ static validateGTIN14(gtin14) {
631
+ if (gtin14.length !== GTINType.GTIN14) {
632
+ throw new RangeError(i18nextGS1.t("IdentificationKey.invalidGTIN14Length"));
633
+ }
634
+ GTINCreator.validateAny(gtin14);
635
+ }
636
+ }
637
+ /**
638
+ * Non-GTIN numeric identification key validator.
639
+ */
640
+ export class NonGTINNumericIdentificationKeyValidator extends AbstractNumericIdentificationKeyValidator {
641
+ /**
642
+ * Constructor.
643
+ *
644
+ * @param identificationKeyType
645
+ * Identification key type.
646
+ *
647
+ * @param length
648
+ * Length.
649
+ *
650
+ * @param leaderType
651
+ * Leader type.
652
+ */
653
+ constructor(identificationKeyType, length, leaderType = LeaderType.None) {
654
+ super(identificationKeyType, PrefixType.GS1CompanyPrefix, length, leaderType);
655
+ }
656
+ }
657
+ /**
658
+ * Serializable numeric identification key validator. Validates both serialized and non-serialized forms of
659
+ * numeric identification keys that support serialization.
660
+ */
661
+ export class SerializableNumericIdentificationKeyValidator extends NonGTINNumericIdentificationKeyValidator {
662
+ /**
663
+ * Serial component length.
664
+ */
665
+ _serialComponentLength;
666
+ /**
667
+ * Serial component character set.
668
+ */
669
+ _serialComponentCharacterSet;
670
+ /**
671
+ * Serial component validation parameters.
672
+ */
673
+ _serialComponentValidation;
674
+ /**
675
+ * Serial component creator.
676
+ */
677
+ _serialComponentCreator;
678
+ /**
679
+ * Constructor.
680
+ *
681
+ * @param identificationKeyType
682
+ * Identification key type.
683
+ *
684
+ * @param length
685
+ * Length.
686
+ *
687
+ * @param serialComponentLength
688
+ * Serial component length.
689
+ *
690
+ * @param serialComponentCharacterSet
691
+ * Serial component character set.
692
+ */
693
+ constructor(identificationKeyType, length, serialComponentLength, serialComponentCharacterSet) {
694
+ super(identificationKeyType, length, LeaderType.None);
695
+ this._serialComponentLength = serialComponentLength;
696
+ this._serialComponentCharacterSet = serialComponentCharacterSet;
697
+ this._serialComponentValidation = {
698
+ minimumLength: 1,
699
+ maximumLength: serialComponentLength,
700
+ component: () => i18nextGS1.t("IdentificationKey.serialComponent")
701
+ };
702
+ this._serialComponentCreator = SerializableNumericIdentificationKeyValidator.creatorFor(serialComponentCharacterSet);
703
+ }
704
+ /**
705
+ * Get the serial component length.
706
+ */
707
+ get serialComponentLength() {
708
+ return this._serialComponentLength;
709
+ }
710
+ /**
711
+ * Get the serial component character set.
712
+ */
713
+ get serialComponentCharacterSet() {
714
+ return this._serialComponentCharacterSet;
715
+ }
716
+ /**
717
+ * Get the serial component validation parameters.
718
+ */
719
+ get serialComponentValidation() {
720
+ return this._serialComponentValidation;
721
+ }
722
+ /**
723
+ * Get the serial component creator.
724
+ */
725
+ get serialComponentCreator() {
726
+ return this._serialComponentCreator;
727
+ }
728
+ /**
729
+ * @inheritDoc
730
+ */
731
+ validate(identificationKey, validation) {
732
+ super.validate(identificationKey.substring(0, this.length), validation);
733
+ if (identificationKey.length > this.length) {
734
+ this.serialComponentCreator.validate(identificationKey.substring(this.length), this._serialComponentValidation);
735
+ }
736
+ }
737
+ }
738
+ /**
739
+ * Non-numeric identification key validator.
740
+ */
741
+ export class NonNumericIdentificationKeyValidator extends AbstractIdentificationKeyValidator {
742
+ /**
743
+ * Validator to ensure that an identification key (minus check character pair) is not all numeric.
744
+ */
745
+ static NOT_ALL_NUMERIC_VALIDATOR = new class extends RegExpValidator {
746
+ /**
747
+ * @inheritDoc
748
+ */
749
+ createErrorMessage(_s) {
750
+ return i18nextGS1.t("IdentificationKey.referenceCantBeAllNumeric");
751
+ }
752
+ }(/\D/);
753
+ /**
754
+ * True if the identification key requires a check character pair.
755
+ */
756
+ _requiresCheckCharacterPair;
757
+ /**
758
+ * Constructor.
759
+ *
760
+ * @param identificationKeyType
761
+ * Identification key type.
762
+ *
763
+ * @param length
764
+ * Length.
765
+ *
766
+ * @param referenceCharacterSet
767
+ * Reference character set.
768
+ *
769
+ * @param requiresCheckCharacterPair
770
+ * True if the identification key requires a check character pair.
771
+ */
772
+ constructor(identificationKeyType, length, referenceCharacterSet, requiresCheckCharacterPair = false) {
773
+ super(identificationKeyType, PrefixType.GS1CompanyPrefix, length, referenceCharacterSet);
774
+ this._requiresCheckCharacterPair = requiresCheckCharacterPair;
775
+ }
776
+ /**
777
+ * Determine if the identification key requires a check character pair.
778
+ */
779
+ get requiresCheckCharacterPair() {
780
+ return this._requiresCheckCharacterPair;
781
+ }
782
+ /**
783
+ * Validate a non-numeric identification key and throw an error if validation fails.
784
+ *
785
+ * @param identificationKey
786
+ * Identification key.
787
+ *
788
+ * @param validation
789
+ * Validation parameters.
790
+ */
791
+ validate(identificationKey, validation) {
792
+ const partialIdentificationKey = this.requiresCheckCharacterPair ? identificationKey.substring(0, identificationKey.length - 2) : identificationKey;
793
+ super.validatePrefix(partialIdentificationKey, validation?.positionOffset);
794
+ if (!this.requiresCheckCharacterPair) {
795
+ this.referenceCreator.validate(identificationKey, {
796
+ maximumLength: this.length,
797
+ positionOffset: validation?.positionOffset
798
+ });
799
+ // Validating the check character pair will also validate the characters.
800
+ }
801
+ else if (!hasValidCheckCharacterPair(this.padIdentificationKey(identificationKey, validation))) {
802
+ throw new RangeError(i18nextGS1.t("IdentificationKey.invalidCheckCharacterPair"));
803
+ }
804
+ // Check for all-numeric identification key (minus check character pair) if excluded.
805
+ if (validation?.exclusion === Exclusion.AllNumeric) {
806
+ NonNumericIdentificationKeyValidator.NOT_ALL_NUMERIC_VALIDATOR.validate(partialIdentificationKey);
807
+ }
808
+ }
809
+ }
810
+ /**
811
+ * GTIN-13 validator.
812
+ */
813
+ export const GTIN13_VALIDATOR = new GTINValidator(GTINType.GTIN13);
814
+ /**
815
+ * GTIN-12 validator.
816
+ */
817
+ export const GTIN12_VALIDATOR = new GTINValidator(GTINType.GTIN12);
818
+ /**
819
+ * GTIN-8 validator.
820
+ */
821
+ export const GTIN8_VALIDATOR = new GTINValidator(GTINType.GTIN8);
822
+ /**
823
+ * GTIN validators indexed by prefix type.
824
+ */
825
+ export const GTIN_VALIDATORS = [
826
+ GTIN13_VALIDATOR, GTIN12_VALIDATOR, GTIN8_VALIDATOR
827
+ ];
828
+ /**
829
+ * GLN validator.
830
+ */
831
+ export const GLN_VALIDATOR = new NonGTINNumericIdentificationKeyValidator(IdentificationKeyType.GLN, 13);
832
+ /**
833
+ * SSCC validator.
834
+ */
835
+ export const SSCC_VALIDATOR = new NonGTINNumericIdentificationKeyValidator(IdentificationKeyType.SSCC, 18, LeaderType.ExtensionDigit);
836
+ /**
837
+ * GRAI validator.
838
+ */
839
+ export const GRAI_VALIDATOR = new SerializableNumericIdentificationKeyValidator(IdentificationKeyType.GRAI, 13, 16, ContentCharacterSet.AI82);
840
+ /**
841
+ * GIAI validator.
842
+ */
843
+ export const GIAI_VALIDATOR = new NonNumericIdentificationKeyValidator(IdentificationKeyType.GIAI, 30, ContentCharacterSet.AI82);
844
+ /**
845
+ * GSRN validator.
846
+ */
847
+ export const GSRN_VALIDATOR = new NonGTINNumericIdentificationKeyValidator(IdentificationKeyType.GSRN, 18);
848
+ /**
849
+ * GDTI validator.
850
+ */
851
+ export const GDTI_VALIDATOR = new SerializableNumericIdentificationKeyValidator(IdentificationKeyType.GDTI, 13, 17, ContentCharacterSet.AI82);
852
+ /**
853
+ * GINC validator.
854
+ */
855
+ export const GINC_VALIDATOR = new NonNumericIdentificationKeyValidator(IdentificationKeyType.GINC, 30, ContentCharacterSet.AI82);
856
+ /**
857
+ * GSIN validator.
858
+ */
859
+ export const GSIN_VALIDATOR = new NonGTINNumericIdentificationKeyValidator(IdentificationKeyType.GSIN, 17);
860
+ /**
861
+ * GCN validator.
862
+ */
863
+ export const GCN_VALIDATOR = new SerializableNumericIdentificationKeyValidator(IdentificationKeyType.GCN, 13, 12, ContentCharacterSet.Numeric);
864
+ /**
865
+ * CPID validator.
866
+ */
867
+ export const CPID_VALIDATOR = new NonNumericIdentificationKeyValidator(IdentificationKeyType.CPID, 30, ContentCharacterSet.AI39);
868
+ /**
869
+ * GMN validator.
870
+ */
871
+ export const GMN_VALIDATOR = new NonNumericIdentificationKeyValidator(IdentificationKeyType.GMN, 25, ContentCharacterSet.AI82, true);
872
+ /**
873
+ * Abstract identification key creator. Implements common functionality for an identification key creator, bound to a
874
+ * {@link PrefixManager}.
875
+ */
876
+ class AbstractIdentificationKeyCreator {
877
+ /**
878
+ * Prefix manager.
879
+ */
880
+ _prefixManager;
881
+ /**
882
+ * Reference length.
883
+ */
884
+ _referenceLength;
885
+ /**
886
+ * Initialize the prefix manager. This method is in lieu of a constructor due to the mixin architecture.
887
+ *
888
+ * @param prefixManager
889
+ * Prefix manager.
890
+ *
891
+ * @param prefix
892
+ * Prefix within prefix manager to use to calculate reference length.
893
+ *
894
+ * @param checkAllowance
895
+ * Number of characters to allow for check digit or check character pair.
896
+ */
897
+ init(prefixManager, prefix, checkAllowance) {
898
+ this._prefixManager = prefixManager;
899
+ // Reference length allows for prefix and optionally check digit or check character pair.
900
+ this._referenceLength = this.length - prefix.length - checkAllowance;
901
+ }
902
+ /**
903
+ * @inheritDoc
904
+ */
905
+ get prefixManager() {
906
+ return this._prefixManager;
907
+ }
908
+ /**
909
+ * @inheritDoc
910
+ */
911
+ get prefix() {
912
+ return this.prefixManager.gs1CompanyPrefix;
913
+ }
914
+ /**
915
+ * @inheritDoc
916
+ */
917
+ get referenceLength() {
918
+ return this._referenceLength;
919
+ }
920
+ }
921
+ /**
922
+ * Abstract numeric identification key creator. Implements common functionality for a numeric identification key creator.
923
+ */
924
+ class AbstractNumericIdentificationKeyCreator extends AbstractIdentificationKeyCreator {
925
+ /**
926
+ * Capacity.
927
+ */
928
+ _capacity;
929
+ /**
930
+ * Tweak for sparse creation.
931
+ */
932
+ _tweak = 0n;
933
+ /**
934
+ * Initialize the prefix manager. This method is in lieu of a constructor due to the mixin architecture.
935
+ *
936
+ * @param prefixManager
937
+ * Prefix manager.
938
+ *
939
+ * @param prefix
940
+ * Prefix within prefix manager to use to calculate reference length.
941
+ */
942
+ init(prefixManager, prefix) {
943
+ super.init(prefixManager, prefix, 1);
944
+ // Capacity is always in number range.
945
+ this._capacity = Number(CharacterSetCreator.powerOf10(this.referenceLength));
946
+ }
947
+ /**
948
+ * @inheritDoc
949
+ */
950
+ get capacity() {
951
+ return this._capacity;
952
+ }
953
+ /**
954
+ * Get the tweak for sparse creation.
955
+ */
956
+ get tweak() {
957
+ return this._tweak;
958
+ }
959
+ /**
960
+ * Set the tweak for sparse creation.
961
+ */
962
+ set tweak(value) {
963
+ this._tweak = value;
964
+ }
965
+ /**
966
+ * Build an identification key from a reference by merging it with the prefix and adding the check digit.
967
+ *
968
+ * @param reference
969
+ * Identification key reference.
970
+ *
971
+ * @returns
972
+ * Identification key.
973
+ */
974
+ buildIdentificationKey(reference) {
975
+ const partialIdentificationKey = this.leaderType === LeaderType.ExtensionDigit ? reference.substring(0, 1) + this.prefix + reference.substring(1) : this.prefix + reference;
976
+ return partialIdentificationKey + checkDigit(partialIdentificationKey);
977
+ }
978
+ /**
979
+ * @inheritDoc
980
+ */
981
+ create(valueOrValues, sparse = false) {
982
+ return NUMERIC_CREATOR.create(this.referenceLength, valueOrValues, Exclusion.None, sparse ? this.tweak : undefined, reference => this.buildIdentificationKey(reference));
983
+ }
984
+ /**
985
+ * Create all identification keys from a partial identification key. Call is recursive until remaining reference
986
+ * length is 0.
987
+ *
988
+ * @param partialIdentificationKey
989
+ * Partial identification key. Initial value is `this.prefix`.
990
+ *
991
+ * @param remainingReferenceLength
992
+ * Remaining reference length. Initial value is `this.referenceLength`.
993
+ *
994
+ * @param extensionWeight
995
+ * If this value is not zero, the identification key has an extension digit, this call is setting it, and this value
996
+ * is applied to the calculation of the check digit.
997
+ *
998
+ * @param weight
999
+ * If the extension weight is zero, this value is applied to the calculation of the check digit.
1000
+ *
1001
+ * @param partialCheckDigitSum
1002
+ * Partial check digit sum for the partial identification key.
1003
+ *
1004
+ * @yields
1005
+ * Identification key.
1006
+ */
1007
+ static *createAllPartial(partialIdentificationKey, remainingReferenceLength, extensionWeight, weight, partialCheckDigitSum) {
1008
+ if (remainingReferenceLength === 0) {
1009
+ // Finalize check digit calculation and append.
1010
+ yield partialIdentificationKey + NUMERIC_CREATOR.character(9 - (partialCheckDigitSum + 9) % 10);
1011
+ }
1012
+ else {
1013
+ const nextRemainingReferenceLength = remainingReferenceLength - 1;
1014
+ let nextPartialCheckDigitSum = partialCheckDigitSum;
1015
+ if (extensionWeight !== 0) {
1016
+ // Apply every digit to the extension digit.
1017
+ for (const c of NUMERIC_CREATOR.characterSet) {
1018
+ yield* AbstractNumericIdentificationKeyCreator.createAllPartial(c + partialIdentificationKey, nextRemainingReferenceLength, 0, weight, nextPartialCheckDigitSum);
1019
+ nextPartialCheckDigitSum += extensionWeight;
1020
+ }
1021
+ }
1022
+ else {
1023
+ const nextWeight = 4 - weight;
1024
+ // Apply every digit to the current character in the identification key.
1025
+ for (const c of NUMERIC_CREATOR.characterSet) {
1026
+ yield* AbstractNumericIdentificationKeyCreator.createAllPartial(partialIdentificationKey + c, nextRemainingReferenceLength, 0, nextWeight, nextPartialCheckDigitSum);
1027
+ nextPartialCheckDigitSum += weight;
1028
+ }
1029
+ }
1030
+ }
1031
+ }
1032
+ /**
1033
+ * @inheritDoc
1034
+ */
1035
+ createAll() {
1036
+ const hasExtensionDigit = this.leaderType === LeaderType.ExtensionDigit;
1037
+ const prefix = this.prefix;
1038
+ const length = this.length;
1039
+ const referenceLength = this.referenceLength;
1040
+ // Start weight is for reference excluding extension digit, which has its weight calculated separately.
1041
+ const startWeight = 3 - 2 * ((referenceLength + 1 - Number(hasExtensionDigit)) % 2);
1042
+ // Returning separate Iterable object makes iteration repeatable.
1043
+ return {
1044
+ [Symbol.iterator]() {
1045
+ return AbstractNumericIdentificationKeyCreator.createAllPartial(prefix, referenceLength, hasExtensionDigit ? 3 - 2 * length % 2 : 0, startWeight, checkDigitSum(startWeight === 3, prefix));
1046
+ }
1047
+ };
1048
+ }
1049
+ }
1050
+ /**
1051
+ * GTIN creator. Applicable to GTIN-13, GTIN-12, and GTIN-8 types; no applicable to GTIN-14 type.
1052
+ */
1053
+ export class GTINCreator extends Mixin(GTINValidator, AbstractNumericIdentificationKeyCreator) {
1054
+ /**
1055
+ * Validation parameters for required indicator digit.
1056
+ */
1057
+ static REQUIRED_INDICATOR_DIGIT_VALIDATION = {
1058
+ minimumLength: 1,
1059
+ maximumLength: 1,
1060
+ component: () => i18nextGS1.t("IdentificationKey.indicatorDigit")
1061
+ };
1062
+ /**
1063
+ * Constructor. Called internally by {@link PrefixManager.gtinCreator}; should not be called by other code.
1064
+ *
1065
+ * @param prefixManager
1066
+ * Prefix manager.
1067
+ *
1068
+ * @param gtinType
1069
+ * GTIN type.
1070
+ */
1071
+ constructor(prefixManager, gtinType) {
1072
+ super(gtinType);
1073
+ this.init(prefixManager, prefixManager.prefix);
1074
+ }
1075
+ /**
1076
+ * @inheritDoc
1077
+ */
1078
+ get prefix() {
1079
+ return this.prefixManager.prefix;
1080
+ }
1081
+ /**
1082
+ * Create GTIN-14(s) with an indicator digit and reference(s) based on numeric value(s). The value(s) is/are
1083
+ * converted to reference(s) of the appropriate length using {@linkcode NUMERIC_CREATOR}.
1084
+ *
1085
+ * @param indicatorDigit
1086
+ * Indicator digit.
1087
+ *
1088
+ * @param valueOrValues
1089
+ * Numeric value(s).
1090
+ *
1091
+ * @param sparse
1092
+ * If true, the value(s) is/are mapped to a sparse sequence resistant to discovery. Default is false.
1093
+ *
1094
+ * @returns
1095
+ * GTIN-14(s).
1096
+ */
1097
+ createGTIN14(indicatorDigit, valueOrValues, sparse = false) {
1098
+ NUMERIC_CREATOR.validate(indicatorDigit, GTINCreator.REQUIRED_INDICATOR_DIGIT_VALIDATION);
1099
+ return NUMERIC_CREATOR.create(GTINType.GTIN13 - this.prefixManager.gs1CompanyPrefix.length - 1, valueOrValues, Exclusion.None, sparse ? this.tweak : undefined, (reference) => {
1100
+ const partialIdentificationKey = indicatorDigit + this.prefixManager.gs1CompanyPrefix + reference;
1101
+ return partialIdentificationKey + checkDigit(partialIdentificationKey);
1102
+ });
1103
+ }
1104
+ }
1105
+ /**
1106
+ * Non-GTIN numeric identification key creator.
1107
+ */
1108
+ export class NonGTINNumericIdentificationKeyCreator extends Mixin(NonGTINNumericIdentificationKeyValidator, AbstractNumericIdentificationKeyCreator) {
1109
+ /**
1110
+ * Constructor. Called internally by {@link PrefixManager} non-GTIN numeric identification key creator getters;
1111
+ * should not be called by other code.
1112
+ *
1113
+ * @param prefixManager
1114
+ * Prefix manager.
1115
+ *
1116
+ * @param identificationKeyType
1117
+ * Identification key type.
1118
+ *
1119
+ * @param length
1120
+ * Length.
1121
+ *
1122
+ * @param leaderType
1123
+ * Leader type.
1124
+ */
1125
+ constructor(prefixManager, identificationKeyType, length, leaderType = LeaderType.None) {
1126
+ super(identificationKeyType, length, leaderType);
1127
+ this.init(prefixManager, prefixManager.gs1CompanyPrefix);
1128
+ }
1129
+ }
1130
+ /**
1131
+ * Serializable numeric identification key creator.
1132
+ */
1133
+ export class SerializableNumericIdentificationKeyCreator extends Mixin(SerializableNumericIdentificationKeyValidator, AbstractNumericIdentificationKeyCreator) {
1134
+ /**
1135
+ * Constructor. Called internally by {@link PrefixManager} serialized numeric identification key creator getters;
1136
+ * should not be called by other code.
1137
+ *
1138
+ * @param prefixManager
1139
+ * Prefix manager.
1140
+ *
1141
+ * @param identificationKeyType
1142
+ * Identification key type.
1143
+ *
1144
+ * @param length
1145
+ * Length.
1146
+ *
1147
+ * @param serialComponentLength
1148
+ * Serial component length.
1149
+ *
1150
+ * @param serialComponentCharacterSet
1151
+ * Serial component character set.
1152
+ */
1153
+ constructor(prefixManager, identificationKeyType, length, serialComponentLength, serialComponentCharacterSet) {
1154
+ super(identificationKeyType, length, serialComponentLength, serialComponentCharacterSet);
1155
+ this.init(prefixManager, prefixManager.gs1CompanyPrefix);
1156
+ }
1157
+ /**
1158
+ * Concatenate a validated base identification key with serial component(s).
1159
+ *
1160
+ * @param baseIdentificationKey
1161
+ * Base identification key.
1162
+ *
1163
+ * @param serialComponentOrComponents
1164
+ * Serial component(s).
1165
+ *
1166
+ * @returns
1167
+ * Serialized identification key(s).
1168
+ */
1169
+ concatenateValidated(baseIdentificationKey, serialComponentOrComponents) {
1170
+ // TODO Refactor type when https://github.com/microsoft/TypeScript/pull/56941 released.
1171
+ let result;
1172
+ const serialComponentCreator = this.serialComponentCreator;
1173
+ const serialComponentValidation = this.serialComponentValidation;
1174
+ /**
1175
+ * Validate a serial component and concatenate it to the base identification key.
1176
+ *
1177
+ * @param serialComponent
1178
+ * Serial component.
1179
+ *
1180
+ * @returns
1181
+ * Serialized identification key.
1182
+ */
1183
+ function validateAndConcatenate(serialComponent) {
1184
+ serialComponentCreator.validate(serialComponent, serialComponentValidation);
1185
+ return baseIdentificationKey + serialComponent;
1186
+ }
1187
+ if (typeof serialComponentOrComponents !== "object") {
1188
+ result = validateAndConcatenate(serialComponentOrComponents);
1189
+ }
1190
+ else {
1191
+ result = transformIterable(serialComponentOrComponents, validateAndConcatenate);
1192
+ }
1193
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Type determination is handled above.
1194
+ return result;
1195
+ }
1196
+ /**
1197
+ * Create serialized identification key(s) with a reference based on a numeric value concatenated with serial
1198
+ * component(s). The value is converted to a reference of the appropriate length using {@linkcode NUMERIC_CREATOR}.
1199
+ *
1200
+ * @param value
1201
+ * Numeric value of the reference.
1202
+ *
1203
+ * @param serialComponentOrComponents
1204
+ * Serial component(s).
1205
+ *
1206
+ * @param sparse
1207
+ * If true, the value is mapped to a sparse sequence resistant to discovery. Default is false.
1208
+ *
1209
+ * @returns
1210
+ * Serialized identification keys.
1211
+ */
1212
+ createSerialized(value, serialComponentOrComponents, sparse) {
1213
+ return this.concatenateValidated(this.create(value, sparse), serialComponentOrComponents);
1214
+ }
1215
+ /**
1216
+ * Concatenate a base identification key with serial component(s).
1217
+ *
1218
+ * @param baseIdentificationKey
1219
+ * Base identification key.
1220
+ *
1221
+ * @param serialComponentOrComponents
1222
+ * Serial component(s).
1223
+ *
1224
+ * @returns
1225
+ * Serialized identification key(s).
1226
+ */
1227
+ concatenate(baseIdentificationKey, serialComponentOrComponents) {
1228
+ this.validate(baseIdentificationKey);
1229
+ return this.concatenateValidated(baseIdentificationKey, serialComponentOrComponents);
1230
+ }
1231
+ }
1232
+ /**
1233
+ * Non-numeric identification key creator.
1234
+ */
1235
+ export class NonNumericIdentificationKeyCreator extends Mixin(NonNumericIdentificationKeyValidator, AbstractIdentificationKeyCreator) {
1236
+ /**
1237
+ * Reference validation parameters.
1238
+ */
1239
+ _referenceValidation;
1240
+ /**
1241
+ * Constructor. Called internally by {@link PrefixManager} non-numeric identification key creator getters; should
1242
+ * not be called by other code.
1243
+ *
1244
+ * @param prefixManager
1245
+ * Prefix manager.
1246
+ *
1247
+ * @param identificationKeyType
1248
+ * Identification key type.
1249
+ *
1250
+ * @param length
1251
+ * Length.
1252
+ *
1253
+ * @param referenceCharacterSet
1254
+ * Reference character set.
1255
+ *
1256
+ * @param requiresCheckCharacterPair
1257
+ * True if the identification key requires a check character pair.
1258
+ */
1259
+ constructor(prefixManager, identificationKeyType, length, referenceCharacterSet, requiresCheckCharacterPair = false) {
1260
+ super(identificationKeyType, length, referenceCharacterSet, requiresCheckCharacterPair);
1261
+ this.init(prefixManager, prefixManager.gs1CompanyPrefix, 2 * Number(requiresCheckCharacterPair));
1262
+ this._referenceValidation = {
1263
+ minimumLength: 1,
1264
+ // Maximum reference length has to account for prefix and check character pair.
1265
+ maximumLength: this.referenceLength,
1266
+ component: () => i18nextGS1.t("IdentificationKey.reference")
1267
+ };
1268
+ }
1269
+ /**
1270
+ * Get the reference validation parameters.
1271
+ */
1272
+ get referenceValidation() {
1273
+ return this._referenceValidation;
1274
+ }
1275
+ /**
1276
+ * Create identification key(s) with reference(s).
1277
+ *
1278
+ * @param referenceOrReferences
1279
+ * Reference(s).
1280
+ *
1281
+ * @returns
1282
+ * Identification key(s).
1283
+ */
1284
+ create(referenceOrReferences) {
1285
+ // TODO Refactor type when https://github.com/microsoft/TypeScript/pull/56941 released.
1286
+ let result;
1287
+ const referenceCreator = this.referenceCreator;
1288
+ const referenceValidation = this.referenceValidation;
1289
+ const prefix = this.prefix;
1290
+ const requiresCheckCharacterPair = this.requiresCheckCharacterPair;
1291
+ /**
1292
+ * Validate a reference and create an identification key.
1293
+ *
1294
+ * @param reference
1295
+ * Reference.
1296
+ *
1297
+ * @returns
1298
+ * Identification key.
1299
+ */
1300
+ function validateAndCreate(reference) {
1301
+ referenceCreator.validate(reference, referenceValidation);
1302
+ const partialIdentificationKey = prefix + reference;
1303
+ return requiresCheckCharacterPair ? partialIdentificationKey + checkCharacterPair(partialIdentificationKey) : partialIdentificationKey;
1304
+ }
1305
+ if (typeof referenceOrReferences !== "object") {
1306
+ result = validateAndCreate(referenceOrReferences);
1307
+ }
1308
+ else {
1309
+ result = transformIterable(referenceOrReferences, validateAndCreate);
1310
+ }
1311
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Type determination is handled above.
1312
+ return result;
1313
+ }
1314
+ }
1315
+ /**
1316
+ * Prefix manager. This is the core class for identification key creation.
1317
+ *
1318
+ * A prefix manager may be created for any {@link PrefixType | prefix type}. As most applications work with a limited
1319
+ * number of prefixes for creating identification keys, prefix managers are cached in memory and may be reused.
1320
+ *
1321
+ * Prefix managers are keyed by GS1 Company Prefix, so the prefix type that is requested may not match the prefix type
1322
+ * of the returned prefix manager. For example, the prefix manager for GS1 Company Prefix 0614141 is identical to the
1323
+ * one for U.P.C. Company Prefix 614141, with the prefix type equal to {@link PrefixType.UPCCompanyPrefix} and the
1324
+ * prefix equal to "614141".
1325
+ *
1326
+ * To support the creation of sparse identification keys, a prefix manager maintains a {@link tweakFactor | tweak
1327
+ * factor} which is used, along with a type-specific multiplier, as the tweak when creating numeric identification keys.
1328
+ * The default tweak factor is the numeric value of the GS1 Company Prefix representation of the prefix preceded by '1'
1329
+ * to ensure uniqueness (i.e., so that prefixes 0 N1 N2 N3... and N1 N2 N3... produce different tweak factors). This is
1330
+ * usually sufficient for obfuscation, but as the sparse creation algorithm is reversible and as the GS1 Company Prefix
1331
+ * is discoverable via {@link https://www.gs1.org/services/verified-by-gs1 | Verified by GS1}, a user-defined tweak
1332
+ * factor should be used if a higher degree of obfuscation is required. When using a tweak factor other than the
1333
+ * default, care should be taken to restore it when resuming the application. A tweak factor of 0 creates a straight
1334
+ * sequence.
1335
+ */
1336
+ export class PrefixManager {
1337
+ /**
1338
+ * Cached prefix managers, keyed by GS1 Company Prefix.
1339
+ */
1340
+ static PREFIX_MANAGERS_MAP = new Map();
1341
+ /**
1342
+ * GS1 Company Prefix minimum length.
1343
+ */
1344
+ static GS1_COMPANY_PREFIX_MINIMUM_LENGTH = 4;
1345
+ /**
1346
+ * GS1 Company Prefix maximum length.
1347
+ */
1348
+ static GS1_COMPANY_PREFIX_MAXIMUM_LENGTH = 12;
1349
+ /**
1350
+ * U.P.C. Company Prefix minimum length.
1351
+ */
1352
+ static UPC_COMPANY_PREFIX_MINIMUM_LENGTH = 6;
1353
+ /**
1354
+ * U.P.C. Company Prefix maximum length.
1355
+ */
1356
+ static UPC_COMPANY_PREFIX_MAXIMUM_LENGTH = 11;
1357
+ /**
1358
+ * GS1-8 Prefix minimum length.
1359
+ */
1360
+ static GS1_8_PREFIX_MINIMUM_LENGTH = 2;
1361
+ /**
1362
+ * GS1-8 Prefix maximum length.
1363
+ */
1364
+ static GS1_8_PREFIX_MAXIMUM_LENGTH = 7;
1365
+ /**
1366
+ * Validation parameters for GS1 Company Prefix.
1367
+ */
1368
+ static GS1_COMPANY_PREFIX_VALIDATION = {
1369
+ minimumLength: PrefixManager.GS1_COMPANY_PREFIX_MINIMUM_LENGTH,
1370
+ maximumLength: PrefixManager.GS1_COMPANY_PREFIX_MAXIMUM_LENGTH,
1371
+ component: () => i18nextGS1.t("Prefix.gs1CompanyPrefix")
1372
+ };
1373
+ /**
1374
+ * Validation parameters for U.P.C. Company Prefix expressed as GS1 Company Prefix.
1375
+ */
1376
+ static UPC_COMPANY_PREFIX_AS_GS1_COMPANY_PREFIX_VALIDATION = {
1377
+ minimumLength: PrefixManager.UPC_COMPANY_PREFIX_MINIMUM_LENGTH + 1,
1378
+ maximumLength: PrefixManager.UPC_COMPANY_PREFIX_MAXIMUM_LENGTH + 1,
1379
+ component: () => i18nextGS1.t("Prefix.gs1CompanyPrefix")
1380
+ };
1381
+ /**
1382
+ * Validation parameters for GS1-8 Prefix expressed as GS1 Company Prefix.
1383
+ */
1384
+ static GS1_8_PREFIX_AS_GS1_COMPANY_PREFIX_VALIDATION = {
1385
+ minimumLength: PrefixManager.GS1_8_PREFIX_MINIMUM_LENGTH + 5,
1386
+ maximumLength: PrefixManager.GS1_8_PREFIX_MAXIMUM_LENGTH + 5,
1387
+ component: () => i18nextGS1.t("Prefix.gs1CompanyPrefix")
1388
+ };
1389
+ /**
1390
+ * Validation parameters for U.P.C. Company Prefix.
1391
+ */
1392
+ static UPC_COMPANY_PREFIX_VALIDATION = {
1393
+ minimumLength: PrefixManager.UPC_COMPANY_PREFIX_MINIMUM_LENGTH,
1394
+ maximumLength: PrefixManager.UPC_COMPANY_PREFIX_MAXIMUM_LENGTH,
1395
+ component: () => i18nextGS1.t("Prefix.upcCompanyPrefix")
1396
+ };
1397
+ /**
1398
+ * Validation parameters for GS1-8 Prefix.
1399
+ */
1400
+ static GS1_8_PREFIX_VALIDATION = {
1401
+ minimumLength: PrefixManager.GS1_8_PREFIX_MINIMUM_LENGTH,
1402
+ maximumLength: PrefixManager.GS1_8_PREFIX_MAXIMUM_LENGTH,
1403
+ component: () => i18nextGS1.t("Prefix.gs18Prefix")
1404
+ };
1405
+ /**
1406
+ * Creator tweak factors. Different numeric identification key types have different tweak factors so that sparse
1407
+ * creation generates different sequences for each.
1408
+ */
1409
+ static CREATOR_TWEAK_FACTORS_MAP = new Map([
1410
+ [IdentificationKeyType.GTIN, 1987n],
1411
+ [IdentificationKeyType.GLN, 4241n],
1412
+ [IdentificationKeyType.SSCC, 8087n],
1413
+ [IdentificationKeyType.GRAI, 3221n],
1414
+ [IdentificationKeyType.GSRN, 2341n],
1415
+ [IdentificationKeyType.GDTI, 7333n],
1416
+ [IdentificationKeyType.GSIN, 5623n],
1417
+ [IdentificationKeyType.GCN, 6869n]
1418
+ ]);
1419
+ /**
1420
+ * Normalized prefix type.
1421
+ */
1422
+ _prefixType;
1423
+ /**
1424
+ * Normalized prefix.
1425
+ */
1426
+ _prefix;
1427
+ /**
1428
+ * Prefix as GS1 Company Prefix.
1429
+ */
1430
+ _gs1CompanyPrefix;
1431
+ /**
1432
+ * U.P.C. Company Prefix if prefix type is {@link PrefixType.UPCCompanyPrefix}.
1433
+ */
1434
+ _upcCompanyPrefix;
1435
+ /**
1436
+ * GS1-8 Prefix if prefix type is {@link PrefixType.GS18Prefix}.
1437
+ */
1438
+ _gs18Prefix;
1439
+ /**
1440
+ * Default tweak factor.
1441
+ */
1442
+ _defaultTweakFactor;
1443
+ /**
1444
+ * Tweak factor.
1445
+ */
1446
+ _tweakFactor = 0n;
1447
+ /**
1448
+ * Cached identification key creators.
1449
+ */
1450
+ _identificationKeyCreatorsMap = new Map();
1451
+ /**
1452
+ * Constructor.
1453
+ *
1454
+ * @param gs1CompanyPrefix
1455
+ * GS1 Company Prefix.
1456
+ */
1457
+ constructor(gs1CompanyPrefix) {
1458
+ this._gs1CompanyPrefix = gs1CompanyPrefix;
1459
+ // Determine the prefix type and populate the remaining fields.
1460
+ if (!gs1CompanyPrefix.startsWith("0")) {
1461
+ this._prefixType = PrefixType.GS1CompanyPrefix;
1462
+ this._prefix = this._gs1CompanyPrefix;
1463
+ }
1464
+ else if (!gs1CompanyPrefix.startsWith("00000")) {
1465
+ this._prefixType = PrefixType.UPCCompanyPrefix;
1466
+ this._upcCompanyPrefix = gs1CompanyPrefix.substring(1);
1467
+ this._prefix = this._upcCompanyPrefix;
1468
+ }
1469
+ else {
1470
+ this._prefixType = PrefixType.GS18Prefix;
1471
+ this._gs18Prefix = gs1CompanyPrefix.substring(5);
1472
+ this._prefix = this._gs18Prefix;
1473
+ }
1474
+ // Default tweak factor is the numeric value of the GS1 Company Prefix preceded by '1'.
1475
+ this._defaultTweakFactor = BigInt(`1${this.gs1CompanyPrefix}`);
1476
+ this.resetTweakFactor();
1477
+ }
1478
+ /**
1479
+ * Get the prefix type.
1480
+ */
1481
+ get prefixType() {
1482
+ return this._prefixType;
1483
+ }
1484
+ /**
1485
+ * Get the prefix.
1486
+ */
1487
+ get prefix() {
1488
+ return this._prefix;
1489
+ }
1490
+ /**
1491
+ * Get the GS1 Company Prefix.
1492
+ */
1493
+ get gs1CompanyPrefix() {
1494
+ return this._gs1CompanyPrefix;
1495
+ }
1496
+ /**
1497
+ * Get the U.P.C. Company Prefix if prefix type is {@link PrefixType.UPCCompanyPrefix} or undefined if not.
1498
+ */
1499
+ get upcCompanyPrefix() {
1500
+ return this._upcCompanyPrefix;
1501
+ }
1502
+ /**
1503
+ * Get the GS1-8 Prefix if prefix type is {@link PrefixType.GS18Prefix} or undefined if not.
1504
+ */
1505
+ get gs18Prefix() {
1506
+ return this._gs18Prefix;
1507
+ }
1508
+ /**
1509
+ * Set the tweak for an identification key creator if it's a numeric identification key creator.
1510
+ *
1511
+ * @param creator
1512
+ * Identification key creator.
1513
+ */
1514
+ setCreatorTweak(creator) {
1515
+ const creatorTweakFactor = PrefixManager.CREATOR_TWEAK_FACTORS_MAP.get(creator.identificationKeyType);
1516
+ // Creator tweak factor is defined for numeric identification keys only.
1517
+ if (creatorTweakFactor !== undefined) {
1518
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Explicit cast without testing is necessary as "instanceof" doesn't work for mixin types.
1519
+ creator.tweak = this.tweakFactor * creatorTweakFactor;
1520
+ }
1521
+ }
1522
+ /**
1523
+ * Get the tweak factor.
1524
+ */
1525
+ get tweakFactor() {
1526
+ return this._tweakFactor;
1527
+ }
1528
+ /**
1529
+ * Set the tweak factor.
1530
+ *
1531
+ * @param value
1532
+ * Tweak factor.
1533
+ */
1534
+ set tweakFactor(value) {
1535
+ const tweakFactor = BigInt(value);
1536
+ if (this._tweakFactor !== tweakFactor) {
1537
+ this._tweakFactor = tweakFactor;
1538
+ for (const creator of this._identificationKeyCreatorsMap.values()) {
1539
+ this.setCreatorTweak(creator);
1540
+ }
1541
+ }
1542
+ }
1543
+ /**
1544
+ * Reset the tweak factor to its default (numeric value of the GS1 Company Prefix preceded by '1').
1545
+ */
1546
+ resetTweakFactor() {
1547
+ this.tweakFactor = this._defaultTweakFactor;
1548
+ }
1549
+ /**
1550
+ * Get a prefix manager.
1551
+ *
1552
+ * @param prefixType
1553
+ * Prefix type.
1554
+ *
1555
+ * @param prefix
1556
+ * Prefix.
1557
+ *
1558
+ * @returns
1559
+ * Prefix manager with normalized prefix type and prefix.
1560
+ */
1561
+ static get(prefixType, prefix) {
1562
+ PrefixManager.validatePrefix(prefixType, true, true, prefix);
1563
+ let gs1CompanyPrefix;
1564
+ switch (prefixType) {
1565
+ case PrefixType.GS1CompanyPrefix:
1566
+ gs1CompanyPrefix = prefix;
1567
+ break;
1568
+ case PrefixType.UPCCompanyPrefix:
1569
+ gs1CompanyPrefix = "0" + prefix;
1570
+ break;
1571
+ case PrefixType.GS18Prefix:
1572
+ gs1CompanyPrefix = "00000" + prefix;
1573
+ break;
1574
+ // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check -- Method may be called by unsafe means.
1575
+ default:
1576
+ throw new RangeError(i18nextGS1.t("Prefix.invalidPrefixType"));
1577
+ }
1578
+ let prefixManager = PrefixManager.PREFIX_MANAGERS_MAP.get(gs1CompanyPrefix);
1579
+ if (prefixManager === undefined) {
1580
+ prefixManager = new PrefixManager(gs1CompanyPrefix);
1581
+ PrefixManager.PREFIX_MANAGERS_MAP.set(gs1CompanyPrefix, prefixManager);
1582
+ }
1583
+ return prefixManager;
1584
+ }
1585
+ /**
1586
+ * Validate a prefix.
1587
+ *
1588
+ * @param prefixType
1589
+ * Prefix type.
1590
+ *
1591
+ * @param allowUPCCompanyPrefix
1592
+ * If true, a U.P.C. Company Prefix expressed as a GS1 Company Prefix is permitted.
1593
+ *
1594
+ * @param allowGS18Prefix
1595
+ * If true, a GS1-8 Prefix expressed as a GS1 Company Prefix is permitted.
1596
+ *
1597
+ * @param prefix
1598
+ * Prefix.
1599
+ *
1600
+ * @param isFromIdentificationKey
1601
+ * If true, the prefix is from an identification key and should be trimmed before its character set is validated.
1602
+ *
1603
+ * @param isNumericIdentificationKey
1604
+ * If true, the prefix is from a numeric identification key and its character set will be validated by the caller.
1605
+ *
1606
+ * @param positionOffset
1607
+ * Position offset within a larger string.
1608
+ */
1609
+ static validatePrefix(prefixType, allowUPCCompanyPrefix, allowGS18Prefix, prefix, isFromIdentificationKey = false, isNumericIdentificationKey = false, positionOffset) {
1610
+ let baseValidation;
1611
+ // Validate the prefix type and determine the prefix validation parameters.
1612
+ switch (prefixType) {
1613
+ case PrefixType.GS1CompanyPrefix:
1614
+ if (!prefix.startsWith("0")) {
1615
+ baseValidation = PrefixManager.GS1_COMPANY_PREFIX_VALIDATION;
1616
+ }
1617
+ else if (!prefix.startsWith("00000")) {
1618
+ if (!allowUPCCompanyPrefix) {
1619
+ throw new RangeError(i18nextGS1.t("Prefix.gs1CompanyPrefixCantStartWith0"));
1620
+ }
1621
+ baseValidation = PrefixManager.UPC_COMPANY_PREFIX_AS_GS1_COMPANY_PREFIX_VALIDATION;
1622
+ }
1623
+ else if (!prefix.startsWith("000000")) {
1624
+ if (!allowGS18Prefix) {
1625
+ throw new RangeError(i18nextGS1.t("Prefix.gs1CompanyPrefixCantStartWith00000"));
1626
+ }
1627
+ baseValidation = PrefixManager.GS1_8_PREFIX_AS_GS1_COMPANY_PREFIX_VALIDATION;
1628
+ }
1629
+ else {
1630
+ throw new RangeError(i18nextGS1.t("Prefix.gs1CompanyPrefixCantStartWith000000"));
1631
+ }
1632
+ break;
1633
+ case PrefixType.UPCCompanyPrefix:
1634
+ if (prefix.startsWith("0000")) {
1635
+ throw new RangeError(i18nextGS1.t("Prefix.upcCompanyPrefixCantStartWith0000"));
1636
+ }
1637
+ baseValidation = PrefixManager.UPC_COMPANY_PREFIX_VALIDATION;
1638
+ break;
1639
+ case PrefixType.GS18Prefix:
1640
+ if (prefix.startsWith("0")) {
1641
+ throw new RangeError(i18nextGS1.t("Prefix.gs18PrefixCantStartWith0"));
1642
+ }
1643
+ baseValidation = PrefixManager.GS1_8_PREFIX_VALIDATION;
1644
+ break;
1645
+ }
1646
+ const mergedValidation = {
1647
+ ...baseValidation,
1648
+ positionOffset
1649
+ };
1650
+ // If from key and numeric, key validation will take care of character set validation.
1651
+ if (!isFromIdentificationKey) {
1652
+ NUMERIC_CREATOR.validate(prefix, mergedValidation);
1653
+ }
1654
+ else if (!isNumericIdentificationKey) {
1655
+ // Validate only the minimum length, allowing at least one character for the (possibly non-numeric) reference.
1656
+ NUMERIC_CREATOR.validate(prefix.substring(0, Math.min(mergedValidation.minimumLength, prefix.length - 1)), mergedValidation);
1657
+ }
1658
+ }
1659
+ /**
1660
+ * Get an identification key creator.
1661
+ *
1662
+ * @param identificationKeyType
1663
+ * Identification key type.
1664
+ *
1665
+ * @param constructorCallback
1666
+ * Constructor callback.
1667
+ *
1668
+ * @returns
1669
+ * Identification key creator.
1670
+ */
1671
+ getIdentificationKeyCreator(identificationKeyType, constructorCallback) {
1672
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Type is paired with constructor callback.
1673
+ let creator = this._identificationKeyCreatorsMap.get(identificationKeyType);
1674
+ if (creator === undefined) {
1675
+ if (this.prefixType === PrefixType.GS18Prefix && identificationKeyType !== IdentificationKeyType.GTIN) {
1676
+ throw new RangeError(i18nextGS1.t("Prefix.identificationKeyTypeNotSupportedByGS18Prefix", {
1677
+ identificationKeyType
1678
+ }));
1679
+ }
1680
+ creator = constructorCallback();
1681
+ this.setCreatorTweak(creator);
1682
+ this._identificationKeyCreatorsMap.set(identificationKeyType, creator);
1683
+ }
1684
+ return creator;
1685
+ }
1686
+ /**
1687
+ * Get non-GTIN numeric identification key creator.
1688
+ *
1689
+ * @param validator
1690
+ * Validator on which identification key creator is based.
1691
+ *
1692
+ * @returns
1693
+ * Identification key creator.
1694
+ */
1695
+ getNonGTINNumericIdentificationKeyCreator(validator) {
1696
+ return this.getIdentificationKeyCreator(validator.identificationKeyType, () => new NonGTINNumericIdentificationKeyCreator(this, validator.identificationKeyType, validator.length, validator.leaderType));
1697
+ }
1698
+ /**
1699
+ * Get serialized numeric identification key creator.
1700
+ *
1701
+ * @param validator
1702
+ * Validator on which identification key creator is based.
1703
+ *
1704
+ * @returns
1705
+ * Identification key creator.
1706
+ */
1707
+ getSerializableNumericIdentificationKeyCreator(validator) {
1708
+ return this.getIdentificationKeyCreator(validator.identificationKeyType, () => new SerializableNumericIdentificationKeyCreator(this, validator.identificationKeyType, validator.length, validator.serialComponentLength, validator.serialComponentCharacterSet));
1709
+ }
1710
+ /**
1711
+ * Get non-numeric identification key creator.
1712
+ *
1713
+ * @param validator
1714
+ * Validator on which identification key creator is based.
1715
+ *
1716
+ * @returns
1717
+ * Identification key creator.
1718
+ */
1719
+ getNonNumericIdentificationKeyCreator(validator) {
1720
+ return this.getIdentificationKeyCreator(validator.identificationKeyType, () => new NonNumericIdentificationKeyCreator(this, validator.identificationKeyType, validator.length, validator.referenceCharacterSet, validator.requiresCheckCharacterPair));
1721
+ }
1722
+ /**
1723
+ * Get GTIN creator.
1724
+ */
1725
+ get gtinCreator() {
1726
+ return this.getIdentificationKeyCreator(IdentificationKeyType.GTIN, () => {
1727
+ let gtinType;
1728
+ switch (this.prefixType) {
1729
+ case PrefixType.GS1CompanyPrefix:
1730
+ gtinType = GTINType.GTIN13;
1731
+ break;
1732
+ case PrefixType.UPCCompanyPrefix:
1733
+ gtinType = GTINType.GTIN12;
1734
+ break;
1735
+ case PrefixType.GS18Prefix:
1736
+ gtinType = GTINType.GTIN8;
1737
+ break;
1738
+ }
1739
+ return new GTINCreator(this, gtinType);
1740
+ });
1741
+ }
1742
+ /**
1743
+ * Get GLN creator.
1744
+ */
1745
+ get glnCreator() {
1746
+ return this.getNonGTINNumericIdentificationKeyCreator(GLN_VALIDATOR);
1747
+ }
1748
+ /**
1749
+ * Get SSCC creator.
1750
+ */
1751
+ get ssccCreator() {
1752
+ return this.getNonGTINNumericIdentificationKeyCreator(SSCC_VALIDATOR);
1753
+ }
1754
+ /**
1755
+ * Get GRAI creator.
1756
+ */
1757
+ get graiCreator() {
1758
+ return this.getSerializableNumericIdentificationKeyCreator(GRAI_VALIDATOR);
1759
+ }
1760
+ /**
1761
+ * Get GIAI creator.
1762
+ */
1763
+ get giaiCreator() {
1764
+ return this.getNonNumericIdentificationKeyCreator(GIAI_VALIDATOR);
1765
+ }
1766
+ /**
1767
+ * Get GSRN creator.
1768
+ */
1769
+ get gsrnCreator() {
1770
+ return this.getNonGTINNumericIdentificationKeyCreator(GSRN_VALIDATOR);
1771
+ }
1772
+ /**
1773
+ * Get GDTI creator.
1774
+ */
1775
+ get gdtiCreator() {
1776
+ return this.getSerializableNumericIdentificationKeyCreator(GDTI_VALIDATOR);
1777
+ }
1778
+ /**
1779
+ * Get GINC creator.
1780
+ */
1781
+ get gincCreator() {
1782
+ return this.getNonNumericIdentificationKeyCreator(GINC_VALIDATOR);
1783
+ }
1784
+ /**
1785
+ * Get GSIN creator.
1786
+ */
1787
+ get gsinCreator() {
1788
+ return this.getNonGTINNumericIdentificationKeyCreator(GSIN_VALIDATOR);
1789
+ }
1790
+ /**
1791
+ * Get GCN creator.
1792
+ */
1793
+ get gcnCreator() {
1794
+ return this.getSerializableNumericIdentificationKeyCreator(GCN_VALIDATOR);
1795
+ }
1796
+ /**
1797
+ * Get CPID creator.
1798
+ */
1799
+ get cpidCreator() {
1800
+ return this.getNonNumericIdentificationKeyCreator(CPID_VALIDATOR);
1801
+ }
1802
+ /**
1803
+ * Get GMN creator.
1804
+ */
1805
+ get gmnCreator() {
1806
+ return this.getNonNumericIdentificationKeyCreator(GMN_VALIDATOR);
1807
+ }
1808
+ }
1809
+ //# sourceMappingURL=idkey.js.map