@finueva/auth 0.23.0 → 0.26.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 +4 -0
- package/dist/device.d.ts +3 -3
- package/dist/device.js +37 -9
- package/dist/index.d.ts +2 -2
- package/dist/index.js +59 -16
- package/dist/server.d.ts +99 -3
- package/dist/server.js +1650 -1278
- package/dist/{types-CgtPkDeO.d.ts → types-rx4YxsoH.d.ts} +19 -3
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -1,992 +1,1486 @@
|
|
|
1
|
-
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
authentication_required: "Authentication is required.",
|
|
14
|
-
request_origin_denied: "The request origin is not allowed.",
|
|
15
|
-
invalid_request: "The request is invalid.",
|
|
16
|
-
invalid_invitation: "The invitation is invalid.",
|
|
17
|
-
invitation_unavailable: "The invitation is not available.",
|
|
18
|
-
recipient_unavailable: "The recipient is unavailable.",
|
|
19
|
-
invitation_recipient_mismatch: "The invitation cannot be accepted by this account.",
|
|
20
|
-
invitation_recovery_required: "Invitation administration requires separate recovery.",
|
|
21
|
-
membership_removal_recovery_required: "Membership removal requires separate recovery.",
|
|
22
|
-
email_verification_required: "Email verification is required.",
|
|
23
|
-
invalid_workspace_selection: "The workspace selection is invalid.",
|
|
24
|
-
organization_context_too_large: "The organization context is too large.",
|
|
25
|
-
credential_rate_limited: "Credential requests are temporarily limited.",
|
|
26
|
-
auth_request_rate_limited: "Authentication requests are temporarily limited.",
|
|
27
|
-
organization_slug_unavailable: "The organization address is unavailable.",
|
|
28
|
-
state_conflict: "The authentication state conflicts with the request.",
|
|
29
|
-
access_denied: "Access is denied.",
|
|
30
|
-
platform_target_unavailable: "The platform administration target is unavailable.",
|
|
31
|
-
platform_quorum_unavailable: "Platform administration quorum is unavailable.",
|
|
32
|
-
platform_recovery_required: "Platform administration requires separate recovery.",
|
|
33
|
-
identity_authority_unavailable: "Authentication is temporarily unavailable.",
|
|
34
|
-
two_factor_required: "A second authentication factor is required.",
|
|
35
|
-
two_factor_code_invalid: "The verification code is invalid.",
|
|
36
|
-
two_factor_challenge_expired: "The second-factor challenge has ended. Sign in again.",
|
|
37
|
-
two_factor_locked: "Second-factor verification is temporarily locked.",
|
|
38
|
-
recent_sign_in_required: "A recent sign-in is required.",
|
|
39
|
-
enterprise_recovery_required: "Enterprise administration evidence requires operator recovery.",
|
|
40
|
-
recent_authentication_required: "A ready recent-authentication action is required.",
|
|
41
|
-
organization_closure_confirmation_mismatch: "The confirmation does not match the organization.",
|
|
42
|
-
organization_closure_cancellation_ended: "The closure cancellation period has ended.",
|
|
43
|
-
ceremony_return_refused: "The return address is not registered for this application.",
|
|
44
|
-
password_sign_in_required: "A password sign-in method is required for this passkey change."
|
|
45
|
-
};
|
|
46
|
-
var AuthError = class extends Error {
|
|
47
|
-
code;
|
|
48
|
-
status;
|
|
49
|
-
retryAfterSeconds;
|
|
50
|
-
constructor(code, status, retryAfterSeconds) {
|
|
51
|
-
super(messages[code]);
|
|
52
|
-
this.name = "AuthError";
|
|
53
|
-
this.code = code;
|
|
54
|
-
this.status = status;
|
|
55
|
-
this.retryAfterSeconds = retryAfterSeconds;
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
//#endregion
|
|
59
|
-
//#region src/shared.ts
|
|
60
|
-
const DRIVE_CREDENTIAL_LIFETIME_SECONDS = 840;
|
|
61
|
-
const id = /^[A-Za-z0-9_-]{1,128}$/;
|
|
62
|
-
const email = /^[^\s@]+@[^\s@]+$/;
|
|
63
|
-
const MAX_SOCIAL_ID_TOKEN_BYTES = 16 * 1024;
|
|
64
|
-
function normalizeEmail(value) {
|
|
65
|
-
if (typeof value !== "string") throw new TypeError("email is invalid");
|
|
66
|
-
const normalized = value.trim().toLowerCase();
|
|
67
|
-
if (normalized.length === 0 || normalized.length > 320 || !email.test(normalized)) throw new TypeError("email is invalid");
|
|
68
|
-
return normalized;
|
|
1
|
+
String.fromCharCode;
|
|
2
|
+
const HASH_RE = /#/g;
|
|
3
|
+
const AMPERSAND_RE = /&/g;
|
|
4
|
+
const SLASH_RE = /\//g;
|
|
5
|
+
const EQUAL_RE = /=/g;
|
|
6
|
+
const PLUS_RE = /\+/g;
|
|
7
|
+
const ENC_CARET_RE = /%5e/gi;
|
|
8
|
+
const ENC_BACKTICK_RE = /%60/gi;
|
|
9
|
+
const ENC_PIPE_RE = /%7c/gi;
|
|
10
|
+
const ENC_SPACE_RE = /%20/gi;
|
|
11
|
+
function encode$2(text) {
|
|
12
|
+
return encodeURI("" + text).replace(ENC_PIPE_RE, "|");
|
|
69
13
|
}
|
|
70
|
-
function
|
|
71
|
-
|
|
72
|
-
const keys = Object.keys(value);
|
|
73
|
-
if (keys.length !== 3 && keys.length !== 4 || keys.some((key) => key !== "provider" && key !== "idToken" && key !== "nonce" && key !== "signUp") || value.provider !== "google" && value.provider !== "apple" || typeof value.signUp !== "boolean" || typeof value.idToken !== "string" || value.idToken.length < 1 || new TextEncoder().encode(value.idToken).byteLength > MAX_SOCIAL_ID_TOKEN_BYTES || !/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(value.idToken) || value.nonce !== void 0 && (typeof value.nonce !== "string" || value.nonce.length < 1 || value.nonce.length > 256 || !/^[\x20-\x7e]+$/.test(value.nonce))) throw new TypeError("social ID token input is invalid");
|
|
74
|
-
return {
|
|
75
|
-
provider: value.provider,
|
|
76
|
-
idToken: value.idToken,
|
|
77
|
-
...value.nonce === void 0 ? {} : { nonce: value.nonce },
|
|
78
|
-
signUp: value.signUp
|
|
79
|
-
};
|
|
14
|
+
function encodeQueryValue(input) {
|
|
15
|
+
return encode$2(typeof input === "string" ? input : JSON.stringify(input)).replace(PLUS_RE, "%2B").replace(ENC_SPACE_RE, "+").replace(HASH_RE, "%23").replace(AMPERSAND_RE, "%26").replace(ENC_BACKTICK_RE, "`").replace(ENC_CARET_RE, "^").replace(SLASH_RE, "%2F");
|
|
80
16
|
}
|
|
81
|
-
function
|
|
82
|
-
return
|
|
83
|
-
provider: value.provider,
|
|
84
|
-
idToken: {
|
|
85
|
-
token: value.idToken,
|
|
86
|
-
...value.nonce === void 0 ? {} : { nonce: value.nonce }
|
|
87
|
-
},
|
|
88
|
-
requestSignUp: value.signUp
|
|
89
|
-
};
|
|
17
|
+
function encodeQueryKey(text) {
|
|
18
|
+
return encodeQueryValue(text).replace(EQUAL_RE, "%3D");
|
|
90
19
|
}
|
|
91
|
-
function
|
|
92
|
-
if (value.length === 0 || value.length > 2048 || /[^\x20-\x7e]/.test(value)) throw new TypeError(`${name} must be an ASCII HTTP origin`);
|
|
93
|
-
let url;
|
|
20
|
+
function decode$1(text = "") {
|
|
94
21
|
try {
|
|
95
|
-
|
|
22
|
+
return decodeURIComponent("" + text);
|
|
96
23
|
} catch {
|
|
97
|
-
|
|
24
|
+
return "" + text;
|
|
98
25
|
}
|
|
99
|
-
const local = url.hostname === "localhost" || url.hostname.endsWith(".localhost") || url.hostname === "127.0.0.1";
|
|
100
|
-
if (url.protocol !== "https:" && !(local && url.protocol === "http:") || url.username || url.password || url.pathname !== "/" || url.search || url.hash || url.origin !== value) throw new TypeError(`${name} must be an ASCII HTTP origin`);
|
|
101
|
-
return url.origin;
|
|
102
|
-
}
|
|
103
|
-
function normalizeTimeout(value) {
|
|
104
|
-
const timeout = value ?? 1e4;
|
|
105
|
-
if (!Number.isSafeInteger(timeout) || timeout < 1 || timeout > 6e4) throw new TypeError("timeoutMs must be an integer from 1 to 60000");
|
|
106
|
-
return timeout;
|
|
107
26
|
}
|
|
108
|
-
function
|
|
109
|
-
|
|
110
|
-
if (!isObject$1(value) || !isObject$1(value.session) || !isObject$1(value.user)) throw authorityUnavailable();
|
|
111
|
-
const expiresAt = toDate(value.session.expiresAt);
|
|
112
|
-
const image = value.user.image;
|
|
113
|
-
if (!isId(value.session.id) || !expiresAt || !isId(value.user.id) || typeof value.user.name !== "string" || value.user.name.length > 256 || typeof value.user.email !== "string" || value.user.email.length > 320 || !email.test(value.user.email) || typeof value.user.emailVerified !== "boolean" || image !== null && image !== void 0 && (typeof image !== "string" || image.length > 2048)) throw authorityUnavailable();
|
|
114
|
-
return {
|
|
115
|
-
id: value.session.id,
|
|
116
|
-
expiresAt,
|
|
117
|
-
user: {
|
|
118
|
-
id: value.user.id,
|
|
119
|
-
name: value.user.name,
|
|
120
|
-
email: value.user.email,
|
|
121
|
-
emailVerified: value.user.emailVerified,
|
|
122
|
-
image: image ?? null
|
|
123
|
-
}
|
|
124
|
-
};
|
|
27
|
+
function decodeQueryKey(text) {
|
|
28
|
+
return decode$1(text.replace(PLUS_RE, " "));
|
|
125
29
|
}
|
|
126
|
-
function
|
|
127
|
-
|
|
128
|
-
return {
|
|
129
|
-
tokenType: "Bearer",
|
|
130
|
-
token: value.token,
|
|
131
|
-
expiresAt: new Date(now + value.expiresIn * 1e3)
|
|
132
|
-
};
|
|
30
|
+
function decodeQueryValue(text) {
|
|
31
|
+
return decode$1(text.replace(PLUS_RE, " "));
|
|
133
32
|
}
|
|
134
|
-
function
|
|
135
|
-
|
|
136
|
-
if (
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
if (
|
|
145
|
-
|
|
33
|
+
function parseQuery(parametersString = "") {
|
|
34
|
+
const object = Object.create(null);
|
|
35
|
+
if (parametersString[0] === "?") parametersString = parametersString.slice(1);
|
|
36
|
+
for (const parameter of parametersString.split("&")) {
|
|
37
|
+
const s = parameter.match(/([^=]+)=?(.*)/) || [];
|
|
38
|
+
if (s.length < 2) continue;
|
|
39
|
+
const key = decodeQueryKey(s[1]);
|
|
40
|
+
if (key === "__proto__" || key === "constructor") continue;
|
|
41
|
+
const value = decodeQueryValue(s[2] || "");
|
|
42
|
+
if (object[key] === void 0) object[key] = value;
|
|
43
|
+
else if (Array.isArray(object[key])) object[key].push(value);
|
|
44
|
+
else object[key] = [object[key], value];
|
|
146
45
|
}
|
|
147
|
-
return
|
|
46
|
+
return object;
|
|
148
47
|
}
|
|
149
|
-
function
|
|
150
|
-
if (
|
|
151
|
-
return
|
|
48
|
+
function encodeQueryItem(key, value) {
|
|
49
|
+
if (typeof value === "number" || typeof value === "boolean") value = String(value);
|
|
50
|
+
if (!value) return encodeQueryKey(key);
|
|
51
|
+
if (Array.isArray(value)) return value.map((_value) => `${encodeQueryKey(key)}=${encodeQueryValue(_value)}`).join("&");
|
|
52
|
+
return `${encodeQueryKey(key)}=${encodeQueryValue(value)}`;
|
|
152
53
|
}
|
|
153
|
-
function
|
|
154
|
-
|
|
155
|
-
"capabilities",
|
|
156
|
-
"id",
|
|
157
|
-
"lifecycle",
|
|
158
|
-
"logo",
|
|
159
|
-
"name",
|
|
160
|
-
"role",
|
|
161
|
-
"slug"
|
|
162
|
-
]);
|
|
163
|
-
if (!isId(value.id) || !boundedString(value.name, 255) || !boundedString(value.slug, 255) || value.lifecycle !== "ordinary" && value.lifecycle !== "managed" || !role(value.role) || !isObject$1(value.capabilities)) throw authorityUnavailable();
|
|
164
|
-
exact$3(value.capabilities, [
|
|
165
|
-
"readInvitations",
|
|
166
|
-
"readMembers",
|
|
167
|
-
"readTeams"
|
|
168
|
-
]);
|
|
169
|
-
if (value.capabilities.readMembers !== true || value.capabilities.readTeams !== true || typeof value.capabilities.readInvitations !== "boolean") throw authorityUnavailable();
|
|
170
|
-
return {
|
|
171
|
-
id: value.id,
|
|
172
|
-
name: value.name,
|
|
173
|
-
slug: value.slug,
|
|
174
|
-
logo: nullableHttpsUrl(value.logo),
|
|
175
|
-
lifecycle: value.lifecycle,
|
|
176
|
-
role: value.role,
|
|
177
|
-
capabilities: {
|
|
178
|
-
readMembers: true,
|
|
179
|
-
readTeams: true,
|
|
180
|
-
readInvitations: value.capabilities.readInvitations
|
|
181
|
-
}
|
|
182
|
-
};
|
|
54
|
+
function stringifyQuery(query) {
|
|
55
|
+
return Object.keys(query).filter((k) => query[k] !== void 0).map((k) => encodeQueryItem(k, query[k])).filter(Boolean).join("&");
|
|
183
56
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
return {
|
|
194
|
-
name: value.name,
|
|
195
|
-
slug: value.slug,
|
|
196
|
-
logo
|
|
197
|
-
};
|
|
57
|
+
const PROTOCOL_STRICT_REGEX = /^[\s\w\0+.-]{2,}:([/\\]{1,2})/;
|
|
58
|
+
const PROTOCOL_REGEX = /^[\s\w\0+.-]{2,}:([/\\]{2})?/;
|
|
59
|
+
const PROTOCOL_RELATIVE_REGEX = /^([/\\]\s*){2,}[^/\\]/;
|
|
60
|
+
const TRAILING_SLASH_RE = /\/$|\/\?|\/#/;
|
|
61
|
+
const JOIN_LEADING_SLASH_RE = /^\.?\//;
|
|
62
|
+
function hasProtocol(inputString, opts = {}) {
|
|
63
|
+
if (typeof opts === "boolean") opts = { acceptRelative: opts };
|
|
64
|
+
if (opts.strict) return PROTOCOL_STRICT_REGEX.test(inputString);
|
|
65
|
+
return PROTOCOL_REGEX.test(inputString) || (opts.acceptRelative ? PROTOCOL_RELATIVE_REGEX.test(inputString) : false);
|
|
198
66
|
}
|
|
199
|
-
function
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
67
|
+
function hasTrailingSlash(input = "", respectQueryAndFragment) {
|
|
68
|
+
if (!respectQueryAndFragment) return input.endsWith("/");
|
|
69
|
+
return TRAILING_SLASH_RE.test(input);
|
|
70
|
+
}
|
|
71
|
+
function withoutTrailingSlash(input = "", respectQueryAndFragment) {
|
|
72
|
+
if (!respectQueryAndFragment) return (hasTrailingSlash(input) ? input.slice(0, -1) : input) || "/";
|
|
73
|
+
if (!hasTrailingSlash(input, true)) return input || "/";
|
|
74
|
+
let path = input;
|
|
75
|
+
let fragment = "";
|
|
76
|
+
const fragmentIndex = input.indexOf("#");
|
|
77
|
+
if (fragmentIndex !== -1) {
|
|
78
|
+
path = input.slice(0, fragmentIndex);
|
|
79
|
+
fragment = input.slice(fragmentIndex);
|
|
204
80
|
}
|
|
81
|
+
const [s0, ...s] = path.split("?");
|
|
82
|
+
return ((s0.endsWith("/") ? s0.slice(0, -1) : s0) || "/") + (s.length > 0 ? `?${s.join("?")}` : "") + fragment;
|
|
205
83
|
}
|
|
206
|
-
function
|
|
207
|
-
if (!
|
|
208
|
-
return
|
|
84
|
+
function withTrailingSlash(input = "", respectQueryAndFragment) {
|
|
85
|
+
if (!respectQueryAndFragment) return input.endsWith("/") ? input : input + "/";
|
|
86
|
+
if (hasTrailingSlash(input, true)) return input || "/";
|
|
87
|
+
let path = input;
|
|
88
|
+
let fragment = "";
|
|
89
|
+
const fragmentIndex = input.indexOf("#");
|
|
90
|
+
if (fragmentIndex !== -1) {
|
|
91
|
+
path = input.slice(0, fragmentIndex);
|
|
92
|
+
fragment = input.slice(fragmentIndex);
|
|
93
|
+
if (!path) return fragment;
|
|
94
|
+
}
|
|
95
|
+
const [s0, ...s] = path.split("?");
|
|
96
|
+
return s0 + "/" + (s.length > 0 ? `?${s.join("?")}` : "") + fragment;
|
|
209
97
|
}
|
|
210
|
-
function
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
98
|
+
function withBase(input, base) {
|
|
99
|
+
if (isEmptyURL(base) || hasProtocol(input)) return input;
|
|
100
|
+
const _base = withoutTrailingSlash(base);
|
|
101
|
+
if (input.startsWith(_base)) {
|
|
102
|
+
const nextChar = input[_base.length];
|
|
103
|
+
if (!nextChar || nextChar === "/" || nextChar === "?") return input;
|
|
215
104
|
}
|
|
105
|
+
return joinURL(_base, input);
|
|
216
106
|
}
|
|
217
|
-
function
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
107
|
+
function withQuery(input, query) {
|
|
108
|
+
const parsed = parseURL(input);
|
|
109
|
+
parsed.search = stringifyQuery({
|
|
110
|
+
...parseQuery(parsed.search),
|
|
111
|
+
...query
|
|
112
|
+
});
|
|
113
|
+
return stringifyParsedURL(parsed);
|
|
224
114
|
}
|
|
225
|
-
function
|
|
226
|
-
|
|
227
|
-
"id",
|
|
228
|
-
"name",
|
|
229
|
-
"slug"
|
|
230
|
-
]);
|
|
231
|
-
if (!isId(value.id) || !boundedString(value.name, 255) || !boundedString(value.slug, 128)) throw authorityUnavailable();
|
|
232
|
-
return {
|
|
233
|
-
id: value.id,
|
|
234
|
-
name: value.name,
|
|
235
|
-
slug: value.slug
|
|
236
|
-
};
|
|
115
|
+
function isEmptyURL(url) {
|
|
116
|
+
return !url || url === "/";
|
|
237
117
|
}
|
|
238
|
-
function
|
|
239
|
-
|
|
240
|
-
return {
|
|
241
|
-
name,
|
|
242
|
-
idempotencyKey
|
|
243
|
-
};
|
|
118
|
+
function isNonEmptyURL(url) {
|
|
119
|
+
return url && url !== "/";
|
|
244
120
|
}
|
|
245
|
-
function
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
121
|
+
function joinURL(base, ...input) {
|
|
122
|
+
let url = base || "";
|
|
123
|
+
for (const segment of input.filter((url2) => isNonEmptyURL(url2))) if (url) {
|
|
124
|
+
const _segment = segment.replace(JOIN_LEADING_SLASH_RE, "");
|
|
125
|
+
url = withTrailingSlash(url) + _segment;
|
|
126
|
+
} else url = segment;
|
|
127
|
+
return url;
|
|
252
128
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
const
|
|
256
|
-
if (
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
129
|
+
const protocolRelative = Symbol.for("ufo:protocolRelative");
|
|
130
|
+
function parseURL(input = "", defaultProto) {
|
|
131
|
+
const _specialProtoMatch = input.match(/^[\s\0]*(blob:|data:|javascript:|vbscript:)(.*)/i);
|
|
132
|
+
if (_specialProtoMatch) {
|
|
133
|
+
const [, _proto, _pathname = ""] = _specialProtoMatch;
|
|
134
|
+
return {
|
|
135
|
+
protocol: _proto.toLowerCase(),
|
|
136
|
+
pathname: _pathname,
|
|
137
|
+
href: _proto + _pathname,
|
|
138
|
+
auth: "",
|
|
139
|
+
host: "",
|
|
140
|
+
search: "",
|
|
141
|
+
hash: ""
|
|
142
|
+
};
|
|
262
143
|
}
|
|
263
|
-
if (
|
|
264
|
-
const
|
|
265
|
-
|
|
144
|
+
if (!hasProtocol(input, { acceptRelative: true })) return defaultProto ? parseURL(defaultProto + input) : parsePath(input);
|
|
145
|
+
const [, protocol = "", auth, hostAndPath = ""] = input.replace(/\\/g, "/").match(/^[\s\0]*([\w+.-]{2,}:)?\/\/([^/@]+@)?(.*)/) || [];
|
|
146
|
+
let [, host = "", path = ""] = hostAndPath.match(/([^#/?]*)(.*)?/) || [];
|
|
147
|
+
if (protocol === "file:") path = path.replace(/\/(?=[A-Za-z]:)/, "");
|
|
148
|
+
const { pathname, search, hash } = parsePath(path);
|
|
266
149
|
return {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
150
|
+
protocol: protocol.toLowerCase(),
|
|
151
|
+
auth: auth ? auth.slice(0, Math.max(0, auth.length - 1)) : "",
|
|
152
|
+
host,
|
|
153
|
+
pathname,
|
|
154
|
+
search,
|
|
155
|
+
hash,
|
|
156
|
+
[protocolRelative]: !protocol
|
|
270
157
|
};
|
|
271
158
|
}
|
|
272
|
-
function
|
|
273
|
-
|
|
274
|
-
if (!isId(value.id)) throw authorityUnavailable();
|
|
159
|
+
function parsePath(input = "") {
|
|
160
|
+
const [pathname = "", search = "", hash = ""] = (input.match(/([^#?]*)(\?[^#]*)?(#.*)?/) || []).splice(1);
|
|
275
161
|
return {
|
|
276
|
-
|
|
277
|
-
|
|
162
|
+
pathname,
|
|
163
|
+
search,
|
|
164
|
+
hash
|
|
278
165
|
};
|
|
279
166
|
}
|
|
280
|
-
function
|
|
281
|
-
const
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
return { idempotencyKey };
|
|
288
|
-
}
|
|
289
|
-
function normalizeCanceledOrganizationInvitation(value) {
|
|
290
|
-
exact$3(value, ["status"]);
|
|
291
|
-
if (value.status !== "canceled") throw authorityUnavailable();
|
|
292
|
-
return { status: "canceled" };
|
|
293
|
-
}
|
|
294
|
-
function normalizeOrganizationMembershipRemovalInput(idempotencyKey) {
|
|
295
|
-
if (!boundedString(idempotencyKey, 255)) throw new AuthError("invalid_request", 400);
|
|
296
|
-
return { idempotencyKey };
|
|
167
|
+
function stringifyParsedURL(parsed) {
|
|
168
|
+
const pathname = parsed.pathname || "";
|
|
169
|
+
const search = parsed.search ? (parsed.search.startsWith("?") ? "" : "?") + parsed.search : "";
|
|
170
|
+
const hash = parsed.hash || "";
|
|
171
|
+
const auth = parsed.auth ? parsed.auth + "@" : "";
|
|
172
|
+
const host = parsed.host || "";
|
|
173
|
+
return (parsed.protocol || parsed[protocolRelative] ? (parsed.protocol || "") + "//" : "") + auth + host + pathname + search + hash;
|
|
297
174
|
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
175
|
+
//#endregion
|
|
176
|
+
//#region ../../node_modules/.pnpm/destr@2.0.5/node_modules/destr/dist/index.mjs
|
|
177
|
+
const suspectProtoRx = /"(?:_|\\u0{2}5[Ff]){2}(?:p|\\u0{2}70)(?:r|\\u0{2}72)(?:o|\\u0{2}6[Ff])(?:t|\\u0{2}74)(?:o|\\u0{2}6[Ff])(?:_|\\u0{2}5[Ff]){2}"\s*:/;
|
|
178
|
+
const suspectConstructorRx = /"(?:c|\\u0063)(?:o|\\u006[Ff])(?:n|\\u006[Ee])(?:s|\\u0073)(?:t|\\u0074)(?:r|\\u0072)(?:u|\\u0075)(?:c|\\u0063)(?:t|\\u0074)(?:o|\\u006[Ff])(?:r|\\u0072)"\s*:/;
|
|
179
|
+
const JsonSigRx = /^\s*["[{]|^\s*-?\d{1,16}(\.\d{1,17})?([Ee][+-]?\d+)?\s*$/;
|
|
180
|
+
function jsonParseTransform(key, value) {
|
|
181
|
+
if (key === "__proto__" || key === "constructor" && value && typeof value === "object" && "prototype" in value) {
|
|
182
|
+
warnKeyDropped(key);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
return value;
|
|
302
186
|
}
|
|
303
|
-
function
|
|
304
|
-
|
|
305
|
-
if (value.status !== "left") throw authorityUnavailable();
|
|
306
|
-
return { status: "left" };
|
|
187
|
+
function warnKeyDropped(key) {
|
|
188
|
+
console.warn(`[destr] Dropping "${key}" key to prevent prototype pollution.`);
|
|
307
189
|
}
|
|
308
|
-
function
|
|
309
|
-
if (
|
|
310
|
-
return
|
|
190
|
+
function destr(value, options = {}) {
|
|
191
|
+
if (typeof value !== "string") return value;
|
|
192
|
+
if (value[0] === "\"" && value[value.length - 1] === "\"" && value.indexOf("\\") === -1) return value.slice(1, -1);
|
|
193
|
+
const _value = value.trim();
|
|
194
|
+
if (_value.length <= 9) switch (_value.toLowerCase()) {
|
|
195
|
+
case "true": return true;
|
|
196
|
+
case "false": return false;
|
|
197
|
+
case "undefined": return;
|
|
198
|
+
case "null": return null;
|
|
199
|
+
case "nan": return NaN;
|
|
200
|
+
case "infinity": return Number.POSITIVE_INFINITY;
|
|
201
|
+
case "-infinity": return Number.NEGATIVE_INFINITY;
|
|
202
|
+
}
|
|
203
|
+
if (!JsonSigRx.test(value)) {
|
|
204
|
+
if (options.strict) throw new SyntaxError("[destr] Invalid JSON");
|
|
205
|
+
return value;
|
|
206
|
+
}
|
|
207
|
+
try {
|
|
208
|
+
if (suspectProtoRx.test(value) || suspectConstructorRx.test(value)) {
|
|
209
|
+
if (options.strict) throw new Error("[destr] Possible prototype pollution");
|
|
210
|
+
return JSON.parse(value, jsonParseTransform);
|
|
211
|
+
}
|
|
212
|
+
return JSON.parse(value);
|
|
213
|
+
} catch (error) {
|
|
214
|
+
if (options.strict) throw error;
|
|
215
|
+
return value;
|
|
216
|
+
}
|
|
311
217
|
}
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
218
|
+
//#endregion
|
|
219
|
+
//#region ../../node_modules/.pnpm/ofetch@1.5.1/node_modules/ofetch/dist/shared/ofetch.CWycOUEr.mjs
|
|
220
|
+
var FetchError = class extends Error {
|
|
221
|
+
constructor(message, opts) {
|
|
222
|
+
super(message, opts);
|
|
223
|
+
this.name = "FetchError";
|
|
224
|
+
if (opts?.cause && !this.cause) this.cause = opts.cause;
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
function createFetchError(ctx) {
|
|
228
|
+
const errorMessage = ctx.error?.message || ctx.error?.toString() || "";
|
|
229
|
+
const method = ctx.request?.method || ctx.options?.method || "GET";
|
|
230
|
+
const url = ctx.request?.url || String(ctx.request) || "/";
|
|
231
|
+
const fetchError = new FetchError(`${`[${method}] ${JSON.stringify(url)}`}: ${ctx.response ? `${ctx.response.status} ${ctx.response.statusText}` : "<no response>"}${errorMessage ? ` ${errorMessage}` : ""}`, ctx.error ? { cause: ctx.error } : void 0);
|
|
232
|
+
for (const key of [
|
|
233
|
+
"request",
|
|
234
|
+
"options",
|
|
235
|
+
"response"
|
|
236
|
+
]) Object.defineProperty(fetchError, key, { get() {
|
|
237
|
+
return ctx[key];
|
|
238
|
+
} });
|
|
239
|
+
for (const [key, refKey] of [
|
|
240
|
+
["data", "_data"],
|
|
241
|
+
["status", "status"],
|
|
242
|
+
["statusCode", "status"],
|
|
243
|
+
["statusText", "statusText"],
|
|
244
|
+
["statusMessage", "statusText"]
|
|
245
|
+
]) Object.defineProperty(fetchError, key, { get() {
|
|
246
|
+
return ctx.response && ctx.response[refKey];
|
|
247
|
+
} });
|
|
248
|
+
return fetchError;
|
|
316
249
|
}
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
250
|
+
const payloadMethods = new Set(Object.freeze([
|
|
251
|
+
"PATCH",
|
|
252
|
+
"POST",
|
|
253
|
+
"PUT",
|
|
254
|
+
"DELETE"
|
|
255
|
+
]));
|
|
256
|
+
function isPayloadMethod(method = "GET") {
|
|
257
|
+
return payloadMethods.has(method.toUpperCase());
|
|
321
258
|
}
|
|
322
|
-
function
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
259
|
+
function isJSONSerializable(value) {
|
|
260
|
+
if (value === void 0) return false;
|
|
261
|
+
const t = typeof value;
|
|
262
|
+
if (t === "string" || t === "number" || t === "boolean" || t === null) return true;
|
|
263
|
+
if (t !== "object") return false;
|
|
264
|
+
if (Array.isArray(value)) return true;
|
|
265
|
+
if (value.buffer) return false;
|
|
266
|
+
if (value instanceof FormData || value instanceof URLSearchParams) return false;
|
|
267
|
+
return value.constructor && value.constructor.name === "Object" || typeof value.toJSON === "function";
|
|
326
268
|
}
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
269
|
+
const textTypes = new Set([
|
|
270
|
+
"image/svg",
|
|
271
|
+
"application/xml",
|
|
272
|
+
"application/xhtml",
|
|
273
|
+
"application/html"
|
|
274
|
+
]);
|
|
275
|
+
const JSON_RE = /^application\/(?:[\w!#$%&*.^`~-]*\+)?json(;.+)?$/i;
|
|
276
|
+
function detectResponseType(_contentType = "") {
|
|
277
|
+
if (!_contentType) return "json";
|
|
278
|
+
const contentType = _contentType.split(";").shift() || "";
|
|
279
|
+
if (JSON_RE.test(contentType)) return "json";
|
|
280
|
+
if (contentType === "text/event-stream") return "stream";
|
|
281
|
+
if (textTypes.has(contentType) || contentType.startsWith("text/")) return "text";
|
|
282
|
+
return "blob";
|
|
334
283
|
}
|
|
335
|
-
function
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
"image",
|
|
344
|
-
"joinedAt",
|
|
345
|
-
"name",
|
|
346
|
-
"owner",
|
|
347
|
-
"role",
|
|
348
|
-
"teamIds",
|
|
349
|
-
"userId"
|
|
350
|
-
]);
|
|
351
|
-
if (!isId(member.id) || !isId(member.userId) || !boundedString(member.name, 255) || typeof member.email !== "string" || member.email.length > 320 || !email.test(member.email) || !role(member.role) || typeof member.owner !== "boolean" || !Array.isArray(member.teamIds) || member.teamIds.length > 100) throw authorityUnavailable();
|
|
352
|
-
const teamIds = unique(member.teamIds.map((teamId) => normalizeResponseId(teamId)), (item) => item);
|
|
353
|
-
return {
|
|
354
|
-
id: member.id,
|
|
355
|
-
userId: member.userId,
|
|
356
|
-
name: member.name,
|
|
357
|
-
email: member.email,
|
|
358
|
-
image: nullableHttpsUrl(member.image),
|
|
359
|
-
role: member.role,
|
|
360
|
-
owner: member.owner,
|
|
361
|
-
joinedAt: responseDate(member.joinedAt),
|
|
362
|
-
teamIds
|
|
363
|
-
};
|
|
364
|
-
}), (item) => item.id),
|
|
365
|
-
nextCursor: nullableCursor(value.nextCursor)
|
|
284
|
+
function resolveFetchOptions(request, input, defaults, Headers) {
|
|
285
|
+
const headers = mergeHeaders(input?.headers ?? request?.headers, defaults?.headers, Headers);
|
|
286
|
+
let query;
|
|
287
|
+
if (defaults?.query || defaults?.params || input?.params || input?.query) query = {
|
|
288
|
+
...defaults?.params,
|
|
289
|
+
...defaults?.query,
|
|
290
|
+
...input?.params,
|
|
291
|
+
...input?.query
|
|
366
292
|
};
|
|
367
|
-
}
|
|
368
|
-
function normalizeOrganizationTeams(value) {
|
|
369
|
-
exact$3(value, ["nextCursor", "teams"]);
|
|
370
|
-
if (!Array.isArray(value.teams) || value.teams.length > 100) throw authorityUnavailable();
|
|
371
293
|
return {
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
"name"
|
|
378
|
-
]);
|
|
379
|
-
if (!isId(team.id) || !boundedString(team.name, 255) || team.category !== "manual" && team.category !== "managed") throw authorityUnavailable();
|
|
380
|
-
return {
|
|
381
|
-
id: team.id,
|
|
382
|
-
name: team.name,
|
|
383
|
-
category: team.category,
|
|
384
|
-
createdAt: responseDate(team.createdAt)
|
|
385
|
-
};
|
|
386
|
-
}), (item) => item.id),
|
|
387
|
-
nextCursor: nullableCursor(value.nextCursor)
|
|
294
|
+
...defaults,
|
|
295
|
+
...input,
|
|
296
|
+
query,
|
|
297
|
+
params: query,
|
|
298
|
+
headers
|
|
388
299
|
};
|
|
389
300
|
}
|
|
390
|
-
function
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
nextCursor: nullableCursor(value.nextCursor)
|
|
396
|
-
};
|
|
301
|
+
function mergeHeaders(input, defaults, Headers) {
|
|
302
|
+
if (!defaults) return new Headers(input);
|
|
303
|
+
const headers = new Headers(defaults);
|
|
304
|
+
if (input) for (const [key, value] of Symbol.iterator in input || Array.isArray(input) ? input : new Headers(input)) headers.set(key, value);
|
|
305
|
+
return headers;
|
|
397
306
|
}
|
|
398
|
-
function
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
"email",
|
|
402
|
-
"expiresAt",
|
|
403
|
-
"id",
|
|
404
|
-
"inviter",
|
|
405
|
-
"role",
|
|
406
|
-
"status",
|
|
407
|
-
"teamIds"
|
|
408
|
-
]);
|
|
409
|
-
if (!isId(value.id) || typeof value.email !== "string" || value.email.length > 320 || !email.test(value.email) || !role(value.role) || value.status !== "pending" || !Array.isArray(value.teamIds) || value.teamIds.length > 100 || !isObject$1(value.inviter)) throw authorityUnavailable();
|
|
410
|
-
exact$3(value.inviter, ["membershipId", "name"]);
|
|
411
|
-
if (!isId(value.inviter.membershipId) || !boundedString(value.inviter.name, 255)) throw authorityUnavailable();
|
|
412
|
-
return {
|
|
413
|
-
id: value.id,
|
|
414
|
-
email: value.email,
|
|
415
|
-
role: value.role,
|
|
416
|
-
teamIds: unique(value.teamIds.map(normalizeResponseId), (item) => item),
|
|
417
|
-
inviter: {
|
|
418
|
-
membershipId: value.inviter.membershipId,
|
|
419
|
-
name: value.inviter.name
|
|
420
|
-
},
|
|
421
|
-
createdAt: responseDate(value.createdAt),
|
|
422
|
-
expiresAt: responseDate(value.expiresAt),
|
|
423
|
-
status: "pending"
|
|
424
|
-
};
|
|
307
|
+
async function callHooks(context, hooks) {
|
|
308
|
+
if (hooks) if (Array.isArray(hooks)) for (const hook of hooks) await hook(context);
|
|
309
|
+
else await hooks(context);
|
|
425
310
|
}
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
311
|
+
const retryStatusCodes = new Set([
|
|
312
|
+
408,
|
|
313
|
+
409,
|
|
314
|
+
425,
|
|
315
|
+
429,
|
|
316
|
+
500,
|
|
317
|
+
502,
|
|
318
|
+
503,
|
|
319
|
+
504
|
|
320
|
+
]);
|
|
321
|
+
const nullBodyResponses = new Set([
|
|
322
|
+
101,
|
|
323
|
+
204,
|
|
324
|
+
205,
|
|
325
|
+
304
|
|
326
|
+
]);
|
|
327
|
+
function createFetch(globalOptions = {}) {
|
|
328
|
+
const { fetch = globalThis.fetch, Headers = globalThis.Headers, AbortController = globalThis.AbortController } = globalOptions;
|
|
329
|
+
async function onError(context) {
|
|
330
|
+
const isAbort = context.error && context.error.name === "AbortError" && !context.options.timeout || false;
|
|
331
|
+
if (context.options.retry !== false && !isAbort) {
|
|
332
|
+
let retries;
|
|
333
|
+
if (typeof context.options.retry === "number") retries = context.options.retry;
|
|
334
|
+
else retries = isPayloadMethod(context.options.method) ? 0 : 1;
|
|
335
|
+
const responseCode = context.response && context.response.status || 500;
|
|
336
|
+
if (retries > 0 && (Array.isArray(context.options.retryStatusCodes) ? context.options.retryStatusCodes.includes(responseCode) : retryStatusCodes.has(responseCode))) {
|
|
337
|
+
const retryDelay = typeof context.options.retryDelay === "function" ? context.options.retryDelay(context) : context.options.retryDelay || 0;
|
|
338
|
+
if (retryDelay > 0) await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
339
|
+
return $fetchRaw(context.request, {
|
|
340
|
+
...context.options,
|
|
341
|
+
retry: retries - 1
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
const error = createFetchError(context);
|
|
346
|
+
if (Error.captureStackTrace) Error.captureStackTrace(error, $fetchRaw);
|
|
347
|
+
throw error;
|
|
348
|
+
}
|
|
349
|
+
const $fetchRaw = async function $fetchRaw2(_request, _options = {}) {
|
|
350
|
+
const context = {
|
|
351
|
+
request: _request,
|
|
352
|
+
options: resolveFetchOptions(_request, _options, globalOptions.defaults, Headers),
|
|
353
|
+
response: void 0,
|
|
354
|
+
error: void 0
|
|
355
|
+
};
|
|
356
|
+
if (context.options.method) context.options.method = context.options.method.toUpperCase();
|
|
357
|
+
if (context.options.onRequest) {
|
|
358
|
+
await callHooks(context, context.options.onRequest);
|
|
359
|
+
if (!(context.options.headers instanceof Headers)) context.options.headers = new Headers(context.options.headers || {});
|
|
360
|
+
}
|
|
361
|
+
if (typeof context.request === "string") {
|
|
362
|
+
if (context.options.baseURL) context.request = withBase(context.request, context.options.baseURL);
|
|
363
|
+
if (context.options.query) {
|
|
364
|
+
context.request = withQuery(context.request, context.options.query);
|
|
365
|
+
delete context.options.query;
|
|
366
|
+
}
|
|
367
|
+
if ("query" in context.options) delete context.options.query;
|
|
368
|
+
if ("params" in context.options) delete context.options.params;
|
|
369
|
+
}
|
|
370
|
+
if (context.options.body && isPayloadMethod(context.options.method)) {
|
|
371
|
+
if (isJSONSerializable(context.options.body)) {
|
|
372
|
+
const contentType = context.options.headers.get("content-type");
|
|
373
|
+
if (typeof context.options.body !== "string") context.options.body = contentType === "application/x-www-form-urlencoded" ? new URLSearchParams(context.options.body).toString() : JSON.stringify(context.options.body);
|
|
374
|
+
if (!contentType) context.options.headers.set("content-type", "application/json");
|
|
375
|
+
if (!context.options.headers.has("accept")) context.options.headers.set("accept", "application/json");
|
|
376
|
+
} else if ("pipeTo" in context.options.body && typeof context.options.body.pipeTo === "function" || typeof context.options.body.pipe === "function") {
|
|
377
|
+
if (!("duplex" in context.options)) context.options.duplex = "half";
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
let abortTimeout;
|
|
381
|
+
if (!context.options.signal && context.options.timeout) {
|
|
382
|
+
const controller = new AbortController();
|
|
383
|
+
abortTimeout = setTimeout(() => {
|
|
384
|
+
const error = new Error("[TimeoutError]: The operation was aborted due to timeout");
|
|
385
|
+
error.name = "TimeoutError";
|
|
386
|
+
error.code = 23;
|
|
387
|
+
controller.abort(error);
|
|
388
|
+
}, context.options.timeout);
|
|
389
|
+
context.options.signal = controller.signal;
|
|
390
|
+
}
|
|
391
|
+
try {
|
|
392
|
+
context.response = await fetch(context.request, context.options);
|
|
393
|
+
} catch (error) {
|
|
394
|
+
context.error = error;
|
|
395
|
+
if (context.options.onRequestError) await callHooks(context, context.options.onRequestError);
|
|
396
|
+
return await onError(context);
|
|
397
|
+
} finally {
|
|
398
|
+
if (abortTimeout) clearTimeout(abortTimeout);
|
|
399
|
+
}
|
|
400
|
+
if ((context.response.body || context.response._bodyInit) && !nullBodyResponses.has(context.response.status) && context.options.method !== "HEAD") {
|
|
401
|
+
const responseType = (context.options.parseResponse ? "json" : context.options.responseType) || detectResponseType(context.response.headers.get("content-type") || "");
|
|
402
|
+
switch (responseType) {
|
|
403
|
+
case "json": {
|
|
404
|
+
const data = await context.response.text();
|
|
405
|
+
const parseFunction = context.options.parseResponse || destr;
|
|
406
|
+
context.response._data = parseFunction(data);
|
|
407
|
+
break;
|
|
408
|
+
}
|
|
409
|
+
case "stream":
|
|
410
|
+
context.response._data = context.response.body || context.response._bodyInit;
|
|
411
|
+
break;
|
|
412
|
+
default: context.response._data = await context.response[responseType]();
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
if (context.options.onResponse) await callHooks(context, context.options.onResponse);
|
|
416
|
+
if (!context.options.ignoreResponseError && context.response.status >= 400 && context.response.status < 600) {
|
|
417
|
+
if (context.options.onResponseError) await callHooks(context, context.options.onResponseError);
|
|
418
|
+
return await onError(context);
|
|
419
|
+
}
|
|
420
|
+
return context.response;
|
|
421
|
+
};
|
|
422
|
+
const $fetch = async function $fetch2(request, options) {
|
|
423
|
+
return (await $fetchRaw(request, options))._data;
|
|
432
424
|
};
|
|
425
|
+
$fetch.raw = $fetchRaw;
|
|
426
|
+
$fetch.native = (...args) => fetch(...args);
|
|
427
|
+
$fetch.create = (defaultOptions = {}, customGlobalOptions = {}) => createFetch({
|
|
428
|
+
...globalOptions,
|
|
429
|
+
...customGlobalOptions,
|
|
430
|
+
defaults: {
|
|
431
|
+
...globalOptions.defaults,
|
|
432
|
+
...customGlobalOptions.defaults,
|
|
433
|
+
...defaultOptions
|
|
434
|
+
}
|
|
435
|
+
});
|
|
436
|
+
return $fetch;
|
|
433
437
|
}
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
438
|
+
//#endregion
|
|
439
|
+
//#region src/errors.ts
|
|
440
|
+
const messages = {
|
|
441
|
+
invalid_credentials: "The credentials are invalid.",
|
|
442
|
+
invalid_auth_input: "The authentication input is invalid.",
|
|
443
|
+
account_conflict: "The account is not available.",
|
|
444
|
+
social_signup_required: "No account is available for this social sign-in. Start sign-up to create one.",
|
|
445
|
+
google_recovery_in_progress: "A Google connection is already being completed. Return to that sign-in, or wait up to ten minutes and restart.",
|
|
446
|
+
google_recovery_not_required: "Google account recovery is not required.",
|
|
447
|
+
google_recovery_invalid: "The Google account recovery request is invalid.",
|
|
448
|
+
google_recovery_expired: "Google account recovery has expired. Start Google sign-in again.",
|
|
449
|
+
google_recovery_account_mismatch: "Sign in to the existing account associated with this Google identity.",
|
|
450
|
+
password_reset_invalid: "The password reset request is invalid.",
|
|
451
|
+
authentication_required: "Authentication is required.",
|
|
452
|
+
request_origin_denied: "The request origin is not allowed.",
|
|
453
|
+
invalid_request: "The request is invalid.",
|
|
454
|
+
invalid_invitation: "The invitation is invalid.",
|
|
455
|
+
invitation_unavailable: "The invitation is not available.",
|
|
456
|
+
recipient_unavailable: "The recipient is unavailable.",
|
|
457
|
+
invitation_recipient_mismatch: "The invitation cannot be accepted by this account.",
|
|
458
|
+
invitation_recovery_required: "Invitation administration requires separate recovery.",
|
|
459
|
+
membership_removal_recovery_required: "Membership removal requires separate recovery.",
|
|
460
|
+
email_verification_required: "Email verification is required.",
|
|
461
|
+
invalid_workspace_selection: "The workspace selection is invalid.",
|
|
462
|
+
organization_context_too_large: "The organization context is too large.",
|
|
463
|
+
credential_rate_limited: "Credential requests are temporarily limited.",
|
|
464
|
+
auth_request_rate_limited: "Authentication requests are temporarily limited.",
|
|
465
|
+
organization_slug_unavailable: "The organization address is unavailable.",
|
|
466
|
+
state_conflict: "The authentication state conflicts with the request.",
|
|
467
|
+
access_denied: "Access is denied.",
|
|
468
|
+
platform_target_unavailable: "The platform administration target is unavailable.",
|
|
469
|
+
platform_quorum_unavailable: "Platform administration quorum is unavailable.",
|
|
470
|
+
platform_recovery_required: "Platform administration requires separate recovery.",
|
|
471
|
+
identity_authority_unavailable: "Authentication is temporarily unavailable.",
|
|
472
|
+
two_factor_required: "A second authentication factor is required.",
|
|
473
|
+
two_factor_code_invalid: "The verification code is invalid.",
|
|
474
|
+
two_factor_challenge_expired: "The second-factor challenge has ended. Sign in again.",
|
|
475
|
+
two_factor_locked: "Second-factor verification is temporarily locked.",
|
|
476
|
+
recent_sign_in_required: "A recent sign-in is required.",
|
|
477
|
+
enterprise_recovery_required: "Enterprise administration evidence requires operator recovery.",
|
|
478
|
+
recent_authentication_required: "A ready recent-authentication action is required.",
|
|
479
|
+
organization_closure_confirmation_mismatch: "The confirmation does not match the organization.",
|
|
480
|
+
organization_closure_cancellation_ended: "The closure cancellation period has ended.",
|
|
481
|
+
ceremony_return_refused: "The return address is not registered for this application.",
|
|
482
|
+
password_sign_in_required: "A password sign-in method is required for this passkey change."
|
|
483
|
+
};
|
|
484
|
+
var AuthError = class extends Error {
|
|
485
|
+
code;
|
|
486
|
+
status;
|
|
487
|
+
retryAfterSeconds;
|
|
488
|
+
constructor(code, status, retryAfterSeconds) {
|
|
489
|
+
super(messages[code]);
|
|
490
|
+
this.name = "AuthError";
|
|
491
|
+
this.code = code;
|
|
492
|
+
this.status = status;
|
|
493
|
+
this.retryAfterSeconds = retryAfterSeconds;
|
|
494
|
+
}
|
|
495
|
+
};
|
|
496
|
+
//#endregion
|
|
497
|
+
//#region src/shared.ts
|
|
498
|
+
const DRIVE_CREDENTIAL_LIFETIME_SECONDS = 840;
|
|
499
|
+
const id$3 = /^[A-Za-z0-9_-]{1,128}$/;
|
|
500
|
+
const email = /^[^\s@]+@[^\s@]+$/;
|
|
501
|
+
const MAX_SOCIAL_ID_TOKEN_BYTES = 16 * 1024;
|
|
502
|
+
function normalizeEmail(value) {
|
|
503
|
+
if (typeof value !== "string") throw new TypeError("email is invalid");
|
|
504
|
+
const normalized = value.trim().toLowerCase();
|
|
505
|
+
if (normalized.length === 0 || normalized.length > 320 || !email.test(normalized)) throw new TypeError("email is invalid");
|
|
506
|
+
return normalized;
|
|
507
|
+
}
|
|
508
|
+
function normalizeSocialIdTokenInput(value) {
|
|
509
|
+
if (!isObject$1(value)) throw new TypeError("social ID token input is invalid");
|
|
510
|
+
const keys = Object.keys(value);
|
|
511
|
+
if (keys.length !== 3 && keys.length !== 4 || keys.some((key) => key !== "provider" && key !== "idToken" && key !== "nonce" && key !== "signUp") || value.provider !== "google" && value.provider !== "apple" || typeof value.signUp !== "boolean" || typeof value.idToken !== "string" || value.idToken.length < 1 || new TextEncoder().encode(value.idToken).byteLength > MAX_SOCIAL_ID_TOKEN_BYTES || !/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(value.idToken) || value.nonce !== void 0 && (typeof value.nonce !== "string" || value.nonce.length < 1 || value.nonce.length > 256 || !/^[\x20-\x7e]+$/.test(value.nonce))) throw new TypeError("social ID token input is invalid");
|
|
451
512
|
return {
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
slug: value.organization.slug,
|
|
457
|
-
logo: nullableHttpsUrl(value.organization.logo)
|
|
458
|
-
},
|
|
459
|
-
role: value.role,
|
|
460
|
-
teams: unique(value.teams.map((team) => {
|
|
461
|
-
exact$3(team, ["id", "name"]);
|
|
462
|
-
if (!isId(team.id) || !boundedString(team.name, 255)) throw authorityUnavailable();
|
|
463
|
-
return {
|
|
464
|
-
id: team.id,
|
|
465
|
-
name: team.name
|
|
466
|
-
};
|
|
467
|
-
}), (item) => item.id),
|
|
468
|
-
inviterName: value.inviterName,
|
|
469
|
-
expiresAt: responseDate(value.expiresAt)
|
|
513
|
+
provider: value.provider,
|
|
514
|
+
idToken: value.idToken,
|
|
515
|
+
...value.nonce === void 0 ? {} : { nonce: value.nonce },
|
|
516
|
+
signUp: value.signUp
|
|
470
517
|
};
|
|
471
518
|
}
|
|
472
|
-
function
|
|
473
|
-
exact$3(value, ["invitations", "nextCursor"]);
|
|
474
|
-
if (!Array.isArray(value.invitations) || value.invitations.length > 100) throw authorityUnavailable();
|
|
519
|
+
function socialIdTokenRequest(value) {
|
|
475
520
|
return {
|
|
476
|
-
|
|
477
|
-
|
|
521
|
+
provider: value.provider,
|
|
522
|
+
idToken: {
|
|
523
|
+
token: value.idToken,
|
|
524
|
+
...value.nonce === void 0 ? {} : { nonce: value.nonce }
|
|
525
|
+
},
|
|
526
|
+
requestSignUp: value.signUp
|
|
478
527
|
};
|
|
479
528
|
}
|
|
480
|
-
function
|
|
481
|
-
if (
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
529
|
+
function normalizeOrigin(value, name) {
|
|
530
|
+
if (value.length === 0 || value.length > 2048 || /[^\x20-\x7e]/.test(value)) throw new TypeError(`${name} must be an ASCII HTTP origin`);
|
|
531
|
+
let url;
|
|
532
|
+
try {
|
|
533
|
+
url = new URL(value);
|
|
534
|
+
} catch {
|
|
535
|
+
throw new TypeError(`${name} must be an ASCII HTTP origin`);
|
|
536
|
+
}
|
|
537
|
+
const local = url.hostname === "localhost" || url.hostname.endsWith(".localhost") || url.hostname === "127.0.0.1";
|
|
538
|
+
if (url.protocol !== "https:" && !(local && url.protocol === "http:") || url.username || url.password || url.pathname !== "/" || url.search || url.hash || url.origin !== value) throw new TypeError(`${name} must be an ASCII HTTP origin`);
|
|
539
|
+
return url.origin;
|
|
487
540
|
}
|
|
488
|
-
function
|
|
489
|
-
|
|
490
|
-
|
|
541
|
+
function normalizeTimeout(value) {
|
|
542
|
+
const timeout = value ?? 1e4;
|
|
543
|
+
if (!Number.isSafeInteger(timeout) || timeout < 1 || timeout > 6e4) throw new TypeError("timeoutMs must be an integer from 1 to 60000");
|
|
544
|
+
return timeout;
|
|
491
545
|
}
|
|
492
|
-
function
|
|
493
|
-
if (
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
546
|
+
function normalizeSession(value) {
|
|
547
|
+
if (value === null) return null;
|
|
548
|
+
if (!isObject$1(value) || !isObject$1(value.session) || !isObject$1(value.user)) throw authorityUnavailable();
|
|
549
|
+
const expiresAt = toDate(value.session.expiresAt);
|
|
550
|
+
const image = value.user.image;
|
|
551
|
+
if (!isId(value.session.id) || !expiresAt || !isId(value.user.id) || typeof value.user.name !== "string" || value.user.name.length > 256 || typeof value.user.email !== "string" || value.user.email.length > 320 || !email.test(value.user.email) || typeof value.user.emailVerified !== "boolean" || image !== null && image !== void 0 && (typeof image !== "string" || image.length > 2048)) throw authorityUnavailable();
|
|
552
|
+
return {
|
|
553
|
+
id: value.session.id,
|
|
554
|
+
expiresAt,
|
|
555
|
+
user: {
|
|
556
|
+
id: value.user.id,
|
|
557
|
+
name: value.user.name,
|
|
558
|
+
email: value.user.email,
|
|
559
|
+
emailVerified: value.user.emailVerified,
|
|
560
|
+
image: image ?? null
|
|
561
|
+
}
|
|
499
562
|
};
|
|
500
|
-
throw new AuthError("invalid_workspace_selection", 422);
|
|
501
|
-
}
|
|
502
|
-
function fromAuthorityError(value, fallbackStatus, retryAfter) {
|
|
503
|
-
const mapped = mapError(isObject$1(value) && typeof value.code === "string" ? value.code : void 0, fallbackStatus);
|
|
504
|
-
return new AuthError(mapped.code, mapped.status, parseRetryAfter(retryAfter));
|
|
505
563
|
}
|
|
506
|
-
function
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
if (status === 401) return new AuthError("authentication_required", 401);
|
|
514
|
-
if (status === 403) return new AuthError("access_denied", 403);
|
|
515
|
-
if (status === 409) return new AuthError("state_conflict", 409);
|
|
516
|
-
if (status === 429) return new AuthError("auth_request_rate_limited", 429, parseRetryAfter(retryAfter));
|
|
517
|
-
if (status === 400 || status === 422) return new AuthError("invalid_auth_input", 422);
|
|
518
|
-
return authorityUnavailable();
|
|
564
|
+
function normalizeDriveCredential(value, now) {
|
|
565
|
+
if (!isObject$1(value) || value.tokenType !== "Bearer" || value.expiresIn !== DRIVE_CREDENTIAL_LIFETIME_SECONDS || typeof value.token !== "string" || value.token.length === 0 || new TextEncoder().encode(`Bearer ${value.token}`).byteLength > 16 * 1024) throw authorityUnavailable();
|
|
566
|
+
return {
|
|
567
|
+
tokenType: "Bearer",
|
|
568
|
+
token: value.token,
|
|
569
|
+
expiresAt: new Date(now + value.expiresIn * 1e3)
|
|
570
|
+
};
|
|
519
571
|
}
|
|
520
|
-
function
|
|
521
|
-
|
|
522
|
-
if (
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
if (
|
|
527
|
-
|
|
572
|
+
function normalizeOrganizationPageInput(value) {
|
|
573
|
+
if (value === void 0) return new URLSearchParams();
|
|
574
|
+
if (!isObject$1(value) || Object.keys(value).some((key) => key !== "limit" && key !== "cursor")) throw new AuthError("invalid_request", 400);
|
|
575
|
+
const input = value;
|
|
576
|
+
const query = new URLSearchParams();
|
|
577
|
+
if (input.limit !== void 0) {
|
|
578
|
+
if (!Number.isSafeInteger(input.limit) || input.limit < 1 || input.limit > 100) throw new AuthError("invalid_request", 400);
|
|
579
|
+
query.set("limit", String(input.limit));
|
|
528
580
|
}
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
function fromOrganizationListError(error) {
|
|
535
|
-
if (error instanceof AuthError && error.status === 401) return new AuthError("authentication_required", 401);
|
|
536
|
-
if (error instanceof AuthError) return error;
|
|
537
|
-
return authorityUnavailable();
|
|
538
|
-
}
|
|
539
|
-
function fromOrganizationReadAuthorityError(value, status) {
|
|
540
|
-
if (status === 400) return new AuthError("invalid_request", 400);
|
|
541
|
-
if (status === 401) return new AuthError("authentication_required", 401);
|
|
542
|
-
if (status === 403) return new AuthError("access_denied", 403);
|
|
543
|
-
return authorityUnavailable();
|
|
544
|
-
}
|
|
545
|
-
function fromOrganizationMutationAuthorityError(value, status, retryAfter) {
|
|
546
|
-
if (status === 400 || status === 413 || status === 415) return new AuthError("invalid_request", 400);
|
|
547
|
-
if (status === 409 && isObject$1(value) && value.code === "ORGANIZATION_SLUG_UNAVAILABLE") return new AuthError("organization_slug_unavailable", 409);
|
|
548
|
-
if (status === 409) return new AuthError("state_conflict", 409);
|
|
549
|
-
if (status === 429) return new AuthError("auth_request_rate_limited", 429, parseRetryAfter(retryAfter));
|
|
550
|
-
const code = isObject$1(value) && typeof value.code === "string" ? value.code : void 0;
|
|
551
|
-
if (status === 403 && code === "REQUEST_ORIGIN_DENIED") return new AuthError("request_origin_denied", 403);
|
|
552
|
-
return fromOrganizationReadAuthorityError(value, status);
|
|
581
|
+
if (input.cursor !== void 0) {
|
|
582
|
+
if (typeof input.cursor !== "string" || input.cursor.length < 1 || input.cursor.length > 820 || !/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(input.cursor)) throw new AuthError("invalid_request", 400);
|
|
583
|
+
query.set("cursor", input.cursor);
|
|
584
|
+
}
|
|
585
|
+
return query;
|
|
553
586
|
}
|
|
554
|
-
function
|
|
555
|
-
if (
|
|
556
|
-
|
|
587
|
+
function normalizeOrganizationMemberPageInput(value) {
|
|
588
|
+
if (value === void 0) return new URLSearchParams();
|
|
589
|
+
if (!isObject$1(value) || Object.keys(value).some((key) => ![
|
|
590
|
+
"limit",
|
|
591
|
+
"cursor",
|
|
592
|
+
"search"
|
|
593
|
+
].includes(key))) throw new AuthError("invalid_request", 400);
|
|
594
|
+
const { search, ...page } = value;
|
|
595
|
+
const query = normalizeOrganizationPageInput(page);
|
|
596
|
+
if (search !== void 0) {
|
|
597
|
+
if (typeof search !== "string") throw new AuthError("invalid_request", 400);
|
|
598
|
+
const prefix = search.trim().replace(/[A-Z]/g, (character) => character.toLowerCase());
|
|
599
|
+
if (!prefix || prefix.length > 128 || Array.from(prefix).some((character) => character.charCodeAt(0) < 32 || character.charCodeAt(0) === 127)) throw new AuthError("invalid_request", 400);
|
|
600
|
+
query.set("search", prefix);
|
|
601
|
+
}
|
|
602
|
+
return query;
|
|
557
603
|
}
|
|
558
|
-
function
|
|
559
|
-
if (
|
|
560
|
-
return
|
|
604
|
+
function normalizeIdInput(value) {
|
|
605
|
+
if (!isId(value)) throw new AuthError("invalid_request", 400);
|
|
606
|
+
return value;
|
|
561
607
|
}
|
|
562
|
-
function
|
|
563
|
-
exact$
|
|
564
|
-
"
|
|
565
|
-
"
|
|
566
|
-
"
|
|
608
|
+
function normalizeOrganization(value) {
|
|
609
|
+
exact$6(value, [
|
|
610
|
+
"capabilities",
|
|
611
|
+
"id",
|
|
612
|
+
"lifecycle",
|
|
613
|
+
"logo",
|
|
614
|
+
"name",
|
|
615
|
+
"role",
|
|
616
|
+
"slug"
|
|
567
617
|
]);
|
|
568
|
-
if (!isId(value.
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
618
|
+
if (!isId(value.id) || !boundedString(value.name, 255) || !boundedString(value.slug, 255) || value.lifecycle !== "ordinary" && value.lifecycle !== "managed" || !role(value.role) || !isObject$1(value.capabilities)) throw authorityUnavailable();
|
|
619
|
+
exact$6(value.capabilities, [
|
|
620
|
+
"readInvitations",
|
|
621
|
+
"readMembers",
|
|
622
|
+
"readTeams"
|
|
623
|
+
]);
|
|
624
|
+
if (value.capabilities.readMembers !== true || value.capabilities.readTeams !== true || typeof value.capabilities.readInvitations !== "boolean") throw authorityUnavailable();
|
|
574
625
|
return {
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
626
|
+
id: value.id,
|
|
627
|
+
name: value.name,
|
|
628
|
+
slug: value.slug,
|
|
629
|
+
logo: nullableHttpsUrl(value.logo),
|
|
630
|
+
lifecycle: value.lifecycle,
|
|
631
|
+
role: value.role,
|
|
632
|
+
capabilities: {
|
|
633
|
+
readMembers: true,
|
|
634
|
+
readTeams: true,
|
|
635
|
+
readInvitations: value.capabilities.readInvitations
|
|
636
|
+
}
|
|
578
637
|
};
|
|
579
638
|
}
|
|
580
|
-
function
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
639
|
+
function normalizeOrganizationDisplayInput(value) {
|
|
640
|
+
if (!isObject$1(value) || Object.keys(value).sort().join(",") !== "logo,name,slug") throw new AuthError("invalid_request", 400);
|
|
641
|
+
if (!boundedString(value.name, 255) || !boundedString(value.slug, 255)) throw new AuthError("invalid_request", 400);
|
|
642
|
+
let logo;
|
|
643
|
+
try {
|
|
644
|
+
logo = nullableHttpsUrl(value.logo);
|
|
645
|
+
} catch {
|
|
646
|
+
throw new AuthError("invalid_request", 400);
|
|
647
|
+
}
|
|
589
648
|
return {
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
authorityRevision: normalizeAuthorityResultRevision(value.authorityRevision)
|
|
649
|
+
name: value.name,
|
|
650
|
+
slug: value.slug,
|
|
651
|
+
logo
|
|
594
652
|
};
|
|
595
653
|
}
|
|
596
|
-
function
|
|
597
|
-
|
|
598
|
-
|
|
654
|
+
function normalizeOrganizationDisplay(value) {
|
|
655
|
+
try {
|
|
656
|
+
return normalizeOrganizationDisplayInput(value);
|
|
657
|
+
} catch {
|
|
658
|
+
throw authorityUnavailable();
|
|
659
|
+
}
|
|
599
660
|
}
|
|
600
|
-
function
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
if (status === 403 && (code === "INVALID_ORIGIN" || code === "MISSING_OR_NULL_ORIGIN")) return new AuthError("request_origin_denied", 403);
|
|
604
|
-
if (status === 403 && code === "YOU_ARE_NOT_THE_RECIPIENT_OF_THE_INVITATION") return new AuthError("invitation_recipient_mismatch", 403);
|
|
605
|
-
if (status === 403 && code === "EMAIL_VERIFICATION_REQUIRED_BEFORE_ACCEPTING_OR_REJECTING_INVITATION") return new AuthError("email_verification_required", 403);
|
|
606
|
-
if (status === 400 && (code === "INVITATION_NOT_FOUND" || code === "ORGANIZATION_NOT_FOUND" || code === "TEAM_NOT_FOUND")) return new AuthError("invitation_unavailable", 409);
|
|
607
|
-
return authorityUnavailable();
|
|
661
|
+
function normalizeOrganizationTeamDisplayInput(value) {
|
|
662
|
+
if (!isObject$1(value) || Object.keys(value).join(",") !== "name" || !boundedString(value.name, 255)) throw new AuthError("invalid_request", 400);
|
|
663
|
+
return { name: value.name };
|
|
608
664
|
}
|
|
609
|
-
function
|
|
610
|
-
|
|
665
|
+
function normalizeOrganizationTeamDisplay(value) {
|
|
666
|
+
try {
|
|
667
|
+
return normalizeOrganizationTeamDisplayInput(value);
|
|
668
|
+
} catch {
|
|
669
|
+
throw authorityUnavailable();
|
|
670
|
+
}
|
|
611
671
|
}
|
|
612
|
-
function
|
|
613
|
-
if (
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
code,
|
|
619
|
-
status: 403
|
|
620
|
-
};
|
|
621
|
-
if (code === "invalid_workspace_selection") return {
|
|
622
|
-
code,
|
|
623
|
-
status: 422
|
|
624
|
-
};
|
|
625
|
-
if (code === "organization_context_too_large") return {
|
|
626
|
-
code,
|
|
627
|
-
status: 422
|
|
628
|
-
};
|
|
629
|
-
if (code === "credential_rate_limited") return {
|
|
630
|
-
code,
|
|
631
|
-
status: 429
|
|
632
|
-
};
|
|
633
|
-
if (code === "identity_authority_unavailable") return {
|
|
634
|
-
code,
|
|
635
|
-
status: 503
|
|
636
|
-
};
|
|
637
|
-
if (status === 401 || status === 400) return {
|
|
638
|
-
code: "invalid_credentials",
|
|
639
|
-
status: 401
|
|
640
|
-
};
|
|
641
|
-
if (status === 403) return {
|
|
642
|
-
code: "access_denied",
|
|
643
|
-
status: 403
|
|
644
|
-
};
|
|
645
|
-
if (status === 409) return {
|
|
646
|
-
code: "state_conflict",
|
|
647
|
-
status: 409
|
|
648
|
-
};
|
|
649
|
-
if (status === 422) return {
|
|
650
|
-
code: "invalid_workspace_selection",
|
|
651
|
-
status: 422
|
|
672
|
+
function normalizeOrganizationCreationInput(name, slug, idempotencyKey) {
|
|
673
|
+
if (!boundedString(name, 255) || !boundedString(idempotencyKey, 255) || typeof slug !== "string" || !/^[a-z0-9-]{1,128}$/.test(slug)) throw new AuthError("invalid_request", 400);
|
|
674
|
+
return {
|
|
675
|
+
name,
|
|
676
|
+
slug,
|
|
677
|
+
idempotencyKey
|
|
652
678
|
};
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
679
|
+
}
|
|
680
|
+
function normalizeCreatedOrganization(value) {
|
|
681
|
+
exact$6(value, [
|
|
682
|
+
"id",
|
|
683
|
+
"name",
|
|
684
|
+
"slug"
|
|
685
|
+
]);
|
|
686
|
+
if (!isId(value.id) || !boundedString(value.name, 255) || !boundedString(value.slug, 128)) throw authorityUnavailable();
|
|
687
|
+
return {
|
|
688
|
+
id: value.id,
|
|
689
|
+
name: value.name,
|
|
690
|
+
slug: value.slug
|
|
656
691
|
};
|
|
692
|
+
}
|
|
693
|
+
function normalizeOrganizationTeamCreationInput(name, idempotencyKey) {
|
|
694
|
+
if (!boundedString(name, 255) || !boundedString(idempotencyKey, 255)) throw new AuthError("invalid_request", 400);
|
|
657
695
|
return {
|
|
658
|
-
|
|
659
|
-
|
|
696
|
+
name,
|
|
697
|
+
idempotencyKey
|
|
660
698
|
};
|
|
661
699
|
}
|
|
662
|
-
function
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
return
|
|
700
|
+
function normalizeCreatedOrganizationTeam(value) {
|
|
701
|
+
exact$6(value, ["id", "name"]);
|
|
702
|
+
if (!isId(value.id) || !boundedString(value.name, 255)) throw authorityUnavailable();
|
|
703
|
+
return {
|
|
704
|
+
id: value.id,
|
|
705
|
+
name: value.name
|
|
706
|
+
};
|
|
666
707
|
}
|
|
667
|
-
function
|
|
668
|
-
|
|
669
|
-
|
|
708
|
+
function normalizeOrganizationMemberInvitationCreationInput(value) {
|
|
709
|
+
if (!isObject$1(value)) throw new AuthError("invalid_request", 400);
|
|
710
|
+
const keys = Object.keys(value).sort().join(",");
|
|
711
|
+
if (keys !== "email,idempotencyKey" && keys !== "email,idempotencyKey,teamIds") throw new AuthError("invalid_request", 400);
|
|
712
|
+
let normalizedEmail;
|
|
713
|
+
try {
|
|
714
|
+
normalizedEmail = normalizeEmail(value.email);
|
|
715
|
+
} catch {
|
|
716
|
+
throw new AuthError("invalid_request", 400);
|
|
717
|
+
}
|
|
718
|
+
if (new TextEncoder().encode(normalizedEmail).byteLength > 320 || !boundedString(value.idempotencyKey, 255) || value.teamIds !== void 0 && (!Array.isArray(value.teamIds) || value.teamIds.length > 100)) throw new AuthError("invalid_request", 400);
|
|
719
|
+
const teamIds = value.teamIds?.map((teamId) => normalizeIdInput(teamId));
|
|
720
|
+
if (teamIds && new Set(teamIds).size !== teamIds.length) throw new AuthError("invalid_request", 400);
|
|
721
|
+
return {
|
|
722
|
+
email: normalizedEmail,
|
|
723
|
+
...teamIds === void 0 ? {} : { teamIds },
|
|
724
|
+
idempotencyKey: value.idempotencyKey
|
|
725
|
+
};
|
|
670
726
|
}
|
|
671
|
-
function
|
|
672
|
-
|
|
727
|
+
function normalizeCreatedOrganizationMemberInvitation(value) {
|
|
728
|
+
exact$6(value, ["expiresAt", "id"]);
|
|
729
|
+
if (!isId(value.id)) throw authorityUnavailable();
|
|
730
|
+
return {
|
|
731
|
+
id: value.id,
|
|
732
|
+
expiresAt: responseDate(value.expiresAt)
|
|
733
|
+
};
|
|
673
734
|
}
|
|
674
|
-
function
|
|
675
|
-
|
|
735
|
+
function normalizeResentOrganizationInvitation(value, invitationId) {
|
|
736
|
+
const invitation = normalizeCreatedOrganizationMemberInvitation(value);
|
|
737
|
+
if (invitation.id !== invitationId) throw authorityUnavailable();
|
|
738
|
+
return invitation;
|
|
676
739
|
}
|
|
677
|
-
function
|
|
678
|
-
|
|
740
|
+
function normalizeOrganizationInvitationAdministrationInput(idempotencyKey) {
|
|
741
|
+
if (!boundedString(idempotencyKey, 255)) throw new AuthError("invalid_request", 400);
|
|
742
|
+
return { idempotencyKey };
|
|
679
743
|
}
|
|
680
|
-
function
|
|
681
|
-
|
|
744
|
+
function normalizeCanceledOrganizationInvitation(value) {
|
|
745
|
+
exact$6(value, ["status"]);
|
|
746
|
+
if (value.status !== "canceled") throw authorityUnavailable();
|
|
747
|
+
return { status: "canceled" };
|
|
682
748
|
}
|
|
683
|
-
function
|
|
684
|
-
if (
|
|
685
|
-
|
|
686
|
-
let url;
|
|
687
|
-
try {
|
|
688
|
-
url = new URL(value);
|
|
689
|
-
} catch {
|
|
690
|
-
throw authorityUnavailable();
|
|
691
|
-
}
|
|
692
|
-
if (url.protocol !== "https:" || url.username || url.password || url.toString() !== value) throw authorityUnavailable();
|
|
693
|
-
return value;
|
|
749
|
+
function normalizeOrganizationMembershipRemovalInput(idempotencyKey) {
|
|
750
|
+
if (!boundedString(idempotencyKey, 255)) throw new AuthError("invalid_request", 400);
|
|
751
|
+
return { idempotencyKey };
|
|
694
752
|
}
|
|
695
|
-
function
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
return date;
|
|
753
|
+
function normalizeRemovedOrganizationMember(value) {
|
|
754
|
+
exact$6(value, ["status"]);
|
|
755
|
+
if (value.status !== "removed") throw authorityUnavailable();
|
|
756
|
+
return { status: "removed" };
|
|
700
757
|
}
|
|
701
|
-
function
|
|
702
|
-
|
|
703
|
-
if (
|
|
704
|
-
return
|
|
758
|
+
function normalizeOrganizationDeparture(value) {
|
|
759
|
+
exact$6(value, ["status"]);
|
|
760
|
+
if (value.status !== "left") throw authorityUnavailable();
|
|
761
|
+
return { status: "left" };
|
|
705
762
|
}
|
|
706
|
-
function
|
|
707
|
-
if (!
|
|
708
|
-
return
|
|
763
|
+
function normalizeOrganizationTeamMembershipInput(idempotencyKey) {
|
|
764
|
+
if (!boundedString(idempotencyKey, 255)) throw new AuthError("invalid_request", 400);
|
|
765
|
+
return { idempotencyKey };
|
|
709
766
|
}
|
|
710
|
-
function
|
|
711
|
-
|
|
712
|
-
|
|
767
|
+
function normalizeAddedOrganizationTeamMember(value) {
|
|
768
|
+
exact$6(value, ["status"]);
|
|
769
|
+
if (value.status !== "added") throw authorityUnavailable();
|
|
770
|
+
return { status: "added" };
|
|
713
771
|
}
|
|
714
|
-
function
|
|
715
|
-
|
|
772
|
+
function normalizeRemovedOrganizationTeamMember(value) {
|
|
773
|
+
exact$6(value, ["status"]);
|
|
774
|
+
if (value.status !== "removed") throw authorityUnavailable();
|
|
775
|
+
return { status: "removed" };
|
|
716
776
|
}
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
return
|
|
777
|
+
function normalizeDeletedOrganizationTeam(value) {
|
|
778
|
+
exact$6(value, ["status"]);
|
|
779
|
+
if (value.status !== "deleted") throw authorityUnavailable();
|
|
780
|
+
return { status: "deleted" };
|
|
721
781
|
}
|
|
722
|
-
function
|
|
723
|
-
|
|
782
|
+
function normalizeOrganizations(value) {
|
|
783
|
+
exact$6(value, ["nextCursor", "organizations"]);
|
|
784
|
+
if (!Array.isArray(value.organizations) || value.organizations.length > 100) throw authorityUnavailable();
|
|
785
|
+
return {
|
|
786
|
+
organizations: unique(value.organizations.map(normalizeOrganization), (item) => item.id),
|
|
787
|
+
nextCursor: nullableCursor(value.nextCursor)
|
|
788
|
+
};
|
|
724
789
|
}
|
|
725
|
-
function
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
provider: "google",
|
|
729
|
-
idToken: value.idToken.token,
|
|
730
|
-
signUp: false,
|
|
731
|
-
...value.idToken.nonce === void 0 ? {} : { nonce: value.idToken.nonce }
|
|
732
|
-
});
|
|
790
|
+
function normalizeOrganizationMembers(value) {
|
|
791
|
+
exact$6(value, ["members", "nextCursor"]);
|
|
792
|
+
if (!Array.isArray(value.members) || value.members.length > 100) throw authorityUnavailable();
|
|
733
793
|
return {
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
794
|
+
members: unique(value.members.map((member) => {
|
|
795
|
+
exact$6(member, [
|
|
796
|
+
"email",
|
|
797
|
+
"id",
|
|
798
|
+
"image",
|
|
799
|
+
"joinedAt",
|
|
800
|
+
"name",
|
|
801
|
+
"owner",
|
|
802
|
+
"role",
|
|
803
|
+
"teamIds",
|
|
804
|
+
"userId"
|
|
805
|
+
]);
|
|
806
|
+
if (!isId(member.id) || !isId(member.userId) || !boundedString(member.name, 255) || typeof member.email !== "string" || member.email.length > 320 || !email.test(member.email) || !role(member.role) || typeof member.owner !== "boolean" || !Array.isArray(member.teamIds) || member.teamIds.length > 100) throw authorityUnavailable();
|
|
807
|
+
const teamIds = unique(member.teamIds.map((teamId) => normalizeResponseId(teamId)), (item) => item);
|
|
808
|
+
return {
|
|
809
|
+
id: member.id,
|
|
810
|
+
userId: member.userId,
|
|
811
|
+
name: member.name,
|
|
812
|
+
email: member.email,
|
|
813
|
+
image: nullableHttpsUrl(member.image),
|
|
814
|
+
role: member.role,
|
|
815
|
+
owner: member.owner,
|
|
816
|
+
joinedAt: responseDate(member.joinedAt),
|
|
817
|
+
teamIds
|
|
818
|
+
};
|
|
819
|
+
}), (item) => item.id),
|
|
820
|
+
nextCursor: nullableCursor(value.nextCursor)
|
|
821
|
+
};
|
|
822
|
+
}
|
|
823
|
+
function normalizeOrganizationTeams(value) {
|
|
824
|
+
exact$6(value, ["nextCursor", "teams"]);
|
|
825
|
+
if (!Array.isArray(value.teams) || value.teams.length > 100) throw authorityUnavailable();
|
|
826
|
+
return {
|
|
827
|
+
teams: unique(value.teams.map((team) => {
|
|
828
|
+
exact$6(team, [
|
|
829
|
+
"category",
|
|
830
|
+
"createdAt",
|
|
831
|
+
"id",
|
|
832
|
+
"name"
|
|
833
|
+
]);
|
|
834
|
+
if (!isId(team.id) || !boundedString(team.name, 255) || team.category !== "manual" && team.category !== "managed") throw authorityUnavailable();
|
|
835
|
+
return {
|
|
836
|
+
id: team.id,
|
|
837
|
+
name: team.name,
|
|
838
|
+
category: team.category,
|
|
839
|
+
createdAt: responseDate(team.createdAt)
|
|
840
|
+
};
|
|
841
|
+
}), (item) => item.id),
|
|
842
|
+
nextCursor: nullableCursor(value.nextCursor)
|
|
843
|
+
};
|
|
844
|
+
}
|
|
845
|
+
function normalizeOrganizationTeamMembers(value) {
|
|
846
|
+
exact$6(value, ["memberIds", "nextCursor"]);
|
|
847
|
+
if (!Array.isArray(value.memberIds) || value.memberIds.length > 100) throw authorityUnavailable();
|
|
848
|
+
return {
|
|
849
|
+
memberIds: unique(value.memberIds.map((item) => normalizeResponseId(item)), (item) => item),
|
|
850
|
+
nextCursor: nullableCursor(value.nextCursor)
|
|
851
|
+
};
|
|
852
|
+
}
|
|
853
|
+
function normalizeOrganizationInvitation(value) {
|
|
854
|
+
exact$6(value, [
|
|
855
|
+
"createdAt",
|
|
856
|
+
"email",
|
|
857
|
+
"expiresAt",
|
|
858
|
+
"id",
|
|
859
|
+
"inviter",
|
|
860
|
+
"role",
|
|
861
|
+
"status",
|
|
862
|
+
"teamIds"
|
|
863
|
+
]);
|
|
864
|
+
if (!isId(value.id) || typeof value.email !== "string" || value.email.length > 320 || !email.test(value.email) || !role(value.role) || value.status !== "pending" || !Array.isArray(value.teamIds) || value.teamIds.length > 100 || !isObject$1(value.inviter)) throw authorityUnavailable();
|
|
865
|
+
exact$6(value.inviter, ["membershipId", "name"]);
|
|
866
|
+
if (!isId(value.inviter.membershipId) || !boundedString(value.inviter.name, 255)) throw authorityUnavailable();
|
|
867
|
+
return {
|
|
868
|
+
id: value.id,
|
|
869
|
+
email: value.email,
|
|
870
|
+
role: value.role,
|
|
871
|
+
teamIds: unique(value.teamIds.map(normalizeResponseId), (item) => item),
|
|
872
|
+
inviter: {
|
|
873
|
+
membershipId: value.inviter.membershipId,
|
|
874
|
+
name: value.inviter.name
|
|
737
875
|
},
|
|
738
|
-
|
|
876
|
+
createdAt: responseDate(value.createdAt),
|
|
877
|
+
expiresAt: responseDate(value.expiresAt),
|
|
878
|
+
status: "pending"
|
|
739
879
|
};
|
|
740
880
|
}
|
|
741
|
-
function
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
if (!Number.isFinite(expiresAt) || expiresAt <= now || expiresAt > now + 10 * 6e4) throw authorityUnavailable();
|
|
881
|
+
function normalizeOrganizationInvitations(value) {
|
|
882
|
+
exact$6(value, ["invitations", "nextCursor"]);
|
|
883
|
+
if (!Array.isArray(value.invitations) || value.invitations.length > 100) throw authorityUnavailable();
|
|
745
884
|
return {
|
|
746
|
-
|
|
747
|
-
|
|
885
|
+
invitations: unique(value.invitations.map(normalizeOrganizationInvitation), (item) => item.id),
|
|
886
|
+
nextCursor: nullableCursor(value.nextCursor)
|
|
748
887
|
};
|
|
749
888
|
}
|
|
750
|
-
function
|
|
751
|
-
|
|
752
|
-
|
|
889
|
+
function normalizeReceivedInvitation(value) {
|
|
890
|
+
exact$6(value, [
|
|
891
|
+
"expiresAt",
|
|
892
|
+
"id",
|
|
893
|
+
"inviterName",
|
|
894
|
+
"organization",
|
|
895
|
+
"role",
|
|
896
|
+
"teams"
|
|
897
|
+
]);
|
|
898
|
+
if (!isId(value.id) || !boundedString(value.inviterName, 255) || !role(value.role) || !Array.isArray(value.teams) || value.teams.length > 100 || !isObject$1(value.organization)) throw authorityUnavailable();
|
|
899
|
+
exact$6(value.organization, [
|
|
900
|
+
"id",
|
|
901
|
+
"logo",
|
|
902
|
+
"name",
|
|
903
|
+
"slug"
|
|
904
|
+
]);
|
|
905
|
+
if (!isId(value.organization.id) || !boundedString(value.organization.name, 255) || !boundedString(value.organization.slug, 255)) throw authorityUnavailable();
|
|
906
|
+
return {
|
|
907
|
+
id: value.id,
|
|
908
|
+
organization: {
|
|
909
|
+
id: value.organization.id,
|
|
910
|
+
name: value.organization.name,
|
|
911
|
+
slug: value.organization.slug,
|
|
912
|
+
logo: nullableHttpsUrl(value.organization.logo)
|
|
913
|
+
},
|
|
914
|
+
role: value.role,
|
|
915
|
+
teams: unique(value.teams.map((team) => {
|
|
916
|
+
exact$6(team, ["id", "name"]);
|
|
917
|
+
if (!isId(team.id) || !boundedString(team.name, 255)) throw authorityUnavailable();
|
|
918
|
+
return {
|
|
919
|
+
id: team.id,
|
|
920
|
+
name: team.name
|
|
921
|
+
};
|
|
922
|
+
}), (item) => item.id),
|
|
923
|
+
inviterName: value.inviterName,
|
|
924
|
+
expiresAt: responseDate(value.expiresAt)
|
|
925
|
+
};
|
|
753
926
|
}
|
|
754
|
-
function
|
|
755
|
-
|
|
756
|
-
if (
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
if (status === 403 && code === "GOOGLE_RECOVERY_ACCOUNT_MISMATCH") return new AuthError("google_recovery_account_mismatch", 403);
|
|
762
|
-
if (status === 401 && code === "GOOGLE_RECOVERY_FRESH_SIGN_IN_REQUIRED") return new AuthError("recent_sign_in_required", 401);
|
|
763
|
-
if (code === "GOOGLE_RECOVERY_UNAVAILABLE") return authorityUnavailable();
|
|
764
|
-
return fromAccountAuthorityError(value, status, retryAfter);
|
|
927
|
+
function normalizeReceivedInvitations(value) {
|
|
928
|
+
exact$6(value, ["invitations", "nextCursor"]);
|
|
929
|
+
if (!Array.isArray(value.invitations) || value.invitations.length > 100) throw authorityUnavailable();
|
|
930
|
+
return {
|
|
931
|
+
invitations: unique(value.invitations.map(normalizeReceivedInvitation), (item) => item.id),
|
|
932
|
+
nextCursor: nullableCursor(value.nextCursor)
|
|
933
|
+
};
|
|
765
934
|
}
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
const SLASH_RE = /\//g;
|
|
770
|
-
const EQUAL_RE = /=/g;
|
|
771
|
-
const PLUS_RE = /\+/g;
|
|
772
|
-
const ENC_CARET_RE = /%5e/gi;
|
|
773
|
-
const ENC_BACKTICK_RE = /%60/gi;
|
|
774
|
-
const ENC_PIPE_RE = /%7c/gi;
|
|
775
|
-
const ENC_SPACE_RE = /%20/gi;
|
|
776
|
-
function encode$2(text) {
|
|
777
|
-
return encodeURI("" + text).replace(ENC_PIPE_RE, "|");
|
|
935
|
+
function normalizeInvitationInput(value) {
|
|
936
|
+
if (!isObject$1(value) || Object.keys(value).length !== 1 || !isId(value.invitationId)) throw new AuthError("invalid_invitation", 422);
|
|
937
|
+
return { invitationId: value.invitationId };
|
|
778
938
|
}
|
|
779
|
-
function
|
|
780
|
-
|
|
939
|
+
function normalizeInvitationAcceptance(value, invitationId) {
|
|
940
|
+
if (!isObject$1(value) || !isObject$1(value.invitation) || !isObject$1(value.member) || value.invitation.id !== invitationId || value.invitation.status !== "accepted" || !isId(value.invitation.organizationId) || value.member.organizationId !== value.invitation.organizationId) throw authorityUnavailable();
|
|
941
|
+
return { organizationId: value.invitation.organizationId };
|
|
781
942
|
}
|
|
782
|
-
function
|
|
783
|
-
|
|
943
|
+
function normalizeInvitationDecline(value, invitationId) {
|
|
944
|
+
if (!isObject$1(value) || !isObject$1(value.invitation) || value.invitation.id !== invitationId || value.invitation.status !== "rejected" || value.member !== null) throw authorityUnavailable();
|
|
945
|
+
return { status: "declined" };
|
|
784
946
|
}
|
|
785
|
-
function
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
947
|
+
function normalizeWorkspaceSelection(value) {
|
|
948
|
+
if (!isObject$1(value)) throw new AuthError("invalid_workspace_selection", 422);
|
|
949
|
+
const keys = Object.keys(value);
|
|
950
|
+
if (value.type === "personal" && keys.length === 1 && keys[0] === "type") return { type: "personal" };
|
|
951
|
+
if (value.type === "organization" && keys.length === 2 && keys.includes("type") && keys.includes("organizationId") && typeof value.organizationId === "string" && id$3.test(value.organizationId)) return {
|
|
952
|
+
type: "organization",
|
|
953
|
+
organizationId: value.organizationId
|
|
954
|
+
};
|
|
955
|
+
throw new AuthError("invalid_workspace_selection", 422);
|
|
791
956
|
}
|
|
792
|
-
function
|
|
793
|
-
|
|
957
|
+
function fromAuthorityError(value, fallbackStatus, retryAfter) {
|
|
958
|
+
const mapped = mapError(isObject$1(value) && typeof value.code === "string" ? value.code : void 0, fallbackStatus);
|
|
959
|
+
return new AuthError(mapped.code, mapped.status, parseRetryAfter(retryAfter));
|
|
794
960
|
}
|
|
795
|
-
function
|
|
796
|
-
|
|
961
|
+
function fromAccountAuthorityError(value, status, retryAfter) {
|
|
962
|
+
const code = isObject$1(value) && typeof value.code === "string" ? value.code : void 0;
|
|
963
|
+
if (status === 403 && (code === "INVALID_ORIGIN" || code === "MISSING_OR_NULL_ORIGIN")) return new AuthError("request_origin_denied", 403);
|
|
964
|
+
if (code === "USER_ALREADY_EXISTS_USE_ANOTHER_EMAIL") return new AuthError("account_conflict", 409);
|
|
965
|
+
if (code === "INVALID_TOKEN") return new AuthError("password_reset_invalid", 422);
|
|
966
|
+
if (code === "INVALID_PASSWORD" || code === "INVALID_EMAIL_OR_PASSWORD") return new AuthError("invalid_credentials", 401);
|
|
967
|
+
if (code === "INVALID_EMAIL" || code === "PASSWORD_TOO_SHORT" || code === "PASSWORD_TOO_LONG" || code === "BODY_MUST_BE_AN_OBJECT" || code === "EMAIL_CAN_NOT_BE_UPDATED") return new AuthError("invalid_auth_input", 422);
|
|
968
|
+
if (status === 401) return new AuthError("authentication_required", 401);
|
|
969
|
+
if (status === 403) return new AuthError("access_denied", 403);
|
|
970
|
+
if (status === 409) return new AuthError("state_conflict", 409);
|
|
971
|
+
if (status === 429) return new AuthError("auth_request_rate_limited", 429, parseRetryAfter(retryAfter));
|
|
972
|
+
if (status === 400 || status === 422) return new AuthError("invalid_auth_input", 422);
|
|
973
|
+
return authorityUnavailable();
|
|
797
974
|
}
|
|
798
|
-
function
|
|
799
|
-
const
|
|
800
|
-
if (
|
|
801
|
-
|
|
802
|
-
const
|
|
803
|
-
if (
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
const value = decodeQueryValue(s[2] || "");
|
|
807
|
-
if (object[key] === void 0) object[key] = value;
|
|
808
|
-
else if (Array.isArray(object[key])) object[key].push(value);
|
|
809
|
-
else object[key] = [object[key], value];
|
|
975
|
+
function fromSocialIdTokenAuthorityError(value, status, retryAfter) {
|
|
976
|
+
const code = isObject$1(value) && typeof value.code === "string" ? value.code : void 0;
|
|
977
|
+
if (code === "INVALID_TOKEN" || code === "FAILED_TO_GET_USER_INFO" || code === "USER_EMAIL_NOT_FOUND") return new AuthError("invalid_credentials", 401);
|
|
978
|
+
if (code === "OAUTH_LINK_ERROR") {
|
|
979
|
+
const message = isObject$1(value) && typeof value.message === "string" ? value.message : void 0;
|
|
980
|
+
if (message === "account not linked") return new AuthError("account_conflict", 409);
|
|
981
|
+
if (message === "signup disabled") return new AuthError("social_signup_required", 409);
|
|
982
|
+
return authorityUnavailable();
|
|
810
983
|
}
|
|
811
|
-
return
|
|
984
|
+
return fromAccountAuthorityError(value, status, retryAfter);
|
|
812
985
|
}
|
|
813
|
-
function
|
|
814
|
-
|
|
815
|
-
if (!value) return encodeQueryKey(key);
|
|
816
|
-
if (Array.isArray(value)) return value.map((_value) => `${encodeQueryKey(key)}=${encodeQueryValue(_value)}`).join("&");
|
|
817
|
-
return `${encodeQueryKey(key)}=${encodeQueryValue(value)}`;
|
|
986
|
+
function authorityUnavailable() {
|
|
987
|
+
return new AuthError("identity_authority_unavailable", 503);
|
|
818
988
|
}
|
|
819
|
-
function
|
|
820
|
-
|
|
989
|
+
function fromOrganizationListError(error) {
|
|
990
|
+
if (error instanceof AuthError && error.status === 401) return new AuthError("authentication_required", 401);
|
|
991
|
+
if (error instanceof AuthError) return error;
|
|
992
|
+
return authorityUnavailable();
|
|
821
993
|
}
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
function hasProtocol(inputString, opts = {}) {
|
|
828
|
-
if (typeof opts === "boolean") opts = { acceptRelative: opts };
|
|
829
|
-
if (opts.strict) return PROTOCOL_STRICT_REGEX.test(inputString);
|
|
830
|
-
return PROTOCOL_REGEX.test(inputString) || (opts.acceptRelative ? PROTOCOL_RELATIVE_REGEX.test(inputString) : false);
|
|
831
|
-
}
|
|
832
|
-
function hasTrailingSlash(input = "", respectQueryAndFragment) {
|
|
833
|
-
if (!respectQueryAndFragment) return input.endsWith("/");
|
|
834
|
-
return TRAILING_SLASH_RE.test(input);
|
|
835
|
-
}
|
|
836
|
-
function withoutTrailingSlash(input = "", respectQueryAndFragment) {
|
|
837
|
-
if (!respectQueryAndFragment) return (hasTrailingSlash(input) ? input.slice(0, -1) : input) || "/";
|
|
838
|
-
if (!hasTrailingSlash(input, true)) return input || "/";
|
|
839
|
-
let path = input;
|
|
840
|
-
let fragment = "";
|
|
841
|
-
const fragmentIndex = input.indexOf("#");
|
|
842
|
-
if (fragmentIndex !== -1) {
|
|
843
|
-
path = input.slice(0, fragmentIndex);
|
|
844
|
-
fragment = input.slice(fragmentIndex);
|
|
845
|
-
}
|
|
846
|
-
const [s0, ...s] = path.split("?");
|
|
847
|
-
return ((s0.endsWith("/") ? s0.slice(0, -1) : s0) || "/") + (s.length > 0 ? `?${s.join("?")}` : "") + fragment;
|
|
848
|
-
}
|
|
849
|
-
function withTrailingSlash(input = "", respectQueryAndFragment) {
|
|
850
|
-
if (!respectQueryAndFragment) return input.endsWith("/") ? input : input + "/";
|
|
851
|
-
if (hasTrailingSlash(input, true)) return input || "/";
|
|
852
|
-
let path = input;
|
|
853
|
-
let fragment = "";
|
|
854
|
-
const fragmentIndex = input.indexOf("#");
|
|
855
|
-
if (fragmentIndex !== -1) {
|
|
856
|
-
path = input.slice(0, fragmentIndex);
|
|
857
|
-
fragment = input.slice(fragmentIndex);
|
|
858
|
-
if (!path) return fragment;
|
|
859
|
-
}
|
|
860
|
-
const [s0, ...s] = path.split("?");
|
|
861
|
-
return s0 + "/" + (s.length > 0 ? `?${s.join("?")}` : "") + fragment;
|
|
862
|
-
}
|
|
863
|
-
function withBase(input, base) {
|
|
864
|
-
if (isEmptyURL(base) || hasProtocol(input)) return input;
|
|
865
|
-
const _base = withoutTrailingSlash(base);
|
|
866
|
-
if (input.startsWith(_base)) {
|
|
867
|
-
const nextChar = input[_base.length];
|
|
868
|
-
if (!nextChar || nextChar === "/" || nextChar === "?") return input;
|
|
869
|
-
}
|
|
870
|
-
return joinURL(_base, input);
|
|
871
|
-
}
|
|
872
|
-
function withQuery(input, query) {
|
|
873
|
-
const parsed = parseURL(input);
|
|
874
|
-
parsed.search = stringifyQuery({
|
|
875
|
-
...parseQuery(parsed.search),
|
|
876
|
-
...query
|
|
877
|
-
});
|
|
878
|
-
return stringifyParsedURL(parsed);
|
|
994
|
+
function fromOrganizationReadAuthorityError(value, status) {
|
|
995
|
+
if (status === 400) return new AuthError("invalid_request", 400);
|
|
996
|
+
if (status === 401) return new AuthError("authentication_required", 401);
|
|
997
|
+
if (status === 403) return new AuthError("access_denied", 403);
|
|
998
|
+
return authorityUnavailable();
|
|
879
999
|
}
|
|
880
|
-
function
|
|
881
|
-
|
|
1000
|
+
function fromOrganizationMutationAuthorityError(value, status, retryAfter) {
|
|
1001
|
+
if (status === 400 || status === 413 || status === 415) return new AuthError("invalid_request", 400);
|
|
1002
|
+
if (status === 409 && isObject$1(value) && value.code === "ORGANIZATION_SLUG_UNAVAILABLE") return new AuthError("organization_slug_unavailable", 409);
|
|
1003
|
+
if (status === 409) return new AuthError("state_conflict", 409);
|
|
1004
|
+
if (status === 429) return new AuthError("auth_request_rate_limited", 429, parseRetryAfter(retryAfter));
|
|
1005
|
+
const code = isObject$1(value) && typeof value.code === "string" ? value.code : void 0;
|
|
1006
|
+
if (status === 403 && code === "REQUEST_ORIGIN_DENIED") return new AuthError("request_origin_denied", 403);
|
|
1007
|
+
return fromOrganizationReadAuthorityError(value, status);
|
|
882
1008
|
}
|
|
883
|
-
function
|
|
884
|
-
|
|
1009
|
+
function fromOrganizationInvitationAdministrationError(value, status, retryAfter) {
|
|
1010
|
+
if (status === 422 && isObject$1(value) && value.code === "RECOVERY_REQUIRED") return new AuthError("invitation_recovery_required", 422);
|
|
1011
|
+
return fromOrganizationMutationAuthorityError(value, status, retryAfter);
|
|
885
1012
|
}
|
|
886
|
-
function
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
const _segment = segment.replace(JOIN_LEADING_SLASH_RE, "");
|
|
890
|
-
url = withTrailingSlash(url) + _segment;
|
|
891
|
-
} else url = segment;
|
|
892
|
-
return url;
|
|
1013
|
+
function fromOrganizationMembershipRemovalError(value, status, retryAfter) {
|
|
1014
|
+
if (status === 422 && isObject$1(value) && value.code === "RECOVERY_REQUIRED") return new AuthError("membership_removal_recovery_required", 422);
|
|
1015
|
+
return fromOrganizationMutationAuthorityError(value, status, retryAfter);
|
|
893
1016
|
}
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
hash: ""
|
|
907
|
-
};
|
|
908
|
-
}
|
|
909
|
-
if (!hasProtocol(input, { acceptRelative: true })) return defaultProto ? parseURL(defaultProto + input) : parsePath(input);
|
|
910
|
-
const [, protocol = "", auth, hostAndPath = ""] = input.replace(/\\/g, "/").match(/^[\s\0]*([\w+.-]{2,}:)?\/\/([^/@]+@)?(.*)/) || [];
|
|
911
|
-
let [, host = "", path = ""] = hostAndPath.match(/([^#/?]*)(.*)?/) || [];
|
|
912
|
-
if (protocol === "file:") path = path.replace(/\/(?=[A-Za-z]:)/, "");
|
|
913
|
-
const { pathname, search, hash } = parsePath(path);
|
|
1017
|
+
function normalizeOrganizationMemberAuthority(value, organizationId, memberId) {
|
|
1018
|
+
exact$6(value, [
|
|
1019
|
+
"organizationId",
|
|
1020
|
+
"actor",
|
|
1021
|
+
"target"
|
|
1022
|
+
]);
|
|
1023
|
+
if (!isId(value.organizationId) || value.organizationId !== organizationId) throw authorityUnavailable();
|
|
1024
|
+
const actor = normalizeOrganizationAuthorityMemberOutcome(value.actor);
|
|
1025
|
+
const target = normalizeOrganizationAuthorityMemberOutcome(value.target);
|
|
1026
|
+
if (target.memberId !== memberId || actor.manualRole !== "owner" && actor.manualRole !== "admin") throw authorityUnavailable();
|
|
1027
|
+
for (const member of [actor, target]) if (member.manualRole === "member" ? member.role === "owner" : member.role !== member.manualRole) throw authorityUnavailable();
|
|
1028
|
+
if (actor.memberId === target.memberId && (actor.manualRole !== target.manualRole || actor.role !== target.role || actor.authorityRevision !== target.authorityRevision)) throw authorityUnavailable();
|
|
914
1029
|
return {
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
pathname,
|
|
919
|
-
search,
|
|
920
|
-
hash,
|
|
921
|
-
[protocolRelative]: !protocol
|
|
1030
|
+
organizationId: value.organizationId,
|
|
1031
|
+
actor,
|
|
1032
|
+
target
|
|
922
1033
|
};
|
|
923
1034
|
}
|
|
924
|
-
function
|
|
925
|
-
|
|
1035
|
+
function normalizeOrganizationAuthorityMemberOutcome(value, includesStatus = false) {
|
|
1036
|
+
exact$6(value, [
|
|
1037
|
+
"memberId",
|
|
1038
|
+
"manualRole",
|
|
1039
|
+
"role",
|
|
1040
|
+
"authorityRevision",
|
|
1041
|
+
...includesStatus ? ["status"] : []
|
|
1042
|
+
]);
|
|
1043
|
+
if (!isId(value.memberId) || value.manualRole !== "owner" && value.manualRole !== "admin" && value.manualRole !== "member" || value.role !== "owner" && value.role !== "admin" && value.role !== "member") throw authorityUnavailable();
|
|
926
1044
|
return {
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
1045
|
+
memberId: value.memberId,
|
|
1046
|
+
manualRole: value.manualRole,
|
|
1047
|
+
role: value.role,
|
|
1048
|
+
authorityRevision: normalizeAuthorityResultRevision(value.authorityRevision)
|
|
930
1049
|
};
|
|
931
1050
|
}
|
|
932
|
-
function
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
const hash = parsed.hash || "";
|
|
936
|
-
const auth = parsed.auth ? parsed.auth + "@" : "";
|
|
937
|
-
const host = parsed.host || "";
|
|
938
|
-
return (parsed.protocol || parsed[protocolRelative] ? (parsed.protocol || "") + "//" : "") + auth + host + pathname + search + hash;
|
|
1051
|
+
function normalizeAuthorityResultRevision(value) {
|
|
1052
|
+
if (!Number.isSafeInteger(value) || value < 0 || value >= Number.MAX_SAFE_INTEGER) throw authorityUnavailable();
|
|
1053
|
+
return value;
|
|
939
1054
|
}
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
if (
|
|
944
|
-
return
|
|
1055
|
+
function fromInvitationAuthorityError(value, status) {
|
|
1056
|
+
const code = isObject$1(value) && typeof value.code === "string" ? value.code : void 0;
|
|
1057
|
+
if (status === 401 && code === "UNAUTHORIZED") return new AuthError("authentication_required", 401);
|
|
1058
|
+
if (status === 403 && (code === "INVALID_ORIGIN" || code === "MISSING_OR_NULL_ORIGIN")) return new AuthError("request_origin_denied", 403);
|
|
1059
|
+
if (status === 403 && code === "YOU_ARE_NOT_THE_RECIPIENT_OF_THE_INVITATION") return new AuthError("invitation_recipient_mismatch", 403);
|
|
1060
|
+
if (status === 403 && code === "EMAIL_VERIFICATION_REQUIRED_BEFORE_ACCEPTING_OR_REJECTING_INVITATION") return new AuthError("email_verification_required", 403);
|
|
1061
|
+
if (status === 400 && (code === "INVITATION_NOT_FOUND" || code === "ORGANIZATION_NOT_FOUND" || code === "TEAM_NOT_FOUND")) return new AuthError("invitation_unavailable", 409);
|
|
1062
|
+
return authorityUnavailable();
|
|
945
1063
|
}
|
|
946
|
-
function
|
|
947
|
-
|
|
1064
|
+
function fromInvitationError(error) {
|
|
1065
|
+
return error instanceof AuthError ? error : authorityUnavailable();
|
|
1066
|
+
}
|
|
1067
|
+
function mapError(code, status) {
|
|
1068
|
+
if (code === "authentication_required") return {
|
|
1069
|
+
code,
|
|
1070
|
+
status: 401
|
|
1071
|
+
};
|
|
1072
|
+
if (code === "request_origin_denied") return {
|
|
1073
|
+
code,
|
|
1074
|
+
status: 403
|
|
1075
|
+
};
|
|
1076
|
+
if (code === "invalid_workspace_selection") return {
|
|
1077
|
+
code,
|
|
1078
|
+
status: 422
|
|
1079
|
+
};
|
|
1080
|
+
if (code === "organization_context_too_large") return {
|
|
1081
|
+
code,
|
|
1082
|
+
status: 422
|
|
1083
|
+
};
|
|
1084
|
+
if (code === "credential_rate_limited") return {
|
|
1085
|
+
code,
|
|
1086
|
+
status: 429
|
|
1087
|
+
};
|
|
1088
|
+
if (code === "identity_authority_unavailable") return {
|
|
1089
|
+
code,
|
|
1090
|
+
status: 503
|
|
1091
|
+
};
|
|
1092
|
+
if (status === 401 || status === 400) return {
|
|
1093
|
+
code: "invalid_credentials",
|
|
1094
|
+
status: 401
|
|
1095
|
+
};
|
|
1096
|
+
if (status === 403) return {
|
|
1097
|
+
code: "access_denied",
|
|
1098
|
+
status: 403
|
|
1099
|
+
};
|
|
1100
|
+
if (status === 409) return {
|
|
1101
|
+
code: "state_conflict",
|
|
1102
|
+
status: 409
|
|
1103
|
+
};
|
|
1104
|
+
if (status === 422) return {
|
|
1105
|
+
code: "invalid_workspace_selection",
|
|
1106
|
+
status: 422
|
|
1107
|
+
};
|
|
1108
|
+
if (status === 429) return {
|
|
1109
|
+
code: "credential_rate_limited",
|
|
1110
|
+
status: 429
|
|
1111
|
+
};
|
|
948
1112
|
return {
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
expiresAt: new Date(startedAt + value.expiresIn * 1e3)
|
|
1113
|
+
code: "identity_authority_unavailable",
|
|
1114
|
+
status: 503
|
|
952
1115
|
};
|
|
953
1116
|
}
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
const
|
|
957
|
-
|
|
958
|
-
function concat(...buffers) {
|
|
959
|
-
const size = buffers.reduce((acc, { length }) => acc + length, 0);
|
|
960
|
-
const buf = new Uint8Array(size);
|
|
961
|
-
let i = 0;
|
|
962
|
-
for (const buffer of buffers) {
|
|
963
|
-
buf.set(buffer, i);
|
|
964
|
-
i += buffer.length;
|
|
965
|
-
}
|
|
966
|
-
return buf;
|
|
1117
|
+
function parseRetryAfter(value) {
|
|
1118
|
+
if (!value || !/^\d+$/.test(value)) return void 0;
|
|
1119
|
+
const seconds = Number(value);
|
|
1120
|
+
return Number.isSafeInteger(seconds) && seconds >= 1 && seconds <= 3600 ? seconds : void 0;
|
|
967
1121
|
}
|
|
968
|
-
function
|
|
969
|
-
const
|
|
970
|
-
|
|
971
|
-
const code = string.charCodeAt(i);
|
|
972
|
-
if (code > 127) throw new TypeError("non-ASCII string encountered in encode()");
|
|
973
|
-
bytes[i] = code;
|
|
974
|
-
}
|
|
975
|
-
return bytes;
|
|
1122
|
+
function toDate(value) {
|
|
1123
|
+
const result = value instanceof Date ? value : typeof value === "string" ? new Date(value) : void 0;
|
|
1124
|
+
return result && Number.isFinite(result.getTime()) ? result : void 0;
|
|
976
1125
|
}
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
function encodeBase64(input) {
|
|
980
|
-
if (Uint8Array.prototype.toBase64) return input.toBase64();
|
|
981
|
-
const CHUNK_SIZE = 32768;
|
|
982
|
-
const arr = [];
|
|
983
|
-
for (let i = 0; i < input.length; i += CHUNK_SIZE) arr.push(String.fromCharCode.apply(null, input.subarray(i, i + CHUNK_SIZE)));
|
|
984
|
-
return btoa(arr.join(""));
|
|
1126
|
+
function isId(value) {
|
|
1127
|
+
return typeof value === "string" && id$3.test(value);
|
|
985
1128
|
}
|
|
986
|
-
function
|
|
987
|
-
if (
|
|
988
|
-
|
|
989
|
-
|
|
1129
|
+
function exact$6(value, keys) {
|
|
1130
|
+
if (!isObject$1(value) || Object.keys(value).sort().join(",") !== [...keys].sort().join(",")) throw authorityUnavailable();
|
|
1131
|
+
}
|
|
1132
|
+
function boundedString(value, maximum) {
|
|
1133
|
+
return typeof value === "string" && value.length > 0 && new TextEncoder().encode(value).byteLength <= maximum;
|
|
1134
|
+
}
|
|
1135
|
+
function role(value) {
|
|
1136
|
+
return value === "owner" || value === "admin" || value === "member";
|
|
1137
|
+
}
|
|
1138
|
+
function nullableHttpsUrl(value) {
|
|
1139
|
+
if (value === null) return null;
|
|
1140
|
+
if (typeof value !== "string" || value.length > 2048) throw authorityUnavailable();
|
|
1141
|
+
let url;
|
|
1142
|
+
try {
|
|
1143
|
+
url = new URL(value);
|
|
1144
|
+
} catch {
|
|
1145
|
+
throw authorityUnavailable();
|
|
1146
|
+
}
|
|
1147
|
+
if (url.protocol !== "https:" || url.username || url.password || url.toString() !== value) throw authorityUnavailable();
|
|
1148
|
+
return value;
|
|
1149
|
+
}
|
|
1150
|
+
function responseDate(value) {
|
|
1151
|
+
if (typeof value !== "string") throw authorityUnavailable();
|
|
1152
|
+
const date = new Date(value);
|
|
1153
|
+
if (!Number.isFinite(date.getTime()) || date.toISOString() !== value) throw authorityUnavailable();
|
|
1154
|
+
return date;
|
|
1155
|
+
}
|
|
1156
|
+
function nullableCursor(value) {
|
|
1157
|
+
if (value === null) return null;
|
|
1158
|
+
if (typeof value !== "string" || value.length < 1 || value.length > 820 || !/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(value)) throw authorityUnavailable();
|
|
1159
|
+
return value;
|
|
1160
|
+
}
|
|
1161
|
+
function normalizeResponseId(value) {
|
|
1162
|
+
if (!isId(value)) throw authorityUnavailable();
|
|
1163
|
+
return value;
|
|
1164
|
+
}
|
|
1165
|
+
function unique(items, key) {
|
|
1166
|
+
if (new Set(items.map(key)).size !== items.length) throw authorityUnavailable();
|
|
1167
|
+
return items;
|
|
1168
|
+
}
|
|
1169
|
+
function isObject$1(value) {
|
|
1170
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1171
|
+
}
|
|
1172
|
+
//#endregion
|
|
1173
|
+
//#region src/http.ts
|
|
1174
|
+
const MAX_RESPONSE_BYTES = 64 * 1024;
|
|
1175
|
+
async function requestJson(url, options) {
|
|
1176
|
+
return (await requestJsonResponse(url, options)).value;
|
|
1177
|
+
}
|
|
1178
|
+
async function requestJsonResponse(url, options) {
|
|
1179
|
+
let response;
|
|
1180
|
+
try {
|
|
1181
|
+
response = await createFetch({ fetch: options.fetch }).raw(url, {
|
|
1182
|
+
method: options.method,
|
|
1183
|
+
headers: options.headers,
|
|
1184
|
+
body: options.body,
|
|
1185
|
+
credentials: options.credentials ?? "include",
|
|
1186
|
+
cache: options.cache,
|
|
1187
|
+
retry: 0,
|
|
1188
|
+
timeout: options.timeoutMs,
|
|
1189
|
+
redirect: "manual",
|
|
1190
|
+
signal: options.signal,
|
|
1191
|
+
responseType: "stream",
|
|
1192
|
+
ignoreResponseError: true
|
|
1193
|
+
});
|
|
1194
|
+
} catch {
|
|
1195
|
+
throw authorityUnavailable();
|
|
1196
|
+
}
|
|
1197
|
+
const contentType = response.headers.get("content-type")?.split(";", 1)[0]?.trim().toLowerCase();
|
|
1198
|
+
if (response.status >= 300 || response.status < 200 || contentType !== "application/json") {
|
|
1199
|
+
const body = contentType === "application/json" ? await readJson(response, options.maxResponseBytes, options.signal) : void 0;
|
|
1200
|
+
response.body?.cancel().catch(() => void 0);
|
|
1201
|
+
throw (options.mapError ?? fromAuthorityError)(body, response.status, response.headers.get("retry-after"));
|
|
1202
|
+
}
|
|
1203
|
+
return {
|
|
1204
|
+
value: await readJson(response, options.maxResponseBytes, options.signal),
|
|
1205
|
+
headers: response.headers
|
|
1206
|
+
};
|
|
1207
|
+
}
|
|
1208
|
+
async function readJson(response, maximum = MAX_RESPONSE_BYTES, signal) {
|
|
1209
|
+
const length = response.headers.get("content-length");
|
|
1210
|
+
if (length && (!/^\d+$/.test(length) || Number(length) > maximum)) {
|
|
1211
|
+
response.body?.cancel().catch(() => void 0);
|
|
1212
|
+
throw authorityUnavailable();
|
|
1213
|
+
}
|
|
1214
|
+
if (!response.body) throw authorityUnavailable();
|
|
1215
|
+
if (signal?.aborted) {
|
|
1216
|
+
response.body.cancel().catch(() => void 0);
|
|
1217
|
+
throw authorityUnavailable();
|
|
1218
|
+
}
|
|
1219
|
+
const reader = response.body.getReader();
|
|
1220
|
+
const cancel = () => {
|
|
1221
|
+
reader.cancel().catch(() => void 0);
|
|
1222
|
+
};
|
|
1223
|
+
signal?.addEventListener("abort", cancel, { once: true });
|
|
1224
|
+
const chunks = [];
|
|
1225
|
+
let size = 0;
|
|
1226
|
+
try {
|
|
1227
|
+
while (true) {
|
|
1228
|
+
const { done, value } = await reader.read();
|
|
1229
|
+
if (signal?.aborted) throw authorityUnavailable();
|
|
1230
|
+
if (done) break;
|
|
1231
|
+
size += value.byteLength;
|
|
1232
|
+
if (size > maximum) throw authorityUnavailable();
|
|
1233
|
+
chunks.push(value);
|
|
1234
|
+
}
|
|
1235
|
+
} catch (error) {
|
|
1236
|
+
reader.cancel().catch(() => void 0);
|
|
1237
|
+
throw error;
|
|
1238
|
+
} finally {
|
|
1239
|
+
signal?.removeEventListener("abort", cancel);
|
|
1240
|
+
reader.releaseLock();
|
|
1241
|
+
}
|
|
1242
|
+
const bytes = new Uint8Array(size);
|
|
1243
|
+
let offset = 0;
|
|
1244
|
+
for (const chunk of chunks) {
|
|
1245
|
+
bytes.set(chunk, offset);
|
|
1246
|
+
offset += chunk.byteLength;
|
|
1247
|
+
}
|
|
1248
|
+
try {
|
|
1249
|
+
return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
|
|
1250
|
+
} catch {
|
|
1251
|
+
throw authorityUnavailable();
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
//#endregion
|
|
1255
|
+
//#region src/product-operations/contract.ts
|
|
1256
|
+
const id$2 = /^[A-Za-z0-9_-]{1,128}$(?![\s\S])/;
|
|
1257
|
+
const digest$1 = /^[a-f0-9]{64}$(?![\s\S])/;
|
|
1258
|
+
const credential = /^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$(?![\s\S])/;
|
|
1259
|
+
function exact$5(value, keys) {
|
|
1260
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) && Object.keys(value).length === keys.length && keys.every((key) => Object.hasOwn(value, key));
|
|
1261
|
+
}
|
|
1262
|
+
function identifier(value) {
|
|
1263
|
+
return typeof value === "string" && id$2.test(value);
|
|
1264
|
+
}
|
|
1265
|
+
function timestamp(value) {
|
|
1266
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 && value <= 864e13;
|
|
1267
|
+
}
|
|
1268
|
+
function operationProof(value) {
|
|
1269
|
+
if (!exact$5(value, [
|
|
1270
|
+
"applicationCredential",
|
|
1271
|
+
"serviceAssertion",
|
|
1272
|
+
"actorUserId",
|
|
1273
|
+
"actorSessionId",
|
|
1274
|
+
"serviceId",
|
|
1275
|
+
"environment"
|
|
1276
|
+
]) || !identifier(value.actorUserId) || !identifier(value.actorSessionId) || !identifier(value.serviceId) || ![
|
|
1277
|
+
"local",
|
|
1278
|
+
"development",
|
|
1279
|
+
"staging",
|
|
1280
|
+
"production"
|
|
1281
|
+
].includes(value.environment) || [value.applicationCredential, value.serviceAssertion].some((token) => typeof token !== "string" || token.length > 16 * 1024 || !credential.test(token))) throw new AuthError("invalid_request", 400);
|
|
1282
|
+
return {
|
|
1283
|
+
applicationCredential: value.applicationCredential,
|
|
1284
|
+
serviceAssertion: value.serviceAssertion,
|
|
1285
|
+
actorUserId: value.actorUserId,
|
|
1286
|
+
actorSessionId: value.actorSessionId,
|
|
1287
|
+
serviceId: value.serviceId,
|
|
1288
|
+
environment: value.environment
|
|
1289
|
+
};
|
|
1290
|
+
}
|
|
1291
|
+
function snapshotInput(value) {
|
|
1292
|
+
if (!exact$5(value, ["applicationId", "participantUserUids"]) || !identifier(value.applicationId) || !Array.isArray(value.participantUserUids) || value.participantUserUids.length < 1 || value.participantUserUids.length > 100 || !value.participantUserUids.every((uid, index, all) => identifier(uid) && (index === 0 || all[index - 1] < uid))) throw new AuthError("invalid_request", 400);
|
|
1293
|
+
return {
|
|
1294
|
+
applicationId: value.applicationId,
|
|
1295
|
+
participantUserUids: [...value.participantUserUids]
|
|
1296
|
+
};
|
|
1297
|
+
}
|
|
1298
|
+
function operationInput(value) {
|
|
1299
|
+
if (!exact$5(value, [
|
|
1300
|
+
"applicationId",
|
|
1301
|
+
"snapshotId",
|
|
1302
|
+
"operationHash",
|
|
1303
|
+
"nonce"
|
|
1304
|
+
]) || !identifier(value.applicationId) || !identifier(value.snapshotId) || typeof value.operationHash !== "string" || !digest$1.test(value.operationHash) || typeof value.nonce !== "string" || !digest$1.test(value.nonce)) throw new AuthError("invalid_request", 400);
|
|
1305
|
+
return {
|
|
1306
|
+
applicationId: value.applicationId,
|
|
1307
|
+
snapshotId: value.snapshotId,
|
|
1308
|
+
operationHash: value.operationHash,
|
|
1309
|
+
nonce: value.nonce
|
|
1310
|
+
};
|
|
1311
|
+
}
|
|
1312
|
+
const snapshotKeys = [
|
|
1313
|
+
"snapshotId",
|
|
1314
|
+
"actorUserId",
|
|
1315
|
+
"actorSessionId",
|
|
1316
|
+
"issuedAt",
|
|
1317
|
+
"expiresAt"
|
|
1318
|
+
];
|
|
1319
|
+
function snapshotFields(value) {
|
|
1320
|
+
if (!identifier(value.snapshotId) || !identifier(value.actorUserId) || !identifier(value.actorSessionId) || !timestamp(value.issuedAt) || !timestamp(value.expiresAt) || value.expiresAt <= value.issuedAt || value.expiresAt - value.issuedAt > 3e4) throw authorityUnavailable();
|
|
1321
|
+
return {
|
|
1322
|
+
snapshotId: value.snapshotId,
|
|
1323
|
+
actorUserId: value.actorUserId,
|
|
1324
|
+
actorSessionId: value.actorSessionId,
|
|
1325
|
+
issuedAt: value.issuedAt,
|
|
1326
|
+
expiresAt: value.expiresAt
|
|
1327
|
+
};
|
|
1328
|
+
}
|
|
1329
|
+
function snapshotOutput(value, participants, proof) {
|
|
1330
|
+
if (!exact$5(value, snapshotKeys)) throw authorityUnavailable();
|
|
1331
|
+
const result = snapshotFields(value);
|
|
1332
|
+
if (!participants.includes(result.actorUserId) || result.actorUserId !== proof.actorUserId || result.actorSessionId !== proof.actorSessionId) throw authorityUnavailable();
|
|
1333
|
+
return result;
|
|
1334
|
+
}
|
|
1335
|
+
function receiptOutput(value, input, proof, phase) {
|
|
1336
|
+
if (!exact$5(value, [
|
|
1337
|
+
...snapshotKeys,
|
|
1338
|
+
"serviceId",
|
|
1339
|
+
"applicationId",
|
|
1340
|
+
"actorAccountCreatedAt",
|
|
1341
|
+
"environment",
|
|
1342
|
+
"scopeKind",
|
|
1343
|
+
"organizationId",
|
|
1344
|
+
"nonce",
|
|
1345
|
+
"operationHash",
|
|
1346
|
+
"consumedAt"
|
|
1347
|
+
])) throw authorityUnavailable();
|
|
1348
|
+
const snapshot = snapshotFields(value);
|
|
1349
|
+
if (snapshot.snapshotId !== input.snapshotId || snapshot.actorUserId !== proof.actorUserId || phase === "consume" && snapshot.actorSessionId !== proof.actorSessionId || value.serviceId !== proof.serviceId || value.environment !== proof.environment || value.applicationId !== input.applicationId || value.nonce !== input.nonce || value.operationHash !== input.operationHash || !identifier(value.serviceId) || !timestamp(value.actorAccountCreatedAt) || value.scopeKind !== "account" || value.organizationId !== null || !timestamp(value.consumedAt) || value.consumedAt < snapshot.issuedAt || value.consumedAt >= snapshot.expiresAt || ![
|
|
1350
|
+
"local",
|
|
1351
|
+
"development",
|
|
1352
|
+
"staging",
|
|
1353
|
+
"production"
|
|
1354
|
+
].includes(value.environment)) throw authorityUnavailable();
|
|
1355
|
+
return {
|
|
1356
|
+
...snapshot,
|
|
1357
|
+
serviceId: value.serviceId,
|
|
1358
|
+
applicationId: input.applicationId,
|
|
1359
|
+
actorAccountCreatedAt: value.actorAccountCreatedAt,
|
|
1360
|
+
environment: value.environment,
|
|
1361
|
+
scopeKind: "account",
|
|
1362
|
+
organizationId: null,
|
|
1363
|
+
nonce: input.nonce,
|
|
1364
|
+
operationHash: input.operationHash,
|
|
1365
|
+
consumedAt: value.consumedAt
|
|
1366
|
+
};
|
|
1367
|
+
}
|
|
1368
|
+
//#endregion
|
|
1369
|
+
//#region src/product-operations/index.ts
|
|
1370
|
+
function createAccountProductOperationAuth(options) {
|
|
1371
|
+
const base = joinURL(normalizeOrigin(options.authOrigin, "authOrigin"), "api/v1/auth/product-operations/account");
|
|
1372
|
+
const fetchImpl = options.fetch ?? globalThis.fetch?.bind(globalThis);
|
|
1373
|
+
if (typeof fetchImpl !== "function") throw new TypeError("fetch is required");
|
|
1374
|
+
const timeoutMs = normalizeTimeout(options.timeoutMs);
|
|
1375
|
+
function audience(phase) {
|
|
1376
|
+
if (![
|
|
1377
|
+
"snapshot",
|
|
1378
|
+
"consume",
|
|
1379
|
+
"receipt"
|
|
1380
|
+
].includes(phase)) throw new AuthError("invalid_request", 400);
|
|
1381
|
+
return joinURL(base, phase);
|
|
1382
|
+
}
|
|
1383
|
+
async function exchange(phase, applicationId, body, proof) {
|
|
1384
|
+
const credentials = proof;
|
|
1385
|
+
const url = new URL(audience(phase));
|
|
1386
|
+
url.searchParams.set("applicationId", applicationId);
|
|
1387
|
+
const controller = new AbortController();
|
|
1388
|
+
let timer;
|
|
1389
|
+
try {
|
|
1390
|
+
const deadline = new Promise((_, reject) => {
|
|
1391
|
+
timer = setTimeout(() => {
|
|
1392
|
+
controller.abort();
|
|
1393
|
+
reject(authorityUnavailable());
|
|
1394
|
+
}, timeoutMs);
|
|
1395
|
+
});
|
|
1396
|
+
return await Promise.race([requestJson(url.toString(), {
|
|
1397
|
+
fetch: fetchImpl,
|
|
1398
|
+
timeoutMs,
|
|
1399
|
+
method: "POST",
|
|
1400
|
+
credentials: "omit",
|
|
1401
|
+
cache: "no-store",
|
|
1402
|
+
signal: controller.signal,
|
|
1403
|
+
maxResponseBytes: 4096,
|
|
1404
|
+
headers: {
|
|
1405
|
+
"x-finueva-application-credential": credentials.applicationCredential,
|
|
1406
|
+
"x-finueva-service-assertion": credentials.serviceAssertion,
|
|
1407
|
+
accept: "application/json",
|
|
1408
|
+
"content-type": "application/json"
|
|
1409
|
+
},
|
|
1410
|
+
body,
|
|
1411
|
+
mapError: (_value, status, retryAfter) => {
|
|
1412
|
+
if (status === 401) return new AuthError("access_denied", 401);
|
|
1413
|
+
if (status === 429 && retryAfter !== null && /^(?:[1-9]|[1-5][0-9]|60)$/.test(retryAfter)) return new AuthError("auth_request_rate_limited", 429, Number(retryAfter));
|
|
1414
|
+
return authorityUnavailable();
|
|
1415
|
+
}
|
|
1416
|
+
}), deadline]);
|
|
1417
|
+
} finally {
|
|
1418
|
+
clearTimeout(timer);
|
|
1419
|
+
controller.abort();
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1422
|
+
return {
|
|
1423
|
+
audience,
|
|
1424
|
+
async captureAccountOperation(input, proof) {
|
|
1425
|
+
const validated = snapshotInput(input);
|
|
1426
|
+
const expected = operationProof(proof);
|
|
1427
|
+
return snapshotOutput(await exchange("snapshot", validated.applicationId, { participantUserUids: validated.participantUserUids }, expected), validated.participantUserUids, expected);
|
|
1428
|
+
},
|
|
1429
|
+
async consumeAccountOperation(input, proof) {
|
|
1430
|
+
const validated = operationInput(input);
|
|
1431
|
+
const expected = operationProof(proof);
|
|
1432
|
+
const { applicationId, ...body } = validated;
|
|
1433
|
+
const value = await exchange("consume", applicationId, body, expected);
|
|
1434
|
+
if (!exact$5(value, ["receipt", "replayed"]) || typeof value.replayed !== "boolean") throw authorityUnavailable();
|
|
1435
|
+
return {
|
|
1436
|
+
receipt: receiptOutput(value.receipt, validated, expected, "consume"),
|
|
1437
|
+
replayed: value.replayed
|
|
1438
|
+
};
|
|
1439
|
+
},
|
|
1440
|
+
async retrieveAccountOperationReceipt(input, proof) {
|
|
1441
|
+
const validated = operationInput(input);
|
|
1442
|
+
const expected = operationProof(proof);
|
|
1443
|
+
const { applicationId, ...body } = validated;
|
|
1444
|
+
return receiptOutput(await exchange("receipt", applicationId, body, expected), validated, expected, "receipt");
|
|
1445
|
+
}
|
|
1446
|
+
};
|
|
1447
|
+
}
|
|
1448
|
+
//#endregion
|
|
1449
|
+
//#region ../../node_modules/.pnpm/jose@6.2.4/node_modules/jose/dist/webapi/lib/buffer_utils.js
|
|
1450
|
+
const encoder$1 = new TextEncoder();
|
|
1451
|
+
const decoder = new TextDecoder();
|
|
1452
|
+
function concat(...buffers) {
|
|
1453
|
+
const size = buffers.reduce((acc, { length }) => acc + length, 0);
|
|
1454
|
+
const buf = new Uint8Array(size);
|
|
1455
|
+
let i = 0;
|
|
1456
|
+
for (const buffer of buffers) {
|
|
1457
|
+
buf.set(buffer, i);
|
|
1458
|
+
i += buffer.length;
|
|
1459
|
+
}
|
|
1460
|
+
return buf;
|
|
1461
|
+
}
|
|
1462
|
+
function encode$1(string) {
|
|
1463
|
+
const bytes = new Uint8Array(string.length);
|
|
1464
|
+
for (let i = 0; i < string.length; i++) {
|
|
1465
|
+
const code = string.charCodeAt(i);
|
|
1466
|
+
if (code > 127) throw new TypeError("non-ASCII string encountered in encode()");
|
|
1467
|
+
bytes[i] = code;
|
|
1468
|
+
}
|
|
1469
|
+
return bytes;
|
|
1470
|
+
}
|
|
1471
|
+
//#endregion
|
|
1472
|
+
//#region ../../node_modules/.pnpm/jose@6.2.4/node_modules/jose/dist/webapi/lib/base64.js
|
|
1473
|
+
function encodeBase64(input) {
|
|
1474
|
+
if (Uint8Array.prototype.toBase64) return input.toBase64();
|
|
1475
|
+
const CHUNK_SIZE = 32768;
|
|
1476
|
+
const arr = [];
|
|
1477
|
+
for (let i = 0; i < input.length; i += CHUNK_SIZE) arr.push(String.fromCharCode.apply(null, input.subarray(i, i + CHUNK_SIZE)));
|
|
1478
|
+
return btoa(arr.join(""));
|
|
1479
|
+
}
|
|
1480
|
+
function decodeBase64(encoded) {
|
|
1481
|
+
if (Uint8Array.fromBase64) return Uint8Array.fromBase64(encoded);
|
|
1482
|
+
const binary = atob(encoded);
|
|
1483
|
+
const bytes = new Uint8Array(binary.length);
|
|
990
1484
|
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
991
1485
|
return bytes;
|
|
992
1486
|
}
|
|
@@ -1907,432 +2401,231 @@ async function calculateJwkThumbprint(key, digestAlgorithm) {
|
|
|
1907
2401
|
digestAlgorithm ??= "sha256";
|
|
1908
2402
|
if (digestAlgorithm !== "sha256" && digestAlgorithm !== "sha384" && digestAlgorithm !== "sha512") throw new TypeError("digestAlgorithm must one of \"sha256\", \"sha384\", or \"sha512\"");
|
|
1909
2403
|
let components;
|
|
1910
|
-
switch (jwk.kty) {
|
|
1911
|
-
case "AKP":
|
|
1912
|
-
check(jwk.alg, "\"alg\" (Algorithm) Parameter");
|
|
1913
|
-
check(jwk.pub, "\"pub\" (Public key) Parameter");
|
|
1914
|
-
components = {
|
|
1915
|
-
alg: jwk.alg,
|
|
1916
|
-
kty: jwk.kty,
|
|
1917
|
-
pub: jwk.pub
|
|
1918
|
-
};
|
|
1919
|
-
break;
|
|
1920
|
-
case "EC":
|
|
1921
|
-
check(jwk.crv, "\"crv\" (Curve) Parameter");
|
|
1922
|
-
check(jwk.x, "\"x\" (X Coordinate) Parameter");
|
|
1923
|
-
check(jwk.y, "\"y\" (Y Coordinate) Parameter");
|
|
1924
|
-
components = {
|
|
1925
|
-
crv: jwk.crv,
|
|
1926
|
-
kty: jwk.kty,
|
|
1927
|
-
x: jwk.x,
|
|
1928
|
-
y: jwk.y
|
|
1929
|
-
};
|
|
1930
|
-
break;
|
|
1931
|
-
case "OKP":
|
|
1932
|
-
check(jwk.crv, "\"crv\" (Subtype of Key Pair) Parameter");
|
|
1933
|
-
check(jwk.x, "\"x\" (Public Key) Parameter");
|
|
1934
|
-
components = {
|
|
1935
|
-
crv: jwk.crv,
|
|
1936
|
-
kty: jwk.kty,
|
|
1937
|
-
x: jwk.x
|
|
1938
|
-
};
|
|
1939
|
-
break;
|
|
1940
|
-
case "RSA":
|
|
1941
|
-
check(jwk.e, "\"e\" (Exponent) Parameter");
|
|
1942
|
-
check(jwk.n, "\"n\" (Modulus) Parameter");
|
|
1943
|
-
components = {
|
|
1944
|
-
e: jwk.e,
|
|
1945
|
-
kty: jwk.kty,
|
|
1946
|
-
n: jwk.n
|
|
1947
|
-
};
|
|
1948
|
-
break;
|
|
1949
|
-
case "oct":
|
|
1950
|
-
check(jwk.k, "\"k\" (Key Value) Parameter");
|
|
1951
|
-
components = {
|
|
1952
|
-
k: jwk.k,
|
|
1953
|
-
kty: jwk.kty
|
|
1954
|
-
};
|
|
1955
|
-
break;
|
|
1956
|
-
default: throw new JOSENotSupported("\"kty\" (Key Type) Parameter missing or unsupported");
|
|
1957
|
-
}
|
|
1958
|
-
const data = encode$1(JSON.stringify(components));
|
|
1959
|
-
return encode(await digest(digestAlgorithm, data));
|
|
1960
|
-
}
|
|
1961
|
-
//#endregion
|
|
1962
|
-
//#region ../../node_modules/.pnpm/jose@6.2.4/node_modules/jose/dist/webapi/util/decode_protected_header.js
|
|
1963
|
-
function decodeProtectedHeader(token) {
|
|
1964
|
-
let protectedB64u;
|
|
1965
|
-
if (typeof token === "string") {
|
|
1966
|
-
const parts = token.split(".");
|
|
1967
|
-
if (parts.length === 3 || parts.length === 5) [protectedB64u] = parts;
|
|
1968
|
-
} else if (typeof token === "object" && token) if ("protected" in token) protectedB64u = token.protected;
|
|
1969
|
-
else throw new TypeError("Token does not contain a Protected Header");
|
|
1970
|
-
try {
|
|
1971
|
-
if (typeof protectedB64u !== "string" || !protectedB64u) throw new Error();
|
|
1972
|
-
const result = JSON.parse(decoder.decode(decode(protectedB64u)));
|
|
1973
|
-
if (!isObject(result)) throw new Error();
|
|
1974
|
-
return result;
|
|
1975
|
-
} catch {
|
|
1976
|
-
throw new TypeError("Invalid Token or Protected Header formatting");
|
|
1977
|
-
}
|
|
1978
|
-
}
|
|
1979
|
-
//#endregion
|
|
1980
|
-
//#region ../../node_modules/.pnpm/jose@6.2.4/node_modules/jose/dist/webapi/util/decode_jwt.js
|
|
1981
|
-
function decodeJwt(jwt) {
|
|
1982
|
-
if (typeof jwt !== "string") throw new JWTInvalid("JWTs must use Compact JWS serialization, JWT must be a string");
|
|
1983
|
-
const { 1: payload, length } = jwt.split(".");
|
|
1984
|
-
if (length === 5) throw new JWTInvalid("Only JWTs using Compact JWS serialization can be decoded");
|
|
1985
|
-
if (length !== 3) throw new JWTInvalid("Invalid JWT");
|
|
1986
|
-
if (!payload) throw new JWTInvalid("JWTs must contain a payload");
|
|
1987
|
-
let decoded;
|
|
1988
|
-
try {
|
|
1989
|
-
decoded = decode(payload);
|
|
1990
|
-
} catch {
|
|
1991
|
-
throw new JWTInvalid("Failed to base64url decode the payload");
|
|
1992
|
-
}
|
|
1993
|
-
let result;
|
|
1994
|
-
try {
|
|
1995
|
-
result = JSON.parse(decoder.decode(decoded));
|
|
1996
|
-
} catch {
|
|
1997
|
-
throw new JWTInvalid("Failed to parse the decoded payload as JSON");
|
|
1998
|
-
}
|
|
1999
|
-
if (!isObject(result)) throw new JWTInvalid("Invalid JWT Claims Set");
|
|
2000
|
-
return result;
|
|
2001
|
-
}
|
|
2002
|
-
//#endregion
|
|
2003
|
-
//#region ../../node_modules/.pnpm/destr@2.0.5/node_modules/destr/dist/index.mjs
|
|
2004
|
-
const suspectProtoRx = /"(?:_|\\u0{2}5[Ff]){2}(?:p|\\u0{2}70)(?:r|\\u0{2}72)(?:o|\\u0{2}6[Ff])(?:t|\\u0{2}74)(?:o|\\u0{2}6[Ff])(?:_|\\u0{2}5[Ff]){2}"\s*:/;
|
|
2005
|
-
const suspectConstructorRx = /"(?:c|\\u0063)(?:o|\\u006[Ff])(?:n|\\u006[Ee])(?:s|\\u0073)(?:t|\\u0074)(?:r|\\u0072)(?:u|\\u0075)(?:c|\\u0063)(?:t|\\u0074)(?:o|\\u006[Ff])(?:r|\\u0072)"\s*:/;
|
|
2006
|
-
const JsonSigRx = /^\s*["[{]|^\s*-?\d{1,16}(\.\d{1,17})?([Ee][+-]?\d+)?\s*$/;
|
|
2007
|
-
function jsonParseTransform(key, value) {
|
|
2008
|
-
if (key === "__proto__" || key === "constructor" && value && typeof value === "object" && "prototype" in value) {
|
|
2009
|
-
warnKeyDropped(key);
|
|
2010
|
-
return;
|
|
2011
|
-
}
|
|
2012
|
-
return value;
|
|
2013
|
-
}
|
|
2014
|
-
function warnKeyDropped(key) {
|
|
2015
|
-
console.warn(`[destr] Dropping "${key}" key to prevent prototype pollution.`);
|
|
2016
|
-
}
|
|
2017
|
-
function destr(value, options = {}) {
|
|
2018
|
-
if (typeof value !== "string") return value;
|
|
2019
|
-
if (value[0] === "\"" && value[value.length - 1] === "\"" && value.indexOf("\\") === -1) return value.slice(1, -1);
|
|
2020
|
-
const _value = value.trim();
|
|
2021
|
-
if (_value.length <= 9) switch (_value.toLowerCase()) {
|
|
2022
|
-
case "true": return true;
|
|
2023
|
-
case "false": return false;
|
|
2024
|
-
case "undefined": return;
|
|
2025
|
-
case "null": return null;
|
|
2026
|
-
case "nan": return NaN;
|
|
2027
|
-
case "infinity": return Number.POSITIVE_INFINITY;
|
|
2028
|
-
case "-infinity": return Number.NEGATIVE_INFINITY;
|
|
2029
|
-
}
|
|
2030
|
-
if (!JsonSigRx.test(value)) {
|
|
2031
|
-
if (options.strict) throw new SyntaxError("[destr] Invalid JSON");
|
|
2032
|
-
return value;
|
|
2033
|
-
}
|
|
2034
|
-
try {
|
|
2035
|
-
if (suspectProtoRx.test(value) || suspectConstructorRx.test(value)) {
|
|
2036
|
-
if (options.strict) throw new Error("[destr] Possible prototype pollution");
|
|
2037
|
-
return JSON.parse(value, jsonParseTransform);
|
|
2038
|
-
}
|
|
2039
|
-
return JSON.parse(value);
|
|
2040
|
-
} catch (error) {
|
|
2041
|
-
if (options.strict) throw error;
|
|
2042
|
-
return value;
|
|
2043
|
-
}
|
|
2044
|
-
}
|
|
2045
|
-
//#endregion
|
|
2046
|
-
//#region ../../node_modules/.pnpm/ofetch@1.5.1/node_modules/ofetch/dist/shared/ofetch.CWycOUEr.mjs
|
|
2047
|
-
var FetchError = class extends Error {
|
|
2048
|
-
constructor(message, opts) {
|
|
2049
|
-
super(message, opts);
|
|
2050
|
-
this.name = "FetchError";
|
|
2051
|
-
if (opts?.cause && !this.cause) this.cause = opts.cause;
|
|
2052
|
-
}
|
|
2053
|
-
};
|
|
2054
|
-
function createFetchError(ctx) {
|
|
2055
|
-
const errorMessage = ctx.error?.message || ctx.error?.toString() || "";
|
|
2056
|
-
const method = ctx.request?.method || ctx.options?.method || "GET";
|
|
2057
|
-
const url = ctx.request?.url || String(ctx.request) || "/";
|
|
2058
|
-
const fetchError = new FetchError(`${`[${method}] ${JSON.stringify(url)}`}: ${ctx.response ? `${ctx.response.status} ${ctx.response.statusText}` : "<no response>"}${errorMessage ? ` ${errorMessage}` : ""}`, ctx.error ? { cause: ctx.error } : void 0);
|
|
2059
|
-
for (const key of [
|
|
2060
|
-
"request",
|
|
2061
|
-
"options",
|
|
2062
|
-
"response"
|
|
2063
|
-
]) Object.defineProperty(fetchError, key, { get() {
|
|
2064
|
-
return ctx[key];
|
|
2065
|
-
} });
|
|
2066
|
-
for (const [key, refKey] of [
|
|
2067
|
-
["data", "_data"],
|
|
2068
|
-
["status", "status"],
|
|
2069
|
-
["statusCode", "status"],
|
|
2070
|
-
["statusText", "statusText"],
|
|
2071
|
-
["statusMessage", "statusText"]
|
|
2072
|
-
]) Object.defineProperty(fetchError, key, { get() {
|
|
2073
|
-
return ctx.response && ctx.response[refKey];
|
|
2074
|
-
} });
|
|
2075
|
-
return fetchError;
|
|
2076
|
-
}
|
|
2077
|
-
const payloadMethods = new Set(Object.freeze([
|
|
2078
|
-
"PATCH",
|
|
2079
|
-
"POST",
|
|
2080
|
-
"PUT",
|
|
2081
|
-
"DELETE"
|
|
2082
|
-
]));
|
|
2083
|
-
function isPayloadMethod(method = "GET") {
|
|
2084
|
-
return payloadMethods.has(method.toUpperCase());
|
|
2085
|
-
}
|
|
2086
|
-
function isJSONSerializable(value) {
|
|
2087
|
-
if (value === void 0) return false;
|
|
2088
|
-
const t = typeof value;
|
|
2089
|
-
if (t === "string" || t === "number" || t === "boolean" || t === null) return true;
|
|
2090
|
-
if (t !== "object") return false;
|
|
2091
|
-
if (Array.isArray(value)) return true;
|
|
2092
|
-
if (value.buffer) return false;
|
|
2093
|
-
if (value instanceof FormData || value instanceof URLSearchParams) return false;
|
|
2094
|
-
return value.constructor && value.constructor.name === "Object" || typeof value.toJSON === "function";
|
|
2095
|
-
}
|
|
2096
|
-
const textTypes = new Set([
|
|
2097
|
-
"image/svg",
|
|
2098
|
-
"application/xml",
|
|
2099
|
-
"application/xhtml",
|
|
2100
|
-
"application/html"
|
|
2101
|
-
]);
|
|
2102
|
-
const JSON_RE = /^application\/(?:[\w!#$%&*.^`~-]*\+)?json(;.+)?$/i;
|
|
2103
|
-
function detectResponseType(_contentType = "") {
|
|
2104
|
-
if (!_contentType) return "json";
|
|
2105
|
-
const contentType = _contentType.split(";").shift() || "";
|
|
2106
|
-
if (JSON_RE.test(contentType)) return "json";
|
|
2107
|
-
if (contentType === "text/event-stream") return "stream";
|
|
2108
|
-
if (textTypes.has(contentType) || contentType.startsWith("text/")) return "text";
|
|
2109
|
-
return "blob";
|
|
2110
|
-
}
|
|
2111
|
-
function resolveFetchOptions(request, input, defaults, Headers) {
|
|
2112
|
-
const headers = mergeHeaders(input?.headers ?? request?.headers, defaults?.headers, Headers);
|
|
2113
|
-
let query;
|
|
2114
|
-
if (defaults?.query || defaults?.params || input?.params || input?.query) query = {
|
|
2115
|
-
...defaults?.params,
|
|
2116
|
-
...defaults?.query,
|
|
2117
|
-
...input?.params,
|
|
2118
|
-
...input?.query
|
|
2119
|
-
};
|
|
2120
|
-
return {
|
|
2121
|
-
...defaults,
|
|
2122
|
-
...input,
|
|
2123
|
-
query,
|
|
2124
|
-
params: query,
|
|
2125
|
-
headers
|
|
2126
|
-
};
|
|
2127
|
-
}
|
|
2128
|
-
function mergeHeaders(input, defaults, Headers) {
|
|
2129
|
-
if (!defaults) return new Headers(input);
|
|
2130
|
-
const headers = new Headers(defaults);
|
|
2131
|
-
if (input) for (const [key, value] of Symbol.iterator in input || Array.isArray(input) ? input : new Headers(input)) headers.set(key, value);
|
|
2132
|
-
return headers;
|
|
2133
|
-
}
|
|
2134
|
-
async function callHooks(context, hooks) {
|
|
2135
|
-
if (hooks) if (Array.isArray(hooks)) for (const hook of hooks) await hook(context);
|
|
2136
|
-
else await hooks(context);
|
|
2137
|
-
}
|
|
2138
|
-
const retryStatusCodes = new Set([
|
|
2139
|
-
408,
|
|
2140
|
-
409,
|
|
2141
|
-
425,
|
|
2142
|
-
429,
|
|
2143
|
-
500,
|
|
2144
|
-
502,
|
|
2145
|
-
503,
|
|
2146
|
-
504
|
|
2147
|
-
]);
|
|
2148
|
-
const nullBodyResponses = new Set([
|
|
2149
|
-
101,
|
|
2150
|
-
204,
|
|
2151
|
-
205,
|
|
2152
|
-
304
|
|
2153
|
-
]);
|
|
2154
|
-
function createFetch(globalOptions = {}) {
|
|
2155
|
-
const { fetch = globalThis.fetch, Headers = globalThis.Headers, AbortController = globalThis.AbortController } = globalOptions;
|
|
2156
|
-
async function onError(context) {
|
|
2157
|
-
const isAbort = context.error && context.error.name === "AbortError" && !context.options.timeout || false;
|
|
2158
|
-
if (context.options.retry !== false && !isAbort) {
|
|
2159
|
-
let retries;
|
|
2160
|
-
if (typeof context.options.retry === "number") retries = context.options.retry;
|
|
2161
|
-
else retries = isPayloadMethod(context.options.method) ? 0 : 1;
|
|
2162
|
-
const responseCode = context.response && context.response.status || 500;
|
|
2163
|
-
if (retries > 0 && (Array.isArray(context.options.retryStatusCodes) ? context.options.retryStatusCodes.includes(responseCode) : retryStatusCodes.has(responseCode))) {
|
|
2164
|
-
const retryDelay = typeof context.options.retryDelay === "function" ? context.options.retryDelay(context) : context.options.retryDelay || 0;
|
|
2165
|
-
if (retryDelay > 0) await new Promise((resolve) => setTimeout(resolve, retryDelay));
|
|
2166
|
-
return $fetchRaw(context.request, {
|
|
2167
|
-
...context.options,
|
|
2168
|
-
retry: retries - 1
|
|
2169
|
-
});
|
|
2170
|
-
}
|
|
2171
|
-
}
|
|
2172
|
-
const error = createFetchError(context);
|
|
2173
|
-
if (Error.captureStackTrace) Error.captureStackTrace(error, $fetchRaw);
|
|
2174
|
-
throw error;
|
|
2175
|
-
}
|
|
2176
|
-
const $fetchRaw = async function $fetchRaw2(_request, _options = {}) {
|
|
2177
|
-
const context = {
|
|
2178
|
-
request: _request,
|
|
2179
|
-
options: resolveFetchOptions(_request, _options, globalOptions.defaults, Headers),
|
|
2180
|
-
response: void 0,
|
|
2181
|
-
error: void 0
|
|
2182
|
-
};
|
|
2183
|
-
if (context.options.method) context.options.method = context.options.method.toUpperCase();
|
|
2184
|
-
if (context.options.onRequest) {
|
|
2185
|
-
await callHooks(context, context.options.onRequest);
|
|
2186
|
-
if (!(context.options.headers instanceof Headers)) context.options.headers = new Headers(context.options.headers || {});
|
|
2187
|
-
}
|
|
2188
|
-
if (typeof context.request === "string") {
|
|
2189
|
-
if (context.options.baseURL) context.request = withBase(context.request, context.options.baseURL);
|
|
2190
|
-
if (context.options.query) {
|
|
2191
|
-
context.request = withQuery(context.request, context.options.query);
|
|
2192
|
-
delete context.options.query;
|
|
2193
|
-
}
|
|
2194
|
-
if ("query" in context.options) delete context.options.query;
|
|
2195
|
-
if ("params" in context.options) delete context.options.params;
|
|
2196
|
-
}
|
|
2197
|
-
if (context.options.body && isPayloadMethod(context.options.method)) {
|
|
2198
|
-
if (isJSONSerializable(context.options.body)) {
|
|
2199
|
-
const contentType = context.options.headers.get("content-type");
|
|
2200
|
-
if (typeof context.options.body !== "string") context.options.body = contentType === "application/x-www-form-urlencoded" ? new URLSearchParams(context.options.body).toString() : JSON.stringify(context.options.body);
|
|
2201
|
-
if (!contentType) context.options.headers.set("content-type", "application/json");
|
|
2202
|
-
if (!context.options.headers.has("accept")) context.options.headers.set("accept", "application/json");
|
|
2203
|
-
} else if ("pipeTo" in context.options.body && typeof context.options.body.pipeTo === "function" || typeof context.options.body.pipe === "function") {
|
|
2204
|
-
if (!("duplex" in context.options)) context.options.duplex = "half";
|
|
2205
|
-
}
|
|
2206
|
-
}
|
|
2207
|
-
let abortTimeout;
|
|
2208
|
-
if (!context.options.signal && context.options.timeout) {
|
|
2209
|
-
const controller = new AbortController();
|
|
2210
|
-
abortTimeout = setTimeout(() => {
|
|
2211
|
-
const error = new Error("[TimeoutError]: The operation was aborted due to timeout");
|
|
2212
|
-
error.name = "TimeoutError";
|
|
2213
|
-
error.code = 23;
|
|
2214
|
-
controller.abort(error);
|
|
2215
|
-
}, context.options.timeout);
|
|
2216
|
-
context.options.signal = controller.signal;
|
|
2217
|
-
}
|
|
2218
|
-
try {
|
|
2219
|
-
context.response = await fetch(context.request, context.options);
|
|
2220
|
-
} catch (error) {
|
|
2221
|
-
context.error = error;
|
|
2222
|
-
if (context.options.onRequestError) await callHooks(context, context.options.onRequestError);
|
|
2223
|
-
return await onError(context);
|
|
2224
|
-
} finally {
|
|
2225
|
-
if (abortTimeout) clearTimeout(abortTimeout);
|
|
2226
|
-
}
|
|
2227
|
-
if ((context.response.body || context.response._bodyInit) && !nullBodyResponses.has(context.response.status) && context.options.method !== "HEAD") {
|
|
2228
|
-
const responseType = (context.options.parseResponse ? "json" : context.options.responseType) || detectResponseType(context.response.headers.get("content-type") || "");
|
|
2229
|
-
switch (responseType) {
|
|
2230
|
-
case "json": {
|
|
2231
|
-
const data = await context.response.text();
|
|
2232
|
-
const parseFunction = context.options.parseResponse || destr;
|
|
2233
|
-
context.response._data = parseFunction(data);
|
|
2234
|
-
break;
|
|
2235
|
-
}
|
|
2236
|
-
case "stream":
|
|
2237
|
-
context.response._data = context.response.body || context.response._bodyInit;
|
|
2238
|
-
break;
|
|
2239
|
-
default: context.response._data = await context.response[responseType]();
|
|
2240
|
-
}
|
|
2241
|
-
}
|
|
2242
|
-
if (context.options.onResponse) await callHooks(context, context.options.onResponse);
|
|
2243
|
-
if (!context.options.ignoreResponseError && context.response.status >= 400 && context.response.status < 600) {
|
|
2244
|
-
if (context.options.onResponseError) await callHooks(context, context.options.onResponseError);
|
|
2245
|
-
return await onError(context);
|
|
2246
|
-
}
|
|
2247
|
-
return context.response;
|
|
2248
|
-
};
|
|
2249
|
-
const $fetch = async function $fetch2(request, options) {
|
|
2250
|
-
return (await $fetchRaw(request, options))._data;
|
|
2251
|
-
};
|
|
2252
|
-
$fetch.raw = $fetchRaw;
|
|
2253
|
-
$fetch.native = (...args) => fetch(...args);
|
|
2254
|
-
$fetch.create = (defaultOptions = {}, customGlobalOptions = {}) => createFetch({
|
|
2255
|
-
...globalOptions,
|
|
2256
|
-
...customGlobalOptions,
|
|
2257
|
-
defaults: {
|
|
2258
|
-
...globalOptions.defaults,
|
|
2259
|
-
...customGlobalOptions.defaults,
|
|
2260
|
-
...defaultOptions
|
|
2261
|
-
}
|
|
2262
|
-
});
|
|
2263
|
-
return $fetch;
|
|
2404
|
+
switch (jwk.kty) {
|
|
2405
|
+
case "AKP":
|
|
2406
|
+
check(jwk.alg, "\"alg\" (Algorithm) Parameter");
|
|
2407
|
+
check(jwk.pub, "\"pub\" (Public key) Parameter");
|
|
2408
|
+
components = {
|
|
2409
|
+
alg: jwk.alg,
|
|
2410
|
+
kty: jwk.kty,
|
|
2411
|
+
pub: jwk.pub
|
|
2412
|
+
};
|
|
2413
|
+
break;
|
|
2414
|
+
case "EC":
|
|
2415
|
+
check(jwk.crv, "\"crv\" (Curve) Parameter");
|
|
2416
|
+
check(jwk.x, "\"x\" (X Coordinate) Parameter");
|
|
2417
|
+
check(jwk.y, "\"y\" (Y Coordinate) Parameter");
|
|
2418
|
+
components = {
|
|
2419
|
+
crv: jwk.crv,
|
|
2420
|
+
kty: jwk.kty,
|
|
2421
|
+
x: jwk.x,
|
|
2422
|
+
y: jwk.y
|
|
2423
|
+
};
|
|
2424
|
+
break;
|
|
2425
|
+
case "OKP":
|
|
2426
|
+
check(jwk.crv, "\"crv\" (Subtype of Key Pair) Parameter");
|
|
2427
|
+
check(jwk.x, "\"x\" (Public Key) Parameter");
|
|
2428
|
+
components = {
|
|
2429
|
+
crv: jwk.crv,
|
|
2430
|
+
kty: jwk.kty,
|
|
2431
|
+
x: jwk.x
|
|
2432
|
+
};
|
|
2433
|
+
break;
|
|
2434
|
+
case "RSA":
|
|
2435
|
+
check(jwk.e, "\"e\" (Exponent) Parameter");
|
|
2436
|
+
check(jwk.n, "\"n\" (Modulus) Parameter");
|
|
2437
|
+
components = {
|
|
2438
|
+
e: jwk.e,
|
|
2439
|
+
kty: jwk.kty,
|
|
2440
|
+
n: jwk.n
|
|
2441
|
+
};
|
|
2442
|
+
break;
|
|
2443
|
+
case "oct":
|
|
2444
|
+
check(jwk.k, "\"k\" (Key Value) Parameter");
|
|
2445
|
+
components = {
|
|
2446
|
+
k: jwk.k,
|
|
2447
|
+
kty: jwk.kty
|
|
2448
|
+
};
|
|
2449
|
+
break;
|
|
2450
|
+
default: throw new JOSENotSupported("\"kty\" (Key Type) Parameter missing or unsupported");
|
|
2451
|
+
}
|
|
2452
|
+
const data = encode$1(JSON.stringify(components));
|
|
2453
|
+
return encode(await digest(digestAlgorithm, data));
|
|
2264
2454
|
}
|
|
2265
2455
|
//#endregion
|
|
2266
|
-
//#region
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2456
|
+
//#region ../../node_modules/.pnpm/jose@6.2.4/node_modules/jose/dist/webapi/util/decode_protected_header.js
|
|
2457
|
+
function decodeProtectedHeader(token) {
|
|
2458
|
+
let protectedB64u;
|
|
2459
|
+
if (typeof token === "string") {
|
|
2460
|
+
const parts = token.split(".");
|
|
2461
|
+
if (parts.length === 3 || parts.length === 5) [protectedB64u] = parts;
|
|
2462
|
+
} else if (typeof token === "object" && token) if ("protected" in token) protectedB64u = token.protected;
|
|
2463
|
+
else throw new TypeError("Token does not contain a Protected Header");
|
|
2464
|
+
try {
|
|
2465
|
+
if (typeof protectedB64u !== "string" || !protectedB64u) throw new Error();
|
|
2466
|
+
const result = JSON.parse(decoder.decode(decode(protectedB64u)));
|
|
2467
|
+
if (!isObject(result)) throw new Error();
|
|
2468
|
+
return result;
|
|
2469
|
+
} catch {
|
|
2470
|
+
throw new TypeError("Invalid Token or Protected Header formatting");
|
|
2471
|
+
}
|
|
2270
2472
|
}
|
|
2271
|
-
|
|
2272
|
-
|
|
2473
|
+
//#endregion
|
|
2474
|
+
//#region ../../node_modules/.pnpm/jose@6.2.4/node_modules/jose/dist/webapi/util/decode_jwt.js
|
|
2475
|
+
function decodeJwt(jwt) {
|
|
2476
|
+
if (typeof jwt !== "string") throw new JWTInvalid("JWTs must use Compact JWS serialization, JWT must be a string");
|
|
2477
|
+
const { 1: payload, length } = jwt.split(".");
|
|
2478
|
+
if (length === 5) throw new JWTInvalid("Only JWTs using Compact JWS serialization can be decoded");
|
|
2479
|
+
if (length !== 3) throw new JWTInvalid("Invalid JWT");
|
|
2480
|
+
if (!payload) throw new JWTInvalid("JWTs must contain a payload");
|
|
2481
|
+
let decoded;
|
|
2273
2482
|
try {
|
|
2274
|
-
|
|
2275
|
-
method: options.method,
|
|
2276
|
-
headers: options.headers,
|
|
2277
|
-
body: options.body,
|
|
2278
|
-
credentials: options.credentials ?? "include",
|
|
2279
|
-
retry: 0,
|
|
2280
|
-
timeout: options.timeoutMs,
|
|
2281
|
-
redirect: "manual",
|
|
2282
|
-
signal: options.signal,
|
|
2283
|
-
responseType: "stream",
|
|
2284
|
-
ignoreResponseError: true
|
|
2285
|
-
});
|
|
2483
|
+
decoded = decode(payload);
|
|
2286
2484
|
} catch {
|
|
2287
|
-
throw
|
|
2485
|
+
throw new JWTInvalid("Failed to base64url decode the payload");
|
|
2288
2486
|
}
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
throw (
|
|
2487
|
+
let result;
|
|
2488
|
+
try {
|
|
2489
|
+
result = JSON.parse(decoder.decode(decoded));
|
|
2490
|
+
} catch {
|
|
2491
|
+
throw new JWTInvalid("Failed to parse the decoded payload as JSON");
|
|
2294
2492
|
}
|
|
2493
|
+
if (!isObject(result)) throw new JWTInvalid("Invalid JWT Claims Set");
|
|
2494
|
+
return result;
|
|
2495
|
+
}
|
|
2496
|
+
//#endregion
|
|
2497
|
+
//#region src/organization-presence.ts
|
|
2498
|
+
const id$1 = /^[A-Za-z0-9_-]{1,128}$(?![\s\S])/;
|
|
2499
|
+
function presenceInput(input) {
|
|
2500
|
+
if (!input || typeof input.applicationId !== "string" || !id$1.test(input.applicationId) || !Array.isArray(input.userIds) || input.userIds.length < 1 || input.userIds.length > 50 || input.userIds.some((value) => typeof value !== "string" || !id$1.test(value)) || new Set(input.userIds).size !== input.userIds.length) throw new TypeError("Organization presence selection is invalid");
|
|
2295
2501
|
return {
|
|
2296
|
-
|
|
2297
|
-
|
|
2502
|
+
applicationId: input.applicationId,
|
|
2503
|
+
userIds: [...input.userIds]
|
|
2298
2504
|
};
|
|
2299
2505
|
}
|
|
2300
|
-
|
|
2301
|
-
const length = response.headers.get("content-length");
|
|
2302
|
-
if (length && (!/^\d+$/.test(length) || Number(length) > maximum)) {
|
|
2303
|
-
await response.body?.cancel();
|
|
2304
|
-
throw authorityUnavailable();
|
|
2305
|
-
}
|
|
2306
|
-
if (!response.body) throw authorityUnavailable();
|
|
2307
|
-
const reader = response.body.getReader();
|
|
2308
|
-
const chunks = [];
|
|
2309
|
-
let size = 0;
|
|
2310
|
-
try {
|
|
2311
|
-
while (true) {
|
|
2312
|
-
const { done, value } = await reader.read();
|
|
2313
|
-
if (done) break;
|
|
2314
|
-
size += value.byteLength;
|
|
2315
|
-
if (size > maximum) throw authorityUnavailable();
|
|
2316
|
-
chunks.push(value);
|
|
2317
|
-
}
|
|
2318
|
-
} catch (error) {
|
|
2319
|
-
await reader.cancel();
|
|
2320
|
-
throw error;
|
|
2321
|
-
} finally {
|
|
2322
|
-
reader.releaseLock();
|
|
2323
|
-
}
|
|
2324
|
-
const bytes = new Uint8Array(size);
|
|
2325
|
-
let offset = 0;
|
|
2326
|
-
for (const chunk of chunks) {
|
|
2327
|
-
bytes.set(chunk, offset);
|
|
2328
|
-
offset += chunk.byteLength;
|
|
2329
|
-
}
|
|
2506
|
+
function presenceProofActor(token, applicationId) {
|
|
2330
2507
|
try {
|
|
2331
|
-
|
|
2508
|
+
const claims = decodeJwt(token);
|
|
2509
|
+
if (typeof claims.sub !== "string" || !id$1.test(claims.sub) || typeof claims.sid !== "string" || !id$1.test(claims.sid) || claims.app !== applicationId) throw new Error("Invalid projection");
|
|
2510
|
+
return {
|
|
2511
|
+
userId: claims.sub,
|
|
2512
|
+
sessionId: claims.sid
|
|
2513
|
+
};
|
|
2332
2514
|
} catch {
|
|
2333
|
-
throw
|
|
2515
|
+
throw new TypeError("Organization presence credential is invalid");
|
|
2334
2516
|
}
|
|
2335
2517
|
}
|
|
2518
|
+
function exact$4(value, keys) {
|
|
2519
|
+
return !!value && typeof value === "object" && !Array.isArray(value) && Object.keys(value).length === keys.length && keys.every((key) => Object.hasOwn(value, key));
|
|
2520
|
+
}
|
|
2521
|
+
function normalizePresence(value, organizationId, input, actor) {
|
|
2522
|
+
if (!exact$4(value, [
|
|
2523
|
+
"organizationId",
|
|
2524
|
+
"applicationId",
|
|
2525
|
+
"actor",
|
|
2526
|
+
"userIds",
|
|
2527
|
+
"checkedAt"
|
|
2528
|
+
]) || value.organizationId !== organizationId || value.applicationId !== input.applicationId || !exact$4(value.actor, ["userId", "sessionId"]) || value.actor.userId !== actor.userId || value.actor.sessionId !== actor.sessionId || !Array.isArray(value.userIds) || value.userIds.length !== input.userIds.length || value.userIds.some((userId, index) => userId !== input.userIds[index]) || typeof value.checkedAt !== "string" || !/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$(?![\s\S])/.test(value.checkedAt) || Number.isNaN(Date.parse(value.checkedAt)) || new Date(value.checkedAt).toISOString() !== value.checkedAt) throw new AuthError("identity_authority_unavailable", 503);
|
|
2529
|
+
return {
|
|
2530
|
+
organizationId,
|
|
2531
|
+
applicationId: input.applicationId,
|
|
2532
|
+
actor: { ...actor },
|
|
2533
|
+
userIds: [...input.userIds],
|
|
2534
|
+
checkedAt: new Date(value.checkedAt)
|
|
2535
|
+
};
|
|
2536
|
+
}
|
|
2537
|
+
//#endregion
|
|
2538
|
+
//#region src/application-access.ts
|
|
2539
|
+
const id = /^[A-Za-z0-9_-]{1,128}$(?![\s\S])/;
|
|
2540
|
+
function applicationAccessInput(input) {
|
|
2541
|
+
if (!input || typeof input.applicationId !== "string" || !id.test(input.applicationId) || !Array.isArray(input.userIds) || input.userIds.length < 1 || input.userIds.length > 50 || input.userIds.some((value) => typeof value !== "string" || !id.test(value)) || new Set(input.userIds).size !== input.userIds.length) throw new TypeError("Application access input is invalid");
|
|
2542
|
+
return {
|
|
2543
|
+
applicationId: input.applicationId,
|
|
2544
|
+
userIds: [...input.userIds]
|
|
2545
|
+
};
|
|
2546
|
+
}
|
|
2547
|
+
function exact$3(value, keys) {
|
|
2548
|
+
return !!value && typeof value === "object" && !Array.isArray(value) && Object.keys(value).length === keys.length && keys.every((key) => Object.hasOwn(value, key));
|
|
2549
|
+
}
|
|
2550
|
+
function normalizeApplicationAccess(value, userIds) {
|
|
2551
|
+
const invalid = () => new AuthError("identity_authority_unavailable", 503);
|
|
2552
|
+
if (!exact$3(value, ["members"]) || !Array.isArray(value.members) || value.members.length !== userIds.length) throw invalid();
|
|
2553
|
+
return { members: value.members.map((member, index) => {
|
|
2554
|
+
if (!exact$3(member, [
|
|
2555
|
+
"userId",
|
|
2556
|
+
"latestAppSessionAdmittedAt",
|
|
2557
|
+
"activeAppSessionCount"
|
|
2558
|
+
]) || member.userId !== userIds[index] || typeof member.activeAppSessionCount !== "number" || !Number.isSafeInteger(member.activeAppSessionCount) || member.activeAppSessionCount < 0 || member.latestAppSessionAdmittedAt !== null && (typeof member.latestAppSessionAdmittedAt !== "string" || !/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$(?![\s\S])/.test(member.latestAppSessionAdmittedAt) || Number.isNaN(Date.parse(member.latestAppSessionAdmittedAt)) || new Date(member.latestAppSessionAdmittedAt).toISOString() !== member.latestAppSessionAdmittedAt)) throw invalid();
|
|
2559
|
+
return {
|
|
2560
|
+
userId: member.userId,
|
|
2561
|
+
latestAppSessionAdmittedAt: member.latestAppSessionAdmittedAt,
|
|
2562
|
+
activeAppSessionCount: member.activeAppSessionCount
|
|
2563
|
+
};
|
|
2564
|
+
}) };
|
|
2565
|
+
}
|
|
2566
|
+
//#endregion
|
|
2567
|
+
//#region src/google-recovery.ts
|
|
2568
|
+
function object(value) {
|
|
2569
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
2570
|
+
}
|
|
2571
|
+
function validTicket(value) {
|
|
2572
|
+
return typeof value === "string" && /^[A-Za-z0-9_-]{43}$/.test(value);
|
|
2573
|
+
}
|
|
2574
|
+
function googleRecoveryInput(value, complete) {
|
|
2575
|
+
if (!object(value) || Object.keys(value).sort().join(",") !== (complete ? "idToken,recoveryToken" : "idToken") || !object(value.idToken) || Object.keys(value.idToken).some((key) => key !== "token" && key !== "nonce") || complete && !validTicket(value.recoveryToken)) throw new AuthError("invalid_request", 400);
|
|
2576
|
+
const social = normalizeSocialIdTokenInput({
|
|
2577
|
+
provider: "google",
|
|
2578
|
+
idToken: value.idToken.token,
|
|
2579
|
+
signUp: false,
|
|
2580
|
+
...value.idToken.nonce === void 0 ? {} : { nonce: value.idToken.nonce }
|
|
2581
|
+
});
|
|
2582
|
+
return {
|
|
2583
|
+
idToken: {
|
|
2584
|
+
token: social.idToken,
|
|
2585
|
+
...social.nonce === void 0 ? {} : { nonce: social.nonce }
|
|
2586
|
+
},
|
|
2587
|
+
...complete ? { recoveryToken: value.recoveryToken } : {}
|
|
2588
|
+
};
|
|
2589
|
+
}
|
|
2590
|
+
function normalizeGoogleRecovery(value, now) {
|
|
2591
|
+
if (!object(value) || Object.keys(value).sort().join(",") !== "expiresAt,recoveryToken" || !validTicket(value.recoveryToken) || typeof value.expiresAt !== "string") throw authorityUnavailable();
|
|
2592
|
+
const expiresAt = Date.parse(value.expiresAt);
|
|
2593
|
+
if (!Number.isFinite(expiresAt) || expiresAt <= now || expiresAt > now + 10 * 6e4) throw authorityUnavailable();
|
|
2594
|
+
return {
|
|
2595
|
+
recoveryToken: value.recoveryToken,
|
|
2596
|
+
expiresAt: value.expiresAt
|
|
2597
|
+
};
|
|
2598
|
+
}
|
|
2599
|
+
function normalizeGoogleRecoveryCompletion(value) {
|
|
2600
|
+
if (!object(value) || Object.keys(value).join(",") !== "linked" || value.linked !== true) throw authorityUnavailable();
|
|
2601
|
+
return { linked: true };
|
|
2602
|
+
}
|
|
2603
|
+
function fromGoogleRecoveryError(value, status, retryAfter) {
|
|
2604
|
+
const code = object(value) ? value.code : void 0;
|
|
2605
|
+
if (status === 409 && code === "GOOGLE_RECOVERY_IN_PROGRESS") return new AuthError("google_recovery_in_progress", 409);
|
|
2606
|
+
if (status === 409 && code === "GOOGLE_RECOVERY_NOT_REQUIRED") return new AuthError("google_recovery_not_required", 409);
|
|
2607
|
+
if (status === 403 && code === "GOOGLE_RECOVERY_EMAIL_VERIFICATION_REQUIRED") return new AuthError("email_verification_required", 403);
|
|
2608
|
+
if (status === 400 && code === "GOOGLE_RECOVERY_INVALID") return new AuthError("google_recovery_invalid", 400);
|
|
2609
|
+
if (status === 410 && code === "GOOGLE_RECOVERY_EXPIRED") return new AuthError("google_recovery_expired", 410);
|
|
2610
|
+
if (status === 403 && code === "GOOGLE_RECOVERY_ACCOUNT_MISMATCH") return new AuthError("google_recovery_account_mismatch", 403);
|
|
2611
|
+
if (status === 401 && code === "GOOGLE_RECOVERY_FRESH_SIGN_IN_REQUIRED") return new AuthError("recent_sign_in_required", 401);
|
|
2612
|
+
if (code === "GOOGLE_RECOVERY_UNAVAILABLE") return authorityUnavailable();
|
|
2613
|
+
return fromAccountAuthorityError(value, status, retryAfter);
|
|
2614
|
+
}
|
|
2615
|
+
//#endregion
|
|
2616
|
+
//#region src/user-api/credential.ts
|
|
2617
|
+
function userApiApplication(input) {
|
|
2618
|
+
if (!input || typeof input.applicationId !== "string" || !/^[A-Za-z0-9_-]{1,128}$(?![\s\S])/.test(input.applicationId) || input.forceRefresh !== void 0 && typeof input.forceRefresh !== "boolean") throw new TypeError("User API credential input is invalid");
|
|
2619
|
+
return input.applicationId;
|
|
2620
|
+
}
|
|
2621
|
+
function normalizeUserApiCredential(value, startedAt) {
|
|
2622
|
+
if (!value || typeof value !== "object" || Array.isArray(value) || !("tokenType" in value) || value.tokenType !== "Bearer" || !("token" in value) || typeof value.token !== "string" || value.token.length + 7 > 16 * 1024 || !/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(value.token) || !("expiresIn" in value) || typeof value.expiresIn !== "number" || !Number.isInteger(value.expiresIn) || value.expiresIn < 1 || value.expiresIn > 840 || Object.keys(value).sort().join(",") !== "expiresIn,token,tokenType") throw new AuthError("identity_authority_unavailable", 503);
|
|
2623
|
+
return {
|
|
2624
|
+
tokenType: "Bearer",
|
|
2625
|
+
token: value.token,
|
|
2626
|
+
expiresAt: new Date(startedAt + value.expiresIn * 1e3)
|
|
2627
|
+
};
|
|
2628
|
+
}
|
|
2336
2629
|
//#endregion
|
|
2337
2630
|
//#region src/user-api/verifier.ts
|
|
2338
2631
|
const ID = /^[A-Za-z0-9_-]{1,128}$(?![\s\S])/;
|
|
@@ -3064,8 +3357,8 @@ function createServerAuth(options) {
|
|
|
3064
3357
|
mapError: fromOrganizationMutationAuthorityError
|
|
3065
3358
|
});
|
|
3066
3359
|
}
|
|
3067
|
-
async function organizationRead(path, input, normalize) {
|
|
3068
|
-
const query =
|
|
3360
|
+
async function organizationRead(path, input, normalize, queryInput = normalizeOrganizationPageInput) {
|
|
3361
|
+
const query = queryInput(input);
|
|
3069
3362
|
return normalize(await requestJson(`${joinURL(authOrigin, "api/v1/auth/organizations", path)}${query.size ? `?${query}` : ""}`, {
|
|
3070
3363
|
fetch: fetchImpl,
|
|
3071
3364
|
timeoutMs,
|
|
@@ -3142,6 +3435,85 @@ function createServerAuth(options) {
|
|
|
3142
3435
|
getOrganization(organizationId) {
|
|
3143
3436
|
return organizationRead(normalizeIdInput(organizationId), void 0, normalizeOrganization);
|
|
3144
3437
|
},
|
|
3438
|
+
async authorizeOrganizationPresence(organizationId, input, serviceAssertion, options) {
|
|
3439
|
+
if (typeof serviceAssertion !== "string" || serviceAssertion.length > 16 * 1024 || !/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$(?![\s\S])/.test(serviceAssertion)) throw new TypeError("Organization presence service assertion is invalid");
|
|
3440
|
+
const organization = normalizeIdInput(organizationId);
|
|
3441
|
+
const body = presenceInput(input);
|
|
3442
|
+
let applicationCredential;
|
|
3443
|
+
if (options !== void 0) {
|
|
3444
|
+
const supplied = options?.applicationCredential;
|
|
3445
|
+
if (typeof supplied !== "string" || supplied.length > 16 * 1024 || !/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$(?![\s\S])/.test(supplied)) throw new TypeError("Organization presence credential is invalid");
|
|
3446
|
+
applicationCredential = supplied;
|
|
3447
|
+
} else {
|
|
3448
|
+
const startedAt = now();
|
|
3449
|
+
applicationCredential = normalizeUserApiCredential(await requestJson(joinURL(authOrigin, "api/v1/auth/user-api-credential"), {
|
|
3450
|
+
fetch: fetchImpl,
|
|
3451
|
+
timeoutMs,
|
|
3452
|
+
method: "POST",
|
|
3453
|
+
credentials,
|
|
3454
|
+
headers: {
|
|
3455
|
+
...authHeaders(),
|
|
3456
|
+
"content-type": "application/json"
|
|
3457
|
+
},
|
|
3458
|
+
body: { applicationId: body.applicationId }
|
|
3459
|
+
}), startedAt).token;
|
|
3460
|
+
}
|
|
3461
|
+
const actor = presenceProofActor(applicationCredential, body.applicationId);
|
|
3462
|
+
return normalizePresence(await requestJson(joinURL(authOrigin, "api/v1/auth/organizations", organization, "presence/authorize"), {
|
|
3463
|
+
fetch: fetchImpl,
|
|
3464
|
+
timeoutMs,
|
|
3465
|
+
method: "POST",
|
|
3466
|
+
maxResponseBytes: 16 * 1024,
|
|
3467
|
+
credentials,
|
|
3468
|
+
headers: {
|
|
3469
|
+
...authHeaders(!authorization),
|
|
3470
|
+
"content-type": "application/json",
|
|
3471
|
+
"x-finueva-application-credential": applicationCredential,
|
|
3472
|
+
"x-finueva-service-assertion": serviceAssertion
|
|
3473
|
+
},
|
|
3474
|
+
body,
|
|
3475
|
+
mapError: fromOrganizationReadAuthorityError
|
|
3476
|
+
}), organization, body, actor);
|
|
3477
|
+
},
|
|
3478
|
+
async getOrganizationMemberApplicationAccess(organizationId, input, serviceAssertion, options) {
|
|
3479
|
+
if (typeof serviceAssertion !== "string" || serviceAssertion.length > 16 * 1024 || !/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$(?![\s\S])/.test(serviceAssertion)) throw new TypeError("Application access service assertion is invalid");
|
|
3480
|
+
const organization = normalizeIdInput(organizationId);
|
|
3481
|
+
const body = applicationAccessInput(input);
|
|
3482
|
+
let applicationCredential;
|
|
3483
|
+
if (options !== void 0) {
|
|
3484
|
+
const supplied = options?.applicationCredential;
|
|
3485
|
+
if (typeof supplied !== "string" || supplied.length > 16 * 1024 || !/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$(?![\s\S])/.test(supplied)) throw new TypeError("Application access credential is invalid");
|
|
3486
|
+
applicationCredential = supplied;
|
|
3487
|
+
} else {
|
|
3488
|
+
const startedAt = now();
|
|
3489
|
+
applicationCredential = normalizeUserApiCredential(await requestJson(joinURL(authOrigin, "api/v1/auth/user-api-credential"), {
|
|
3490
|
+
fetch: fetchImpl,
|
|
3491
|
+
timeoutMs,
|
|
3492
|
+
method: "POST",
|
|
3493
|
+
credentials,
|
|
3494
|
+
headers: {
|
|
3495
|
+
...authHeaders(),
|
|
3496
|
+
"content-type": "application/json"
|
|
3497
|
+
},
|
|
3498
|
+
body: { applicationId: body.applicationId }
|
|
3499
|
+
}), startedAt).token;
|
|
3500
|
+
}
|
|
3501
|
+
return normalizeApplicationAccess(await requestJson(joinURL(authOrigin, "api/v1/auth/organizations", organization, "members/application-access"), {
|
|
3502
|
+
fetch: fetchImpl,
|
|
3503
|
+
timeoutMs,
|
|
3504
|
+
method: "POST",
|
|
3505
|
+
maxResponseBytes: 16 * 1024,
|
|
3506
|
+
credentials,
|
|
3507
|
+
headers: {
|
|
3508
|
+
...authHeaders(!authorization),
|
|
3509
|
+
"content-type": "application/json",
|
|
3510
|
+
"x-finueva-application-credential": applicationCredential,
|
|
3511
|
+
"x-finueva-service-assertion": serviceAssertion
|
|
3512
|
+
},
|
|
3513
|
+
body,
|
|
3514
|
+
mapError: fromOrganizationReadAuthorityError
|
|
3515
|
+
}), body.userIds);
|
|
3516
|
+
},
|
|
3145
3517
|
async getOrganizationMemberAuthority(organizationId, memberId) {
|
|
3146
3518
|
const organization = normalizeIdInput(organizationId);
|
|
3147
3519
|
const member = normalizeIdInput(memberId);
|
|
@@ -3316,7 +3688,7 @@ function createServerAuth(options) {
|
|
|
3316
3688
|
}));
|
|
3317
3689
|
},
|
|
3318
3690
|
listOrganizationMembers(organizationId, input) {
|
|
3319
|
-
return organizationRead(`${normalizeIdInput(organizationId)}/members`, input, normalizeOrganizationMembers);
|
|
3691
|
+
return organizationRead(`${normalizeIdInput(organizationId)}/members`, input, normalizeOrganizationMembers, normalizeOrganizationMemberPageInput);
|
|
3320
3692
|
},
|
|
3321
3693
|
listOrganizationTeams(organizationId, input) {
|
|
3322
3694
|
return organizationRead(`${normalizeIdInput(organizationId)}/teams`, input, normalizeOrganizationTeams);
|
|
@@ -3481,4 +3853,4 @@ function authAuthorizationHeader(value) {
|
|
|
3481
3853
|
return value;
|
|
3482
3854
|
}
|
|
3483
3855
|
//#endregion
|
|
3484
|
-
export { AuthError, createDriveProvisioningAuth, createDriveRecipientAuth, createIdentityResolverAuth, createMembershipResolverAuth, createServerAuth, createUserApiVerifier };
|
|
3856
|
+
export { AuthError, createAccountProductOperationAuth, createDriveProvisioningAuth, createDriveRecipientAuth, createIdentityResolverAuth, createMembershipResolverAuth, createServerAuth, createUserApiVerifier };
|