@fanvue/builder-sdk 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +77 -1
- package/dist/bridge/index.d.ts +2 -0
- package/dist/bridge/index.js +3 -0
- package/dist/bridge-CGVtI3hr.js +336 -0
- package/dist/bridge-CGVtI3hr.js.map +1 -0
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.js +2 -1
- package/dist/core-BqdYUMrJ.js +1653 -0
- package/dist/core-BqdYUMrJ.js.map +1 -0
- package/dist/index-BRDYLBlc.d.ts +223 -0
- package/dist/index-BRDYLBlc.d.ts.map +1 -0
- package/dist/{index-CweVyIKX.d.ts → index-C4ewLil3.d.ts} +2 -2
- package/dist/{index-CweVyIKX.d.ts.map → index-C4ewLil3.d.ts.map} +1 -1
- package/dist/index-ClbZoV_Z.d.ts +420 -0
- package/dist/index-ClbZoV_Z.d.ts.map +1 -0
- package/dist/{index-pS9wR5yg.d.ts → index-Dr-mZ0qP.d.ts} +500 -901
- package/dist/index-Dr-mZ0qP.d.ts.map +1 -0
- package/dist/nextjs/embedded-app/index.d.ts +2 -2
- package/dist/nextjs/embedded-app/index.js +3 -2
- package/dist/nextjs/embedded-app/index.js.map +1 -1
- package/dist/nextjs/off-platform/index.d.ts +2 -2
- package/dist/nextjs/off-platform/index.js +3 -2
- package/dist/nextjs/off-platform/index.js.map +1 -1
- package/dist/{nextjs-CESI_EiU.js → nextjs-B5Tqgt_n.js} +2 -2
- package/dist/{nextjs-CESI_EiU.js.map → nextjs-B5Tqgt_n.js.map} +1 -1
- package/dist/react/index.d.ts +37 -2
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +61 -2
- package/dist/react/index.js.map +1 -1
- package/dist/{core-CvVOMyqr.js → schemas-DbyHF7Xi.js} +261 -1662
- package/dist/schemas-DbyHF7Xi.js.map +1 -0
- package/package.json +20 -16
- package/dist/core-CvVOMyqr.js.map +0 -1
- package/dist/index-pS9wR5yg.d.ts.map +0 -1
|
@@ -1,40 +1,6 @@
|
|
|
1
1
|
//#region \0rolldown/runtime.js
|
|
2
2
|
var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
3
3
|
//#endregion
|
|
4
|
-
//#region src/core/constants.ts
|
|
5
|
-
/** The `Bearer ` token prefix (includes trailing space). */
|
|
6
|
-
const BEARER_PREFIX = "Bearer ";
|
|
7
|
-
/** Response header carrying a refreshed session JWT back to the client. */
|
|
8
|
-
const HEADER_UPDATED_SESSION = "X-Updated-Session";
|
|
9
|
-
//#endregion
|
|
10
|
-
//#region src/core/defaults.ts
|
|
11
|
-
/** Default OAuth scopes requested during authorization. */
|
|
12
|
-
const DEFAULT_SCOPES = "openid offline_access offline";
|
|
13
|
-
/** Default OAuth issuer URL for Fanvue authentication. */
|
|
14
|
-
const DEFAULT_ISSUER_URL = "https://auth.fanvue.com";
|
|
15
|
-
/** Default base URL for the Fanvue API. */
|
|
16
|
-
const DEFAULT_API_BASE_URL = "https://api.fanvue.com";
|
|
17
|
-
/** Default base URL for the Fanvue platform (embedded authorize-on-behalf). */
|
|
18
|
-
const DEFAULT_PLATFORM_URL = "https://www.fanvue.com";
|
|
19
|
-
/** The Fanvue API version header value sent with every request. */
|
|
20
|
-
const API_VERSION = "2025-06-26";
|
|
21
|
-
/**
|
|
22
|
-
* Validates that a URL belongs to the `fanvue.com` domain.
|
|
23
|
-
*
|
|
24
|
-
* @param url - The URL string to validate.
|
|
25
|
-
* @throws If the URL is malformed or its hostname is not `fanvue.com`
|
|
26
|
-
* (or a subdomain of it).
|
|
27
|
-
*/
|
|
28
|
-
function assertFanvueDomain(url) {
|
|
29
|
-
let hostname;
|
|
30
|
-
try {
|
|
31
|
-
hostname = new URL(url).hostname;
|
|
32
|
-
} catch {
|
|
33
|
-
throw new Error(`Invalid apiBaseUrl: "${url}" is not a valid URL.`);
|
|
34
|
-
}
|
|
35
|
-
if (hostname !== "fanvue.com" && !hostname.endsWith(".fanvue.com")) throw new Error(`Invalid apiBaseUrl: "${url}" must be a fanvue.com domain (e.g. https://api.fanvue.com).`);
|
|
36
|
-
}
|
|
37
|
-
//#endregion
|
|
38
4
|
//#region node_modules/.pnpm/neverthrow@8.2.0/node_modules/neverthrow/dist/index.cjs.js
|
|
39
5
|
var require_index_cjs = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
40
6
|
const defaultErrorConfig = { withStackTrace: false };
|
|
@@ -521,126 +487,6 @@ var require_index_cjs = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
521
487
|
exports.okAsync = okAsync;
|
|
522
488
|
exports.safeTry = safeTry;
|
|
523
489
|
}));
|
|
524
|
-
if (typeof navigator === "undefined" || !navigator.userAgent?.startsWith?.("Mozilla/5.0 "));
|
|
525
|
-
const ERR_INVALID_ARG_VALUE = "ERR_INVALID_ARG_VALUE";
|
|
526
|
-
const ERR_INVALID_ARG_TYPE = "ERR_INVALID_ARG_TYPE";
|
|
527
|
-
function CodedTypeError(message, code, cause) {
|
|
528
|
-
const err = new TypeError(message, { cause });
|
|
529
|
-
Object.assign(err, { code });
|
|
530
|
-
return err;
|
|
531
|
-
}
|
|
532
|
-
const encoder$1 = new TextEncoder();
|
|
533
|
-
const decoder$1 = new TextDecoder();
|
|
534
|
-
function buf(input) {
|
|
535
|
-
if (typeof input === "string") return encoder$1.encode(input);
|
|
536
|
-
return decoder$1.decode(input);
|
|
537
|
-
}
|
|
538
|
-
let encodeBase64Url;
|
|
539
|
-
if (Uint8Array.prototype.toBase64) encodeBase64Url = (input) => {
|
|
540
|
-
if (input instanceof ArrayBuffer) input = new Uint8Array(input);
|
|
541
|
-
return input.toBase64({
|
|
542
|
-
alphabet: "base64url",
|
|
543
|
-
omitPadding: true
|
|
544
|
-
});
|
|
545
|
-
};
|
|
546
|
-
else {
|
|
547
|
-
const CHUNK_SIZE = 32768;
|
|
548
|
-
encodeBase64Url = (input) => {
|
|
549
|
-
if (input instanceof ArrayBuffer) input = new Uint8Array(input);
|
|
550
|
-
const arr = [];
|
|
551
|
-
for (let i = 0; i < input.byteLength; i += CHUNK_SIZE) arr.push(String.fromCharCode.apply(null, input.subarray(i, i + CHUNK_SIZE)));
|
|
552
|
-
return btoa(arr.join("")).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
553
|
-
};
|
|
554
|
-
}
|
|
555
|
-
let decodeBase64Url;
|
|
556
|
-
if (Uint8Array.fromBase64) decodeBase64Url = (input) => {
|
|
557
|
-
try {
|
|
558
|
-
return Uint8Array.fromBase64(input, { alphabet: "base64url" });
|
|
559
|
-
} catch (cause) {
|
|
560
|
-
throw CodedTypeError("The input to be decoded is not correctly encoded.", ERR_INVALID_ARG_VALUE, cause);
|
|
561
|
-
}
|
|
562
|
-
};
|
|
563
|
-
else decodeBase64Url = (input) => {
|
|
564
|
-
try {
|
|
565
|
-
const binary = atob(input.replace(/-/g, "+").replace(/_/g, "/").replace(/\s/g, ""));
|
|
566
|
-
const bytes = new Uint8Array(binary.length);
|
|
567
|
-
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
568
|
-
return bytes;
|
|
569
|
-
} catch (cause) {
|
|
570
|
-
throw CodedTypeError("The input to be decoded is not correctly encoded.", ERR_INVALID_ARG_VALUE, cause);
|
|
571
|
-
}
|
|
572
|
-
};
|
|
573
|
-
function b64u(input) {
|
|
574
|
-
if (typeof input === "string") return decodeBase64Url(input);
|
|
575
|
-
return encodeBase64Url(input);
|
|
576
|
-
}
|
|
577
|
-
var OperationProcessingError = class extends Error {
|
|
578
|
-
code;
|
|
579
|
-
constructor(message, options) {
|
|
580
|
-
super(message, options);
|
|
581
|
-
this.name = this.constructor.name;
|
|
582
|
-
if (options?.code) this.code = options?.code;
|
|
583
|
-
Error.captureStackTrace?.(this, this.constructor);
|
|
584
|
-
}
|
|
585
|
-
};
|
|
586
|
-
function OPE(message, code, cause) {
|
|
587
|
-
return new OperationProcessingError(message, {
|
|
588
|
-
code,
|
|
589
|
-
cause
|
|
590
|
-
});
|
|
591
|
-
}
|
|
592
|
-
function assertString(input, it, code, cause) {
|
|
593
|
-
try {
|
|
594
|
-
if (typeof input !== "string") throw CodedTypeError(`${it} must be a string`, ERR_INVALID_ARG_TYPE, cause);
|
|
595
|
-
if (input.length === 0) throw CodedTypeError(`${it} must not be empty`, ERR_INVALID_ARG_VALUE, cause);
|
|
596
|
-
} catch (err) {
|
|
597
|
-
if (code) throw OPE(err.message, code, cause);
|
|
598
|
-
throw err;
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
|
-
function randomBytes() {
|
|
602
|
-
return b64u(crypto.getRandomValues(new Uint8Array(32)));
|
|
603
|
-
}
|
|
604
|
-
function generateRandomCodeVerifier() {
|
|
605
|
-
return randomBytes();
|
|
606
|
-
}
|
|
607
|
-
function generateRandomState() {
|
|
608
|
-
return randomBytes();
|
|
609
|
-
}
|
|
610
|
-
async function calculatePKCECodeChallenge(codeVerifier) {
|
|
611
|
-
assertString(codeVerifier, "codeVerifier");
|
|
612
|
-
return b64u(await crypto.subtle.digest("SHA-256", buf(codeVerifier)));
|
|
613
|
-
}
|
|
614
|
-
URL.parse;
|
|
615
|
-
const tokenMatch = "[a-zA-Z0-9!#$%&\\'\\*\\+\\-\\.\\^_`\\|~]+";
|
|
616
|
-
const token68Match = "[a-zA-Z0-9\\-\\._\\~\\+\\/]+={0,2}";
|
|
617
|
-
const quotedParamMatcher = "(" + tokenMatch + ")\\s*=\\s*\"((?:[^\"\\\\]|\\\\[\\s\\S])*)\"";
|
|
618
|
-
const paramMatcher = "(" + tokenMatch + ")\\s*=\\s*([a-zA-Z0-9!#$%&\\'\\*\\+\\-\\.\\^_`\\|~]+)";
|
|
619
|
-
new RegExp("^[,\\s]*(" + tokenMatch + ")");
|
|
620
|
-
new RegExp("^[,\\s]*" + quotedParamMatcher + "[,\\s]*(.*)");
|
|
621
|
-
new RegExp("^[,\\s]*" + paramMatcher + "[,\\s]*(.*)");
|
|
622
|
-
new RegExp("^(" + token68Match + ")(?:$|[,\\s])(.*)");
|
|
623
|
-
//#endregion
|
|
624
|
-
//#region src/core/json.ts
|
|
625
|
-
var import_index_cjs = require_index_cjs();
|
|
626
|
-
const ERROR_RAW_TEXT_MAX_LENGTH = 500;
|
|
627
|
-
/**
|
|
628
|
-
* Safely parses a JSON string, returning a `Result` instead of throwing.
|
|
629
|
-
*
|
|
630
|
-
* @param text - The raw text to parse as JSON.
|
|
631
|
-
* @returns `ok(parsed)` on success, or `err({ code, rawText, message })` on failure.
|
|
632
|
-
*/
|
|
633
|
-
function safeJsonParse(text) {
|
|
634
|
-
try {
|
|
635
|
-
return (0, import_index_cjs.ok)(JSON.parse(text));
|
|
636
|
-
} catch (e) {
|
|
637
|
-
return (0, import_index_cjs.err)({
|
|
638
|
-
code: "JSON_PARSE_ERROR",
|
|
639
|
-
rawText: text.length > ERROR_RAW_TEXT_MAX_LENGTH ? text.slice(0, ERROR_RAW_TEXT_MAX_LENGTH) + "..." : text,
|
|
640
|
-
message: e instanceof Error ? e.message : "Failed to parse JSON"
|
|
641
|
-
});
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
490
|
Object.freeze({ status: "aborted" });
|
|
645
491
|
function $constructor(name, initializer, params) {
|
|
646
492
|
function init(inst, def) {
|
|
@@ -777,7 +623,7 @@ function slugify(input) {
|
|
|
777
623
|
return input.toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/[\s_-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
778
624
|
}
|
|
779
625
|
const captureStackTrace = "captureStackTrace" in Error ? Error.captureStackTrace : (..._args) => {};
|
|
780
|
-
function isObject
|
|
626
|
+
function isObject(data) {
|
|
781
627
|
return typeof data === "object" && data !== null && !Array.isArray(data);
|
|
782
628
|
}
|
|
783
629
|
const allowsEval = cached(() => {
|
|
@@ -790,12 +636,12 @@ const allowsEval = cached(() => {
|
|
|
790
636
|
}
|
|
791
637
|
});
|
|
792
638
|
function isPlainObject(o) {
|
|
793
|
-
if (isObject
|
|
639
|
+
if (isObject(o) === false) return false;
|
|
794
640
|
const ctor = o.constructor;
|
|
795
641
|
if (ctor === void 0) return true;
|
|
796
642
|
if (typeof ctor !== "function") return true;
|
|
797
643
|
const prot = ctor.prototype;
|
|
798
|
-
if (isObject
|
|
644
|
+
if (isObject(prot) === false) return false;
|
|
799
645
|
if (Object.prototype.hasOwnProperty.call(prot, "isPrototypeOf") === false) return false;
|
|
800
646
|
return true;
|
|
801
647
|
}
|
|
@@ -1067,6 +913,59 @@ function formatError(error, mapper = (issue) => issue.message) {
|
|
|
1067
913
|
processError(error);
|
|
1068
914
|
return fieldErrors;
|
|
1069
915
|
}
|
|
916
|
+
/** Format a ZodError as a human-readable string in the following form.
|
|
917
|
+
*
|
|
918
|
+
* From
|
|
919
|
+
*
|
|
920
|
+
* ```ts
|
|
921
|
+
* ZodError {
|
|
922
|
+
* issues: [
|
|
923
|
+
* {
|
|
924
|
+
* expected: 'string',
|
|
925
|
+
* code: 'invalid_type',
|
|
926
|
+
* path: [ 'username' ],
|
|
927
|
+
* message: 'Invalid input: expected string'
|
|
928
|
+
* },
|
|
929
|
+
* {
|
|
930
|
+
* expected: 'number',
|
|
931
|
+
* code: 'invalid_type',
|
|
932
|
+
* path: [ 'favoriteNumbers', 1 ],
|
|
933
|
+
* message: 'Invalid input: expected number'
|
|
934
|
+
* }
|
|
935
|
+
* ];
|
|
936
|
+
* }
|
|
937
|
+
* ```
|
|
938
|
+
*
|
|
939
|
+
* to
|
|
940
|
+
*
|
|
941
|
+
* ```
|
|
942
|
+
* username
|
|
943
|
+
* ✖ Expected number, received string at "username
|
|
944
|
+
* favoriteNumbers[0]
|
|
945
|
+
* ✖ Invalid input: expected number
|
|
946
|
+
* ```
|
|
947
|
+
*/
|
|
948
|
+
function toDotPath(_path) {
|
|
949
|
+
const segs = [];
|
|
950
|
+
const path = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
951
|
+
for (const seg of path) if (typeof seg === "number") segs.push(`[${seg}]`);
|
|
952
|
+
else if (typeof seg === "symbol") segs.push(`[${JSON.stringify(String(seg))}]`);
|
|
953
|
+
else if (/[^\w$]/.test(seg)) segs.push(`[${JSON.stringify(seg)}]`);
|
|
954
|
+
else {
|
|
955
|
+
if (segs.length) segs.push(".");
|
|
956
|
+
segs.push(seg);
|
|
957
|
+
}
|
|
958
|
+
return segs.join("");
|
|
959
|
+
}
|
|
960
|
+
function prettifyError(error) {
|
|
961
|
+
const lines = [];
|
|
962
|
+
const issues = [...error.issues].sort((a, b) => (a.path ?? []).length - (b.path ?? []).length);
|
|
963
|
+
for (const issue of issues) {
|
|
964
|
+
lines.push(`✖ ${issue.message}`);
|
|
965
|
+
if (issue.path?.length) lines.push(` → at ${toDotPath(issue.path)}`);
|
|
966
|
+
}
|
|
967
|
+
return lines.join("\n");
|
|
968
|
+
}
|
|
1070
969
|
//#endregion
|
|
1071
970
|
//#region node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/core/parse.js
|
|
1072
971
|
const _parse = (_Err) => (schema, value, _ctx, _params) => {
|
|
@@ -2130,13 +2029,13 @@ const $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
|
|
|
2130
2029
|
}
|
|
2131
2030
|
return propValues;
|
|
2132
2031
|
});
|
|
2133
|
-
const isObject = isObject
|
|
2032
|
+
const isObject$2 = isObject;
|
|
2134
2033
|
const catchall = def.catchall;
|
|
2135
2034
|
let value;
|
|
2136
2035
|
inst._zod.parse = (payload, ctx) => {
|
|
2137
2036
|
value ?? (value = _normalized.value);
|
|
2138
2037
|
const input = payload.value;
|
|
2139
|
-
if (!isObject(input)) {
|
|
2038
|
+
if (!isObject$2(input)) {
|
|
2140
2039
|
payload.issues.push({
|
|
2141
2040
|
expected: "object",
|
|
2142
2041
|
code: "invalid_type",
|
|
@@ -2230,7 +2129,7 @@ const $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def)
|
|
|
2230
2129
|
return (payload, ctx) => fn(shape, payload, ctx);
|
|
2231
2130
|
};
|
|
2232
2131
|
let fastpass;
|
|
2233
|
-
const isObject = isObject
|
|
2132
|
+
const isObject$1 = isObject;
|
|
2234
2133
|
const jit = !globalConfig.jitless;
|
|
2235
2134
|
const fastEnabled = jit && allowsEval.value;
|
|
2236
2135
|
const catchall = def.catchall;
|
|
@@ -2238,7 +2137,7 @@ const $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def)
|
|
|
2238
2137
|
inst._zod.parse = (payload, ctx) => {
|
|
2239
2138
|
value ?? (value = _normalized.value);
|
|
2240
2139
|
const input = payload.value;
|
|
2241
|
-
if (!isObject(input)) {
|
|
2140
|
+
if (!isObject$1(input)) {
|
|
2242
2141
|
payload.issues.push({
|
|
2243
2142
|
expected: "object",
|
|
2244
2143
|
code: "invalid_type",
|
|
@@ -2411,6 +2310,97 @@ function handleIntersectionResults(result, left, right) {
|
|
|
2411
2310
|
result.value = merged.data;
|
|
2412
2311
|
return result;
|
|
2413
2312
|
}
|
|
2313
|
+
const $ZodRecord = /* @__PURE__ */ $constructor("$ZodRecord", (inst, def) => {
|
|
2314
|
+
$ZodType.init(inst, def);
|
|
2315
|
+
inst._zod.parse = (payload, ctx) => {
|
|
2316
|
+
const input = payload.value;
|
|
2317
|
+
if (!isPlainObject(input)) {
|
|
2318
|
+
payload.issues.push({
|
|
2319
|
+
expected: "record",
|
|
2320
|
+
code: "invalid_type",
|
|
2321
|
+
input,
|
|
2322
|
+
inst
|
|
2323
|
+
});
|
|
2324
|
+
return payload;
|
|
2325
|
+
}
|
|
2326
|
+
const proms = [];
|
|
2327
|
+
const values = def.keyType._zod.values;
|
|
2328
|
+
if (values) {
|
|
2329
|
+
payload.value = {};
|
|
2330
|
+
const recordKeys = /* @__PURE__ */ new Set();
|
|
2331
|
+
for (const key of values) if (typeof key === "string" || typeof key === "number" || typeof key === "symbol") {
|
|
2332
|
+
recordKeys.add(typeof key === "number" ? key.toString() : key);
|
|
2333
|
+
const result = def.valueType._zod.run({
|
|
2334
|
+
value: input[key],
|
|
2335
|
+
issues: []
|
|
2336
|
+
}, ctx);
|
|
2337
|
+
if (result instanceof Promise) proms.push(result.then((result) => {
|
|
2338
|
+
if (result.issues.length) payload.issues.push(...prefixIssues(key, result.issues));
|
|
2339
|
+
payload.value[key] = result.value;
|
|
2340
|
+
}));
|
|
2341
|
+
else {
|
|
2342
|
+
if (result.issues.length) payload.issues.push(...prefixIssues(key, result.issues));
|
|
2343
|
+
payload.value[key] = result.value;
|
|
2344
|
+
}
|
|
2345
|
+
}
|
|
2346
|
+
let unrecognized;
|
|
2347
|
+
for (const key in input) if (!recordKeys.has(key)) {
|
|
2348
|
+
unrecognized = unrecognized ?? [];
|
|
2349
|
+
unrecognized.push(key);
|
|
2350
|
+
}
|
|
2351
|
+
if (unrecognized && unrecognized.length > 0) payload.issues.push({
|
|
2352
|
+
code: "unrecognized_keys",
|
|
2353
|
+
input,
|
|
2354
|
+
inst,
|
|
2355
|
+
keys: unrecognized
|
|
2356
|
+
});
|
|
2357
|
+
} else {
|
|
2358
|
+
payload.value = {};
|
|
2359
|
+
for (const key of Reflect.ownKeys(input)) {
|
|
2360
|
+
if (key === "__proto__") continue;
|
|
2361
|
+
let keyResult = def.keyType._zod.run({
|
|
2362
|
+
value: key,
|
|
2363
|
+
issues: []
|
|
2364
|
+
}, ctx);
|
|
2365
|
+
if (keyResult instanceof Promise) throw new Error("Async schemas not supported in object keys currently");
|
|
2366
|
+
if (typeof key === "string" && number$1.test(key) && keyResult.issues.length) {
|
|
2367
|
+
const retryResult = def.keyType._zod.run({
|
|
2368
|
+
value: Number(key),
|
|
2369
|
+
issues: []
|
|
2370
|
+
}, ctx);
|
|
2371
|
+
if (retryResult instanceof Promise) throw new Error("Async schemas not supported in object keys currently");
|
|
2372
|
+
if (retryResult.issues.length === 0) keyResult = retryResult;
|
|
2373
|
+
}
|
|
2374
|
+
if (keyResult.issues.length) {
|
|
2375
|
+
if (def.mode === "loose") payload.value[key] = input[key];
|
|
2376
|
+
else payload.issues.push({
|
|
2377
|
+
code: "invalid_key",
|
|
2378
|
+
origin: "record",
|
|
2379
|
+
issues: keyResult.issues.map((iss) => finalizeIssue(iss, ctx, config())),
|
|
2380
|
+
input: key,
|
|
2381
|
+
path: [key],
|
|
2382
|
+
inst
|
|
2383
|
+
});
|
|
2384
|
+
continue;
|
|
2385
|
+
}
|
|
2386
|
+
const result = def.valueType._zod.run({
|
|
2387
|
+
value: input[key],
|
|
2388
|
+
issues: []
|
|
2389
|
+
}, ctx);
|
|
2390
|
+
if (result instanceof Promise) proms.push(result.then((result) => {
|
|
2391
|
+
if (result.issues.length) payload.issues.push(...prefixIssues(key, result.issues));
|
|
2392
|
+
payload.value[keyResult.value] = result.value;
|
|
2393
|
+
}));
|
|
2394
|
+
else {
|
|
2395
|
+
if (result.issues.length) payload.issues.push(...prefixIssues(key, result.issues));
|
|
2396
|
+
payload.value[keyResult.value] = result.value;
|
|
2397
|
+
}
|
|
2398
|
+
}
|
|
2399
|
+
}
|
|
2400
|
+
if (proms.length) return Promise.all(proms).then(() => payload);
|
|
2401
|
+
return payload;
|
|
2402
|
+
};
|
|
2403
|
+
});
|
|
2414
2404
|
const $ZodEnum = /* @__PURE__ */ $constructor("$ZodEnum", (inst, def) => {
|
|
2415
2405
|
$ZodType.init(inst, def);
|
|
2416
2406
|
const values = getEnumValues(def.entries);
|
|
@@ -2429,6 +2419,24 @@ const $ZodEnum = /* @__PURE__ */ $constructor("$ZodEnum", (inst, def) => {
|
|
|
2429
2419
|
return payload;
|
|
2430
2420
|
};
|
|
2431
2421
|
});
|
|
2422
|
+
const $ZodLiteral = /* @__PURE__ */ $constructor("$ZodLiteral", (inst, def) => {
|
|
2423
|
+
$ZodType.init(inst, def);
|
|
2424
|
+
if (def.values.length === 0) throw new Error("Cannot create literal schema with no valid values");
|
|
2425
|
+
const values = new Set(def.values);
|
|
2426
|
+
inst._zod.values = values;
|
|
2427
|
+
inst._zod.pattern = new RegExp(`^(${def.values.map((o) => typeof o === "string" ? escapeRegex(o) : o ? escapeRegex(o.toString()) : String(o)).join("|")})$`);
|
|
2428
|
+
inst._zod.parse = (payload, _ctx) => {
|
|
2429
|
+
const input = payload.value;
|
|
2430
|
+
if (values.has(input)) return payload;
|
|
2431
|
+
payload.issues.push({
|
|
2432
|
+
code: "invalid_value",
|
|
2433
|
+
values: def.values,
|
|
2434
|
+
input,
|
|
2435
|
+
inst
|
|
2436
|
+
});
|
|
2437
|
+
return payload;
|
|
2438
|
+
};
|
|
2439
|
+
});
|
|
2432
2440
|
const $ZodTransform = /* @__PURE__ */ $constructor("$ZodTransform", (inst, def) => {
|
|
2433
2441
|
$ZodType.init(inst, def);
|
|
2434
2442
|
inst._zod.parse = (payload, ctx) => {
|
|
@@ -3551,6 +3559,27 @@ const enumProcessor = (schema, _ctx, json, _params) => {
|
|
|
3551
3559
|
if (values.every((v) => typeof v === "string")) json.type = "string";
|
|
3552
3560
|
json.enum = values;
|
|
3553
3561
|
};
|
|
3562
|
+
const literalProcessor = (schema, ctx, json, _params) => {
|
|
3563
|
+
const def = schema._zod.def;
|
|
3564
|
+
const vals = [];
|
|
3565
|
+
for (const val of def.values) if (val === void 0) {
|
|
3566
|
+
if (ctx.unrepresentable === "throw") throw new Error("Literal `undefined` cannot be represented in JSON Schema");
|
|
3567
|
+
} else if (typeof val === "bigint") if (ctx.unrepresentable === "throw") throw new Error("BigInt literals cannot be represented in JSON Schema");
|
|
3568
|
+
else vals.push(Number(val));
|
|
3569
|
+
else vals.push(val);
|
|
3570
|
+
if (vals.length === 0) {} else if (vals.length === 1) {
|
|
3571
|
+
const val = vals[0];
|
|
3572
|
+
json.type = val === null ? "null" : typeof val;
|
|
3573
|
+
if (ctx.target === "draft-04" || ctx.target === "openapi-3.0") json.enum = [val];
|
|
3574
|
+
else json.const = val;
|
|
3575
|
+
} else {
|
|
3576
|
+
if (vals.every((v) => typeof v === "number")) json.type = "number";
|
|
3577
|
+
if (vals.every((v) => typeof v === "string")) json.type = "string";
|
|
3578
|
+
if (vals.every((v) => typeof v === "boolean")) json.type = "boolean";
|
|
3579
|
+
if (vals.every((v) => v === null)) json.type = "null";
|
|
3580
|
+
json.enum = vals;
|
|
3581
|
+
}
|
|
3582
|
+
};
|
|
3554
3583
|
const customProcessor = (_schema, ctx, _json, _params) => {
|
|
3555
3584
|
if (ctx.unrepresentable === "throw") throw new Error("Custom types cannot be represented in JSON Schema");
|
|
3556
3585
|
};
|
|
@@ -3633,6 +3662,39 @@ const intersectionProcessor = (schema, ctx, json, params) => {
|
|
|
3633
3662
|
const isSimpleIntersection = (val) => "allOf" in val && Object.keys(val).length === 1;
|
|
3634
3663
|
json.allOf = [...isSimpleIntersection(a) ? a.allOf : [a], ...isSimpleIntersection(b) ? b.allOf : [b]];
|
|
3635
3664
|
};
|
|
3665
|
+
const recordProcessor = (schema, ctx, _json, params) => {
|
|
3666
|
+
const json = _json;
|
|
3667
|
+
const def = schema._zod.def;
|
|
3668
|
+
json.type = "object";
|
|
3669
|
+
const keyType = def.keyType;
|
|
3670
|
+
const patterns = keyType._zod.bag?.patterns;
|
|
3671
|
+
if (def.mode === "loose" && patterns && patterns.size > 0) {
|
|
3672
|
+
const valueSchema = process(def.valueType, ctx, {
|
|
3673
|
+
...params,
|
|
3674
|
+
path: [
|
|
3675
|
+
...params.path,
|
|
3676
|
+
"patternProperties",
|
|
3677
|
+
"*"
|
|
3678
|
+
]
|
|
3679
|
+
});
|
|
3680
|
+
json.patternProperties = {};
|
|
3681
|
+
for (const pattern of patterns) json.patternProperties[pattern.source] = valueSchema;
|
|
3682
|
+
} else {
|
|
3683
|
+
if (ctx.target === "draft-07" || ctx.target === "draft-2020-12") json.propertyNames = process(def.keyType, ctx, {
|
|
3684
|
+
...params,
|
|
3685
|
+
path: [...params.path, "propertyNames"]
|
|
3686
|
+
});
|
|
3687
|
+
json.additionalProperties = process(def.valueType, ctx, {
|
|
3688
|
+
...params,
|
|
3689
|
+
path: [...params.path, "additionalProperties"]
|
|
3690
|
+
});
|
|
3691
|
+
}
|
|
3692
|
+
const keyValues = keyType._zod.values;
|
|
3693
|
+
if (keyValues) {
|
|
3694
|
+
const validKeyValues = [...keyValues].filter((v) => typeof v === "string" || typeof v === "number");
|
|
3695
|
+
if (validKeyValues.length > 0) json.required = validKeyValues;
|
|
3696
|
+
}
|
|
3697
|
+
};
|
|
3636
3698
|
const nullableProcessor = (schema, ctx, json, params) => {
|
|
3637
3699
|
const def = schema._zod.def;
|
|
3638
3700
|
const inner = process(def.innerType, ctx, params);
|
|
@@ -3754,8 +3816,8 @@ const parse = /* @__PURE__ */ _parse(ZodRealError);
|
|
|
3754
3816
|
const parseAsync = /* @__PURE__ */ _parseAsync(ZodRealError);
|
|
3755
3817
|
const safeParse = /* @__PURE__ */ _safeParse(ZodRealError);
|
|
3756
3818
|
const safeParseAsync = /* @__PURE__ */ _safeParseAsync(ZodRealError);
|
|
3757
|
-
const encode
|
|
3758
|
-
const decode
|
|
3819
|
+
const encode = /* @__PURE__ */ _encode(ZodRealError);
|
|
3820
|
+
const decode = /* @__PURE__ */ _decode(ZodRealError);
|
|
3759
3821
|
const encodeAsync = /* @__PURE__ */ _encodeAsync(ZodRealError);
|
|
3760
3822
|
const decodeAsync = /* @__PURE__ */ _decodeAsync(ZodRealError);
|
|
3761
3823
|
const safeEncode = /* @__PURE__ */ _safeEncode(ZodRealError);
|
|
@@ -3793,8 +3855,8 @@ const ZodType = /* @__PURE__ */ $constructor("ZodType", (inst, def) => {
|
|
|
3793
3855
|
inst.parseAsync = async (data, params) => parseAsync(inst, data, params, { callee: inst.parseAsync });
|
|
3794
3856
|
inst.safeParseAsync = async (data, params) => safeParseAsync(inst, data, params);
|
|
3795
3857
|
inst.spa = inst.safeParseAsync;
|
|
3796
|
-
inst.encode = (data, params) => encode
|
|
3797
|
-
inst.decode = (data, params) => decode
|
|
3858
|
+
inst.encode = (data, params) => encode(inst, data, params);
|
|
3859
|
+
inst.decode = (data, params) => decode(inst, data, params);
|
|
3798
3860
|
inst.encodeAsync = async (data, params) => encodeAsync(inst, data, params);
|
|
3799
3861
|
inst.decodeAsync = async (data, params) => decodeAsync(inst, data, params);
|
|
3800
3862
|
inst.safeEncode = (data, params) => safeEncode(inst, data, params);
|
|
@@ -4125,6 +4187,21 @@ function intersection(left, right) {
|
|
|
4125
4187
|
right
|
|
4126
4188
|
});
|
|
4127
4189
|
}
|
|
4190
|
+
const ZodRecord = /* @__PURE__ */ $constructor("ZodRecord", (inst, def) => {
|
|
4191
|
+
$ZodRecord.init(inst, def);
|
|
4192
|
+
ZodType.init(inst, def);
|
|
4193
|
+
inst._zod.processJSONSchema = (ctx, json, params) => recordProcessor(inst, ctx, json, params);
|
|
4194
|
+
inst.keyType = def.keyType;
|
|
4195
|
+
inst.valueType = def.valueType;
|
|
4196
|
+
});
|
|
4197
|
+
function record(keyType, valueType, params) {
|
|
4198
|
+
return new ZodRecord({
|
|
4199
|
+
type: "record",
|
|
4200
|
+
keyType,
|
|
4201
|
+
valueType,
|
|
4202
|
+
...normalizeParams(params)
|
|
4203
|
+
});
|
|
4204
|
+
}
|
|
4128
4205
|
const ZodEnum = /* @__PURE__ */ $constructor("ZodEnum", (inst, def) => {
|
|
4129
4206
|
$ZodEnum.init(inst, def);
|
|
4130
4207
|
ZodType.init(inst, def);
|
|
@@ -4162,6 +4239,23 @@ function _enum(values, params) {
|
|
|
4162
4239
|
...normalizeParams(params)
|
|
4163
4240
|
});
|
|
4164
4241
|
}
|
|
4242
|
+
const ZodLiteral = /* @__PURE__ */ $constructor("ZodLiteral", (inst, def) => {
|
|
4243
|
+
$ZodLiteral.init(inst, def);
|
|
4244
|
+
ZodType.init(inst, def);
|
|
4245
|
+
inst._zod.processJSONSchema = (ctx, json, params) => literalProcessor(inst, ctx, json, params);
|
|
4246
|
+
inst.values = new Set(def.values);
|
|
4247
|
+
Object.defineProperty(inst, "value", { get() {
|
|
4248
|
+
if (def.values.length > 1) throw new Error("This schema contains multiple valid literal values. Use `.values` instead.");
|
|
4249
|
+
return def.values[0];
|
|
4250
|
+
} });
|
|
4251
|
+
});
|
|
4252
|
+
function literal(value, params) {
|
|
4253
|
+
return new ZodLiteral({
|
|
4254
|
+
type: "literal",
|
|
4255
|
+
values: Array.isArray(value) ? value : [value],
|
|
4256
|
+
...normalizeParams(params)
|
|
4257
|
+
});
|
|
4258
|
+
}
|
|
4165
4259
|
const ZodTransform = /* @__PURE__ */ $constructor("ZodTransform", (inst, def) => {
|
|
4166
4260
|
$ZodTransform.init(inst, def);
|
|
4167
4261
|
ZodType.init(inst, def);
|
|
@@ -4326,1501 +4420,6 @@ function superRefine(fn) {
|
|
|
4326
4420
|
return /* @__PURE__ */ _superRefine(fn);
|
|
4327
4421
|
}
|
|
4328
4422
|
//#endregion
|
|
4329
|
-
|
|
4330
|
-
/** Zod schema for the raw token response from the OAuth token endpoint. */
|
|
4331
|
-
const TokenResponseSchema = object({
|
|
4332
|
-
access_token: string(),
|
|
4333
|
-
refresh_token: string().nullable().optional().default(null),
|
|
4334
|
-
expires_in: number(),
|
|
4335
|
-
token_type: string(),
|
|
4336
|
-
scope: string().nullable().optional().default(null),
|
|
4337
|
-
id_token: string().nullable().optional().default(null)
|
|
4338
|
-
});
|
|
4339
|
-
/** Zod schema for a Fanvue user profile. */
|
|
4340
|
-
const FanvueUserSchema = object({
|
|
4341
|
-
uuid: string(),
|
|
4342
|
-
email: string(),
|
|
4343
|
-
handle: string(),
|
|
4344
|
-
displayName: string(),
|
|
4345
|
-
isCreator: boolean(),
|
|
4346
|
-
avatarUrl: string().nullable(),
|
|
4347
|
-
bannerUrl: string().nullable(),
|
|
4348
|
-
createdAt: string(),
|
|
4349
|
-
updatedAt: string().nullable()
|
|
4350
|
-
});
|
|
4351
|
-
/** Zod schema for the authorize-on-behalf response from the Fanvue platform. */
|
|
4352
|
-
const AuthorizeOnBehalfResponseSchema = object({
|
|
4353
|
-
code: string(),
|
|
4354
|
-
state: string()
|
|
4355
|
-
});
|
|
4356
|
-
/** Zod schema for the session JWT payload. */
|
|
4357
|
-
const SessionPayloadSchema = object({
|
|
4358
|
-
accessToken: string(),
|
|
4359
|
-
refreshToken: string().nullable(),
|
|
4360
|
-
expiresAt: number(),
|
|
4361
|
-
tokenType: string().nullable(),
|
|
4362
|
-
scope: string().nullable(),
|
|
4363
|
-
idToken: string().nullable(),
|
|
4364
|
-
userUuid: string(),
|
|
4365
|
-
handle: string(),
|
|
4366
|
-
displayName: string(),
|
|
4367
|
-
isCreator: boolean(),
|
|
4368
|
-
avatarUrl: string().nullable()
|
|
4369
|
-
}).passthrough();
|
|
4370
|
-
//#endregion
|
|
4371
|
-
//#region src/core/oauth.ts
|
|
4372
|
-
const CONTENT_TYPE_FORM_URLENCODED = "application/x-www-form-urlencoded";
|
|
4373
|
-
const OAUTH_TOKEN_ENDPOINT = "/oauth2/token";
|
|
4374
|
-
/**
|
|
4375
|
-
* Builds an OAuth 2.0 authorization URL with PKCE parameters.
|
|
4376
|
-
*
|
|
4377
|
-
* @param config - The OAuth configuration.
|
|
4378
|
-
* @param opts - Optional overrides. Pass `state` to use a deterministic state value.
|
|
4379
|
-
* @returns The authorization URL, the PKCE code verifier, and the state parameter.
|
|
4380
|
-
*/
|
|
4381
|
-
async function createAuthorizationUrl(config, opts = null) {
|
|
4382
|
-
const codeVerifier = generateRandomCodeVerifier();
|
|
4383
|
-
const codeChallenge = await calculatePKCECodeChallenge(codeVerifier);
|
|
4384
|
-
const state = opts?.state ?? generateRandomState();
|
|
4385
|
-
const issuerUrl = config.issuerUrl ?? "https://auth.fanvue.com";
|
|
4386
|
-
const scope = config.scopes !== null ? `${DEFAULT_SCOPES} ${config.scopes}`.trim() : DEFAULT_SCOPES;
|
|
4387
|
-
const url = new URL(`${issuerUrl}/oauth2/auth`);
|
|
4388
|
-
url.searchParams.set("response_type", "code");
|
|
4389
|
-
url.searchParams.set("client_id", config.clientId);
|
|
4390
|
-
url.searchParams.set("redirect_uri", config.redirectUri);
|
|
4391
|
-
url.searchParams.set("scope", scope);
|
|
4392
|
-
url.searchParams.set("state", state);
|
|
4393
|
-
url.searchParams.set("code_challenge", codeChallenge);
|
|
4394
|
-
url.searchParams.set("code_challenge_method", "S256");
|
|
4395
|
-
if (config.responseMode !== null) url.searchParams.set("response_mode", config.responseMode);
|
|
4396
|
-
if (config.prompt !== null) url.searchParams.set("prompt", config.prompt);
|
|
4397
|
-
return {
|
|
4398
|
-
url,
|
|
4399
|
-
codeVerifier,
|
|
4400
|
-
state
|
|
4401
|
-
};
|
|
4402
|
-
}
|
|
4403
|
-
/**
|
|
4404
|
-
* Exchanges an authorization code for tokens using the OAuth token endpoint.
|
|
4405
|
-
*
|
|
4406
|
-
* @param config - The OAuth configuration.
|
|
4407
|
-
* @param opts - The authorization code, PKCE code verifier, and optional redirect URI override.
|
|
4408
|
-
* @returns A `Result` containing `TokenResponse` on success or `OAuthError` on failure.
|
|
4409
|
-
*/
|
|
4410
|
-
async function exchangeCodeForToken(config, opts) {
|
|
4411
|
-
const issuerUrl = config.issuerUrl ?? "https://auth.fanvue.com";
|
|
4412
|
-
const body = new URLSearchParams({
|
|
4413
|
-
grant_type: "authorization_code",
|
|
4414
|
-
code: opts.code,
|
|
4415
|
-
redirect_uri: opts.redirectUri ?? config.redirectUri,
|
|
4416
|
-
client_id: config.clientId,
|
|
4417
|
-
code_verifier: opts.codeVerifier
|
|
4418
|
-
});
|
|
4419
|
-
let response;
|
|
4420
|
-
try {
|
|
4421
|
-
response = await fetch(`${issuerUrl}${OAUTH_TOKEN_ENDPOINT}`, {
|
|
4422
|
-
method: "POST",
|
|
4423
|
-
headers: {
|
|
4424
|
-
"Content-Type": CONTENT_TYPE_FORM_URLENCODED,
|
|
4425
|
-
Authorization: `Basic ${btoa(`${config.clientId}:${config.clientSecret}`)}`
|
|
4426
|
-
},
|
|
4427
|
-
body
|
|
4428
|
-
});
|
|
4429
|
-
} catch (error) {
|
|
4430
|
-
return (0, import_index_cjs.err)({
|
|
4431
|
-
code: "TOKEN_EXCHANGE_FAILED",
|
|
4432
|
-
statusCode: 0,
|
|
4433
|
-
message: `Network error during token exchange: ${error instanceof Error ? error.message : String(error)}`
|
|
4434
|
-
});
|
|
4435
|
-
}
|
|
4436
|
-
if (!response.ok) return (0, import_index_cjs.err)({
|
|
4437
|
-
code: "TOKEN_EXCHANGE_FAILED",
|
|
4438
|
-
statusCode: response.status,
|
|
4439
|
-
message: `Token exchange failed: ${response.status} ${response.statusText}`
|
|
4440
|
-
});
|
|
4441
|
-
const parseResult = safeJsonParse(await response.text());
|
|
4442
|
-
if (parseResult.isErr()) {
|
|
4443
|
-
const { rawText, message } = parseResult.error;
|
|
4444
|
-
return (0, import_index_cjs.err)({
|
|
4445
|
-
code: "OAUTH_JSON_PARSE_ERROR",
|
|
4446
|
-
rawText,
|
|
4447
|
-
message
|
|
4448
|
-
});
|
|
4449
|
-
}
|
|
4450
|
-
const validated = TokenResponseSchema.safeParse(parseResult.value);
|
|
4451
|
-
if (!validated.success) return (0, import_index_cjs.err)({
|
|
4452
|
-
code: "OAUTH_VALIDATION_ERROR",
|
|
4453
|
-
message: validated.error.message
|
|
4454
|
-
});
|
|
4455
|
-
return (0, import_index_cjs.ok)(validated.data);
|
|
4456
|
-
}
|
|
4457
|
-
/**
|
|
4458
|
-
* Refreshes an access token using a refresh token.
|
|
4459
|
-
*
|
|
4460
|
-
* @param config - The OAuth configuration.
|
|
4461
|
-
* @param refreshToken - The refresh token to use.
|
|
4462
|
-
* @returns A `Result` containing `TokenResponse` on success or `OAuthError` on failure.
|
|
4463
|
-
*/
|
|
4464
|
-
async function refreshAccessToken(config, refreshToken) {
|
|
4465
|
-
const issuerUrl = config.issuerUrl ?? "https://auth.fanvue.com";
|
|
4466
|
-
const body = new URLSearchParams({
|
|
4467
|
-
grant_type: "refresh_token",
|
|
4468
|
-
refresh_token: refreshToken,
|
|
4469
|
-
client_id: config.clientId
|
|
4470
|
-
});
|
|
4471
|
-
let response;
|
|
4472
|
-
try {
|
|
4473
|
-
response = await fetch(`${issuerUrl}${OAUTH_TOKEN_ENDPOINT}`, {
|
|
4474
|
-
method: "POST",
|
|
4475
|
-
headers: {
|
|
4476
|
-
"Content-Type": CONTENT_TYPE_FORM_URLENCODED,
|
|
4477
|
-
Authorization: `Basic ${btoa(`${config.clientId}:${config.clientSecret}`)}`
|
|
4478
|
-
},
|
|
4479
|
-
body
|
|
4480
|
-
});
|
|
4481
|
-
} catch (error) {
|
|
4482
|
-
return (0, import_index_cjs.err)({
|
|
4483
|
-
code: "TOKEN_REFRESH_FAILED",
|
|
4484
|
-
statusCode: 0,
|
|
4485
|
-
message: `Network error during token refresh: ${error instanceof Error ? error.message : String(error)}`
|
|
4486
|
-
});
|
|
4487
|
-
}
|
|
4488
|
-
if (!response.ok) return (0, import_index_cjs.err)({
|
|
4489
|
-
code: "TOKEN_REFRESH_FAILED",
|
|
4490
|
-
statusCode: response.status,
|
|
4491
|
-
message: `Token refresh failed: ${response.status} ${response.statusText}`
|
|
4492
|
-
});
|
|
4493
|
-
const parseResult = safeJsonParse(await response.text());
|
|
4494
|
-
if (parseResult.isErr()) {
|
|
4495
|
-
const { rawText, message } = parseResult.error;
|
|
4496
|
-
return (0, import_index_cjs.err)({
|
|
4497
|
-
code: "OAUTH_JSON_PARSE_ERROR",
|
|
4498
|
-
rawText,
|
|
4499
|
-
message
|
|
4500
|
-
});
|
|
4501
|
-
}
|
|
4502
|
-
const validated = TokenResponseSchema.safeParse(parseResult.value);
|
|
4503
|
-
if (!validated.success) return (0, import_index_cjs.err)({
|
|
4504
|
-
code: "OAUTH_VALIDATION_ERROR",
|
|
4505
|
-
message: validated.error.message
|
|
4506
|
-
});
|
|
4507
|
-
return (0, import_index_cjs.ok)(validated.data);
|
|
4508
|
-
}
|
|
4509
|
-
//#endregion
|
|
4510
|
-
//#region node_modules/.pnpm/jose@6.2.1/node_modules/jose/dist/webapi/lib/buffer_utils.js
|
|
4511
|
-
const encoder = new TextEncoder();
|
|
4512
|
-
const decoder = new TextDecoder();
|
|
4513
|
-
function concat(...buffers) {
|
|
4514
|
-
const size = buffers.reduce((acc, { length }) => acc + length, 0);
|
|
4515
|
-
const buf = new Uint8Array(size);
|
|
4516
|
-
let i = 0;
|
|
4517
|
-
for (const buffer of buffers) {
|
|
4518
|
-
buf.set(buffer, i);
|
|
4519
|
-
i += buffer.length;
|
|
4520
|
-
}
|
|
4521
|
-
return buf;
|
|
4522
|
-
}
|
|
4523
|
-
function encode$1(string) {
|
|
4524
|
-
const bytes = new Uint8Array(string.length);
|
|
4525
|
-
for (let i = 0; i < string.length; i++) {
|
|
4526
|
-
const code = string.charCodeAt(i);
|
|
4527
|
-
if (code > 127) throw new TypeError("non-ASCII string encountered in encode()");
|
|
4528
|
-
bytes[i] = code;
|
|
4529
|
-
}
|
|
4530
|
-
return bytes;
|
|
4531
|
-
}
|
|
4532
|
-
//#endregion
|
|
4533
|
-
//#region node_modules/.pnpm/jose@6.2.1/node_modules/jose/dist/webapi/lib/base64.js
|
|
4534
|
-
function encodeBase64(input) {
|
|
4535
|
-
if (Uint8Array.prototype.toBase64) return input.toBase64();
|
|
4536
|
-
const CHUNK_SIZE = 32768;
|
|
4537
|
-
const arr = [];
|
|
4538
|
-
for (let i = 0; i < input.length; i += CHUNK_SIZE) arr.push(String.fromCharCode.apply(null, input.subarray(i, i + CHUNK_SIZE)));
|
|
4539
|
-
return btoa(arr.join(""));
|
|
4540
|
-
}
|
|
4541
|
-
function decodeBase64(encoded) {
|
|
4542
|
-
if (Uint8Array.fromBase64) return Uint8Array.fromBase64(encoded);
|
|
4543
|
-
const binary = atob(encoded);
|
|
4544
|
-
const bytes = new Uint8Array(binary.length);
|
|
4545
|
-
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
4546
|
-
return bytes;
|
|
4547
|
-
}
|
|
4548
|
-
//#endregion
|
|
4549
|
-
//#region node_modules/.pnpm/jose@6.2.1/node_modules/jose/dist/webapi/util/base64url.js
|
|
4550
|
-
function decode(input) {
|
|
4551
|
-
if (Uint8Array.fromBase64) return Uint8Array.fromBase64(typeof input === "string" ? input : decoder.decode(input), { alphabet: "base64url" });
|
|
4552
|
-
let encoded = input;
|
|
4553
|
-
if (encoded instanceof Uint8Array) encoded = decoder.decode(encoded);
|
|
4554
|
-
encoded = encoded.replace(/-/g, "+").replace(/_/g, "/");
|
|
4555
|
-
try {
|
|
4556
|
-
return decodeBase64(encoded);
|
|
4557
|
-
} catch {
|
|
4558
|
-
throw new TypeError("The input to be decoded is not correctly encoded.");
|
|
4559
|
-
}
|
|
4560
|
-
}
|
|
4561
|
-
function encode(input) {
|
|
4562
|
-
let unencoded = input;
|
|
4563
|
-
if (typeof unencoded === "string") unencoded = encoder.encode(unencoded);
|
|
4564
|
-
if (Uint8Array.prototype.toBase64) return unencoded.toBase64({
|
|
4565
|
-
alphabet: "base64url",
|
|
4566
|
-
omitPadding: true
|
|
4567
|
-
});
|
|
4568
|
-
return encodeBase64(unencoded).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
4569
|
-
}
|
|
4570
|
-
//#endregion
|
|
4571
|
-
//#region node_modules/.pnpm/jose@6.2.1/node_modules/jose/dist/webapi/lib/crypto_key.js
|
|
4572
|
-
const unusable = (name, prop = "algorithm.name") => /* @__PURE__ */ new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`);
|
|
4573
|
-
const isAlgorithm = (algorithm, name) => algorithm.name === name;
|
|
4574
|
-
function getHashLength(hash) {
|
|
4575
|
-
return parseInt(hash.name.slice(4), 10);
|
|
4576
|
-
}
|
|
4577
|
-
function checkHashLength(algorithm, expected) {
|
|
4578
|
-
if (getHashLength(algorithm.hash) !== expected) throw unusable(`SHA-${expected}`, "algorithm.hash");
|
|
4579
|
-
}
|
|
4580
|
-
function getNamedCurve(alg) {
|
|
4581
|
-
switch (alg) {
|
|
4582
|
-
case "ES256": return "P-256";
|
|
4583
|
-
case "ES384": return "P-384";
|
|
4584
|
-
case "ES512": return "P-521";
|
|
4585
|
-
default: throw new Error("unreachable");
|
|
4586
|
-
}
|
|
4587
|
-
}
|
|
4588
|
-
function checkUsage(key, usage) {
|
|
4589
|
-
if (usage && !key.usages.includes(usage)) throw new TypeError(`CryptoKey does not support this operation, its usages must include ${usage}.`);
|
|
4590
|
-
}
|
|
4591
|
-
function checkSigCryptoKey(key, alg, usage) {
|
|
4592
|
-
switch (alg) {
|
|
4593
|
-
case "HS256":
|
|
4594
|
-
case "HS384":
|
|
4595
|
-
case "HS512":
|
|
4596
|
-
if (!isAlgorithm(key.algorithm, "HMAC")) throw unusable("HMAC");
|
|
4597
|
-
checkHashLength(key.algorithm, parseInt(alg.slice(2), 10));
|
|
4598
|
-
break;
|
|
4599
|
-
case "RS256":
|
|
4600
|
-
case "RS384":
|
|
4601
|
-
case "RS512":
|
|
4602
|
-
if (!isAlgorithm(key.algorithm, "RSASSA-PKCS1-v1_5")) throw unusable("RSASSA-PKCS1-v1_5");
|
|
4603
|
-
checkHashLength(key.algorithm, parseInt(alg.slice(2), 10));
|
|
4604
|
-
break;
|
|
4605
|
-
case "PS256":
|
|
4606
|
-
case "PS384":
|
|
4607
|
-
case "PS512":
|
|
4608
|
-
if (!isAlgorithm(key.algorithm, "RSA-PSS")) throw unusable("RSA-PSS");
|
|
4609
|
-
checkHashLength(key.algorithm, parseInt(alg.slice(2), 10));
|
|
4610
|
-
break;
|
|
4611
|
-
case "Ed25519":
|
|
4612
|
-
case "EdDSA":
|
|
4613
|
-
if (!isAlgorithm(key.algorithm, "Ed25519")) throw unusable("Ed25519");
|
|
4614
|
-
break;
|
|
4615
|
-
case "ML-DSA-44":
|
|
4616
|
-
case "ML-DSA-65":
|
|
4617
|
-
case "ML-DSA-87":
|
|
4618
|
-
if (!isAlgorithm(key.algorithm, alg)) throw unusable(alg);
|
|
4619
|
-
break;
|
|
4620
|
-
case "ES256":
|
|
4621
|
-
case "ES384":
|
|
4622
|
-
case "ES512": {
|
|
4623
|
-
if (!isAlgorithm(key.algorithm, "ECDSA")) throw unusable("ECDSA");
|
|
4624
|
-
const expected = getNamedCurve(alg);
|
|
4625
|
-
if (key.algorithm.namedCurve !== expected) throw unusable(expected, "algorithm.namedCurve");
|
|
4626
|
-
break;
|
|
4627
|
-
}
|
|
4628
|
-
default: throw new TypeError("CryptoKey does not support this operation");
|
|
4629
|
-
}
|
|
4630
|
-
checkUsage(key, usage);
|
|
4631
|
-
}
|
|
4632
|
-
//#endregion
|
|
4633
|
-
//#region node_modules/.pnpm/jose@6.2.1/node_modules/jose/dist/webapi/lib/invalid_key_input.js
|
|
4634
|
-
function message(msg, actual, ...types) {
|
|
4635
|
-
types = types.filter(Boolean);
|
|
4636
|
-
if (types.length > 2) {
|
|
4637
|
-
const last = types.pop();
|
|
4638
|
-
msg += `one of type ${types.join(", ")}, or ${last}.`;
|
|
4639
|
-
} else if (types.length === 2) msg += `one of type ${types[0]} or ${types[1]}.`;
|
|
4640
|
-
else msg += `of type ${types[0]}.`;
|
|
4641
|
-
if (actual == null) msg += ` Received ${actual}`;
|
|
4642
|
-
else if (typeof actual === "function" && actual.name) msg += ` Received function ${actual.name}`;
|
|
4643
|
-
else if (typeof actual === "object" && actual != null) {
|
|
4644
|
-
if (actual.constructor?.name) msg += ` Received an instance of ${actual.constructor.name}`;
|
|
4645
|
-
}
|
|
4646
|
-
return msg;
|
|
4647
|
-
}
|
|
4648
|
-
const invalidKeyInput = (actual, ...types) => message("Key must be ", actual, ...types);
|
|
4649
|
-
const withAlg = (alg, actual, ...types) => message(`Key for the ${alg} algorithm must be `, actual, ...types);
|
|
4650
|
-
//#endregion
|
|
4651
|
-
//#region node_modules/.pnpm/jose@6.2.1/node_modules/jose/dist/webapi/util/errors.js
|
|
4652
|
-
var JOSEError = class extends Error {
|
|
4653
|
-
static code = "ERR_JOSE_GENERIC";
|
|
4654
|
-
code = "ERR_JOSE_GENERIC";
|
|
4655
|
-
constructor(message, options) {
|
|
4656
|
-
super(message, options);
|
|
4657
|
-
this.name = this.constructor.name;
|
|
4658
|
-
Error.captureStackTrace?.(this, this.constructor);
|
|
4659
|
-
}
|
|
4660
|
-
};
|
|
4661
|
-
var JWTClaimValidationFailed = class extends JOSEError {
|
|
4662
|
-
static code = "ERR_JWT_CLAIM_VALIDATION_FAILED";
|
|
4663
|
-
code = "ERR_JWT_CLAIM_VALIDATION_FAILED";
|
|
4664
|
-
claim;
|
|
4665
|
-
reason;
|
|
4666
|
-
payload;
|
|
4667
|
-
constructor(message, payload, claim = "unspecified", reason = "unspecified") {
|
|
4668
|
-
super(message, { cause: {
|
|
4669
|
-
claim,
|
|
4670
|
-
reason,
|
|
4671
|
-
payload
|
|
4672
|
-
} });
|
|
4673
|
-
this.claim = claim;
|
|
4674
|
-
this.reason = reason;
|
|
4675
|
-
this.payload = payload;
|
|
4676
|
-
}
|
|
4677
|
-
};
|
|
4678
|
-
var JWTExpired = class extends JOSEError {
|
|
4679
|
-
static code = "ERR_JWT_EXPIRED";
|
|
4680
|
-
code = "ERR_JWT_EXPIRED";
|
|
4681
|
-
claim;
|
|
4682
|
-
reason;
|
|
4683
|
-
payload;
|
|
4684
|
-
constructor(message, payload, claim = "unspecified", reason = "unspecified") {
|
|
4685
|
-
super(message, { cause: {
|
|
4686
|
-
claim,
|
|
4687
|
-
reason,
|
|
4688
|
-
payload
|
|
4689
|
-
} });
|
|
4690
|
-
this.claim = claim;
|
|
4691
|
-
this.reason = reason;
|
|
4692
|
-
this.payload = payload;
|
|
4693
|
-
}
|
|
4694
|
-
};
|
|
4695
|
-
var JOSEAlgNotAllowed = class extends JOSEError {
|
|
4696
|
-
static code = "ERR_JOSE_ALG_NOT_ALLOWED";
|
|
4697
|
-
code = "ERR_JOSE_ALG_NOT_ALLOWED";
|
|
4698
|
-
};
|
|
4699
|
-
var JOSENotSupported = class extends JOSEError {
|
|
4700
|
-
static code = "ERR_JOSE_NOT_SUPPORTED";
|
|
4701
|
-
code = "ERR_JOSE_NOT_SUPPORTED";
|
|
4702
|
-
};
|
|
4703
|
-
var JWSInvalid = class extends JOSEError {
|
|
4704
|
-
static code = "ERR_JWS_INVALID";
|
|
4705
|
-
code = "ERR_JWS_INVALID";
|
|
4706
|
-
};
|
|
4707
|
-
var JWTInvalid = class extends JOSEError {
|
|
4708
|
-
static code = "ERR_JWT_INVALID";
|
|
4709
|
-
code = "ERR_JWT_INVALID";
|
|
4710
|
-
};
|
|
4711
|
-
Symbol.asyncIterator;
|
|
4712
|
-
var JWSSignatureVerificationFailed = class extends JOSEError {
|
|
4713
|
-
static code = "ERR_JWS_SIGNATURE_VERIFICATION_FAILED";
|
|
4714
|
-
code = "ERR_JWS_SIGNATURE_VERIFICATION_FAILED";
|
|
4715
|
-
constructor(message = "signature verification failed", options) {
|
|
4716
|
-
super(message, options);
|
|
4717
|
-
}
|
|
4718
|
-
};
|
|
4719
|
-
//#endregion
|
|
4720
|
-
//#region node_modules/.pnpm/jose@6.2.1/node_modules/jose/dist/webapi/lib/is_key_like.js
|
|
4721
|
-
const isCryptoKey = (key) => {
|
|
4722
|
-
if (key?.[Symbol.toStringTag] === "CryptoKey") return true;
|
|
4723
|
-
try {
|
|
4724
|
-
return key instanceof CryptoKey;
|
|
4725
|
-
} catch {
|
|
4726
|
-
return false;
|
|
4727
|
-
}
|
|
4728
|
-
};
|
|
4729
|
-
const isKeyObject = (key) => key?.[Symbol.toStringTag] === "KeyObject";
|
|
4730
|
-
const isKeyLike = (key) => isCryptoKey(key) || isKeyObject(key);
|
|
4731
|
-
//#endregion
|
|
4732
|
-
//#region node_modules/.pnpm/jose@6.2.1/node_modules/jose/dist/webapi/lib/helpers.js
|
|
4733
|
-
function assertNotSet(value, name) {
|
|
4734
|
-
if (value) throw new TypeError(`${name} can only be called once`);
|
|
4735
|
-
}
|
|
4736
|
-
function decodeBase64url(value, label, ErrorClass) {
|
|
4737
|
-
try {
|
|
4738
|
-
return decode(value);
|
|
4739
|
-
} catch {
|
|
4740
|
-
throw new ErrorClass(`Failed to base64url decode the ${label}`);
|
|
4741
|
-
}
|
|
4742
|
-
}
|
|
4743
|
-
//#endregion
|
|
4744
|
-
//#region node_modules/.pnpm/jose@6.2.1/node_modules/jose/dist/webapi/lib/type_checks.js
|
|
4745
|
-
const isObjectLike = (value) => typeof value === "object" && value !== null;
|
|
4746
|
-
function isObject(input) {
|
|
4747
|
-
if (!isObjectLike(input) || Object.prototype.toString.call(input) !== "[object Object]") return false;
|
|
4748
|
-
if (Object.getPrototypeOf(input) === null) return true;
|
|
4749
|
-
let proto = input;
|
|
4750
|
-
while (Object.getPrototypeOf(proto) !== null) proto = Object.getPrototypeOf(proto);
|
|
4751
|
-
return Object.getPrototypeOf(input) === proto;
|
|
4752
|
-
}
|
|
4753
|
-
function isDisjoint(...headers) {
|
|
4754
|
-
const sources = headers.filter(Boolean);
|
|
4755
|
-
if (sources.length === 0 || sources.length === 1) return true;
|
|
4756
|
-
let acc;
|
|
4757
|
-
for (const header of sources) {
|
|
4758
|
-
const parameters = Object.keys(header);
|
|
4759
|
-
if (!acc || acc.size === 0) {
|
|
4760
|
-
acc = new Set(parameters);
|
|
4761
|
-
continue;
|
|
4762
|
-
}
|
|
4763
|
-
for (const parameter of parameters) {
|
|
4764
|
-
if (acc.has(parameter)) return false;
|
|
4765
|
-
acc.add(parameter);
|
|
4766
|
-
}
|
|
4767
|
-
}
|
|
4768
|
-
return true;
|
|
4769
|
-
}
|
|
4770
|
-
const isJWK = (key) => isObject(key) && typeof key.kty === "string";
|
|
4771
|
-
const isPrivateJWK = (key) => key.kty !== "oct" && (key.kty === "AKP" && typeof key.priv === "string" || typeof key.d === "string");
|
|
4772
|
-
const isPublicJWK = (key) => key.kty !== "oct" && key.d === void 0 && key.priv === void 0;
|
|
4773
|
-
const isSecretJWK = (key) => key.kty === "oct" && typeof key.k === "string";
|
|
4774
|
-
//#endregion
|
|
4775
|
-
//#region node_modules/.pnpm/jose@6.2.1/node_modules/jose/dist/webapi/lib/signing.js
|
|
4776
|
-
function checkKeyLength(alg, key) {
|
|
4777
|
-
if (alg.startsWith("RS") || alg.startsWith("PS")) {
|
|
4778
|
-
const { modulusLength } = key.algorithm;
|
|
4779
|
-
if (typeof modulusLength !== "number" || modulusLength < 2048) throw new TypeError(`${alg} requires key modulusLength to be 2048 bits or larger`);
|
|
4780
|
-
}
|
|
4781
|
-
}
|
|
4782
|
-
function subtleAlgorithm(alg, algorithm) {
|
|
4783
|
-
const hash = `SHA-${alg.slice(-3)}`;
|
|
4784
|
-
switch (alg) {
|
|
4785
|
-
case "HS256":
|
|
4786
|
-
case "HS384":
|
|
4787
|
-
case "HS512": return {
|
|
4788
|
-
hash,
|
|
4789
|
-
name: "HMAC"
|
|
4790
|
-
};
|
|
4791
|
-
case "PS256":
|
|
4792
|
-
case "PS384":
|
|
4793
|
-
case "PS512": return {
|
|
4794
|
-
hash,
|
|
4795
|
-
name: "RSA-PSS",
|
|
4796
|
-
saltLength: parseInt(alg.slice(-3), 10) >> 3
|
|
4797
|
-
};
|
|
4798
|
-
case "RS256":
|
|
4799
|
-
case "RS384":
|
|
4800
|
-
case "RS512": return {
|
|
4801
|
-
hash,
|
|
4802
|
-
name: "RSASSA-PKCS1-v1_5"
|
|
4803
|
-
};
|
|
4804
|
-
case "ES256":
|
|
4805
|
-
case "ES384":
|
|
4806
|
-
case "ES512": return {
|
|
4807
|
-
hash,
|
|
4808
|
-
name: "ECDSA",
|
|
4809
|
-
namedCurve: algorithm.namedCurve
|
|
4810
|
-
};
|
|
4811
|
-
case "Ed25519":
|
|
4812
|
-
case "EdDSA": return { name: "Ed25519" };
|
|
4813
|
-
case "ML-DSA-44":
|
|
4814
|
-
case "ML-DSA-65":
|
|
4815
|
-
case "ML-DSA-87": return { name: alg };
|
|
4816
|
-
default: throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`);
|
|
4817
|
-
}
|
|
4818
|
-
}
|
|
4819
|
-
async function getSigKey(alg, key, usage) {
|
|
4820
|
-
if (key instanceof Uint8Array) {
|
|
4821
|
-
if (!alg.startsWith("HS")) throw new TypeError(invalidKeyInput(key, "CryptoKey", "KeyObject", "JSON Web Key"));
|
|
4822
|
-
return crypto.subtle.importKey("raw", key, {
|
|
4823
|
-
hash: `SHA-${alg.slice(-3)}`,
|
|
4824
|
-
name: "HMAC"
|
|
4825
|
-
}, false, [usage]);
|
|
4826
|
-
}
|
|
4827
|
-
checkSigCryptoKey(key, alg, usage);
|
|
4828
|
-
return key;
|
|
4829
|
-
}
|
|
4830
|
-
async function sign(alg, key, data) {
|
|
4831
|
-
const cryptoKey = await getSigKey(alg, key, "sign");
|
|
4832
|
-
checkKeyLength(alg, cryptoKey);
|
|
4833
|
-
const signature = await crypto.subtle.sign(subtleAlgorithm(alg, cryptoKey.algorithm), cryptoKey, data);
|
|
4834
|
-
return new Uint8Array(signature);
|
|
4835
|
-
}
|
|
4836
|
-
async function verify(alg, key, signature, data) {
|
|
4837
|
-
const cryptoKey = await getSigKey(alg, key, "verify");
|
|
4838
|
-
checkKeyLength(alg, cryptoKey);
|
|
4839
|
-
const algorithm = subtleAlgorithm(alg, cryptoKey.algorithm);
|
|
4840
|
-
try {
|
|
4841
|
-
return await crypto.subtle.verify(algorithm, cryptoKey, signature, data);
|
|
4842
|
-
} catch {
|
|
4843
|
-
return false;
|
|
4844
|
-
}
|
|
4845
|
-
}
|
|
4846
|
-
//#endregion
|
|
4847
|
-
//#region node_modules/.pnpm/jose@6.2.1/node_modules/jose/dist/webapi/lib/jwk_to_key.js
|
|
4848
|
-
const unsupportedAlg = "Invalid or unsupported JWK \"alg\" (Algorithm) Parameter value";
|
|
4849
|
-
function subtleMapping(jwk) {
|
|
4850
|
-
let algorithm;
|
|
4851
|
-
let keyUsages;
|
|
4852
|
-
switch (jwk.kty) {
|
|
4853
|
-
case "AKP":
|
|
4854
|
-
switch (jwk.alg) {
|
|
4855
|
-
case "ML-DSA-44":
|
|
4856
|
-
case "ML-DSA-65":
|
|
4857
|
-
case "ML-DSA-87":
|
|
4858
|
-
algorithm = { name: jwk.alg };
|
|
4859
|
-
keyUsages = jwk.priv ? ["sign"] : ["verify"];
|
|
4860
|
-
break;
|
|
4861
|
-
default: throw new JOSENotSupported(unsupportedAlg);
|
|
4862
|
-
}
|
|
4863
|
-
break;
|
|
4864
|
-
case "RSA":
|
|
4865
|
-
switch (jwk.alg) {
|
|
4866
|
-
case "PS256":
|
|
4867
|
-
case "PS384":
|
|
4868
|
-
case "PS512":
|
|
4869
|
-
algorithm = {
|
|
4870
|
-
name: "RSA-PSS",
|
|
4871
|
-
hash: `SHA-${jwk.alg.slice(-3)}`
|
|
4872
|
-
};
|
|
4873
|
-
keyUsages = jwk.d ? ["sign"] : ["verify"];
|
|
4874
|
-
break;
|
|
4875
|
-
case "RS256":
|
|
4876
|
-
case "RS384":
|
|
4877
|
-
case "RS512":
|
|
4878
|
-
algorithm = {
|
|
4879
|
-
name: "RSASSA-PKCS1-v1_5",
|
|
4880
|
-
hash: `SHA-${jwk.alg.slice(-3)}`
|
|
4881
|
-
};
|
|
4882
|
-
keyUsages = jwk.d ? ["sign"] : ["verify"];
|
|
4883
|
-
break;
|
|
4884
|
-
case "RSA-OAEP":
|
|
4885
|
-
case "RSA-OAEP-256":
|
|
4886
|
-
case "RSA-OAEP-384":
|
|
4887
|
-
case "RSA-OAEP-512":
|
|
4888
|
-
algorithm = {
|
|
4889
|
-
name: "RSA-OAEP",
|
|
4890
|
-
hash: `SHA-${parseInt(jwk.alg.slice(-3), 10) || 1}`
|
|
4891
|
-
};
|
|
4892
|
-
keyUsages = jwk.d ? ["decrypt", "unwrapKey"] : ["encrypt", "wrapKey"];
|
|
4893
|
-
break;
|
|
4894
|
-
default: throw new JOSENotSupported(unsupportedAlg);
|
|
4895
|
-
}
|
|
4896
|
-
break;
|
|
4897
|
-
case "EC":
|
|
4898
|
-
switch (jwk.alg) {
|
|
4899
|
-
case "ES256":
|
|
4900
|
-
case "ES384":
|
|
4901
|
-
case "ES512":
|
|
4902
|
-
algorithm = {
|
|
4903
|
-
name: "ECDSA",
|
|
4904
|
-
namedCurve: {
|
|
4905
|
-
ES256: "P-256",
|
|
4906
|
-
ES384: "P-384",
|
|
4907
|
-
ES512: "P-521"
|
|
4908
|
-
}[jwk.alg]
|
|
4909
|
-
};
|
|
4910
|
-
keyUsages = jwk.d ? ["sign"] : ["verify"];
|
|
4911
|
-
break;
|
|
4912
|
-
case "ECDH-ES":
|
|
4913
|
-
case "ECDH-ES+A128KW":
|
|
4914
|
-
case "ECDH-ES+A192KW":
|
|
4915
|
-
case "ECDH-ES+A256KW":
|
|
4916
|
-
algorithm = {
|
|
4917
|
-
name: "ECDH",
|
|
4918
|
-
namedCurve: jwk.crv
|
|
4919
|
-
};
|
|
4920
|
-
keyUsages = jwk.d ? ["deriveBits"] : [];
|
|
4921
|
-
break;
|
|
4922
|
-
default: throw new JOSENotSupported(unsupportedAlg);
|
|
4923
|
-
}
|
|
4924
|
-
break;
|
|
4925
|
-
case "OKP":
|
|
4926
|
-
switch (jwk.alg) {
|
|
4927
|
-
case "Ed25519":
|
|
4928
|
-
case "EdDSA":
|
|
4929
|
-
algorithm = { name: "Ed25519" };
|
|
4930
|
-
keyUsages = jwk.d ? ["sign"] : ["verify"];
|
|
4931
|
-
break;
|
|
4932
|
-
case "ECDH-ES":
|
|
4933
|
-
case "ECDH-ES+A128KW":
|
|
4934
|
-
case "ECDH-ES+A192KW":
|
|
4935
|
-
case "ECDH-ES+A256KW":
|
|
4936
|
-
algorithm = { name: jwk.crv };
|
|
4937
|
-
keyUsages = jwk.d ? ["deriveBits"] : [];
|
|
4938
|
-
break;
|
|
4939
|
-
default: throw new JOSENotSupported(unsupportedAlg);
|
|
4940
|
-
}
|
|
4941
|
-
break;
|
|
4942
|
-
default: throw new JOSENotSupported("Invalid or unsupported JWK \"kty\" (Key Type) Parameter value");
|
|
4943
|
-
}
|
|
4944
|
-
return {
|
|
4945
|
-
algorithm,
|
|
4946
|
-
keyUsages
|
|
4947
|
-
};
|
|
4948
|
-
}
|
|
4949
|
-
async function jwkToKey(jwk) {
|
|
4950
|
-
if (!jwk.alg) throw new TypeError("\"alg\" argument is required when \"jwk.alg\" is not present");
|
|
4951
|
-
const { algorithm, keyUsages } = subtleMapping(jwk);
|
|
4952
|
-
const keyData = { ...jwk };
|
|
4953
|
-
if (keyData.kty !== "AKP") delete keyData.alg;
|
|
4954
|
-
delete keyData.use;
|
|
4955
|
-
return crypto.subtle.importKey("jwk", keyData, algorithm, jwk.ext ?? (jwk.d || jwk.priv ? false : true), jwk.key_ops ?? keyUsages);
|
|
4956
|
-
}
|
|
4957
|
-
//#endregion
|
|
4958
|
-
//#region node_modules/.pnpm/jose@6.2.1/node_modules/jose/dist/webapi/lib/normalize_key.js
|
|
4959
|
-
const unusableForAlg = "given KeyObject instance cannot be used for this algorithm";
|
|
4960
|
-
let cache;
|
|
4961
|
-
const handleJWK = async (key, jwk, alg, freeze = false) => {
|
|
4962
|
-
cache ||= /* @__PURE__ */ new WeakMap();
|
|
4963
|
-
let cached = cache.get(key);
|
|
4964
|
-
if (cached?.[alg]) return cached[alg];
|
|
4965
|
-
const cryptoKey = await jwkToKey({
|
|
4966
|
-
...jwk,
|
|
4967
|
-
alg
|
|
4968
|
-
});
|
|
4969
|
-
if (freeze) Object.freeze(key);
|
|
4970
|
-
if (!cached) cache.set(key, { [alg]: cryptoKey });
|
|
4971
|
-
else cached[alg] = cryptoKey;
|
|
4972
|
-
return cryptoKey;
|
|
4973
|
-
};
|
|
4974
|
-
const handleKeyObject = (keyObject, alg) => {
|
|
4975
|
-
cache ||= /* @__PURE__ */ new WeakMap();
|
|
4976
|
-
let cached = cache.get(keyObject);
|
|
4977
|
-
if (cached?.[alg]) return cached[alg];
|
|
4978
|
-
const isPublic = keyObject.type === "public";
|
|
4979
|
-
const extractable = isPublic ? true : false;
|
|
4980
|
-
let cryptoKey;
|
|
4981
|
-
if (keyObject.asymmetricKeyType === "x25519") {
|
|
4982
|
-
switch (alg) {
|
|
4983
|
-
case "ECDH-ES":
|
|
4984
|
-
case "ECDH-ES+A128KW":
|
|
4985
|
-
case "ECDH-ES+A192KW":
|
|
4986
|
-
case "ECDH-ES+A256KW": break;
|
|
4987
|
-
default: throw new TypeError(unusableForAlg);
|
|
4988
|
-
}
|
|
4989
|
-
cryptoKey = keyObject.toCryptoKey(keyObject.asymmetricKeyType, extractable, isPublic ? [] : ["deriveBits"]);
|
|
4990
|
-
}
|
|
4991
|
-
if (keyObject.asymmetricKeyType === "ed25519") {
|
|
4992
|
-
if (alg !== "EdDSA" && alg !== "Ed25519") throw new TypeError(unusableForAlg);
|
|
4993
|
-
cryptoKey = keyObject.toCryptoKey(keyObject.asymmetricKeyType, extractable, [isPublic ? "verify" : "sign"]);
|
|
4994
|
-
}
|
|
4995
|
-
switch (keyObject.asymmetricKeyType) {
|
|
4996
|
-
case "ml-dsa-44":
|
|
4997
|
-
case "ml-dsa-65":
|
|
4998
|
-
case "ml-dsa-87":
|
|
4999
|
-
if (alg !== keyObject.asymmetricKeyType.toUpperCase()) throw new TypeError(unusableForAlg);
|
|
5000
|
-
cryptoKey = keyObject.toCryptoKey(keyObject.asymmetricKeyType, extractable, [isPublic ? "verify" : "sign"]);
|
|
5001
|
-
}
|
|
5002
|
-
if (keyObject.asymmetricKeyType === "rsa") {
|
|
5003
|
-
let hash;
|
|
5004
|
-
switch (alg) {
|
|
5005
|
-
case "RSA-OAEP":
|
|
5006
|
-
hash = "SHA-1";
|
|
5007
|
-
break;
|
|
5008
|
-
case "RS256":
|
|
5009
|
-
case "PS256":
|
|
5010
|
-
case "RSA-OAEP-256":
|
|
5011
|
-
hash = "SHA-256";
|
|
5012
|
-
break;
|
|
5013
|
-
case "RS384":
|
|
5014
|
-
case "PS384":
|
|
5015
|
-
case "RSA-OAEP-384":
|
|
5016
|
-
hash = "SHA-384";
|
|
5017
|
-
break;
|
|
5018
|
-
case "RS512":
|
|
5019
|
-
case "PS512":
|
|
5020
|
-
case "RSA-OAEP-512":
|
|
5021
|
-
hash = "SHA-512";
|
|
5022
|
-
break;
|
|
5023
|
-
default: throw new TypeError(unusableForAlg);
|
|
5024
|
-
}
|
|
5025
|
-
if (alg.startsWith("RSA-OAEP")) return keyObject.toCryptoKey({
|
|
5026
|
-
name: "RSA-OAEP",
|
|
5027
|
-
hash
|
|
5028
|
-
}, extractable, isPublic ? ["encrypt"] : ["decrypt"]);
|
|
5029
|
-
cryptoKey = keyObject.toCryptoKey({
|
|
5030
|
-
name: alg.startsWith("PS") ? "RSA-PSS" : "RSASSA-PKCS1-v1_5",
|
|
5031
|
-
hash
|
|
5032
|
-
}, extractable, [isPublic ? "verify" : "sign"]);
|
|
5033
|
-
}
|
|
5034
|
-
if (keyObject.asymmetricKeyType === "ec") {
|
|
5035
|
-
const namedCurve = new Map([
|
|
5036
|
-
["prime256v1", "P-256"],
|
|
5037
|
-
["secp384r1", "P-384"],
|
|
5038
|
-
["secp521r1", "P-521"]
|
|
5039
|
-
]).get(keyObject.asymmetricKeyDetails?.namedCurve);
|
|
5040
|
-
if (!namedCurve) throw new TypeError(unusableForAlg);
|
|
5041
|
-
const expectedCurve = {
|
|
5042
|
-
ES256: "P-256",
|
|
5043
|
-
ES384: "P-384",
|
|
5044
|
-
ES512: "P-521"
|
|
5045
|
-
};
|
|
5046
|
-
if (expectedCurve[alg] && namedCurve === expectedCurve[alg]) cryptoKey = keyObject.toCryptoKey({
|
|
5047
|
-
name: "ECDSA",
|
|
5048
|
-
namedCurve
|
|
5049
|
-
}, extractable, [isPublic ? "verify" : "sign"]);
|
|
5050
|
-
if (alg.startsWith("ECDH-ES")) cryptoKey = keyObject.toCryptoKey({
|
|
5051
|
-
name: "ECDH",
|
|
5052
|
-
namedCurve
|
|
5053
|
-
}, extractable, isPublic ? [] : ["deriveBits"]);
|
|
5054
|
-
}
|
|
5055
|
-
if (!cryptoKey) throw new TypeError(unusableForAlg);
|
|
5056
|
-
if (!cached) cache.set(keyObject, { [alg]: cryptoKey });
|
|
5057
|
-
else cached[alg] = cryptoKey;
|
|
5058
|
-
return cryptoKey;
|
|
5059
|
-
};
|
|
5060
|
-
async function normalizeKey(key, alg) {
|
|
5061
|
-
if (key instanceof Uint8Array) return key;
|
|
5062
|
-
if (isCryptoKey(key)) return key;
|
|
5063
|
-
if (isKeyObject(key)) {
|
|
5064
|
-
if (key.type === "secret") return key.export();
|
|
5065
|
-
if ("toCryptoKey" in key && typeof key.toCryptoKey === "function") try {
|
|
5066
|
-
return handleKeyObject(key, alg);
|
|
5067
|
-
} catch (err) {
|
|
5068
|
-
if (err instanceof TypeError) throw err;
|
|
5069
|
-
}
|
|
5070
|
-
return handleJWK(key, key.export({ format: "jwk" }), alg);
|
|
5071
|
-
}
|
|
5072
|
-
if (isJWK(key)) {
|
|
5073
|
-
if (key.k) return decode(key.k);
|
|
5074
|
-
return handleJWK(key, key, alg, true);
|
|
5075
|
-
}
|
|
5076
|
-
throw new Error("unreachable");
|
|
5077
|
-
}
|
|
5078
|
-
//#endregion
|
|
5079
|
-
//#region node_modules/.pnpm/jose@6.2.1/node_modules/jose/dist/webapi/lib/validate_crit.js
|
|
5080
|
-
function validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) {
|
|
5081
|
-
if (joseHeader.crit !== void 0 && protectedHeader?.crit === void 0) throw new Err("\"crit\" (Critical) Header Parameter MUST be integrity protected");
|
|
5082
|
-
if (!protectedHeader || protectedHeader.crit === void 0) return /* @__PURE__ */ new Set();
|
|
5083
|
-
if (!Array.isArray(protectedHeader.crit) || protectedHeader.crit.length === 0 || protectedHeader.crit.some((input) => typeof input !== "string" || input.length === 0)) throw new Err("\"crit\" (Critical) Header Parameter MUST be an array of non-empty strings when present");
|
|
5084
|
-
let recognized;
|
|
5085
|
-
if (recognizedOption !== void 0) recognized = new Map([...Object.entries(recognizedOption), ...recognizedDefault.entries()]);
|
|
5086
|
-
else recognized = recognizedDefault;
|
|
5087
|
-
for (const parameter of protectedHeader.crit) {
|
|
5088
|
-
if (!recognized.has(parameter)) throw new JOSENotSupported(`Extension Header Parameter "${parameter}" is not recognized`);
|
|
5089
|
-
if (joseHeader[parameter] === void 0) throw new Err(`Extension Header Parameter "${parameter}" is missing`);
|
|
5090
|
-
if (recognized.get(parameter) && protectedHeader[parameter] === void 0) throw new Err(`Extension Header Parameter "${parameter}" MUST be integrity protected`);
|
|
5091
|
-
}
|
|
5092
|
-
return new Set(protectedHeader.crit);
|
|
5093
|
-
}
|
|
5094
|
-
//#endregion
|
|
5095
|
-
//#region node_modules/.pnpm/jose@6.2.1/node_modules/jose/dist/webapi/lib/validate_algorithms.js
|
|
5096
|
-
function validateAlgorithms(option, algorithms) {
|
|
5097
|
-
if (algorithms !== void 0 && (!Array.isArray(algorithms) || algorithms.some((s) => typeof s !== "string"))) throw new TypeError(`"${option}" option must be an array of strings`);
|
|
5098
|
-
if (!algorithms) return;
|
|
5099
|
-
return new Set(algorithms);
|
|
5100
|
-
}
|
|
5101
|
-
//#endregion
|
|
5102
|
-
//#region node_modules/.pnpm/jose@6.2.1/node_modules/jose/dist/webapi/lib/check_key_type.js
|
|
5103
|
-
const tag = (key) => key?.[Symbol.toStringTag];
|
|
5104
|
-
const jwkMatchesOp = (alg, key, usage) => {
|
|
5105
|
-
if (key.use !== void 0) {
|
|
5106
|
-
let expected;
|
|
5107
|
-
switch (usage) {
|
|
5108
|
-
case "sign":
|
|
5109
|
-
case "verify":
|
|
5110
|
-
expected = "sig";
|
|
5111
|
-
break;
|
|
5112
|
-
case "encrypt":
|
|
5113
|
-
case "decrypt":
|
|
5114
|
-
expected = "enc";
|
|
5115
|
-
break;
|
|
5116
|
-
}
|
|
5117
|
-
if (key.use !== expected) throw new TypeError(`Invalid key for this operation, its "use" must be "${expected}" when present`);
|
|
5118
|
-
}
|
|
5119
|
-
if (key.alg !== void 0 && key.alg !== alg) throw new TypeError(`Invalid key for this operation, its "alg" must be "${alg}" when present`);
|
|
5120
|
-
if (Array.isArray(key.key_ops)) {
|
|
5121
|
-
let expectedKeyOp;
|
|
5122
|
-
switch (true) {
|
|
5123
|
-
case usage === "sign" || usage === "verify":
|
|
5124
|
-
case alg === "dir":
|
|
5125
|
-
case alg.includes("CBC-HS"):
|
|
5126
|
-
expectedKeyOp = usage;
|
|
5127
|
-
break;
|
|
5128
|
-
case alg.startsWith("PBES2"):
|
|
5129
|
-
expectedKeyOp = "deriveBits";
|
|
5130
|
-
break;
|
|
5131
|
-
case /^A\d{3}(?:GCM)?(?:KW)?$/.test(alg):
|
|
5132
|
-
if (!alg.includes("GCM") && alg.endsWith("KW")) expectedKeyOp = usage === "encrypt" ? "wrapKey" : "unwrapKey";
|
|
5133
|
-
else expectedKeyOp = usage;
|
|
5134
|
-
break;
|
|
5135
|
-
case usage === "encrypt" && alg.startsWith("RSA"):
|
|
5136
|
-
expectedKeyOp = "wrapKey";
|
|
5137
|
-
break;
|
|
5138
|
-
case usage === "decrypt":
|
|
5139
|
-
expectedKeyOp = alg.startsWith("RSA") ? "unwrapKey" : "deriveBits";
|
|
5140
|
-
break;
|
|
5141
|
-
}
|
|
5142
|
-
if (expectedKeyOp && key.key_ops?.includes?.(expectedKeyOp) === false) throw new TypeError(`Invalid key for this operation, its "key_ops" must include "${expectedKeyOp}" when present`);
|
|
5143
|
-
}
|
|
5144
|
-
return true;
|
|
5145
|
-
};
|
|
5146
|
-
const symmetricTypeCheck = (alg, key, usage) => {
|
|
5147
|
-
if (key instanceof Uint8Array) return;
|
|
5148
|
-
if (isJWK(key)) {
|
|
5149
|
-
if (isSecretJWK(key) && jwkMatchesOp(alg, key, usage)) return;
|
|
5150
|
-
throw new TypeError(`JSON Web Key for symmetric algorithms must have JWK "kty" (Key Type) equal to "oct" and the JWK "k" (Key Value) present`);
|
|
5151
|
-
}
|
|
5152
|
-
if (!isKeyLike(key)) throw new TypeError(withAlg(alg, key, "CryptoKey", "KeyObject", "JSON Web Key", "Uint8Array"));
|
|
5153
|
-
if (key.type !== "secret") throw new TypeError(`${tag(key)} instances for symmetric algorithms must be of type "secret"`);
|
|
5154
|
-
};
|
|
5155
|
-
const asymmetricTypeCheck = (alg, key, usage) => {
|
|
5156
|
-
if (isJWK(key)) switch (usage) {
|
|
5157
|
-
case "decrypt":
|
|
5158
|
-
case "sign":
|
|
5159
|
-
if (isPrivateJWK(key) && jwkMatchesOp(alg, key, usage)) return;
|
|
5160
|
-
throw new TypeError(`JSON Web Key for this operation must be a private JWK`);
|
|
5161
|
-
case "encrypt":
|
|
5162
|
-
case "verify":
|
|
5163
|
-
if (isPublicJWK(key) && jwkMatchesOp(alg, key, usage)) return;
|
|
5164
|
-
throw new TypeError(`JSON Web Key for this operation must be a public JWK`);
|
|
5165
|
-
}
|
|
5166
|
-
if (!isKeyLike(key)) throw new TypeError(withAlg(alg, key, "CryptoKey", "KeyObject", "JSON Web Key"));
|
|
5167
|
-
if (key.type === "secret") throw new TypeError(`${tag(key)} instances for asymmetric algorithms must not be of type "secret"`);
|
|
5168
|
-
if (key.type === "public") switch (usage) {
|
|
5169
|
-
case "sign": throw new TypeError(`${tag(key)} instances for asymmetric algorithm signing must be of type "private"`);
|
|
5170
|
-
case "decrypt": throw new TypeError(`${tag(key)} instances for asymmetric algorithm decryption must be of type "private"`);
|
|
5171
|
-
}
|
|
5172
|
-
if (key.type === "private") switch (usage) {
|
|
5173
|
-
case "verify": throw new TypeError(`${tag(key)} instances for asymmetric algorithm verifying must be of type "public"`);
|
|
5174
|
-
case "encrypt": throw new TypeError(`${tag(key)} instances for asymmetric algorithm encryption must be of type "public"`);
|
|
5175
|
-
}
|
|
5176
|
-
};
|
|
5177
|
-
function checkKeyType(alg, key, usage) {
|
|
5178
|
-
switch (alg.substring(0, 2)) {
|
|
5179
|
-
case "A1":
|
|
5180
|
-
case "A2":
|
|
5181
|
-
case "di":
|
|
5182
|
-
case "HS":
|
|
5183
|
-
case "PB":
|
|
5184
|
-
symmetricTypeCheck(alg, key, usage);
|
|
5185
|
-
break;
|
|
5186
|
-
default: asymmetricTypeCheck(alg, key, usage);
|
|
5187
|
-
}
|
|
5188
|
-
}
|
|
5189
|
-
//#endregion
|
|
5190
|
-
//#region node_modules/.pnpm/jose@6.2.1/node_modules/jose/dist/webapi/jws/flattened/verify.js
|
|
5191
|
-
async function flattenedVerify(jws, key, options) {
|
|
5192
|
-
if (!isObject(jws)) throw new JWSInvalid("Flattened JWS must be an object");
|
|
5193
|
-
if (jws.protected === void 0 && jws.header === void 0) throw new JWSInvalid("Flattened JWS must have either of the \"protected\" or \"header\" members");
|
|
5194
|
-
if (jws.protected !== void 0 && typeof jws.protected !== "string") throw new JWSInvalid("JWS Protected Header incorrect type");
|
|
5195
|
-
if (jws.payload === void 0) throw new JWSInvalid("JWS Payload missing");
|
|
5196
|
-
if (typeof jws.signature !== "string") throw new JWSInvalid("JWS Signature missing or incorrect type");
|
|
5197
|
-
if (jws.header !== void 0 && !isObject(jws.header)) throw new JWSInvalid("JWS Unprotected Header incorrect type");
|
|
5198
|
-
let parsedProt = {};
|
|
5199
|
-
if (jws.protected) try {
|
|
5200
|
-
const protectedHeader = decode(jws.protected);
|
|
5201
|
-
parsedProt = JSON.parse(decoder.decode(protectedHeader));
|
|
5202
|
-
} catch {
|
|
5203
|
-
throw new JWSInvalid("JWS Protected Header is invalid");
|
|
5204
|
-
}
|
|
5205
|
-
if (!isDisjoint(parsedProt, jws.header)) throw new JWSInvalid("JWS Protected and JWS Unprotected Header Parameter names must be disjoint");
|
|
5206
|
-
const joseHeader = {
|
|
5207
|
-
...parsedProt,
|
|
5208
|
-
...jws.header
|
|
5209
|
-
};
|
|
5210
|
-
const extensions = validateCrit(JWSInvalid, new Map([["b64", true]]), options?.crit, parsedProt, joseHeader);
|
|
5211
|
-
let b64 = true;
|
|
5212
|
-
if (extensions.has("b64")) {
|
|
5213
|
-
b64 = parsedProt.b64;
|
|
5214
|
-
if (typeof b64 !== "boolean") throw new JWSInvalid("The \"b64\" (base64url-encode payload) Header Parameter must be a boolean");
|
|
5215
|
-
}
|
|
5216
|
-
const { alg } = joseHeader;
|
|
5217
|
-
if (typeof alg !== "string" || !alg) throw new JWSInvalid("JWS \"alg\" (Algorithm) Header Parameter missing or invalid");
|
|
5218
|
-
const algorithms = options && validateAlgorithms("algorithms", options.algorithms);
|
|
5219
|
-
if (algorithms && !algorithms.has(alg)) throw new JOSEAlgNotAllowed("\"alg\" (Algorithm) Header Parameter value not allowed");
|
|
5220
|
-
if (b64) {
|
|
5221
|
-
if (typeof jws.payload !== "string") throw new JWSInvalid("JWS Payload must be a string");
|
|
5222
|
-
} else if (typeof jws.payload !== "string" && !(jws.payload instanceof Uint8Array)) throw new JWSInvalid("JWS Payload must be a string or an Uint8Array instance");
|
|
5223
|
-
let resolvedKey = false;
|
|
5224
|
-
if (typeof key === "function") {
|
|
5225
|
-
key = await key(parsedProt, jws);
|
|
5226
|
-
resolvedKey = true;
|
|
5227
|
-
}
|
|
5228
|
-
checkKeyType(alg, key, "verify");
|
|
5229
|
-
const data = concat(jws.protected !== void 0 ? encode$1(jws.protected) : new Uint8Array(), encode$1("."), typeof jws.payload === "string" ? b64 ? encode$1(jws.payload) : encoder.encode(jws.payload) : jws.payload);
|
|
5230
|
-
const signature = decodeBase64url(jws.signature, "signature", JWSInvalid);
|
|
5231
|
-
const k = await normalizeKey(key, alg);
|
|
5232
|
-
if (!await verify(alg, k, signature, data)) throw new JWSSignatureVerificationFailed();
|
|
5233
|
-
let payload;
|
|
5234
|
-
if (b64) payload = decodeBase64url(jws.payload, "payload", JWSInvalid);
|
|
5235
|
-
else if (typeof jws.payload === "string") payload = encoder.encode(jws.payload);
|
|
5236
|
-
else payload = jws.payload;
|
|
5237
|
-
const result = { payload };
|
|
5238
|
-
if (jws.protected !== void 0) result.protectedHeader = parsedProt;
|
|
5239
|
-
if (jws.header !== void 0) result.unprotectedHeader = jws.header;
|
|
5240
|
-
if (resolvedKey) return {
|
|
5241
|
-
...result,
|
|
5242
|
-
key: k
|
|
5243
|
-
};
|
|
5244
|
-
return result;
|
|
5245
|
-
}
|
|
5246
|
-
//#endregion
|
|
5247
|
-
//#region node_modules/.pnpm/jose@6.2.1/node_modules/jose/dist/webapi/jws/compact/verify.js
|
|
5248
|
-
async function compactVerify(jws, key, options) {
|
|
5249
|
-
if (jws instanceof Uint8Array) jws = decoder.decode(jws);
|
|
5250
|
-
if (typeof jws !== "string") throw new JWSInvalid("Compact JWS must be a string or Uint8Array");
|
|
5251
|
-
const { 0: protectedHeader, 1: payload, 2: signature, length } = jws.split(".");
|
|
5252
|
-
if (length !== 3) throw new JWSInvalid("Invalid Compact JWS");
|
|
5253
|
-
const verified = await flattenedVerify({
|
|
5254
|
-
payload,
|
|
5255
|
-
protected: protectedHeader,
|
|
5256
|
-
signature
|
|
5257
|
-
}, key, options);
|
|
5258
|
-
const result = {
|
|
5259
|
-
payload: verified.payload,
|
|
5260
|
-
protectedHeader: verified.protectedHeader
|
|
5261
|
-
};
|
|
5262
|
-
if (typeof key === "function") return {
|
|
5263
|
-
...result,
|
|
5264
|
-
key: verified.key
|
|
5265
|
-
};
|
|
5266
|
-
return result;
|
|
5267
|
-
}
|
|
5268
|
-
//#endregion
|
|
5269
|
-
//#region node_modules/.pnpm/jose@6.2.1/node_modules/jose/dist/webapi/lib/jwt_claims_set.js
|
|
5270
|
-
const epoch = (date) => Math.floor(date.getTime() / 1e3);
|
|
5271
|
-
const minute = 60;
|
|
5272
|
-
const hour = minute * 60;
|
|
5273
|
-
const day = hour * 24;
|
|
5274
|
-
const week = day * 7;
|
|
5275
|
-
const year = day * 365.25;
|
|
5276
|
-
const REGEX = /^(\+|\-)? ?(\d+|\d+\.\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)(?: (ago|from now))?$/i;
|
|
5277
|
-
function secs(str) {
|
|
5278
|
-
const matched = REGEX.exec(str);
|
|
5279
|
-
if (!matched || matched[4] && matched[1]) throw new TypeError("Invalid time period format");
|
|
5280
|
-
const value = parseFloat(matched[2]);
|
|
5281
|
-
const unit = matched[3].toLowerCase();
|
|
5282
|
-
let numericDate;
|
|
5283
|
-
switch (unit) {
|
|
5284
|
-
case "sec":
|
|
5285
|
-
case "secs":
|
|
5286
|
-
case "second":
|
|
5287
|
-
case "seconds":
|
|
5288
|
-
case "s":
|
|
5289
|
-
numericDate = Math.round(value);
|
|
5290
|
-
break;
|
|
5291
|
-
case "minute":
|
|
5292
|
-
case "minutes":
|
|
5293
|
-
case "min":
|
|
5294
|
-
case "mins":
|
|
5295
|
-
case "m":
|
|
5296
|
-
numericDate = Math.round(value * minute);
|
|
5297
|
-
break;
|
|
5298
|
-
case "hour":
|
|
5299
|
-
case "hours":
|
|
5300
|
-
case "hr":
|
|
5301
|
-
case "hrs":
|
|
5302
|
-
case "h":
|
|
5303
|
-
numericDate = Math.round(value * hour);
|
|
5304
|
-
break;
|
|
5305
|
-
case "day":
|
|
5306
|
-
case "days":
|
|
5307
|
-
case "d":
|
|
5308
|
-
numericDate = Math.round(value * day);
|
|
5309
|
-
break;
|
|
5310
|
-
case "week":
|
|
5311
|
-
case "weeks":
|
|
5312
|
-
case "w":
|
|
5313
|
-
numericDate = Math.round(value * week);
|
|
5314
|
-
break;
|
|
5315
|
-
default:
|
|
5316
|
-
numericDate = Math.round(value * year);
|
|
5317
|
-
break;
|
|
5318
|
-
}
|
|
5319
|
-
if (matched[1] === "-" || matched[4] === "ago") return -numericDate;
|
|
5320
|
-
return numericDate;
|
|
5321
|
-
}
|
|
5322
|
-
function validateInput(label, input) {
|
|
5323
|
-
if (!Number.isFinite(input)) throw new TypeError(`Invalid ${label} input`);
|
|
5324
|
-
return input;
|
|
5325
|
-
}
|
|
5326
|
-
const normalizeTyp = (value) => {
|
|
5327
|
-
if (value.includes("/")) return value.toLowerCase();
|
|
5328
|
-
return `application/${value.toLowerCase()}`;
|
|
5329
|
-
};
|
|
5330
|
-
const checkAudiencePresence = (audPayload, audOption) => {
|
|
5331
|
-
if (typeof audPayload === "string") return audOption.includes(audPayload);
|
|
5332
|
-
if (Array.isArray(audPayload)) return audOption.some(Set.prototype.has.bind(new Set(audPayload)));
|
|
5333
|
-
return false;
|
|
5334
|
-
};
|
|
5335
|
-
function validateClaimsSet(protectedHeader, encodedPayload, options = {}) {
|
|
5336
|
-
let payload;
|
|
5337
|
-
try {
|
|
5338
|
-
payload = JSON.parse(decoder.decode(encodedPayload));
|
|
5339
|
-
} catch {}
|
|
5340
|
-
if (!isObject(payload)) throw new JWTInvalid("JWT Claims Set must be a top-level JSON object");
|
|
5341
|
-
const { typ } = options;
|
|
5342
|
-
if (typ && (typeof protectedHeader.typ !== "string" || normalizeTyp(protectedHeader.typ) !== normalizeTyp(typ))) throw new JWTClaimValidationFailed("unexpected \"typ\" JWT header value", payload, "typ", "check_failed");
|
|
5343
|
-
const { requiredClaims = [], issuer, subject, audience, maxTokenAge } = options;
|
|
5344
|
-
const presenceCheck = [...requiredClaims];
|
|
5345
|
-
if (maxTokenAge !== void 0) presenceCheck.push("iat");
|
|
5346
|
-
if (audience !== void 0) presenceCheck.push("aud");
|
|
5347
|
-
if (subject !== void 0) presenceCheck.push("sub");
|
|
5348
|
-
if (issuer !== void 0) presenceCheck.push("iss");
|
|
5349
|
-
for (const claim of new Set(presenceCheck.reverse())) if (!(claim in payload)) throw new JWTClaimValidationFailed(`missing required "${claim}" claim`, payload, claim, "missing");
|
|
5350
|
-
if (issuer && !(Array.isArray(issuer) ? issuer : [issuer]).includes(payload.iss)) throw new JWTClaimValidationFailed("unexpected \"iss\" claim value", payload, "iss", "check_failed");
|
|
5351
|
-
if (subject && payload.sub !== subject) throw new JWTClaimValidationFailed("unexpected \"sub\" claim value", payload, "sub", "check_failed");
|
|
5352
|
-
if (audience && !checkAudiencePresence(payload.aud, typeof audience === "string" ? [audience] : audience)) throw new JWTClaimValidationFailed("unexpected \"aud\" claim value", payload, "aud", "check_failed");
|
|
5353
|
-
let tolerance;
|
|
5354
|
-
switch (typeof options.clockTolerance) {
|
|
5355
|
-
case "string":
|
|
5356
|
-
tolerance = secs(options.clockTolerance);
|
|
5357
|
-
break;
|
|
5358
|
-
case "number":
|
|
5359
|
-
tolerance = options.clockTolerance;
|
|
5360
|
-
break;
|
|
5361
|
-
case "undefined":
|
|
5362
|
-
tolerance = 0;
|
|
5363
|
-
break;
|
|
5364
|
-
default: throw new TypeError("Invalid clockTolerance option type");
|
|
5365
|
-
}
|
|
5366
|
-
const { currentDate } = options;
|
|
5367
|
-
const now = epoch(currentDate || /* @__PURE__ */ new Date());
|
|
5368
|
-
if ((payload.iat !== void 0 || maxTokenAge) && typeof payload.iat !== "number") throw new JWTClaimValidationFailed("\"iat\" claim must be a number", payload, "iat", "invalid");
|
|
5369
|
-
if (payload.nbf !== void 0) {
|
|
5370
|
-
if (typeof payload.nbf !== "number") throw new JWTClaimValidationFailed("\"nbf\" claim must be a number", payload, "nbf", "invalid");
|
|
5371
|
-
if (payload.nbf > now + tolerance) throw new JWTClaimValidationFailed("\"nbf\" claim timestamp check failed", payload, "nbf", "check_failed");
|
|
5372
|
-
}
|
|
5373
|
-
if (payload.exp !== void 0) {
|
|
5374
|
-
if (typeof payload.exp !== "number") throw new JWTClaimValidationFailed("\"exp\" claim must be a number", payload, "exp", "invalid");
|
|
5375
|
-
if (payload.exp <= now - tolerance) throw new JWTExpired("\"exp\" claim timestamp check failed", payload, "exp", "check_failed");
|
|
5376
|
-
}
|
|
5377
|
-
if (maxTokenAge) {
|
|
5378
|
-
const age = now - payload.iat;
|
|
5379
|
-
const max = typeof maxTokenAge === "number" ? maxTokenAge : secs(maxTokenAge);
|
|
5380
|
-
if (age - tolerance > max) throw new JWTExpired("\"iat\" claim timestamp check failed (too far in the past)", payload, "iat", "check_failed");
|
|
5381
|
-
if (age < 0 - tolerance) throw new JWTClaimValidationFailed("\"iat\" claim timestamp check failed (it should be in the past)", payload, "iat", "check_failed");
|
|
5382
|
-
}
|
|
5383
|
-
return payload;
|
|
5384
|
-
}
|
|
5385
|
-
var JWTClaimsBuilder = class {
|
|
5386
|
-
#payload;
|
|
5387
|
-
constructor(payload) {
|
|
5388
|
-
if (!isObject(payload)) throw new TypeError("JWT Claims Set MUST be an object");
|
|
5389
|
-
this.#payload = structuredClone(payload);
|
|
5390
|
-
}
|
|
5391
|
-
data() {
|
|
5392
|
-
return encoder.encode(JSON.stringify(this.#payload));
|
|
5393
|
-
}
|
|
5394
|
-
get iss() {
|
|
5395
|
-
return this.#payload.iss;
|
|
5396
|
-
}
|
|
5397
|
-
set iss(value) {
|
|
5398
|
-
this.#payload.iss = value;
|
|
5399
|
-
}
|
|
5400
|
-
get sub() {
|
|
5401
|
-
return this.#payload.sub;
|
|
5402
|
-
}
|
|
5403
|
-
set sub(value) {
|
|
5404
|
-
this.#payload.sub = value;
|
|
5405
|
-
}
|
|
5406
|
-
get aud() {
|
|
5407
|
-
return this.#payload.aud;
|
|
5408
|
-
}
|
|
5409
|
-
set aud(value) {
|
|
5410
|
-
this.#payload.aud = value;
|
|
5411
|
-
}
|
|
5412
|
-
set jti(value) {
|
|
5413
|
-
this.#payload.jti = value;
|
|
5414
|
-
}
|
|
5415
|
-
set nbf(value) {
|
|
5416
|
-
if (typeof value === "number") this.#payload.nbf = validateInput("setNotBefore", value);
|
|
5417
|
-
else if (value instanceof Date) this.#payload.nbf = validateInput("setNotBefore", epoch(value));
|
|
5418
|
-
else this.#payload.nbf = epoch(/* @__PURE__ */ new Date()) + secs(value);
|
|
5419
|
-
}
|
|
5420
|
-
set exp(value) {
|
|
5421
|
-
if (typeof value === "number") this.#payload.exp = validateInput("setExpirationTime", value);
|
|
5422
|
-
else if (value instanceof Date) this.#payload.exp = validateInput("setExpirationTime", epoch(value));
|
|
5423
|
-
else this.#payload.exp = epoch(/* @__PURE__ */ new Date()) + secs(value);
|
|
5424
|
-
}
|
|
5425
|
-
set iat(value) {
|
|
5426
|
-
if (value === void 0) this.#payload.iat = epoch(/* @__PURE__ */ new Date());
|
|
5427
|
-
else if (value instanceof Date) this.#payload.iat = validateInput("setIssuedAt", epoch(value));
|
|
5428
|
-
else if (typeof value === "string") this.#payload.iat = validateInput("setIssuedAt", epoch(/* @__PURE__ */ new Date()) + secs(value));
|
|
5429
|
-
else this.#payload.iat = validateInput("setIssuedAt", value);
|
|
5430
|
-
}
|
|
5431
|
-
};
|
|
5432
|
-
//#endregion
|
|
5433
|
-
//#region node_modules/.pnpm/jose@6.2.1/node_modules/jose/dist/webapi/jwt/verify.js
|
|
5434
|
-
async function jwtVerify(jwt, key, options) {
|
|
5435
|
-
const verified = await compactVerify(jwt, key, options);
|
|
5436
|
-
if (verified.protectedHeader.crit?.includes("b64") && verified.protectedHeader.b64 === false) throw new JWTInvalid("JWTs MUST NOT use unencoded payload");
|
|
5437
|
-
const result = {
|
|
5438
|
-
payload: validateClaimsSet(verified.protectedHeader, verified.payload, options),
|
|
5439
|
-
protectedHeader: verified.protectedHeader
|
|
5440
|
-
};
|
|
5441
|
-
if (typeof key === "function") return {
|
|
5442
|
-
...result,
|
|
5443
|
-
key: verified.key
|
|
5444
|
-
};
|
|
5445
|
-
return result;
|
|
5446
|
-
}
|
|
5447
|
-
//#endregion
|
|
5448
|
-
//#region node_modules/.pnpm/jose@6.2.1/node_modules/jose/dist/webapi/jws/flattened/sign.js
|
|
5449
|
-
var FlattenedSign = class {
|
|
5450
|
-
#payload;
|
|
5451
|
-
#protectedHeader;
|
|
5452
|
-
#unprotectedHeader;
|
|
5453
|
-
constructor(payload) {
|
|
5454
|
-
if (!(payload instanceof Uint8Array)) throw new TypeError("payload must be an instance of Uint8Array");
|
|
5455
|
-
this.#payload = payload;
|
|
5456
|
-
}
|
|
5457
|
-
setProtectedHeader(protectedHeader) {
|
|
5458
|
-
assertNotSet(this.#protectedHeader, "setProtectedHeader");
|
|
5459
|
-
this.#protectedHeader = protectedHeader;
|
|
5460
|
-
return this;
|
|
5461
|
-
}
|
|
5462
|
-
setUnprotectedHeader(unprotectedHeader) {
|
|
5463
|
-
assertNotSet(this.#unprotectedHeader, "setUnprotectedHeader");
|
|
5464
|
-
this.#unprotectedHeader = unprotectedHeader;
|
|
5465
|
-
return this;
|
|
5466
|
-
}
|
|
5467
|
-
async sign(key, options) {
|
|
5468
|
-
if (!this.#protectedHeader && !this.#unprotectedHeader) throw new JWSInvalid("either setProtectedHeader or setUnprotectedHeader must be called before #sign()");
|
|
5469
|
-
if (!isDisjoint(this.#protectedHeader, this.#unprotectedHeader)) throw new JWSInvalid("JWS Protected and JWS Unprotected Header Parameter names must be disjoint");
|
|
5470
|
-
const joseHeader = {
|
|
5471
|
-
...this.#protectedHeader,
|
|
5472
|
-
...this.#unprotectedHeader
|
|
5473
|
-
};
|
|
5474
|
-
const extensions = validateCrit(JWSInvalid, new Map([["b64", true]]), options?.crit, this.#protectedHeader, joseHeader);
|
|
5475
|
-
let b64 = true;
|
|
5476
|
-
if (extensions.has("b64")) {
|
|
5477
|
-
b64 = this.#protectedHeader.b64;
|
|
5478
|
-
if (typeof b64 !== "boolean") throw new JWSInvalid("The \"b64\" (base64url-encode payload) Header Parameter must be a boolean");
|
|
5479
|
-
}
|
|
5480
|
-
const { alg } = joseHeader;
|
|
5481
|
-
if (typeof alg !== "string" || !alg) throw new JWSInvalid("JWS \"alg\" (Algorithm) Header Parameter missing or invalid");
|
|
5482
|
-
checkKeyType(alg, key, "sign");
|
|
5483
|
-
let payloadS;
|
|
5484
|
-
let payloadB;
|
|
5485
|
-
if (b64) {
|
|
5486
|
-
payloadS = encode(this.#payload);
|
|
5487
|
-
payloadB = encode$1(payloadS);
|
|
5488
|
-
} else {
|
|
5489
|
-
payloadB = this.#payload;
|
|
5490
|
-
payloadS = "";
|
|
5491
|
-
}
|
|
5492
|
-
let protectedHeaderString;
|
|
5493
|
-
let protectedHeaderBytes;
|
|
5494
|
-
if (this.#protectedHeader) {
|
|
5495
|
-
protectedHeaderString = encode(JSON.stringify(this.#protectedHeader));
|
|
5496
|
-
protectedHeaderBytes = encode$1(protectedHeaderString);
|
|
5497
|
-
} else {
|
|
5498
|
-
protectedHeaderString = "";
|
|
5499
|
-
protectedHeaderBytes = new Uint8Array();
|
|
5500
|
-
}
|
|
5501
|
-
const data = concat(protectedHeaderBytes, encode$1("."), payloadB);
|
|
5502
|
-
const jws = {
|
|
5503
|
-
signature: encode(await sign(alg, await normalizeKey(key, alg), data)),
|
|
5504
|
-
payload: payloadS
|
|
5505
|
-
};
|
|
5506
|
-
if (this.#unprotectedHeader) jws.header = this.#unprotectedHeader;
|
|
5507
|
-
if (this.#protectedHeader) jws.protected = protectedHeaderString;
|
|
5508
|
-
return jws;
|
|
5509
|
-
}
|
|
5510
|
-
};
|
|
5511
|
-
//#endregion
|
|
5512
|
-
//#region node_modules/.pnpm/jose@6.2.1/node_modules/jose/dist/webapi/jws/compact/sign.js
|
|
5513
|
-
var CompactSign = class {
|
|
5514
|
-
#flattened;
|
|
5515
|
-
constructor(payload) {
|
|
5516
|
-
this.#flattened = new FlattenedSign(payload);
|
|
5517
|
-
}
|
|
5518
|
-
setProtectedHeader(protectedHeader) {
|
|
5519
|
-
this.#flattened.setProtectedHeader(protectedHeader);
|
|
5520
|
-
return this;
|
|
5521
|
-
}
|
|
5522
|
-
async sign(key, options) {
|
|
5523
|
-
const jws = await this.#flattened.sign(key, options);
|
|
5524
|
-
if (jws.payload === void 0) throw new TypeError("use the flattened module for creating JWS with b64: false");
|
|
5525
|
-
return `${jws.protected}.${jws.payload}.${jws.signature}`;
|
|
5526
|
-
}
|
|
5527
|
-
};
|
|
5528
|
-
//#endregion
|
|
5529
|
-
//#region node_modules/.pnpm/jose@6.2.1/node_modules/jose/dist/webapi/jwt/sign.js
|
|
5530
|
-
var SignJWT = class {
|
|
5531
|
-
#protectedHeader;
|
|
5532
|
-
#jwt;
|
|
5533
|
-
constructor(payload = {}) {
|
|
5534
|
-
this.#jwt = new JWTClaimsBuilder(payload);
|
|
5535
|
-
}
|
|
5536
|
-
setIssuer(issuer) {
|
|
5537
|
-
this.#jwt.iss = issuer;
|
|
5538
|
-
return this;
|
|
5539
|
-
}
|
|
5540
|
-
setSubject(subject) {
|
|
5541
|
-
this.#jwt.sub = subject;
|
|
5542
|
-
return this;
|
|
5543
|
-
}
|
|
5544
|
-
setAudience(audience) {
|
|
5545
|
-
this.#jwt.aud = audience;
|
|
5546
|
-
return this;
|
|
5547
|
-
}
|
|
5548
|
-
setJti(jwtId) {
|
|
5549
|
-
this.#jwt.jti = jwtId;
|
|
5550
|
-
return this;
|
|
5551
|
-
}
|
|
5552
|
-
setNotBefore(input) {
|
|
5553
|
-
this.#jwt.nbf = input;
|
|
5554
|
-
return this;
|
|
5555
|
-
}
|
|
5556
|
-
setExpirationTime(input) {
|
|
5557
|
-
this.#jwt.exp = input;
|
|
5558
|
-
return this;
|
|
5559
|
-
}
|
|
5560
|
-
setIssuedAt(input) {
|
|
5561
|
-
this.#jwt.iat = input;
|
|
5562
|
-
return this;
|
|
5563
|
-
}
|
|
5564
|
-
setProtectedHeader(protectedHeader) {
|
|
5565
|
-
this.#protectedHeader = protectedHeader;
|
|
5566
|
-
return this;
|
|
5567
|
-
}
|
|
5568
|
-
async sign(key, options) {
|
|
5569
|
-
const sig = new CompactSign(this.#jwt.data());
|
|
5570
|
-
sig.setProtectedHeader(this.#protectedHeader);
|
|
5571
|
-
if (Array.isArray(this.#protectedHeader?.crit) && this.#protectedHeader.crit.includes("b64") && this.#protectedHeader.b64 === false) throw new JWTInvalid("JWTs MUST NOT use unencoded payload");
|
|
5572
|
-
return sig.sign(key, options);
|
|
5573
|
-
}
|
|
5574
|
-
};
|
|
5575
|
-
//#endregion
|
|
5576
|
-
//#region src/core/session.ts
|
|
5577
|
-
/**
|
|
5578
|
-
* Creates a signed JWT containing the given session payload.
|
|
5579
|
-
*
|
|
5580
|
-
* @param secret - The secret key used to sign the JWT.
|
|
5581
|
-
* @param payload - The session data to embed in the token.
|
|
5582
|
-
* @param expiresIn - How long until the token expires (e.g., `"30d"`), or `null` for the default (`"30d"`).
|
|
5583
|
-
* @returns The signed JWT string.
|
|
5584
|
-
*/
|
|
5585
|
-
async function createSessionJwt(secret, payload, expiresIn = null) {
|
|
5586
|
-
const key = new TextEncoder().encode(secret);
|
|
5587
|
-
return new SignJWT({ ...payload }).setProtectedHeader({ alg: "HS256" }).setIssuedAt().setExpirationTime(expiresIn ?? "30d").sign(key);
|
|
5588
|
-
}
|
|
5589
|
-
/**
|
|
5590
|
-
* Verifies a session JWT and returns the validated session payload.
|
|
5591
|
-
*
|
|
5592
|
-
* @param secret - The secret key used to verify the JWT signature.
|
|
5593
|
-
* @param token - The JWT string to verify.
|
|
5594
|
-
* @returns A {@link Result} containing the validated {@link SessionPayload}, or a {@link SessionVerifyError}.
|
|
5595
|
-
*/
|
|
5596
|
-
async function verifySessionJwt(secret, token) {
|
|
5597
|
-
const key = new TextEncoder().encode(secret);
|
|
5598
|
-
let payload;
|
|
5599
|
-
try {
|
|
5600
|
-
payload = (await jwtVerify(token, key)).payload;
|
|
5601
|
-
} catch (e) {
|
|
5602
|
-
return (0, import_index_cjs.err)({
|
|
5603
|
-
code: "JWT_VERIFY_FAILED",
|
|
5604
|
-
message: e instanceof Error ? e.message : "JWT verification failed"
|
|
5605
|
-
});
|
|
5606
|
-
}
|
|
5607
|
-
const parsed = SessionPayloadSchema.safeParse(payload);
|
|
5608
|
-
if (!parsed.success) return (0, import_index_cjs.err)({
|
|
5609
|
-
code: "SESSION_VALIDATION_ERROR",
|
|
5610
|
-
message: parsed.error.message
|
|
5611
|
-
});
|
|
5612
|
-
return (0, import_index_cjs.ok)(parsed.data);
|
|
5613
|
-
}
|
|
5614
|
-
//#endregion
|
|
5615
|
-
//#region src/core/embedded.ts
|
|
5616
|
-
const AUTHORIZE_ON_BEHALF_PATH = "/api/v1/app-integrations/authorize-on-behalf";
|
|
5617
|
-
const SESSION_TOKEN_QUERY_PARAM = "token";
|
|
5618
|
-
const THEME_QUERY_PARAM = "theme";
|
|
5619
|
-
/**
|
|
5620
|
-
* Extracts the embedded session token from a URL.
|
|
5621
|
-
*
|
|
5622
|
-
* When Fanvue opens an embedded app, it loads the app's embed URL with a
|
|
5623
|
-
* short-lived session token appended as a `?token=` query parameter.
|
|
5624
|
-
*
|
|
5625
|
-
* @param url - The URL to read the token from (e.g. `window.location.href`).
|
|
5626
|
-
* @returns The session token, or `null` when absent or the URL is malformed.
|
|
5627
|
-
*/
|
|
5628
|
-
function getSessionTokenFromUrl(url) {
|
|
5629
|
-
let parsed;
|
|
5630
|
-
try {
|
|
5631
|
-
parsed = new URL(url);
|
|
5632
|
-
} catch {
|
|
5633
|
-
return null;
|
|
5634
|
-
}
|
|
5635
|
-
const token = parsed.searchParams.get(SESSION_TOKEN_QUERY_PARAM);
|
|
5636
|
-
return token !== null && token.length > 0 ? token : null;
|
|
5637
|
-
}
|
|
5638
|
-
/**
|
|
5639
|
-
* Extracts the creator's active colour scheme from a URL.
|
|
5640
|
-
*
|
|
5641
|
-
* When Fanvue opens an embedded app, it appends the creator's resolved colour
|
|
5642
|
-
* scheme as a `?theme=` query parameter (`light` or `dark`), letting the app
|
|
5643
|
-
* theme-match Fanvue.
|
|
5644
|
-
*
|
|
5645
|
-
* @param url - The URL to read the theme from (e.g. `window.location.href`).
|
|
5646
|
-
* @returns The {@link FanvueTheme}, or `null` when absent, unrecognised, or the
|
|
5647
|
-
* URL is malformed (e.g. the app was opened outside Fanvue).
|
|
5648
|
-
*/
|
|
5649
|
-
function getThemeFromUrl(url) {
|
|
5650
|
-
let parsed;
|
|
5651
|
-
try {
|
|
5652
|
-
parsed = new URL(url);
|
|
5653
|
-
} catch {
|
|
5654
|
-
return null;
|
|
5655
|
-
}
|
|
5656
|
-
const theme = parsed.searchParams.get(THEME_QUERY_PARAM);
|
|
5657
|
-
return theme === "light" || theme === "dark" ? theme : null;
|
|
5658
|
-
}
|
|
5659
|
-
/**
|
|
5660
|
-
* Requests an authorization code from the Fanvue platform on behalf of the
|
|
5661
|
-
* creator currently using the embedded app.
|
|
5662
|
-
*
|
|
5663
|
-
* This is the "authorize" half of the delegated flow: the platform verifies
|
|
5664
|
-
* the session token, runs the OAuth authorize as the creator, and returns the
|
|
5665
|
-
* resulting authorization code. The PKCE verifier and client secret never
|
|
5666
|
-
* leave the caller — only the challenge is sent.
|
|
5667
|
-
*
|
|
5668
|
-
* Most apps should use {@link exchangeSessionToken}, which composes this with
|
|
5669
|
-
* the code exchange.
|
|
5670
|
-
*
|
|
5671
|
-
* @param config - The embedded auth configuration.
|
|
5672
|
-
* @param sessionToken - The short-lived session token received in the iframe.
|
|
5673
|
-
* @param opts - The PKCE code challenge and state to bind the code to.
|
|
5674
|
-
* @returns A `Result` containing the authorization code on success or
|
|
5675
|
-
* {@link EmbeddedAuthError} on failure.
|
|
5676
|
-
*/
|
|
5677
|
-
async function requestAuthorizationCodeOnBehalf(config, sessionToken, opts) {
|
|
5678
|
-
const platformUrl = config.platformUrl ?? "https://www.fanvue.com";
|
|
5679
|
-
let response;
|
|
5680
|
-
try {
|
|
5681
|
-
response = await fetch(`${platformUrl}${AUTHORIZE_ON_BEHALF_PATH}`, {
|
|
5682
|
-
method: "POST",
|
|
5683
|
-
headers: {
|
|
5684
|
-
"Content-Type": "application/json",
|
|
5685
|
-
Authorization: `Bearer ${sessionToken}`
|
|
5686
|
-
},
|
|
5687
|
-
body: JSON.stringify({
|
|
5688
|
-
code_challenge: opts.codeChallenge,
|
|
5689
|
-
code_challenge_method: "S256",
|
|
5690
|
-
state: opts.state
|
|
5691
|
-
})
|
|
5692
|
-
});
|
|
5693
|
-
} catch (error) {
|
|
5694
|
-
return (0, import_index_cjs.err)({
|
|
5695
|
-
code: "AUTHORIZE_ON_BEHALF_FAILED",
|
|
5696
|
-
statusCode: 0,
|
|
5697
|
-
message: `Network error during authorize-on-behalf: ${error instanceof Error ? error.message : String(error)}`
|
|
5698
|
-
});
|
|
5699
|
-
}
|
|
5700
|
-
if (response.status === 401) return (0, import_index_cjs.err)({
|
|
5701
|
-
code: "SESSION_TOKEN_REJECTED",
|
|
5702
|
-
statusCode: response.status,
|
|
5703
|
-
message: "The platform rejected the session token. Session tokens expire after ~60 seconds — reopen the embedded surface to receive a fresh one."
|
|
5704
|
-
});
|
|
5705
|
-
if (response.status === 403) return (0, import_index_cjs.err)({
|
|
5706
|
-
code: "CONSENT_REQUIRED",
|
|
5707
|
-
statusCode: response.status,
|
|
5708
|
-
message: "The creator has not approved (or has revoked) consent for this app. Consent is granted on the Fanvue consent screen when the surface is opened."
|
|
5709
|
-
});
|
|
5710
|
-
if (!response.ok) return (0, import_index_cjs.err)({
|
|
5711
|
-
code: "AUTHORIZE_ON_BEHALF_FAILED",
|
|
5712
|
-
statusCode: response.status,
|
|
5713
|
-
message: `authorize-on-behalf failed: ${response.status} ${response.statusText}`
|
|
5714
|
-
});
|
|
5715
|
-
const parseResult = safeJsonParse(await response.text());
|
|
5716
|
-
if (parseResult.isErr()) {
|
|
5717
|
-
const { rawText, message } = parseResult.error;
|
|
5718
|
-
return (0, import_index_cjs.err)({
|
|
5719
|
-
code: "EMBEDDED_JSON_PARSE_ERROR",
|
|
5720
|
-
rawText,
|
|
5721
|
-
message
|
|
5722
|
-
});
|
|
5723
|
-
}
|
|
5724
|
-
const validated = AuthorizeOnBehalfResponseSchema.safeParse(parseResult.value);
|
|
5725
|
-
if (!validated.success) return (0, import_index_cjs.err)({
|
|
5726
|
-
code: "EMBEDDED_VALIDATION_ERROR",
|
|
5727
|
-
message: validated.error.message
|
|
5728
|
-
});
|
|
5729
|
-
if (validated.data.state !== opts.state) return (0, import_index_cjs.err)({
|
|
5730
|
-
code: "AUTHORIZE_STATE_MISMATCH",
|
|
5731
|
-
message: "authorize-on-behalf returned a different state than was sent."
|
|
5732
|
-
});
|
|
5733
|
-
return (0, import_index_cjs.ok)({ code: validated.data.code });
|
|
5734
|
-
}
|
|
5735
|
-
/**
|
|
5736
|
-
* Exchanges an embedded session token for OAuth access and refresh tokens.
|
|
5737
|
-
*
|
|
5738
|
-
* Runs the complete delegated authorize-on-behalf flow:
|
|
5739
|
-
*
|
|
5740
|
-
* 1. Generates a PKCE verifier/challenge pair and a random `state`.
|
|
5741
|
-
* 2. Asks the Fanvue platform to authorize as the creator
|
|
5742
|
-
* ({@link requestAuthorizationCodeOnBehalf}).
|
|
5743
|
-
* 3. Exchanges the returned code at the token endpoint using the client
|
|
5744
|
-
* secret and PKCE verifier.
|
|
5745
|
-
*
|
|
5746
|
-
* Must run server-side: it uses the client secret. The session token should
|
|
5747
|
-
* be used promptly — it expires after ~60 seconds.
|
|
5748
|
-
*
|
|
5749
|
-
* @param config - The embedded auth configuration. `redirectUri` must be a
|
|
5750
|
-
* redirect URI registered on the OAuth client (it is never visited; it only
|
|
5751
|
-
* binds the authorization code).
|
|
5752
|
-
* @param sessionToken - The short-lived session token received in the iframe.
|
|
5753
|
-
* @returns A `Result` containing {@link TokenResponse} on success or an
|
|
5754
|
-
* {@link EmbeddedAuthError} / {@link OAuthError} on failure.
|
|
5755
|
-
*/
|
|
5756
|
-
async function exchangeSessionToken(config, sessionToken) {
|
|
5757
|
-
const codeVerifier = generateRandomCodeVerifier();
|
|
5758
|
-
const codeResult = await requestAuthorizationCodeOnBehalf(config, sessionToken, {
|
|
5759
|
-
codeChallenge: await calculatePKCECodeChallenge(codeVerifier),
|
|
5760
|
-
state: generateRandomState()
|
|
5761
|
-
});
|
|
5762
|
-
if (codeResult.isErr()) return (0, import_index_cjs.err)(codeResult.error);
|
|
5763
|
-
return exchangeCodeForToken(config, {
|
|
5764
|
-
code: codeResult.value.code,
|
|
5765
|
-
codeVerifier,
|
|
5766
|
-
redirectUri: null
|
|
5767
|
-
});
|
|
5768
|
-
}
|
|
5769
|
-
//#endregion
|
|
5770
|
-
//#region src/core/client.ts
|
|
5771
|
-
/**
|
|
5772
|
-
* Creates a new {@link FanvueClient} for making authenticated requests to the Fanvue API.
|
|
5773
|
-
*
|
|
5774
|
-
* @param accessToken - The OAuth access token to authenticate requests.
|
|
5775
|
-
* @param apiBaseUrl - The base URL for the Fanvue API, or `null` to use the default.
|
|
5776
|
-
* @returns A {@link FanvueClient} instance.
|
|
5777
|
-
*/
|
|
5778
|
-
function createFanvueClient(accessToken, apiBaseUrl) {
|
|
5779
|
-
if (apiBaseUrl != null) assertFanvueDomain(apiBaseUrl);
|
|
5780
|
-
const baseUrl = apiBaseUrl ?? "https://api.fanvue.com";
|
|
5781
|
-
async function fetchApi(path) {
|
|
5782
|
-
let response;
|
|
5783
|
-
try {
|
|
5784
|
-
response = await fetch(`${baseUrl}${path}`, { headers: {
|
|
5785
|
-
Authorization: `Bearer ${accessToken}`,
|
|
5786
|
-
"X-Fanvue-API-Version": API_VERSION
|
|
5787
|
-
} });
|
|
5788
|
-
} catch (error) {
|
|
5789
|
-
return (0, import_index_cjs.err)({
|
|
5790
|
-
code: "API_REQUEST_FAILED",
|
|
5791
|
-
statusCode: 0,
|
|
5792
|
-
message: `Network error: ${error instanceof Error ? error.message : String(error)}`
|
|
5793
|
-
});
|
|
5794
|
-
}
|
|
5795
|
-
if (!response.ok) return (0, import_index_cjs.err)({
|
|
5796
|
-
code: "API_REQUEST_FAILED",
|
|
5797
|
-
statusCode: response.status,
|
|
5798
|
-
message: `API request failed: ${response.status} ${response.statusText}`
|
|
5799
|
-
});
|
|
5800
|
-
const parseResult = safeJsonParse(await response.text());
|
|
5801
|
-
if (parseResult.isErr()) {
|
|
5802
|
-
const { rawText, message } = parseResult.error;
|
|
5803
|
-
return (0, import_index_cjs.err)({
|
|
5804
|
-
code: "API_JSON_PARSE_ERROR",
|
|
5805
|
-
rawText,
|
|
5806
|
-
message
|
|
5807
|
-
});
|
|
5808
|
-
}
|
|
5809
|
-
return (0, import_index_cjs.ok)(parseResult.value);
|
|
5810
|
-
}
|
|
5811
|
-
async function getCurrentUser() {
|
|
5812
|
-
const result = await fetchApi("/users/me");
|
|
5813
|
-
if (result.isErr()) return (0, import_index_cjs.err)(result.error);
|
|
5814
|
-
const validated = FanvueUserSchema.safeParse(result.value);
|
|
5815
|
-
if (!validated.success) return (0, import_index_cjs.err)({
|
|
5816
|
-
code: "API_VALIDATION_ERROR",
|
|
5817
|
-
message: validated.error.message
|
|
5818
|
-
});
|
|
5819
|
-
return (0, import_index_cjs.ok)(validated.data);
|
|
5820
|
-
}
|
|
5821
|
-
return { getCurrentUser };
|
|
5822
|
-
}
|
|
5823
|
-
//#endregion
|
|
5824
|
-
export { assertFanvueDomain as C, DEFAULT_SCOPES as S, HEADER_UPDATED_SESSION as T, safeJsonParse as _, requestAuthorizationCodeOnBehalf as a, DEFAULT_ISSUER_URL as b, createAuthorizationUrl as c, AuthorizeOnBehalfResponseSchema as d, FanvueUserSchema as f, string as g, object as h, getThemeFromUrl as i, exchangeCodeForToken as l, TokenResponseSchema as m, exchangeSessionToken as n, createSessionJwt as o, SessionPayloadSchema as p, getSessionTokenFromUrl as r, verifySessionJwt as s, createFanvueClient as t, refreshAccessToken as u, API_VERSION as v, BEARER_PREFIX as w, DEFAULT_PLATFORM_URL as x, DEFAULT_API_BASE_URL as y };
|
|
4423
|
+
export { number as a, string as c, prettifyError as d, require_index_cjs as f, literal as i, union as l, array as n, object as o, boolean as r, record as s, _enum as t, unknown as u };
|
|
5825
4424
|
|
|
5826
|
-
//# sourceMappingURL=
|
|
4425
|
+
//# sourceMappingURL=schemas-DbyHF7Xi.js.map
|