@datalayer/personal-agent-protocol 0.3.0 → 0.3.2

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.
Files changed (65) hide show
  1. package/LICENSE +29 -0
  2. package/README.md +300 -19
  3. package/lib/auth.d.ts +35 -1
  4. package/lib/auth.d.ts.map +1 -1
  5. package/lib/auth.js +230 -2
  6. package/lib/auth.js.map +1 -1
  7. package/lib/browser-server.d.ts +26 -0
  8. package/lib/browser-server.d.ts.map +1 -0
  9. package/lib/browser-server.js +61 -0
  10. package/lib/browser-server.js.map +1 -0
  11. package/lib/browser.d.ts +43 -0
  12. package/lib/browser.d.ts.map +1 -0
  13. package/lib/browser.js +103 -0
  14. package/lib/browser.js.map +1 -0
  15. package/lib/chunk-TU6B5MQ7.js +4863 -0
  16. package/lib/chunk-TU6B5MQ7.js.map +7 -0
  17. package/lib/conversations.d.ts +48 -0
  18. package/lib/conversations.d.ts.map +1 -0
  19. package/lib/conversations.js +240 -0
  20. package/lib/conversations.js.map +1 -0
  21. package/lib/crypto.d.ts +1 -1
  22. package/lib/crypto.d.ts.map +1 -1
  23. package/lib/crypto.js +2 -3
  24. package/lib/crypto.js.map +1 -1
  25. package/lib/discovery.d.ts +1 -0
  26. package/lib/discovery.d.ts.map +1 -1
  27. package/lib/discovery.js +4 -3
  28. package/lib/discovery.js.map +1 -1
  29. package/lib/errors.d.ts +23 -0
  30. package/lib/errors.d.ts.map +1 -1
  31. package/lib/errors.js +24 -0
  32. package/lib/errors.js.map +1 -1
  33. package/lib/identity.d.ts +19 -0
  34. package/lib/identity.d.ts.map +1 -0
  35. package/lib/identity.js +111 -0
  36. package/lib/identity.js.map +1 -0
  37. package/lib/index.d.ts +11 -6
  38. package/lib/index.d.ts.map +1 -1
  39. package/lib/index.js +79 -3734
  40. package/lib/index.js.map +4 -4
  41. package/lib/models.d.ts +15 -0
  42. package/lib/models.d.ts.map +1 -1
  43. package/lib/models.js +53 -0
  44. package/lib/models.js.map +1 -1
  45. package/lib/reactor.d.ts +20 -1
  46. package/lib/reactor.d.ts.map +1 -1
  47. package/lib/reactor.js +7 -1
  48. package/lib/reactor.js.map +1 -1
  49. package/lib/secret.d.ts +9 -0
  50. package/lib/secret.d.ts.map +1 -0
  51. package/lib/secret.js +21 -0
  52. package/lib/secret.js.map +1 -0
  53. package/lib/server.d.ts +16 -0
  54. package/lib/server.d.ts.map +1 -0
  55. package/lib/server.js +136 -0
  56. package/lib/server.js.map +7 -0
  57. package/lib/sessions.d.ts +6 -7
  58. package/lib/sessions.d.ts.map +1 -1
  59. package/lib/sessions.js +6 -19
  60. package/lib/sessions.js.map +1 -1
  61. package/lib/transport.d.ts +24 -0
  62. package/lib/transport.d.ts.map +1 -0
  63. package/lib/transport.js +112 -0
  64. package/lib/transport.js.map +1 -0
  65. package/package.json +14 -5
package/lib/index.js CHANGED
@@ -1,3749 +1,90 @@
1
- // src/errors.ts
2
- var PersonalAgentProtocolError = class extends Error {
3
- code;
4
- statusCode;
5
- details;
6
- constructor(code, message2, options = {}) {
7
- super(message2, { cause: options.cause });
8
- this.name = "PersonalAgentProtocolError";
9
- this.code = code;
10
- this.statusCode = options.statusCode;
11
- this.details = options.details ?? {};
12
- }
13
- toString() {
14
- return `${this.code}: ${this.message}`;
15
- }
16
- };
17
- var ProtocolValidationError = class extends PersonalAgentProtocolError {
18
- constructor(code, message2, options = {}) {
19
- super(code, message2, options);
20
- this.name = "ProtocolValidationError";
21
- }
22
- };
23
- var DiscoveryError = class extends PersonalAgentProtocolError {
24
- constructor(code, message2, options = {}) {
25
- super(code, message2, options);
26
- this.name = "DiscoveryError";
27
- }
28
- };
29
- var AuthorizationError = class extends PersonalAgentProtocolError {
30
- constructor(code, message2, options = {}) {
31
- super(code, message2, options);
32
- this.name = "AuthorizationError";
33
- }
34
- };
35
- var SessionError = class extends PersonalAgentProtocolError {
36
- constructor(code, message2, options = {}) {
37
- super(code, message2, options);
38
- this.name = "SessionError";
39
- }
40
- };
41
- var ProofError = class extends PersonalAgentProtocolError {
42
- constructor(code, message2, options = {}) {
43
- super(code, message2, options);
44
- this.name = "ProofError";
45
- }
46
- };
47
-
48
- // ../../node_modules/jose/dist/webapi/lib/buffer_utils.js
49
- var encoder = new TextEncoder();
50
- var decoder = new TextDecoder();
51
- var strictDecoder = new TextDecoder("utf-8", { fatal: true });
52
- var MAX_INT32 = 2 ** 32;
53
- function concat(...buffers) {
54
- const size = buffers.reduce((acc, { length }) => acc + length, 0), buf = new Uint8Array(size);
55
- let i = 0;
56
- for (const buffer of buffers)
57
- buf.set(buffer, i), i += buffer.length;
58
- return buf;
59
- }
60
- var NON_ASCII = /[^\x00-\x7f]/;
61
- function encode(string2) {
62
- if (typeof string2 == "string" && string2.length >= 128) {
63
- if (NON_ASCII.test(string2))
64
- throw new TypeError("non-ASCII string encountered in encode()");
65
- return encoder.encode(string2);
66
- }
67
- const bytes = new Uint8Array(string2.length);
68
- for (let i = 0; i < string2.length; i++) {
69
- const code = string2.charCodeAt(i);
70
- if (code > 127)
71
- throw new TypeError("non-ASCII string encountered in encode()");
72
- bytes[i] = code;
73
- }
74
- return bytes;
75
- }
76
- function encodeBase64(input, url = false) {
77
- if (Uint8Array.prototype.toBase64)
78
- return input.toBase64({ alphabet: url ? "base64url" : "base64", omitPadding: url });
79
- const CHUNK_SIZE = 32768, arr = [];
80
- for (let i = 0; i < input.length; i += CHUNK_SIZE)
81
- arr.push(String.fromCharCode.apply(null, input.subarray(i, i + CHUNK_SIZE)));
82
- const encoded = btoa(arr.join(""));
83
- return url ? encoded.replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_") : encoded;
84
- }
85
- function decodeBase64(encoded, url = false) {
86
- if (Uint8Array.fromBase64)
87
- return Uint8Array.fromBase64(encoded, { alphabet: url ? "base64url" : "base64" });
88
- if (url) {
89
- if (encoded.includes("+") || encoded.includes("/"))
90
- throw new TypeError("Invalid base64url");
91
- encoded = encoded.replace(/-/g, "+").replace(/_/g, "/");
92
- }
93
- const binary = atob(encoded), bytes = new Uint8Array(binary.length);
94
- for (let i = 0; i < binary.length; i++)
95
- bytes[i] = binary.charCodeAt(i);
96
- return bytes;
97
- }
98
- async function digest(algorithm2, data) {
99
- const subtleDigest = `SHA-${algorithm2.slice(-3)}`;
100
- return new Uint8Array(await crypto.subtle.digest(subtleDigest, data));
101
- }
102
-
103
- // ../../node_modules/jose/dist/webapi/util/errors.js
104
- var JOSEError = class extends Error {
105
- static code = "ERR_JOSE_GENERIC";
106
- code = "ERR_JOSE_GENERIC";
107
- constructor(message2, options) {
108
- super(message2, options), this.name = this.constructor.name, Error.captureStackTrace?.(this, this.constructor);
109
- }
110
- };
111
- var JWTClaimValidationFailed = class extends JOSEError {
112
- static code = "ERR_JWT_CLAIM_VALIDATION_FAILED";
113
- code = "ERR_JWT_CLAIM_VALIDATION_FAILED";
114
- claim;
115
- reason;
116
- payload;
117
- constructor(message2, payload, claim = "unspecified", reason = "unspecified") {
118
- super(message2, { cause: { claim, reason, payload } }), this.claim = claim, this.reason = reason, this.payload = payload;
119
- }
120
- };
121
- var JWTExpired = class extends JOSEError {
122
- static code = "ERR_JWT_EXPIRED";
123
- code = "ERR_JWT_EXPIRED";
124
- claim;
125
- reason;
126
- payload;
127
- constructor(message2, payload, claim = "unspecified", reason = "unspecified") {
128
- super(message2, { cause: { claim, reason, payload } }), this.claim = claim, this.reason = reason, this.payload = payload;
129
- }
130
- };
131
- var JOSEAlgNotAllowed = class extends JOSEError {
132
- static code = "ERR_JOSE_ALG_NOT_ALLOWED";
133
- code = "ERR_JOSE_ALG_NOT_ALLOWED";
134
- };
135
- var JOSENotSupported = class extends JOSEError {
136
- static code = "ERR_JOSE_NOT_SUPPORTED";
137
- code = "ERR_JOSE_NOT_SUPPORTED";
138
- };
139
- var JWSInvalid = class extends JOSEError {
140
- static code = "ERR_JWS_INVALID";
141
- code = "ERR_JWS_INVALID";
142
- };
143
- var JWTInvalid = class extends JOSEError {
144
- static code = "ERR_JWT_INVALID";
145
- code = "ERR_JWT_INVALID";
146
- };
147
- var JWKInvalid = class extends JOSEError {
148
- static code = "ERR_JWK_INVALID";
149
- code = "ERR_JWK_INVALID";
150
- };
151
- var JWSSignatureVerificationFailed = class extends JOSEError {
152
- static code = "ERR_JWS_SIGNATURE_VERIFICATION_FAILED";
153
- code = "ERR_JWS_SIGNATURE_VERIFICATION_FAILED";
154
- constructor(message2 = "signature verification failed", options) {
155
- super(message2, options);
156
- }
157
- };
158
-
159
- // ../../node_modules/jose/dist/webapi/util/base64url.js
160
- var invalid = "The input to be decoded is not correctly encoded.";
161
- function decode(input) {
162
- try {
163
- return decodeBase64(typeof input == "string" ? input : decoder.decode(input), true);
164
- } catch (cause) {
165
- throw new TypeError(invalid, { cause });
166
- }
167
- }
168
- function encode2(input) {
169
- return encodeBase64(typeof input == "string" ? encoder.encode(input) : input, true);
170
- }
171
-
172
- // ../../node_modules/jose/dist/webapi/lib/validate.js
173
- function isObject(input) {
174
- if (typeof input != "object" || input === null || Object.prototype.toString.call(input) !== "[object Object]")
175
- return false;
176
- const prototype = Object.getPrototypeOf(input);
177
- return prototype === null || Object.getPrototypeOf(prototype) === null;
178
- }
179
- function isDisjoint(...headers) {
180
- const parameters = /* @__PURE__ */ new Set();
181
- for (const header of headers)
182
- if (header)
183
- for (const parameter of Object.keys(header)) {
184
- if (parameters.has(parameter))
185
- return false;
186
- parameters.add(parameter);
187
- }
188
- return true;
189
- }
190
- function assertNotSet(value, name) {
191
- if (value !== void 0)
192
- throw new TypeError(`${name} can only be called once`);
193
- }
194
- function decodeBase64url(value, label, ErrorClass) {
195
- try {
196
- return decode(value);
197
- } catch {
198
- throw new ErrorClass(`Failed to base64url decode the ${label}`);
199
- }
200
- }
201
- function encodeBase64url(value, label, ErrorClass) {
202
- try {
203
- return encode(value);
204
- } catch {
205
- throw new ErrorClass(`The ${label} is not a valid base64url string`);
206
- }
207
- }
208
- function parseJoseHeader(b64, ErrorClass, message2) {
209
- let parsed;
210
- try {
211
- parsed = JSON.parse(strictDecoder.decode(decode(b64)));
212
- } catch {
213
- throw new ErrorClass(message2);
214
- }
215
- if (!isObject(parsed))
216
- throw new ErrorClass(message2);
217
- return parsed;
218
- }
219
- var JWS_RECOGNIZED = { __proto__: null, b64: true };
220
- function validateAlgorithms(option, algorithms) {
221
- if (algorithms !== void 0 && (!Array.isArray(algorithms) || algorithms.some((s) => typeof s != "string")))
222
- throw new TypeError(`"${option}" option must be an array of strings`);
223
- return algorithms === void 0 ? void 0 : new Set(algorithms);
224
- }
225
- function validateCritDuplicates(Err, protectedHeader) {
226
- const { crit } = protectedHeader ?? {};
227
- if (Array.isArray(crit) && new Set(crit).size !== crit.length)
228
- throw new Err('"crit" (Critical) Header Parameter MUST NOT contain duplicate values');
229
- }
230
- function validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) {
231
- if (joseHeader.crit !== void 0 && protectedHeader?.crit === void 0)
232
- throw new Err('"crit" (Critical) Header Parameter MUST be integrity protected');
233
- if (!protectedHeader || protectedHeader.crit === void 0)
234
- return [];
235
- if (!Array.isArray(protectedHeader.crit) || protectedHeader.crit.length === 0 || protectedHeader.crit.some((input) => typeof input != "string" || input.length === 0))
236
- throw new Err('"crit" (Critical) Header Parameter MUST be an array of non-empty strings when present');
237
- const recognized = recognizedOption === void 0 ? recognizedDefault : { __proto__: null, ...recognizedOption, ...recognizedDefault };
238
- for (const parameter of protectedHeader.crit) {
239
- if (!(parameter in recognized))
240
- throw new JOSENotSupported(`Extension Header Parameter "${parameter}" is not recognized`);
241
- if (!Object.hasOwn(joseHeader, parameter) || joseHeader[parameter] === void 0)
242
- throw new Err(`Extension Header Parameter "${parameter}" is missing`);
243
- if (recognized[parameter] && (!Object.hasOwn(protectedHeader, parameter) || protectedHeader[parameter] === void 0))
244
- throw new Err(`Extension Header Parameter "${parameter}" MUST be integrity protected`);
245
- }
246
- return protectedHeader.crit;
247
- }
248
- function validateB64(protectedHeader, extensions2) {
249
- if (extensions2.includes("b64")) {
250
- const b64 = protectedHeader.b64;
251
- if (typeof b64 != "boolean")
252
- throw new JWSInvalid('The "b64" (base64url-encode payload) Header Parameter must be a boolean');
253
- return b64;
254
- }
255
- return true;
256
- }
257
- function serializeJoseHeader(Err, header) {
258
- let serialized, parsed;
259
- try {
260
- serialized = JSON.stringify(header), parsed = JSON.parse(serialized);
261
- } catch (cause) {
262
- throw new Err("JOSE Header is not valid JSON", { cause });
263
- }
264
- if (!isObject(parsed))
265
- throw new Err("JOSE Header is not a JSON object");
266
- return [parsed, serialized];
267
- }
268
-
269
- // ../../node_modules/jose/dist/webapi/lib/key.js
270
- var tag = (key) => key[Symbol.toStringTag];
271
- var jwkMatchesOp = (entry, key, usage) => {
272
- const { alg } = entry;
273
- if (key.use !== void 0) {
274
- const expected = usage === "sign" || usage === "verify" ? "sig" : "enc";
275
- if (key.use !== expected)
276
- throw new TypeError(`Invalid key for this operation, its "use" must be "${expected}" when present`);
277
- }
278
- if (key.alg !== void 0 && key.alg !== alg)
279
- throw new TypeError(`Invalid key for this operation, its "alg" must be "${alg}" when present`);
280
- if (Array.isArray(key.key_ops)) {
281
- const expectedKeyOp = usage === "encrypt" || usage === "decrypt" ? entry.ops?.[usage === "encrypt" ? 0 : 1] : usage;
282
- if (expectedKeyOp && !key.key_ops.includes(expectedKeyOp))
283
- throw new TypeError(`Invalid key for this operation, its "key_ops" must include "${expectedKeyOp}" when present`);
284
- }
285
- };
286
- async function prepareKey(entry, key, usage) {
287
- const { alg, secret } = entry, privateKey = usage === "decrypt" || usage === "sign";
288
- if (secret && key instanceof Uint8Array)
289
- return key;
290
- let normalized, keyObject;
291
- if (isObject(key)) {
292
- if (normalized = normalizeJwk(key), typeof normalized.kty != "string")
293
- throw invalidKeyType(alg, key, secret);
294
- if (!(secret ? normalized.kty === "oct" && typeof normalized.k == "string" : normalized.kty !== "oct" && (privateKey ? normalized.kty === "AKP" && typeof normalized.priv == "string" || typeof normalized.d == "string" : normalized.d === void 0 && normalized.priv === void 0)))
295
- throw new TypeError(secret ? 'JSON Web Key for symmetric algorithms must have JWK "kty" (Key Type) equal to "oct" and the JWK "k" (Key Value) present' : `JSON Web Key for this operation must be a ${privateKey ? "private" : "public"} JWK`);
296
- if (jwkMatchesOp(entry, normalized, usage), normalized.kty === "oct")
297
- return decode(normalized.k);
298
- if (!Object.isFrozen(key)) {
299
- const { key_ops } = key;
300
- Array.isArray(key_ops) && Object.freeze(key_ops), Object.freeze(key);
301
- }
302
- } else {
303
- if (!isKeyLike(key))
304
- throw invalidKeyType(alg, key, secret);
305
- const expectedType = secret ? "secret" : privateKey ? "private" : "public";
306
- if (key.type !== expectedType && (secret || ["secret", "public", "private"].includes(key.type)))
307
- throw new TypeError(`${tag(key)} instances must be of type "${expectedType}" for the ${alg} algorithm`);
308
- if (isCryptoKey(key))
309
- return key;
310
- if (keyObject = key, keyObject.type === "secret")
311
- return keyObject.export();
312
- }
313
- cache ||= /* @__PURE__ */ new WeakMap();
314
- const cacheKey = key;
315
- let cached = cache.get(cacheKey);
316
- if (cached?.[alg])
317
- return cached[alg];
318
- if (cached || cache.set(cacheKey, cached = {}), keyObject && typeof keyObject.toCryptoKey == "function") {
319
- const isPublic = keyObject.type === "public", crv = nist[keyObject.asymmetricKeyDetails?.namedCurve], params = entry.resolve?.({ crv, asymmetricKeyType: keyObject.asymmetricKeyType }) ?? entry.subtle;
320
- return cached[alg] = keyObject.toCryptoKey(params, isPublic, entry.usages[isPublic ? 0 : 1]);
321
- }
322
- return normalized ??= keyObject.export({ format: "jwk" }), normalized.alg = alg, cached[alg] = await jwkToKey(entry, normalized);
323
- }
324
- var cache;
325
- var nist = {
326
- __proto__: null,
327
- prime256v1: "P-256",
328
- secp384r1: "P-384",
329
- secp521r1: "P-521"
330
- };
331
- var isCryptoKey = (key) => {
332
- if (key?.[Symbol.toStringTag] === "CryptoKey")
333
- return true;
334
- try {
335
- return key instanceof CryptoKey;
336
- } catch {
337
- return false;
338
- }
339
- };
340
- var isKeyObject = (key) => key?.[Symbol.toStringTag] === "KeyObject";
341
- var isKeyLike = (key) => isCryptoKey(key) || isKeyObject(key);
342
- function message(msg, actual, ...types) {
343
- if (types.length > 2) {
344
- const last = types.pop();
345
- msg += `one of type ${types.join(", ")}, or ${last}.`;
346
- } else types.length === 2 ? msg += `one of type ${types[0]} or ${types[1]}.` : msg += `of type ${types[0]}.`;
347
- return actual == null ? msg += ` Received ${actual}` : typeof actual == "function" && actual.name ? msg += ` Received function ${actual.name}` : typeof actual == "object" && actual != null && actual.constructor?.name && (msg += ` Received an instance of ${actual.constructor.name}`), msg;
348
- }
349
- var invalidKeyInput = (actual, ...types) => message("Key must be ", actual, ...types);
350
- function invalidKeyType(alg, actual, secret) {
351
- const types = ["CryptoKey", "KeyObject", "JSON Web Key"];
352
- return secret && types.push("Uint8Array"), new TypeError(message(`Key for the ${alg} algorithm must be `, actual, ...types));
353
- }
354
- var unusable = (name, prop = "algorithm.name") => new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`);
355
- function checkUsage(key, usage) {
356
- if (usage && !key.usages.includes(usage))
357
- throw new TypeError(`CryptoKey does not support this operation, its usages must include ${usage}.`);
358
- }
359
- function checkModulusLength(alg, key) {
360
- const { modulusLength } = key.algorithm;
361
- if (typeof modulusLength != "number" || modulusLength < 2048)
362
- throw new TypeError(`${alg} requires key modulusLength to be 2048 bits or larger`);
363
- }
364
- function checkCryptoKey(key, expected, usage) {
365
- const algorithm2 = key.algorithm;
366
- if (algorithm2.name !== expected.name)
367
- throw unusable(expected.name);
368
- if (expected.hash && algorithm2.hash?.name !== expected.hash)
369
- throw unusable(expected.hash, "algorithm.hash");
370
- if (expected.namedCurve && algorithm2.namedCurve !== expected.namedCurve)
371
- throw unusable(expected.namedCurve, "algorithm.namedCurve");
372
- if (expected.length !== void 0 && algorithm2.length !== expected.length)
373
- throw unusable(expected.length, "algorithm.length");
374
- checkUsage(key, usage);
375
- }
376
- function snapshotJwk(jwk) {
377
- return { __proto__: null, ...jwk };
378
- }
379
- function normalizeJwk(jwk) {
380
- const normalized = snapshotJwk(jwk);
381
- if (normalized.ext !== void 0 && typeof normalized.ext != "boolean")
382
- throw new TypeError('"ext" (Extractable) Parameter must be a boolean');
383
- if (normalized.key_ops !== void 0) {
384
- const value = normalized.key_ops, keyOps = Array.isArray(value) ? [...value] : void 0;
385
- if (!keyOps || keyOps.some((operation) => typeof operation != "string") || new Set(keyOps).size !== keyOps.length)
386
- throw new TypeError('"key_ops" (Key Operations) Parameter must be an array of unique strings');
387
- normalized.key_ops = keyOps;
388
- }
389
- return normalized;
390
- }
391
- function validateExtractableOption(extractable) {
392
- if (extractable !== void 0 && typeof extractable != "boolean")
393
- throw new TypeError('"extractable" option must be a boolean');
394
- return extractable;
395
- }
396
- async function jwkToKey(entry, jwk, extractable) {
397
- if (!entry.kty.includes(jwk.kty))
398
- throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
399
- const algorithm2 = entry.resolve?.({ kty: jwk.kty, crv: jwk.crv }) ?? entry.subtle, isPrivate = !!(jwk.d || jwk.priv), keyData = { ...jwk, ext: extractable ?? jwk.ext };
400
- return keyData.kty !== "AKP" && delete keyData.alg, delete keyData.use, crypto.subtle.importKey("jwk", keyData, algorithm2, keyData.ext ?? !isPrivate, jwk.key_ops ?? entry.usages[isPrivate ? 1 : 0]);
401
- }
402
- async function rawKey(key, expected, usage, extractable = false) {
403
- return key instanceof Uint8Array && (key = await crypto.subtle.importKey("raw", key, expected, extractable, [usage])), checkCryptoKey(key, expected, usage), key;
404
- }
405
-
406
- // ../../node_modules/jose/dist/webapi/lib/key_descriptor.js
407
- function table(entries) {
408
- const out = { __proto__: null };
409
- for (const alg in entries)
410
- out[alg] = { ...entries[alg], alg };
411
- return out;
412
- }
413
-
414
- // ../../node_modules/jose/dist/webapi/lib/jwe_algorithms.js
415
- var wrap = [
416
- ["encrypt", "wrapKey"],
417
- ["decrypt", "unwrapKey"]
418
- ];
419
- var derive = [[], ["deriveBits"]];
420
- var none = [[], []];
421
- function rsaes(bits) {
422
- return {
423
- kty: ["RSA"],
424
- mode: "key-encryption",
425
- subtle: { name: "RSA-OAEP", hash: `SHA-${bits}` },
426
- usages: wrap,
427
- ops: ["wrapKey", "unwrapKey"]
428
- };
429
- }
430
- function ecdh(mode) {
431
- return {
432
- kty: ["EC", "OKP"],
433
- mode,
434
- subtle: { name: "ECDH" },
435
- resolve: ({ kty, crv, asymmetricKeyType }) => {
436
- if (crv === "X25519" || asymmetricKeyType === "x25519")
437
- return { name: "X25519" };
438
- if (kty === "OKP")
439
- throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value');
440
- return { name: "ECDH", namedCurve: crv };
441
- },
442
- usages: derive,
443
- ops: [void 0, "deriveBits"]
444
- };
445
- }
446
- function aeskw(bits, gcm = false) {
447
- return {
448
- kty: ["oct"],
449
- mode: "key-wrapping",
450
- secret: true,
451
- subtle: { name: gcm ? "AES-GCM" : "AES-KW", length: bits },
452
- usages: none,
453
- ops: gcm ? ["encrypt", "decrypt"] : ["wrapKey", "unwrapKey"]
454
- };
455
- }
456
- function pbes2() {
457
- return {
458
- kty: ["oct"],
459
- mode: "key-wrapping",
460
- secret: true,
461
- subtle: { name: "PBKDF2" },
462
- usages: none,
463
- ops: ["deriveBits", "deriveBits"]
464
- };
465
- }
466
- var JWE = table({
467
- dir: {
468
- kty: ["oct"],
469
- mode: "direct-encryption",
470
- secret: true,
471
- subtle: { name: "AES-GCM" },
472
- usages: none,
473
- ops: ["encrypt", "decrypt"]
474
- },
475
- "RSA-OAEP": rsaes(1),
476
- "RSA-OAEP-256": rsaes(256),
477
- "RSA-OAEP-384": rsaes(384),
478
- "RSA-OAEP-512": rsaes(512),
479
- "ECDH-ES": ecdh("direct-key-agreement"),
480
- "ECDH-ES+A128KW": ecdh("key-agreement-with-key-wrapping"),
481
- "ECDH-ES+A192KW": ecdh("key-agreement-with-key-wrapping"),
482
- "ECDH-ES+A256KW": ecdh("key-agreement-with-key-wrapping"),
483
- A128KW: aeskw(128),
484
- A192KW: aeskw(192),
485
- A256KW: aeskw(256),
486
- A128GCMKW: aeskw(128, true),
487
- A192GCMKW: aeskw(192, true),
488
- A256GCMKW: aeskw(256, true),
489
- "PBES2-HS256+A128KW": pbes2(),
490
- "PBES2-HS384+A192KW": pbes2(),
491
- "PBES2-HS512+A256KW": pbes2()
492
- });
493
- var contentOps = ["encrypt", "decrypt"];
494
- function contentEncryption(bits, cbc = false) {
495
- return {
496
- kty: ["oct"],
497
- secret: true,
498
- subtle: { name: cbc ? "AES-CBC" : "AES-GCM", length: bits },
499
- usages: none,
500
- ops: contentOps,
501
- cekBits: bits,
502
- ivBits: cbc ? 128 : 96,
503
- cbc
504
- };
505
- }
506
- var ENC = table({
507
- A128GCM: contentEncryption(128),
508
- A192GCM: contentEncryption(192),
509
- A256GCM: contentEncryption(256),
510
- "A128CBC-HS256": contentEncryption(256, true),
511
- "A192CBC-HS384": contentEncryption(384, true),
512
- "A256CBC-HS512": contentEncryption(512, true)
513
- });
514
-
515
- // ../../node_modules/jose/dist/webapi/lib/jws_algorithms.js
516
- var sig = [["verify"], ["sign"]];
517
- function hmac(bits) {
518
- const subtle = { name: "HMAC", hash: `SHA-${bits}` };
519
- return { kty: ["oct"], secret: true, subtle, signing: subtle, usages: sig };
520
- }
521
- function rsa(bits, saltLength) {
522
- const subtle = { name: saltLength ? "RSA-PSS" : "RSASSA-PKCS1-v1_5", hash: `SHA-${bits}` };
523
- return {
524
- kty: ["RSA"],
525
- subtle,
526
- signing: saltLength ? { ...subtle, saltLength } : subtle,
527
- usages: sig,
528
- minRsaBits: 2048
529
- };
530
- }
531
- function ecdsa(crv, bits) {
532
- return {
533
- kty: ["EC"],
534
- crv,
535
- subtle: { name: "ECDSA", namedCurve: crv },
536
- signing: { name: "ECDSA", hash: `SHA-${bits}` },
537
- usages: sig
538
- };
539
- }
540
- function eddsa() {
541
- const subtle = { name: "Ed25519" };
542
- return {
543
- kty: ["OKP"],
544
- crv: "Ed25519",
545
- subtle,
546
- signing: subtle,
547
- usages: sig
548
- };
549
- }
550
- function mldsa(bits) {
551
- const subtle = { name: `ML-DSA-${bits}` };
552
- return {
553
- kty: ["AKP"],
554
- subtle,
555
- signing: subtle,
556
- usages: sig
557
- };
558
- }
559
- var JWS = table({
560
- HS256: hmac(256),
561
- HS384: hmac(384),
562
- HS512: hmac(512),
563
- RS256: rsa(256),
564
- RS384: rsa(384),
565
- RS512: rsa(512),
566
- PS256: rsa(256, 32),
567
- PS384: rsa(384, 48),
568
- PS512: rsa(512, 64),
569
- ES256: ecdsa("P-256", 256),
570
- ES384: ecdsa("P-384", 384),
571
- ES512: ecdsa("P-521", 512),
572
- EdDSA: eddsa(),
573
- Ed25519: eddsa(),
574
- "ML-DSA-44": mldsa(44),
575
- "ML-DSA-65": mldsa(65),
576
- "ML-DSA-87": mldsa(87)
577
- });
578
- function jwsAlgorithm(alg) {
579
- const entry = typeof alg == "string" ? JWS[alg] : void 0;
580
- if (!entry)
581
- throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`);
582
- return entry;
583
- }
584
-
585
- // ../../node_modules/jose/dist/webapi/lib/jws_verify.js
586
- function prepareVerify(options) {
587
- return [options && validateAlgorithms("algorithms", options.algorithms), options?.crit];
588
- }
589
- function parseProtectedHeader(encodedProtected) {
590
- return encodedProtected === void 0 ? {} : parseJoseHeader(encodedProtected, JWSInvalid, "JWS Protected Header is invalid");
591
- }
592
- function encodeCompactUnencodedPayload(payload) {
593
- try {
594
- return encode(payload);
595
- } catch {
596
- throw new JWSInvalid("JWS Compact Serialization payload must use only ASCII characters");
597
- }
598
- }
599
- async function verifySignature(jws, shared, key, encodeUnencodedPayload, parsedProtected) {
600
- const { protected: encodedProtected, header, payload: inputPayload } = jws, parsedProt = parsedProtected ?? parseProtectedHeader(encodedProtected);
601
- if (!isDisjoint(parsedProt, header))
602
- throw new JWSInvalid("JWS Protected and JWS Unprotected Header Parameter names must be disjoint");
603
- const joseHeader = { ...parsedProt, ...header }, b64 = validateB64(parsedProt, validateCrit(JWSInvalid, JWS_RECOGNIZED, shared[1], parsedProt, joseHeader)), { alg } = joseHeader;
604
- if (typeof alg != "string" || !alg)
605
- throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid');
606
- if (shared[0] && !shared[0].has(alg))
607
- throw new JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter value not allowed');
608
- if (b64) {
609
- if (typeof inputPayload != "string")
610
- throw new JWSInvalid("JWS Payload must be a string");
611
- } else if (typeof inputPayload != "string" && !(inputPayload instanceof Uint8Array))
612
- throw new JWSInvalid("JWS Payload must be a string or an Uint8Array instance");
613
- const signingPayload = b64 || typeof inputPayload != "string" ? inputPayload : encodeUnencodedPayload(inputPayload);
614
- let resolvedKey = false;
615
- typeof key == "function" && (key = await key(parsedProt, jws), resolvedKey = true);
616
- const entry = jwsAlgorithm(alg), data = concat(encodedProtected !== void 0 ? encode(encodedProtected) : new Uint8Array(), encode("."), typeof signingPayload == "string" ? shared[2] ??= encodeBase64url(signingPayload, "payload", JWSInvalid) : signingPayload), signature = decodeBase64url(jws.signature, "signature", JWSInvalid), k = await prepareKey(entry, key, "verify"), cryptoKey = await rawKey(k, entry.subtle, "verify");
617
- entry.minRsaBits && checkModulusLength(entry.alg, cryptoKey);
618
- let verified = false;
619
- try {
620
- verified = await crypto.subtle.verify(entry.signing, cryptoKey, signature, data);
621
- } catch {
622
- }
623
- if (!verified)
624
- throw new JWSSignatureVerificationFailed();
625
- const result = { payload: typeof signingPayload == "string" ? decodeBase64url(signingPayload, "payload", JWSInvalid) : signingPayload };
626
- return encodedProtected !== void 0 && (result.protectedHeader = parsedProt), header !== void 0 && (result.unprotectedHeader = header), resolvedKey ? [{ ...result, key: k }, b64] : [result, b64];
627
- }
628
- async function verifyCompact(jws, shared, key) {
629
- if (jws instanceof Uint8Array && (jws = decoder.decode(jws)), typeof jws != "string")
630
- throw new JWSInvalid("Compact JWS must be a string or Uint8Array");
631
- const { 0: protectedHeader, 1: payload, 2: signature, length } = jws.split(".");
632
- if (length !== 3)
633
- throw new JWSInvalid("Invalid Compact JWS");
634
- return verifySignature({ payload, protected: protectedHeader, signature }, shared, key, encodeCompactUnencodedPayload);
635
- }
636
-
637
- // ../../node_modules/jose/dist/webapi/lib/jwt_claims_set.js
638
- var epoch = (date) => Math.floor(date.getTime() / 1e3);
639
- var multipliers = {
640
- s: 1,
641
- m: 60,
642
- h: 3600,
643
- d: 86400,
644
- w: 604800,
645
- y: 31557600
646
- };
647
- var REGEX = /^(\+|\-)? ?(\d+|\d+\.\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)(?: (ago|from now))?$/i;
648
- var checkFailed = "check_failed";
649
- function invalidDuration() {
650
- throw new TypeError("Invalid time period format");
651
- }
652
- function secs(str) {
653
- typeof str != "string" && invalidDuration();
654
- const matched = REGEX.exec(str);
655
- (!matched || matched[4] && matched[1]) && invalidDuration();
656
- const value = parseFloat(matched[2]), numericDate2 = Math.round(value * multipliers[matched[3][0].toLowerCase()]);
657
- return Number.isFinite(numericDate2) || invalidDuration(), matched[1] === "-" || matched[4] === "ago" ? -numericDate2 : numericDate2;
658
- }
659
- function validateInput(label, input) {
660
- if (!Number.isFinite(input))
661
- throw new TypeError(`Invalid ${label} input`);
662
- return input;
663
- }
664
- function validateStringClaim(claim, value) {
665
- if (typeof value != "string")
666
- throw new TypeError(`"${claim}" claim must be a string`);
667
- }
668
- function validateAudienceClaim(value) {
669
- if (typeof value != "string" && (!Array.isArray(value) || Array.from(value).some((member) => typeof member != "string")))
670
- throw new TypeError('"aud" claim must be a string or an array of strings');
671
- }
672
- function numericDate(value, label) {
673
- return typeof value == "number" ? validateInput(label, value) : value instanceof Date ? validateInput(label, epoch(value)) : epoch(/* @__PURE__ */ new Date()) + secs(value);
674
- }
675
- var normalizeTyp = (value) => {
676
- const normalized = value.toLowerCase();
677
- return value.includes("/") ? normalized : `application/${normalized}`;
678
- };
679
- var checkAudiencePresence = (audPayload, audOption) => typeof audPayload == "string" ? audOption.includes(audPayload) : Array.isArray(audPayload) ? audOption.some((aud) => audPayload.includes(aud)) : false;
680
- function validateNumericDate(payload, claim, required = false) {
681
- const value = payload[claim];
682
- if (!(value === void 0 && !required)) {
683
- if (typeof value != "number")
684
- throw new JWTClaimValidationFailed(`"${claim}" claim must be a number`, payload, claim, "invalid");
685
- return value;
686
- }
687
- }
688
- function unexpectedClaim(payload, claim) {
689
- throw new JWTClaimValidationFailed(`unexpected "${claim}" claim value`, payload, claim, checkFailed);
690
- }
691
- function validateClaimsSet(protectedHeader, encodedPayload, options = {}) {
692
- let payload;
693
- try {
694
- payload = JSON.parse(strictDecoder.decode(encodedPayload));
695
- } catch {
696
- }
697
- if (!isObject(payload))
698
- throw new JWTInvalid("JWT Claims Set must be a top-level JSON object");
699
- const { typ } = options;
700
- if (typ !== void 0 && (typeof protectedHeader.typ != "string" || normalizeTyp(protectedHeader.typ) !== normalizeTyp(typ)))
701
- throw new JWTClaimValidationFailed('unexpected "typ" JWT header value', payload, "typ", checkFailed);
702
- const { requiredClaims = [], issuer, subject, audience, maxTokenAge } = options, presenceCheck = [...requiredClaims];
703
- maxTokenAge !== void 0 && presenceCheck.push("iat"), audience !== void 0 && presenceCheck.push("aud"), subject !== void 0 && presenceCheck.push("sub"), issuer !== void 0 && presenceCheck.push("iss");
704
- for (const claim of new Set(presenceCheck.reverse()))
705
- if (!Object.hasOwn(payload, claim))
706
- throw new JWTClaimValidationFailed(`missing required "${claim}" claim`, payload, claim, "missing");
707
- issuer !== void 0 && !(Array.isArray(issuer) ? issuer : [issuer]).includes(payload.iss) && unexpectedClaim(payload, "iss"), subject !== void 0 && payload.sub !== subject && unexpectedClaim(payload, "sub"), audience !== void 0 && !checkAudiencePresence(payload.aud, typeof audience == "string" ? [audience] : audience) && unexpectedClaim(payload, "aud");
708
- const { clockTolerance } = options;
709
- let tolerance = 0;
710
- if (typeof clockTolerance == "string")
711
- tolerance = secs(clockTolerance);
712
- else if (clockTolerance !== void 0) {
713
- if (typeof clockTolerance != "number")
714
- throw new TypeError("Invalid clockTolerance option type");
715
- tolerance = clockTolerance;
716
- }
717
- validateInput("clockTolerance option", tolerance);
718
- const { currentDate } = options, now = validateInput("currentDate option", epoch(currentDate === void 0 ? /* @__PURE__ */ new Date() : currentDate)), iat = validateNumericDate(payload, "iat", maxTokenAge !== void 0), nbf = validateNumericDate(payload, "nbf");
719
- if (nbf !== void 0 && nbf > now + tolerance)
720
- throw new JWTClaimValidationFailed('"nbf" claim timestamp check failed', payload, "nbf", checkFailed);
721
- const exp = validateNumericDate(payload, "exp");
722
- if (exp !== void 0 && exp <= now - tolerance)
723
- throw new JWTExpired('"exp" claim timestamp check failed', payload, "exp", checkFailed);
724
- if (maxTokenAge !== void 0) {
725
- const age = now - iat, max = validateInput("maxTokenAge option", typeof maxTokenAge == "number" ? maxTokenAge : secs(maxTokenAge));
726
- if (age - tolerance > max)
727
- throw new JWTExpired('"iat" claim timestamp check failed (too far in the past)', payload, "iat", checkFailed);
728
- if (age < -tolerance)
729
- throw new JWTClaimValidationFailed('"iat" claim timestamp check failed (it should be in the past)', payload, "iat", checkFailed);
730
- }
731
- return payload;
732
- }
733
- var producerPayloads;
734
- function producerPayload(producer) {
735
- return producerPayloads.get(producer);
736
- }
737
- function jwtData(producer) {
738
- const payload = producerPayload(producer);
739
- for (const claim of ["iat", "nbf", "exp"]) {
740
- const value = payload[claim];
741
- if (typeof value == "number" && !Number.isFinite(value))
742
- throw new TypeError(`"${claim}" claim must be a finite number`);
743
- }
744
- return encoder.encode(JSON.stringify(payload));
745
- }
746
- var JWTClaimsBuilder = class {
747
- constructor(payload = {}) {
748
- if (!isObject(payload))
749
- throw new TypeError("JWT Claims Set MUST be an object");
750
- (producerPayloads ||= /* @__PURE__ */ new WeakMap()).set(this, structuredClone(payload));
751
- }
752
- setIssuer(value) {
753
- return validateStringClaim("iss", value), producerPayload(this).iss = value, this;
754
- }
755
- setSubject(value) {
756
- return validateStringClaim("sub", value), producerPayload(this).sub = value, this;
757
- }
758
- setAudience(value) {
759
- return validateAudienceClaim(value), producerPayload(this).aud = value, this;
760
- }
761
- setJti(value) {
762
- return validateStringClaim("jti", value), producerPayload(this).jti = value, this;
763
- }
764
- setNotBefore(value) {
765
- return producerPayload(this).nbf = numericDate(value, "setNotBefore"), this;
766
- }
767
- setExpirationTime(value) {
768
- return producerPayload(this).exp = numericDate(value, "setExpirationTime"), this;
769
- }
770
- setIssuedAt(value) {
771
- const payload = producerPayload(this);
772
- return value === void 0 ? payload.iat = epoch(/* @__PURE__ */ new Date()) : typeof value == "string" ? payload.iat = validateInput("setIssuedAt", epoch(/* @__PURE__ */ new Date()) + secs(value)) : payload.iat = numericDate(value, "setIssuedAt"), this;
773
- }
774
- };
775
-
776
- // ../../node_modules/jose/dist/webapi/jwt/verify.js
777
- async function jwtVerify(jwt, key, options) {
778
- const [verified, b64] = await verifyCompact(jwt, prepareVerify(options), key);
779
- if (!b64)
780
- throw new JWTInvalid("JWTs MUST NOT use unencoded payload");
781
- const payload = validateClaimsSet(verified.protectedHeader, verified.payload, options);
782
- return { ...verified, payload };
783
- }
784
-
785
- // ../../node_modules/jose/dist/webapi/lib/jws_sign.js
786
- async function createSignature(input, key, rejectUnencoded) {
787
- let [payload, protectedHeader, unprotectedHeader, crit] = input, protectedHeaderString = "";
788
- if (protectedHeader !== void 0) {
789
- const normalized = serializeJoseHeader(JWSInvalid, protectedHeader);
790
- protectedHeader = normalized[0], protectedHeaderString = encode2(normalized[1]);
791
- }
792
- if (unprotectedHeader !== void 0 && (unprotectedHeader = serializeJoseHeader(JWSInvalid, unprotectedHeader)[0]), !protectedHeader && !unprotectedHeader)
793
- throw new JWSInvalid("either setProtectedHeader or setUnprotectedHeader must be called before #sign()");
794
- if (!isDisjoint(protectedHeader, unprotectedHeader))
795
- throw new JWSInvalid("JWS Protected and JWS Unprotected Header Parameter names must be disjoint");
796
- const joseHeader = { ...protectedHeader, ...unprotectedHeader };
797
- validateCritDuplicates(JWSInvalid, protectedHeader);
798
- const b64 = validateB64(protectedHeader, validateCrit(JWSInvalid, JWS_RECOGNIZED, crit, protectedHeader, joseHeader));
799
- b64 || rejectUnencoded?.();
800
- const { alg } = joseHeader;
801
- if (typeof alg != "string" || !alg)
802
- throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid');
803
- const entry = jwsAlgorithm(alg);
804
- let payloadS = "", payloadB = payload, data;
805
- if (b64) {
806
- const encoded = input[4];
807
- encoded ? (payloadS = encoded[0] ??= encode2(payload), payloadB = encoded[1] ??= encode(payloadS)) : (payloadS = encode2(payload), data = encoder.encode(`${protectedHeaderString}.${payloadS}`));
808
- }
809
- data ??= concat(encode(protectedHeaderString), encode("."), payloadB);
810
- const k = await rawKey(await prepareKey(entry, key, "sign"), entry.subtle, "sign");
811
- entry.minRsaBits && checkModulusLength(entry.alg, k);
812
- const jws = {
813
- signature: encode2(new Uint8Array(await crypto.subtle.sign(entry.signing, k, data))),
814
- payload: payloadS
815
- };
816
- return protectedHeader && (jws.protected = protectedHeaderString), unprotectedHeader && (jws.header = unprotectedHeader), [jws, b64];
817
- }
818
- async function createCompactSignature(payload, protectedHeader, crit, key, rejectUnencoded) {
819
- const [jws] = await createSignature([payload, protectedHeader, void 0, crit], key, rejectUnencoded);
820
- return `${jws.protected}.${jws.payload}.${jws.signature}`;
821
- }
822
-
823
- // ../../node_modules/jose/dist/webapi/jwt/sign.js
824
- var SignJWT_base = JWTClaimsBuilder;
825
- var SignJWT = class extends SignJWT_base {
826
- #protectedHeader;
827
- setProtectedHeader(protectedHeader) {
828
- return assertNotSet(this.#protectedHeader, "setProtectedHeader"), this.#protectedHeader = protectedHeader, this;
829
- }
830
- async sign(key, options) {
831
- return createCompactSignature(jwtData(this), this.#protectedHeader, options?.crit, key, () => {
832
- throw new JWTInvalid("JWTs MUST NOT use unencoded payload");
833
- });
834
- }
835
- };
836
-
837
- // ../../node_modules/jose/dist/webapi/lib/key_algorithm.js
838
- function unsupportedAlg(source = 'JWK "alg" (Algorithm) Parameter') {
839
- throw new JOSENotSupported(`Invalid or unsupported ${source} value`);
840
- }
841
- function keyAlgorithm(alg, source) {
842
- return (typeof alg == "string" ? JWS[alg] ?? JWE[alg] : void 0) ?? unsupportedAlg(source);
843
- }
844
-
845
- // ../../node_modules/jose/dist/webapi/key/export.js
846
- async function exportJWK(key) {
847
- if (isKeyObject(key))
848
- if (key.type === "secret")
849
- key = key.export();
850
- else
851
- return key.export({ format: "jwk" });
852
- if (key instanceof Uint8Array)
853
- return {
854
- kty: "oct",
855
- k: encode2(key)
856
- };
857
- if (!isCryptoKey(key))
858
- throw new TypeError(invalidKeyInput(key, "CryptoKey", "KeyObject", "Uint8Array"));
859
- if (!key.extractable)
860
- throw new TypeError("non-extractable CryptoKey cannot be exported as a JWK");
861
- const jwk = await crypto.subtle.exportKey("jwk", key);
862
- delete jwk.ext, delete jwk.key_ops, delete jwk.use, jwk.kty !== "AKP" && delete jwk.alg;
863
- for (const parameter of Object.keys(jwk))
864
- jwk[parameter] === void 0 && delete jwk[parameter];
865
- return jwk;
866
- }
867
-
868
- // ../../node_modules/jose/dist/webapi/jwk/thumbprint.js
869
- var check = (value, description) => {
870
- if (typeof value != "string" || !value)
871
- throw new JWKInvalid(`${description} missing or invalid`);
872
- };
873
- async function calculateJwkThumbprint(key, digestAlgorithm) {
874
- let jwk;
875
- if (isObject(key)) {
876
- if (jwk = snapshotJwk(key), typeof jwk.kty != "string")
877
- throw new TypeError(invalidKeyInput(key, "CryptoKey", "KeyObject", "JSON Web Key"));
878
- } else if (isKeyLike(key))
879
- jwk = snapshotJwk(await exportJWK(key));
880
- else
881
- throw new TypeError(invalidKeyInput(key, "CryptoKey", "KeyObject", "JSON Web Key"));
882
- if (digestAlgorithm ??= "sha256", digestAlgorithm !== "sha256" && digestAlgorithm !== "sha384" && digestAlgorithm !== "sha512")
883
- throw new TypeError('digestAlgorithm must one of "sha256", "sha384", or "sha512"');
884
- let components;
885
- switch (jwk.kty) {
886
- case "AKP":
887
- check(jwk.alg, '"alg" (Algorithm) Parameter'), check(jwk.pub, '"pub" (Public key) Parameter'), components = { alg: jwk.alg, kty: jwk.kty, pub: jwk.pub };
888
- break;
889
- case "EC":
890
- check(jwk.crv, '"crv" (Curve) Parameter'), check(jwk.x, '"x" (X Coordinate) Parameter'), check(jwk.y, '"y" (Y Coordinate) Parameter'), components = { crv: jwk.crv, kty: jwk.kty, x: jwk.x, y: jwk.y };
891
- break;
892
- case "OKP":
893
- check(jwk.crv, '"crv" (Subtype of Key Pair) Parameter'), check(jwk.x, '"x" (Public Key) Parameter'), components = { crv: jwk.crv, kty: jwk.kty, x: jwk.x };
894
- break;
895
- case "RSA":
896
- check(jwk.e, '"e" (Exponent) Parameter'), check(jwk.n, '"n" (Modulus) Parameter'), components = { e: jwk.e, kty: jwk.kty, n: jwk.n };
897
- break;
898
- case "oct":
899
- if (typeof jwk.k != "string")
900
- throw new JWKInvalid('"k" (Key Value) Parameter missing or invalid');
901
- components = { k: jwk.k, kty: jwk.kty };
902
- break;
903
- default:
904
- throw new JOSENotSupported('"kty" (Key Type) Parameter missing or unsupported');
905
- }
906
- const data = encode(JSON.stringify(components));
907
- return encode2(await digest(digestAlgorithm, data));
908
- }
909
-
910
- // ../../node_modules/jose/dist/webapi/key/import.js
911
- async function importJWK(jwk, alg, options) {
912
- if (!isObject(jwk))
913
- throw new TypeError("JWK must be an object");
914
- const normalized = normalizeJwk(jwk), extractable = validateExtractableOption(options?.extractable), { alg: jwkAlg } = normalized;
915
- if (alg ??= jwkAlg, normalized.kty !== "oct" && !alg)
916
- throw new TypeError('"alg" argument is required when "jwk.alg" is not present');
917
- switch (normalized.kty) {
918
- case "oct":
919
- if (typeof normalized.k != "string")
920
- throw new TypeError('missing "k" (Key Value) Parameter value');
921
- return decode(normalized.k);
922
- case "AKP": {
923
- if (typeof jwkAlg != "string" || !jwkAlg)
924
- throw new TypeError('missing "alg" (Algorithm) Parameter value');
925
- if (alg !== jwkAlg)
926
- throw new TypeError("JWK alg and alg option value mismatch");
927
- return jwkToKey(keyAlgorithm(alg), normalized, extractable);
928
- }
929
- case "RSA":
930
- case "EC":
931
- case "OKP":
932
- return jwkToKey(keyAlgorithm(alg), normalized, extractable);
933
- default:
934
- throw new JOSENotSupported('Unsupported "kty" (Key Type) Parameter value');
935
- }
936
- }
937
-
938
- // ../../node_modules/jose/dist/webapi/util/decode_protected_header.js
939
- function decodeProtectedHeader(token) {
940
- let protectedB64u;
941
- if (typeof token == "string") {
942
- const parts = token.split(".");
943
- (parts.length === 3 || parts.length === 5) && ([protectedB64u] = parts);
944
- } else if (typeof token == "object" && token)
945
- if ("protected" in token)
946
- protectedB64u = token.protected;
947
- else
948
- throw new TypeError("Token does not contain a Protected Header");
949
- const invalid2 = "Invalid Token or Protected Header formatting";
950
- if (typeof protectedB64u != "string" || !protectedB64u)
951
- throw new TypeError(invalid2);
952
- return parseJoseHeader(protectedB64u, TypeError, invalid2);
953
- }
954
-
955
- // src/json.ts
956
- function parseJsonStrict(source) {
957
- return new StrictJsonParser(source).parse();
958
- }
959
- var StrictJsonParser = class {
960
- constructor(source) {
961
- this.source = source;
962
- }
963
- #offset = 0;
964
- parse() {
965
- this.#skipWhitespace();
966
- const value = this.#parseValue();
967
- this.#skipWhitespace();
968
- if (this.#offset !== this.source.length) {
969
- this.#invalid("Unexpected content after the JSON value");
970
- }
971
- return value;
972
- }
973
- #parseValue() {
974
- const character = this.source[this.#offset];
975
- if (character === "{") return this.#parseObject();
976
- if (character === "[") return this.#parseArray();
977
- if (character === '"') return this.#parseString();
978
- if (character === "t") return this.#parseLiteral("true", true);
979
- if (character === "f") return this.#parseLiteral("false", false);
980
- if (character === "n") return this.#parseLiteral("null", null);
981
- if (character === "-" || character !== void 0 && /[0-9]/.test(character)) {
982
- return this.#parseNumber();
983
- }
984
- this.#invalid("Expected a JSON value");
985
- }
986
- #parseObject() {
987
- this.#offset += 1;
988
- this.#skipWhitespace();
989
- const result = {};
990
- const names = /* @__PURE__ */ new Set();
991
- if (this.#consume("}")) return result;
992
- while (true) {
993
- if (this.source[this.#offset] !== '"') {
994
- this.#invalid("Expected a JSON object member name");
995
- }
996
- const name = this.#parseString();
997
- if (names.has(name)) {
998
- throw new ProtocolValidationError(
999
- "duplicate_json_member",
1000
- `JSON object contains duplicate member ${JSON.stringify(name)}`
1001
- );
1002
- }
1003
- names.add(name);
1004
- this.#skipWhitespace();
1005
- if (!this.#consume(":")) this.#invalid("Expected ':' after an object member name");
1006
- this.#skipWhitespace();
1007
- result[name] = this.#parseValue();
1008
- this.#skipWhitespace();
1009
- if (this.#consume("}")) return result;
1010
- if (!this.#consume(",")) this.#invalid("Expected ',' or '}' in a JSON object");
1011
- this.#skipWhitespace();
1012
- }
1013
- }
1014
- #parseArray() {
1015
- this.#offset += 1;
1016
- this.#skipWhitespace();
1017
- const result = [];
1018
- if (this.#consume("]")) return result;
1019
- while (true) {
1020
- result.push(this.#parseValue());
1021
- this.#skipWhitespace();
1022
- if (this.#consume("]")) return result;
1023
- if (!this.#consume(",")) this.#invalid("Expected ',' or ']' in a JSON array");
1024
- this.#skipWhitespace();
1025
- }
1026
- }
1027
- #parseString() {
1028
- const start = this.#offset;
1029
- this.#offset += 1;
1030
- while (this.#offset < this.source.length) {
1031
- const character = this.source[this.#offset];
1032
- if (character === '"') {
1033
- this.#offset += 1;
1034
- const encoded = this.source.slice(start, this.#offset);
1035
- try {
1036
- return JSON.parse(encoded);
1037
- } catch (cause) {
1038
- this.#invalid("Invalid JSON string", cause);
1039
- }
1040
- }
1041
- if (character === "\\") {
1042
- this.#offset += 1;
1043
- if (this.#offset >= this.source.length) this.#invalid("Unterminated JSON escape");
1044
- if (this.source[this.#offset] === "u") {
1045
- const digits = this.source.slice(this.#offset + 1, this.#offset + 5);
1046
- if (!/^[0-9a-fA-F]{4}$/.test(digits)) this.#invalid("Invalid Unicode escape");
1047
- this.#offset += 4;
1048
- } else if (!'"\\/bfnrt'.includes(this.source[this.#offset] ?? "")) {
1049
- this.#invalid("Invalid JSON escape");
1050
- }
1051
- } else if (character === void 0 || character.charCodeAt(0) < 32) {
1052
- this.#invalid("Invalid control character in JSON string");
1053
- }
1054
- this.#offset += 1;
1055
- }
1056
- this.#invalid("Unterminated JSON string");
1057
- }
1058
- #parseNumber() {
1059
- const remainder = this.source.slice(this.#offset);
1060
- const match = /^-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?/.exec(remainder);
1061
- if (!match) this.#invalid("Invalid JSON number");
1062
- this.#offset += match[0].length;
1063
- const value = Number(match[0]);
1064
- if (!Number.isFinite(value)) this.#invalid("JSON number is outside the supported range");
1065
- return value;
1066
- }
1067
- #parseLiteral(encoded, value) {
1068
- if (!this.source.startsWith(encoded, this.#offset)) {
1069
- this.#invalid("Invalid JSON literal");
1070
- }
1071
- this.#offset += encoded.length;
1072
- return value;
1073
- }
1074
- #skipWhitespace() {
1075
- while (this.#offset < this.source.length && " \r\n".includes(this.source[this.#offset] ?? "")) {
1076
- this.#offset += 1;
1077
- }
1078
- }
1079
- #consume(character) {
1080
- if (this.source[this.#offset] !== character) return false;
1081
- this.#offset += 1;
1082
- return true;
1083
- }
1084
- #invalid(message2, cause) {
1085
- throw new ProtocolValidationError("invalid_json", message2, {
1086
- cause
1087
- });
1088
- }
1089
- };
1090
-
1091
- // ../../node_modules/@datalayer/reactor/lib/core/contributions.js
1092
- function defineContributionPoint(id) {
1093
- if (!id) {
1094
- throw new Error("defineContributionPoint: a contribution point needs an id");
1095
- }
1096
- return { id };
1097
- }
1098
- function contribution(point, value, options) {
1099
- return { point, value, options };
1100
- }
1101
- var ContributionRegistry = class {
1102
- byPoint = /* @__PURE__ */ new Map();
1103
- byPlugin = /* @__PURE__ */ new Map();
1104
- seq = 0;
1105
- /**
1106
- * Store a contribution and return its disposer. The disposer is idempotent
1107
- * and is also called automatically when the contributing plugin stops.
1108
- */
1109
- add(pluginName, point, value, options = {}) {
1110
- const entry = {
1111
- plugin: pluginName,
1112
- id: options.id ?? pluginName,
1113
- order: options.order ?? 0,
1114
- value,
1115
- seq: this.seq++
1116
- };
1117
- const entries = this.byPoint.get(point.id);
1118
- if (entries) {
1119
- entries.push(entry);
1120
- } else {
1121
- this.byPoint.set(point.id, [entry]);
1122
- }
1123
- let disposed = false;
1124
- const dispose = () => {
1125
- if (disposed) {
1126
- return;
1127
- }
1128
- disposed = true;
1129
- const current = this.byPoint.get(point.id);
1130
- if (current) {
1131
- const index = current.indexOf(entry);
1132
- if (index >= 0) {
1133
- current.splice(index, 1);
1134
- }
1135
- if (current.length === 0) {
1136
- this.byPoint.delete(point.id);
1137
- }
1138
- }
1139
- this.byPlugin.get(pluginName)?.delete(dispose);
1140
- };
1141
- const owned = this.byPlugin.get(pluginName);
1142
- if (owned) {
1143
- owned.add(dispose);
1144
- } else {
1145
- this.byPlugin.set(pluginName, /* @__PURE__ */ new Set([dispose]));
1146
- }
1147
- return dispose;
1148
- }
1149
- /** Contributions for a point, ordered by `order` then registration order. */
1150
- get(point) {
1151
- const entries = this.byPoint.get(point.id);
1152
- if (!entries || entries.length === 0) {
1153
- return [];
1154
- }
1155
- return [...entries].sort((a, b) => a.order === b.order ? a.seq - b.seq : a.order - b.order).map(({ plugin, id, order, value }) => ({
1156
- plugin,
1157
- id,
1158
- order,
1159
- value
1160
- }));
1161
- }
1162
- /** Ids of the points that currently hold something. */
1163
- points() {
1164
- return [...this.byPoint.keys()].sort();
1165
- }
1166
- /**
1167
- * Every point and what is currently contributed to it.
1168
- *
1169
- * For hosts that describe the whole graph rather than read one point — they
1170
- * have no `ContributionPoint` objects to look things up with, only ids.
1171
- */
1172
- describe() {
1173
- return this.points().map((point) => ({
1174
- point,
1175
- contributions: (this.byPoint.get(point) ?? []).slice().sort((a, b) => a.order === b.order ? a.seq - b.seq : a.order - b.order).map(({ plugin, id, order, value }) => ({ plugin, id, order, value }))
1176
- }));
1177
- }
1178
- /** Drop everything one plugin contributed (on `disable`, `stop`). */
1179
- disposePlugin(pluginName) {
1180
- const owned = this.byPlugin.get(pluginName);
1181
- if (!owned) {
1182
- return;
1183
- }
1184
- for (const dispose of [...owned]) {
1185
- dispose();
1186
- }
1187
- this.byPlugin.delete(pluginName);
1188
- }
1189
- };
1190
-
1191
- // ../../node_modules/@datalayer/reactor/lib/core/commands.js
1192
- var CommandRegistry = class {
1193
- byId = /* @__PURE__ */ new Map();
1194
- byPlugin = /* @__PURE__ */ new Map();
1195
- listeners = /* @__PURE__ */ new Set();
1196
- seq = 0;
1197
- /**
1198
- * Register a command and return its disposer.
1199
- *
1200
- * The disposer is idempotent, and is also run when the registering plugin
1201
- * stops — so the ordinary case needs no disposer at all.
1202
- *
1203
- * @throws if `id` is already registered. See {@link ReactorCommand.id}.
1204
- */
1205
- add(pluginName, command) {
1206
- if (!command.id) {
1207
- throw new Error("CommandRegistry.add: a command needs an id");
1208
- }
1209
- const existing = this.byId.get(command.id);
1210
- if (existing) {
1211
- throw new Error(`CommandRegistry.add: command '${command.id}' is already registered by plugin '${existing.plugin}'. Command ids must be unique; namespace them with the plugin they belong to.`);
1212
- }
1213
- const entry = {
1214
- plugin: pluginName,
1215
- seq: this.seq++,
1216
- command
1217
- };
1218
- this.byId.set(command.id, entry);
1219
- let disposed = false;
1220
- const dispose = () => {
1221
- if (disposed) {
1222
- return;
1223
- }
1224
- disposed = true;
1225
- if (this.byId.get(command.id) === entry) {
1226
- this.byId.delete(command.id);
1227
- }
1228
- this.byPlugin.get(pluginName)?.delete(dispose);
1229
- this.notify();
1230
- };
1231
- const owned = this.byPlugin.get(pluginName);
1232
- if (owned) {
1233
- owned.add(dispose);
1234
- } else {
1235
- this.byPlugin.set(pluginName, /* @__PURE__ */ new Set([dispose]));
1236
- }
1237
- this.notify();
1238
- return dispose;
1239
- }
1240
- /** One command by id, or `undefined`. */
1241
- get(id) {
1242
- const entry = this.byId.get(id);
1243
- return entry ? { ...entry.command, plugin: entry.plugin } : void 0;
1244
- }
1245
- /** Every command, ordered by `order` then registration order. */
1246
- list() {
1247
- return [...this.byId.values()].sort((a, b) => {
1248
- const orderA = a.command.order ?? 0;
1249
- const orderB = b.command.order ?? 0;
1250
- return orderA === orderB ? a.seq - b.seq : orderA - orderB;
1251
- }).map((entry) => ({ ...entry.command, plugin: entry.plugin }));
1252
- }
1253
- /**
1254
- * Run a command by id.
1255
- *
1256
- * Always async, even for a synchronous command, so a caller never has to ask
1257
- * which kind it invoked. A command that throws rejects here rather than
1258
- * taking down the surface that invoked it — the caller decides what a failed
1259
- * command looks like, because only it knows where to say so. Resolves with
1260
- * whatever the command returned: nothing for most, the answer for one that
1261
- * is an agent's tool.
1262
- *
1263
- * @throws if no such command is registered, or if it is currently disabled.
1264
- */
1265
- async execute(id, argument) {
1266
- const entry = this.byId.get(id);
1267
- if (!entry) {
1268
- throw new Error(`CommandRegistry.execute: no command '${id}' is registered`);
1269
- }
1270
- if (entry.command.isEnabled && !entry.command.isEnabled()) {
1271
- throw new Error(`CommandRegistry.execute: command '${id}' is not available right now`);
1272
- }
1273
- return await entry.command.execute(argument);
1274
- }
1275
- /**
1276
- * Be told when the set of commands changes.
1277
- *
1278
- * Registration and disposal both wake subscribers; *running* a command does
1279
- * not. Hosts that already follow the reactor's revision get this for free —
1280
- * this exists for a surface holding the registry alone.
1281
- */
1282
- subscribe(listener) {
1283
- this.listeners.add(listener);
1284
- return () => {
1285
- this.listeners.delete(listener);
1286
- };
1287
- }
1288
- /** Drop every command one plugin registered (on `disable`, `stop`). */
1289
- disposePlugin(pluginName) {
1290
- const owned = this.byPlugin.get(pluginName);
1291
- if (!owned) {
1292
- return;
1293
- }
1294
- for (const dispose of [...owned]) {
1295
- dispose();
1296
- }
1297
- this.byPlugin.delete(pluginName);
1298
- }
1299
- notify() {
1300
- for (const listener of [...this.listeners]) {
1301
- listener();
1302
- }
1303
- }
1304
- };
1305
-
1306
- // ../../node_modules/@datalayer/reactor/lib/core/activation.js
1307
- var ON_STARTUP = "onStartup";
1308
- var ON_ANY = "*";
1309
- function onContributionPoint(point) {
1310
- return `onContributionPoint:${typeof point === "string" ? point : point.id}`;
1311
- }
1312
- function matchesActivation(declared, event) {
1313
- if (!declared || declared.length === 0) {
1314
- return event === ON_STARTUP;
1315
- }
1316
- return declared.some((candidate) => candidate === ON_ANY || candidate === event);
1317
- }
1318
- function matchesDeactivation(declared, event) {
1319
- if (!declared || declared.length === 0) {
1320
- return false;
1321
- }
1322
- return declared.some((candidate) => candidate === ON_ANY || candidate === event);
1323
- }
1324
- function activatesAtStartup(declared) {
1325
- return matchesActivation(declared, ON_STARTUP);
1326
- }
1327
-
1328
- // ../../node_modules/@datalayer/reactor/lib/core/extension.js
1329
- function isExtension(ref) {
1330
- return typeof ref === "object" && ref !== null && typeof ref.name === "string" && Array.isArray(ref.plugins);
1331
- }
1332
-
1333
- // ../../node_modules/@datalayer/reactor/lib/core/gates.js
1334
- function isRefusal(answer) {
1335
- return answer !== true;
1336
- }
1337
- function resolveGate(answers, context) {
1338
- const refusals = [];
1339
- for (const answer of answers) {
1340
- let result;
1341
- try {
1342
- result = answer.value.check(context);
1343
- } catch (error) {
1344
- result = error instanceof Error ? error.message : String(error);
1345
- }
1346
- if (isRefusal(result)) {
1347
- refusals.push({ plugin: answer.plugin, reason: result });
1348
- }
1349
- }
1350
- const first = refusals[0];
1351
- return {
1352
- allowed: refusals.length === 0,
1353
- reason: first?.reason,
1354
- blockedBy: first?.plugin,
1355
- refusals
1356
- };
1357
- }
1358
-
1359
- // ../../node_modules/@datalayer/reactor/lib/core/reactor.js
1360
- function placeholderFor(ref) {
1361
- return {
1362
- name: ref.name,
1363
- version: ref.version,
1364
- displayName: ref.displayName,
1365
- description: ref.description,
1366
- octicon: ref.octicon,
1367
- emoji: ref.emoji,
1368
- dependencies: ref.dependencies,
1369
- activationEvents: ref.activationEvents,
1370
- deactivationEvents: ref.deactivationEvents,
1371
- requiredBackendPlugins: ref.requiredBackendPlugins,
1372
- optionalBackendPlugins: ref.optionalBackendPlugins,
1373
- contributionPoints: ref.contributionPoints
1374
- };
1375
- }
1376
- function mergeLoaded(ref, loaded) {
1377
- return {
1378
- ...loaded,
1379
- displayName: loaded.displayName ?? ref.displayName,
1380
- description: loaded.description ?? ref.description,
1381
- octicon: loaded.octicon ?? ref.octicon,
1382
- emoji: loaded.emoji ?? ref.emoji,
1383
- version: loaded.version ?? ref.version,
1384
- activationEvents: loaded.activationEvents ?? ref.activationEvents,
1385
- deactivationEvents: loaded.deactivationEvents ?? ref.deactivationEvents,
1386
- requiredBackendPlugins: loaded.requiredBackendPlugins ?? ref.requiredBackendPlugins,
1387
- optionalBackendPlugins: loaded.optionalBackendPlugins ?? ref.optionalBackendPlugins,
1388
- contributionPoints: loaded.contributionPoints ?? ref.contributionPoints
1389
- };
1390
- }
1391
- function shallowMergeConfig(base, override) {
1392
- return { ...base, ...override };
1393
- }
1394
- function normalizePlugins(input) {
1395
- const discovered = /* @__PURE__ */ new Map();
1396
- const lazyByName = /* @__PURE__ */ new Map();
1397
- const extensionOf = /* @__PURE__ */ new Map();
1398
- const extensions2 = /* @__PURE__ */ new Map();
1399
- const queue = input.map((ref) => ({ ref }));
1400
- while (queue.length > 0) {
1401
- const entry = queue.shift();
1402
- if (!entry?.ref) {
1403
- continue;
1404
- }
1405
- const { ref, from } = entry;
1406
- if (isExtension(ref)) {
1407
- extensions2.set(ref.name, ref);
1408
- for (const member of ref.plugins) {
1409
- queue.push({ ref: member, from: ref.name });
1410
- }
1411
- continue;
1412
- }
1413
- if (isLazyPluginRef(ref)) {
1414
- if (!discovered.has(ref.name)) {
1415
- lazyByName.set(ref.name, ref);
1416
- discovered.set(ref.name, placeholderFor(ref));
1417
- if (from) {
1418
- extensionOf.set(ref.name, from);
1419
- }
1420
- for (const dep of ref.dependencies ?? []) {
1421
- queue.push({ ref: dep });
1422
- }
1423
- }
1424
- continue;
1425
- }
1426
- const configured = asConfigured(ref);
1427
- const plugin = configured.plugin;
1428
- if (!discovered.has(plugin.name)) {
1429
- discovered.set(plugin.name, plugin);
1430
- if (from) {
1431
- extensionOf.set(plugin.name, from);
1432
- }
1433
- for (const dep of plugin.dependencies ?? []) {
1434
- queue.push({ ref: dep });
1435
- }
1436
- }
1437
- }
1438
- return { plugins: Array.from(discovered.values()), lazyByName, extensionOf, extensions: extensions2 };
1439
- }
1440
- function topoSort(plugins) {
1441
- const byName = new Map(plugins.map((plugin) => [plugin.name, plugin]));
1442
- const temp = /* @__PURE__ */ new Set();
1443
- const perm = /* @__PURE__ */ new Set();
1444
- const ordered = [];
1445
- function visit(name) {
1446
- if (perm.has(name)) {
1447
- return;
1448
- }
1449
- if (temp.has(name)) {
1450
- throw new Error(`Circular dependency detected at ${name}`);
1451
- }
1452
- temp.add(name);
1453
- const plugin = byName.get(name);
1454
- if (!plugin) {
1455
- throw new Error(`Unknown plugin ${name}`);
1456
- }
1457
- for (const dep of plugin.dependencies ?? []) {
1458
- visit(asConfigured(dep).plugin.name);
1459
- }
1460
- temp.delete(name);
1461
- perm.add(name);
1462
- ordered.push(plugin);
1463
- }
1464
- for (const plugin of plugins) {
1465
- visit(plugin.name);
1466
- }
1467
- return ordered;
1468
- }
1469
- function collectOverrides(input) {
1470
- const out = /* @__PURE__ */ new Map();
1471
- const queue = [...input];
1472
- while (queue.length > 0) {
1473
- const ref = queue.shift();
1474
- if (!ref) {
1475
- continue;
1476
- }
1477
- if (isExtension(ref)) {
1478
- queue.push(...ref.plugins);
1479
- continue;
1480
- }
1481
- if (isLazyPluginRef(ref)) {
1482
- for (const dep of ref.dependencies ?? []) {
1483
- queue.push(dep);
1484
- }
1485
- continue;
1486
- }
1487
- const configured = asConfigured(ref);
1488
- const name = configured.plugin.name;
1489
- const previous = out.get(name) ?? {};
1490
- const merged = shallowMergeConfig(previous, configured.config);
1491
- out.set(name, merged);
1492
- for (const dep of configured.plugin.dependencies ?? []) {
1493
- queue.push(dep);
1494
- }
1495
- }
1496
- return out;
1497
- }
1498
- function buildReactorFromPlugins(pluginsInput, options = {}) {
1499
- const { plugins: allPlugins, lazyByName, extensionOf, extensions: extensions2 } = normalizePlugins(pluginsInput);
1500
- const orderedPlugins = topoSort(allPlugins);
1501
- const byName = new Map(orderedPlugins.map((plugin) => [plugin.name, plugin]));
1502
- const configOverrides = collectOverrides(pluginsInput);
1503
- const state = /* @__PURE__ */ new Map();
1504
- const listeners = /* @__PURE__ */ new Set();
1505
- const contributions = new ContributionRegistry();
1506
- const commands = new CommandRegistry();
1507
- let revision = 0;
1508
- let mutationDepth = 0;
1509
- let readyPromise;
1510
- let started = false;
1511
- const activating = /* @__PURE__ */ new Map();
1512
- const firedPoints = /* @__PURE__ */ new Set();
1513
- const standingDownForBackend = /* @__PURE__ */ new Set();
1514
- let availableBackendPlugins = /* @__PURE__ */ new Set();
1515
- function emitChange() {
1516
- if (mutationDepth > 0) {
1517
- return;
1518
- }
1519
- revision += 1;
1520
- for (const listener of listeners) {
1521
- listener();
1522
- }
1523
- }
1524
- function asOneChange(operation) {
1525
- mutationDepth += 1;
1526
- try {
1527
- return operation();
1528
- } finally {
1529
- mutationDepth -= 1;
1530
- if (mutationDepth === 0) {
1531
- emitChange();
1532
- }
1533
- }
1534
- }
1535
- for (const plugin of orderedPlugins) {
1536
- const mergedConfig = mergeWithDefaults(plugin, configOverrides.get(plugin.name) ?? {});
1537
- state.set(plugin.name, {
1538
- plugin,
1539
- config: mergedConfig,
1540
- enabled: true,
1541
- activated: false,
1542
- extension: extensionOf.get(plugin.name),
1543
- lazy: lazyByName.get(plugin.name),
1544
- loaded: !lazyByName.has(plugin.name)
1545
- });
1546
- }
1547
- for (const plugin of orderedPlugins) {
1548
- for (const conflict of plugin.conflictsWith ?? []) {
1549
- if (byName.has(conflict)) {
1550
- throw new Error(`Plugin ${plugin.name} conflicts with ${conflict}`);
1551
- }
1552
- }
1553
- for (const peer of plugin.peerDependencies ?? []) {
1554
- if (!peer.optional && !byName.has(peer.name) && options.strictPeerDependencies) {
1555
- throw new Error(`Missing required peer dependency ${peer.name} for ${plugin.name}`);
1556
- }
1557
- }
1558
- }
1559
- function waitingFor(event) {
1560
- const waiting = [];
1561
- for (const plugin of orderedPlugins) {
1562
- const current = state.get(plugin.name);
1563
- if (!current || current.activated) {
1564
- continue;
1565
- }
1566
- if (matchesActivation(current.plugin.activationEvents, event)) {
1567
- waiting.push(plugin.name);
1568
- }
1569
- }
1570
- return waiting;
1571
- }
1572
- function readContributions(point) {
1573
- if (!firedPoints.has(point.id)) {
1574
- firedPoints.add(point.id);
1575
- const event = onContributionPoint(point);
1576
- if (waitingFor(event).length > 0) {
1577
- void Promise.resolve().then(() => activateFor(event));
1578
- }
1579
- }
1580
- return contributions.get(point);
1581
- }
1582
- const reactorView = {
1583
- hasPlugin(name) {
1584
- return state.has(name);
1585
- },
1586
- getOutput(name) {
1587
- return state.get(name)?.outputValue;
1588
- },
1589
- getRequiredBackendPlugins(name) {
1590
- return state.get(name)?.plugin.requiredBackendPlugins ?? [];
1591
- },
1592
- getOptionalBackendPlugins(name) {
1593
- return state.get(name)?.plugin.optionalBackendPlugins ?? [];
1594
- },
1595
- getManifest(name) {
1596
- const current = state.get(name);
1597
- if (!current) {
1598
- return void 0;
1599
- }
1600
- const { plugin } = current;
1601
- return {
1602
- name: plugin.name,
1603
- version: plugin.version,
1604
- // The identifier is the fallback: a host should always have something
1605
- // to print, and `@music/catalog` beats an empty line.
1606
- displayName: plugin.displayName ?? plugin.name,
1607
- description: plugin.description,
1608
- octicon: plugin.octicon,
1609
- emoji: plugin.emoji,
1610
- extension: current.extension,
1611
- requiredBackendPlugins: plugin.requiredBackendPlugins ?? [],
1612
- optionalBackendPlugins: plugin.optionalBackendPlugins ?? [],
1613
- loaded: current.loaded,
1614
- lazy: Boolean(current.lazy),
1615
- activated: current.activated,
1616
- disabledBy: current.enabled ? void 0 : current.disabledBy ?? "user",
1617
- loadError: current.loadError?.message,
1618
- activationEvents: plugin.activationEvents ?? [ON_STARTUP],
1619
- deactivationEvents: plugin.deactivationEvents ?? [],
1620
- contributionPoints: (plugin.contributionPoints ?? []).map((point) => point.id),
1621
- // Only what is declared up-front, and only once the module is here: an
1622
- // imperative `ctx.contribute` is not knowable before it runs, and the
1623
- // graph reads those from the registry instead.
1624
- contributesTo: [
1625
- ...new Set((plugin.contributes ?? []).map((record2) => record2.point.id))
1626
- ]
1627
- };
1628
- },
1629
- isEnabled(name) {
1630
- return state.get(name)?.enabled ?? false;
1631
- },
1632
- getContributions(point) {
1633
- return readContributions(point);
1634
- },
1635
- checkGate(gate, context) {
1636
- return resolveGate(readContributions(gate), context);
1637
- }
1638
- };
1639
- function buildPhaseContext(name, current) {
1640
- return {
1641
- plugin: current.plugin,
1642
- config: current.config,
1643
- state: {
1644
- getConfig: () => current.config,
1645
- getInit: () => current.initValue,
1646
- getOutput: () => current.outputValue
1647
- },
1648
- reactor: reactorView,
1649
- contribute(point, value, options2) {
1650
- const dispose = contributions.add(name, point, value, options2);
1651
- emitChange();
1652
- let disposed = false;
1653
- return () => {
1654
- if (disposed) {
1655
- return;
1656
- }
1657
- disposed = true;
1658
- dispose();
1659
- emitChange();
1660
- };
1661
- },
1662
- registerCommand(command) {
1663
- const dispose = commands.add(name, command);
1664
- emitChange();
1665
- let disposed = false;
1666
- return () => {
1667
- if (disposed) {
1668
- return;
1669
- }
1670
- disposed = true;
1671
- dispose();
1672
- emitChange();
1673
- };
1674
- }
1675
- };
1676
- }
1677
- function runInitAndBuild(name) {
1678
- const current = state.get(name);
1679
- if (!current) {
1680
- throw new Error(`Unknown plugin ${name}`);
1681
- }
1682
- if (!current.loaded) {
1683
- return;
1684
- }
1685
- const ctx = buildPhaseContext(name, current);
1686
- current.initValue = current.plugin.init?.(ctx);
1687
- current.outputValue = current.plugin.build?.(ctx);
1688
- }
1689
- function runRegister(name) {
1690
- const current = state.get(name);
1691
- if (!current || !current.enabled || !current.loaded) {
1692
- return;
1693
- }
1694
- const ctx = buildPhaseContext(name, current);
1695
- for (const record2 of current.plugin.contributes ?? []) {
1696
- contributions.add(name, record2.point, record2.value, record2.options);
1697
- }
1698
- for (const command of current.plugin.commands ?? []) {
1699
- commands.add(name, command);
1700
- }
1701
- emitChange();
1702
- current.registerDispose = current.plugin.register?.(ctx) ?? void 0;
1703
- current.afterDispose = current.plugin.afterRegistration?.(ctx) ?? void 0;
1704
- }
1705
- function activateLoaded(name) {
1706
- const current = state.get(name);
1707
- if (!current || current.activated || !current.loaded) {
1708
- return;
1709
- }
1710
- current.activated = true;
1711
- asOneChange(() => {
1712
- if (current.enabled) {
1713
- const keepsWhatItBuilt = current.plugin.preserveOutput && current.outputValue !== void 0;
1714
- if (!keepsWhatItBuilt) {
1715
- runInitAndBuild(name);
1716
- }
1717
- runRegister(name);
1718
- }
1719
- });
1720
- }
1721
- async function loadModule(name) {
1722
- const current = state.get(name);
1723
- if (!current?.lazy || current.loaded) {
1724
- return;
1725
- }
1726
- current.loading ??= Promise.resolve().then(() => current.lazy.load());
1727
- try {
1728
- const module = await current.loading;
1729
- if (current.loaded) {
1730
- return;
1731
- }
1732
- const loaded = module.default ?? module;
1733
- if (!loaded || typeof loaded !== "object" || !loaded.name) {
1734
- throw new Error(`Lazy plugin ${name} did not resolve to a plugin`);
1735
- }
1736
- current.plugin = mergeLoaded(current.lazy, loaded);
1737
- current.config = mergeWithDefaults(current.plugin, configOverrides.get(name) ?? {});
1738
- current.loaded = true;
1739
- } catch (error) {
1740
- current.loadError = error instanceof Error ? error : new Error(String(error));
1741
- emitChange();
1742
- }
1743
- }
1744
- function ensureActivated(name) {
1745
- const current = state.get(name);
1746
- if (!current || current.activated) {
1747
- return Promise.resolve();
1748
- }
1749
- const inFlight = activating.get(name);
1750
- if (inFlight) {
1751
- return inFlight;
1752
- }
1753
- const run = (async () => {
1754
- for (const dep of current.plugin.dependencies ?? []) {
1755
- await ensureActivated(asConfigured(dep).plugin.name);
1756
- }
1757
- if (current.lazy && !current.loaded) {
1758
- await loadModule(name);
1759
- }
1760
- activateLoaded(name);
1761
- standingDownForBackend.delete(name);
1762
- })().finally(() => {
1763
- activating.delete(name);
1764
- });
1765
- activating.set(name, run);
1766
- return run;
1767
- }
1768
- async function activateFor(event) {
1769
- const waiting = waitingFor(event);
1770
- if (waiting.length === 0) {
1771
- return [];
1772
- }
1773
- for (const name of waiting) {
1774
- const current = state.get(name);
1775
- if (current?.lazy && !current.loaded) {
1776
- current.loading ??= Promise.resolve().then(() => current.lazy.load());
1777
- }
1778
- }
1779
- for (const name of waiting) {
1780
- await ensureActivated(name);
1781
- }
1782
- return waiting.filter((name) => state.get(name)?.activated);
1783
- }
1784
- function dependantsOf(name) {
1785
- const wanted = /* @__PURE__ */ new Set([name]);
1786
- for (const plugin of orderedPlugins) {
1787
- const dependsOnWanted = (plugin.dependencies ?? []).some((dep) => wanted.has(asConfigured(dep).plugin.name));
1788
- if (dependsOnWanted) {
1789
- wanted.add(plugin.name);
1790
- }
1791
- }
1792
- wanted.delete(name);
1793
- return orderedPlugins.map((plugin) => plugin.name).filter((candidate) => wanted.has(candidate)).reverse();
1794
- }
1795
- function dependenciesEnabled(name) {
1796
- const plugin = state.get(name)?.plugin;
1797
- return (plugin?.dependencies ?? []).every((dep) => state.get(asConfigured(dep).plugin.name)?.enabled ?? true);
1798
- }
1799
- function enableOne(name) {
1800
- const current = state.get(name);
1801
- if (!current || current.enabled) {
1802
- return;
1803
- }
1804
- current.enabled = true;
1805
- current.disabledBy = void 0;
1806
- if (!current.loaded || !current.activated) {
1807
- return;
1808
- }
1809
- const keepsWhatItBuilt = current.plugin.preserveOutput && current.outputValue !== void 0;
1810
- if (!keepsWhatItBuilt) {
1811
- runInitAndBuild(name);
1812
- }
1813
- runRegister(name);
1814
- }
1815
- function deactivatePlugin(name, cause = "other") {
1816
- const current = state.get(name);
1817
- if (!current) {
1818
- throw new Error(`Unknown plugin ${name}`);
1819
- }
1820
- if (cause === "other") {
1821
- standingDownForBackend.delete(name);
1822
- }
1823
- if (!current.activated) {
1824
- return [];
1825
- }
1826
- const stoodDown = [];
1827
- asOneChange(() => {
1828
- for (const dependant of dependantsOf(name)) {
1829
- const dependantState = state.get(dependant);
1830
- if (!dependantState?.activated) {
1831
- continue;
1832
- }
1833
- stopPlugin(dependant);
1834
- dependantState.activated = false;
1835
- forgetPointsAwaiting(dependant);
1836
- stoodDown.push(dependant);
1837
- }
1838
- stopPlugin(name);
1839
- current.activated = false;
1840
- forgetPointsAwaiting(name);
1841
- stoodDown.push(name);
1842
- });
1843
- if (cause === "other") {
1844
- for (const stoodDownName of stoodDown) {
1845
- standingDownForBackend.delete(stoodDownName);
1846
- }
1847
- }
1848
- return stoodDown;
1849
- }
1850
- function forgetPointsAwaiting(name) {
1851
- const events = state.get(name)?.plugin.activationEvents ?? [];
1852
- for (const event of events) {
1853
- if (event.startsWith("onContributionPoint:")) {
1854
- firedPoints.delete(event.slice("onContributionPoint:".length));
1855
- }
1856
- }
1857
- }
1858
- function deactivateFor(event) {
1859
- const stoodDown = [];
1860
- for (const plugin of orderedPlugins) {
1861
- const current = state.get(plugin.name);
1862
- if (!current?.activated) {
1863
- continue;
1864
- }
1865
- if (matchesDeactivation(current.plugin.deactivationEvents, event)) {
1866
- stoodDown.push(...deactivatePlugin(plugin.name));
1867
- }
1868
- }
1869
- return stoodDown;
1870
- }
1871
- function stopPlugin(name) {
1872
- const current = state.get(name);
1873
- if (!current) {
1874
- return;
1875
- }
1876
- current.afterDispose?.();
1877
- current.afterDispose = void 0;
1878
- current.registerDispose?.();
1879
- current.registerDispose = void 0;
1880
- contributions.disposePlugin(name);
1881
- commands.disposePlugin(name);
1882
- }
1883
- return {
1884
- ...reactorView,
1885
- start() {
1886
- started = true;
1887
- asOneChange(() => {
1888
- const due = orderedPlugins.filter((plugin) => {
1889
- const current = state.get(plugin.name);
1890
- return current && current.loaded && !current.activated && activatesAtStartup(current.plugin.activationEvents);
1891
- });
1892
- for (const plugin of due) {
1893
- state.get(plugin.name).activated = true;
1894
- runInitAndBuild(plugin.name);
1895
- }
1896
- for (const plugin of due) {
1897
- runRegister(plugin.name);
1898
- }
1899
- });
1900
- readyPromise = activateFor(ON_STARTUP).then(() => void 0);
1901
- },
1902
- whenReady() {
1903
- return readyPromise ?? Promise.resolve();
1904
- },
1905
- async fire(event) {
1906
- const deactivated = deactivateFor(event);
1907
- const activated = await activateFor(event);
1908
- return { deactivated, activated };
1909
- },
1910
- deactivate(name) {
1911
- deactivatePlugin(name);
1912
- },
1913
- async setBackendPlugins(available) {
1914
- availableBackendPlugins = new Set(available);
1915
- const satisfied = (name) => (state.get(name)?.plugin.requiredBackendPlugins ?? []).every((backend) => availableBackendPlugins.has(backend));
1916
- const deactivated = [];
1917
- for (const plugin of orderedPlugins) {
1918
- const current = state.get(plugin.name);
1919
- if (!current?.activated || satisfied(plugin.name)) {
1920
- continue;
1921
- }
1922
- const stoodDown = deactivatePlugin(plugin.name, "backend");
1923
- for (const name of stoodDown) {
1924
- standingDownForBackend.add(name);
1925
- }
1926
- deactivated.push(...stoodDown);
1927
- }
1928
- const activated = [];
1929
- for (const plugin of orderedPlugins) {
1930
- const name = plugin.name;
1931
- if (!standingDownForBackend.has(name) || !satisfied(name)) {
1932
- continue;
1933
- }
1934
- const current = state.get(name);
1935
- if (!current?.enabled) {
1936
- continue;
1937
- }
1938
- standingDownForBackend.delete(name);
1939
- await ensureActivated(name);
1940
- if (state.get(name)?.activated) {
1941
- activated.push(name);
1942
- }
1943
- }
1944
- return { deactivated, activated };
1945
- },
1946
- async install(input) {
1947
- const incoming = normalizePlugins([input]);
1948
- const fresh = incoming.plugins.filter((plugin) => !state.has(plugin.name));
1949
- if (fresh.length === 0) {
1950
- return [];
1951
- }
1952
- for (const plugin of fresh) {
1953
- for (const conflict of plugin.conflictsWith ?? []) {
1954
- if (byName.has(conflict) || fresh.some((one) => one.name === conflict)) {
1955
- throw new Error(`Plugin ${plugin.name} conflicts with ${conflict}`);
1956
- }
1957
- }
1958
- }
1959
- for (const [name, ref] of incoming.lazyByName) {
1960
- lazyByName.set(name, ref);
1961
- }
1962
- for (const [name, from] of incoming.extensionOf) {
1963
- extensionOf.set(name, from);
1964
- }
1965
- for (const [name, extension] of incoming.extensions) {
1966
- extensions2.set(name, extension);
1967
- }
1968
- const overrides = collectOverrides([input]);
1969
- for (const plugin of fresh) {
1970
- byName.set(plugin.name, plugin);
1971
- state.set(plugin.name, {
1972
- plugin,
1973
- config: mergeWithDefaults(plugin, overrides.get(plugin.name) ?? {}),
1974
- enabled: true,
1975
- activated: false,
1976
- extension: extensionOf.get(plugin.name),
1977
- lazy: lazyByName.get(plugin.name),
1978
- loaded: !lazyByName.has(plugin.name)
1979
- });
1980
- }
1981
- const reordered = topoSort([...orderedPlugins, ...fresh]);
1982
- orderedPlugins.splice(0, orderedPlugins.length, ...reordered);
1983
- emitChange();
1984
- if (!started) {
1985
- return fresh.map((plugin) => plugin.name);
1986
- }
1987
- const installed = [];
1988
- for (const plugin of reordered) {
1989
- if (!fresh.some((one) => one.name === plugin.name)) {
1990
- continue;
1991
- }
1992
- installed.push(plugin.name);
1993
- if (activatesAtStartup(plugin.activationEvents)) {
1994
- await ensureActivated(plugin.name);
1995
- }
1996
- }
1997
- return installed;
1998
- },
1999
- stop() {
2000
- started = false;
2001
- asOneChange(() => {
2002
- for (const plugin of [...orderedPlugins].reverse()) {
2003
- stopPlugin(plugin.name);
2004
- const current = state.get(plugin.name);
2005
- if (current) {
2006
- current.activated = false;
2007
- }
2008
- }
2009
- firedPoints.clear();
2010
- });
2011
- },
2012
- enable(name) {
2013
- const current = state.get(name);
2014
- if (!current) {
2015
- throw new Error(`Unknown plugin ${name}`);
2016
- }
2017
- if (current.enabled) {
2018
- return;
2019
- }
2020
- asOneChange(() => {
2021
- enableOne(name);
2022
- for (const dependant of [...dependantsOf(name)].reverse()) {
2023
- const dependantState = state.get(dependant);
2024
- if (!dependantState || dependantState.enabled) {
2025
- continue;
2026
- }
2027
- if (dependantState.disabledBy !== "dependency") {
2028
- continue;
2029
- }
2030
- if (!dependenciesEnabled(dependant)) {
2031
- continue;
2032
- }
2033
- enableOne(dependant);
2034
- }
2035
- });
2036
- },
2037
- disable(name) {
2038
- const current = state.get(name);
2039
- if (!current) {
2040
- throw new Error(`Unknown plugin ${name}`);
2041
- }
2042
- if (!current.enabled) {
2043
- return;
2044
- }
2045
- asOneChange(() => {
2046
- for (const dependant of dependantsOf(name)) {
2047
- const dependantState = state.get(dependant);
2048
- if (!dependantState?.enabled) {
2049
- continue;
2050
- }
2051
- dependantState.enabled = false;
2052
- dependantState.disabledBy = "dependency";
2053
- stopPlugin(dependant);
2054
- }
2055
- current.enabled = false;
2056
- current.disabledBy = "user";
2057
- stopPlugin(name);
2058
- });
2059
- },
2060
- subscribe(listener) {
2061
- listeners.add(listener);
2062
- return () => {
2063
- listeners.delete(listener);
2064
- };
2065
- },
2066
- listPlugins() {
2067
- return orderedPlugins.map((plugin) => plugin.name);
2068
- },
2069
- listExtensions() {
2070
- return [...extensions2.keys()];
2071
- },
2072
- getExtensionManifest(name) {
2073
- const extension = extensions2.get(name);
2074
- if (!extension) {
2075
- return void 0;
2076
- }
2077
- return {
2078
- name: extension.name,
2079
- version: extension.version,
2080
- displayName: extension.displayName ?? extension.name,
2081
- description: extension.description,
2082
- octicon: extension.octicon,
2083
- emoji: extension.emoji,
2084
- // Read back from what was actually registered, not from the
2085
- // declaration: a plugin that appeared twice is listed once.
2086
- plugins: orderedPlugins.filter((plugin) => extensionOf.get(plugin.name) === name).map((plugin) => plugin.name)
2087
- };
2088
- },
2089
- getConfig(name) {
2090
- return state.get(name)?.config;
2091
- },
2092
- describeContributions() {
2093
- return contributions.describe();
2094
- },
2095
- listCommands() {
2096
- return commands.list();
2097
- },
2098
- getCommand(id) {
2099
- return commands.get(id);
2100
- },
2101
- executeCommand(id, argument) {
2102
- return commands.execute(id, argument);
2103
- },
2104
- getDependencies(name) {
2105
- return (state.get(name)?.plugin.dependencies ?? []).map((dep) => asConfigured(dep).plugin.name);
2106
- },
2107
- getRevision() {
2108
- return revision;
2109
- }
2110
- };
2111
- }
2112
-
2113
- // ../../node_modules/@datalayer/reactor/lib/core/plugin.js
2114
- function definePlugin(plugin) {
2115
- return plugin;
2116
- }
2117
- function isLazyPluginRef(ref) {
2118
- return typeof ref === "object" && ref !== null && typeof ref.load === "function" && typeof ref.name === "string" && !("plugin" in ref);
2119
- }
2120
- function asConfigured(ref) {
2121
- if ("plugin" in ref) {
2122
- return ref;
2123
- }
2124
- return { plugin: ref, config: {} };
2125
- }
2126
- function mergeWithDefaults(plugin, override) {
2127
- const defaults = plugin.config ?? {};
2128
- if (plugin.mergeConfig) {
2129
- return plugin.mergeConfig(defaults, override);
2130
- }
2131
- return shallowMergeConfig(defaults, override);
2132
- }
2133
-
2134
- // ../../node_modules/@datalayer/reactor/lib/core/origins.js
2135
- var ANY_ORIGIN = "*";
2136
- var OriginNotAllowedError = class extends Error {
2137
- /** The URL that was refused, as it was written. */
2138
- url;
2139
- /** The origin it resolved to — which is the thing being refused. */
2140
- origin;
2141
- constructor(url, origin, what = "a remote") {
2142
- super(`Refusing to load ${what} from ${origin}: not an allowed origin. Pass allowedOrigins, or call setAllowedOrigins() from the host, to accept it.`);
2143
- this.name = "OriginNotAllowedError";
2144
- this.url = url;
2145
- this.origin = origin;
2146
- }
2147
- };
2148
- var LEFTMOST_WILDCARD = /^[a-z][a-z0-9+.-]*:\/\/\*\./i;
2149
- function parseOriginRule(pattern) {
2150
- const written = pattern.trim();
2151
- if (written === ANY_ORIGIN) {
2152
- return { kind: "any" };
2153
- }
2154
- try {
2155
- if (LEFTMOST_WILDCARD.test(written)) {
2156
- const url = new URL(written.replace("*.", ""));
2157
- return {
2158
- kind: "suffix",
2159
- protocol: url.protocol,
2160
- suffix: `.${url.hostname}`,
2161
- port: url.port
2162
- };
2163
- }
2164
- return { kind: "exact", origin: new URL(written).origin };
2165
- } catch {
2166
- console.warn(`[reactor] ignoring an unreadable allowed origin: ${JSON.stringify(pattern)}. Write it with a scheme, e.g. https://cdn.example.com or https://*.example.com.`);
2167
- return void 0;
2168
- }
2169
- }
2170
- function matches(rule, origin) {
2171
- if (rule.kind === "any") {
2172
- return true;
2173
- }
2174
- if (rule.kind === "exact") {
2175
- return rule.origin === origin;
2176
- }
2177
- let url;
2178
- try {
2179
- url = new URL(origin);
2180
- } catch {
2181
- return false;
2182
- }
2183
- return url.protocol === rule.protocol && url.port === rule.port && url.hostname.endsWith(rule.suffix);
2184
- }
2185
- var policy = [];
2186
- function resolveOrigin(url) {
2187
- const base = typeof location !== "undefined" && location?.href ? location.href : void 0;
2188
- if (base) {
2189
- return new URL(url, base).origin;
2190
- }
2191
- return /^[a-z]+:\/\//i.test(url) ? new URL(url).origin : void 0;
2192
- }
2193
- function pageOrigin() {
2194
- const href = typeof location !== "undefined" && location?.href ? location.href : void 0;
2195
- return href ? new URL(href).origin : void 0;
2196
- }
2197
- function isOriginAllowed(url, extra = []) {
2198
- let origin;
2199
- try {
2200
- origin = resolveOrigin(url);
2201
- } catch {
2202
- return false;
2203
- }
2204
- if (origin === void 0 || origin === pageOrigin()) {
2205
- return true;
2206
- }
2207
- if (origin === "null") {
2208
- return false;
2209
- }
2210
- for (const pattern of [...policy, ...extra]) {
2211
- const rule = parseOriginRule(pattern);
2212
- if (rule && matches(rule, origin)) {
2213
- return true;
2214
- }
2215
- }
2216
- return false;
2217
- }
2218
- function assertOriginAllowed(url, extra = [], what = "a remote") {
2219
- if (isOriginAllowed(url, extra)) {
2220
- return;
2221
- }
2222
- let origin;
2223
- try {
2224
- origin = resolveOrigin(url) ?? url;
2225
- } catch {
2226
- throw new OriginNotAllowedError(url, url, what);
2227
- }
2228
- throw new OriginNotAllowedError(url, origin, what);
2229
- }
2230
-
2231
- // ../../node_modules/@datalayer/reactor/lib/core/federation.js
2232
- var runtimeOverride;
2233
- var runtimeLoad;
2234
- async function federationRuntime() {
2235
- if (runtimeOverride) {
2236
- return runtimeOverride;
2237
- }
2238
- if (!runtimeLoad) {
2239
- const specifier = "@module-federation/runtime";
2240
- runtimeLoad = import(
2241
- /* @vite-ignore */
2242
- /* webpackIgnore: true */
2243
- specifier
2244
- ).then((module) => module.default ?? module).catch((error) => {
2245
- runtimeLoad = void 0;
2246
- throw new Error(`Loading a Module Federation container needs @module-federation/runtime, which is an optional peer dependency of @datalayer/reactor. Install it, or pass a loader of your own. (${String(error)})`);
2247
- });
2248
- }
2249
- return runtimeLoad;
2250
- }
2251
- var HOST_NAME = "datalayer_reactor_host";
2252
- function sharedFromHost(versions = {}, overrides = {}) {
2253
- const published = getReactorSharedModules();
2254
- const shared = {};
2255
- for (const [name, value] of Object.entries(published)) {
2256
- const { shareConfig, ...override } = overrides[name] ?? {};
2257
- shared[name] = {
2258
- lib: () => value,
2259
- version: versions[name],
2260
- ...override,
2261
- shareConfig: { singleton: true, requiredVersion: false, ...shareConfig }
2262
- };
2263
- }
2264
- return shared;
2265
- }
2266
- var initialised;
2267
- async function initReactorFederation(options = {}) {
2268
- if (initialised) {
2269
- return initialised;
2270
- }
2271
- const pending = (async () => {
2272
- const runtime = await federationRuntime();
2273
- runtime.init({
2274
- name: options.name ?? HOST_NAME,
2275
- remotes: options.remotes ?? [],
2276
- shared: options.shared ?? sharedFromHost(options.versions)
2277
- });
2278
- return runtime;
2279
- })();
2280
- initialised = pending;
2281
- pending.catch(() => {
2282
- if (initialised === pending) {
2283
- initialised = void 0;
2284
- }
2285
- });
2286
- return pending;
2287
- }
2288
- async function registerFederatedRemote(remote, options = {}) {
2289
- assertOriginAllowed(remote.entry, options.allowedOrigins, `the container ${remote.name}`);
2290
- const runtime = await initReactorFederation();
2291
- runtime.registerRemotes([remote], { force: options.force ?? false });
2292
- }
2293
- function createFederationLoader() {
2294
- return async (entry, ref) => {
2295
- const scope = ref?.scope;
2296
- if (!scope) {
2297
- throw new Error(`${ref?.name ?? entry}: the federation loader needs a container name \u2014 pass \`scope\` on the remote reference.`);
2298
- }
2299
- await registerFederatedRemote({ name: scope, entry, type: ref?.type }, { allowedOrigins: ref?.allowedOrigins });
2300
- const runtime = await initReactorFederation();
2301
- const id = `${scope}/${(ref?.module ?? "./plugin").replace(/^\.\//, "")}`;
2302
- const module = await runtime.loadRemote(id);
2303
- if (!module) {
2304
- throw new Error(`${ref?.name ?? scope}: the container at ${entry} exposes no ${id}.`);
2305
- }
2306
- return module;
2307
- };
2308
- }
2309
- var federationLoader = createFederationLoader();
2310
-
2311
- // ../../node_modules/@datalayer/reactor/lib/core/remote.js
2312
- var SHARED_GLOBAL = "__DATALAYER_REACTOR__";
2313
- function getReactorSharedModules() {
2314
- const target = globalThis;
2315
- return target[SHARED_GLOBAL]?.shared ?? {};
2316
- }
2317
-
2318
- // ../../node_modules/@datalayer/reactor/lib/core/agentTools.js
2319
- var AgentTools = defineContributionPoint("reactor.agentTools");
2320
-
2321
- // src/reactor.ts
2322
- var DiscoveryTransports = defineContributionPoint(
2323
- "pap.discoveryTransport"
2324
- );
2325
- var UrlSafetyPolicies = defineContributionPoint(
2326
- "pap.urlSafetyPolicy"
2327
- );
2328
- var ProtocolProfiles = defineContributionPoint(
2329
- "pap.protocolProfile"
2330
- );
2331
- var ExtensionHandlers = defineContributionPoint(
2332
- "pap.extensionHandler"
2333
- );
2334
- var Clocks = defineContributionPoint("pap.clock");
2335
- var RandomSources = defineContributionPoint("pap.randomSource");
2336
- var Signers = defineContributionPoint("pap.signer");
2337
- var KeyStores = defineContributionPoint("pap.keyStore");
2338
- var TokenStores = defineContributionPoint("pap.tokenStore");
2339
- var Caches = defineContributionPoint("pap.cache");
2340
- var BrowserHandoffs = defineContributionPoint(
2341
- "pap.browserHandoff"
2342
- );
2343
- var DpopProofProviders = defineContributionPoint(
2344
- "pap.dpopProofProvider"
2345
- );
2346
- var systemClock = { now: () => /* @__PURE__ */ new Date() };
2347
- var systemRandom = {
2348
- bytes(length) {
2349
- if (!Number.isInteger(length) || length <= 0) {
2350
- throw new RangeError("Random byte length must be a positive integer");
2351
- }
2352
- if (!globalThis.crypto) {
2353
- throw new Error("A cryptographically secure random source is required");
2354
- }
2355
- return globalThis.crypto.getRandomValues(new Uint8Array(length));
2356
- }
2357
- };
2358
- function assertObviouslyPublic(url) {
2359
- if (url.protocol !== "https:" || url.username || url.password) {
2360
- throw new DiscoveryError("unsafe_url", "Discovery and metadata URLs must use HTTPS");
2361
- }
2362
- const host = url.hostname.toLowerCase().replace(/[\[\]]/g, "");
2363
- if (host === "localhost" || host.endsWith(".localhost") || host === "::1" || /^127\./.test(host) || /^10\./.test(host) || /^192\.168\./.test(host) || /^169\.254\./.test(host) || /^172\.(1[6-9]|2[0-9]|3[01])\./.test(host)) {
2364
- throw new DiscoveryError("unsafe_address", "Discovery URL names a private address");
2365
- }
2366
- }
2367
- function createPapCorePlugin(options = {}) {
2368
- const fetcher = options.fetch ?? globalThis.fetch;
2369
- if (!fetcher) {
2370
- throw new DiscoveryError("fetch_unavailable", "A fetch implementation is required");
2371
- }
2372
- return definePlugin({
2373
- name: "@datalayer/personal-agent-protocol-core",
2374
- version: "0.3.0",
2375
- contributionPoints: [
2376
- DiscoveryTransports,
2377
- UrlSafetyPolicies,
2378
- ProtocolProfiles,
2379
- ExtensionHandlers,
2380
- Clocks,
2381
- RandomSources,
2382
- Signers,
2383
- KeyStores,
2384
- TokenStores,
2385
- Caches,
2386
- BrowserHandoffs,
2387
- DpopProofProviders
2388
- ],
2389
- contributes: [
2390
- contribution(
2391
- DiscoveryTransports,
2392
- { fetch: (input, init) => fetcher(input, init) },
2393
- { id: "fetch", order: 100 }
2394
- ),
2395
- contribution(
2396
- UrlSafetyPolicies,
2397
- {
2398
- async assertSafe(url) {
2399
- assertObviouslyPublic(url);
2400
- await options.assertSafeUrl?.(url);
2401
- }
2402
- },
2403
- { id: "public", order: 100 }
2404
- ),
2405
- contribution(ProtocolProfiles, { version: "0.1" }, { id: "0.1", order: 100 }),
2406
- contribution(Clocks, systemClock, { id: "system", order: 100 }),
2407
- contribution(RandomSources, systemRandom, { id: "system", order: 100 })
2408
- ]
2409
- });
2410
- }
2411
- function buildPapReactor(options = {}, plugins = []) {
2412
- const reactor = buildReactorFromPlugins([createPapCorePlugin(options), ...plugins]);
2413
- reactor.start();
2414
- return reactor;
2415
- }
2416
- function firstContribution(reactor, point, label) {
2417
- const contributions = reactor.getContributions(point);
2418
- const selected = contributions[0];
2419
- if (!selected) {
2420
- throw new Error(`PAP Reactor has no active ${label} contribution`);
2421
- }
2422
- if (contributions[1]?.order === selected.order) {
2423
- throw new Error(`PAP Reactor has ambiguous ${label} contributions`);
2424
- }
2425
- return selected.value;
2426
- }
2427
-
2428
- // src/sessions.ts
2429
- var JWT_BEARER_GRANT = "urn:ietf:params:oauth:grant-type:jwt-bearer";
2430
- var JWT_CLIENT_ASSERTION = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer";
2431
- var SecretValue = class {
2432
- #value;
2433
- constructor(value) {
2434
- if (!value) {
2435
- throw new ProtocolValidationError("invalid_secret", "Secret value must not be empty");
2436
- }
2437
- this.#value = value;
2438
- }
2439
- reveal() {
2440
- return this.#value;
2441
- }
2442
- toString() {
2443
- return "[REDACTED]";
2444
- }
2445
- toJSON() {
2446
- return "[REDACTED]";
2447
- }
2448
- };
2449
- function defaultRandomBytes(length) {
2450
- const cryptoApi = globalThis.crypto;
2451
- if (!cryptoApi) {
2452
- throw new Error("A cryptographically secure random source is required");
2453
- }
2454
- return cryptoApi.getRandomValues(new Uint8Array(length));
2455
- }
2456
- function base64Url(bytes) {
2457
- const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
2458
- let output = "";
2459
- for (let index = 0; index < bytes.length; index += 3) {
2460
- const first = bytes[index] ?? 0;
2461
- const second = bytes[index + 1];
2462
- const third = bytes[index + 2];
2463
- output += alphabet[first >>> 2];
2464
- output += alphabet[(first & 3) << 4 | (second ?? 0) >>> 4];
2465
- if (second !== void 0) {
2466
- output += alphabet[(second & 15) << 2 | (third ?? 0) >>> 6];
2467
- }
2468
- if (third !== void 0) {
2469
- output += alphabet[third & 63];
2470
- }
2471
- }
2472
- return output;
2473
- }
2474
- function opaqueId(prefix, randomBytes2) {
2475
- const bytes = randomBytes2(16);
2476
- if (bytes.byteLength < 16) {
2477
- throw new Error("Opaque PAP identifiers require at least 128 random bits");
2478
- }
2479
- return `${prefix}_${base64Url(bytes)}`;
2480
- }
2481
- function generatePairwiseUserId(randomBytes2 = defaultRandomBytes) {
2482
- return opaqueId("usr", randomBytes2);
2483
- }
2484
- function httpsUrl(value, label) {
2485
- let parsed;
2486
- try {
2487
- parsed = new URL(value);
2488
- } catch (cause) {
2489
- throw new ProtocolValidationError("invalid_url", `${label} must be an HTTPS URL`, {
2490
- cause
2491
- });
2492
- }
2493
- if (parsed.protocol !== "https:" || parsed.username || parsed.password) {
2494
- throw new ProtocolValidationError("invalid_url", `${label} must be an HTTPS URL`);
2495
- }
2496
- return value;
2497
- }
2498
- function buildSessionAssertionClaims(options) {
2499
- const lifetime = options.lifetimeSeconds ?? 60;
2500
- if (!Number.isInteger(lifetime) || lifetime <= 0) {
2501
- throw new ProtocolValidationError(
2502
- "invalid_assertion_lifetime",
2503
- "Assertion lifetime must be a positive integer"
2504
- );
2505
- }
2506
- if (!/^[A-Za-z0-9_-]{1,256}$/.test(options.pairwiseUserId)) {
2507
- throw new ProtocolValidationError(
2508
- "invalid_user_id",
2509
- "Pairwise user ID must use the URL-safe base64 alphabet"
2510
- );
2511
- }
2512
- const iat = Math.floor((options.now ?? /* @__PURE__ */ new Date()).getTime() / 1e3);
2513
- return {
2514
- iss: httpsUrl(options.clientId, "clientId"),
2515
- sub: options.pairwiseUserId,
2516
- aud: httpsUrl(options.tokenEndpoint, "tokenEndpoint"),
2517
- iat,
2518
- exp: iat + lifetime,
2519
- jti: opaqueId("jti", options.randomBytes ?? defaultRandomBytes)
2520
- };
2521
- }
2522
- var SessionGrant = class {
2523
- assertion;
2524
- clientId;
2525
- clientAssertion;
2526
- sessionId;
2527
- constructor(options) {
2528
- this.assertion = new SecretValue(options.assertion);
2529
- this.clientId = httpsUrl(options.clientId, "clientId");
2530
- this.clientAssertion = new SecretValue(options.clientAssertion);
2531
- if (options.sessionId !== void 0 && !/^[A-Za-z0-9_-]{1,256}$/.test(options.sessionId)) {
2532
- throw new ProtocolValidationError("invalid_session_id", "Invalid PAP session ID");
2533
- }
2534
- this.sessionId = options.sessionId;
2535
- }
2536
- toForm() {
2537
- const form = new URLSearchParams({
2538
- grant_type: JWT_BEARER_GRANT,
2539
- assertion: this.assertion.reveal(),
2540
- client_id: this.clientId,
2541
- client_assertion_type: JWT_CLIENT_ASSERTION,
2542
- client_assertion: this.clientAssertion.reveal()
2543
- });
2544
- if (this.sessionId !== void 0) {
2545
- form.set("session_id", this.sessionId);
2546
- }
2547
- return form;
2548
- }
2549
- toJSON() {
2550
- return {
2551
- grant_type: JWT_BEARER_GRANT,
2552
- assertion: this.assertion,
2553
- client_id: this.clientId,
2554
- client_assertion_type: JWT_CLIENT_ASSERTION,
2555
- client_assertion: this.clientAssertion,
2556
- ...this.sessionId === void 0 ? {} : { session_id: this.sessionId }
2557
- };
2558
- }
2559
- };
2560
- function object(value, label) {
2561
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
2562
- throw new ProtocolValidationError("invalid_type", `${label} must be an object`);
2563
- }
2564
- return value;
2565
- }
2566
- function nonEmptyString(value, label) {
2567
- if (typeof value !== "string" || !value) {
2568
- throw new ProtocolValidationError("invalid_type", `${label} must be a string`);
2569
- }
2570
- return value;
2571
- }
2572
- function parseSessionToken(value) {
2573
- const source = object(value, "session token response");
2574
- const tokenType = nonEmptyString(source.token_type, "token_type");
2575
- if (tokenType !== "DPoP" && tokenType !== "Bearer") {
2576
- throw new ProtocolValidationError("invalid_token_type", "Unsupported token_type");
2577
- }
2578
- const expiresIn = source.expires_in;
2579
- if (!Number.isInteger(expiresIn) || expiresIn <= 0) {
2580
- throw new ProtocolValidationError("invalid_expiry", "expires_in must be positive");
2581
- }
2582
- const sessionId = nonEmptyString(source.session_id, "session_id");
2583
- if (!/^[A-Za-z0-9_-]{1,256}$/.test(sessionId)) {
2584
- throw new ProtocolValidationError("invalid_session_id", "Invalid PAP session ID");
2585
- }
2586
- if (typeof source.signed_in !== "boolean") {
2587
- throw new ProtocolValidationError("invalid_type", "signed_in must be boolean");
2588
- }
2589
- if (source.scope !== void 0 && typeof source.scope !== "string") {
2590
- throw new ProtocolValidationError("invalid_type", "scope must be a string");
2591
- }
2592
- const scope = source.scope ?? "";
2593
- return {
2594
- accessToken: new SecretValue(nonEmptyString(source.access_token, "access_token")),
2595
- tokenType,
2596
- expiresIn,
2597
- scopes: scope.split(" ").filter(Boolean),
2598
- sessionId,
2599
- signedIn: source.signed_in,
2600
- ...source.refresh_token === void 0 ? {} : {
2601
- accountToken: new SecretValue(
2602
- nonEmptyString(source.refresh_token, "refresh_token")
2603
- )
2604
- }
2605
- };
2606
- }
2607
- var SessionClient = class {
2608
- #reactor;
2609
- #fetch;
2610
- #maxResponseBytes;
2611
- constructor(options) {
2612
- const fetcher = options.fetch ?? globalThis.fetch;
2613
- if (!fetcher) throw new SessionError("fetch_unavailable", "A fetch implementation is required");
2614
- const maxResponseBytes = options.maxResponseBytes ?? 100 * 1024;
2615
- if (!Number.isInteger(maxResponseBytes) || maxResponseBytes <= 0) {
2616
- throw new RangeError("maxResponseBytes must be a positive integer");
2617
- }
2618
- this.#reactor = options.reactor;
2619
- this.#fetch = fetcher;
2620
- this.#maxResponseBytes = maxResponseBytes;
2621
- }
2622
- start(options) {
2623
- return this.#request(options);
2624
- }
2625
- renew(options) {
2626
- return this.#request(options, options.sessionId);
2627
- }
2628
- async #request(options, sessionId) {
2629
- const clock = firstContribution(this.#reactor, Clocks, "clock");
2630
- const random = firstContribution(this.#reactor, RandomSources, "random source");
2631
- const signer = firstContribution(this.#reactor, Signers, "signer");
2632
- const dpop = firstContribution(
2633
- this.#reactor,
2634
- DpopProofProviders,
2635
- "DPoP proof provider"
2636
- );
2637
- let nonce;
2638
- for (let attempt = 0; attempt < 2; attempt += 1) {
2639
- const now = clock.now();
2640
- const sessionClaims = buildSessionAssertionClaims({
2641
- clientId: options.clientId,
2642
- pairwiseUserId: options.pairwiseUserId,
2643
- tokenEndpoint: options.tokenEndpoint,
2644
- now,
2645
- randomBytes: (length) => random.bytes(length)
2646
- });
2647
- const iat = Math.floor(now.getTime() / 1e3);
2648
- const clientId = httpsUrl(options.clientId, "clientId");
2649
- const tokenEndpoint = httpsUrl(options.tokenEndpoint, "tokenEndpoint");
2650
- const issuer = httpsUrl(options.issuer, "issuer");
2651
- const clientClaims = {
2652
- iss: clientId,
2653
- sub: clientId,
2654
- aud: tokenEndpoint,
2655
- iat,
2656
- exp: iat + 60,
2657
- jti: opaqueId("jti", (length) => random.bytes(length))
2658
- };
2659
- const assertion = await signer.sign({ ...sessionClaims }, {
2660
- purpose: "session_assertion"
2661
- });
2662
- const clientAssertion = await signer.sign(clientClaims, {
2663
- purpose: "client_assertion"
2664
- });
2665
- const proof = await dpop.create({
2666
- method: "POST",
2667
- url: tokenEndpoint,
2668
- tenantId: options.tenantId,
2669
- subject: options.pairwiseUserId,
2670
- issuer,
2671
- ...nonce === void 0 ? {} : { nonce }
2672
- });
2673
- const grant = new SessionGrant({
2674
- assertion: assertion.reveal(),
2675
- clientId,
2676
- clientAssertion: clientAssertion.reveal(),
2677
- ...sessionId === void 0 ? {} : { sessionId }
2678
- });
2679
- let response;
2680
- try {
2681
- response = await this.#fetch(tokenEndpoint, {
2682
- method: "POST",
2683
- headers: { Accept: "application/json", DPoP: proof.reveal() },
2684
- body: grant.toForm(),
2685
- credentials: "omit",
2686
- redirect: "error",
2687
- ...options.signal === void 0 ? {} : { signal: options.signal }
2688
- });
2689
- } catch (cause) {
2690
- throw new SessionError("request_failed", "Session token request failed", { cause });
2691
- }
2692
- const contentType = response.headers.get("content-type")?.split(";", 1)[0]?.trim();
2693
- if (contentType !== "application/json") {
2694
- throw new SessionError(
2695
- "invalid_content_type",
2696
- "Session token endpoint must return JSON",
2697
- { statusCode: response.status }
2698
- );
2699
- }
2700
- const body = await response.text();
2701
- if (new TextEncoder().encode(body).byteLength > this.#maxResponseBytes) {
2702
- throw new SessionError(
2703
- "response_too_large",
2704
- "Session token response exceeds size limit",
2705
- { statusCode: response.status }
2706
- );
2707
- }
2708
- let payload;
2709
- try {
2710
- payload = parseJsonStrict(body);
2711
- } catch (cause) {
2712
- throw new SessionError("invalid_json", "Session token endpoint returned invalid JSON", {
2713
- statusCode: response.status,
2714
- cause
2715
- });
2716
- }
2717
- if (response.ok) {
2718
- let token;
2719
- try {
2720
- token = parseSessionToken(payload);
2721
- } catch (cause) {
2722
- throw new SessionError(
2723
- "invalid_token_response",
2724
- "Session token response is malformed",
2725
- { statusCode: response.status, cause }
2726
- );
2727
- }
2728
- if (token.tokenType !== "DPoP") {
2729
- throw new SessionError(
2730
- "unexpected_token_type",
2731
- "A proof-bound session request must return a DPoP token",
2732
- { statusCode: response.status }
2733
- );
2734
- }
2735
- return token;
2736
- }
2737
- const source = typeof payload === "object" && payload !== null ? payload : {};
2738
- const remoteCode = "error" in source ? source.error : void 0;
2739
- const code = typeof remoteCode === "string" ? remoteCode : "http_error";
2740
- if (code === "use_dpop_nonce" && attempt === 0) {
2741
- nonce = response.headers.get("dpop-nonce") ?? void 0;
2742
- if (!nonce) {
2743
- throw new SessionError(
2744
- "missing_dpop_nonce",
2745
- "Company requested a DPoP nonce but did not send one",
2746
- { statusCode: response.status }
2747
- );
2748
- }
2749
- continue;
2750
- }
2751
- const retryAfter = response.headers.get("retry-after");
2752
- throw new SessionError(code, "Company refused the session token request", {
2753
- statusCode: response.status,
2754
- ...retryAfter === null ? {} : { details: { retryAfter } }
2755
- });
2756
- }
2757
- throw new SessionError("use_dpop_nonce", "Company rejected the refreshed DPoP proof");
2758
- }
2759
- };
2760
-
2761
- // src/crypto.ts
2762
- var privateJwkMembers = /* @__PURE__ */ new Set(["d", "p", "q", "dp", "dq", "qi", "oth", "k"]);
2763
- function algorithm(value) {
2764
- if (value !== "ES256" && value !== "RS256") {
2765
- throw new TypeError("PAP JOSE algorithms must be ES256 or RS256");
2766
- }
2767
- return value;
2768
- }
2769
- function publicJwk(value, alg) {
2770
- for (const member of privateJwkMembers) {
2771
- if (member in value) {
2772
- throw new TypeError("DPoP public JWK must not contain private key material");
2773
- }
2774
- }
2775
- const expected = alg === "ES256" ? "EC" : "RSA";
2776
- if (value.kty !== expected) throw new TypeError(`${alg} requires a ${expected} public JWK`);
2777
- if (alg === "ES256") {
2778
- if (value.crv !== "P-256" || !value.x || !value.y) {
2779
- throw new TypeError("ES256 requires a complete P-256 public JWK");
2780
- }
2781
- } else if (!value.n || !value.e) {
2782
- throw new TypeError("RS256 requires a complete RSA public JWK");
2783
- }
2784
- return { ...value };
2785
- }
2786
- function normalizedHtu(value) {
2787
- let url;
2788
- try {
2789
- url = new URL(value);
2790
- } catch (cause) {
2791
- throw new ProofError("invalid_htu", "DPoP target must be an HTTPS URL", { cause });
2792
- }
2793
- if (url.protocol !== "https:" || url.username || url.password) {
2794
- throw new ProofError("invalid_htu", "DPoP target must be an HTTPS URL");
2795
- }
2796
- url.search = "";
2797
- url.hash = "";
2798
- return url.href;
2799
- }
2800
- function base64Url2(bytes) {
2801
- let binary = "";
2802
- for (const value of bytes) binary += String.fromCharCode(value);
2803
- return btoa(binary).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/u, "");
2804
- }
2805
- function randomBytes(length) {
2806
- if (!globalThis.crypto) throw new ProofError("crypto_unavailable", "Web Crypto is required");
2807
- return globalThis.crypto.getRandomValues(new Uint8Array(length));
2808
- }
2809
- async function accessTokenHash(token) {
2810
- if (!globalThis.crypto) throw new ProofError("crypto_unavailable", "Web Crypto is required");
2811
- const digest2 = await globalThis.crypto.subtle.digest(
2812
- "SHA-256",
2813
- new TextEncoder().encode(token.reveal())
2814
- );
2815
- return base64Url2(new Uint8Array(digest2));
2816
- }
2817
- var JoseSigner = class {
2818
- #privateKey;
2819
- #algorithm;
2820
- #keyId;
2821
- constructor(options) {
2822
- this.#privateKey = options.privateKey;
2823
- this.#algorithm = algorithm(options.algorithm ?? "ES256");
2824
- this.#keyId = options.keyId;
2825
- }
2826
- async sign(claims, _options) {
2827
- try {
2828
- const token = await new SignJWT(claims).setProtectedHeader({
2829
- alg: this.#algorithm,
2830
- typ: "JWT",
2831
- ...this.#keyId === void 0 ? {} : { kid: this.#keyId }
2832
- }).sign(this.#privateKey);
2833
- return new SecretValue(token);
2834
- } catch (cause) {
2835
- throw new ProofError("signing_failed", "Could not sign PAP assertion", { cause });
2836
- }
2837
- }
2838
- };
2839
- var JoseDpopProofProvider = class {
2840
- #resolveKey;
2841
- #now;
2842
- #randomBytes;
2843
- constructor(options) {
2844
- this.#resolveKey = options.resolveKey;
2845
- this.#now = options.now ?? (() => /* @__PURE__ */ new Date());
2846
- this.#randomBytes = options.randomBytes ?? randomBytes;
2847
- }
2848
- async create(request) {
2849
- const material = await this.#resolveKey(request);
2850
- const alg = algorithm(material.algorithm ?? "ES256");
2851
- const jwk = publicJwk(material.publicJwk, alg);
2852
- const entropy2 = this.#randomBytes(16);
2853
- if (entropy2.byteLength < 16) {
2854
- throw new ProofError("weak_randomness", "DPoP proof IDs require 128 random bits");
2855
- }
2856
- const claims = {
2857
- jti: base64Url2(entropy2),
2858
- htm: request.method.toUpperCase(),
2859
- htu: normalizedHtu(request.url),
2860
- iat: Math.floor(this.#now().getTime() / 1e3),
2861
- ...request.nonce === void 0 ? {} : { nonce: request.nonce },
2862
- ...request.accessToken === void 0 ? {} : { ath: await accessTokenHash(request.accessToken) }
2863
- };
2864
- try {
2865
- const token = await new SignJWT(claims).setProtectedHeader({ typ: "dpop+jwt", alg, jwk }).sign(material.privateKey);
2866
- return new SecretValue(token);
2867
- } catch (cause) {
2868
- throw new ProofError("signing_failed", "Could not sign DPoP proof", { cause });
2869
- }
2870
- }
2871
- };
2872
- async function verifyDpopProof(proof, options) {
2873
- const compact = proof instanceof SecretValue ? proof.reveal() : proof;
2874
- const now = options.now ?? /* @__PURE__ */ new Date();
2875
- const windowSeconds = options.acceptanceWindowSeconds ?? 60;
2876
- if (!Number.isInteger(windowSeconds) || windowSeconds <= 0) {
2877
- throw new RangeError("acceptanceWindowSeconds must be a positive integer");
2878
- }
2879
- let jwk;
2880
- let payload;
2881
- try {
2882
- const header = decodeProtectedHeader(compact);
2883
- const alg = algorithm(header.alg ?? "");
2884
- if (header.typ !== "dpop+jwt" || typeof header.jwk !== "object") {
2885
- throw new ProofError("invalid_dpop_proof", "DPoP protected header is invalid");
2886
- }
2887
- jwk = publicJwk(header.jwk, alg);
2888
- const key = await importJWK(jwk, alg);
2889
- ({ payload } = await jwtVerify(compact, key, {
2890
- algorithms: [alg],
2891
- typ: "dpop+jwt",
2892
- requiredClaims: ["jti", "htm", "htu", "iat"]
2893
- }));
2894
- } catch (cause) {
2895
- if (cause instanceof ProofError) throw cause;
2896
- throw new ProofError("invalid_dpop_proof", "DPoP signature or claims are invalid", {
2897
- cause
2898
- });
2899
- }
2900
- if (typeof payload.jti !== "string" || !payload.jti || typeof payload.iat !== "number") {
2901
- throw new ProofError("invalid_dpop_proof", "DPoP proof identity is invalid");
2902
- }
2903
- const issuedAt = new Date(payload.iat * 1e3);
2904
- const difference = Math.abs(now.getTime() - issuedAt.getTime());
2905
- if (difference > windowSeconds * 1e3) {
2906
- throw new ProofError("invalid_dpop_proof", "DPoP proof is outside the acceptance window");
2907
- }
2908
- if (payload.htm !== options.method.toUpperCase() || payload.htu !== normalizedHtu(options.url)) {
2909
- throw new ProofError("invalid_dpop_proof", "DPoP proof does not match the request");
2910
- }
2911
- if (options.nonce !== void 0 && payload.nonce !== options.nonce) {
2912
- throw new ProofError("use_dpop_nonce", "DPoP proof nonce is missing or invalid");
2913
- }
2914
- if (options.accessToken !== void 0) {
2915
- if (payload.ath !== await accessTokenHash(options.accessToken)) {
2916
- throw new ProofError("invalid_dpop_proof", "DPoP access-token hash is invalid");
2917
- }
2918
- } else if (payload.ath !== void 0) {
2919
- throw new ProofError(
2920
- "invalid_dpop_proof",
2921
- "Token-endpoint DPoP proof must not contain ath"
2922
- );
2923
- }
2924
- const keyThumbprint = await calculateJwkThumbprint(jwk);
2925
- if (!await options.replayCache.markOnce(`${keyThumbprint}:${payload.jti}`, {
2926
- expiresAt: new Date(now.getTime() + windowSeconds * 1e3)
2927
- })) {
2928
- throw new ProofError("invalid_dpop_proof", "DPoP proof has already been used");
2929
- }
2930
- return { jti: payload.jti, issuedAt, publicJwk: jwk, keyThumbprint };
2931
- }
2932
-
2933
- // src/auth.ts
2934
- function defaultRandomBytes2(length) {
2935
- if (!globalThis.crypto) {
2936
- throw new AuthorizationError("crypto_unavailable", "Web Crypto is required");
2937
- }
2938
- return globalThis.crypto.getRandomValues(new Uint8Array(length));
2939
- }
2940
- function entropy(length, randomBytes2) {
2941
- const value = randomBytes2(length);
2942
- if (value.byteLength < length) {
2943
- throw new AuthorizationError(
2944
- "weak_entropy",
2945
- `Authorization requires ${length * 8} random bits`
2946
- );
2947
- }
2948
- return value;
2949
- }
2950
- function base64Url3(bytes) {
2951
- const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
2952
- let output = "";
2953
- for (let index = 0; index < bytes.length; index += 3) {
2954
- const first = bytes[index] ?? 0;
2955
- const second = bytes[index + 1];
2956
- const third = bytes[index + 2];
2957
- output += alphabet[first >>> 2];
2958
- output += alphabet[(first & 3) << 4 | (second ?? 0) >>> 4];
2959
- if (second !== void 0) {
2960
- output += alphabet[(second & 15) << 2 | (third ?? 0) >>> 6];
2961
- }
2962
- if (third !== void 0) {
2963
- output += alphabet[third & 63];
2964
- }
2965
- }
2966
- return output;
2967
- }
2968
- function httpsUrl2(value, label) {
2969
- let parsed;
2970
- try {
2971
- parsed = new URL(value);
2972
- } catch (cause) {
2973
- throw new AuthorizationError("invalid_url", `${label} must be an HTTPS URL`, { cause });
2974
- }
2975
- if (parsed.protocol !== "https:" || parsed.username || parsed.password) {
2976
- throw new AuthorizationError("invalid_url", `${label} must be an HTTPS URL`);
2977
- }
2978
- return parsed;
2979
- }
2980
- function validScopes(values) {
2981
- const scopes2 = [...new Set(values)];
2982
- const token = /^[\x21\x23-\x5b\x5d-\x7e]+$/;
2983
- if (scopes2.length === 0 || scopes2.some((scope) => !token.test(scope))) {
2984
- throw new AuthorizationError("invalid_scope", "At least one valid OAuth scope is required");
2985
- }
2986
- return scopes2;
2987
- }
2988
- async function buildDirectSignInRequest(options) {
2989
- const randomBytes2 = options.randomBytes ?? defaultRandomBytes2;
2990
- const state = base64Url3(entropy(16, randomBytes2));
2991
- const verifier = base64Url3(entropy(32, randomBytes2));
2992
- const challenge = base64Url3(
2993
- new Uint8Array(await globalThis.crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier)))
2994
- );
2995
- const endpoint = httpsUrl2(options.authorizationEndpoint, "authorizationEndpoint");
2996
- const scopes2 = validScopes(options.scopes);
2997
- const clientId = httpsUrl2(options.clientId, "clientId").toString();
2998
- const redirectUri = httpsUrl2(options.redirectUri, "redirectUri").toString();
2999
- const issuer = httpsUrl2(options.issuer, "issuer").toString().replace(/\/$/, "");
3000
- endpoint.searchParams.set("response_type", "code");
3001
- endpoint.searchParams.set("client_id", clientId);
3002
- endpoint.searchParams.set("redirect_uri", redirectUri);
3003
- endpoint.searchParams.set("scope", scopes2.join(" "));
3004
- endpoint.searchParams.set("state", state);
3005
- endpoint.searchParams.set("code_challenge", challenge);
3006
- endpoint.searchParams.set("code_challenge_method", "S256");
3007
- endpoint.hash = "";
3008
- return {
3009
- authorizationUrl: new SecretValue(endpoint.toString()),
3010
- issuer,
3011
- clientId,
3012
- redirectUri,
3013
- scopes: scopes2,
3014
- state: new SecretValue(state),
3015
- codeVerifier: new SecretValue(verifier)
3016
- };
3017
- }
3018
- function equalConstantTime(left, right) {
3019
- let difference = left.length ^ right.length;
3020
- const length = Math.max(left.length, right.length);
3021
- for (let index = 0; index < length; index += 1) {
3022
- difference |= (left.charCodeAt(index) || 0) ^ (right.charCodeAt(index) || 0);
3023
- }
3024
- return difference === 0;
3025
- }
3026
- function validateDirectSignInCallback(request, callbackUrl) {
3027
- const expected = httpsUrl2(request.redirectUri, "redirectUri");
3028
- const callback = httpsUrl2(callbackUrl, "callbackUrl");
3029
- if (callback.hash) {
3030
- throw new AuthorizationError("invalid_callback", "Authorization callback has a fragment");
3031
- }
3032
- if (callback.origin !== expected.origin || callback.pathname !== expected.pathname) {
3033
- throw new AuthorizationError("redirect_mismatch", "Callback does not match redirect URI");
3034
- }
3035
- for (const [key, value] of expected.searchParams) {
3036
- if (callback.searchParams.get(key) !== value) {
3037
- throw new AuthorizationError(
3038
- "redirect_mismatch",
3039
- "Callback changed redirect URI parameters"
3040
- );
3041
- }
3042
- }
3043
- for (const key of ["code", "state", "iss", "error"]) {
3044
- if (callback.searchParams.getAll(key).length > 1) {
3045
- throw new AuthorizationError(
3046
- "invalid_callback",
3047
- "Authorization callback repeats a security parameter"
3048
- );
3049
- }
3050
- }
3051
- if (callback.searchParams.has("error")) {
3052
- throw new AuthorizationError("authorization_denied", "Company did not authorize the request");
3053
- }
3054
- if (!equalConstantTime(callback.searchParams.get("state") ?? "", request.state.reveal())) {
3055
- throw new AuthorizationError("state_mismatch", "Authorization state does not match");
3056
- }
3057
- if (callback.searchParams.get("iss") !== request.issuer) {
3058
- throw new AuthorizationError("issuer_mismatch", "Authorization issuer does not match");
3059
- }
3060
- const code = callback.searchParams.get("code");
3061
- if (!code) {
3062
- throw new AuthorizationError("invalid_callback", "Authorization callback has no code");
3063
- }
3064
- return { code: new SecretValue(code), issuer: request.issuer };
3065
- }
3066
- var AuthorizationCodeGrant = class {
3067
- code;
3068
- redirectUri;
3069
- codeVerifier;
3070
- sessionId;
3071
- clientId;
3072
- clientAssertion;
3073
- constructor(options) {
3074
- this.code = new SecretValue(options.code);
3075
- this.redirectUri = httpsUrl2(options.redirectUri, "redirectUri").toString();
3076
- this.codeVerifier = new SecretValue(options.codeVerifier);
3077
- if (!/^[A-Za-z0-9_-]{1,256}$/.test(options.sessionId)) {
3078
- throw new AuthorizationError("invalid_session_id", "Invalid PAP session ID");
3079
- }
3080
- this.sessionId = options.sessionId;
3081
- this.clientId = httpsUrl2(options.clientId, "clientId").toString();
3082
- this.clientAssertion = new SecretValue(options.clientAssertion);
3083
- }
3084
- toForm() {
3085
- return new URLSearchParams({
3086
- grant_type: "authorization_code",
3087
- code: this.code.reveal(),
3088
- redirect_uri: this.redirectUri,
3089
- code_verifier: this.codeVerifier.reveal(),
3090
- session_id: this.sessionId,
3091
- client_id: this.clientId,
3092
- client_assertion_type: JWT_CLIENT_ASSERTION,
3093
- client_assertion: this.clientAssertion.reveal()
3094
- });
3095
- }
3096
- toJSON() {
3097
- return {
3098
- grant_type: "authorization_code",
3099
- code: this.code,
3100
- redirect_uri: this.redirectUri,
3101
- code_verifier: this.codeVerifier,
3102
- session_id: this.sessionId,
3103
- client_id: this.clientId,
3104
- client_assertion_type: JWT_CLIENT_ASSERTION,
3105
- client_assertion: this.clientAssertion
3106
- };
3107
- }
3108
- };
3109
-
3110
- // src/models.ts
3111
- function record(value, label) {
3112
- if (typeof value !== "object" || value === null || Array.isArray(value)) {
3113
- throw new ProtocolValidationError("invalid_type", `${label} must be an object`);
3114
- }
3115
- return value;
3116
- }
3117
- function string(value, label) {
3118
- if (typeof value !== "string" || value.length === 0) {
3119
- throw new ProtocolValidationError("invalid_type", `${label} must be a non-empty string`);
3120
- }
3121
- return value;
3122
- }
3123
- function array(value, label) {
3124
- if (!Array.isArray(value)) {
3125
- throw new ProtocolValidationError("invalid_type", `${label} must be an array`);
3126
- }
3127
- return value;
3128
- }
3129
- function boolean(value, label) {
3130
- if (typeof value !== "boolean") {
3131
- throw new ProtocolValidationError("invalid_type", `${label} must be a boolean`);
3132
- }
3133
- return value;
3134
- }
3135
- function integer(value, label, minimum = 1) {
3136
- if (!Number.isInteger(value) || value < minimum) {
3137
- throw new ProtocolValidationError(
3138
- "invalid_type",
3139
- `${label} must be an integer greater than or equal to ${minimum}`
3140
- );
3141
- }
3142
- return value;
3143
- }
3144
- function identifier(value, label) {
3145
- const result = string(value, label);
3146
- if (!/^[A-Za-z0-9_-]{1,256}$/.test(result)) {
3147
- throw new ProtocolValidationError(
3148
- "invalid_identifier",
3149
- `${label} must use the URL-safe base64 alphabet`
3150
- );
3151
- }
3152
- return result;
3153
- }
3154
- function timestamp(value, label) {
3155
- const result = string(value, label);
3156
- if (!/(?:Z|[+-][0-9]{2}:[0-9]{2})$/u.test(result) || Number.isNaN(Date.parse(result))) {
3157
- throw new ProtocolValidationError(
3158
- "invalid_timestamp",
3159
- `${label} must be an RFC 3339 timestamp with a timezone`
3160
- );
3161
- }
3162
- return result;
3163
- }
3164
- function oneOf(value, values, label) {
3165
- if (typeof value !== "string" || !values.includes(value)) {
3166
- throw new ProtocolValidationError(
3167
- "invalid_value",
3168
- `${label} must be one of ${values.join(", ")}`
3169
- );
3170
- }
3171
- return value;
3172
- }
3173
- function optionalRecord(value, label) {
3174
- return value === void 0 ? void 0 : record(value, label);
3175
- }
3176
- function extensions(value, label) {
3177
- const source = record(value ?? {}, label);
3178
- return Object.fromEntries(
3179
- Object.entries(source).map(([name, item]) => {
3180
- const extension = record(item, `${label}.${name}`);
3181
- const version = string(extension.version, `${label}.${name}.version`);
3182
- if (!/^(0|[1-9][0-9]*)$/.test(version)) {
3183
- throw new ProtocolValidationError(
3184
- "invalid_extension_version",
3185
- `${label}.${name}.version must be a major version`
3186
- );
3187
- }
3188
- return [name, { ...extension, version }];
3189
- })
3190
- );
3191
- }
3192
- function httpsUrl3(value, label) {
3193
- const result = string(value, label);
3194
- let parsed;
3195
- try {
3196
- parsed = new URL(result);
3197
- } catch (cause) {
3198
- throw new ProtocolValidationError("invalid_url", `${label} must be an HTTPS URL`, {
3199
- cause
3200
- });
3201
- }
3202
- if (parsed.protocol !== "https:" || parsed.username || parsed.password) {
3203
- throw new ProtocolValidationError(
3204
- "invalid_url",
3205
- `${label} must be an HTTPS URL without user information`
3206
- );
3207
- }
3208
- return result;
3209
- }
3210
- function domain(value, label) {
3211
- const result = string(value, label).replace(/\.$/, "").toLowerCase();
3212
- if (!/^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/.test(
3213
- result
3214
- )) {
3215
- throw new ProtocolValidationError("invalid_domain", `${label} must be a DNS domain`);
3216
- }
3217
- return result;
3218
- }
3219
- function scopes(value, label) {
3220
- const source = record(value, label);
3221
- return {
3222
- ...source,
3223
- scopes: array(source.scopes ?? [], `${label}.scopes`).map((item) => string(item, "scope"))
3224
- };
3225
- }
3226
- function stringMap(value, label) {
3227
- const source = record(value, label);
3228
- return Object.fromEntries(
3229
- Object.entries(source).map(([key, item]) => [key, string(item, `${label}.${key}`)])
3230
- );
3231
- }
3232
- function parseDiscoveryDocument(value) {
3233
- const source = record(value, "poppy.json");
3234
- const version = string(source.protocol_version, "protocol_version");
3235
- const versionMatch = /^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$/.exec(version);
3236
- if (!versionMatch || versionMatch[1] !== "0") {
3237
- throw new ProtocolValidationError(
3238
- "unsupported_protocol_version",
3239
- "protocol_version must be a supported major.minor version"
3240
- );
3241
- }
3242
- const organizationSource = record(source.organization, "organization");
3243
- const organization = {
3244
- ...organizationSource,
3245
- name: string(organizationSource.name, "organization.name"),
3246
- domain: domain(organizationSource.domain, "organization.domain")
3247
- };
3248
- let auth;
3249
- if (source.auth !== void 0) {
3250
- const authSource = record(source.auth, "auth");
3251
- let mediated;
3252
- if (authSource.mediated !== void 0) {
3253
- const mediatedSource = record(authSource.mediated, "auth.mediated");
3254
- const fields = array(mediatedSource.fields, "auth.mediated.fields").map(
3255
- (item, index) => {
3256
- const field = record(item, `auth.mediated.fields[${index}]`);
3257
- return {
3258
- ...field,
3259
- name: string(field.name, `auth.mediated.fields[${index}].name`),
3260
- label: string(field.label, `auth.mediated.fields[${index}].label`),
3261
- secret: boolean(field.secret, `auth.mediated.fields[${index}].secret`)
3262
- };
3263
- }
3264
- );
3265
- if (fields.length === 0) {
3266
- throw new ProtocolValidationError(
3267
- "invalid_mediated_sign_in",
3268
- "auth.mediated.fields must not be empty"
3269
- );
3270
- }
3271
- mediated = {
3272
- ...mediatedSource,
3273
- ...scopes(mediatedSource, "auth.mediated"),
3274
- endpoint: httpsUrl3(mediatedSource.endpoint, "auth.mediated.endpoint"),
3275
- fields
3276
- };
3277
- }
3278
- auth = {
3279
- ...authSource,
3280
- issuer: httpsUrl3(authSource.issuer, "auth.issuer").replace(/\/$/, ""),
3281
- ...authSource.direct === void 0 ? {} : { direct: scopes(authSource.direct, "auth.direct") },
3282
- ...authSource.device === void 0 ? {} : { device: scopes(authSource.device, "auth.device") },
3283
- ...mediated === void 0 ? {} : { mediated },
3284
- ...authSource.custom_scopes === void 0 ? {} : {
3285
- custom_scopes: stringMap(authSource.custom_scopes, "auth.custom_scopes")
3286
- }
3287
- };
3288
- }
3289
- const apis = array(source.apis ?? [], "apis").map((item, index) => {
3290
- const api = record(item, `apis[${index}]`);
3291
- return {
3292
- ...api,
3293
- type: string(api.type, `apis[${index}].type`),
3294
- url: httpsUrl3(api.url, `apis[${index}].url`),
3295
- description: string(api.description, `apis[${index}].description`),
3296
- ...api.resource === void 0 ? {} : { resource: httpsUrl3(api.resource, `apis[${index}].resource`) }
3297
- };
3298
- });
3299
- let agent;
3300
- if (source.agent !== void 0) {
3301
- const agentSource = record(source.agent, "agent");
3302
- const protocols = array(agentSource.protocols, "agent.protocols").map((item, index) => {
3303
- const protocol = record(item, `agent.protocols[${index}]`);
3304
- return {
3305
- ...protocol,
3306
- type: string(protocol.type, `agent.protocols[${index}].type`),
3307
- endpoint: httpsUrl3(protocol.endpoint, `agent.protocols[${index}].endpoint`),
3308
- ...protocol.resource === void 0 ? {} : {
3309
- resource: httpsUrl3(
3310
- protocol.resource,
3311
- `agent.protocols[${index}].resource`
3312
- )
3313
- }
3314
- };
3315
- });
3316
- if (protocols.length === 0) {
3317
- throw new ProtocolValidationError(
3318
- "invalid_agent",
3319
- "agent.protocols must not be empty"
3320
- );
3321
- }
3322
- agent = { ...agentSource, protocols };
3323
- }
3324
- let web;
3325
- if (source.web !== void 0) {
3326
- const webSource = record(source.web, "web");
3327
- web = {
3328
- ...webSource,
3329
- ...webSource.browser_session_endpoint === void 0 ? {} : {
3330
- browser_session_endpoint: httpsUrl3(
3331
- webSource.browser_session_endpoint,
3332
- "web.browser_session_endpoint"
3333
- )
3334
- }
3335
- };
3336
- }
3337
- if (!agent && apis.length === 0 && !web) {
3338
- throw new ProtocolValidationError(
3339
- "missing_interface",
3340
- "one of agent, apis, or web is required"
3341
- );
3342
- }
3343
- if ((agent || apis.length > 0 || web?.browser_session_endpoint) && !auth) {
3344
- throw new ProtocolValidationError(
3345
- "missing_auth",
3346
- "auth is required for sessions, APIs, or conversations"
3347
- );
3348
- }
3349
- const parsedExtensions = extensions(source.extensions, "extensions");
3350
- return {
3351
- ...source,
3352
- protocol_version: version,
3353
- organization,
3354
- ...auth ? { auth } : {},
3355
- ...agent ? { agent } : {},
3356
- ...web ? { web } : {},
3357
- apis,
3358
- extensions: parsedExtensions
3359
- };
3360
- }
3361
- function parseOAuthServerMetadata(value) {
3362
- const source = record(value, "OAuth metadata");
3363
- const poppyDomains = array(source.poppy_domains, "poppy_domains").map(
3364
- (item) => domain(item, "poppy_domains entry")
3365
- );
3366
- if (poppyDomains.length === 0) {
3367
- throw new ProtocolValidationError(
3368
- "invalid_oauth_metadata",
3369
- "poppy_domains must not be empty"
3370
- );
3371
- }
3372
- return {
3373
- ...source,
3374
- issuer: httpsUrl3(source.issuer, "issuer").replace(/\/$/, ""),
3375
- token_endpoint: httpsUrl3(source.token_endpoint, "token_endpoint"),
3376
- revocation_endpoint: httpsUrl3(source.revocation_endpoint, "revocation_endpoint"),
3377
- ...source.authorization_endpoint === void 0 ? {} : {
3378
- authorization_endpoint: httpsUrl3(
3379
- source.authorization_endpoint,
3380
- "authorization_endpoint"
3381
- )
3382
- },
3383
- ...source.device_authorization_endpoint === void 0 ? {} : {
3384
- device_authorization_endpoint: httpsUrl3(
3385
- source.device_authorization_endpoint,
3386
- "device_authorization_endpoint"
3387
- )
3388
- },
3389
- poppy_domains: poppyDomains
3390
- };
3391
- }
3392
- function parseClientMetadata(value) {
3393
- const source = record(value, "client metadata");
3394
- const clientId = httpsUrl3(source.client_id, "client_id");
3395
- const clientDomain = new URL(clientId).hostname;
3396
- const jwksUri = httpsUrl3(source.jwks_uri, "jwks_uri");
3397
- const redirectUris = array(source.redirect_uris ?? [], "redirect_uris").map(
3398
- (item) => httpsUrl3(item, "redirect URI")
3399
- );
3400
- if (new URL(jwksUri).hostname !== clientDomain || redirectUris.some((uri) => new URL(uri).hostname !== clientDomain)) {
3401
- throw new ProtocolValidationError(
3402
- "client_domain_mismatch",
3403
- "jwks_uri and redirect_uris must use the client_id domain"
3404
- );
3405
- }
3406
- const authMethod = source.token_endpoint_auth_method ?? "private_key_jwt";
3407
- if (authMethod !== "private_key_jwt") {
3408
- throw new ProtocolValidationError(
3409
- "invalid_client_auth_method",
3410
- "token_endpoint_auth_method must be private_key_jwt"
3411
- );
3412
- }
3413
- return {
3414
- ...source,
3415
- client_id: clientId,
3416
- client_name: string(source.client_name, "client_name"),
3417
- ...source.logo_uri === void 0 ? {} : { logo_uri: httpsUrl3(source.logo_uri, "logo_uri") },
3418
- jwks_uri: jwksUri,
3419
- redirect_uris: redirectUris,
3420
- token_endpoint_auth_method: authMethod,
3421
- extensions: extensions(source.extensions, "extensions")
3422
- };
3423
- }
3424
- function parseOperation(value) {
3425
- const source = record(value, "operation");
3426
- const state = oneOf(
3427
- source.state,
3428
- ["proposed", "in_progress", "succeeded", "failed", "cancelled", "expired"],
3429
- "operation.state"
3430
- );
3431
- const revision = integer(source.revision, "operation.revision");
3432
- let confirmation = null;
3433
- if (source.confirmation !== void 0 && source.confirmation !== null) {
3434
- const item = record(source.confirmation, "operation.confirmation");
3435
- confirmation = {
3436
- ...item,
3437
- revision: integer(item.revision, "operation.confirmation.revision"),
3438
- approved_by: oneOf(
3439
- item.approved_by,
3440
- ["user", "standing_permission"],
3441
- "operation.confirmation.approved_by"
3442
- ),
3443
- confirmed_at: timestamp(item.confirmed_at, "operation.confirmation.confirmed_at")
3444
- };
3445
- }
3446
- let result = null;
3447
- if (source.result !== void 0 && source.result !== null) {
3448
- const item = record(source.result, "operation.result");
3449
- result = {
3450
- ...item,
3451
- summary: string(item.summary, "operation.result.summary"),
3452
- ...item.data === void 0 ? {} : { data: record(item.data, "operation.result.data") }
3453
- };
3454
- }
3455
- const expiresAt = source.expires_at === void 0 ? void 0 : timestamp(source.expires_at, "operation.expires_at");
3456
- if (state === "proposed" && expiresAt === void 0) {
3457
- throw new ProtocolValidationError(
3458
- "invalid_operation",
3459
- "a proposed operation requires expires_at"
3460
- );
3461
- }
3462
- if (state === "proposed" && confirmation !== null) {
3463
- throw new ProtocolValidationError(
3464
- "invalid_operation",
3465
- "a proposed operation cannot be confirmed"
3466
- );
3467
- }
3468
- if (confirmation !== null && confirmation.revision !== revision) {
3469
- throw new ProtocolValidationError(
3470
- "invalid_operation",
3471
- "confirmation must name the current revision"
3472
- );
3473
- }
3474
- if (["succeeded", "failed", "cancelled", "expired"].includes(state) && result === null) {
3475
- throw new ProtocolValidationError(
3476
- "invalid_operation",
3477
- "a final operation requires a result"
3478
- );
3479
- }
3480
- return {
3481
- ...source,
3482
- operation_id: identifier(source.operation_id, "operation.operation_id"),
3483
- revision,
3484
- state,
3485
- summary: string(source.summary, "operation.summary"),
3486
- ...source.terms === void 0 ? {} : { terms: record(source.terms, "operation.terms") },
3487
- ...expiresAt === void 0 ? {} : { expires_at: expiresAt },
3488
- user_approval_required: source.user_approval_required === void 0 ? false : boolean(source.user_approval_required, "operation.user_approval_required"),
3489
- ...source.url === void 0 ? {} : { url: httpsUrl3(source.url, "operation.url") },
3490
- confirmation,
3491
- result
3492
- };
3493
- }
3494
- function parseMessage(value) {
3495
- const source = record(value, "message");
3496
- const text = source.text === void 0 ? void 0 : string(source.text, "message.text");
3497
- const data = optionalRecord(source.data, "message.data");
3498
- const context = optionalRecord(source.context, "message.context");
3499
- const operation = source.operation === void 0 ? void 0 : parseOperation(source.operation);
3500
- if (text === void 0 && data === void 0 && context === void 0 && operation === void 0) {
3501
- throw new ProtocolValidationError(
3502
- "invalid_message",
3503
- "a message requires text, data, context, or operation"
3504
- );
3505
- }
3506
- return {
3507
- ...source,
3508
- id: identifier(source.id, "message.id"),
3509
- sender: oneOf(source.sender, ["agent", "human"], "message.sender"),
3510
- ...source.role === void 0 ? {} : { role: oneOf(source.role, ["user", "company"], "message.role") },
3511
- ...text === void 0 ? {} : { text },
3512
- ...data === void 0 ? {} : { data },
3513
- ...context === void 0 ? {} : { context },
3514
- ...operation === void 0 ? {} : { operation }
3515
- };
3516
- }
3517
- function parseConversationEvent(value) {
3518
- const source = record(value, "conversation event");
3519
- const type = string(source.type, "conversation event.type");
3520
- const parsed = {
3521
- ...source,
3522
- id: identifier(source.id, "conversation event.id"),
3523
- type,
3524
- created_at: timestamp(source.created_at, "conversation event.created_at"),
3525
- ...source.message === void 0 ? {} : { message: parseMessage(source.message) },
3526
- ...source.status === void 0 ? {} : {
3527
- status: oneOf(
3528
- source.status,
3529
- ["working", "idle", "queued", "closed"],
3530
- "conversation event.status"
3531
- )
3532
- },
3533
- ...source.responder === void 0 ? {} : {
3534
- responder: oneOf(
3535
- source.responder,
3536
- ["agent", "human"],
3537
- "conversation event.responder"
3538
- )
3539
- },
3540
- ...source.error === void 0 ? {} : {
3541
- error: oneOf(
3542
- source.error,
3543
- ["sign_in_required", "insufficient_scope"],
3544
- "conversation event.error"
3545
- )
3546
- },
3547
- ...source.scope === void 0 ? {} : { scope: string(source.scope, "conversation event.scope") },
3548
- ...source.reason === void 0 ? {} : { reason: string(source.reason, "conversation event.reason") },
3549
- ...source.conversation_id === void 0 ? {} : {
3550
- conversation_id: identifier(
3551
- source.conversation_id,
3552
- "conversation event.conversation_id"
3553
- )
3554
- }
3555
- };
3556
- if (type === "message" && parsed.message === void 0) {
3557
- throw new ProtocolValidationError("invalid_event", "a message event requires message");
3558
- }
3559
- if (type === "state" && (parsed.status === void 0 || parsed.responder === void 0)) {
3560
- throw new ProtocolValidationError(
3561
- "invalid_event",
3562
- "a state event requires status and responder"
3563
- );
3564
- }
3565
- if (type === "authorization") {
3566
- if (parsed.error === void 0) {
3567
- throw new ProtocolValidationError(
3568
- "invalid_event",
3569
- "an authorization event requires error"
3570
- );
3571
- }
3572
- if (parsed.error === "insufficient_scope" && parsed.scope === void 0) {
3573
- throw new ProtocolValidationError(
3574
- "invalid_event",
3575
- "insufficient_scope requires scope"
3576
- );
3577
- }
3578
- }
3579
- if (type === "user_requested" && parsed.reason === void 0) {
3580
- throw new ProtocolValidationError(
3581
- "invalid_event",
3582
- "a user_requested event requires reason"
3583
- );
3584
- }
3585
- if ((type === "direct_opened" || type === "direct_closed") && parsed.conversation_id === void 0) {
3586
- throw new ProtocolValidationError(
3587
- "invalid_event",
3588
- "a direct conversation event requires conversation_id"
3589
- );
3590
- }
3591
- return parsed;
3592
- }
3593
- function parseConversationEventPage(value) {
3594
- const source = record(value, "conversation event page");
3595
- return {
3596
- ...source,
3597
- conversation_id: identifier(source.conversation_id, "conversation_id"),
3598
- events: array(source.events, "events").map(parseConversationEvent),
3599
- cursor: identifier(source.cursor, "cursor"),
3600
- has_more: boolean(source.has_more, "has_more"),
3601
- status: oneOf(
3602
- source.status,
3603
- ["working", "idle", "queued", "closed"],
3604
- "status"
3605
- ),
3606
- responder: oneOf(source.responder, ["agent", "human"], "responder")
3607
- };
3608
- }
3609
-
3610
- // src/discovery.ts
3611
- function normalizeDomain(domain2) {
3612
- const value = domain2.replace(/\.$/, "").toLowerCase();
3613
- if (!value || value.includes("://") || value.includes("/")) {
3614
- throw new DiscoveryError("invalid_domain", "Discovery requires a DNS domain name");
3615
- }
3616
- return value;
3617
- }
3618
- function metadataUrl(issuer) {
3619
- const parsed = new URL(issuer);
3620
- const path = parsed.pathname.replace(/\/$/, "");
3621
- parsed.pathname = `/.well-known/oauth-authorization-server${path}`;
3622
- parsed.search = "";
3623
- parsed.hash = "";
3624
- return parsed;
3625
- }
3626
- async function readJson(initialUrl, transport, urlPolicy, maxRedirects, maxResponseBytes) {
3627
- let current = initialUrl;
3628
- for (let redirects = 0; redirects <= maxRedirects; redirects += 1) {
3629
- await urlPolicy.assertSafe(current);
3630
- let response;
3631
- try {
3632
- response = await transport.fetch(current, {
3633
- headers: { Accept: "application/json" },
3634
- redirect: "manual",
3635
- credentials: "omit"
3636
- });
3637
- } catch (cause) {
3638
- throw new DiscoveryError("request_failed", "Discovery request failed", { cause });
3639
- }
3640
- if (response.status >= 300 && response.status < 400) {
3641
- if (redirects === maxRedirects) {
3642
- throw new DiscoveryError("too_many_redirects", "Discovery exceeded redirect limit");
3643
- }
3644
- const location2 = response.headers.get("location");
3645
- if (!location2) {
3646
- throw new DiscoveryError("invalid_redirect", "Discovery redirect has no location");
3647
- }
3648
- current = new URL(location2, current);
3649
- continue;
3650
- }
3651
- if (!response.ok) {
3652
- throw new DiscoveryError(
3653
- "http_error",
3654
- "Discovery endpoint returned an unsuccessful status",
3655
- { statusCode: response.status }
3656
- );
3657
- }
3658
- const contentType = response.headers.get("content-type")?.split(";", 1)[0]?.trim();
3659
- if (contentType !== "application/json" && contentType !== "application/poppy+json") {
3660
- throw new DiscoveryError("invalid_content_type", "Discovery response must be JSON");
3661
- }
3662
- const body = await response.text();
3663
- if (new TextEncoder().encode(body).byteLength > maxResponseBytes) {
3664
- throw new DiscoveryError("response_too_large", "Discovery response exceeds size limit");
3665
- }
3666
- try {
3667
- return { value: parseJsonStrict(body), finalUrl: current };
3668
- } catch (cause) {
3669
- if (cause instanceof ProtocolValidationError) throw cause;
3670
- throw new ProtocolValidationError("invalid_json", "Response is not valid JSON", {
3671
- cause
3672
- });
3673
- }
3674
- }
3675
- throw new DiscoveryError("too_many_redirects", "Discovery exceeded redirect limit");
3676
- }
3677
- async function discoverCompany(domain2, options = {}) {
3678
- const requestedDomain = normalizeDomain(domain2);
3679
- const reactor = options.reactor ?? buildPapReactor(options);
3680
- const transport = firstContribution(
3681
- reactor,
3682
- DiscoveryTransports,
3683
- "discovery transport"
3684
- );
3685
- const urlPolicy = firstContribution(
3686
- reactor,
3687
- UrlSafetyPolicies,
3688
- "URL safety policy"
3689
- );
3690
- const maxRedirects = options.maxRedirects ?? 3;
3691
- const maxBytes = options.maxResponseBytes ?? 100 * 1024;
3692
- const discovery = await readJson(
3693
- new URL(`https://${requestedDomain}/.well-known/poppy.json`),
3694
- transport,
3695
- urlPolicy,
3696
- maxRedirects,
3697
- maxBytes
3698
- );
3699
- const document = parseDiscoveryDocument(discovery.value);
3700
- if (document.organization.domain.replace(/^www\./, "") !== requestedDomain.replace(/^www\./, "")) {
3701
- throw new DiscoveryError(
3702
- "organization_domain_mismatch",
3703
- "Discovery organization domain does not match the requested domain"
3704
- );
3705
- }
3706
- if (!document.auth) {
3707
- return { discoveryUrl: discovery.finalUrl.toString(), document };
3708
- }
3709
- const metadataResponse = await readJson(
3710
- metadataUrl(document.auth.issuer),
3711
- transport,
3712
- urlPolicy,
3713
- maxRedirects,
3714
- maxBytes
3715
- );
3716
- const oauthMetadata = parseOAuthServerMetadata(metadataResponse.value);
3717
- if (oauthMetadata.issuer !== document.auth.issuer) {
3718
- throw new DiscoveryError("issuer_mismatch", "OAuth metadata issuer does not match auth.issuer");
3719
- }
3720
- if (!oauthMetadata.poppy_domains.includes(document.organization.domain)) {
3721
- throw new DiscoveryError(
3722
- "domain_not_authorized",
3723
- "OAuth metadata does not authorize the discovered company domain"
3724
- );
3725
- }
3726
- return {
3727
- discoveryUrl: discovery.finalUrl.toString(),
3728
- document,
3729
- oauthMetadata
3730
- };
3731
- }
1
+ import {
2
+ AgentIdentityClient,
3
+ AuthorizationCodeGrant,
4
+ AuthorizationError,
5
+ AuthorizationStateStores,
6
+ BROWSER_ASSERTION_TYPE,
7
+ BrowserFormPosts,
8
+ BrowserHandoffs,
9
+ BrowserSessionClient,
10
+ BrowserSessionError,
11
+ Caches,
12
+ Clocks,
13
+ ConversationClient,
14
+ ConversationError,
15
+ DirectSignInClient,
16
+ DiscoveryError,
17
+ DiscoveryTransports,
18
+ DpopFetchClient,
19
+ DpopProofProviders,
20
+ ExtensionHandlers,
21
+ IdentityError,
22
+ JWT_BEARER_GRANT,
23
+ JWT_CLIENT_ASSERTION,
24
+ JoseDpopProofProvider,
25
+ KeyStores,
26
+ PairwiseUserIdStores,
27
+ PersonalAgentProtocolError,
28
+ ProofError,
29
+ ProtocolProfiles,
30
+ ProtocolValidationError,
31
+ RandomSources,
32
+ SecretValue,
33
+ SessionClient,
34
+ SessionError,
35
+ SessionGrant,
36
+ Signers,
37
+ TokenStores,
38
+ TransportError,
39
+ UrlSafetyPolicies,
40
+ buildBrowserAssertionClaims,
41
+ buildDirectSignInRequest,
42
+ buildPapReactor,
43
+ buildSessionAssertionClaims,
44
+ createPapCorePlugin,
45
+ discoverCompany,
46
+ firstContribution,
47
+ generateMessageId,
48
+ generatePairwiseUserId,
49
+ parseClientMetadata,
50
+ parseConversationEvent,
51
+ parseConversationEventPage,
52
+ parseDiscoveryDocument,
53
+ parseJsonStrict,
54
+ parseJsonWebKeySet,
55
+ parseMessage,
56
+ parseOAuthServerMetadata,
57
+ parseOperation,
58
+ parseSessionToken,
59
+ resolvePairwiseUserId,
60
+ validateDirectSignInCallback
61
+ } from "./chunk-TU6B5MQ7.js";
3732
62
  export {
63
+ AgentIdentityClient,
3733
64
  AuthorizationCodeGrant,
3734
65
  AuthorizationError,
66
+ AuthorizationStateStores,
67
+ BROWSER_ASSERTION_TYPE,
68
+ BrowserFormPosts,
3735
69
  BrowserHandoffs,
70
+ BrowserSessionClient,
71
+ BrowserSessionError,
3736
72
  Caches,
3737
73
  Clocks,
74
+ ConversationClient,
75
+ ConversationError,
76
+ DirectSignInClient,
3738
77
  DiscoveryError,
3739
78
  DiscoveryTransports,
79
+ DpopFetchClient,
3740
80
  DpopProofProviders,
3741
81
  ExtensionHandlers,
82
+ IdentityError,
3742
83
  JWT_BEARER_GRANT,
3743
84
  JWT_CLIENT_ASSERTION,
3744
85
  JoseDpopProofProvider,
3745
- JoseSigner,
3746
86
  KeyStores,
87
+ PairwiseUserIdStores,
3747
88
  PersonalAgentProtocolError,
3748
89
  ProofError,
3749
90
  ProtocolProfiles,
@@ -3755,24 +96,28 @@ export {
3755
96
  SessionGrant,
3756
97
  Signers,
3757
98
  TokenStores,
99
+ TransportError,
3758
100
  UrlSafetyPolicies,
101
+ buildBrowserAssertionClaims,
3759
102
  buildDirectSignInRequest,
3760
103
  buildPapReactor,
3761
104
  buildSessionAssertionClaims,
3762
105
  createPapCorePlugin,
3763
106
  discoverCompany,
3764
107
  firstContribution,
108
+ generateMessageId,
3765
109
  generatePairwiseUserId,
3766
110
  parseClientMetadata,
3767
111
  parseConversationEvent,
3768
112
  parseConversationEventPage,
3769
113
  parseDiscoveryDocument,
3770
114
  parseJsonStrict,
115
+ parseJsonWebKeySet,
3771
116
  parseMessage,
3772
117
  parseOAuthServerMetadata,
3773
118
  parseOperation,
3774
119
  parseSessionToken,
3775
- validateDirectSignInCallback,
3776
- verifyDpopProof
120
+ resolvePairwiseUserId,
121
+ validateDirectSignInCallback
3777
122
  };
3778
123
  //# sourceMappingURL=index.js.map