@irvinebroque/http-rfc-utils 0.1.0
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 +21 -0
- package/README.md +222 -0
- package/dist/auth.d.ts +139 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +991 -0
- package/dist/auth.js.map +1 -0
- package/dist/cache-status.d.ts +15 -0
- package/dist/cache-status.d.ts.map +1 -0
- package/dist/cache-status.js +152 -0
- package/dist/cache-status.js.map +1 -0
- package/dist/cache.d.ts +94 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +244 -0
- package/dist/cache.js.map +1 -0
- package/dist/client-hints.d.ts +23 -0
- package/dist/client-hints.d.ts.map +1 -0
- package/dist/client-hints.js +81 -0
- package/dist/client-hints.js.map +1 -0
- package/dist/conditional.d.ts +97 -0
- package/dist/conditional.d.ts.map +1 -0
- package/dist/conditional.js +300 -0
- package/dist/conditional.js.map +1 -0
- package/dist/content-disposition.d.ts +23 -0
- package/dist/content-disposition.d.ts.map +1 -0
- package/dist/content-disposition.js +122 -0
- package/dist/content-disposition.js.map +1 -0
- package/dist/cookie.d.ts +43 -0
- package/dist/cookie.d.ts.map +1 -0
- package/dist/cookie.js +472 -0
- package/dist/cookie.js.map +1 -0
- package/dist/cors.d.ts +53 -0
- package/dist/cors.d.ts.map +1 -0
- package/dist/cors.js +170 -0
- package/dist/cors.js.map +1 -0
- package/dist/datetime.d.ts +53 -0
- package/dist/datetime.d.ts.map +1 -0
- package/dist/datetime.js +205 -0
- package/dist/datetime.js.map +1 -0
- package/dist/digest.d.ts +220 -0
- package/dist/digest.d.ts.map +1 -0
- package/dist/digest.js +355 -0
- package/dist/digest.js.map +1 -0
- package/dist/encoding.d.ts +14 -0
- package/dist/encoding.d.ts.map +1 -0
- package/dist/encoding.js +86 -0
- package/dist/encoding.js.map +1 -0
- package/dist/etag.d.ts +55 -0
- package/dist/etag.d.ts.map +1 -0
- package/dist/etag.js +182 -0
- package/dist/etag.js.map +1 -0
- package/dist/ext-value.d.ts +40 -0
- package/dist/ext-value.d.ts.map +1 -0
- package/dist/ext-value.js +119 -0
- package/dist/ext-value.js.map +1 -0
- package/dist/forwarded.d.ts +14 -0
- package/dist/forwarded.d.ts.map +1 -0
- package/dist/forwarded.js +93 -0
- package/dist/forwarded.js.map +1 -0
- package/dist/header-utils.d.ts +71 -0
- package/dist/header-utils.d.ts.map +1 -0
- package/dist/header-utils.js +143 -0
- package/dist/header-utils.js.map +1 -0
- package/dist/headers.d.ts +71 -0
- package/dist/headers.d.ts.map +1 -0
- package/dist/headers.js +134 -0
- package/dist/headers.js.map +1 -0
- package/dist/hsts.d.ts +15 -0
- package/dist/hsts.d.ts.map +1 -0
- package/dist/hsts.js +106 -0
- package/dist/hsts.js.map +1 -0
- package/dist/http-signatures.d.ts +202 -0
- package/dist/http-signatures.d.ts.map +1 -0
- package/dist/http-signatures.js +720 -0
- package/dist/http-signatures.js.map +1 -0
- package/dist/index.d.ts +41 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +125 -0
- package/dist/index.js.map +1 -0
- package/dist/json-pointer.d.ts +97 -0
- package/dist/json-pointer.d.ts.map +1 -0
- package/dist/json-pointer.js +278 -0
- package/dist/json-pointer.js.map +1 -0
- package/dist/jsonpath.d.ts +98 -0
- package/dist/jsonpath.d.ts.map +1 -0
- package/dist/jsonpath.js +1470 -0
- package/dist/jsonpath.js.map +1 -0
- package/dist/language.d.ts +14 -0
- package/dist/language.d.ts.map +1 -0
- package/dist/language.js +95 -0
- package/dist/language.js.map +1 -0
- package/dist/link.d.ts +102 -0
- package/dist/link.d.ts.map +1 -0
- package/dist/link.js +437 -0
- package/dist/link.js.map +1 -0
- package/dist/linkset.d.ts +111 -0
- package/dist/linkset.d.ts.map +1 -0
- package/dist/linkset.js +501 -0
- package/dist/linkset.js.map +1 -0
- package/dist/negotiate.d.ts +71 -0
- package/dist/negotiate.d.ts.map +1 -0
- package/dist/negotiate.js +357 -0
- package/dist/negotiate.js.map +1 -0
- package/dist/pagination.d.ts +80 -0
- package/dist/pagination.d.ts.map +1 -0
- package/dist/pagination.js +188 -0
- package/dist/pagination.js.map +1 -0
- package/dist/prefer.d.ts +18 -0
- package/dist/prefer.d.ts.map +1 -0
- package/dist/prefer.js +93 -0
- package/dist/prefer.js.map +1 -0
- package/dist/problem.d.ts +54 -0
- package/dist/problem.d.ts.map +1 -0
- package/dist/problem.js +104 -0
- package/dist/problem.js.map +1 -0
- package/dist/proxy-status.d.ts +28 -0
- package/dist/proxy-status.d.ts.map +1 -0
- package/dist/proxy-status.js +220 -0
- package/dist/proxy-status.js.map +1 -0
- package/dist/range.d.ts +28 -0
- package/dist/range.d.ts.map +1 -0
- package/dist/range.js +243 -0
- package/dist/range.js.map +1 -0
- package/dist/response.d.ts +101 -0
- package/dist/response.d.ts.map +1 -0
- package/dist/response.js +200 -0
- package/dist/response.js.map +1 -0
- package/dist/sorting.d.ts +66 -0
- package/dist/sorting.d.ts.map +1 -0
- package/dist/sorting.js +168 -0
- package/dist/sorting.js.map +1 -0
- package/dist/structured-fields.d.ts +30 -0
- package/dist/structured-fields.d.ts.map +1 -0
- package/dist/structured-fields.js +468 -0
- package/dist/structured-fields.js.map +1 -0
- package/dist/types.d.ts +772 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/dist/uri-template.d.ts +48 -0
- package/dist/uri-template.d.ts.map +1 -0
- package/dist/uri-template.js +483 -0
- package/dist/uri-template.js.map +1 -0
- package/dist/uri.d.ts +80 -0
- package/dist/uri.d.ts.map +1 -0
- package/dist/uri.js +423 -0
- package/dist/uri.js.map +1 -0
- package/package.json +66 -0
package/dist/link.js
ADDED
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Link header utilities per RFC 8288.
|
|
3
|
+
* RFC 8288 §3, §3.1, §3.2, §3.3, §3.4, §6.2.2.
|
|
4
|
+
* @see https://www.rfc-editor.org/rfc/rfc8288.html
|
|
5
|
+
*/
|
|
6
|
+
import { decodeExtValue } from './ext-value.js';
|
|
7
|
+
import { isEmptyHeader, quoteIfNeeded as quoteIfNeededImpl, unquote as unquoteImpl, } from './header-utils.js';
|
|
8
|
+
/**
|
|
9
|
+
* Standard link relation types (RFC 8288 Section 6.2.2 + common extensions)
|
|
10
|
+
*/
|
|
11
|
+
// RFC 8288 §6.2.2: Registered relation types.
|
|
12
|
+
// RFC 8594 §6: sunset link relation type.
|
|
13
|
+
// RFC 9264 §6: linkset link relation type.
|
|
14
|
+
// RFC 9727 §7.2: api-catalog link relation type.
|
|
15
|
+
export const LinkRelation = {
|
|
16
|
+
SELF: 'self',
|
|
17
|
+
FIRST: 'first',
|
|
18
|
+
LAST: 'last',
|
|
19
|
+
NEXT: 'next',
|
|
20
|
+
PREV: 'prev',
|
|
21
|
+
PREVIOUS: 'previous', // Alias for prev
|
|
22
|
+
ALTERNATE: 'alternate',
|
|
23
|
+
CANONICAL: 'canonical',
|
|
24
|
+
AUTHOR: 'author',
|
|
25
|
+
COLLECTION: 'collection',
|
|
26
|
+
ITEM: 'item',
|
|
27
|
+
EDIT: 'edit',
|
|
28
|
+
EDIT_FORM: 'edit-form',
|
|
29
|
+
CREATE_FORM: 'create-form',
|
|
30
|
+
SEARCH: 'search',
|
|
31
|
+
DESCRIBEDBY: 'describedby',
|
|
32
|
+
SERVICE_DESC: 'service-desc',
|
|
33
|
+
SERVICE_DOC: 'service-doc',
|
|
34
|
+
SERVICE_META: 'service-meta',
|
|
35
|
+
STATUS: 'status',
|
|
36
|
+
SUNSET: 'sunset', // RFC 8594 §6
|
|
37
|
+
LINKSET: 'linkset', // RFC 9264 §6
|
|
38
|
+
API_CATALOG: 'api-catalog', // RFC 9727 §7.2
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Quote a value if needed for Link header attribute.
|
|
42
|
+
* Values containing special characters must be quoted.
|
|
43
|
+
*
|
|
44
|
+
* @param value - The value to potentially quote
|
|
45
|
+
* @returns Quoted value if needed
|
|
46
|
+
*/
|
|
47
|
+
// RFC 8288 §3.2: Link-param quoting rules.
|
|
48
|
+
export function quoteIfNeeded(value) {
|
|
49
|
+
return quoteIfNeededImpl(value);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Unquote a quoted string value, handling escapes.
|
|
53
|
+
*
|
|
54
|
+
* @param value - Potentially quoted value
|
|
55
|
+
* @returns Unquoted value with escapes resolved
|
|
56
|
+
*/
|
|
57
|
+
// RFC 8288 §3.2: Link-param quoted-string unescaping.
|
|
58
|
+
export function unquote(value) {
|
|
59
|
+
return unquoteImpl(value);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Format a single link as a Link header value segment.
|
|
63
|
+
*
|
|
64
|
+
* Output format: <href>; rel="value"; [other params]
|
|
65
|
+
*
|
|
66
|
+
* @param link - Link definition
|
|
67
|
+
* @returns Formatted link string
|
|
68
|
+
*/
|
|
69
|
+
// RFC 8288 §3.1, §3.2, §3.3, §3.4: Link-value formatting and parameters.
|
|
70
|
+
export function formatLink(link) {
|
|
71
|
+
const parts = [`<${link.href}>`];
|
|
72
|
+
// rel is always first and always quoted per convention
|
|
73
|
+
if (link.rel) {
|
|
74
|
+
parts.push(`rel="${link.rel}"`);
|
|
75
|
+
}
|
|
76
|
+
// Add other parameters in a consistent order
|
|
77
|
+
// Always quote values for consistency
|
|
78
|
+
const orderedKeys = ['type', 'title', 'media', 'anchor', 'rev'];
|
|
79
|
+
for (const key of orderedKeys) {
|
|
80
|
+
if (key in link && link[key] !== undefined) {
|
|
81
|
+
const value = link[key];
|
|
82
|
+
if (typeof value === 'string') {
|
|
83
|
+
// Always quote values - escape any quotes in the value
|
|
84
|
+
const escaped = value.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
85
|
+
parts.push(`${key}="${escaped}"`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// RFC 8288 §3.4.1: hreflang may appear multiple times
|
|
90
|
+
if (link.hreflang !== undefined) {
|
|
91
|
+
const hreflangs = Array.isArray(link.hreflang) ? link.hreflang : [link.hreflang];
|
|
92
|
+
for (const lang of hreflangs) {
|
|
93
|
+
const escaped = lang.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
|
|
94
|
+
parts.push(`hreflang="${escaped}"`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Add any extension attributes (skip titleLang as it's metadata)
|
|
98
|
+
const skipKeys = new Set(['href', 'rel', 'titleLang', ...orderedKeys, 'hreflang']);
|
|
99
|
+
for (const [key, value] of Object.entries(link)) {
|
|
100
|
+
if (skipKeys.has(key)) {
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if (value !== undefined) {
|
|
104
|
+
if (typeof value === 'string') {
|
|
105
|
+
parts.push(`${key}=${quoteIfNeeded(value)}`);
|
|
106
|
+
}
|
|
107
|
+
else if (Array.isArray(value)) {
|
|
108
|
+
// Multiple values for extension attribute
|
|
109
|
+
for (const v of value) {
|
|
110
|
+
parts.push(`${key}=${quoteIfNeeded(v)}`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return parts.join('; ');
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Format multiple links as a complete Link header value.
|
|
119
|
+
* Links are comma-separated.
|
|
120
|
+
*
|
|
121
|
+
* @param links - Array of link definitions
|
|
122
|
+
* @returns Complete Link header value
|
|
123
|
+
*/
|
|
124
|
+
// RFC 8288 §3: Link header field-value formatting.
|
|
125
|
+
export function formatLinkHeader(links) {
|
|
126
|
+
return links.map(formatLink).join(', ');
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Build Link header from PaginationLinks (backward-compatible).
|
|
130
|
+
*
|
|
131
|
+
* @param links - Pagination links object
|
|
132
|
+
* @returns Link header value
|
|
133
|
+
*/
|
|
134
|
+
// RFC 8288 §3, §3.3: Link header with relation types.
|
|
135
|
+
export function buildLinkHeader(links) {
|
|
136
|
+
const definitions = [];
|
|
137
|
+
definitions.push({ href: links.self, rel: 'self' });
|
|
138
|
+
definitions.push({ href: links.first, rel: 'first' });
|
|
139
|
+
if (links.prev) {
|
|
140
|
+
definitions.push({ href: links.prev, rel: 'prev' });
|
|
141
|
+
}
|
|
142
|
+
if (links.next) {
|
|
143
|
+
definitions.push({ href: links.next, rel: 'next' });
|
|
144
|
+
}
|
|
145
|
+
definitions.push({ href: links.last, rel: 'last' });
|
|
146
|
+
return formatLinkHeader(definitions);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Parse a Link header value into link definitions.
|
|
150
|
+
*
|
|
151
|
+
* **CRITICAL IMPLEMENTATION NOTES**:
|
|
152
|
+
*
|
|
153
|
+
* 1. Commas INSIDE quoted strings are NOT separators:
|
|
154
|
+
* `<url1>; title="Hello, World", <url2>; rel="next"`
|
|
155
|
+
* This is TWO links, not three.
|
|
156
|
+
*
|
|
157
|
+
* 2. Escaped characters in quoted values:
|
|
158
|
+
* `title="Say \"Hello\""` -> title = Say "Hello"
|
|
159
|
+
* `title="Back\\slash"` -> title = Back\slash
|
|
160
|
+
*
|
|
161
|
+
* 3. Multiple values for same attribute (e.g., hreflang):
|
|
162
|
+
* `<url>; rel="alternate"; hreflang="en"; hreflang="de"`
|
|
163
|
+
* This should work but is rare.
|
|
164
|
+
*
|
|
165
|
+
* 4. Parameters without values:
|
|
166
|
+
* `<url>; rel="prefetch"; crossorigin`
|
|
167
|
+
* crossorigin is a boolean attribute.
|
|
168
|
+
*
|
|
169
|
+
* 5. Whitespace around delimiters should be trimmed:
|
|
170
|
+
* `<url> ; rel = "next"` is valid
|
|
171
|
+
*
|
|
172
|
+
* @param header - Link header value
|
|
173
|
+
* @returns Array of parsed link definitions
|
|
174
|
+
*/
|
|
175
|
+
// RFC 8288 §3, §3.1, §3.2, §3.3: Link header parsing.
|
|
176
|
+
export function parseLinkHeader(header) {
|
|
177
|
+
if (isEmptyHeader(header)) {
|
|
178
|
+
return [];
|
|
179
|
+
}
|
|
180
|
+
const results = [];
|
|
181
|
+
let state = 0 /* State.BETWEEN_LINKS */;
|
|
182
|
+
let currentLink = {};
|
|
183
|
+
let currentParamName = '';
|
|
184
|
+
let currentParamValue = '';
|
|
185
|
+
let currentUri = '';
|
|
186
|
+
let escaped = false;
|
|
187
|
+
const saveParam = () => {
|
|
188
|
+
const name = currentParamName.trim().toLowerCase();
|
|
189
|
+
const rawValue = currentParamValue.trim();
|
|
190
|
+
if (!name) {
|
|
191
|
+
currentParamName = '';
|
|
192
|
+
currentParamValue = '';
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
// Unquote the value
|
|
196
|
+
const value = rawValue.startsWith('"') ? unquote(rawValue) : (rawValue || '');
|
|
197
|
+
// RFC 8288 §3.4.1: These params MUST NOT appear more than once (ignore duplicates)
|
|
198
|
+
const singleUseParams = new Set(['rel', 'type', 'media', 'anchor']);
|
|
199
|
+
if (singleUseParams.has(name) && currentLink[name] !== undefined) {
|
|
200
|
+
currentParamName = '';
|
|
201
|
+
currentParamValue = '';
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
// RFC 8288 §3.4.1: title* takes precedence over title
|
|
205
|
+
// title and title* also single-use, but title* wins
|
|
206
|
+
if (name === 'title*') {
|
|
207
|
+
if (currentLink['title*'] !== undefined) {
|
|
208
|
+
// Ignore duplicate title*
|
|
209
|
+
currentParamName = '';
|
|
210
|
+
currentParamValue = '';
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
// Decode RFC 8187 ext-value
|
|
214
|
+
const decoded = decodeExtValue(value);
|
|
215
|
+
if (decoded) {
|
|
216
|
+
currentLink.title = decoded.value;
|
|
217
|
+
currentLink.titleLang = decoded.language;
|
|
218
|
+
currentLink['title*'] = value; // Store raw for round-trip
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
// Decoding failed, store raw value
|
|
222
|
+
currentLink['title*'] = value;
|
|
223
|
+
}
|
|
224
|
+
currentParamName = '';
|
|
225
|
+
currentParamValue = '';
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
if (name === 'title') {
|
|
229
|
+
// Only use title if title* hasn't been seen
|
|
230
|
+
if (currentLink['title*'] !== undefined || currentLink.title !== undefined) {
|
|
231
|
+
currentParamName = '';
|
|
232
|
+
currentParamValue = '';
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
currentLink.title = value;
|
|
236
|
+
currentParamName = '';
|
|
237
|
+
currentParamValue = '';
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
// RFC 8288 §3.4.1: hreflang may appear multiple times
|
|
241
|
+
if (name === 'hreflang') {
|
|
242
|
+
const existing = currentLink.hreflang;
|
|
243
|
+
if (existing === undefined) {
|
|
244
|
+
currentLink.hreflang = value;
|
|
245
|
+
}
|
|
246
|
+
else if (Array.isArray(existing)) {
|
|
247
|
+
existing.push(value);
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
currentLink.hreflang = [existing, value];
|
|
251
|
+
}
|
|
252
|
+
currentParamName = '';
|
|
253
|
+
currentParamValue = '';
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
// RFC 8288 §3.3: rev is deprecated but should be parsed
|
|
257
|
+
if (name === 'rev') {
|
|
258
|
+
if (currentLink.rev === undefined) {
|
|
259
|
+
currentLink.rev = value;
|
|
260
|
+
}
|
|
261
|
+
currentParamName = '';
|
|
262
|
+
currentParamValue = '';
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
// RFC 8288 §3.4.2: Extension attributes with * suffix
|
|
266
|
+
// Prefer the *-suffixed version when both are present
|
|
267
|
+
if (name.endsWith('*')) {
|
|
268
|
+
const baseName = name.slice(0, -1);
|
|
269
|
+
const decoded = decodeExtValue(value);
|
|
270
|
+
if (decoded) {
|
|
271
|
+
// Store decoded value under base name
|
|
272
|
+
currentLink[baseName] = decoded.value;
|
|
273
|
+
currentLink[name] = value; // Store raw for reference
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
currentLink[name] = value;
|
|
277
|
+
}
|
|
278
|
+
currentParamName = '';
|
|
279
|
+
currentParamValue = '';
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
// Regular parameter - only set if not already set by *-version
|
|
283
|
+
const starName = `${name}*`;
|
|
284
|
+
if (currentLink[starName] !== undefined) {
|
|
285
|
+
// Skip, the *-version takes precedence
|
|
286
|
+
currentParamName = '';
|
|
287
|
+
currentParamValue = '';
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
if (currentLink[name] === undefined) {
|
|
291
|
+
currentLink[name] = value;
|
|
292
|
+
}
|
|
293
|
+
currentParamName = '';
|
|
294
|
+
currentParamValue = '';
|
|
295
|
+
};
|
|
296
|
+
const saveLink = () => {
|
|
297
|
+
if (currentLink.href) {
|
|
298
|
+
if (!currentLink.rel) {
|
|
299
|
+
currentLink = {};
|
|
300
|
+
currentUri = '';
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
const rels = currentLink.rel
|
|
304
|
+
.split(/\s+/)
|
|
305
|
+
.map(rel => rel.trim())
|
|
306
|
+
.filter(Boolean);
|
|
307
|
+
for (const rel of rels) {
|
|
308
|
+
results.push({
|
|
309
|
+
...currentLink,
|
|
310
|
+
rel,
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
currentLink = {};
|
|
315
|
+
currentUri = '';
|
|
316
|
+
};
|
|
317
|
+
for (let i = 0; i < header.length; i++) {
|
|
318
|
+
const char = header[i];
|
|
319
|
+
switch (state) {
|
|
320
|
+
case 0 /* State.BETWEEN_LINKS */:
|
|
321
|
+
if (char === '<') {
|
|
322
|
+
currentUri = '';
|
|
323
|
+
state = 1 /* State.IN_URI */;
|
|
324
|
+
}
|
|
325
|
+
// Ignore whitespace and commas between links
|
|
326
|
+
break;
|
|
327
|
+
case 1 /* State.IN_URI */:
|
|
328
|
+
if (char === '>') {
|
|
329
|
+
currentLink.href = currentUri.trim();
|
|
330
|
+
state = 2 /* State.IN_PARAMS */;
|
|
331
|
+
}
|
|
332
|
+
else {
|
|
333
|
+
currentUri += char;
|
|
334
|
+
}
|
|
335
|
+
break;
|
|
336
|
+
case 2 /* State.IN_PARAMS */:
|
|
337
|
+
if (char === ';') {
|
|
338
|
+
// Save any pending parameter
|
|
339
|
+
saveParam();
|
|
340
|
+
state = 3 /* State.IN_PARAM_NAME */;
|
|
341
|
+
}
|
|
342
|
+
else if (char === ',') {
|
|
343
|
+
// End of this link
|
|
344
|
+
saveParam();
|
|
345
|
+
saveLink();
|
|
346
|
+
state = 0 /* State.BETWEEN_LINKS */;
|
|
347
|
+
}
|
|
348
|
+
else if (char === '"') {
|
|
349
|
+
// Starting a quoted value directly (shouldn't happen normally)
|
|
350
|
+
currentParamValue += char;
|
|
351
|
+
state = 5 /* State.IN_QUOTED_VALUE */;
|
|
352
|
+
}
|
|
353
|
+
else if (char !== ' ' && char !== '\t') {
|
|
354
|
+
// Some character that's part of a param name (unusual)
|
|
355
|
+
currentParamName += char;
|
|
356
|
+
state = 3 /* State.IN_PARAM_NAME */;
|
|
357
|
+
}
|
|
358
|
+
break;
|
|
359
|
+
case 3 /* State.IN_PARAM_NAME */:
|
|
360
|
+
if (char === '=') {
|
|
361
|
+
state = 4 /* State.IN_PARAM_VALUE */;
|
|
362
|
+
}
|
|
363
|
+
else if (char === ';') {
|
|
364
|
+
// Boolean parameter with no value
|
|
365
|
+
saveParam();
|
|
366
|
+
// Stay in IN_PARAM_NAME for next param
|
|
367
|
+
}
|
|
368
|
+
else if (char === ',') {
|
|
369
|
+
// End of link with boolean param
|
|
370
|
+
saveParam();
|
|
371
|
+
saveLink();
|
|
372
|
+
state = 0 /* State.BETWEEN_LINKS */;
|
|
373
|
+
}
|
|
374
|
+
else if (char !== ' ' && char !== '\t') {
|
|
375
|
+
currentParamName += char;
|
|
376
|
+
}
|
|
377
|
+
break;
|
|
378
|
+
case 4 /* State.IN_PARAM_VALUE */:
|
|
379
|
+
if (char === '"') {
|
|
380
|
+
currentParamValue += char;
|
|
381
|
+
state = 5 /* State.IN_QUOTED_VALUE */;
|
|
382
|
+
}
|
|
383
|
+
else if (char === ';') {
|
|
384
|
+
saveParam();
|
|
385
|
+
state = 3 /* State.IN_PARAM_NAME */;
|
|
386
|
+
}
|
|
387
|
+
else if (char === ',') {
|
|
388
|
+
saveParam();
|
|
389
|
+
saveLink();
|
|
390
|
+
state = 0 /* State.BETWEEN_LINKS */;
|
|
391
|
+
}
|
|
392
|
+
else if (char !== ' ' && char !== '\t' || currentParamValue.length > 0) {
|
|
393
|
+
// Only add non-whitespace, or whitespace if we've started the value
|
|
394
|
+
// But actually, we should trim, so skip leading whitespace
|
|
395
|
+
if (char !== ' ' && char !== '\t') {
|
|
396
|
+
currentParamValue += char;
|
|
397
|
+
}
|
|
398
|
+
else if (currentParamValue.length > 0 && !currentParamValue.startsWith('"')) {
|
|
399
|
+
// For unquoted values, stop at whitespace
|
|
400
|
+
// This handles: rel = "next" where space before quote
|
|
401
|
+
// Don't add whitespace, just continue
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
break;
|
|
405
|
+
case 5 /* State.IN_QUOTED_VALUE */:
|
|
406
|
+
if (escaped) {
|
|
407
|
+
currentParamValue += char;
|
|
408
|
+
escaped = false;
|
|
409
|
+
}
|
|
410
|
+
else if (char === '\\') {
|
|
411
|
+
currentParamValue += char;
|
|
412
|
+
escaped = true;
|
|
413
|
+
}
|
|
414
|
+
else if (char === '"') {
|
|
415
|
+
currentParamValue += char;
|
|
416
|
+
// End of quoted value - go back to param processing
|
|
417
|
+
state = 4 /* State.IN_PARAM_VALUE */;
|
|
418
|
+
}
|
|
419
|
+
else {
|
|
420
|
+
currentParamValue += char;
|
|
421
|
+
}
|
|
422
|
+
break;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
// Handle end of string
|
|
426
|
+
if (state === 3 /* State.IN_PARAM_NAME */ || state === 4 /* State.IN_PARAM_VALUE */ || state === 2 /* State.IN_PARAMS */) {
|
|
427
|
+
saveParam();
|
|
428
|
+
saveLink();
|
|
429
|
+
}
|
|
430
|
+
else if (state === 5 /* State.IN_QUOTED_VALUE */) {
|
|
431
|
+
// Unclosed quote - save what we have anyway
|
|
432
|
+
saveParam();
|
|
433
|
+
saveLink();
|
|
434
|
+
}
|
|
435
|
+
return results;
|
|
436
|
+
}
|
|
437
|
+
//# sourceMappingURL=link.js.map
|
package/dist/link.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"link.js","sourceRoot":"","sources":["../src/link.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Linkset utilities per RFC 9264.
|
|
3
|
+
* API catalog support per RFC 9727.
|
|
4
|
+
* RFC 9264 §4.1, §4.2, §5, §6.
|
|
5
|
+
* RFC 9727 §§2-4, §7.
|
|
6
|
+
* @see https://www.rfc-editor.org/rfc/rfc9264.html
|
|
7
|
+
* @see https://www.rfc-editor.org/rfc/rfc9727.html
|
|
8
|
+
*/
|
|
9
|
+
import type { LinkDefinition, Linkset, LinksetJsonOptions, ApiCatalog, ApiCatalogOptions } from './types.js';
|
|
10
|
+
export declare const LINKSET_MEDIA_TYPE = "application/linkset+json";
|
|
11
|
+
export declare const API_CATALOG_PROFILE = "https://www.rfc-editor.org/info/rfc9727";
|
|
12
|
+
export declare const API_CATALOG_PATH = "/.well-known/api-catalog";
|
|
13
|
+
/**
|
|
14
|
+
* Parse an application/linkset document into link definitions.
|
|
15
|
+
* RFC 9264 §4.1: Same as HTTP Link header format but allows newlines as separators.
|
|
16
|
+
*
|
|
17
|
+
* @param document - The linkset document content
|
|
18
|
+
* @returns Array of parsed link definitions, or null if parsing fails
|
|
19
|
+
*/
|
|
20
|
+
export declare function parseLinkset(document: string): LinkDefinition[] | null;
|
|
21
|
+
/**
|
|
22
|
+
* Parse an application/linkset+json document.
|
|
23
|
+
* RFC 9264 §4.2: JSON format for link sets.
|
|
24
|
+
*
|
|
25
|
+
* @param json - The JSON string or object
|
|
26
|
+
* @returns Parsed Linkset object, or null if invalid
|
|
27
|
+
*/
|
|
28
|
+
export declare function parseLinksetJson(json: string | object): Linkset | null;
|
|
29
|
+
/**
|
|
30
|
+
* Format link definitions as an application/linkset document.
|
|
31
|
+
* RFC 9264 §4.1: Uses Link header format with newlines for readability.
|
|
32
|
+
*
|
|
33
|
+
* @param links - Array of link definitions
|
|
34
|
+
* @returns Formatted linkset document
|
|
35
|
+
*/
|
|
36
|
+
export declare function formatLinkset(links: LinkDefinition[]): string;
|
|
37
|
+
/**
|
|
38
|
+
* Format link definitions as an application/linkset+json object.
|
|
39
|
+
* RFC 9264 §4.2: JSON format for link sets.
|
|
40
|
+
*
|
|
41
|
+
* @param links - Array of link definitions
|
|
42
|
+
* @param options - Formatting options
|
|
43
|
+
* @returns Linkset JSON object
|
|
44
|
+
*/
|
|
45
|
+
export declare function formatLinksetJson(links: LinkDefinition[], options?: LinksetJsonOptions): Linkset;
|
|
46
|
+
/**
|
|
47
|
+
* Convert an application/linkset document to JSON format.
|
|
48
|
+
* RFC 9264 §4.1, §4.2: Format conversion.
|
|
49
|
+
*
|
|
50
|
+
* @param document - The linkset document
|
|
51
|
+
* @returns Linkset JSON object, or null if parsing fails
|
|
52
|
+
*/
|
|
53
|
+
export declare function linksetToJson(document: string): Linkset | null;
|
|
54
|
+
/**
|
|
55
|
+
* Convert a JSON linkset to application/linkset format.
|
|
56
|
+
* RFC 9264 §4.1, §4.2: Format conversion.
|
|
57
|
+
*
|
|
58
|
+
* @param linkset - The Linkset object
|
|
59
|
+
* @returns Formatted linkset document
|
|
60
|
+
*/
|
|
61
|
+
export declare function jsonToLinkset(linkset: Linkset): string;
|
|
62
|
+
/**
|
|
63
|
+
* Type guard to validate a Linkset object.
|
|
64
|
+
* RFC 9264 §4.2.1: linkset must be the sole top-level member.
|
|
65
|
+
*
|
|
66
|
+
* @param obj - Object to validate
|
|
67
|
+
* @returns True if valid Linkset
|
|
68
|
+
*/
|
|
69
|
+
export declare function isValidLinkset(obj: unknown): obj is Linkset;
|
|
70
|
+
/**
|
|
71
|
+
* Create an API catalog document.
|
|
72
|
+
* RFC 9727 §4: API catalog document structure.
|
|
73
|
+
*
|
|
74
|
+
* @param options - API catalog configuration
|
|
75
|
+
* @returns API catalog Linkset document
|
|
76
|
+
*/
|
|
77
|
+
export declare function createApiCatalog(options: ApiCatalogOptions): ApiCatalog;
|
|
78
|
+
/**
|
|
79
|
+
* Parse an API catalog document.
|
|
80
|
+
* RFC 9727 §4: Validate and parse API catalog structure.
|
|
81
|
+
*
|
|
82
|
+
* @param json - JSON string or object
|
|
83
|
+
* @returns Parsed API catalog, or null if invalid
|
|
84
|
+
*/
|
|
85
|
+
export declare function parseApiCatalog(json: string | object): ApiCatalog | null;
|
|
86
|
+
/**
|
|
87
|
+
* Check if a Linkset is an API catalog (has the RFC 9727 profile).
|
|
88
|
+
* RFC 9727 §4.2, §7.3: Profile URI indicates api-catalog semantics.
|
|
89
|
+
*
|
|
90
|
+
* @param linkset - Linkset to check
|
|
91
|
+
* @returns True if the linkset has the api-catalog profile
|
|
92
|
+
*/
|
|
93
|
+
export declare function isApiCatalog(linkset: Linkset | ApiCatalog): boolean;
|
|
94
|
+
/**
|
|
95
|
+
* Convert a Linkset to an array of LinkDefinitions.
|
|
96
|
+
* Useful for converting API catalog entries to Link header format.
|
|
97
|
+
*
|
|
98
|
+
* @param linkset - Linkset to convert
|
|
99
|
+
* @returns Array of LinkDefinition objects
|
|
100
|
+
*/
|
|
101
|
+
export declare function linksetToLinks(linkset: Linkset): LinkDefinition[];
|
|
102
|
+
/**
|
|
103
|
+
* Convert an array of LinkDefinitions to a Linkset.
|
|
104
|
+
* Useful for creating API catalogs from Link header entries.
|
|
105
|
+
*
|
|
106
|
+
* @param links - Array of link definitions
|
|
107
|
+
* @param anchor - Default anchor URI for links without one
|
|
108
|
+
* @returns Linkset object
|
|
109
|
+
*/
|
|
110
|
+
export declare function linksToLinkset(links: LinkDefinition[], anchor?: string): Linkset;
|
|
111
|
+
//# sourceMappingURL=linkset.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"linkset.d.ts","sourceRoot":"","sources":["../src/linkset.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EACR,cAAc,EACd,OAAO,EAGP,kBAAkB,EAElB,UAAU,EACV,iBAAiB,EAGpB,MAAM,YAAY,CAAC;AAIpB,eAAO,MAAM,kBAAkB,6BAA6B,CAAC;AAG7D,eAAO,MAAM,mBAAmB,4CAA4C,CAAC;AAG7E,eAAO,MAAM,gBAAgB,6BAA6B,CAAC;AAE3D;;;;;;GAMG;AAEH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,EAAE,GAAG,IAAI,CAUtE;AA0ED;;;;;;GAMG;AAEH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAkBtE;AAED;;;;;;GAMG;AAEH,wBAAgB,aAAa,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,MAAM,CAO7D;AAED;;;;;;;GAOG;AAEH,wBAAgB,iBAAiB,CAC7B,KAAK,EAAE,cAAc,EAAE,EACvB,OAAO,GAAE,kBAAuB,GACjC,OAAO,CAsDT;AA0CD;;;;;;GAMG;AAEH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAO9D;AAED;;;;;;GAMG;AAEH,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAGtD;AAwFD;;;;;;GAMG;AAEH,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,OAAO,CA0D3D;AAMD;;;;;;GAMG;AAEH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,GAAG,UAAU,CAgEvE;AAED;;;;;;GAMG;AAEH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,IAAI,CAaxE;AAED;;;;;;GAMG;AAEH,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,UAAU,GAAG,OAAO,CAKnE;AAED;;;;;;GAMG;AAEH,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,cAAc,EAAE,CAEjE;AAED;;;;;;;GAOG;AAEH,wBAAgB,cAAc,CAAC,KAAK,EAAE,cAAc,EAAE,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAQhF"}
|