@bsv/dpp-profiles 0.3.0-beta.1
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 +58 -0
- package/README.md +64 -0
- package/dist/applicability.d.ts +96 -0
- package/dist/applicability.d.ts.map +1 -0
- package/dist/applicability.js +181 -0
- package/dist/applicability.js.map +1 -0
- package/dist/combinations.d.ts +30 -0
- package/dist/combinations.d.ts.map +1 -0
- package/dist/combinations.js +103 -0
- package/dist/combinations.js.map +1 -0
- package/dist/evidence-shapes.d.ts +198 -0
- package/dist/evidence-shapes.d.ts.map +1 -0
- package/dist/evidence-shapes.js +123 -0
- package/dist/evidence-shapes.js.map +1 -0
- package/dist/gs1-epc-binary.d.ts +81 -0
- package/dist/gs1-epc-binary.d.ts.map +1 -0
- package/dist/gs1-epc-binary.js +252 -0
- package/dist/gs1-epc-binary.js.map +1 -0
- package/dist/gs1-resolution.d.ts +392 -0
- package/dist/gs1-resolution.d.ts.map +1 -0
- package/dist/gs1-resolution.js +696 -0
- package/dist/gs1-resolution.js.map +1 -0
- package/dist/identifiers.d.ts +57 -0
- package/dist/identifiers.d.ts.map +1 -0
- package/dist/identifiers.js +117 -0
- package/dist/identifiers.js.map +1 -0
- package/dist/index.d.ts +235 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +124 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest-v2.d.ts +87 -0
- package/dist/manifest-v2.d.ts.map +1 -0
- package/dist/manifest-v2.js +31 -0
- package/dist/manifest-v2.js.map +1 -0
- package/dist/mapping.d.ts +84 -0
- package/dist/mapping.d.ts.map +1 -0
- package/dist/mapping.js +88 -0
- package/dist/mapping.js.map +1 -0
- package/dist/projections.d.ts +233 -0
- package/dist/projections.d.ts.map +1 -0
- package/dist/projections.js +466 -0
- package/dist/projections.js.map +1 -0
- package/frozen.json +42 -0
- package/generated/consumer/battery-v2.json +2248 -0
- package/generated/consumer/battery-v3.json +4354 -0
- package/generated/consumer/general-v1.json +9 -0
- package/generated/consumer/general-v2.json +714 -0
- package/generated/consumer/textile-v1.json +101 -0
- package/generated/consumer/textile-v2.json +1033 -0
- package/generated/consumer/textile-v3.json +2011 -0
- package/generated/index.json +86 -0
- package/generated/mapping/battery@2.md +116 -0
- package/generated/mapping/battery@3.md +130 -0
- package/generated/mapping/general@2.md +50 -0
- package/generated/mapping/textile@2.md +61 -0
- package/generated/mapping/textile@3.md +73 -0
- package/generated/payload-schema/battery@2.public.schema.json +609 -0
- package/generated/payload-schema/battery@2.restricted.schema.json +377 -0
- package/generated/payload-schema/battery@3.public.schema.json +1364 -0
- package/generated/payload-schema/battery@3.restricted.schema.json +1097 -0
- package/generated/payload-schema/general@1.public.schema.json +37 -0
- package/generated/payload-schema/general@1.restricted.schema.json +9 -0
- package/generated/payload-schema/general@2.public.schema.json +352 -0
- package/generated/payload-schema/general@2.restricted.schema.json +52 -0
- package/generated/payload-schema/textile@1.public.schema.json +82 -0
- package/generated/payload-schema/textile@1.restricted.schema.json +22 -0
- package/generated/payload-schema/textile@2.public.schema.json +464 -0
- package/generated/payload-schema/textile@2.restricted.schema.json +78 -0
- package/generated/payload-schema/textile@3.public.schema.json +1299 -0
- package/generated/payload-schema/textile@3.restricted.schema.json +78 -0
- package/manifests/battery@2.json +4047 -0
- package/manifests/battery@3.json +6164 -0
- package/manifests/exchange/untp-0.7.0-jose@1.json +191 -0
- package/manifests/exchange/vc-di-ecdsa-rdfc-2019@1.json +74 -0
- package/manifests/exchange/vsc-draft-compat@0.1.0.json +64 -0
- package/manifests/general@1.json +148 -0
- package/manifests/general@2.json +1266 -0
- package/manifests/interoperability/epcis-json@1.json +69 -0
- package/manifests/interoperability/epcis-vsc@1.json +64 -0
- package/manifests/interoperability/gs1-digital-link@1.json +71 -0
- package/manifests/operator/federated-operators@1.json +54 -0
- package/manifests/operator/single-operator@1.json +52 -0
- package/manifests/textile@1.json +383 -0
- package/manifests/textile@2.json +1682 -0
- package/manifests/textile@3.json +2763 -0
- package/package.json +59 -0
- package/schemas/exchange-profile.schema.json +134 -0
- package/schemas/gs1/NOTICE.md +11 -0
- package/schemas/gs1/resolver-description-file-schema-1.2.0.json +124 -0
- package/schemas/gs1/resolver-linkset-context-1.2.1.jsonld +39 -0
- package/schemas/gs1/resolver-linkset-schema-1.2.1.json +96 -0
- package/schemas/interoperability-profile.schema.json +347 -0
- package/schemas/operator-profile.schema.json +108 -0
- package/schemas/product-identity.schema.json +45 -0
- package/schemas/profile-manifest-v2.schema.json +1087 -0
- package/schemas/profile-manifest.schema.json +291 -0
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EPC binary strings, decoded for the one scope the discovery profile
|
|
3
|
+
* declares (`spec/gs1-discovery.md` §3): a serialised trade item under the
|
|
4
|
+
* GS1 EPC Tag Data Standard's SGTIN-96 and SGTIN-198 schemes. A compressed GS1
|
|
5
|
+
* Digital Link URI whose compression string begins `eh` or `ex` carries such a
|
|
6
|
+
* string (GS1 Digital Link URI: Compression Technical Standard for EPC binary
|
|
7
|
+
* strings, release 1.0.0, July 2025, §4.1 and §4.2), and a GS1-Conformant
|
|
8
|
+
* Resolver must decompress it (GS1-Conformant Resolver 1.2.1 §2.3).
|
|
9
|
+
*
|
|
10
|
+
* Everything here is arithmetic over a bit string: the two alphabets of §4.1
|
|
11
|
+
* and §4.2, the SGTIN partition table of the Tag Data Standard, the 38-bit
|
|
12
|
+
* integer serial of SGTIN-96 and the twenty seven-bit characters of SGTIN-198.
|
|
13
|
+
* Nothing is guessed: a header this module does not implement, a company
|
|
14
|
+
* prefix or item reference outside its partition's digit count, a serial with
|
|
15
|
+
* a character the GS1 encodable set 82 does not contain, or a string of the
|
|
16
|
+
* wrong length is refused by name. A decoding establishes what the bits say
|
|
17
|
+
* and no more; it is not evidence that the GTIN was allocated to anyone.
|
|
18
|
+
*/
|
|
19
|
+
import { gs1CheckDigit } from './identifiers.js';
|
|
20
|
+
/** The EPC header of the SGTIN-96 scheme (Tag Data Standard). */
|
|
21
|
+
export const SGTIN_96_HEADER = 0x30;
|
|
22
|
+
/** The EPC header of the SGTIN-198 scheme (Tag Data Standard). */
|
|
23
|
+
export const SGTIN_198_HEADER = 0x36;
|
|
24
|
+
/** The file-safe, URI-safe base 64 alphabet of the compression standard §4.1 (RFC 4648 §5). */
|
|
25
|
+
export const URI_SAFE_BASE64_ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
|
|
26
|
+
/**
|
|
27
|
+
* The SGTIN partition table of the Tag Data Standard: for each partition
|
|
28
|
+
* value, the bits and digits of the GS1 Company Prefix and of the item
|
|
29
|
+
* reference (indicator digit included). The two digit counts always sum to
|
|
30
|
+
* thirteen, so the GTIN-14 is the indicator digit, the company prefix, the
|
|
31
|
+
* rest of the item reference and a check digit.
|
|
32
|
+
*/
|
|
33
|
+
export const SGTIN_PARTITIONS = [
|
|
34
|
+
{ companyPrefixBits: 40, companyPrefixDigits: 12, itemReferenceBits: 4, itemReferenceDigits: 1 },
|
|
35
|
+
{ companyPrefixBits: 37, companyPrefixDigits: 11, itemReferenceBits: 7, itemReferenceDigits: 2 },
|
|
36
|
+
{ companyPrefixBits: 34, companyPrefixDigits: 10, itemReferenceBits: 10, itemReferenceDigits: 3 },
|
|
37
|
+
{ companyPrefixBits: 30, companyPrefixDigits: 9, itemReferenceBits: 14, itemReferenceDigits: 4 },
|
|
38
|
+
{ companyPrefixBits: 27, companyPrefixDigits: 8, itemReferenceBits: 17, itemReferenceDigits: 5 },
|
|
39
|
+
{ companyPrefixBits: 24, companyPrefixDigits: 7, itemReferenceBits: 20, itemReferenceDigits: 6 },
|
|
40
|
+
{ companyPrefixBits: 20, companyPrefixDigits: 6, itemReferenceBits: 24, itemReferenceDigits: 7 },
|
|
41
|
+
];
|
|
42
|
+
/** The GS1 AI encodable character set 82, which the SGTIN-198 serial and every Digital Link qualifier value draw from. */
|
|
43
|
+
export const GS1_CHARACTER_SET_82 = /^[!"%&'()*+,\-./0-9:;<=>?A-Z_a-z]+$/;
|
|
44
|
+
const refuse = (reason, detail, header) => ({ ok: false, reason, detail, ...(header == null ? {} : { header }) });
|
|
45
|
+
/** A string of `0` and `1` from lower-case hexadecimal, four bits per character (compression standard §4.2.1). */
|
|
46
|
+
export function bitsFromHex(hex) {
|
|
47
|
+
if (hex.length === 0 || !/^[0-9a-f]+$/.test(hex))
|
|
48
|
+
return undefined;
|
|
49
|
+
let bits = '';
|
|
50
|
+
for (const character of hex)
|
|
51
|
+
bits += parseInt(character, 16).toString(2).padStart(4, '0');
|
|
52
|
+
return bits;
|
|
53
|
+
}
|
|
54
|
+
/** A string of `0` and `1` from the URI-safe base 64 alphabet, six bits per character (compression standard §4.1). */
|
|
55
|
+
export function bitsFromUriSafeBase64(text) {
|
|
56
|
+
if (text.length === 0)
|
|
57
|
+
return undefined;
|
|
58
|
+
let bits = '';
|
|
59
|
+
for (const character of text) {
|
|
60
|
+
const index = URI_SAFE_BASE64_ALPHABET.indexOf(character);
|
|
61
|
+
if (index === -1)
|
|
62
|
+
return undefined;
|
|
63
|
+
bits += index.toString(2).padStart(6, '0');
|
|
64
|
+
}
|
|
65
|
+
return bits;
|
|
66
|
+
}
|
|
67
|
+
function integerOf(bits) {
|
|
68
|
+
let value = 0n;
|
|
69
|
+
for (const bit of bits)
|
|
70
|
+
value = (value << 1n) | (bit === '1' ? 1n : 0n);
|
|
71
|
+
return value;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The serial of an SGTIN-198: twenty seven-bit characters, the string ending
|
|
75
|
+
* at the first all-zero character, everything after it required to be zero
|
|
76
|
+
* padding. The Tag Data Standard draws the characters from the encodable set
|
|
77
|
+
* 82; a character outside it, or an empty serial, is refused.
|
|
78
|
+
*/
|
|
79
|
+
function decodeSerial198(bits) {
|
|
80
|
+
let serial = '';
|
|
81
|
+
let ended = false;
|
|
82
|
+
for (let index = 0; index < 20; index++) {
|
|
83
|
+
const code = Number(integerOf(bits.slice(index * 7, index * 7 + 7)));
|
|
84
|
+
if (code === 0) {
|
|
85
|
+
ended = true;
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (ended)
|
|
89
|
+
return { error: 'a character follows the serial terminator' };
|
|
90
|
+
const character = String.fromCharCode(code);
|
|
91
|
+
if (!GS1_CHARACTER_SET_82.test(character))
|
|
92
|
+
return { error: `character code ${code} is outside the GS1 encodable set 82` };
|
|
93
|
+
serial += character;
|
|
94
|
+
}
|
|
95
|
+
if (serial.length === 0)
|
|
96
|
+
return { error: 'the serial is empty' };
|
|
97
|
+
return { serial };
|
|
98
|
+
}
|
|
99
|
+
/** The Tag Data Standard's percent-escaping of the pure-identity URI's serial component. */
|
|
100
|
+
function escapeSerialForUri(serial) {
|
|
101
|
+
return serial.replace(/[%"&/<>?#]/g, (character) => `%${character.charCodeAt(0).toString(16).toUpperCase().padStart(2, '0')}`);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Decode an EPC binary string, given as bits, under the SGTIN-96 and SGTIN-198
|
|
105
|
+
* schemes. The bit count must be exactly the scheme's length; a hexadecimal
|
|
106
|
+
* encoding of a 198-bit string carries two padding bits, which must be zero.
|
|
107
|
+
*/
|
|
108
|
+
export function decodeEpcBinaryBits(bits) {
|
|
109
|
+
if (bits.length < 8)
|
|
110
|
+
return refuse('length', `${bits.length} bits cannot carry an EPC header`);
|
|
111
|
+
const header = Number(integerOf(bits.slice(0, 8)));
|
|
112
|
+
const headerHex = header.toString(16).padStart(2, '0');
|
|
113
|
+
let scheme;
|
|
114
|
+
let serialBits;
|
|
115
|
+
if (header === SGTIN_96_HEADER) {
|
|
116
|
+
scheme = 'sgtin-96';
|
|
117
|
+
serialBits = 38;
|
|
118
|
+
if (bits.length !== 96)
|
|
119
|
+
return refuse('length', `SGTIN-96 is 96 bits; ${bits.length} were given`, headerHex);
|
|
120
|
+
}
|
|
121
|
+
else if (header === SGTIN_198_HEADER) {
|
|
122
|
+
scheme = 'sgtin-198';
|
|
123
|
+
serialBits = 140;
|
|
124
|
+
if (bits.length === 200) {
|
|
125
|
+
if (bits.slice(198) !== '00')
|
|
126
|
+
return refuse('length', 'the two padding bits after an SGTIN-198 must be zero', headerHex);
|
|
127
|
+
bits = bits.slice(0, 198);
|
|
128
|
+
}
|
|
129
|
+
else if (bits.length !== 198) {
|
|
130
|
+
return refuse('length', `SGTIN-198 is 198 bits (200 in hexadecimal with zero padding); ${bits.length} were given`, headerHex);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
return refuse('unsupported-epc-scheme', `EPC header ${headerHex} is not SGTIN-96 (30) or SGTIN-198 (36); only serialised trade items are decoded`, headerHex);
|
|
135
|
+
}
|
|
136
|
+
const filter = Number(integerOf(bits.slice(8, 11)));
|
|
137
|
+
const partition = Number(integerOf(bits.slice(11, 14)));
|
|
138
|
+
const layout = SGTIN_PARTITIONS[partition];
|
|
139
|
+
if (layout == null)
|
|
140
|
+
return refuse('partition', `partition value ${partition} is not defined for SGTIN`, headerHex);
|
|
141
|
+
let at = 14;
|
|
142
|
+
const companyPrefixValue = integerOf(bits.slice(at, at + layout.companyPrefixBits));
|
|
143
|
+
at += layout.companyPrefixBits;
|
|
144
|
+
const itemReferenceValue = integerOf(bits.slice(at, at + layout.itemReferenceBits));
|
|
145
|
+
at += layout.itemReferenceBits;
|
|
146
|
+
if (companyPrefixValue >= 10n ** BigInt(layout.companyPrefixDigits))
|
|
147
|
+
return refuse('company-prefix', `the company prefix exceeds ${layout.companyPrefixDigits} digits`, headerHex);
|
|
148
|
+
if (itemReferenceValue >= 10n ** BigInt(layout.itemReferenceDigits))
|
|
149
|
+
return refuse('item-reference', `the item reference exceeds ${layout.itemReferenceDigits} digits`, headerHex);
|
|
150
|
+
const companyPrefix = companyPrefixValue.toString().padStart(layout.companyPrefixDigits, '0');
|
|
151
|
+
const itemReference = itemReferenceValue.toString().padStart(layout.itemReferenceDigits, '0');
|
|
152
|
+
let serial;
|
|
153
|
+
const serialField = bits.slice(at, at + serialBits);
|
|
154
|
+
if (scheme === 'sgtin-96') {
|
|
155
|
+
serial = integerOf(serialField).toString();
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
const decoded = decodeSerial198(serialField);
|
|
159
|
+
if ('error' in decoded)
|
|
160
|
+
return refuse('serial', decoded.error, headerHex);
|
|
161
|
+
serial = decoded.serial;
|
|
162
|
+
}
|
|
163
|
+
const thirteen = `${itemReference[0]}${companyPrefix}${itemReference.slice(1)}`;
|
|
164
|
+
const gtin = `${thirteen}${gs1CheckDigit(thirteen)}`;
|
|
165
|
+
return {
|
|
166
|
+
ok: true,
|
|
167
|
+
scheme,
|
|
168
|
+
header,
|
|
169
|
+
filter,
|
|
170
|
+
partition,
|
|
171
|
+
companyPrefix,
|
|
172
|
+
itemReference,
|
|
173
|
+
gtin,
|
|
174
|
+
serial,
|
|
175
|
+
epcUri: `urn:epc:id:sgtin:${companyPrefix}.${itemReference}.${escapeSerialForUri(serial)}`,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Decode the compression string of a special compressed GS1 Digital Link URI:
|
|
180
|
+
* the two characters after the slash select the alphabet (`eh` hexadecimal,
|
|
181
|
+
* `ex` URI-safe base 64) and the rest is the EPC binary string.
|
|
182
|
+
*/
|
|
183
|
+
export function decodeEpcCompressionString(compressionString) {
|
|
184
|
+
if (compressionString.startsWith('eh')) {
|
|
185
|
+
const payload = compressionString.slice(2);
|
|
186
|
+
if (payload.length === 0)
|
|
187
|
+
return refuse('empty', 'nothing follows the eh prefix');
|
|
188
|
+
const bits = bitsFromHex(payload);
|
|
189
|
+
if (bits == null)
|
|
190
|
+
return refuse('not-hex', 'the characters after eh are not lower-case hexadecimal');
|
|
191
|
+
return decodeEpcBinaryBits(bits);
|
|
192
|
+
}
|
|
193
|
+
if (compressionString.startsWith('ex')) {
|
|
194
|
+
const payload = compressionString.slice(2);
|
|
195
|
+
if (payload.length === 0)
|
|
196
|
+
return refuse('empty', 'nothing follows the ex prefix');
|
|
197
|
+
const bits = bitsFromUriSafeBase64(payload);
|
|
198
|
+
if (bits == null)
|
|
199
|
+
return refuse('not-uri-safe-base64', 'the characters after ex are not from the URI-safe base 64 alphabet');
|
|
200
|
+
return decodeEpcBinaryBits(bits);
|
|
201
|
+
}
|
|
202
|
+
return refuse('unsupported-epc-scheme', 'the compression string begins with neither eh nor ex; the general GS1 Digital Link compression is not decoded here');
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* The inverse, for tests and for a writer that prints a compressed carrier:
|
|
206
|
+
* an SGTIN-96 or SGTIN-198 EPC binary string as bits, from its parts. Refuses
|
|
207
|
+
* a serial the scheme cannot carry rather than truncating it.
|
|
208
|
+
*/
|
|
209
|
+
export function encodeSgtinBits(input) {
|
|
210
|
+
const layout = SGTIN_PARTITIONS[input.partition];
|
|
211
|
+
if (layout == null)
|
|
212
|
+
throw new Error('partition value must be 0 to 6');
|
|
213
|
+
if (!/^\d+$/.test(input.companyPrefix) || input.companyPrefix.length !== layout.companyPrefixDigits)
|
|
214
|
+
throw new Error(`a partition ${input.partition} company prefix has ${layout.companyPrefixDigits} digits`);
|
|
215
|
+
if (!/^\d+$/.test(input.itemReference) || input.itemReference.length !== layout.itemReferenceDigits)
|
|
216
|
+
throw new Error(`a partition ${input.partition} item reference has ${layout.itemReferenceDigits} digits`);
|
|
217
|
+
if (!Number.isInteger(input.filter) || input.filter < 0 || input.filter > 7)
|
|
218
|
+
throw new Error('the filter value is three bits');
|
|
219
|
+
const field = (value, width) => value.toString(2).padStart(width, '0');
|
|
220
|
+
let bits = field(BigInt(input.scheme === 'sgtin-96' ? SGTIN_96_HEADER : SGTIN_198_HEADER), 8) + field(BigInt(input.filter), 3) + field(BigInt(input.partition), 3);
|
|
221
|
+
bits += field(BigInt(input.companyPrefix), layout.companyPrefixBits) + field(BigInt(input.itemReference), layout.itemReferenceBits);
|
|
222
|
+
if (input.scheme === 'sgtin-96') {
|
|
223
|
+
if (!/^(0|[1-9]\d*)$/.test(input.serial) || BigInt(input.serial) >= 2n ** 38n)
|
|
224
|
+
throw new Error('an SGTIN-96 serial is an integer below 2^38 without leading zeros');
|
|
225
|
+
bits += field(BigInt(input.serial), 38);
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
if (input.serial.length === 0 || input.serial.length > 20 || !GS1_CHARACTER_SET_82.test(input.serial))
|
|
229
|
+
throw new Error('an SGTIN-198 serial is 1 to 20 characters of the GS1 encodable set 82');
|
|
230
|
+
for (const character of input.serial)
|
|
231
|
+
bits += field(BigInt(character.charCodeAt(0)), 7);
|
|
232
|
+
bits = bits.padEnd(198, '0');
|
|
233
|
+
}
|
|
234
|
+
return bits;
|
|
235
|
+
}
|
|
236
|
+
/** Bits to the `eh` form: lower-case hexadecimal, zero-padded to a multiple of four bits. */
|
|
237
|
+
export function hexFromBits(bits) {
|
|
238
|
+
const padded = bits.padEnd(Math.ceil(bits.length / 4) * 4, '0');
|
|
239
|
+
let hex = '';
|
|
240
|
+
for (let at = 0; at < padded.length; at += 4)
|
|
241
|
+
hex += parseInt(padded.slice(at, at + 4), 2).toString(16);
|
|
242
|
+
return hex;
|
|
243
|
+
}
|
|
244
|
+
/** Bits to the `ex` form: the URI-safe base 64 alphabet, zero-padded to a multiple of six bits. */
|
|
245
|
+
export function uriSafeBase64FromBits(bits) {
|
|
246
|
+
const padded = bits.padEnd(Math.ceil(bits.length / 6) * 6, '0');
|
|
247
|
+
let text = '';
|
|
248
|
+
for (let at = 0; at < padded.length; at += 6)
|
|
249
|
+
text += URI_SAFE_BASE64_ALPHABET[parseInt(padded.slice(at, at + 6), 2)];
|
|
250
|
+
return text;
|
|
251
|
+
}
|
|
252
|
+
//# sourceMappingURL=gs1-epc-binary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gs1-epc-binary.js","sourceRoot":"","sources":["../src/gs1-epc-binary.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
import { type EpcBinaryRefusalReason, type SgtinDecoding } from './gs1-epc-binary.js';
|
|
2
|
+
/**
|
|
3
|
+
* The GS1 Web vocabulary namespace the resolver standard expands `gs1:` to
|
|
4
|
+
* (GS1-Conformant Resolver 1.2.1 §2.14). The published linkset context maps
|
|
5
|
+
* the same prefix to `http://gs1.org/voc/`; `normaliseLinkType` treats the
|
|
6
|
+
* three spellings as one so a linkset from another resolver is read
|
|
7
|
+
* correctly and this module always writes the standard's own.
|
|
8
|
+
*/
|
|
9
|
+
export declare const GS1_VOCABULARY = "https://ref.gs1.org/voc/";
|
|
10
|
+
/** The GS1 link types this profile uses, as full IRIs; a linkset key is always the full IRI. */
|
|
11
|
+
export declare const GS1_LINK_TYPES: {
|
|
12
|
+
readonly defaultLink: "https://ref.gs1.org/voc/defaultLink";
|
|
13
|
+
readonly defaultLinkMulti: "https://ref.gs1.org/voc/defaultLinkMulti";
|
|
14
|
+
readonly pip: "https://ref.gs1.org/voc/pip";
|
|
15
|
+
readonly sustainabilityInfo: "https://ref.gs1.org/voc/sustainabilityInfo";
|
|
16
|
+
readonly certificationInfo: "https://ref.gs1.org/voc/certificationInfo";
|
|
17
|
+
readonly epcis: "https://ref.gs1.org/voc/epcis";
|
|
18
|
+
readonly traceability: "https://ref.gs1.org/voc/traceability";
|
|
19
|
+
readonly recallStatus: "https://ref.gs1.org/voc/recallStatus";
|
|
20
|
+
readonly handledBy: "https://ref.gs1.org/voc/handledBy";
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* The namespace of the link types this standard owns, and the one relation it
|
|
24
|
+
* defines: a link to a passport's portable evidence package
|
|
25
|
+
* (`spec/portable-evidence.md`), for which the GS1 vocabulary has no term.
|
|
26
|
+
* The pinned linkset schema admits a link relation key only as a bare
|
|
27
|
+
* lower-case token or as an `http(s)` IRI of letters, digits, dots and
|
|
28
|
+
* slashes, so the relation is spelled without a hyphen under the programme's
|
|
29
|
+
* public host and versioned in its path; the standard's usual
|
|
30
|
+
* `bsv-blockchain.github.io` base cannot be a link relation under that schema.
|
|
31
|
+
*/
|
|
32
|
+
export declare const DPP_LINK_NAMESPACE = "https://dpp.bsvb.net/link/";
|
|
33
|
+
export declare const DPP_EVIDENCE_PACKAGE_LINK_TYPE = "https://dpp.bsvb.net/link/evidencePackage/1";
|
|
34
|
+
/** The media types and relations of the resolver standard §2.9 and §2.10. */
|
|
35
|
+
export declare const LINKSET_MEDIA_TYPE = "application/linkset+json";
|
|
36
|
+
export declare const LINKSET_CONTEXT_URI = "https://ref.gs1.org/standards/resolver/1.2.1/linkset-context";
|
|
37
|
+
export declare const JSON_LD_CONTEXT_RELATION = "http://www.w3.org/ns/json-ld#context";
|
|
38
|
+
/** The one primary key this profile hosts, and its three key qualifiers in the order the URI syntax fixes. */
|
|
39
|
+
export declare const SUPPORTED_PRIMARY_KEY = "01";
|
|
40
|
+
export declare const GTIN_QUALIFIER_ORDER: readonly ["22", "10", "21"];
|
|
41
|
+
export type GtinQualifierAi = (typeof GTIN_QUALIFIER_ORDER)[number];
|
|
42
|
+
export interface AiValue {
|
|
43
|
+
ai: string;
|
|
44
|
+
value: string;
|
|
45
|
+
}
|
|
46
|
+
export interface DataAttribute extends AiValue {
|
|
47
|
+
/** True when this module knows the AI's format and the value met it; false when the AI is unknown here and only the character set was checked. */
|
|
48
|
+
validated: boolean;
|
|
49
|
+
}
|
|
50
|
+
export interface LinkTypeRequest {
|
|
51
|
+
/** The query parameter as written. */
|
|
52
|
+
raw: string;
|
|
53
|
+
/** The full IRI, when the value was a full IRI or a `gs1:` CURIE. */
|
|
54
|
+
iri?: string;
|
|
55
|
+
/** True for `linkset` (and its common alias `all`): the client wants the list, not a redirect. */
|
|
56
|
+
linkset?: boolean;
|
|
57
|
+
}
|
|
58
|
+
export interface Gs1Key {
|
|
59
|
+
ai: '01';
|
|
60
|
+
/** Fourteen digits. */
|
|
61
|
+
value: string;
|
|
62
|
+
qualifiers: AiValue[];
|
|
63
|
+
}
|
|
64
|
+
export interface ParsedUncompressedUri {
|
|
65
|
+
kind: 'uncompressed';
|
|
66
|
+
origin: string;
|
|
67
|
+
host: string;
|
|
68
|
+
/** The path before `/01`, without a trailing slash; empty for a root resolver. */
|
|
69
|
+
pathStem: string;
|
|
70
|
+
primaryKey: {
|
|
71
|
+
ai: '01';
|
|
72
|
+
value: string;
|
|
73
|
+
checkDigitValid: boolean;
|
|
74
|
+
demonstration: boolean;
|
|
75
|
+
};
|
|
76
|
+
/** In the order the syntax fixes: 22, then 10, then 21. */
|
|
77
|
+
qualifiers: AiValue[];
|
|
78
|
+
dataAttributes: DataAttribute[];
|
|
79
|
+
linkType?: LinkTypeRequest;
|
|
80
|
+
/** Query parameters that are neither AIs nor linkType, preserved for forwarding. */
|
|
81
|
+
otherQuery: Array<[string, string]>;
|
|
82
|
+
}
|
|
83
|
+
export interface ParsedCompressedUri {
|
|
84
|
+
kind: 'compressed';
|
|
85
|
+
origin: string;
|
|
86
|
+
host: string;
|
|
87
|
+
pathStem: string;
|
|
88
|
+
prefix: 'eh' | 'ex';
|
|
89
|
+
/** The whole compression string, prefix included. */
|
|
90
|
+
compressionString: string;
|
|
91
|
+
/** The query string as given, so it can be carried to the uncompressed form. */
|
|
92
|
+
query: string;
|
|
93
|
+
}
|
|
94
|
+
export type UriRefusalReason = 'not-a-url' | 'scheme' | 'percent-encoding' | 'no-primary-key' | 'unsupported-primary-key' | 'primary-key-not-a-gtin' | 'trailing-segment' | 'qualifier-order' | 'qualifier-repeated' | 'qualifier-unsupported' | 'qualifier-value' | 'key-in-query' | 'attribute-ai' | 'attribute-value';
|
|
95
|
+
export interface InvalidUri {
|
|
96
|
+
kind: 'invalid';
|
|
97
|
+
reason: UriRefusalReason;
|
|
98
|
+
detail: string;
|
|
99
|
+
}
|
|
100
|
+
export type ParsedGs1Uri = ParsedUncompressedUri | ParsedCompressedUri | InvalidUri;
|
|
101
|
+
/**
|
|
102
|
+
* Read a GS1 Digital Link URI in the grammar this profile hosts: primary key
|
|
103
|
+
* 01, its key qualifiers 22, 10 and 21 in that order, data attributes in the
|
|
104
|
+
* query, `linkType` beside them, and the special compressed form of the EPC
|
|
105
|
+
* binary standard. Refusals are answers, not exceptions, each with the
|
|
106
|
+
* standard's reason: a resolver turns them into 400 and a client into a
|
|
107
|
+
* finding. One trailing slash is tolerated (resolver standard §2.13).
|
|
108
|
+
*
|
|
109
|
+
* A URI this reads is syntactically a GS1 Digital Link URI and nothing more:
|
|
110
|
+
* the check digit is reported, not enforced, because a historical record may
|
|
111
|
+
* carry a GTIN that fails it, and allocation authority is never inferred.
|
|
112
|
+
*/
|
|
113
|
+
export declare function parseGs1DigitalLinkUri(uri: string): ParsedGs1Uri;
|
|
114
|
+
export interface Decompressed {
|
|
115
|
+
ok: true;
|
|
116
|
+
/** The fully uncompressed URI under the stem the compressed form carried. */
|
|
117
|
+
uri: string;
|
|
118
|
+
key: Gs1Key;
|
|
119
|
+
epc: SgtinDecoding;
|
|
120
|
+
}
|
|
121
|
+
export type DecompressionResult = Decompressed | {
|
|
122
|
+
ok: false;
|
|
123
|
+
reason: 'not-compressed' | EpcBinaryRefusalReason;
|
|
124
|
+
detail: string;
|
|
125
|
+
header?: string;
|
|
126
|
+
};
|
|
127
|
+
/**
|
|
128
|
+
* Turn a special compressed GS1 Digital Link URI into its uncompressed form
|
|
129
|
+
* (compression standard §4.2.1 and §4.2.2): the stem up to the compression
|
|
130
|
+
* string is kept, the EPC binary string after `eh` or `ex` is decoded under
|
|
131
|
+
* the Tag Data Standard, and the result is `${stem}/01/{gtin}/21/{serial}`.
|
|
132
|
+
* A query string is carried across unchanged. An uncompressed URI is refused
|
|
133
|
+
* as `not-compressed` rather than echoed, so a caller never mistakes a
|
|
134
|
+
* pass-through for a decoding.
|
|
135
|
+
*/
|
|
136
|
+
export declare function decompressGs1DigitalLink(uri: string): DecompressionResult;
|
|
137
|
+
/** The key an uncompressed parse names, or one built from its parts with the qualifiers put in canonical order. */
|
|
138
|
+
export declare function gs1KeyOf(source: ParsedUncompressedUri | {
|
|
139
|
+
gtin: string;
|
|
140
|
+
qualifiers?: AiValue[];
|
|
141
|
+
}): Gs1Key;
|
|
142
|
+
/**
|
|
143
|
+
* The canonical spelling of a key tuple, `01:{gtin14}` followed by each
|
|
144
|
+
* qualifier as `ai:value` in the syntax's order, joined by `|`. Two Digital
|
|
145
|
+
* Link URIs under different hosts with the same tuple name the same entity;
|
|
146
|
+
* the same serial under a different GTIN does not. Equivalence is a statement
|
|
147
|
+
* about identifiers only: it is not authority to bind a signed credential to
|
|
148
|
+
* a passport, which needs the binding evidence `spec/gs1-discovery.md` §2
|
|
149
|
+
* names.
|
|
150
|
+
*/
|
|
151
|
+
export declare function gs1KeyTuple(key: Gs1Key | ParsedUncompressedUri): string;
|
|
152
|
+
export declare function sameGs1Key(a: Gs1Key | ParsedUncompressedUri, b: Gs1Key | ParsedUncompressedUri): boolean;
|
|
153
|
+
/** The granularity a key tuple names, by its most specific qualifier. */
|
|
154
|
+
export type KeyGranularity = 'model' | 'variant' | 'lot' | 'item';
|
|
155
|
+
export declare function granularityOf(qualifiers: readonly AiValue[]): KeyGranularity;
|
|
156
|
+
/** The uncompressed Digital Link URI of a key under a resolver root (origin plus optional stem, no trailing slash). */
|
|
157
|
+
export declare function uncompressedUri(resolverRoot: string, key: Gs1Key): string;
|
|
158
|
+
/** The path of the legacy evidence JSON answered at the API origin, and its alias, for an item key; undefined for any other granularity. */
|
|
159
|
+
export declare function legacyEvidencePaths(key: Gs1Key): {
|
|
160
|
+
legacy: string;
|
|
161
|
+
alias: string;
|
|
162
|
+
} | undefined;
|
|
163
|
+
export type Disclosure = 'public' | 'restricted';
|
|
164
|
+
export interface ResolutionLink {
|
|
165
|
+
/** The descriptive link relation type, as a full IRI. */
|
|
166
|
+
rel: string;
|
|
167
|
+
href: string;
|
|
168
|
+
title: string;
|
|
169
|
+
/** An IANA media type, when declared. */
|
|
170
|
+
type?: string;
|
|
171
|
+
/** BCP 47 language tags, when declared. */
|
|
172
|
+
hreflang?: string[];
|
|
173
|
+
context?: string[];
|
|
174
|
+
/** `single`: the entity's one default link (no optional attributes); `multi`: a default refined by request headers. */
|
|
175
|
+
default?: 'single' | 'multi';
|
|
176
|
+
/** Whether public discovery may return the link; a restricted link is only ever returned to an authorised audience, and access is enforced again at its target. */
|
|
177
|
+
disclosure: Disclosure;
|
|
178
|
+
/** Whether the resolver forwards the request's query string on redirect; the standard's default is to forward everything (§2.12). */
|
|
179
|
+
forwardQuery?: boolean;
|
|
180
|
+
}
|
|
181
|
+
export interface ResolutionRecord {
|
|
182
|
+
key: {
|
|
183
|
+
ai: '01';
|
|
184
|
+
value: string;
|
|
185
|
+
};
|
|
186
|
+
/** The qualifiers this record is registered at, in the syntax's order; a record with 21 carries neither 22 nor 10 (resolver standard §2.5.10). */
|
|
187
|
+
qualifiers: AiValue[];
|
|
188
|
+
/** The exact signed passport identifier bound to this entity, where the binding is established; never inferred from the key. */
|
|
189
|
+
passportId?: string;
|
|
190
|
+
/** A reference to the evidence or policy establishing that binding. */
|
|
191
|
+
bindingRef?: string;
|
|
192
|
+
links: ResolutionLink[];
|
|
193
|
+
/** The revision of the configuration the record was written under. */
|
|
194
|
+
configurationRevision: string;
|
|
195
|
+
description?: string;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Every rule a record must meet before it is stored, so the resolver validates
|
|
199
|
+
* at ingestion and not at every request (resolver standard §2.4): a GTIN
|
|
200
|
+
* whose check digit holds, qualifiers in order with no repeat and no TPX, a
|
|
201
|
+
* serial never registered beside a variant or a lot, at most one single
|
|
202
|
+
* default link with no optional attributes, and every link with an `https`
|
|
203
|
+
* target, a title, a relation the linkset schema can carry, and declared
|
|
204
|
+
* disclosure. An empty list means the record is admissible.
|
|
205
|
+
*/
|
|
206
|
+
export declare function resolutionRecordProblems(record: ResolutionRecord): string[];
|
|
207
|
+
export interface ResolutionRequest {
|
|
208
|
+
key: Gs1Key;
|
|
209
|
+
/** Public discovery never sees a restricted link; an authorised audience sees it flagged. */
|
|
210
|
+
audience: 'public' | 'authorised';
|
|
211
|
+
/** The requested link type as a full IRI, `linkset` for the list, or absent for the default. */
|
|
212
|
+
linkType?: string | 'linkset';
|
|
213
|
+
/** Acceptable media types, most preferred first (`parseAcceptHeader`). */
|
|
214
|
+
accept?: string[];
|
|
215
|
+
/** Preferred languages, most preferred first (`parseAcceptLanguage`). */
|
|
216
|
+
acceptLanguage?: string[];
|
|
217
|
+
context?: string[];
|
|
218
|
+
/** The origin and stem the linkset anchors are written under. */
|
|
219
|
+
resolverRoot: string;
|
|
220
|
+
}
|
|
221
|
+
export interface ResolvedLink extends ResolutionLink {
|
|
222
|
+
/** The uncompressed URI of the record the link was registered at, never the request's. */
|
|
223
|
+
anchor: string;
|
|
224
|
+
/** The granularity of that record: a model-level link answering an item request is still model information. */
|
|
225
|
+
granularity: KeyGranularity;
|
|
226
|
+
record: ResolutionRecord;
|
|
227
|
+
}
|
|
228
|
+
export interface MatchedRecord {
|
|
229
|
+
record: ResolutionRecord;
|
|
230
|
+
anchor: string;
|
|
231
|
+
granularity: KeyGranularity;
|
|
232
|
+
}
|
|
233
|
+
export type ResolutionOutcome = {
|
|
234
|
+
outcome: 'no-records';
|
|
235
|
+
matched: [];
|
|
236
|
+
} | {
|
|
237
|
+
outcome: 'linkset';
|
|
238
|
+
matched: MatchedRecord[];
|
|
239
|
+
links: ResolvedLink[];
|
|
240
|
+
} | {
|
|
241
|
+
outcome: 'redirect';
|
|
242
|
+
matched: MatchedRecord[];
|
|
243
|
+
link: ResolvedLink;
|
|
244
|
+
links: ResolvedLink[];
|
|
245
|
+
} | {
|
|
246
|
+
outcome: 'multiple-choices';
|
|
247
|
+
matched: MatchedRecord[];
|
|
248
|
+
candidates: ResolvedLink[];
|
|
249
|
+
links: ResolvedLink[];
|
|
250
|
+
} | {
|
|
251
|
+
outcome: 'not-found';
|
|
252
|
+
matched: MatchedRecord[];
|
|
253
|
+
requested: string;
|
|
254
|
+
links: ResolvedLink[];
|
|
255
|
+
};
|
|
256
|
+
/** `text/html;q=0.9, application/json` to `['application/json', 'text/html']`: q-values honoured, zero excluded. */
|
|
257
|
+
export declare function parseAcceptHeader(header: string | undefined): string[];
|
|
258
|
+
/** `fr-CH, fr;q=0.9, en;q=0.8` to `['fr-CH', 'fr', 'en']`. */
|
|
259
|
+
export declare function parseAcceptLanguage(header: string | undefined): string[];
|
|
260
|
+
/**
|
|
261
|
+
* The records a request selects: the union the resolver standard §2.5.10
|
|
262
|
+
* fixes, most specific level first, so a link registered at the lot level is
|
|
263
|
+
* found under a serialised request and a link at the model level under every
|
|
264
|
+
* request. Each match keeps its own anchor and granularity.
|
|
265
|
+
*/
|
|
266
|
+
export declare function matchRecords(records: readonly ResolutionRecord[], key: Gs1Key, resolverRoot: string): MatchedRecord[];
|
|
267
|
+
/**
|
|
268
|
+
* The best match among candidates of one link type (resolver standard §2.6.3,
|
|
269
|
+
* media type before language before context): the unique best, or every
|
|
270
|
+
* candidate when the best is not unique, so the resolver answers 300 rather
|
|
271
|
+
* than choosing.
|
|
272
|
+
*/
|
|
273
|
+
export declare function bestMatch<L extends ResolutionLink>(candidates: readonly L[], request: Pick<ResolutionRequest, 'accept' | 'acceptLanguage' | 'context'>): {
|
|
274
|
+
unique: L;
|
|
275
|
+
} | {
|
|
276
|
+
tie: L[];
|
|
277
|
+
} | undefined;
|
|
278
|
+
/**
|
|
279
|
+
* Resolve a request against the records this resolver holds, exactly as the
|
|
280
|
+
* standard's flow chart does and without any I/O: which records the key
|
|
281
|
+
* selects, which links the audience may see, then the default, the requested
|
|
282
|
+
* type, the list, or the refusal. A restricted link is never returned to a
|
|
283
|
+
* public audience. The redirect target is the link's own `href`; forwarding
|
|
284
|
+
* the request's query string onto it (§2.12) is the route's step, because
|
|
285
|
+
* the query is the route's to read.
|
|
286
|
+
*/
|
|
287
|
+
export declare function resolveLinks(records: readonly ResolutionRecord[], request: ResolutionRequest): ResolutionOutcome;
|
|
288
|
+
export interface LinksetLink {
|
|
289
|
+
href: string;
|
|
290
|
+
title: string;
|
|
291
|
+
type?: string;
|
|
292
|
+
hreflang?: string[];
|
|
293
|
+
context?: string[];
|
|
294
|
+
fwqs?: boolean;
|
|
295
|
+
public?: boolean;
|
|
296
|
+
}
|
|
297
|
+
/** One link context object of RFC 9264 as the GS1 schema shapes it: the anchor, an optional description and the links keyed by relation. */
|
|
298
|
+
export type LinksetEntry = {
|
|
299
|
+
anchor: string;
|
|
300
|
+
description?: string;
|
|
301
|
+
} & Record<string, unknown>;
|
|
302
|
+
export interface LinksetDocument {
|
|
303
|
+
linkset: LinksetEntry[];
|
|
304
|
+
}
|
|
305
|
+
/** One relation IRI for the three spellings of the GS1 vocabulary; anything else is returned as given. */
|
|
306
|
+
export declare function normaliseLinkType(iri: string): string;
|
|
307
|
+
/**
|
|
308
|
+
* The linkset a resolver returns for a request (resolver standard §2.9 and
|
|
309
|
+
* §2.10): one link context object per matched record, most specific first,
|
|
310
|
+
* its anchor the uncompressed URI of that record's own identifier, every link
|
|
311
|
+
* under its descriptive relation and a default additionally under
|
|
312
|
+
* `gs1:defaultLink` or `gs1:defaultLinkMulti`. Links a public audience may
|
|
313
|
+
* not see are absent, not blanked; a restricted link shown to an authorised
|
|
314
|
+
* audience says `public: false`. The document validates against the pinned
|
|
315
|
+
* linkset schema.
|
|
316
|
+
*/
|
|
317
|
+
export declare function linksetDocument(records: readonly ResolutionRecord[], request: Omit<ResolutionRequest, 'linkType'>): LinksetDocument | undefined;
|
|
318
|
+
export interface LinkSelection {
|
|
319
|
+
rel: string;
|
|
320
|
+
mediaType?: string;
|
|
321
|
+
language?: string;
|
|
322
|
+
context?: string;
|
|
323
|
+
}
|
|
324
|
+
export type SelectedLink = {
|
|
325
|
+
outcome: 'selected';
|
|
326
|
+
link: LinksetLink;
|
|
327
|
+
anchor: string;
|
|
328
|
+
scope: {
|
|
329
|
+
key?: Gs1Key;
|
|
330
|
+
granularity: KeyGranularity | 'unknown';
|
|
331
|
+
};
|
|
332
|
+
} | {
|
|
333
|
+
outcome: 'ambiguous';
|
|
334
|
+
candidates: Array<{
|
|
335
|
+
link: LinksetLink;
|
|
336
|
+
anchor: string;
|
|
337
|
+
}>;
|
|
338
|
+
} | {
|
|
339
|
+
outcome: 'not-found';
|
|
340
|
+
available: string[];
|
|
341
|
+
};
|
|
342
|
+
/**
|
|
343
|
+
* A discovery client's choice over a linkset another resolver returned: the
|
|
344
|
+
* links under the requested relation (a full IRI or a `gs1:` CURIE) across
|
|
345
|
+
* every link context object, the best match by media type, language and
|
|
346
|
+
* context, and the anchor's own scope beside the result, so a link found at
|
|
347
|
+
* the model level under an item request is handed back as model
|
|
348
|
+
* information. An anchor that is not a Digital Link URI this module reads
|
|
349
|
+
* has scope `unknown`; it is not guessed.
|
|
350
|
+
*/
|
|
351
|
+
export declare function selectLink(linkset: LinksetDocument, selection: LinkSelection): SelectedLink;
|
|
352
|
+
export interface ResolverDescriptionConfig {
|
|
353
|
+
/** The origin, with an optional stem, the resolver answers at; no trailing slash. */
|
|
354
|
+
resolverRoot: string;
|
|
355
|
+
name?: string;
|
|
356
|
+
contact?: {
|
|
357
|
+
fn?: string;
|
|
358
|
+
hasAddress?: {
|
|
359
|
+
streetAddress?: string;
|
|
360
|
+
locality?: string;
|
|
361
|
+
region?: string;
|
|
362
|
+
'postal-code'?: string;
|
|
363
|
+
};
|
|
364
|
+
hasTelephone?: string;
|
|
365
|
+
};
|
|
366
|
+
supportedContextValuesEnumerated?: string[];
|
|
367
|
+
extensionProfile?: string;
|
|
368
|
+
}
|
|
369
|
+
export interface ResolverDescription {
|
|
370
|
+
name?: string;
|
|
371
|
+
resolverRoot: string;
|
|
372
|
+
supportedPrimaryKeys: ['01'];
|
|
373
|
+
supportedLinkType: Array<{
|
|
374
|
+
namespace: string;
|
|
375
|
+
prefix: string;
|
|
376
|
+
}>;
|
|
377
|
+
linkTypeDefaultCanBeLinkset: false;
|
|
378
|
+
supportedContextValuesEnumerated?: string[];
|
|
379
|
+
contact?: ResolverDescriptionConfig['contact'];
|
|
380
|
+
extensionProfile?: string;
|
|
381
|
+
jsonLdContextLocation: string;
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* The `/.well-known/gs1resolver` document (resolver standard §3) for the one
|
|
385
|
+
* scope this profile hosts: primary key 01 with every qualifier, the GS1
|
|
386
|
+
* vocabulary and this standard's own link namespace, `linkset` never the
|
|
387
|
+
* default, and the pinned GS1 context for JSON linksets. It is published only
|
|
388
|
+
* by an origin that actually provides the resolver contract; the legacy API
|
|
389
|
+
* origin does not describe itself as one.
|
|
390
|
+
*/
|
|
391
|
+
export declare function describeResolver(config: ResolverDescriptionConfig): ResolverDescription;
|
|
392
|
+
//# sourceMappingURL=gs1-resolution.d.ts.map
|