@aidc-toolkit/gs1 0.9.7-beta → 0.9.9-beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +0 -27
- package/README.md +14 -0
- package/dist/index.cjs +143 -131
- package/dist/index.d.cts +145 -6
- package/dist/index.d.ts +145 -6
- package/dist/index.js +104 -105
- package/package.json +9 -8
- package/src/check.ts +24 -9
- package/src/idkey.ts +53 -99
- package/src/index.ts +18 -2
- package/src/locale/en/{locale_strings.ts → locale-strings.ts} +2 -0
- package/src/locale/fr/{locale_strings.ts → locale-strings.ts} +2 -0
- package/src/locale/i18n.ts +40 -6
- package/src/locale/i18next.d.ts +5 -3
- package/test/check.test.ts +9 -8
- package/test/idkey.test.ts +17 -16
- /package/src/{character_set.ts → character-set.ts} +0 -0
package/src/idkey.ts
CHANGED
|
@@ -2,16 +2,16 @@ import {
|
|
|
2
2
|
CharacterSetCreator,
|
|
3
3
|
type CharacterSetValidation,
|
|
4
4
|
Exclusion,
|
|
5
|
-
IteratorProxy,
|
|
6
5
|
NUMERIC_CREATOR,
|
|
7
6
|
RegExpValidator,
|
|
8
7
|
type StringValidation,
|
|
9
8
|
type StringValidator,
|
|
10
9
|
type TransformerInput,
|
|
11
|
-
type TransformerOutput
|
|
10
|
+
type TransformerOutput,
|
|
11
|
+
transformIterable
|
|
12
12
|
} from "@aidc-toolkit/utility";
|
|
13
13
|
import { Mixin } from "ts-mixer";
|
|
14
|
-
import { AI39_CREATOR, AI82_CREATOR } from "./
|
|
14
|
+
import { AI39_CREATOR, AI82_CREATOR } from "./character-set.js";
|
|
15
15
|
import {
|
|
16
16
|
checkCharacterPair,
|
|
17
17
|
checkDigit,
|
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
hasValidCheckCharacterPair,
|
|
20
20
|
hasValidCheckDigit
|
|
21
21
|
} from "./check.js";
|
|
22
|
-
import
|
|
22
|
+
import { i18nextGS1 } from "./locale/i18n.js";
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* Identification key type.
|
|
@@ -409,8 +409,7 @@ abstract class AbstractNumericIdentificationKeyValidator extends AbstractIdentif
|
|
|
409
409
|
|
|
410
410
|
// Validate the length.
|
|
411
411
|
if (identificationKey.length !== this.length) {
|
|
412
|
-
throw new RangeError(
|
|
413
|
-
ns: gs1NS,
|
|
412
|
+
throw new RangeError(i18nextGS1.t("IdentificationKey.identificationKeyTypeLength", {
|
|
414
413
|
identificationKeyType: this.identificationKeyType,
|
|
415
414
|
length: this.length
|
|
416
415
|
}));
|
|
@@ -418,9 +417,7 @@ abstract class AbstractNumericIdentificationKeyValidator extends AbstractIdentif
|
|
|
418
417
|
|
|
419
418
|
// Validating the check digit will also validate the characters.
|
|
420
419
|
if (!hasValidCheckDigit(this.padIdentificationKey(identificationKey, validation))) {
|
|
421
|
-
throw new RangeError(
|
|
422
|
-
ns: gs1NS
|
|
423
|
-
}));
|
|
420
|
+
throw new RangeError(i18nextGS1.t("IdentificationKey.invalidCheckDigit"));
|
|
424
421
|
}
|
|
425
422
|
}
|
|
426
423
|
}
|
|
@@ -560,9 +557,7 @@ export class GTINValidator extends AbstractNumericIdentificationKeyValidator {
|
|
|
560
557
|
}
|
|
561
558
|
|
|
562
559
|
if (gtin12 === undefined) {
|
|
563
|
-
throw new RangeError(
|
|
564
|
-
ns: gs1NS
|
|
565
|
-
}));
|
|
560
|
+
throw new RangeError(i18nextGS1.t("IdentificationKey.invalidZeroSuppressedGTIN12"));
|
|
566
561
|
}
|
|
567
562
|
|
|
568
563
|
// Make sure that resulting GTIN-12 is valid.
|
|
@@ -589,9 +584,7 @@ export class GTINValidator extends AbstractNumericIdentificationKeyValidator {
|
|
|
589
584
|
switch (gtin.length) {
|
|
590
585
|
case GTINType.GTIN13 as number:
|
|
591
586
|
if (gtin.startsWith("0")) {
|
|
592
|
-
throw new RangeError(
|
|
593
|
-
ns: gs1NS
|
|
594
|
-
}));
|
|
587
|
+
throw new RangeError(i18nextGS1.t("IdentificationKey.invalidGTIN13AtRetail"));
|
|
595
588
|
}
|
|
596
589
|
|
|
597
590
|
// Validate prefix requiring exact match for prefix type.
|
|
@@ -627,23 +620,17 @@ export class GTINValidator extends AbstractNumericIdentificationKeyValidator {
|
|
|
627
620
|
break;
|
|
628
621
|
|
|
629
622
|
default:
|
|
630
|
-
throw new RangeError(
|
|
631
|
-
ns: gs1NS
|
|
632
|
-
}));
|
|
623
|
+
throw new RangeError(i18nextGS1.t("IdentificationKey.invalidGTINLength"));
|
|
633
624
|
}
|
|
634
625
|
|
|
635
626
|
// Validating the check digit will also validate the characters.
|
|
636
627
|
if (!hasValidCheckDigit(lengthValidatedGTIN)) {
|
|
637
|
-
throw new RangeError(
|
|
638
|
-
ns: gs1NS
|
|
639
|
-
}));
|
|
628
|
+
throw new RangeError(i18nextGS1.t("IdentificationKey.invalidCheckDigit"));
|
|
640
629
|
}
|
|
641
630
|
|
|
642
631
|
// Validate against level if required.
|
|
643
632
|
if (gtinLevel !== GTINLevel.Any && gtinLevelRestriction !== GTINLevel.Any && gtinLevelRestriction !== gtinLevel) {
|
|
644
|
-
throw new RangeError(
|
|
645
|
-
ns: gs1NS
|
|
646
|
-
}));
|
|
633
|
+
throw new RangeError(i18nextGS1.t(gtinLevel === GTINLevel.RetailConsumer ? "IdentificationKey.invalidGTINAtRetail" : "IdentificationKey.invalidGTINAtOtherThanRetail"));
|
|
647
634
|
}
|
|
648
635
|
}
|
|
649
636
|
|
|
@@ -655,9 +642,7 @@ export class GTINValidator extends AbstractNumericIdentificationKeyValidator {
|
|
|
655
642
|
*/
|
|
656
643
|
static validateGTIN14(gtin14: string): void {
|
|
657
644
|
if (gtin14.length as GTINType !== GTINType.GTIN14) {
|
|
658
|
-
throw new RangeError(
|
|
659
|
-
ns: gs1NS
|
|
660
|
-
}));
|
|
645
|
+
throw new RangeError(i18nextGS1.t("IdentificationKey.invalidGTIN14Length"));
|
|
661
646
|
}
|
|
662
647
|
|
|
663
648
|
GTINCreator.validateAny(gtin14);
|
|
@@ -734,9 +719,7 @@ export class SerializableNumericIdentificationKeyValidator extends NonGTINNumeri
|
|
|
734
719
|
this._serialComponentValidation = {
|
|
735
720
|
minimumLength: 1,
|
|
736
721
|
maximumLength: serialComponentLength,
|
|
737
|
-
component: () =>
|
|
738
|
-
ns: gs1NS
|
|
739
|
-
})
|
|
722
|
+
component: () => i18nextGS1.t("IdentificationKey.serialComponent")
|
|
740
723
|
};
|
|
741
724
|
|
|
742
725
|
this._serialComponentCreator = SerializableNumericIdentificationKeyValidator.creatorFor(serialComponentCharacterSet);
|
|
@@ -805,9 +788,7 @@ export class NonNumericIdentificationKeyValidator extends AbstractIdentification
|
|
|
805
788
|
* @inheritDoc
|
|
806
789
|
*/
|
|
807
790
|
protected override createErrorMessage(_s: string): string {
|
|
808
|
-
return
|
|
809
|
-
ns: gs1NS
|
|
810
|
-
});
|
|
791
|
+
return i18nextGS1.t("IdentificationKey.referenceCantBeAllNumeric");
|
|
811
792
|
}
|
|
812
793
|
}(/\D/);
|
|
813
794
|
|
|
@@ -865,9 +846,7 @@ export class NonNumericIdentificationKeyValidator extends AbstractIdentification
|
|
|
865
846
|
});
|
|
866
847
|
// Validating the check character pair will also validate the characters.
|
|
867
848
|
} else if (!hasValidCheckCharacterPair(this.padIdentificationKey(identificationKey, validation))) {
|
|
868
|
-
throw new RangeError(
|
|
869
|
-
ns: gs1NS
|
|
870
|
-
}));
|
|
849
|
+
throw new RangeError(i18nextGS1.t("IdentificationKey.invalidCheckCharacterPair"));
|
|
871
850
|
}
|
|
872
851
|
|
|
873
852
|
// Check for all-numeric identification key (minus check character pair) if excluded.
|
|
@@ -1074,13 +1053,14 @@ export interface NumericIdentificationKeyCreator extends NumericIdentificationKe
|
|
|
1074
1053
|
/**
|
|
1075
1054
|
* Create all identification keys for the prefix from `0` to `capacity - 1`.
|
|
1076
1055
|
*
|
|
1077
|
-
* The implementation creates the strings as needed using an internal generator function
|
|
1078
|
-
*
|
|
1056
|
+
* The implementation creates the strings only as needed using an internal generator function. Although the result
|
|
1057
|
+
* is equivalent to calling `creator.create(new Sequence(0, creator.capacity))`, this method is significantly
|
|
1058
|
+
* faster.
|
|
1079
1059
|
*
|
|
1080
1060
|
* @returns
|
|
1081
|
-
*
|
|
1061
|
+
* All identification keys for the prefix.
|
|
1082
1062
|
*/
|
|
1083
|
-
createAll: () =>
|
|
1063
|
+
createAll: () => Iterable<string>;
|
|
1084
1064
|
}
|
|
1085
1065
|
|
|
1086
1066
|
/**
|
|
@@ -1213,15 +1193,21 @@ abstract class AbstractNumericIdentificationKeyCreator extends AbstractIdentific
|
|
|
1213
1193
|
/**
|
|
1214
1194
|
* @inheritDoc
|
|
1215
1195
|
*/
|
|
1216
|
-
createAll():
|
|
1196
|
+
createAll(): Iterable<string> {
|
|
1217
1197
|
const hasExtensionDigit = this.leaderType === LeaderType.ExtensionDigit;
|
|
1218
1198
|
const prefix = this.prefix;
|
|
1199
|
+
const length = this.length;
|
|
1219
1200
|
const referenceLength = this.referenceLength;
|
|
1220
1201
|
|
|
1221
1202
|
// Start weight is for reference excluding extension digit, which has its weight calculated separately.
|
|
1222
1203
|
const startWeight = 3 - 2 * ((referenceLength + 1 - Number(hasExtensionDigit)) % 2);
|
|
1223
1204
|
|
|
1224
|
-
|
|
1205
|
+
// Returning separate Iterable object makes iteration repeatable.
|
|
1206
|
+
return {
|
|
1207
|
+
[Symbol.iterator]() {
|
|
1208
|
+
return AbstractNumericIdentificationKeyCreator.createAllPartial(prefix, referenceLength, hasExtensionDigit ? 3 - 2 * length % 2 : 0, startWeight, checkDigitSum(startWeight === 3, prefix));
|
|
1209
|
+
}
|
|
1210
|
+
};
|
|
1225
1211
|
}
|
|
1226
1212
|
}
|
|
1227
1213
|
|
|
@@ -1235,9 +1221,7 @@ export class GTINCreator extends Mixin(GTINValidator, AbstractNumericIdentificat
|
|
|
1235
1221
|
private static readonly REQUIRED_INDICATOR_DIGIT_VALIDATION: CharacterSetValidation = {
|
|
1236
1222
|
minimumLength: 1,
|
|
1237
1223
|
maximumLength: 1,
|
|
1238
|
-
component: () =>
|
|
1239
|
-
ns: gs1NS
|
|
1240
|
-
})
|
|
1224
|
+
component: () => i18nextGS1.t("IdentificationKey.indicatorDigit")
|
|
1241
1225
|
};
|
|
1242
1226
|
|
|
1243
1227
|
/**
|
|
@@ -1246,9 +1230,7 @@ export class GTINCreator extends Mixin(GTINValidator, AbstractNumericIdentificat
|
|
|
1246
1230
|
private static readonly OPTIONAL_INDICATOR_DIGIT_VALIDATION: CharacterSetValidation = {
|
|
1247
1231
|
minimumLength: 0,
|
|
1248
1232
|
maximumLength: 1,
|
|
1249
|
-
component: () =>
|
|
1250
|
-
ns: gs1NS
|
|
1251
|
-
})
|
|
1233
|
+
component: () => i18nextGS1.t("IdentificationKey.indicatorDigit")
|
|
1252
1234
|
};
|
|
1253
1235
|
|
|
1254
1236
|
/**
|
|
@@ -1330,9 +1312,7 @@ export class GTINCreator extends Mixin(GTINValidator, AbstractNumericIdentificat
|
|
|
1330
1312
|
}
|
|
1331
1313
|
|
|
1332
1314
|
if (zeroSuppressedGTIN12 === undefined) {
|
|
1333
|
-
throw new RangeError(
|
|
1334
|
-
ns: gs1NS
|
|
1335
|
-
}));
|
|
1315
|
+
throw new RangeError(i18nextGS1.t("IdentificationKey.invalidZeroSuppressibleGTIN12"));
|
|
1336
1316
|
}
|
|
1337
1317
|
|
|
1338
1318
|
return zeroSuppressedGTIN12;
|
|
@@ -1400,9 +1380,7 @@ export class GTINCreator extends Mixin(GTINValidator, AbstractNumericIdentificat
|
|
|
1400
1380
|
// GTIN is GTIN-8.
|
|
1401
1381
|
normalizedGTIN = gtin.substring(5);
|
|
1402
1382
|
} else {
|
|
1403
|
-
throw new RangeError(
|
|
1404
|
-
ns: gs1NS
|
|
1405
|
-
}));
|
|
1383
|
+
throw new RangeError(i18nextGS1.t("IdentificationKey.invalidZeroSuppressedGTIN12AsGTIN13"));
|
|
1406
1384
|
}
|
|
1407
1385
|
break;
|
|
1408
1386
|
|
|
@@ -1435,16 +1413,12 @@ export class GTINCreator extends Mixin(GTINValidator, AbstractNumericIdentificat
|
|
|
1435
1413
|
// GTIN is GTIN-8.
|
|
1436
1414
|
normalizedGTIN = gtin.substring(6);
|
|
1437
1415
|
} else {
|
|
1438
|
-
throw new RangeError(
|
|
1439
|
-
ns: gs1NS
|
|
1440
|
-
}));
|
|
1416
|
+
throw new RangeError(i18nextGS1.t("IdentificationKey.invalidZeroSuppressedGTIN12AsGTIN14"));
|
|
1441
1417
|
}
|
|
1442
1418
|
break;
|
|
1443
1419
|
|
|
1444
1420
|
default:
|
|
1445
|
-
throw new RangeError(
|
|
1446
|
-
ns: gs1NS
|
|
1447
|
-
}));
|
|
1421
|
+
throw new RangeError(i18nextGS1.t("IdentificationKey.invalidGTINLength"));
|
|
1448
1422
|
}
|
|
1449
1423
|
|
|
1450
1424
|
// Validation applies to the normalized GTIN.
|
|
@@ -1524,7 +1498,7 @@ export class SerializableNumericIdentificationKeyCreator extends Mixin(Serializa
|
|
|
1524
1498
|
*/
|
|
1525
1499
|
private concatenateValidated<T extends TransformerInput<string>>(baseIdentificationKey: string, serialComponentOrComponents: T): TransformerOutput<T, string> {
|
|
1526
1500
|
// TODO Refactor type when https://github.com/microsoft/TypeScript/pull/56941 released.
|
|
1527
|
-
let result: string |
|
|
1501
|
+
let result: string | Iterable<string>;
|
|
1528
1502
|
|
|
1529
1503
|
const serialComponentCreator = this.serialComponentCreator;
|
|
1530
1504
|
const serialComponentValidation = this.serialComponentValidation;
|
|
@@ -1547,9 +1521,10 @@ export class SerializableNumericIdentificationKeyCreator extends Mixin(Serializa
|
|
|
1547
1521
|
if (typeof serialComponentOrComponents !== "object") {
|
|
1548
1522
|
result = validateAndConcatenate(serialComponentOrComponents);
|
|
1549
1523
|
} else {
|
|
1550
|
-
result =
|
|
1524
|
+
result = transformIterable(serialComponentOrComponents, validateAndConcatenate);
|
|
1551
1525
|
}
|
|
1552
1526
|
|
|
1527
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Type determination is handled above.
|
|
1553
1528
|
return result as TransformerOutput<T, string>;
|
|
1554
1529
|
}
|
|
1555
1530
|
|
|
@@ -1629,9 +1604,7 @@ export class NonNumericIdentificationKeyCreator extends Mixin(NonNumericIdentifi
|
|
|
1629
1604
|
minimumLength: 1,
|
|
1630
1605
|
// Maximum reference length has to account for prefix and check character pair.
|
|
1631
1606
|
maximumLength: this.referenceLength,
|
|
1632
|
-
component: () =>
|
|
1633
|
-
ns: gs1NS
|
|
1634
|
-
})
|
|
1607
|
+
component: () => i18nextGS1.t("IdentificationKey.reference")
|
|
1635
1608
|
};
|
|
1636
1609
|
}
|
|
1637
1610
|
|
|
@@ -1653,7 +1626,7 @@ export class NonNumericIdentificationKeyCreator extends Mixin(NonNumericIdentifi
|
|
|
1653
1626
|
*/
|
|
1654
1627
|
create<T extends TransformerInput<string>>(referenceOrReferences: T): TransformerOutput<T, string> {
|
|
1655
1628
|
// TODO Refactor type when https://github.com/microsoft/TypeScript/pull/56941 released.
|
|
1656
|
-
let result: string |
|
|
1629
|
+
let result: string | Iterable<string>;
|
|
1657
1630
|
|
|
1658
1631
|
const referenceCreator = this.referenceCreator;
|
|
1659
1632
|
const referenceValidation = this.referenceValidation;
|
|
@@ -1680,9 +1653,10 @@ export class NonNumericIdentificationKeyCreator extends Mixin(NonNumericIdentifi
|
|
|
1680
1653
|
if (typeof referenceOrReferences !== "object") {
|
|
1681
1654
|
result = validateAndCreate(referenceOrReferences);
|
|
1682
1655
|
} else {
|
|
1683
|
-
result =
|
|
1656
|
+
result = transformIterable(referenceOrReferences, validateAndCreate);
|
|
1684
1657
|
}
|
|
1685
1658
|
|
|
1659
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Type determination is handled above.
|
|
1686
1660
|
return result as TransformerOutput<T, string>;
|
|
1687
1661
|
}
|
|
1688
1662
|
}
|
|
@@ -1770,9 +1744,7 @@ export class PrefixManager {
|
|
|
1770
1744
|
private static readonly GS1_COMPANY_PREFIX_VALIDATION: PrefixValidation = {
|
|
1771
1745
|
minimumLength: PrefixManager.GS1_COMPANY_PREFIX_MINIMUM_LENGTH,
|
|
1772
1746
|
maximumLength: PrefixManager.GS1_COMPANY_PREFIX_MAXIMUM_LENGTH,
|
|
1773
|
-
component: () =>
|
|
1774
|
-
ns: gs1NS
|
|
1775
|
-
})
|
|
1747
|
+
component: () => i18nextGS1.t("Prefix.gs1CompanyPrefix")
|
|
1776
1748
|
};
|
|
1777
1749
|
|
|
1778
1750
|
/**
|
|
@@ -1781,9 +1753,7 @@ export class PrefixManager {
|
|
|
1781
1753
|
private static readonly UPC_COMPANY_PREFIX_AS_GS1_COMPANY_PREFIX_VALIDATION: PrefixValidation = {
|
|
1782
1754
|
minimumLength: PrefixManager.UPC_COMPANY_PREFIX_MINIMUM_LENGTH + 1,
|
|
1783
1755
|
maximumLength: PrefixManager.UPC_COMPANY_PREFIX_MAXIMUM_LENGTH + 1,
|
|
1784
|
-
component: () =>
|
|
1785
|
-
ns: gs1NS
|
|
1786
|
-
})
|
|
1756
|
+
component: () => i18nextGS1.t("Prefix.gs1CompanyPrefix")
|
|
1787
1757
|
};
|
|
1788
1758
|
|
|
1789
1759
|
/**
|
|
@@ -1792,9 +1762,7 @@ export class PrefixManager {
|
|
|
1792
1762
|
private static readonly GS1_8_PREFIX_AS_GS1_COMPANY_PREFIX_VALIDATION: PrefixValidation = {
|
|
1793
1763
|
minimumLength: PrefixManager.GS1_8_PREFIX_MINIMUM_LENGTH + 5,
|
|
1794
1764
|
maximumLength: PrefixManager.GS1_8_PREFIX_MAXIMUM_LENGTH + 5,
|
|
1795
|
-
component: () =>
|
|
1796
|
-
ns: gs1NS
|
|
1797
|
-
})
|
|
1765
|
+
component: () => i18nextGS1.t("Prefix.gs1CompanyPrefix")
|
|
1798
1766
|
};
|
|
1799
1767
|
|
|
1800
1768
|
/**
|
|
@@ -1803,9 +1771,7 @@ export class PrefixManager {
|
|
|
1803
1771
|
private static readonly UPC_COMPANY_PREFIX_VALIDATION: PrefixValidation = {
|
|
1804
1772
|
minimumLength: PrefixManager.UPC_COMPANY_PREFIX_MINIMUM_LENGTH,
|
|
1805
1773
|
maximumLength: PrefixManager.UPC_COMPANY_PREFIX_MAXIMUM_LENGTH,
|
|
1806
|
-
component: () =>
|
|
1807
|
-
ns: gs1NS
|
|
1808
|
-
})
|
|
1774
|
+
component: () => i18nextGS1.t("Prefix.upcCompanyPrefix")
|
|
1809
1775
|
};
|
|
1810
1776
|
|
|
1811
1777
|
/**
|
|
@@ -1814,9 +1780,7 @@ export class PrefixManager {
|
|
|
1814
1780
|
private static readonly GS1_8_PREFIX_VALIDATION: PrefixValidation = {
|
|
1815
1781
|
minimumLength: PrefixManager.GS1_8_PREFIX_MINIMUM_LENGTH,
|
|
1816
1782
|
maximumLength: PrefixManager.GS1_8_PREFIX_MAXIMUM_LENGTH,
|
|
1817
|
-
component: () =>
|
|
1818
|
-
ns: gs1NS
|
|
1819
|
-
})
|
|
1783
|
+
component: () => i18nextGS1.t("Prefix.gs18Prefix")
|
|
1820
1784
|
};
|
|
1821
1785
|
|
|
1822
1786
|
/**
|
|
@@ -2054,32 +2018,24 @@ export class PrefixManager {
|
|
|
2054
2018
|
baseValidation = PrefixManager.GS1_COMPANY_PREFIX_VALIDATION;
|
|
2055
2019
|
} else if (!prefix.startsWith("00000")) {
|
|
2056
2020
|
if (!allowUPCCompanyPrefix) {
|
|
2057
|
-
throw new RangeError(
|
|
2058
|
-
ns: gs1NS
|
|
2059
|
-
}));
|
|
2021
|
+
throw new RangeError(i18nextGS1.t("Prefix.gs1CompanyPrefixCantStartWith0"));
|
|
2060
2022
|
}
|
|
2061
2023
|
|
|
2062
2024
|
baseValidation = PrefixManager.UPC_COMPANY_PREFIX_AS_GS1_COMPANY_PREFIX_VALIDATION;
|
|
2063
2025
|
} else if (!prefix.startsWith("000000")) {
|
|
2064
2026
|
if (!allowGS18Prefix) {
|
|
2065
|
-
throw new RangeError(
|
|
2066
|
-
ns: gs1NS
|
|
2067
|
-
}));
|
|
2027
|
+
throw new RangeError(i18nextGS1.t("Prefix.gs1CompanyPrefixCantStartWith00000"));
|
|
2068
2028
|
}
|
|
2069
2029
|
|
|
2070
2030
|
baseValidation = PrefixManager.GS1_8_PREFIX_AS_GS1_COMPANY_PREFIX_VALIDATION;
|
|
2071
2031
|
} else {
|
|
2072
|
-
throw new RangeError(
|
|
2073
|
-
ns: gs1NS
|
|
2074
|
-
}));
|
|
2032
|
+
throw new RangeError(i18nextGS1.t("Prefix.gs1CompanyPrefixCantStartWith000000"));
|
|
2075
2033
|
}
|
|
2076
2034
|
break;
|
|
2077
2035
|
|
|
2078
2036
|
case PrefixType.UPCCompanyPrefix:
|
|
2079
2037
|
if (prefix.startsWith("0000")) {
|
|
2080
|
-
throw new RangeError(
|
|
2081
|
-
ns: gs1NS
|
|
2082
|
-
}));
|
|
2038
|
+
throw new RangeError(i18nextGS1.t("Prefix.upcCompanyPrefixCantStartWith0000"));
|
|
2083
2039
|
}
|
|
2084
2040
|
|
|
2085
2041
|
baseValidation = PrefixManager.UPC_COMPANY_PREFIX_VALIDATION;
|
|
@@ -2087,9 +2043,7 @@ export class PrefixManager {
|
|
|
2087
2043
|
|
|
2088
2044
|
case PrefixType.GS18Prefix:
|
|
2089
2045
|
if (prefix.startsWith("0")) {
|
|
2090
|
-
throw new RangeError(
|
|
2091
|
-
ns: gs1NS
|
|
2092
|
-
}));
|
|
2046
|
+
throw new RangeError(i18nextGS1.t("Prefix.gs18PrefixCantStartWith0"));
|
|
2093
2047
|
}
|
|
2094
2048
|
|
|
2095
2049
|
baseValidation = PrefixManager.GS1_8_PREFIX_VALIDATION;
|
|
@@ -2123,12 +2077,12 @@ export class PrefixManager {
|
|
|
2123
2077
|
* Identification key creator.
|
|
2124
2078
|
*/
|
|
2125
2079
|
private getIdentificationKeyCreator<T extends IdentificationKeyCreator>(identificationKeyType: IdentificationKeyType, constructorCallback: () => T): T {
|
|
2080
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Type is paired with constructor callback.
|
|
2126
2081
|
let creator = this._identificationKeyCreatorsMap.get(identificationKeyType) as (T | undefined);
|
|
2127
2082
|
|
|
2128
2083
|
if (creator === undefined) {
|
|
2129
2084
|
if (this.prefixType === PrefixType.GS18Prefix && identificationKeyType !== IdentificationKeyType.GTIN) {
|
|
2130
|
-
throw new RangeError(
|
|
2131
|
-
ns: gs1NS,
|
|
2085
|
+
throw new RangeError(i18nextGS1.t("Prefix.identificationKeyTypeNotSupportedByGS18Prefix", {
|
|
2132
2086
|
identificationKeyType
|
|
2133
2087
|
}));
|
|
2134
2088
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright © 2024-2025 Dolphin Data Development Ltd. and AIDC Toolkit
|
|
3
|
+
* contributors
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* https://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
export * from "./locale/i18n.js";
|
|
18
|
+
export * from "./character-set.js";
|
|
3
19
|
export * from "./check.js";
|
|
4
20
|
export * from "./idkey.js";
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export const localeStrings = {
|
|
2
2
|
Check: {
|
|
3
|
+
lengthOfStringForPriceOrWeightMustBeExactly: "Length {{length}} of string for price or weight sum must be exactly {{exactLength}}",
|
|
4
|
+
priceOrWeightComponent: "price or weight",
|
|
3
5
|
lengthOfStringForCheckCharacterPairMustBeLessThanOrEqualTo: "Length {{length}} of string for check character pair must be less than or equal to {{maximumLength}}"
|
|
4
6
|
},
|
|
5
7
|
IdentificationKey: {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export const localeStrings = {
|
|
2
2
|
Check: {
|
|
3
|
+
lengthOfStringForPriceOrWeightMustBeExactly: "La longueur {{longueur}} de la chaîne pour le prix ou la somme du poids doit être exactement {{exactLength}}",
|
|
4
|
+
priceOrWeightComponent: "prix ou poids",
|
|
3
5
|
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
6
|
},
|
|
5
7
|
IdentificationKey: {
|
package/src/locale/i18n.ts
CHANGED
|
@@ -1,12 +1,46 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import { i18nAssertValidResources, i18nCoreInit, type I18NEnvironment } from "@aidc-toolkit/core";
|
|
2
|
+
import { i18nUtilityInit, utilityResources } from "@aidc-toolkit/utility";
|
|
3
|
+
import i18next, { type i18n } from "i18next";
|
|
4
|
+
import { localeStrings as enLocaleStrings } from "./en/locale-strings.js";
|
|
5
|
+
import { localeStrings as frLocaleStrings } from "./fr/locale-strings.js";
|
|
4
6
|
|
|
5
7
|
export const gs1NS = "aidct_gs1";
|
|
6
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Locale strings type is extracted from the English locale strings object.
|
|
11
|
+
*/
|
|
12
|
+
export type GS1LocaleStrings = typeof enLocaleStrings;
|
|
13
|
+
|
|
7
14
|
i18nAssertValidResources(enLocaleStrings, "fr", frLocaleStrings);
|
|
8
15
|
|
|
9
|
-
|
|
10
|
-
|
|
16
|
+
/**
|
|
17
|
+
* GS1 resources.
|
|
18
|
+
*/
|
|
19
|
+
export const gs1Resources = {
|
|
20
|
+
en: {
|
|
21
|
+
aidct_gs1: enLocaleStrings
|
|
22
|
+
},
|
|
23
|
+
fr: {
|
|
24
|
+
aidct_gs1: frLocaleStrings
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// Explicit type is necessary to work around bug in type discovery with linked packages.
|
|
29
|
+
export const i18nextGS1: i18n = i18next.createInstance();
|
|
11
30
|
|
|
12
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Initialize internationalization.
|
|
33
|
+
*
|
|
34
|
+
* @param environment
|
|
35
|
+
* Environment in which the application is running.
|
|
36
|
+
*
|
|
37
|
+
* @param debug
|
|
38
|
+
* Debug setting.
|
|
39
|
+
*
|
|
40
|
+
* @returns
|
|
41
|
+
* Void promise.
|
|
42
|
+
*/
|
|
43
|
+
export async function i18nGS1Init(environment: I18NEnvironment, debug = false): Promise<void> {
|
|
44
|
+
await i18nUtilityInit(environment, debug);
|
|
45
|
+
await i18nCoreInit(i18nextGS1, environment, debug, gs1NS, utilityResources, gs1Resources);
|
|
46
|
+
}
|
package/src/locale/i18next.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { UtilityLocaleStrings } from "@aidc-toolkit/utility";
|
|
2
|
+
import type { GS1LocaleStrings } from "./i18n.js";
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Internationalization module.
|
|
@@ -8,9 +9,10 @@ declare module "i18next" {
|
|
|
8
9
|
* Custom type options for this package.
|
|
9
10
|
*/
|
|
10
11
|
interface CustomTypeOptions {
|
|
12
|
+
defaultNS: "aidct_gs1";
|
|
11
13
|
resources: {
|
|
12
|
-
|
|
13
|
-
aidct_gs1:
|
|
14
|
+
aidct_utility: UtilityLocaleStrings;
|
|
15
|
+
aidct_gs1: GS1LocaleStrings;
|
|
14
16
|
};
|
|
15
17
|
}
|
|
16
18
|
}
|
package/test/check.test.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { I18NEnvironment
|
|
1
|
+
import { I18NEnvironment } from "@aidc-toolkit/core";
|
|
2
2
|
import { NUMERIC_CREATOR } from "@aidc-toolkit/utility";
|
|
3
3
|
import { describe, expect, test } from "vitest";
|
|
4
4
|
import {
|
|
@@ -8,10 +8,11 @@ import {
|
|
|
8
8
|
fiveDigitPriceWeightCheckDigit,
|
|
9
9
|
fourDigitPriceWeightCheckDigit,
|
|
10
10
|
hasValidCheckCharacterPair,
|
|
11
|
-
hasValidCheckDigit
|
|
11
|
+
hasValidCheckDigit,
|
|
12
|
+
i18nGS1Init
|
|
12
13
|
} from "../src/index.js";
|
|
13
14
|
|
|
14
|
-
await
|
|
15
|
+
await i18nGS1Init(I18NEnvironment.CLI, true);
|
|
15
16
|
|
|
16
17
|
describe("Check digit", () => {
|
|
17
18
|
const testNumericString = "1234567890";
|
|
@@ -93,8 +94,8 @@ describe("Price/weight check digit", () => {
|
|
|
93
94
|
testFourDigitPriceWeightCheckDigit("9012");
|
|
94
95
|
|
|
95
96
|
expect(() => fourDigitPriceWeightCheckDigit("l234")).toThrow("Invalid character 'l' at position 1");
|
|
96
|
-
expect(() => fourDigitPriceWeightCheckDigit("123")).toThrow("
|
|
97
|
-
expect(() => fourDigitPriceWeightCheckDigit("12345")).toThrow("
|
|
97
|
+
expect(() => fourDigitPriceWeightCheckDigit("123")).toThrow("Length 3 of string for price or weight sum must be exactly 4");
|
|
98
|
+
expect(() => fourDigitPriceWeightCheckDigit("12345")).toThrow("Length 5 of string for price or weight sum must be exactly 4");
|
|
98
99
|
});
|
|
99
100
|
|
|
100
101
|
test("Five-digit", () => {
|
|
@@ -109,9 +110,9 @@ describe("Price/weight check digit", () => {
|
|
|
109
110
|
testFiveDigitPriceWeightCheckDigit("89012");
|
|
110
111
|
testFiveDigitPriceWeightCheckDigit("90123");
|
|
111
112
|
|
|
112
|
-
expect(() => fiveDigitPriceWeightCheckDigit("l2345")).toThrow("Invalid character 'l' at position 1");
|
|
113
|
-
expect(() => fiveDigitPriceWeightCheckDigit("1234")).toThrow("
|
|
114
|
-
expect(() => fiveDigitPriceWeightCheckDigit("123456")).toThrow("
|
|
113
|
+
expect(() => fiveDigitPriceWeightCheckDigit("l2345")).toThrow("Invalid character 'l' at position 1 of price or weight");
|
|
114
|
+
expect(() => fiveDigitPriceWeightCheckDigit("1234")).toThrow("Length 4 of string for price or weight sum must be exactly 5");
|
|
115
|
+
expect(() => fiveDigitPriceWeightCheckDigit("123456")).toThrow("Length 6 of string for price or weight sum must be exactly 5");
|
|
115
116
|
});
|
|
116
117
|
});
|
|
117
118
|
|