@aidc-toolkit/gs1 1.0.32-beta → 1.0.34-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/README.md +290 -21
- package/dist/character-set.d.ts.map +1 -1
- package/dist/character-set.js +44 -11
- package/dist/character-set.js.map +1 -1
- package/dist/gcp-length-cache.d.ts +54 -15
- package/dist/gcp-length-cache.d.ts.map +1 -1
- package/dist/gcp-length-cache.js +181 -45
- package/dist/gcp-length-cache.js.map +1 -1
- package/dist/gcp-length-data.d.ts +74 -20
- package/dist/gcp-length-data.d.ts.map +1 -1
- package/dist/gcp-length-data.js +39 -15
- package/dist/gcp-length-data.js.map +1 -1
- package/dist/gcp-length.d.ts +1 -1
- package/dist/gcp-length.d.ts.map +1 -1
- package/dist/gcp-length.js +5 -6
- package/dist/gcp-length.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/locale/en/locale-resources.d.ts +39 -36
- package/dist/locale/en/locale-resources.d.ts.map +1 -1
- package/dist/locale/en/locale-resources.js +4 -1
- package/dist/locale/en/locale-resources.js.map +1 -1
- package/dist/locale/fr/locale-resources.d.ts +39 -36
- package/dist/locale/fr/locale-resources.d.ts.map +1 -1
- package/dist/locale/fr/locale-resources.js +4 -1
- package/dist/locale/fr/locale-resources.js.map +1 -1
- package/dist/locale/i18n.d.ts +6 -3
- package/dist/locale/i18n.d.ts.map +1 -1
- package/dist/locale/i18n.js +8 -6
- package/dist/locale/i18n.js.map +1 -1
- package/dist/numeric-identifier-validator.d.ts.map +1 -1
- package/dist/numeric-identifier-validator.js.map +1 -1
- package/dist/variable-measure.d.ts +4 -4
- package/dist/variable-measure.js +4 -4
- package/package.json +12 -10
- package/src/character-set.ts +55 -11
- package/src/gcp-length-cache.ts +208 -54
- package/src/gcp-length-data.ts +95 -27
- package/src/gcp-length.ts +5 -43
- package/src/index.ts +2 -1
- package/src/locale/en/locale-resources.ts +5 -2
- package/src/locale/fr/locale-resources.ts +5 -2
- package/src/locale/i18n.ts +9 -7
- package/src/locale/i18next.d.ts +2 -0
- package/src/numeric-identifier-validator.ts +1 -1
- package/src/variable-measure.ts +4 -4
- package/test/character-set.test.ts +46 -0
- package/test/gcp-length.test.ts +179 -240
- package/tsconfig-src.tsbuildinfo +1 -1
package/src/gcp-length-cache.ts
CHANGED
|
@@ -1,74 +1,222 @@
|
|
|
1
|
-
import { Cache } from "@aidc-toolkit/core";
|
|
2
|
-
import {
|
|
1
|
+
import { type AppData, type AppDataStorage, Cache, omit, RemoteAppDataStorage } from "@aidc-toolkit/core";
|
|
2
|
+
import {
|
|
3
|
+
type GCPLengthAppData,
|
|
4
|
+
type GCPLengthData,
|
|
5
|
+
type GCPLengthHeader,
|
|
6
|
+
type GCPLengthSourceJSON,
|
|
7
|
+
isGCPLengthAppData,
|
|
8
|
+
isGCPLengthHeader
|
|
9
|
+
} from "./gcp-length-data.js";
|
|
3
10
|
import { i18nextGS1 } from "./locale/i18n.js";
|
|
4
11
|
|
|
5
12
|
/**
|
|
6
13
|
* GS1 Company Prefix length cache.
|
|
7
14
|
*/
|
|
8
|
-
export abstract class GCPLengthCache extends Cache<GCPLengthData, GCPLengthData |
|
|
9
|
-
|
|
15
|
+
export abstract class GCPLengthCache extends Cache<GCPLengthData, GCPLengthData | GCPLengthSourceJSON> {
|
|
16
|
+
/**
|
|
17
|
+
* Storage key for full application data object.
|
|
18
|
+
*/
|
|
19
|
+
static APP_DATA_STORAGE_KEY = "gcp-length";
|
|
10
20
|
|
|
11
|
-
/**
|
|
12
|
-
* GS1 Company Prefix length cache with remote source.
|
|
13
|
-
*/
|
|
14
|
-
export abstract class RemoteGCPLengthCache extends GCPLengthCache {
|
|
15
21
|
/**
|
|
16
|
-
*
|
|
22
|
+
* Storage key for next check date/time.
|
|
17
23
|
*/
|
|
18
|
-
static
|
|
24
|
+
static NEXT_CHECK_DATE_TIME_STORAGE_KEY = "gcp-length-next-check-date-time";
|
|
19
25
|
|
|
20
26
|
/**
|
|
21
|
-
*
|
|
27
|
+
* Storage key for header information (date/time and disclaimer).
|
|
22
28
|
*/
|
|
23
|
-
static
|
|
29
|
+
static HEADER_STORAGE_KEY = "gcp-length-header";
|
|
24
30
|
|
|
25
31
|
/**
|
|
26
|
-
*
|
|
32
|
+
* Storage key for data only.
|
|
27
33
|
*/
|
|
28
|
-
static
|
|
34
|
+
static DATA_STORAGE_KEY = "gcp-length-data";
|
|
29
35
|
|
|
30
36
|
/**
|
|
31
|
-
*
|
|
37
|
+
* Application data storage.
|
|
32
38
|
*/
|
|
33
|
-
readonly #
|
|
39
|
+
readonly #appDataStorage: AppDataStorage<boolean>;
|
|
34
40
|
|
|
35
41
|
/**
|
|
36
|
-
* GS1 Company Prefix
|
|
42
|
+
* GS1 Company Prefix application data.
|
|
37
43
|
*/
|
|
38
|
-
#
|
|
44
|
+
#cacheGCPLengthAppData?: GCPLengthAppData | undefined;
|
|
39
45
|
|
|
40
46
|
/**
|
|
41
47
|
* Constructor.
|
|
42
48
|
*
|
|
43
|
-
* @param
|
|
44
|
-
*
|
|
45
|
-
* SOURCE_DATA_FILE_NAME} files.
|
|
49
|
+
* @param appDataStorage
|
|
50
|
+
* Application data storage.
|
|
46
51
|
*/
|
|
47
|
-
constructor(
|
|
52
|
+
constructor(appDataStorage: AppDataStorage<boolean>) {
|
|
48
53
|
super();
|
|
49
54
|
|
|
50
|
-
this.#
|
|
55
|
+
this.#appDataStorage = appDataStorage;
|
|
51
56
|
}
|
|
52
57
|
|
|
53
58
|
/**
|
|
54
|
-
* Get
|
|
55
|
-
|
|
59
|
+
* Get the application data storage.
|
|
60
|
+
*/
|
|
61
|
+
get appDataStorage(): AppDataStorage<boolean> {
|
|
62
|
+
return this.#appDataStorage;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Load cached GS1 Company Prefix length application data from application data storage.
|
|
56
67
|
*
|
|
57
|
-
* @
|
|
58
|
-
*
|
|
68
|
+
* @returns
|
|
69
|
+
* GS1 Company Prefix length application data.
|
|
70
|
+
*/
|
|
71
|
+
async #loadCache(): Promise<GCPLengthAppData> {
|
|
72
|
+
if (this.#cacheGCPLengthAppData === undefined) {
|
|
73
|
+
if (!this.appDataStorage.supportsBinary) {
|
|
74
|
+
// Everything is stored in a single object.
|
|
75
|
+
const appData = await this.appDataStorage.read(GCPLengthCache.APP_DATA_STORAGE_KEY);
|
|
76
|
+
|
|
77
|
+
if (isGCPLengthAppData(appData)) {
|
|
78
|
+
this.#cacheGCPLengthAppData = appData;
|
|
79
|
+
}
|
|
80
|
+
} else {
|
|
81
|
+
const nextCheckDateTime = await this.appDataStorage.read(GCPLengthCache.NEXT_CHECK_DATE_TIME_STORAGE_KEY);
|
|
82
|
+
const header = await this.appDataStorage.read(GCPLengthCache.HEADER_STORAGE_KEY);
|
|
83
|
+
const data = await this.appDataStorage.read(GCPLengthCache.DATA_STORAGE_KEY, true);
|
|
84
|
+
|
|
85
|
+
this.#cacheGCPLengthAppData = {
|
|
86
|
+
nextCheckDateTime: nextCheckDateTime instanceof Date ? nextCheckDateTime : undefined,
|
|
87
|
+
gcpLengthData: isGCPLengthHeader(header) && data instanceof Uint8Array ?
|
|
88
|
+
{
|
|
89
|
+
...header,
|
|
90
|
+
data
|
|
91
|
+
} :
|
|
92
|
+
undefined
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// If there's nothing in the cache yet, create an object with the next check date/time set to now.
|
|
98
|
+
if (this.#cacheGCPLengthAppData === undefined) {
|
|
99
|
+
this.#cacheGCPLengthAppData = {
|
|
100
|
+
nextCheckDateTime: new Date(),
|
|
101
|
+
gcpLengthData: undefined
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return this.#cacheGCPLengthAppData;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* @inheritDoc
|
|
110
|
+
*/
|
|
111
|
+
override get nextCheckDateTime(): Promise<Date | undefined> {
|
|
112
|
+
return this.#loadCache().then(gcpLengthAppData => gcpLengthAppData.nextCheckDateTime);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* @inheritDoc
|
|
117
|
+
*/
|
|
118
|
+
override get cacheDateTime(): Promise<Date | undefined> {
|
|
119
|
+
return this.#loadCache().then(gcpLengthAppData => gcpLengthAppData.gcpLengthData?.dateTime);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* @inheritDoc
|
|
124
|
+
*/
|
|
125
|
+
override get cacheData(): Promise<GCPLengthData> {
|
|
126
|
+
return this.#loadCache().then((gcpLengthAppData) => {
|
|
127
|
+
if (gcpLengthAppData.gcpLengthData === undefined) {
|
|
128
|
+
// Application error; no localization necessary.
|
|
129
|
+
throw new Error("GS1 Company Prefix length application data not loaded");
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return gcpLengthAppData.gcpLengthData;
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* @inheritDoc
|
|
138
|
+
*/
|
|
139
|
+
override async update(nextCheckDateTime: Date, _cacheDateTime?: Date, cacheData?: GCPLengthData): Promise<void> {
|
|
140
|
+
this.#cacheGCPLengthAppData = {
|
|
141
|
+
nextCheckDateTime,
|
|
142
|
+
// Retain existing data if cache data is not provided.
|
|
143
|
+
gcpLengthData: cacheData ?? this.#cacheGCPLengthAppData?.gcpLengthData
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
if (!this.appDataStorage.supportsBinary) {
|
|
147
|
+
// Everything is stored in a single object.
|
|
148
|
+
await this.appDataStorage.write(GCPLengthCache.APP_DATA_STORAGE_KEY, this.#cacheGCPLengthAppData);
|
|
149
|
+
} else {
|
|
150
|
+
await this.appDataStorage.write(GCPLengthCache.NEXT_CHECK_DATE_TIME_STORAGE_KEY, nextCheckDateTime);
|
|
151
|
+
|
|
152
|
+
if (cacheData !== undefined) {
|
|
153
|
+
await this.appDataStorage.write(GCPLengthCache.HEADER_STORAGE_KEY, omit(cacheData, "data"));
|
|
154
|
+
await this.appDataStorage.write(GCPLengthCache.DATA_STORAGE_KEY, cacheData.data);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* GS1 Company Prefix length cache with remote source.
|
|
162
|
+
*/
|
|
163
|
+
export class RemoteGCPLengthCache extends GCPLengthCache {
|
|
164
|
+
/**
|
|
165
|
+
* Default base URL pointing to AIDC Toolkit website data directory.
|
|
166
|
+
*/
|
|
167
|
+
static DEFAULT_BASE_URL = "https://aidc-toolkit.com/data";
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Remote application data storage.
|
|
171
|
+
*/
|
|
172
|
+
readonly #remoteAppDataStorage: RemoteAppDataStorage;
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Remote GS1 Company Prefix header data.
|
|
176
|
+
*/
|
|
177
|
+
#remoteGCPLengthHeader?: GCPLengthHeader | undefined;
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Constructor.
|
|
181
|
+
*
|
|
182
|
+
* @param appDataStorage
|
|
183
|
+
* Application data storage.
|
|
184
|
+
*
|
|
185
|
+
* @param baseURL
|
|
186
|
+
* Base URL. The URL must not end with a slash and must host the `gcp-length-header.json` and `gcp-length-data.bin`
|
|
187
|
+
* files.
|
|
188
|
+
*/
|
|
189
|
+
constructor(appDataStorage: AppDataStorage<boolean>, baseURL: string = RemoteGCPLengthCache.DEFAULT_BASE_URL) {
|
|
190
|
+
super(appDataStorage);
|
|
191
|
+
|
|
192
|
+
this.#remoteAppDataStorage = new RemoteAppDataStorage(baseURL);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Get remote application data. If an exception is thrown while retrieving or processing the data, retrying is
|
|
197
|
+
* delayed for ten minutes to prevent repeated network calls.
|
|
198
|
+
*
|
|
199
|
+
* @param pathKey
|
|
200
|
+
* Key relative to base URL.
|
|
201
|
+
*
|
|
202
|
+
* @param asBinary
|
|
203
|
+
* True if binary data is requested, false if string data is requested.
|
|
204
|
+
*
|
|
205
|
+
* @param callback
|
|
206
|
+
* Callback function to process the application data.
|
|
59
207
|
*
|
|
60
208
|
* @returns
|
|
61
|
-
*
|
|
209
|
+
* Application data.
|
|
62
210
|
*/
|
|
63
|
-
async #
|
|
64
|
-
return
|
|
65
|
-
if (
|
|
66
|
-
throw new RangeError(i18nextGS1.t("Prefix.
|
|
67
|
-
|
|
211
|
+
async #getRemoteAppData<T>(pathKey: string, asBinary: boolean, callback: (appData: AppData) => T): Promise<T> {
|
|
212
|
+
return this.#remoteAppDataStorage.read(pathKey, asBinary).then((appData) => {
|
|
213
|
+
if (appData === undefined) {
|
|
214
|
+
throw new RangeError(i18nextGS1.t("Prefix.gs1CompanyPrefixLengthDataFileNotFound", {
|
|
215
|
+
key: pathKey
|
|
68
216
|
}));
|
|
69
217
|
}
|
|
70
218
|
|
|
71
|
-
return
|
|
219
|
+
return callback(appData);
|
|
72
220
|
}).catch(async (e: unknown) => {
|
|
73
221
|
// Try again in ten minutes.
|
|
74
222
|
const nowPlus10Minutes = new Date();
|
|
@@ -83,35 +231,41 @@ export abstract class RemoteGCPLengthCache extends GCPLengthCache {
|
|
|
83
231
|
/**
|
|
84
232
|
* @inheritDoc
|
|
85
233
|
*/
|
|
86
|
-
get sourceDateTime(): Promise<Date> {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
234
|
+
override get sourceDateTime(): Promise<Date> {
|
|
235
|
+
// Header is fetched on each call.
|
|
236
|
+
return this.#getRemoteAppData(RemoteGCPLengthCache.HEADER_STORAGE_KEY, false, (appData) => {
|
|
237
|
+
if (!isGCPLengthHeader(appData)) {
|
|
238
|
+
// Application error; no localization necessary.
|
|
239
|
+
throw new Error("Invalid GS1 Company Prefix length header");
|
|
240
|
+
}
|
|
91
241
|
|
|
92
|
-
|
|
242
|
+
this.#remoteGCPLengthHeader = appData;
|
|
243
|
+
|
|
244
|
+
return this.#remoteGCPLengthHeader.dateTime;
|
|
93
245
|
});
|
|
94
246
|
}
|
|
95
247
|
|
|
96
248
|
/**
|
|
97
249
|
* @inheritDoc
|
|
98
250
|
*/
|
|
99
|
-
get sourceData(): Promise<GCPLengthData> {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
throw new Error("GS1 Company Prefix length header not loaded");
|
|
103
|
-
}
|
|
251
|
+
override get sourceData(): Promise<GCPLengthData> {
|
|
252
|
+
return this.#getRemoteAppData(RemoteGCPLengthCache.DATA_STORAGE_KEY, true, (appData) => {
|
|
253
|
+
const gcpLengthHeader = this.#remoteGCPLengthHeader;
|
|
104
254
|
|
|
105
|
-
|
|
255
|
+
if (gcpLengthHeader === undefined) {
|
|
256
|
+
// Application error; no localization necessary.
|
|
257
|
+
throw new Error("GS1 Company Prefix length header not loaded");
|
|
258
|
+
}
|
|
106
259
|
|
|
107
|
-
|
|
108
|
-
|
|
260
|
+
if (!(appData instanceof Uint8Array)) {
|
|
261
|
+
// Application error; no localization necessary.
|
|
262
|
+
throw new Error("Invalid GS1 Company Prefix length data");
|
|
263
|
+
}
|
|
109
264
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}));
|
|
265
|
+
return {
|
|
266
|
+
...gcpLengthHeader,
|
|
267
|
+
data: appData
|
|
268
|
+
};
|
|
269
|
+
});
|
|
116
270
|
}
|
|
117
271
|
}
|
package/src/gcp-length-data.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { AppData } from "@aidc-toolkit/core";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* GS1 Company Prefix length header.
|
|
3
5
|
*/
|
|
@@ -14,55 +16,121 @@ export interface GCPLengthHeader {
|
|
|
14
16
|
}
|
|
15
17
|
|
|
16
18
|
/**
|
|
17
|
-
*
|
|
19
|
+
* Determine if application data object is GS1 Company Prefix length header.
|
|
18
20
|
*
|
|
19
|
-
* @param
|
|
20
|
-
*
|
|
21
|
+
* @param appData
|
|
22
|
+
* Application data object.
|
|
21
23
|
*
|
|
22
24
|
* @returns
|
|
23
|
-
* GS1 Company Prefix length header.
|
|
25
|
+
* True if application data object is GS1 Company Prefix length header.
|
|
24
26
|
*/
|
|
25
|
-
export function
|
|
26
|
-
//
|
|
27
|
-
return
|
|
28
|
-
key === "dateTime" && typeof value === "string" ? new Date(value) : value
|
|
29
|
-
) as GCPLengthHeader;
|
|
27
|
+
export function isGCPLengthHeader(appData: AppData | undefined): appData is GCPLengthHeader {
|
|
28
|
+
// Property type check is necessary to guard against data corruption or changes in format.
|
|
29
|
+
return typeof appData === "object" && "dateTime" in appData && appData.dateTime instanceof Date && "disclaimer" in appData && typeof appData.disclaimer === "string";
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
|
-
*
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
* GS1 Company Prefix length data.
|
|
34
|
+
*/
|
|
35
|
+
export interface GCPLengthData extends GCPLengthHeader {
|
|
36
|
+
/**
|
|
37
|
+
* Tree data in binary form.
|
|
38
|
+
*/
|
|
39
|
+
readonly data: Uint8Array;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Determine if application data object is GS1 Company Prefix length data.
|
|
37
44
|
*
|
|
38
|
-
* @param
|
|
39
|
-
*
|
|
45
|
+
* @param appData
|
|
46
|
+
* Application data object.
|
|
40
47
|
*
|
|
41
48
|
* @returns
|
|
42
|
-
*
|
|
49
|
+
* True if application data object is GS1 Company Prefix length data.
|
|
43
50
|
*/
|
|
44
|
-
export function
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
space);
|
|
51
|
+
export function isGCPLengthData(appData: AppData | undefined): appData is GCPLengthData {
|
|
52
|
+
// Property type check is necessary to guard against data corruption or changes in format.
|
|
53
|
+
return isGCPLengthHeader(appData) && "data" in appData && appData.data instanceof Uint8Array;
|
|
48
54
|
}
|
|
49
55
|
|
|
50
56
|
/**
|
|
51
|
-
* GS1 Company Prefix length data.
|
|
57
|
+
* GS1 Company Prefix length application data.
|
|
52
58
|
*/
|
|
53
|
-
export interface
|
|
59
|
+
export interface GCPLengthAppData {
|
|
54
60
|
/**
|
|
55
|
-
*
|
|
61
|
+
* Next check date/time.
|
|
56
62
|
*/
|
|
57
|
-
|
|
63
|
+
nextCheckDateTime: Date | undefined;
|
|
58
64
|
|
|
65
|
+
/**
|
|
66
|
+
* GS1 Company Prefix length data.
|
|
67
|
+
*/
|
|
68
|
+
gcpLengthData: GCPLengthData | undefined;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Determine if application data object is GS1 Company Prefix length application data.
|
|
73
|
+
*
|
|
74
|
+
* @param appData
|
|
75
|
+
* Application data object.
|
|
76
|
+
*
|
|
77
|
+
* @returns
|
|
78
|
+
* True if application data object is GS1 Company Prefix length application data.
|
|
79
|
+
*/
|
|
80
|
+
export function isGCPLengthAppData(appData: AppData | undefined): appData is GCPLengthAppData {
|
|
81
|
+
// Property type check is necessary to guard against data corruption or changes in format.
|
|
82
|
+
return typeof appData === "object" && "nextCheckDateTime" in appData && appData.nextCheckDateTime instanceof Date && (
|
|
83
|
+
!("gcpLengthData" in appData) || appData.gcpLengthData === undefined || (
|
|
84
|
+
typeof appData.gcpLengthData === "object" && appData.gcpLengthData !== null && isGCPLengthData(appData.gcpLengthData)
|
|
85
|
+
)
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* GS1 Company Prefix length JSON source file format.
|
|
91
|
+
*/
|
|
92
|
+
export interface GCPLengthSourceJSON {
|
|
59
93
|
/**
|
|
60
94
|
* Disclaimer.
|
|
61
95
|
*/
|
|
62
|
-
|
|
96
|
+
_disclaimer: string[];
|
|
63
97
|
|
|
64
98
|
/**
|
|
65
|
-
*
|
|
99
|
+
* Format list.
|
|
66
100
|
*/
|
|
67
|
-
|
|
101
|
+
GCPPrefixFormatList: {
|
|
102
|
+
/**
|
|
103
|
+
* ISO data/time the table was last updated.
|
|
104
|
+
*/
|
|
105
|
+
date: string;
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Entries.
|
|
109
|
+
*/
|
|
110
|
+
entry: Array<{
|
|
111
|
+
/**
|
|
112
|
+
* Identification key prefix start.
|
|
113
|
+
*/
|
|
114
|
+
prefix: string;
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Length of GS1 Company Prefix.
|
|
118
|
+
*/
|
|
119
|
+
gcpLength: number;
|
|
120
|
+
}>;
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Determine if application data object is GS1 Company Prefix length source JSON.
|
|
126
|
+
*
|
|
127
|
+
* @param appData
|
|
128
|
+
* Application data object.
|
|
129
|
+
*
|
|
130
|
+
* @returns
|
|
131
|
+
* True if application data object is GS1 Company Prefix length source JSON.
|
|
132
|
+
*/
|
|
133
|
+
export function isGCPLengthSourceJSON(appData: AppData | undefined): appData is GCPLengthSourceJSON {
|
|
134
|
+
// Checking is minimal as this is generally used in a controlled environment (e.g., updating remote storage).
|
|
135
|
+
return typeof appData === "object" && "_disclaimer" in appData && "GCPPrefixFormatList" in appData;
|
|
68
136
|
}
|
package/src/gcp-length.ts
CHANGED
|
@@ -1,47 +1,12 @@
|
|
|
1
1
|
import { omit } from "@aidc-toolkit/core";
|
|
2
2
|
import type { GCPLengthCache } from "./gcp-length-cache.js";
|
|
3
|
-
import type
|
|
3
|
+
import { type GCPLengthData, type GCPLengthHeader, isGCPLengthData } from "./gcp-length-data.js";
|
|
4
4
|
import { GTINLengths } from "./gtin-length.js";
|
|
5
5
|
import { GTINValidator } from "./gtin-validator.js";
|
|
6
6
|
import { type IdentifierType, IdentifierTypes } from "./identifier-type.js";
|
|
7
7
|
import { IdentifierValidators, isNumericIdentifierValidator } from "./identifier-validators.js";
|
|
8
8
|
import { LeaderTypes } from "./leader-type.js";
|
|
9
9
|
|
|
10
|
-
/**
|
|
11
|
-
* GS1 Company Prefix length JSON source file format.
|
|
12
|
-
*/
|
|
13
|
-
interface GCPLengthJSON {
|
|
14
|
-
/**
|
|
15
|
-
* Disclaimer.
|
|
16
|
-
*/
|
|
17
|
-
_disclaimer: string[];
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Format list.
|
|
21
|
-
*/
|
|
22
|
-
GCPPrefixFormatList: {
|
|
23
|
-
/**
|
|
24
|
-
* ISO data/time the table was last updated.
|
|
25
|
-
*/
|
|
26
|
-
date: string;
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Entries.
|
|
30
|
-
*/
|
|
31
|
-
entry: Array<{
|
|
32
|
-
/**
|
|
33
|
-
* Identification key prefix start.
|
|
34
|
-
*/
|
|
35
|
-
prefix: string;
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Length of GS1 Company Prefix.
|
|
39
|
-
*/
|
|
40
|
-
gcpLength: number;
|
|
41
|
-
}>;
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
|
|
45
10
|
/**
|
|
46
11
|
* Leaf of GS1 Company Prefix length tree.
|
|
47
12
|
*/
|
|
@@ -299,7 +264,7 @@ export async function loadData(gcpLengthCache: GCPLengthCache): Promise<Root | u
|
|
|
299
264
|
|
|
300
265
|
let cacheData: GCPLengthData;
|
|
301
266
|
|
|
302
|
-
if (
|
|
267
|
+
if (isGCPLengthData(sourceData)) {
|
|
303
268
|
root = {
|
|
304
269
|
dateTime: sourceData.dateTime,
|
|
305
270
|
disclaimer: sourceData.disclaimer,
|
|
@@ -310,13 +275,10 @@ export async function loadData(gcpLengthCache: GCPLengthCache): Promise<Root | u
|
|
|
310
275
|
|
|
311
276
|
cacheData = sourceData;
|
|
312
277
|
} else {
|
|
313
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- File format is known.
|
|
314
|
-
const gcpLength = JSON.parse(sourceData) as GCPLengthJSON;
|
|
315
|
-
|
|
316
278
|
root = {
|
|
317
|
-
dateTime: new Date(
|
|
279
|
+
dateTime: new Date(sourceData.GCPPrefixFormatList.date),
|
|
318
280
|
// Join disclaimer as a single string.
|
|
319
|
-
disclaimer: `${
|
|
281
|
+
disclaimer: `${sourceData._disclaimer.reduce<string[]>((lines, line) => {
|
|
320
282
|
if (lines.length === 0 || lines[lines.length - 1] === "" || line === "") {
|
|
321
283
|
lines.push(line);
|
|
322
284
|
} else {
|
|
@@ -331,7 +293,7 @@ export async function loadData(gcpLengthCache: GCPLengthCache): Promise<Root | u
|
|
|
331
293
|
|
|
332
294
|
let branchesAdded = 1;
|
|
333
295
|
|
|
334
|
-
for (const entry of
|
|
296
|
+
for (const entry of sourceData.GCPPrefixFormatList.entry) {
|
|
335
297
|
branchesAdded += addEntry(root, entry.prefix, entry.gcpLength);
|
|
336
298
|
}
|
|
337
299
|
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* Copyright © 2024-
|
|
2
|
+
* Copyright © 2024-2026 Dolphin Data Development Ltd. and AIDC Toolkit
|
|
3
3
|
* contributors
|
|
4
4
|
*
|
|
5
5
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
* See the License for the specific language governing permissions and
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/
|
|
17
|
+
|
|
17
18
|
export * from "./locale/i18n.js";
|
|
18
19
|
|
|
19
20
|
export * from "./character-set.js";
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export default {
|
|
2
|
+
AI64CharacterSetValidator: {
|
|
3
|
+
lengthMustBeMultipleOf4: "Length {{length, number}} must be a multiple of 4"
|
|
4
|
+
},
|
|
2
5
|
Check: {
|
|
3
6
|
lengthOfStringForPriceOrWeightMustBeExactly: "Length {{length, number}} of string for price or weight must be 4 or 5",
|
|
4
7
|
priceOrWeightComponent: "price or weight",
|
|
@@ -35,7 +38,7 @@ export default {
|
|
|
35
38
|
upcCompanyPrefixCantStartWith0000: "U.P.C. Company Prefix can't start with \"0000\"",
|
|
36
39
|
gs18PrefixCantStartWith0: "GS1-8 Prefix can't start with \"0\"",
|
|
37
40
|
identifierTypeNotSupportedByGS18Prefix: "{{identifierType}} not supported by GS1-8 Prefix",
|
|
38
|
-
|
|
41
|
+
gs1CompanyPrefixLengthDataFileNotFound: "GS1 Company Prefix length data \"{{key}}\" not found",
|
|
39
42
|
gs1CompanyPrefixLengthDataNotLoaded: "GS1 Company Prefix length data not loaded"
|
|
40
43
|
}
|
|
41
|
-
}
|
|
44
|
+
};
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export default {
|
|
2
|
+
AI64CharacterSetValidator: {
|
|
3
|
+
lengthMustBeMultipleOf4: "La longueur {{length, number}} doit être un multiple de 4"
|
|
4
|
+
},
|
|
2
5
|
Check: {
|
|
3
6
|
lengthOfStringForPriceOrWeightMustBeExactly: "La longueur {{length, number}} de la chaîne pour le prix ou le poids doit être 4 ou 5",
|
|
4
7
|
priceOrWeightComponent: "prix ou poids",
|
|
@@ -35,7 +38,7 @@ export default {
|
|
|
35
38
|
upcCompanyPrefixCantStartWith0000: "Le préfixe de l'entreprise U.P.C. ne peut pas commencer par \"0000\"",
|
|
36
39
|
gs18PrefixCantStartWith0: "Le préfixe GS1-8 ne peut pas commencer par \"0\"",
|
|
37
40
|
identifierTypeNotSupportedByGS18Prefix: "{{identifierType}} non pris en charge par le préfixe GS1-8",
|
|
38
|
-
|
|
41
|
+
gs1CompanyPrefixLengthDataFileNotFound: "Données de longueur du préfixe d'entreprise GS1 «{{key}}» introuvables",
|
|
39
42
|
gs1CompanyPrefixLengthDataNotLoaded: "Les données relatives à la longueur du préfixe d'entreprise GS1 n'ont pas été chargées"
|
|
40
43
|
}
|
|
41
|
-
}
|
|
44
|
+
};
|
package/src/locale/i18n.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type I18nEnvironment,
|
|
2
|
-
import { i18nUtilityInit
|
|
1
|
+
import { i18nCoreInit, type I18nEnvironment, i18nInit } from "@aidc-toolkit/core";
|
|
2
|
+
import { i18nUtilityInit } from "@aidc-toolkit/utility";
|
|
3
3
|
import i18next, { type i18n, type Resource } from "i18next";
|
|
4
4
|
import enLocaleResources from "./en/locale-resources.js";
|
|
5
5
|
import frLocaleResources from "./fr/locale-resources.js";
|
|
@@ -12,9 +12,9 @@ export const gs1NS = "aidct_gs1";
|
|
|
12
12
|
export type GS1LocaleResources = typeof enLocaleResources;
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
* GS1
|
|
15
|
+
* GS1 resource bundle.
|
|
16
16
|
*/
|
|
17
|
-
export const
|
|
17
|
+
export const gs1ResourceBundle: Resource = {
|
|
18
18
|
en: {
|
|
19
19
|
aidct_gs1: enLocaleResources
|
|
20
20
|
},
|
|
@@ -34,8 +34,10 @@ export const i18nextGS1: i18n = i18next.createInstance();
|
|
|
34
34
|
*
|
|
35
35
|
* @param debug
|
|
36
36
|
* Debug setting.
|
|
37
|
+
*
|
|
38
|
+
* @returns
|
|
39
|
+
* GS1 resource bundle.
|
|
37
40
|
*/
|
|
38
|
-
export async function i18nGS1Init(environment: I18nEnvironment, debug = false): Promise<
|
|
39
|
-
|
|
40
|
-
await i18nFinalizeInit(i18nextGS1, environment, debug, gs1NS, utilityResources, gs1Resources);
|
|
41
|
+
export async function i18nGS1Init(environment: I18nEnvironment, debug = false): Promise<Resource> {
|
|
42
|
+
return i18nInit(i18nextGS1, environment, debug, gs1NS, gs1ResourceBundle, i18nCoreInit, i18nUtilityInit);
|
|
41
43
|
}
|
package/src/locale/i18next.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CoreLocaleResources } from "@aidc-toolkit/core";
|
|
1
2
|
import type { UtilityLocaleResources } from "@aidc-toolkit/utility";
|
|
2
3
|
import type { GS1LocaleResources } from "./i18n.js";
|
|
3
4
|
|
|
@@ -11,6 +12,7 @@ declare module "i18next" {
|
|
|
11
12
|
interface CustomTypeOptions {
|
|
12
13
|
defaultNS: "aidct_gs1";
|
|
13
14
|
resources: {
|
|
15
|
+
aidct_core: CoreLocaleResources;
|
|
14
16
|
aidct_utility: UtilityLocaleResources;
|
|
15
17
|
aidct_gs1: GS1LocaleResources;
|
|
16
18
|
};
|
|
@@ -56,7 +56,7 @@ export abstract class NumericIdentifierValidator<TNumericIdentifierType extends
|
|
|
56
56
|
/**
|
|
57
57
|
* @inheritDoc
|
|
58
58
|
*/
|
|
59
|
-
validate(identifier: string, validation?: NumericIdentifierValidation): void {
|
|
59
|
+
override validate(identifier: string, validation?: NumericIdentifierValidation): void {
|
|
60
60
|
// Validate the prefix, with care taken for its position within the identifier.
|
|
61
61
|
if (this.#prefixPosition === 0) {
|
|
62
62
|
super.validatePrefix(identifier);
|