@tempoxyz/id 0.0.0-pr-718.sha-8b3b450 → 0.0.0-pr-723.sha-e2f626f
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/dist/{Connections-DLVOXLEL.js → Connections-GTESLWTN.js} +2 -2
- package/dist/{Sheet-II5IGP5J.js → Sheet-GQPH2MUR.js} +1 -1
- package/dist/{chunk-MTJSZT4S.js → chunk-AOIGHDXR.js} +304 -97
- package/dist/{chunk-O3UAZSAM.js → chunk-DN57D5UC.js} +1 -1
- package/dist/{chunk-7JMEEUUA.js → chunk-K4WPSEXZ.js} +1 -1
- package/dist/commands/login.js +3 -3
- package/dist/commands/logout.js +3 -3
- package/dist/commands/whoami.js +3 -3
- package/dist/{dialog-FFLTODHO.js → dialog-TGNSW7U4.js} +1 -1
- package/package.json +1 -1
|
@@ -308,6 +308,7 @@ async function clientAuthentication(auth) {
|
|
|
308
308
|
if (auth.clientSecret) return { client_secret: auth.clientSecret };
|
|
309
309
|
return {};
|
|
310
310
|
}
|
|
311
|
+
var revokeTimeout = 1e4;
|
|
311
312
|
async function revoke(auth, options) {
|
|
312
313
|
const body = new URLSearchParams({
|
|
313
314
|
client_id: auth.clientId,
|
|
@@ -315,29 +316,38 @@ async function revoke(auth, options) {
|
|
|
315
316
|
token_type_hint: "refresh_token",
|
|
316
317
|
...await clientAuthentication(auth)
|
|
317
318
|
});
|
|
318
|
-
const
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
319
|
+
const controller = new AbortController();
|
|
320
|
+
const timer = setTimeout(() => controller.abort(), revokeTimeout);
|
|
321
|
+
try {
|
|
322
|
+
const response = await (auth.fetch ?? fetch)(
|
|
323
|
+
new URL("/oauth2/revoke", auth.url),
|
|
324
|
+
{
|
|
325
|
+
body,
|
|
326
|
+
// A session cookie fails the issuer's origin check, and the revocation needs none.
|
|
327
|
+
credentials: "omit",
|
|
328
|
+
method: "POST",
|
|
329
|
+
// A redirect would send the refresh token and the client authentication to another origin.
|
|
330
|
+
redirect: "manual",
|
|
331
|
+
signal: controller.signal
|
|
332
|
+
}
|
|
333
|
+
).catch((error3) => {
|
|
334
|
+
if (controller.signal.aborted) return void 0;
|
|
335
|
+
throw new RequestError({
|
|
336
|
+
cause: error3,
|
|
337
|
+
code: "server_error",
|
|
338
|
+
message: "The revocation received no response. Check the connection, and sign out again.",
|
|
339
|
+
status: 0
|
|
340
|
+
});
|
|
334
341
|
});
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
342
|
+
if (!response) return;
|
|
343
|
+
if (response.ok) {
|
|
344
|
+
await response.body?.cancel();
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
await json(response);
|
|
348
|
+
} finally {
|
|
349
|
+
clearTimeout(timer);
|
|
339
350
|
}
|
|
340
|
-
await json(response);
|
|
341
351
|
}
|
|
342
352
|
var clientAssertionType = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer";
|
|
343
353
|
async function tokenHeaders(auth, options) {
|
|
@@ -359,6 +369,16 @@ function requestHeaders(init, options) {
|
|
|
359
369
|
function bound(token2) {
|
|
360
370
|
return jkt(token2) !== void 0;
|
|
361
371
|
}
|
|
372
|
+
function lifetime(token2) {
|
|
373
|
+
try {
|
|
374
|
+
const claims = JSON.parse(Base642.toString(token2.split(".")[1] ?? ""));
|
|
375
|
+
if (typeof claims.exp !== "number" || typeof claims.iat !== "number")
|
|
376
|
+
return void 0;
|
|
377
|
+
return (claims.exp - claims.iat) * 1e3;
|
|
378
|
+
} catch {
|
|
379
|
+
return void 0;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
362
382
|
function jkt(token2) {
|
|
363
383
|
try {
|
|
364
384
|
const claims = JSON.parse(Base642.toString(token2.split(".")[1] ?? ""));
|
|
@@ -1005,9 +1025,9 @@ async function authorizeUrl(auth, options) {
|
|
|
1005
1025
|
if (!accessKey2 && options.challenge !== void 0)
|
|
1006
1026
|
throw new ChallengeWithoutKeyError();
|
|
1007
1027
|
const redirectUri = options.redirectUri ?? auth.redirectUri ?? `${window.location.origin}/`;
|
|
1008
|
-
const key = accessKey2 ? await resolve(accessKey2) : void 0;
|
|
1028
|
+
const key = accessKey2 && !("address" in accessKey2) ? await resolve(accessKey2) : void 0;
|
|
1009
1029
|
const pending = from2({
|
|
1010
|
-
...key ? key.material : { key: false },
|
|
1030
|
+
...key ? key.material : accessKey2 ? {} : { key: false },
|
|
1011
1031
|
chainId: auth.chainId,
|
|
1012
1032
|
clientId: auth.clientId,
|
|
1013
1033
|
redirectUri,
|
|
@@ -1015,9 +1035,13 @@ async function authorizeUrl(auth, options) {
|
|
|
1015
1035
|
state: Base644.fromBytes(Bytes2.random(16), base64url),
|
|
1016
1036
|
verifier: Base644.fromBytes(Bytes2.random(32), base64url)
|
|
1017
1037
|
});
|
|
1018
|
-
const authorization2 =
|
|
1019
|
-
|
|
1020
|
-
|
|
1038
|
+
const authorization2 = (() => {
|
|
1039
|
+
if (!accessKey2) return void 0;
|
|
1040
|
+
if ("address" in accessKey2) return keyAuthorization(auth, { accessKey: accessKey2 });
|
|
1041
|
+
return keyAuthorization(auth, {
|
|
1042
|
+
accessKey: { ...accessKey2, account: key.accessKey }
|
|
1043
|
+
});
|
|
1044
|
+
})();
|
|
1021
1045
|
const url = new URL("/oauth2/authorize", auth.url);
|
|
1022
1046
|
const parameters = new URLSearchParams({
|
|
1023
1047
|
...options.challenge === void 0 ? {} : { challenge: options.challenge },
|
|
@@ -1074,23 +1098,39 @@ function request(auth, options) {
|
|
|
1074
1098
|
};
|
|
1075
1099
|
}
|
|
1076
1100
|
function keyAuthorization(auth, options) {
|
|
1077
|
-
const {
|
|
1078
|
-
const permissions2 = resolve2(
|
|
1101
|
+
const { accessKey: accessKey2 } = options;
|
|
1102
|
+
const permissions2 = resolve2(accessKey2, {
|
|
1079
1103
|
chainId: auth.chainId
|
|
1080
1104
|
});
|
|
1081
|
-
const
|
|
1105
|
+
const named = (() => {
|
|
1106
|
+
if ("address" in accessKey2)
|
|
1107
|
+
return {
|
|
1108
|
+
account: options.account ?? accessKey2.access,
|
|
1109
|
+
address: accessKey2.address,
|
|
1110
|
+
keyType: accessKey2.type ?? "secp256k1",
|
|
1111
|
+
witness: accessKey2.witness
|
|
1112
|
+
};
|
|
1113
|
+
const { account: signer } = accessKey2;
|
|
1114
|
+
return {
|
|
1115
|
+
account: options.account ?? (signer.accessKeyAddress ? signer.address : void 0),
|
|
1116
|
+
address: signer.accessKeyAddress ?? signer.address,
|
|
1117
|
+
keyType: signer.keyType,
|
|
1118
|
+
witness: void 0
|
|
1119
|
+
};
|
|
1120
|
+
})();
|
|
1082
1121
|
return {
|
|
1083
|
-
...
|
|
1084
|
-
address:
|
|
1122
|
+
...named.account ? { account: named.account } : {},
|
|
1123
|
+
address: named.address,
|
|
1085
1124
|
chainId: Hex2.fromNumber(permissions2.chainId),
|
|
1086
1125
|
expiry: permissions2.expiry,
|
|
1087
|
-
keyType:
|
|
1126
|
+
keyType: named.keyType,
|
|
1088
1127
|
limits: permissions2.limits?.map(({ limit, period, token: token2 }) => ({
|
|
1089
1128
|
limit: Hex2.fromNumber(limit),
|
|
1090
1129
|
...period ? { period } : {},
|
|
1091
1130
|
token: token2
|
|
1092
1131
|
})),
|
|
1093
|
-
scopes: permissions2.scopes
|
|
1132
|
+
scopes: permissions2.scopes,
|
|
1133
|
+
...named.witness ? { witness: named.witness } : {}
|
|
1094
1134
|
};
|
|
1095
1135
|
}
|
|
1096
1136
|
function funding(options) {
|
|
@@ -1672,6 +1712,7 @@ var funding_exports = {};
|
|
|
1672
1712
|
__export(funding_exports, {
|
|
1673
1713
|
BlockedError: () => BlockedError,
|
|
1674
1714
|
OriginError: () => OriginError,
|
|
1715
|
+
PageRequiredError: () => PageRequiredError,
|
|
1675
1716
|
complete: () => complete2,
|
|
1676
1717
|
open: () => open
|
|
1677
1718
|
});
|
|
@@ -1691,6 +1732,14 @@ var OriginError = class extends Error {
|
|
|
1691
1732
|
);
|
|
1692
1733
|
}
|
|
1693
1734
|
};
|
|
1735
|
+
var PageRequiredError = class extends Error {
|
|
1736
|
+
name = "Actions.funding.PageRequiredError";
|
|
1737
|
+
constructor() {
|
|
1738
|
+
super(
|
|
1739
|
+
"No browser window: the deposit page opens only from a page. On a server, pass `funding` to `accounts.backend.start`. In a CLI, pass it to `accounts.device.signIn`."
|
|
1740
|
+
);
|
|
1741
|
+
}
|
|
1742
|
+
};
|
|
1694
1743
|
function complete2(auth, options = {}) {
|
|
1695
1744
|
const own2 = options.url === void 0;
|
|
1696
1745
|
const url = new URL(options.url ?? window.location.href);
|
|
@@ -1716,6 +1765,10 @@ function complete2(auth, options = {}) {
|
|
|
1716
1765
|
}
|
|
1717
1766
|
async function open(auth, options) {
|
|
1718
1767
|
const { amount, currency, signal, token: token2 } = options;
|
|
1768
|
+
if (typeof options.address === "object")
|
|
1769
|
+
Promise.resolve(options.address).catch(() => void 0);
|
|
1770
|
+
signal?.throwIfAborted();
|
|
1771
|
+
if (typeof document === "undefined") throw new PageRequiredError();
|
|
1719
1772
|
const mode = (() => {
|
|
1720
1773
|
const value = options.mode ?? "frame";
|
|
1721
1774
|
if (value !== "frame") return value;
|
|
@@ -1727,8 +1780,6 @@ async function open(auth, options) {
|
|
|
1727
1780
|
return "popup";
|
|
1728
1781
|
return value;
|
|
1729
1782
|
})();
|
|
1730
|
-
if (options.address instanceof Promise) options.address.catch(() => void 0);
|
|
1731
|
-
signal?.throwIfAborted();
|
|
1732
1783
|
const redirectUri = options.redirectUri ?? auth.redirectUri ?? `${window.location.origin}/`;
|
|
1733
1784
|
const toUrl = (address2, entry = { mode }) => {
|
|
1734
1785
|
const url = new URL(
|
|
@@ -1768,7 +1819,7 @@ async function open(auth, options) {
|
|
|
1768
1819
|
throw new OriginError({ origin: window.location.origin, redirectUri });
|
|
1769
1820
|
if (mode === "popup" && options.mode !== "popup" && !activated()) {
|
|
1770
1821
|
const address2 = await abortable(read2(), { signal });
|
|
1771
|
-
const Sheet = await import("./Sheet-
|
|
1822
|
+
const Sheet = await import("./Sheet-GQPH2MUR.js");
|
|
1772
1823
|
return await new Promise((resolve3, reject) => {
|
|
1773
1824
|
const abort = () => {
|
|
1774
1825
|
close();
|
|
@@ -1819,7 +1870,7 @@ async function watch(auth, options) {
|
|
|
1819
1870
|
try {
|
|
1820
1871
|
return await new Promise(
|
|
1821
1872
|
(resolve3, reject) => {
|
|
1822
|
-
void import("./Sheet-
|
|
1873
|
+
void import("./Sheet-GQPH2MUR.js").then(
|
|
1823
1874
|
(Sheet) => {
|
|
1824
1875
|
if (settled) return;
|
|
1825
1876
|
unblock = Sheet.waiting({
|
|
@@ -1884,7 +1935,7 @@ function parse(url, options) {
|
|
|
1884
1935
|
async function frame(auth, options) {
|
|
1885
1936
|
const { redirectUri, signal, toUrl } = options;
|
|
1886
1937
|
const address2 = await abortable(options.address, { signal });
|
|
1887
|
-
const Sheet = await import("./Sheet-
|
|
1938
|
+
const Sheet = await import("./Sheet-GQPH2MUR.js");
|
|
1888
1939
|
signal?.throwIfAborted();
|
|
1889
1940
|
let close;
|
|
1890
1941
|
let abort;
|
|
@@ -2052,7 +2103,7 @@ function complete3(auth, options = {}) {
|
|
|
2052
2103
|
removed
|
|
2053
2104
|
]);
|
|
2054
2105
|
return finish({
|
|
2055
|
-
accessKey:
|
|
2106
|
+
accessKey: options.accessKey,
|
|
2056
2107
|
body,
|
|
2057
2108
|
pending: stored
|
|
2058
2109
|
});
|
|
@@ -2065,7 +2116,7 @@ async function createUrl(auth, options = {}) {
|
|
|
2065
2116
|
}
|
|
2066
2117
|
async function handleCallback(auth, options) {
|
|
2067
2118
|
return finish({
|
|
2068
|
-
accessKey:
|
|
2119
|
+
accessKey: options.accessKey,
|
|
2069
2120
|
body: await redeem(auth, {
|
|
2070
2121
|
pending: options.pending,
|
|
2071
2122
|
url: new URL(options.url)
|
|
@@ -2094,7 +2145,7 @@ function handleResult(options) {
|
|
|
2094
2145
|
status: 400
|
|
2095
2146
|
});
|
|
2096
2147
|
return finish({
|
|
2097
|
-
accessKey:
|
|
2148
|
+
accessKey: options.accessKey,
|
|
2098
2149
|
body: authorization2,
|
|
2099
2150
|
pending: options.pending
|
|
2100
2151
|
});
|
|
@@ -2172,13 +2223,24 @@ function finish(options) {
|
|
|
2172
2223
|
signedIn: true,
|
|
2173
2224
|
status: 400
|
|
2174
2225
|
});
|
|
2226
|
+
if (options.accessKey && "address" in options.accessKey) {
|
|
2227
|
+
const tokens3 = tokens(body);
|
|
2228
|
+
return {
|
|
2229
|
+
...tokens3,
|
|
2230
|
+
key: from({
|
|
2231
|
+
account: body.account,
|
|
2232
|
+
keyAuthorization: body.key_authorization
|
|
2233
|
+
}),
|
|
2234
|
+
user: user(tokens3)
|
|
2235
|
+
};
|
|
2236
|
+
}
|
|
2175
2237
|
return authorization(
|
|
2176
2238
|
{
|
|
2177
2239
|
account: body.account,
|
|
2178
2240
|
key_authorization: body.key_authorization,
|
|
2179
2241
|
tokens: body
|
|
2180
2242
|
},
|
|
2181
|
-
{ accessKey: options.accessKey, material }
|
|
2243
|
+
{ accessKey: own(options.accessKey), material }
|
|
2182
2244
|
);
|
|
2183
2245
|
}
|
|
2184
2246
|
async function prefetch(auth) {
|
|
@@ -2204,16 +2266,28 @@ async function prefetch(auth) {
|
|
|
2204
2266
|
return urls;
|
|
2205
2267
|
}
|
|
2206
2268
|
async function start(auth, options = {}) {
|
|
2207
|
-
const { pending, url } = await createUrl(auth, options);
|
|
2208
2269
|
const store2 = get2(auth.store);
|
|
2270
|
+
const [{ pending, url }, stored] = await Promise.all([
|
|
2271
|
+
createUrl(auth, options),
|
|
2272
|
+
(async () => store2.getItem(indexKey))()
|
|
2273
|
+
]);
|
|
2274
|
+
const index = stored ?? [];
|
|
2209
2275
|
const now = Date.now();
|
|
2210
2276
|
const expiresAt = now + pendingLifetime;
|
|
2211
|
-
const
|
|
2212
|
-
|
|
2213
|
-
|
|
2277
|
+
const page = [
|
|
2278
|
+
...(written.get(store2) ?? []).filter((entry) => entry.expiresAt > now),
|
|
2279
|
+
{ expiresAt, state: pending.state }
|
|
2280
|
+
];
|
|
2281
|
+
written.set(store2, page);
|
|
2282
|
+
const rows = [
|
|
2283
|
+
...index,
|
|
2284
|
+
...page.filter((entry) => !index.some((row) => row.state === entry.state))
|
|
2285
|
+
];
|
|
2286
|
+
const expired3 = rows.filter((entry) => entry.expiresAt <= now);
|
|
2287
|
+
const kept = rows.filter((entry) => entry.expiresAt > now);
|
|
2214
2288
|
await Promise.all([
|
|
2215
2289
|
...expired3.map((entry) => store2.removeItem(storeKey(entry.state))),
|
|
2216
|
-
store2.setItem(indexKey,
|
|
2290
|
+
store2.setItem(indexKey, kept, {
|
|
2217
2291
|
expiresAt
|
|
2218
2292
|
}),
|
|
2219
2293
|
store2.setItem(storeKey(pending.state), pending, { expiresAt })
|
|
@@ -2222,6 +2296,7 @@ async function start(auth, options = {}) {
|
|
|
2222
2296
|
window.location.assign(url);
|
|
2223
2297
|
}
|
|
2224
2298
|
var completed = /* @__PURE__ */ new WeakMap();
|
|
2299
|
+
var written = /* @__PURE__ */ new WeakMap();
|
|
2225
2300
|
var indexKey = "tempo-id:redirects";
|
|
2226
2301
|
var pendingLifetime = 60 * 60 * 1e3;
|
|
2227
2302
|
var legacyStoreKey = "tempo-id:redirect";
|
|
@@ -2413,7 +2488,7 @@ async function authorize3(auth, options) {
|
|
|
2413
2488
|
let broadcast;
|
|
2414
2489
|
let name;
|
|
2415
2490
|
let unwatch;
|
|
2416
|
-
let
|
|
2491
|
+
let written2;
|
|
2417
2492
|
let sheet = reused;
|
|
2418
2493
|
try {
|
|
2419
2494
|
const { pending, url: popupUrl } = await Promise.race([
|
|
@@ -2435,8 +2510,8 @@ async function authorize3(auth, options) {
|
|
|
2435
2510
|
if (mode === "iframe")
|
|
2436
2511
|
sheet ??= create2({ url: frameUrl(auth, { redirectUri }) });
|
|
2437
2512
|
name = channel({ state: pending.state });
|
|
2438
|
-
|
|
2439
|
-
await Promise.race([
|
|
2513
|
+
written2 = Promise.resolve(store2.setItem(name, true));
|
|
2514
|
+
await Promise.race([written2, aborted, closed, replaced]);
|
|
2440
2515
|
if (popup?.closed)
|
|
2441
2516
|
throw new DOMException("The user closed the sign-in.", "AbortError");
|
|
2442
2517
|
const listener = new BroadcastChannel(name);
|
|
@@ -2519,7 +2594,7 @@ async function authorize3(auth, options) {
|
|
|
2519
2594
|
popup?.close();
|
|
2520
2595
|
if (name) {
|
|
2521
2596
|
const item = name;
|
|
2522
|
-
void (
|
|
2597
|
+
void (written2 ?? Promise.resolve()).then(() => store2.removeItem(item)).catch(() => {
|
|
2523
2598
|
});
|
|
2524
2599
|
}
|
|
2525
2600
|
}
|
|
@@ -2666,10 +2741,10 @@ __export(email_exports2, {
|
|
|
2666
2741
|
import { Authentication as Authentication3 } from "ox/webauthn";
|
|
2667
2742
|
|
|
2668
2743
|
// ../../accounts/src/internal/Registration.ts
|
|
2669
|
-
var
|
|
2744
|
+
var lifetime2 = 4 * 60 * 1e3;
|
|
2670
2745
|
function from3(value, options) {
|
|
2671
2746
|
return {
|
|
2672
|
-
expiresAt: options.requestedAt +
|
|
2747
|
+
expiresAt: options.requestedAt + lifetime2,
|
|
2673
2748
|
options: value.options,
|
|
2674
2749
|
...value.proof ? { proof: value.proof } : {}
|
|
2675
2750
|
};
|
|
@@ -3315,9 +3390,10 @@ function create3(options) {
|
|
|
3315
3390
|
// The message names a sign-out, which other tabs count as one. Another empty write,
|
|
3316
3391
|
// such as a renewal of an expired session, empties their session as `set` does.
|
|
3317
3392
|
save: (args) => {
|
|
3393
|
+
const signOut3 = args.event.type.startsWith("signOut");
|
|
3318
3394
|
const message = {
|
|
3319
|
-
everywhere: args.context.signingOut?.everywhere,
|
|
3320
|
-
signOut:
|
|
3395
|
+
everywhere: signOut3 && args.context.signingOut?.everywhere,
|
|
3396
|
+
signOut: signOut3
|
|
3321
3397
|
};
|
|
3322
3398
|
writes?.save(name, args.context.session).then(() => channel2?.postMessage(message)).catch(() => void 0);
|
|
3323
3399
|
}
|
|
@@ -3325,11 +3401,13 @@ function create3(options) {
|
|
|
3325
3401
|
})
|
|
3326
3402
|
).start() : void 0;
|
|
3327
3403
|
let obtained = 0;
|
|
3404
|
+
let obtainedLogouts = 0;
|
|
3328
3405
|
let held = actor?.getSnapshot().context.session;
|
|
3329
3406
|
actor?.subscribe((snapshot) => {
|
|
3330
3407
|
if (snapshot.context.session === held) return;
|
|
3331
3408
|
held = snapshot.context.session;
|
|
3332
3409
|
obtained = Date.now();
|
|
3410
|
+
obtainedLogouts = snapshot.context.logouts.remote;
|
|
3333
3411
|
});
|
|
3334
3412
|
const context = () => actor.getSnapshot().context;
|
|
3335
3413
|
function set(session2, options2 = {}) {
|
|
@@ -3460,9 +3538,17 @@ function create3(options) {
|
|
|
3460
3538
|
(entry) => typeof entry === "string"
|
|
3461
3539
|
) : [];
|
|
3462
3540
|
},
|
|
3541
|
+
/**
|
|
3542
|
+
* Returns the tokens that the entry holds once the store took the write, at most the latest 16,
|
|
3543
|
+
* or `undefined` when the store refused it.
|
|
3544
|
+
*/
|
|
3463
3545
|
async write(tokens3) {
|
|
3464
3546
|
const key = `${name}:unanswered`;
|
|
3465
|
-
|
|
3547
|
+
const held2 = tokens3.slice(-16);
|
|
3548
|
+
return (async () => {
|
|
3549
|
+
await (held2.length === 0 ? store2?.removeItem(key) : store2?.setItem(key, held2));
|
|
3550
|
+
return held2;
|
|
3551
|
+
})().catch(() => void 0);
|
|
3466
3552
|
}
|
|
3467
3553
|
};
|
|
3468
3554
|
const revoked = {
|
|
@@ -3673,6 +3759,7 @@ function create3(options) {
|
|
|
3673
3759
|
return () => subscription.unsubscribe();
|
|
3674
3760
|
}
|
|
3675
3761
|
const rotated = /* @__PURE__ */ new Map();
|
|
3762
|
+
const retained = /* @__PURE__ */ new Map();
|
|
3676
3763
|
const authorizations = /* @__PURE__ */ new Set();
|
|
3677
3764
|
return {
|
|
3678
3765
|
actor,
|
|
@@ -3938,19 +4025,41 @@ function create3(options) {
|
|
|
3938
4025
|
await hydrate();
|
|
3939
4026
|
await writes?.flush().catch(() => void 0);
|
|
3940
4027
|
const local = actor ? context().session : void 0;
|
|
4028
|
+
const unsaved = !!local && writes?.unsaved() === local;
|
|
4029
|
+
const logouts = obtainedLogouts;
|
|
4030
|
+
const since = obtained;
|
|
3941
4031
|
const before = await read2();
|
|
3942
4032
|
actor?.send({ type: "signOut" });
|
|
3943
4033
|
const ownSignIns = actor ? context().signIns : 0;
|
|
3944
4034
|
rotated.clear();
|
|
3945
4035
|
const emptied = settle(writes?.flush());
|
|
3946
4036
|
return exclusive(async () => {
|
|
3947
|
-
const [{ failed, stored }, earlier, digests] = await Promise.all(
|
|
3948
|
-
|
|
3949
|
-
|
|
3950
|
-
|
|
3951
|
-
|
|
4037
|
+
const [{ failed, stored }, earlier, digests, entries] = await Promise.all(
|
|
4038
|
+
[
|
|
4039
|
+
emptied.then(async (failed2) => ({ failed: failed2, stored: await read2() })),
|
|
4040
|
+
unanswered2.read(),
|
|
4041
|
+
revoked.read(),
|
|
4042
|
+
unsaved ? rotations.read() : void 0
|
|
4043
|
+
]
|
|
4044
|
+
);
|
|
4045
|
+
const held2 = !before || !local || before.user.id !== local.user.id;
|
|
4046
|
+
const revocable = (token2) => machines2.revocable({
|
|
4047
|
+
entries,
|
|
4048
|
+
held: held2,
|
|
4049
|
+
live: token2 && entries ? rotations.successor(entries, token2) : void 0,
|
|
4050
|
+
remote: !!actor && context().logouts.remote !== logouts,
|
|
4051
|
+
revoked: options2.revoked,
|
|
4052
|
+
since,
|
|
4053
|
+
token: token2
|
|
4054
|
+
});
|
|
3952
4055
|
const current = actor ? context().session : void 0;
|
|
3953
|
-
const ending = machines2.ending({
|
|
4056
|
+
const ending = machines2.ending({
|
|
4057
|
+
before,
|
|
4058
|
+
current,
|
|
4059
|
+
failed: unsaved,
|
|
4060
|
+
local,
|
|
4061
|
+
stored
|
|
4062
|
+
});
|
|
3954
4063
|
if (ending.empty)
|
|
3955
4064
|
actor?.send({ type: current ? "save" : "signOut.empty" });
|
|
3956
4065
|
const saved = ending.empty ? await settle(writes?.flush()) : void 0;
|
|
@@ -3959,11 +4068,24 @@ function create3(options) {
|
|
|
3959
4068
|
const skipped = ended?.refreshToken ? rotated.get(ended.refreshToken) : void 0;
|
|
3960
4069
|
const signIns = actor ? context().signIns : 0;
|
|
3961
4070
|
const known = !!ended?.refreshToken && ended.refreshToken === options2.revoked;
|
|
3962
|
-
const
|
|
3963
|
-
const
|
|
4071
|
+
const stale = unsaved && ended === local && !revocable(ended?.refreshToken);
|
|
4072
|
+
const revoking = known || stale || ended?.refreshToken && rotated.has(ended.refreshToken) || revoked.has(digests, ended) ? void 0 : ended;
|
|
4073
|
+
const unsavedToken = revocable(ending.unsaved?.refreshToken) ? ending.unsaved?.refreshToken : void 0;
|
|
4074
|
+
const resent = machines2.resent({
|
|
4075
|
+
remote: actor ? context().logouts.remote : void 0,
|
|
4076
|
+
retained
|
|
4077
|
+
});
|
|
4078
|
+
const pending = [
|
|
4079
|
+
.../* @__PURE__ */ new Set([
|
|
4080
|
+
...earlier ?? [],
|
|
4081
|
+
...resent,
|
|
4082
|
+
...unsavedToken ? [unsavedToken] : []
|
|
4083
|
+
])
|
|
4084
|
+
].filter(
|
|
3964
4085
|
(token2) => token2 !== revoking?.refreshToken && !revoked.has(digests, { refreshToken: token2 })
|
|
3965
4086
|
);
|
|
3966
4087
|
const answered2 = /* @__PURE__ */ new Set();
|
|
4088
|
+
const errors = /* @__PURE__ */ new Map();
|
|
3967
4089
|
const signedOut = await settle(
|
|
3968
4090
|
signOut2(revoking, {
|
|
3969
4091
|
logout: machines2.logout({
|
|
@@ -3983,6 +4105,9 @@ function create3(options) {
|
|
|
3983
4105
|
answered2.add(refreshToken);
|
|
3984
4106
|
return Promise.resolve();
|
|
3985
4107
|
},
|
|
4108
|
+
onUnanswered: (error3) => {
|
|
4109
|
+
errors.set(refreshToken, error3);
|
|
4110
|
+
},
|
|
3986
4111
|
refreshToken
|
|
3987
4112
|
})),
|
|
3988
4113
|
unrevoked: skipped
|
|
@@ -3996,22 +4121,47 @@ function create3(options) {
|
|
|
3996
4121
|
...pending.filter((token2) => answered2.has(token2)),
|
|
3997
4122
|
...revoking?.refreshToken && answered2.has(revoking.refreshToken) ? [revoking.refreshToken] : []
|
|
3998
4123
|
];
|
|
3999
|
-
await Promise.all([
|
|
4124
|
+
const [, persisted] = await Promise.all([
|
|
4000
4125
|
revoked.write(digests, marks),
|
|
4001
4126
|
(async () => {
|
|
4002
4127
|
if (earlier === void 0) {
|
|
4003
4128
|
const again = live.length > 0 ? await unanswered2.read() : void 0;
|
|
4004
|
-
if (again)
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
}
|
|
4010
|
-
|
|
4129
|
+
if (!again) return live.length === 0 ? [] : void 0;
|
|
4130
|
+
return unanswered2.write([
|
|
4131
|
+
...again.filter((token2) => !live.includes(token2)),
|
|
4132
|
+
...live
|
|
4133
|
+
]);
|
|
4134
|
+
}
|
|
4135
|
+
if (earlier.length > 0 || live.length > 0)
|
|
4136
|
+
return unanswered2.write(live);
|
|
4137
|
+
return [];
|
|
4011
4138
|
})()
|
|
4012
4139
|
]);
|
|
4140
|
+
const kept = machines2.retains({
|
|
4141
|
+
live,
|
|
4142
|
+
logouts,
|
|
4143
|
+
persisted,
|
|
4144
|
+
retained,
|
|
4145
|
+
unsaved: [
|
|
4146
|
+
...unsavedToken ? [unsavedToken] : [],
|
|
4147
|
+
...unsaved && local?.refreshToken ? [local.refreshToken] : []
|
|
4148
|
+
]
|
|
4149
|
+
});
|
|
4150
|
+
retained.clear();
|
|
4151
|
+
for (const [token2, remote] of kept) retained.set(token2, remote);
|
|
4013
4152
|
if (erased) throw erased.error;
|
|
4014
4153
|
if (signedOut) throw signedOut.error;
|
|
4154
|
+
const unsent = [...unsavedToken ? [unsavedToken] : [], ...resent];
|
|
4155
|
+
const failing = unsent.find(
|
|
4156
|
+
(token2) => pending.includes(token2) && !answered2.has(token2)
|
|
4157
|
+
);
|
|
4158
|
+
if (failing && errors.has(failing)) throw errors.get(failing);
|
|
4159
|
+
if (failing)
|
|
4160
|
+
throw new RequestError({
|
|
4161
|
+
code: "server_error",
|
|
4162
|
+
message: "Revocation failed: no response for the refresh token of the unsaved session. Sign out again once online.",
|
|
4163
|
+
status: 0
|
|
4164
|
+
});
|
|
4015
4165
|
});
|
|
4016
4166
|
}
|
|
4017
4167
|
}
|
|
@@ -4042,13 +4192,16 @@ function settle(promise) {
|
|
|
4042
4192
|
function queue(store2, options = {}) {
|
|
4043
4193
|
let pending = Promise.resolve();
|
|
4044
4194
|
let failed = false;
|
|
4045
|
-
|
|
4195
|
+
let unsaved;
|
|
4196
|
+
const enqueue = (write, session2) => {
|
|
4046
4197
|
const next = pending.catch(() => void 0).then(write).then(
|
|
4047
4198
|
() => {
|
|
4048
4199
|
failed = false;
|
|
4200
|
+
unsaved = void 0;
|
|
4049
4201
|
},
|
|
4050
4202
|
(error3) => {
|
|
4051
4203
|
failed = true;
|
|
4204
|
+
unsaved = session2;
|
|
4052
4205
|
throw error3;
|
|
4053
4206
|
}
|
|
4054
4207
|
);
|
|
@@ -4065,6 +4218,8 @@ function queue(store2, options = {}) {
|
|
|
4065
4218
|
};
|
|
4066
4219
|
return {
|
|
4067
4220
|
failed: () => failed,
|
|
4221
|
+
/** Returns the session that the last write failed to save, or `undefined` after a saved write. */
|
|
4222
|
+
unsaved: () => unsaved,
|
|
4068
4223
|
/**
|
|
4069
4224
|
* Resolves when every earlier write completed. It reads the queue after a microtask, since a
|
|
4070
4225
|
* change that a subscriber sends during another change is processed only once that change's
|
|
@@ -4079,7 +4234,8 @@ function queue(store2, options = {}) {
|
|
|
4079
4234
|
() => store2.setItem(name, {
|
|
4080
4235
|
state: { session: toSaved(session2) },
|
|
4081
4236
|
version: 0
|
|
4082
|
-
})
|
|
4237
|
+
}),
|
|
4238
|
+
session2
|
|
4083
4239
|
),
|
|
4084
4240
|
storage
|
|
4085
4241
|
};
|
|
@@ -4163,6 +4319,7 @@ var machines2;
|
|
|
4163
4319
|
logout: assign2((args) => ({
|
|
4164
4320
|
logouts: {
|
|
4165
4321
|
...args.context.logouts,
|
|
4322
|
+
remote: args.context.logouts.remote + 1,
|
|
4166
4323
|
started: args.context.logouts.started + 1
|
|
4167
4324
|
}
|
|
4168
4325
|
})),
|
|
@@ -4199,7 +4356,11 @@ var machines2;
|
|
|
4199
4356
|
const { logouts, signingOut } = args.context;
|
|
4200
4357
|
const { everywhere } = args.event;
|
|
4201
4358
|
return {
|
|
4202
|
-
logouts: everywhere ? {
|
|
4359
|
+
logouts: everywhere ? {
|
|
4360
|
+
...logouts,
|
|
4361
|
+
running: logouts.running + 1,
|
|
4362
|
+
started: logouts.started + 1
|
|
4363
|
+
} : logouts,
|
|
4203
4364
|
marked: !everywhere,
|
|
4204
4365
|
signingOut: { everywhere, runs: (signingOut?.runs ?? 0) + 1 }
|
|
4205
4366
|
};
|
|
@@ -4240,7 +4401,7 @@ var machines2;
|
|
|
4240
4401
|
authorizations: 0,
|
|
4241
4402
|
delegations: 0,
|
|
4242
4403
|
loaded: false,
|
|
4243
|
-
logouts: { running: 0, started: 0 },
|
|
4404
|
+
logouts: { remote: 0, running: 0, started: 0 },
|
|
4244
4405
|
marked: false,
|
|
4245
4406
|
refusals: 0,
|
|
4246
4407
|
renewing: void 0,
|
|
@@ -4298,17 +4459,24 @@ var machines2;
|
|
|
4298
4459
|
}
|
|
4299
4460
|
machines4.adoptable = adoptable;
|
|
4300
4461
|
function ending(options) {
|
|
4301
|
-
const { before, current, local, stored } = options;
|
|
4302
|
-
const ended2 =
|
|
4303
|
-
|
|
4462
|
+
const { before, current, failed, local, stored } = options;
|
|
4463
|
+
const ended2 = (() => {
|
|
4464
|
+
if (failed && !before) return local;
|
|
4465
|
+
return machines4.newer(before, local) ? before : local;
|
|
4466
|
+
})();
|
|
4467
|
+
const unsaved = failed && before && local && before.user.id !== local.user.id ? local : void 0;
|
|
4468
|
+
if (!stored || !ended2)
|
|
4469
|
+
return { empty: false, kept: false, session: ended2, unsaved };
|
|
4470
|
+
const held = !(failed && !before);
|
|
4304
4471
|
const own2 = stored.refreshToken === current?.refreshToken;
|
|
4305
|
-
const later = !own2 && stored.user.id === ended2.user.id && stored.key?.keyAuthorization.keyId === ended2.key?.keyAuthorization.keyId && stored.refreshToken !== ended2.refreshToken && stored.expiresAt >= ended2.expiresAt;
|
|
4306
|
-
const stale = !own2 && stored.refreshToken === ended2.refreshToken;
|
|
4472
|
+
const later = held && !own2 && stored.user.id === ended2.user.id && stored.key?.keyAuthorization.keyId === ended2.key?.keyAuthorization.keyId && stored.refreshToken !== ended2.refreshToken && stored.expiresAt >= ended2.expiresAt;
|
|
4473
|
+
const stale = held && !own2 && stored.refreshToken === ended2.refreshToken;
|
|
4307
4474
|
const kept = !own2 && !later && !stale && stored.user.id !== ended2.user.id;
|
|
4308
4475
|
return {
|
|
4309
4476
|
empty: later || stale,
|
|
4310
4477
|
kept,
|
|
4311
|
-
session: later ? stored : ended2
|
|
4478
|
+
session: later ? stored : ended2,
|
|
4479
|
+
unsaved
|
|
4312
4480
|
};
|
|
4313
4481
|
}
|
|
4314
4482
|
machines4.ending = ending;
|
|
@@ -4327,6 +4495,32 @@ var machines2;
|
|
|
4327
4495
|
return first.at > since - 1e3;
|
|
4328
4496
|
}
|
|
4329
4497
|
machines4.lacks = lacks;
|
|
4498
|
+
function resent(options) {
|
|
4499
|
+
const { remote, retained } = options;
|
|
4500
|
+
return [...retained].filter(([, entered]) => remote === void 0 || remote === entered).map(([token2]) => token2);
|
|
4501
|
+
}
|
|
4502
|
+
machines4.resent = resent;
|
|
4503
|
+
function retains(options) {
|
|
4504
|
+
const { live, logouts, persisted, retained, unsaved } = options;
|
|
4505
|
+
const result = /* @__PURE__ */ new Map();
|
|
4506
|
+
for (const token2 of live) {
|
|
4507
|
+
if (persisted?.includes(token2)) continue;
|
|
4508
|
+
const entered = retained.get(token2);
|
|
4509
|
+
if (entered !== void 0) result.set(token2, entered);
|
|
4510
|
+
else if (unsaved.includes(token2)) result.set(token2, logouts);
|
|
4511
|
+
}
|
|
4512
|
+
return result;
|
|
4513
|
+
}
|
|
4514
|
+
machines4.retains = retains;
|
|
4515
|
+
function revocable(options) {
|
|
4516
|
+
const { entries, held, live, remote, revoked, since, token: token2 } = options;
|
|
4517
|
+
if (!token2 || token2 === revoked) return false;
|
|
4518
|
+
if (remote) return false;
|
|
4519
|
+
if (!held) return true;
|
|
4520
|
+
if (!entries || machines4.lacks({ entries, since })) return false;
|
|
4521
|
+
return live === token2;
|
|
4522
|
+
}
|
|
4523
|
+
machines4.revocable = revocable;
|
|
4330
4524
|
function loggedOut(options) {
|
|
4331
4525
|
const { current, started } = options;
|
|
4332
4526
|
if (current.logouts.started !== started.logouts.started) return true;
|
|
@@ -4418,11 +4612,13 @@ var machines2;
|
|
|
4418
4612
|
}
|
|
4419
4613
|
machines4.declined = declined;
|
|
4420
4614
|
function rotated(options) {
|
|
4421
|
-
const { current, now, started } = options;
|
|
4422
|
-
if (!started
|
|
4423
|
-
if (current.user.id !== started.user.id) return false;
|
|
4615
|
+
const { current, lifetime: lifetime3, now, started, startedAt } = options;
|
|
4616
|
+
if (started && !started.refreshToken) return false;
|
|
4617
|
+
if (started && current.user.id !== started.user.id) return false;
|
|
4424
4618
|
if (current.expiresAt <= now) return false;
|
|
4425
|
-
|
|
4619
|
+
if (lifetime3 === void 0) return false;
|
|
4620
|
+
if (current.expiresAt - lifetime3 <= startedAt) return false;
|
|
4621
|
+
return current.refreshToken !== started?.refreshToken;
|
|
4426
4622
|
}
|
|
4427
4623
|
machines4.rotated = rotated;
|
|
4428
4624
|
function switches(options) {
|
|
@@ -4506,13 +4702,11 @@ async function run(context, parameters) {
|
|
|
4506
4702
|
}
|
|
4507
4703
|
function refresh3(context, options = {}) {
|
|
4508
4704
|
const { margin } = options;
|
|
4509
|
-
const started =
|
|
4705
|
+
const started = context.session.get();
|
|
4706
|
+
const startedAt = Date.now();
|
|
4510
4707
|
return context.session.exclusive(async () => {
|
|
4511
4708
|
await context.session.load({ locked: true });
|
|
4512
|
-
const
|
|
4513
|
-
context.session.reload(),
|
|
4514
|
-
started
|
|
4515
|
-
]);
|
|
4709
|
+
const current = await context.session.reload();
|
|
4516
4710
|
const refreshToken = current?.refreshToken;
|
|
4517
4711
|
if (!current || !refreshToken) return void 0;
|
|
4518
4712
|
checkBound(context.config, { accessToken: current.accessToken });
|
|
@@ -4520,10 +4714,12 @@ function refresh3(context, options = {}) {
|
|
|
4520
4714
|
await context.session.change({ update: true }).commit(current);
|
|
4521
4715
|
return context.session.get();
|
|
4522
4716
|
}
|
|
4523
|
-
if (machines2.rotated({
|
|
4717
|
+
if (margin === void 0 && machines2.rotated({
|
|
4524
4718
|
current,
|
|
4719
|
+
lifetime: lifetime(current.accessToken),
|
|
4525
4720
|
now: Date.now(),
|
|
4526
|
-
started
|
|
4721
|
+
started,
|
|
4722
|
+
startedAt
|
|
4527
4723
|
})) {
|
|
4528
4724
|
await context.session.change({ update: true }).commit(current);
|
|
4529
4725
|
return context.session.get();
|
|
@@ -4712,7 +4908,7 @@ var signInIds = /* @__PURE__ */ new Set([
|
|
|
4712
4908
|
function plugin() {
|
|
4713
4909
|
let loading;
|
|
4714
4910
|
function load() {
|
|
4715
|
-
loading ??= import("./dialog-
|
|
4911
|
+
loading ??= import("./dialog-TGNSW7U4.js").then((module) => module.dialog()).catch((error3) => {
|
|
4716
4912
|
loading = void 0;
|
|
4717
4913
|
throw error3;
|
|
4718
4914
|
});
|
|
@@ -5026,7 +5222,15 @@ function create4(options = {}) {
|
|
|
5026
5222
|
return void 0;
|
|
5027
5223
|
return revoke2(ended.refreshToken, onRevoked);
|
|
5028
5224
|
})(),
|
|
5029
|
-
...pending.map((entry) =>
|
|
5225
|
+
...pending.map(async (entry) => {
|
|
5226
|
+
const result = await revoke2(entry.refreshToken, entry.onRevoked);
|
|
5227
|
+
if (result) {
|
|
5228
|
+
if (typeof result.error === "object" && result.error)
|
|
5229
|
+
unanswered2.add(result.error);
|
|
5230
|
+
entry.onUnanswered?.(result.error);
|
|
5231
|
+
}
|
|
5232
|
+
return void 0;
|
|
5233
|
+
})
|
|
5030
5234
|
]);
|
|
5031
5235
|
const loggedOut = logout && !thirdParty(config.clientId);
|
|
5032
5236
|
if (loggedOut) {
|
|
@@ -5079,6 +5283,7 @@ function create4(options = {}) {
|
|
|
5079
5283
|
plugin2.setup?.(context);
|
|
5080
5284
|
}
|
|
5081
5285
|
let refreshing;
|
|
5286
|
+
let rotating;
|
|
5082
5287
|
async function ownAccessToken() {
|
|
5083
5288
|
if (typeof document !== "undefined" || "WorkerGlobalScope" in globalThis)
|
|
5084
5289
|
return void 0;
|
|
@@ -5116,7 +5321,7 @@ function create4(options = {}) {
|
|
|
5116
5321
|
function connections2() {
|
|
5117
5322
|
if (!connectionsOptions)
|
|
5118
5323
|
return Promise.reject(new ConnectionsRequiredError());
|
|
5119
|
-
attached ??= import("./Connections-
|
|
5324
|
+
attached ??= import("./Connections-GTESLWTN.js").then(
|
|
5120
5325
|
(module) => module.attach(config, connectionsOptions)
|
|
5121
5326
|
);
|
|
5122
5327
|
return attached;
|
|
@@ -5202,7 +5407,9 @@ function create4(options = {}) {
|
|
|
5202
5407
|
},
|
|
5203
5408
|
signedOut: session2.signedOut
|
|
5204
5409
|
}),
|
|
5205
|
-
refresh: () => refresh3(context)
|
|
5410
|
+
refresh: () => rotating ??= refresh3(context).finally(() => {
|
|
5411
|
+
rotating = void 0;
|
|
5412
|
+
}),
|
|
5206
5413
|
status: session2.status,
|
|
5207
5414
|
subscribe: session2.subscribe
|
|
5208
5415
|
},
|
package/dist/commands/login.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
env,
|
|
3
3
|
login
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-
|
|
6
|
-
import "../chunk-
|
|
4
|
+
} from "../chunk-DN57D5UC.js";
|
|
5
|
+
import "../chunk-K4WPSEXZ.js";
|
|
6
|
+
import "../chunk-AOIGHDXR.js";
|
|
7
7
|
import "../chunk-YW5DUQT3.js";
|
|
8
8
|
import "../chunk-MLKGABMK.js";
|
|
9
9
|
|
package/dist/commands/logout.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
env,
|
|
3
3
|
remove
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-
|
|
6
|
-
import "../chunk-
|
|
4
|
+
} from "../chunk-DN57D5UC.js";
|
|
5
|
+
import "../chunk-K4WPSEXZ.js";
|
|
6
|
+
import "../chunk-AOIGHDXR.js";
|
|
7
7
|
import "../chunk-YW5DUQT3.js";
|
|
8
8
|
import "../chunk-MLKGABMK.js";
|
|
9
9
|
|
package/dist/commands/whoami.js
CHANGED
|
@@ -2,9 +2,9 @@ import {
|
|
|
2
2
|
env,
|
|
3
3
|
signedOut,
|
|
4
4
|
whoami
|
|
5
|
-
} from "../chunk-
|
|
6
|
-
import "../chunk-
|
|
7
|
-
import "../chunk-
|
|
5
|
+
} from "../chunk-DN57D5UC.js";
|
|
6
|
+
import "../chunk-K4WPSEXZ.js";
|
|
7
|
+
import "../chunk-AOIGHDXR.js";
|
|
8
8
|
import "../chunk-YW5DUQT3.js";
|
|
9
9
|
import "../chunk-MLKGABMK.js";
|
|
10
10
|
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"node": ">=24.21"
|
|
10
10
|
},
|
|
11
11
|
"name": "@tempoxyz/id",
|
|
12
|
-
"version": "0.0.0-pr-
|
|
12
|
+
"version": "0.0.0-pr-723.sha-e2f626f",
|
|
13
13
|
"description": "The tempo-id CLI: sign in to Tempo ID, and call its API and the Admin API.",
|
|
14
14
|
"type": "module",
|
|
15
15
|
"bin": {
|