@aidc-toolkit/gs1 0.9.19-beta → 0.9.21-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/character-set.d.ts +4 -4
- package/dist/character-set.d.ts.map +1 -1
- package/dist/character-set.js +7 -7
- package/dist/character-set.js.map +1 -1
- package/dist/gtin-creator.d.ts +68 -0
- package/dist/gtin-creator.d.ts.map +1 -0
- package/dist/gtin-creator.js +158 -0
- package/dist/gtin-creator.js.map +1 -0
- package/dist/gtin-validator.d.ts +202 -0
- package/dist/gtin-validator.d.ts.map +1 -0
- package/dist/gtin-validator.js +470 -0
- package/dist/gtin-validator.js.map +1 -0
- package/dist/identifier-creator.d.ts +72 -0
- package/dist/identifier-creator.d.ts.map +1 -0
- package/dist/identifier-creator.js +50 -0
- package/dist/identifier-creator.js.map +1 -0
- package/dist/identifier-type.d.ts +58 -0
- package/dist/identifier-type.d.ts.map +1 -0
- package/dist/identifier-type.js +54 -0
- package/dist/identifier-type.js.map +1 -0
- package/dist/identifier-validator.d.ts +174 -0
- package/dist/identifier-validator.d.ts.map +1 -0
- package/dist/identifier-validator.js +145 -0
- package/dist/identifier-validator.js.map +1 -0
- package/dist/index.d.ts +16 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -1
- package/dist/index.js.map +1 -1
- package/dist/locale/en/locale-strings.d.ts +3 -3
- package/dist/locale/en/locale-strings.js +3 -3
- package/dist/locale/en/locale-strings.js.map +1 -1
- package/dist/locale/fr/locale-strings.d.ts +3 -3
- package/dist/locale/fr/locale-strings.js +3 -3
- package/dist/locale/fr/locale-strings.js.map +1 -1
- package/dist/non-gtin-numeric-identifier-creator.d.ts +30 -0
- package/dist/non-gtin-numeric-identifier-creator.d.ts.map +1 -0
- package/dist/non-gtin-numeric-identifier-creator.js +30 -0
- package/dist/non-gtin-numeric-identifier-creator.js.map +1 -0
- package/dist/non-gtin-numeric-identifier-validator.d.ts +41 -0
- package/dist/non-gtin-numeric-identifier-validator.d.ts.map +1 -0
- package/dist/non-gtin-numeric-identifier-validator.js +40 -0
- package/dist/non-gtin-numeric-identifier-validator.js.map +1 -0
- package/dist/non-numeric-identifier-creator.d.ts +55 -0
- package/dist/non-numeric-identifier-creator.d.ts.map +1 -0
- package/dist/non-numeric-identifier-creator.js +93 -0
- package/dist/non-numeric-identifier-creator.js.map +1 -0
- package/dist/non-numeric-identifier-validator.d.ts +78 -0
- package/dist/non-numeric-identifier-validator.d.ts.map +1 -0
- package/dist/non-numeric-identifier-validator.js +95 -0
- package/dist/non-numeric-identifier-validator.js.map +1 -0
- package/dist/numeric-identifier-creator.d.ts +121 -0
- package/dist/numeric-identifier-creator.d.ts.map +1 -0
- package/dist/numeric-identifier-creator.js +135 -0
- package/dist/numeric-identifier-creator.js.map +1 -0
- package/dist/numeric-identifier-validator.d.ts +76 -0
- package/dist/numeric-identifier-validator.d.ts.map +1 -0
- package/dist/numeric-identifier-validator.js +84 -0
- package/dist/numeric-identifier-validator.js.map +1 -0
- package/dist/prefix-manager.d.ts +224 -0
- package/dist/prefix-manager.d.ts.map +1 -0
- package/dist/prefix-manager.js +369 -0
- package/dist/prefix-manager.js.map +1 -0
- package/dist/prefix-provider.d.ts +27 -0
- package/dist/prefix-provider.d.ts.map +1 -0
- package/dist/prefix-provider.js +2 -0
- package/dist/prefix-provider.js.map +1 -0
- package/dist/prefix-type.d.ts +22 -0
- package/dist/prefix-type.d.ts.map +1 -0
- package/dist/prefix-type.js +18 -0
- package/dist/prefix-type.js.map +1 -0
- package/dist/prefix-validator.d.ts +58 -0
- package/dist/prefix-validator.d.ts.map +1 -0
- package/dist/prefix-validator.js +154 -0
- package/dist/prefix-validator.js.map +1 -0
- package/dist/serializable-numeric-identifier-creator.d.ts +86 -0
- package/dist/serializable-numeric-identifier-creator.d.ts.map +1 -0
- package/dist/serializable-numeric-identifier-creator.js +116 -0
- package/dist/serializable-numeric-identifier-creator.js.map +1 -0
- package/dist/serializable-numeric-identifier-validator.d.ts +79 -0
- package/dist/serializable-numeric-identifier-validator.d.ts.map +1 -0
- package/dist/serializable-numeric-identifier-validator.js +99 -0
- package/dist/serializable-numeric-identifier-validator.js.map +1 -0
- package/gs1.iml +4 -1
- package/package.json +2 -3
- package/src/character-set.ts +7 -7
- package/src/gtin-creator.ts +195 -0
- package/src/gtin-validator.ts +564 -0
- package/src/identifier-creator.ts +97 -0
- package/src/identifier-type.ts +69 -0
- package/src/identifier-validator.ts +235 -0
- package/src/index.ts +16 -1
- package/src/locale/en/locale-strings.ts +3 -3
- package/src/locale/fr/locale-strings.ts +3 -3
- package/src/non-gtin-numeric-identifier-creator.ts +33 -0
- package/src/non-gtin-numeric-identifier-validator.ts +54 -0
- package/src/non-numeric-identifier-creator.ts +111 -0
- package/src/non-numeric-identifier-validator.ts +128 -0
- package/src/numeric-identifier-creator.ts +200 -0
- package/src/numeric-identifier-validator.ts +128 -0
- package/src/prefix-manager.ts +446 -0
- package/src/prefix-provider.ts +31 -0
- package/src/prefix-type.ts +24 -0
- package/src/prefix-validator.ts +191 -0
- package/src/serializable-numeric-identifier-creator.ts +128 -0
- package/src/serializable-numeric-identifier-validator.ts +124 -0
- package/test/check.test.ts +0 -4
- package/test/creator.test.ts +30 -0
- package/test/gtin-creator.ts +239 -0
- package/test/gtin-validator.test.ts +149 -0
- package/test/identifier-creator.ts +84 -0
- package/test/identifier-validator.ts +8 -0
- package/test/non-gtin-numeric-identifier-creator.ts +98 -0
- package/test/non-gtin-numeric-identifier-validator.ts +6 -0
- package/test/non-numeric-identifier-validator.ts +24 -0
- package/test/numeric-identifier-creator.ts +132 -0
- package/test/numeric-identifier-validator.ts +23 -0
- package/test/prefix-manager.test.ts +112 -0
- package/test/serializable-numeric-identifier-creator.ts +56 -0
- package/test/serializable-numeric-identifier-validator.ts +24 -0
- package/test/setup.ts +4 -0
- package/test/sparse.test.ts +56 -0
- package/test/utility.ts +22 -0
- package/test/validator.test.ts +52 -0
- package/test/variable-measure-rcn.test.ts +201 -0
- package/vitest.config.ts +7 -0
- package/dist/idkey.d.ts +0 -1346
- package/dist/idkey.d.ts.map +0 -1
- package/dist/idkey.js +0 -2024
- package/dist/idkey.js.map +0 -1
- package/src/idkey.ts +0 -2532
- package/test/idkey.test.ts +0 -1247
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { mapIterable, type TransformerInput, type TransformerOutput } from "@aidc-toolkit/utility";
|
|
2
|
+
import { Mixin } from "ts-mixer";
|
|
3
|
+
import type { IdentifierType } from "./identifier-type.js";
|
|
4
|
+
import type { ContentCharacterSet } from "./identifier-validator.js";
|
|
5
|
+
import { AbstractNumericIdentifierCreator } from "./numeric-identifier-creator.js";
|
|
6
|
+
import type { PrefixProvider } from "./prefix-provider";
|
|
7
|
+
import { SerializableNumericIdentifierValidator } from "./serializable-numeric-identifier-validator.js";
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Serializable numeric identifier creator.
|
|
11
|
+
*/
|
|
12
|
+
export class SerializableNumericIdentifierCreator extends Mixin(SerializableNumericIdentifierValidator, AbstractNumericIdentifierCreator) {
|
|
13
|
+
/**
|
|
14
|
+
* Constructor. Typically called internally by a prefix manager but may be called by other code with another prefix
|
|
15
|
+
* provider type.
|
|
16
|
+
*
|
|
17
|
+
* @param prefixProvider
|
|
18
|
+
* Prefix provider.
|
|
19
|
+
*
|
|
20
|
+
* @param identifierType
|
|
21
|
+
* Identifier type.
|
|
22
|
+
*
|
|
23
|
+
* @param length
|
|
24
|
+
* Length.
|
|
25
|
+
*
|
|
26
|
+
* @param serialComponentLength
|
|
27
|
+
* Serial component length.
|
|
28
|
+
*
|
|
29
|
+
* @param serialComponentCharacterSet
|
|
30
|
+
* Serial component character set.
|
|
31
|
+
*/
|
|
32
|
+
constructor(prefixProvider: PrefixProvider, identifierType: IdentifierType, length: number, serialComponentLength: number, serialComponentCharacterSet: ContentCharacterSet) {
|
|
33
|
+
super(identifierType, length, serialComponentLength, serialComponentCharacterSet);
|
|
34
|
+
|
|
35
|
+
this.init(prefixProvider, prefixProvider.gs1CompanyPrefix);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Concatenate a validated base identifier with serial component(s).
|
|
40
|
+
*
|
|
41
|
+
* @template TTransformerInput
|
|
42
|
+
* Transformer input type.
|
|
43
|
+
*
|
|
44
|
+
* @param baseIdentifier
|
|
45
|
+
* Base identifier.
|
|
46
|
+
*
|
|
47
|
+
* @param serialComponentOrComponents
|
|
48
|
+
* Serial component(s).
|
|
49
|
+
*
|
|
50
|
+
* @returns
|
|
51
|
+
* Serialized identifier(s).
|
|
52
|
+
*/
|
|
53
|
+
private concatenateValidated<TTransformerInput extends TransformerInput<string>>(baseIdentifier: string, serialComponentOrComponents: TTransformerInput): TransformerOutput<TTransformerInput, string> {
|
|
54
|
+
// TODO Refactor type when https://github.com/microsoft/TypeScript/pull/56941 released.
|
|
55
|
+
let result: string | Iterable<string>;
|
|
56
|
+
|
|
57
|
+
const serialComponentCreator = this.serialComponentCreator;
|
|
58
|
+
const serialComponentValidation = this.serialComponentValidation;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Validate a serial component and concatenate it to the base identifier.
|
|
62
|
+
*
|
|
63
|
+
* @param serialComponent
|
|
64
|
+
* Serial component.
|
|
65
|
+
*
|
|
66
|
+
* @returns
|
|
67
|
+
* Serialized identifier.
|
|
68
|
+
*/
|
|
69
|
+
function validateAndConcatenate(serialComponent: string): string {
|
|
70
|
+
serialComponentCreator.validate(serialComponent, serialComponentValidation);
|
|
71
|
+
|
|
72
|
+
return baseIdentifier + serialComponent;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (typeof serialComponentOrComponents !== "object") {
|
|
76
|
+
result = validateAndConcatenate(serialComponentOrComponents);
|
|
77
|
+
} else {
|
|
78
|
+
result = mapIterable(serialComponentOrComponents, validateAndConcatenate);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Type determination is handled above.
|
|
82
|
+
return result as TransformerOutput<TTransformerInput, string>;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Create serialized identifier(s) with a reference based on a numeric value concatenated with serial component(s).
|
|
87
|
+
* The value is converted to a reference of the appropriate length using a numeric creator.
|
|
88
|
+
*
|
|
89
|
+
* @template TTransformerInput
|
|
90
|
+
* Transformer input type.
|
|
91
|
+
*
|
|
92
|
+
* @param value
|
|
93
|
+
* Numeric value of the reference.
|
|
94
|
+
*
|
|
95
|
+
* @param serialComponentOrComponents
|
|
96
|
+
* Serial component(s).
|
|
97
|
+
*
|
|
98
|
+
* @param sparse
|
|
99
|
+
* If true, the value is mapped to a sparse sequence resistant to discovery. Default is false.
|
|
100
|
+
*
|
|
101
|
+
* @returns
|
|
102
|
+
* Serialized identifiers.
|
|
103
|
+
*/
|
|
104
|
+
createSerialized<TTransformerInput extends TransformerInput<string>>(value: number, serialComponentOrComponents: TTransformerInput, sparse?: boolean): TransformerOutput<TTransformerInput, string> {
|
|
105
|
+
return this.concatenateValidated(this.create(value, sparse), serialComponentOrComponents);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Concatenate a base identifier with serial component(s).
|
|
110
|
+
*
|
|
111
|
+
* @template TTransformerInput
|
|
112
|
+
* Transformer input type.
|
|
113
|
+
*
|
|
114
|
+
* @param baseIdentifier
|
|
115
|
+
* Base identifier.
|
|
116
|
+
*
|
|
117
|
+
* @param serialComponentOrComponents
|
|
118
|
+
* Serial component(s).
|
|
119
|
+
*
|
|
120
|
+
* @returns
|
|
121
|
+
* Serialized identifier(s).
|
|
122
|
+
*/
|
|
123
|
+
concatenate<TTransformerInput extends TransformerInput<string>>(baseIdentifier: string, serialComponentOrComponents: TTransformerInput): TransformerOutput<TTransformerInput, string> {
|
|
124
|
+
this.validate(baseIdentifier);
|
|
125
|
+
|
|
126
|
+
return this.concatenateValidated(baseIdentifier, serialComponentOrComponents);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import type { CharacterSetCreator, CharacterSetValidation } from "@aidc-toolkit/utility";
|
|
2
|
+
import { type IdentifierType, IdentifierTypes } from "./identifier-type.js";
|
|
3
|
+
import { type ContentCharacterSet, ContentCharacterSets, type IdentifierValidation } from "./identifier-validator.js";
|
|
4
|
+
import { i18nextGS1 } from "./locale/i18n.js";
|
|
5
|
+
import {
|
|
6
|
+
type NonGTINNumericIdentifierType,
|
|
7
|
+
NonGTINNumericIdentifierValidator
|
|
8
|
+
} from "./non-gtin-numeric-identifier-validator.js";
|
|
9
|
+
import { LeaderTypes } from "./numeric-identifier-validator.js";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Serializable numeric identifier type.
|
|
13
|
+
*/
|
|
14
|
+
export type SerializableNumericIdentifierType = Exclude<NonGTINNumericIdentifierType, typeof IdentifierTypes.GLN | typeof IdentifierTypes.SSCC | typeof IdentifierTypes.GSRN | typeof IdentifierTypes.GSIN>;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Serializable numeric identifier validator. Validates both serialized and non-serialized forms of
|
|
18
|
+
* numeric identifiers that support serialization.
|
|
19
|
+
*/
|
|
20
|
+
export class SerializableNumericIdentifierValidator extends NonGTINNumericIdentifierValidator {
|
|
21
|
+
/**
|
|
22
|
+
* Serial component length.
|
|
23
|
+
*/
|
|
24
|
+
private readonly _serialComponentLength: number;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Serial component character set.
|
|
28
|
+
*/
|
|
29
|
+
private readonly _serialComponentCharacterSet: ContentCharacterSet;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Serial component validation parameters.
|
|
33
|
+
*/
|
|
34
|
+
private readonly _serialComponentValidation: CharacterSetValidation;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Serial component creator.
|
|
38
|
+
*/
|
|
39
|
+
private readonly _serialComponentCreator: CharacterSetCreator;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Constructor.
|
|
43
|
+
*
|
|
44
|
+
* @param identifierType
|
|
45
|
+
* Identifier type.
|
|
46
|
+
*
|
|
47
|
+
* @param length
|
|
48
|
+
* Length.
|
|
49
|
+
*
|
|
50
|
+
* @param serialComponentLength
|
|
51
|
+
* Serial component length.
|
|
52
|
+
*
|
|
53
|
+
* @param serialComponentCharacterSet
|
|
54
|
+
* Serial component character set.
|
|
55
|
+
*/
|
|
56
|
+
constructor(identifierType: IdentifierType, length: number, serialComponentLength: number, serialComponentCharacterSet: ContentCharacterSet) {
|
|
57
|
+
super(identifierType, length, LeaderTypes.None);
|
|
58
|
+
|
|
59
|
+
this._serialComponentLength = serialComponentLength;
|
|
60
|
+
this._serialComponentCharacterSet = serialComponentCharacterSet;
|
|
61
|
+
|
|
62
|
+
this._serialComponentValidation = {
|
|
63
|
+
minimumLength: 1,
|
|
64
|
+
maximumLength: serialComponentLength,
|
|
65
|
+
component: () => i18nextGS1.t("Identifier.serialComponent")
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
this._serialComponentCreator = SerializableNumericIdentifierValidator.creatorFor(serialComponentCharacterSet);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Get the serial component length.
|
|
73
|
+
*/
|
|
74
|
+
get serialComponentLength(): number {
|
|
75
|
+
return this._serialComponentLength;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Get the serial component character set.
|
|
80
|
+
*/
|
|
81
|
+
get serialComponentCharacterSet(): ContentCharacterSet {
|
|
82
|
+
return this._serialComponentCharacterSet;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Get the serial component validation parameters.
|
|
87
|
+
*/
|
|
88
|
+
protected get serialComponentValidation(): CharacterSetValidation {
|
|
89
|
+
return this._serialComponentValidation;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Get the serial component creator.
|
|
94
|
+
*/
|
|
95
|
+
get serialComponentCreator(): CharacterSetCreator {
|
|
96
|
+
return this._serialComponentCreator;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* @inheritDoc
|
|
101
|
+
*/
|
|
102
|
+
override validate(identifier: string, validation?: IdentifierValidation): void {
|
|
103
|
+
super.validate(identifier.substring(0, this.length), validation);
|
|
104
|
+
|
|
105
|
+
if (identifier.length > this.length) {
|
|
106
|
+
this.serialComponentCreator.validate(identifier.substring(this.length), this._serialComponentValidation);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* GRAI validator.
|
|
113
|
+
*/
|
|
114
|
+
export const GRAI_VALIDATOR = new SerializableNumericIdentifierValidator(IdentifierTypes.GRAI, 13, 16, ContentCharacterSets.AI82);
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* GDTI validator.
|
|
118
|
+
*/
|
|
119
|
+
export const GDTI_VALIDATOR = new SerializableNumericIdentifierValidator(IdentifierTypes.GDTI, 13, 17, ContentCharacterSets.AI82);
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* GCN validator.
|
|
123
|
+
*/
|
|
124
|
+
export const GCN_VALIDATOR = new SerializableNumericIdentifierValidator(IdentifierTypes.GCN, 13, 12, ContentCharacterSets.Numeric);
|
package/test/check.test.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { I18nEnvironment } from "@aidc-toolkit/core";
|
|
2
1
|
import { NUMERIC_CREATOR } from "@aidc-toolkit/utility";
|
|
3
2
|
import { describe, expect, test } from "vitest";
|
|
4
3
|
import {
|
|
@@ -7,13 +6,10 @@ import {
|
|
|
7
6
|
checkDigitSum,
|
|
8
7
|
hasValidCheckCharacterPair,
|
|
9
8
|
hasValidCheckDigit,
|
|
10
|
-
i18nGS1Init,
|
|
11
9
|
isValidPriceOrWeightCheckDigit,
|
|
12
10
|
priceOrWeightCheckDigit
|
|
13
11
|
} from "../src";
|
|
14
12
|
|
|
15
|
-
await i18nGS1Init(I18nEnvironment.CLI, true);
|
|
16
|
-
|
|
17
13
|
describe("Check digit", () => {
|
|
18
14
|
const testNumericString = "1234567890";
|
|
19
15
|
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { describe } from "vitest";
|
|
2
|
+
import { PrefixManager, PrefixTypes } from "../src";
|
|
3
|
+
import { testGTINCreator } from "./gtin-creator.js";
|
|
4
|
+
import {
|
|
5
|
+
testNonGTINNumericIdentifierCreator,
|
|
6
|
+
testNonNumericIdentifierCreator
|
|
7
|
+
} from "./non-gtin-numeric-identifier-creator.js";
|
|
8
|
+
import { testSerializableNumericIdentifierCreator } from "./serializable-numeric-identifier-creator.js";
|
|
9
|
+
|
|
10
|
+
describe("Creators", () => {
|
|
11
|
+
testGTINCreator(PrefixManager.get(PrefixTypes.GS1CompanyPrefix, "952123456").gtinCreator);
|
|
12
|
+
testGTINCreator(PrefixManager.get(PrefixTypes.UPCCompanyPrefix, "61414112").gtinCreator);
|
|
13
|
+
testGTINCreator(PrefixManager.get(PrefixTypes.GS18Prefix, "9521").gtinCreator);
|
|
14
|
+
|
|
15
|
+
// Different lengths required to balance testing completeness and run time.
|
|
16
|
+
const shortPrefixManager = PrefixManager.get(PrefixTypes.GS1CompanyPrefix, "952123456");
|
|
17
|
+
const longPrefixManager = PrefixManager.get(PrefixTypes.GS1CompanyPrefix, "952123456789");
|
|
18
|
+
|
|
19
|
+
testNonGTINNumericIdentifierCreator(shortPrefixManager.glnCreator);
|
|
20
|
+
testNonGTINNumericIdentifierCreator(longPrefixManager.ssccCreator);
|
|
21
|
+
testSerializableNumericIdentifierCreator(shortPrefixManager.graiCreator);
|
|
22
|
+
testNonNumericIdentifierCreator(shortPrefixManager.giaiCreator);
|
|
23
|
+
testNonGTINNumericIdentifierCreator(longPrefixManager.gsrnCreator);
|
|
24
|
+
testSerializableNumericIdentifierCreator(shortPrefixManager.gdtiCreator);
|
|
25
|
+
testNonNumericIdentifierCreator(shortPrefixManager.gincCreator);
|
|
26
|
+
testNonGTINNumericIdentifierCreator(longPrefixManager.gsinCreator);
|
|
27
|
+
testSerializableNumericIdentifierCreator(shortPrefixManager.gcnCreator);
|
|
28
|
+
testNonNumericIdentifierCreator(shortPrefixManager.cpidCreator);
|
|
29
|
+
testNonNumericIdentifierCreator(shortPrefixManager.gmnCreator);
|
|
30
|
+
});
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { CharacterSetCreator, Sequence } from "@aidc-toolkit/utility";
|
|
2
|
+
import { expect, test } from "vitest";
|
|
3
|
+
import { type GTINCreator, GTINTypes, GTINValidator, hasValidCheckDigit, PrefixTypes } from "../src";
|
|
4
|
+
import { testNumericIdentifierCreator } from "./numeric-identifier-creator.js";
|
|
5
|
+
|
|
6
|
+
export function testGTINCreator(creator: GTINCreator): void {
|
|
7
|
+
testNumericIdentifierCreator(creator, () => {
|
|
8
|
+
test("Length", () => {
|
|
9
|
+
switch (creator.prefixType) {
|
|
10
|
+
case PrefixTypes.GS1CompanyPrefix:
|
|
11
|
+
expect(creator.length).toBe(13);
|
|
12
|
+
break;
|
|
13
|
+
|
|
14
|
+
case PrefixTypes.UPCCompanyPrefix:
|
|
15
|
+
expect(creator.length).toBe(12);
|
|
16
|
+
break;
|
|
17
|
+
|
|
18
|
+
case PrefixTypes.GS18Prefix:
|
|
19
|
+
expect(creator.length).toBe(8);
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
}, () => {
|
|
24
|
+
const gs1CompanyPrefix = creator.prefixProvider.gs1CompanyPrefix;
|
|
25
|
+
const prefix = creator.prefix;
|
|
26
|
+
const prefixLength = prefix.length;
|
|
27
|
+
const prefixSubstringStart = 14 - creator.length;
|
|
28
|
+
const prefixSubstringEnd = prefixSubstringStart + prefixLength;
|
|
29
|
+
const referenceLength = creator.length - prefixLength - 1;
|
|
30
|
+
const referenceCount = Number(CharacterSetCreator.powerOf10(referenceLength));
|
|
31
|
+
const referenceSubstringStart = prefixSubstringEnd;
|
|
32
|
+
const referenceSubstringEnd = referenceSubstringStart + referenceLength;
|
|
33
|
+
|
|
34
|
+
function validate(gtin: string, index: number, sparse: boolean): void {
|
|
35
|
+
expect(() => {
|
|
36
|
+
GTINValidator.validateGTIN14(gtin);
|
|
37
|
+
}).not.toThrow(RangeError);
|
|
38
|
+
expect(gtin).toBe(creator.createGTIN14("5", index, sparse));
|
|
39
|
+
|
|
40
|
+
expect(gtin.length).toBe(14);
|
|
41
|
+
expect(gtin.charAt(0)).toBe("5");
|
|
42
|
+
expect(gtin.substring(1, prefixSubstringEnd)).toBe(gs1CompanyPrefix);
|
|
43
|
+
expect(gtin.substring(prefixSubstringStart, prefixSubstringEnd)).toBe(prefix);
|
|
44
|
+
expect(hasValidCheckDigit(gtin)).toBe(true);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
test("GTIN-14 straight", () => {
|
|
48
|
+
let index = 0;
|
|
49
|
+
|
|
50
|
+
for (const gtin of creator.createGTIN14("5", new Sequence(0, referenceCount))) {
|
|
51
|
+
expect(Number(gtin.substring(referenceSubstringStart, referenceSubstringEnd))).toBe(index);
|
|
52
|
+
|
|
53
|
+
validate(gtin, index, false);
|
|
54
|
+
|
|
55
|
+
index++;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
expect(index).toBe(referenceCount);
|
|
59
|
+
|
|
60
|
+
const randomValues = new Array<number>();
|
|
61
|
+
const identifiers = new Array<string>();
|
|
62
|
+
|
|
63
|
+
for (let i = 0; i < 1000; i++) {
|
|
64
|
+
const randomValue = Math.floor(Math.random() * creator.capacity);
|
|
65
|
+
|
|
66
|
+
randomValues.push(randomValue);
|
|
67
|
+
identifiers.push(creator.createGTIN14("5", randomValue));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
expect(Array.from(creator.createGTIN14("5", randomValues))).toStrictEqual(identifiers);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test("GTIN-14 sparse", () => {
|
|
74
|
+
const sparseReferenceCount = Math.min(referenceCount, 1000);
|
|
75
|
+
|
|
76
|
+
// Reference count of 1 is neither sequential nor sparse so treat it as sparse.
|
|
77
|
+
let sequential = sparseReferenceCount !== 1;
|
|
78
|
+
|
|
79
|
+
const sequenceSet = new Set<string>();
|
|
80
|
+
|
|
81
|
+
let index = 0;
|
|
82
|
+
|
|
83
|
+
for (const gtin of creator.createGTIN14("5", new Sequence(0, sparseReferenceCount), true)) {
|
|
84
|
+
sequential &&= Number(gtin.substring(referenceSubstringStart, referenceSubstringEnd)) === index;
|
|
85
|
+
|
|
86
|
+
validate(gtin, index, true);
|
|
87
|
+
|
|
88
|
+
expect(sequenceSet.has(gtin)).toBe(false);
|
|
89
|
+
sequenceSet.add(gtin);
|
|
90
|
+
|
|
91
|
+
index++;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
expect(sequential).toBe(false);
|
|
95
|
+
expect(index).toBe(sparseReferenceCount);
|
|
96
|
+
|
|
97
|
+
const randomValues = new Array<number>();
|
|
98
|
+
const identifiers = new Array<string>();
|
|
99
|
+
|
|
100
|
+
for (let i = 0; i < 1000; i++) {
|
|
101
|
+
const randomValue = Math.floor(Math.random() * creator.capacity);
|
|
102
|
+
|
|
103
|
+
randomValues.push(randomValue);
|
|
104
|
+
identifiers.push(creator.createGTIN14("5", randomValue, true));
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
expect(Array.from(creator.createGTIN14("5", randomValues, true))).toStrictEqual(identifiers);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
if (creator.gtinType === GTINTypes.GTIN12) {
|
|
111
|
+
test("Zero-suppress GTIN-12 rule 1", () => {
|
|
112
|
+
expect(GTINValidator.zeroSuppress("012345000058")).toBe("01234558");
|
|
113
|
+
expect(GTINValidator.zeroSuppress("012345000065")).toBe("01234565");
|
|
114
|
+
expect(GTINValidator.zeroSuppress("012345000072")).toBe("01234572");
|
|
115
|
+
expect(GTINValidator.zeroSuppress("012345000089")).toBe("01234589");
|
|
116
|
+
expect(GTINValidator.zeroSuppress("012345000096")).toBe("01234596");
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
test("Zero-suppress GTIN-12 rule 2", () => {
|
|
120
|
+
expect(GTINValidator.zeroSuppress("045670000080")).toBe("04567840");
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
test("Zero-suppress GTIN-12 rule 3", () => {
|
|
124
|
+
expect(GTINValidator.zeroSuppress("034000005673")).toBe("03456703");
|
|
125
|
+
expect(GTINValidator.zeroSuppress("034100005672")).toBe("03456712");
|
|
126
|
+
expect(GTINValidator.zeroSuppress("034200005671")).toBe("03456721");
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
test("Zero-suppress GTIN-12 rule 4", () => {
|
|
130
|
+
expect(GTINValidator.zeroSuppress("098300000752")).toBe("09837532");
|
|
131
|
+
expect(GTINValidator.zeroSuppress("098400000751")).toBe("09847531");
|
|
132
|
+
expect(GTINValidator.zeroSuppress("098500000750")).toBe("09857530");
|
|
133
|
+
expect(GTINValidator.zeroSuppress("098600000759")).toBe("09867539");
|
|
134
|
+
expect(GTINValidator.zeroSuppress("098700000758")).toBe("09877538");
|
|
135
|
+
expect(GTINValidator.zeroSuppress("098800000757")).toBe("09887537");
|
|
136
|
+
expect(GTINValidator.zeroSuppress("098900000756")).toBe("09897536");
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test("Non-zero-suppressible GTIN-12 rule 1", () => {
|
|
140
|
+
expect(() => GTINValidator.zeroSuppress("012345100055")).toThrow("GTIN-12 not zero-suppressible");
|
|
141
|
+
expect(() => GTINValidator.zeroSuppress("012345010057")).toThrow("GTIN-12 not zero-suppressible");
|
|
142
|
+
expect(() => GTINValidator.zeroSuppress("012345001055")).toThrow("GTIN-12 not zero-suppressible");
|
|
143
|
+
expect(() => GTINValidator.zeroSuppress("012345000157")).toThrow("GTIN-12 not zero-suppressible");
|
|
144
|
+
expect(() => GTINValidator.zeroSuppress("012345000041")).toThrow("GTIN-12 not zero-suppressible");
|
|
145
|
+
expect(() => GTINValidator.zeroSuppress("012345000003")).toThrow("GTIN-12 not zero-suppressible");
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
test("Non-zero-suppressible GTIN-12 rule 2", () => {
|
|
149
|
+
expect(() => GTINValidator.zeroSuppress("045670100087")).toThrow("GTIN-12 not zero-suppressible");
|
|
150
|
+
expect(() => GTINValidator.zeroSuppress("045670010089")).toThrow("GTIN-12 not zero-suppressible");
|
|
151
|
+
expect(() => GTINValidator.zeroSuppress("045670001087")).toThrow("GTIN-12 not zero-suppressible");
|
|
152
|
+
expect(() => GTINValidator.zeroSuppress("045670000189")).toThrow("GTIN-12 not zero-suppressible");
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
test("Non-zero-suppressible GTIN-12 rule 3", () => {
|
|
156
|
+
expect(() => GTINValidator.zeroSuppress("034010005670")).toThrow("GTIN-12 not zero-suppressible");
|
|
157
|
+
expect(() => GTINValidator.zeroSuppress("034001005672")).toThrow("GTIN-12 not zero-suppressible");
|
|
158
|
+
expect(() => GTINValidator.zeroSuppress("034000105670")).toThrow("GTIN-12 not zero-suppressible");
|
|
159
|
+
expect(() => GTINValidator.zeroSuppress("034000015672")).toThrow("GTIN-12 not zero-suppressible");
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
test("Non-zero-suppressible GTIN-12 rule 4", () => {
|
|
163
|
+
expect(() => GTINValidator.zeroSuppress("098310000759")).toThrow("GTIN-12 not zero-suppressible");
|
|
164
|
+
expect(() => GTINValidator.zeroSuppress("098301000751")).toThrow("GTIN-12 not zero-suppressible");
|
|
165
|
+
expect(() => GTINValidator.zeroSuppress("098300100759")).toThrow("GTIN-12 not zero-suppressible");
|
|
166
|
+
expect(() => GTINValidator.zeroSuppress("098300010751")).toThrow("GTIN-12 not zero-suppressible");
|
|
167
|
+
expect(() => GTINValidator.zeroSuppress("098300001759")).toThrow("GTIN-12 not zero-suppressible");
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
test("Zero-suppress other error", () => {
|
|
171
|
+
expect(() => GTINValidator.zeroSuppress("0012345000059")).toThrow("GTIN must be 12 digits long");
|
|
172
|
+
expect(() => GTINValidator.zeroSuppress("012345000059")).toThrow("Invalid check digit");
|
|
173
|
+
expect(() => GTINValidator.zeroSuppress("112345000055")).toThrow("GTIN-12 not zero-suppressible");
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
test("Zero-expand GTIN-12 rule 1", () => {
|
|
177
|
+
expect(GTINValidator.zeroExpand("01234558")).toBe("012345000058");
|
|
178
|
+
expect(GTINValidator.zeroExpand("01234565")).toBe("012345000065");
|
|
179
|
+
expect(GTINValidator.zeroExpand("01234572")).toBe("012345000072");
|
|
180
|
+
expect(GTINValidator.zeroExpand("01234589")).toBe("012345000089");
|
|
181
|
+
expect(GTINValidator.zeroExpand("01234596")).toBe("012345000096");
|
|
182
|
+
expect(() => GTINValidator.zeroExpand("00000154")).toThrow("U.P.C. Company Prefix can't start with \"0000\"");
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
test("Zero-expand GTIN-12 rule 2", () => {
|
|
186
|
+
expect(GTINValidator.zeroExpand("04567840")).toBe("045670000080");
|
|
187
|
+
expect(() => GTINValidator.zeroExpand("00001047")).toThrow("U.P.C. Company Prefix can't start with \"0000\"");
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
test("Zero-expand GTIN-12 rule 3", () => {
|
|
191
|
+
expect(GTINValidator.zeroExpand("03456703")).toBe("034000005673");
|
|
192
|
+
expect(GTINValidator.zeroExpand("03456712")).toBe("034100005672");
|
|
193
|
+
expect(GTINValidator.zeroExpand("03456721")).toBe("034200005671");
|
|
194
|
+
expect(() => GTINValidator.zeroExpand("00000028")).not.toThrow(RangeError);
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
test("Zero-expand GTIN-12 rule 4", () => {
|
|
198
|
+
expect(GTINValidator.zeroExpand("09837532")).toBe("098300000752");
|
|
199
|
+
expect(GTINValidator.zeroExpand("09847531")).toBe("098400000751");
|
|
200
|
+
expect(GTINValidator.zeroExpand("09857530")).toBe("098500000750");
|
|
201
|
+
expect(GTINValidator.zeroExpand("09867539")).toBe("098600000759");
|
|
202
|
+
expect(GTINValidator.zeroExpand("09877538")).toBe("098700000758");
|
|
203
|
+
expect(GTINValidator.zeroExpand("09887537")).toBe("098800000757");
|
|
204
|
+
expect(GTINValidator.zeroExpand("09897536")).toBe("098900000756");
|
|
205
|
+
expect(() => GTINValidator.zeroExpand("00030037")).not.toThrow(RangeError);
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
test("Zero-expand error", () => {
|
|
209
|
+
expect(() => GTINValidator.zeroExpand("001234505")).toThrow("Length 9 must be less than or equal to 8");
|
|
210
|
+
expect(() => GTINValidator.zeroExpand("01234506")).toThrow("Invalid check digit");
|
|
211
|
+
expect(() => GTINValidator.zeroExpand("11234506")).toThrow("Invalid zero-suppressed GTIN-12");
|
|
212
|
+
expect(() => GTINValidator.zeroExpand("09800037")).toThrow("Invalid zero-suppressed GTIN-12");
|
|
213
|
+
expect(() => GTINValidator.zeroExpand("09800047")).toThrow("Invalid zero-suppressed GTIN-12");
|
|
214
|
+
expect(() => GTINValidator.zeroExpand("09800052")).toThrow("Invalid zero-suppressed GTIN-12");
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
test("GTIN-14", () => {
|
|
219
|
+
const gtin = creator.create(0, true);
|
|
220
|
+
|
|
221
|
+
expect(gtin.length).toBe(creator.length);
|
|
222
|
+
|
|
223
|
+
let gtin14 = GTINValidator.convertToGTIN14("0", gtin);
|
|
224
|
+
|
|
225
|
+
expect(gtin14.length).toBe(14);
|
|
226
|
+
expect(GTINValidator.normalize(gtin14)).toBe(gtin);
|
|
227
|
+
|
|
228
|
+
gtin14 = GTINValidator.convertToGTIN14("1", gtin);
|
|
229
|
+
|
|
230
|
+
expect(gtin14.length).toBe(14);
|
|
231
|
+
expect(GTINValidator.normalize(gtin14)).not.toBe(gtin);
|
|
232
|
+
|
|
233
|
+
gtin14 = GTINValidator.convertToGTIN14("2", gtin14);
|
|
234
|
+
|
|
235
|
+
expect(gtin14.length).toBe(14);
|
|
236
|
+
expect(GTINValidator.normalize(gtin14)).not.toBe(gtin);
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
}
|