@palbase/web 4.0.0 → 4.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_mls-wasm.cjs +32 -0
- package/dist/_mls-wasm.cjs.map +1 -0
- package/dist/_mls-wasm.js +11 -0
- package/dist/_mls-wasm.js.map +1 -0
- package/dist/{analytics-facade-DwOtlXPP.d.cts → analytics-facade-CaluA4bW.d.cts} +26 -1
- package/dist/{analytics-facade-Nk6J9Ncm.d.ts → analytics-facade-Cp3d4QI-.d.ts} +26 -1
- package/dist/{chunk-S7NAY3MW.js → chunk-CFDU23TB.js} +3 -10
- package/dist/chunk-CFDU23TB.js.map +1 -0
- package/dist/chunk-PZ5AY32C.js +10 -0
- package/dist/chunk-PZ5AY32C.js.map +1 -0
- package/dist/{chunk-NP4NIY7A.js → chunk-TW6YN354.js} +84 -27
- package/dist/chunk-TW6YN354.js.map +1 -0
- package/dist/gen/cli.cjs +5 -5
- package/dist/gen/cli.cjs.map +1 -1
- package/dist/gen/cli.js +6 -5
- package/dist/gen/cli.js.map +1 -1
- package/dist/index.cjs +91 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -2
- package/dist/internal.cjs +90 -26
- package/dist/internal.cjs.map +1 -1
- package/dist/internal.d.cts +3 -3
- package/dist/internal.d.ts +3 -3
- package/dist/internal.js +3 -2
- package/dist/next/client.cjs +90 -26
- package/dist/next/client.cjs.map +1 -1
- package/dist/next/client.js +3 -2
- package/dist/next/client.js.map +1 -1
- package/dist/next/index.cjs +81 -27
- package/dist/next/index.cjs.map +1 -1
- package/dist/next/index.d.cts +2 -2
- package/dist/next/index.d.ts +2 -2
- package/dist/next/index.js +3 -2
- package/dist/next/index.js.map +1 -1
- package/dist/{pb-FG_nV7NR.d.ts → pb-DUK5qy81.d.ts} +1 -1
- package/dist/{pb-C9v5dEO6.d.cts → pb-DvV6ftmf.d.cts} +1 -1
- package/dist/react/index.cjs +10 -2
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +1 -1
- package/dist/react/index.d.ts +1 -1
- package/dist/react/index.js +3 -2
- package/dist/react/index.js.map +1 -1
- package/package.json +10 -3
- package/dist/chunk-NP4NIY7A.js.map +0 -1
- package/dist/chunk-S7NAY3MW.js.map +0 -1
- package/dist/pkg/palbe_mls_bg.wasm +0 -0
package/dist/next/client.js
CHANGED
|
@@ -6,8 +6,9 @@ import {
|
|
|
6
6
|
import {
|
|
7
7
|
__configure,
|
|
8
8
|
getRuntime
|
|
9
|
-
} from "../chunk-
|
|
10
|
-
import "../chunk-
|
|
9
|
+
} from "../chunk-TW6YN354.js";
|
|
10
|
+
import "../chunk-CFDU23TB.js";
|
|
11
|
+
import "../chunk-PZ5AY32C.js";
|
|
11
12
|
|
|
12
13
|
// src/next/client.ts
|
|
13
14
|
var SESSION_MAX_AGE_S = 2592e3;
|
package/dist/next/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/next/client.ts"],"sourcesContent":["/**\n * '@palbase/web/next/client' — the browser half of the Next.js adapter. This entry\n * must NEVER import 'next' (it runs in plain client bundles); the cookie jar\n * is document.cookie itself, written with the shared codec so the server\n * side (pbServer / middleware / callback) reads the same bytes.\n */\nimport { __configure, getRuntime } from '../internal.js';\nimport type { PersistedSession, SessionStorageAdapter } from '../storage.js';\nimport {\n clearedSessionCookieNames,\n decodeSessionCookies,\n encodeSessionCookies,\n} from './cookie-codec.js';\n\n/** 30 days — the refresh-token TTL (P3 design contract). */\nconst SESSION_MAX_AGE_S = 2_592_000;\n\n// Secure is unconditional, INCLUDING http://localhost: browsers treat\n// localhost as a potentially-trustworthy origin, so document.cookie accepts\n// Secure cookies there — no dev-mode special case needed. KNOWN LIMITATION:\n// plain-http origins OTHER than localhost — e.g. LAN-IP device testing on\n// http://192.168.x.x — are NOT trustworthy, so the browser silently DROPS\n// these Secure cookie writes and the session won't persist; use https (or a\n// localhost tunnel/port-forward) for on-device testing. NOT HttpOnly by\n// design: the browser SDK must read/write the session (Supabase-paradigm\n// tradeoff, documented in the P3 plan).\nconst WRITE_ATTRS = 'Path=/; SameSite=Lax; Secure';\n\n/** Parse document.cookie (\"a=1; b=2\") into a name → raw-value map. */\nfunction cookieJar(): Map<string, string> {\n const jar = new Map<string, string>();\n for (const part of document.cookie.split(';')) {\n const eq = part.indexOf('=');\n if (eq === -1) continue;\n const name = part.slice(0, eq).trim();\n if (name) jar.set(name, part.slice(eq + 1).trim());\n }\n return jar;\n}\n\nfunction deleteCookie(name: string): void {\n // biome-ignore lint/suspicious/noDocumentCookie: SessionStorageAdapter is a SYNC contract; the async Cookie Store API can't back it (and isn't universal).\n document.cookie = `${name}=; ${WRITE_ATTRS}; Max-Age=0`;\n}\n\n/**\n * document.cookie-backed SessionStorageAdapter. `load` returns the EXTENDED\n * PersistedSession (access token + expiry ride along) so hydration adopts\n * the full session without a refresh round-trip.\n */\nexport function cookieSessionStorage(environmentRef: string): SessionStorageAdapter {\n return {\n load(): PersistedSession | null {\n if (typeof document === 'undefined') return null;\n const jar = cookieJar();\n const stored = decodeSessionCookies((name) => jar.get(name), environmentRef);\n if (!stored) return null;\n // A refresh-only save round-trips as a:'' / e:0 — normalize back to\n // the legacy shape so hydration takes the expired-trick path cleanly.\n return stored.accessToken && stored.expiresAt > 0\n ? {\n refreshToken: stored.refreshToken,\n accessToken: stored.accessToken,\n expiresAt: stored.expiresAt,\n }\n : { refreshToken: stored.refreshToken };\n },\n save(session: PersistedSession): void {\n if (typeof document === 'undefined') return;\n const jar = cookieJar();\n // Delete every currently-present session cookie first (stale chunks of\n // a previously-larger session, or a stale base when the new write\n // chunks), then set the new cookie(s).\n for (const name of clearedSessionCookieNames(environmentRef, (n) => jar.has(n))) {\n deleteCookie(name);\n }\n const { set, clear } = encodeSessionCookies(environmentRef, {\n accessToken: session.accessToken ?? '',\n refreshToken: session.refreshToken,\n expiresAt: session.expiresAt ?? 0,\n });\n for (const { name, value } of set) {\n // biome-ignore lint/suspicious/noDocumentCookie: SessionStorageAdapter is a SYNC contract; the async Cookie Store API can't back it (and isn't universal).\n document.cookie = `${name}=${value}; ${WRITE_ATTRS}; Max-Age=${SESSION_MAX_AGE_S}`;\n }\n // Overflow guard (codec contract): delete one-past-the-end so a stale\n // orphan chunk behind a gap can never join a future chunk run.\n for (const name of clear) deleteCookie(name);\n },\n clear(): void {\n if (typeof document === 'undefined') return;\n const jar = cookieJar();\n for (const name of clearedSessionCookieNames(environmentRef, (n) => jar.has(n))) {\n deleteCookie(name);\n }\n },\n };\n}\n\n/**\n * One-liner for a client component/provider: re-configure the already-loaded\n * gen config (palbe.gen.ts must be imported first — throws the guided\n * notConfigured error otherwise) with cookie-backed session storage so the\n * browser and the server share the session. Calling it again simply\n * re-configures (safe, e.g. under fast refresh). When Next evaluates the\n * client component module server-side there is no document — no-op.\n */\nexport function setupPalbeNext(): void {\n if (typeof document === 'undefined') return;\n const config = getRuntime().config;\n __configure({\n ...config,\n storage: cookieSessionStorage(config.environmentRef),\n });\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../src/next/client.ts"],"sourcesContent":["/**\n * '@palbase/web/next/client' — the browser half of the Next.js adapter. This entry\n * must NEVER import 'next' (it runs in plain client bundles); the cookie jar\n * is document.cookie itself, written with the shared codec so the server\n * side (pbServer / middleware / callback) reads the same bytes.\n */\nimport { __configure, getRuntime } from '../internal.js';\nimport type { PersistedSession, SessionStorageAdapter } from '../storage.js';\nimport {\n clearedSessionCookieNames,\n decodeSessionCookies,\n encodeSessionCookies,\n} from './cookie-codec.js';\n\n/** 30 days — the refresh-token TTL (P3 design contract). */\nconst SESSION_MAX_AGE_S = 2_592_000;\n\n// Secure is unconditional, INCLUDING http://localhost: browsers treat\n// localhost as a potentially-trustworthy origin, so document.cookie accepts\n// Secure cookies there — no dev-mode special case needed. KNOWN LIMITATION:\n// plain-http origins OTHER than localhost — e.g. LAN-IP device testing on\n// http://192.168.x.x — are NOT trustworthy, so the browser silently DROPS\n// these Secure cookie writes and the session won't persist; use https (or a\n// localhost tunnel/port-forward) for on-device testing. NOT HttpOnly by\n// design: the browser SDK must read/write the session (Supabase-paradigm\n// tradeoff, documented in the P3 plan).\nconst WRITE_ATTRS = 'Path=/; SameSite=Lax; Secure';\n\n/** Parse document.cookie (\"a=1; b=2\") into a name → raw-value map. */\nfunction cookieJar(): Map<string, string> {\n const jar = new Map<string, string>();\n for (const part of document.cookie.split(';')) {\n const eq = part.indexOf('=');\n if (eq === -1) continue;\n const name = part.slice(0, eq).trim();\n if (name) jar.set(name, part.slice(eq + 1).trim());\n }\n return jar;\n}\n\nfunction deleteCookie(name: string): void {\n // biome-ignore lint/suspicious/noDocumentCookie: SessionStorageAdapter is a SYNC contract; the async Cookie Store API can't back it (and isn't universal).\n document.cookie = `${name}=; ${WRITE_ATTRS}; Max-Age=0`;\n}\n\n/**\n * document.cookie-backed SessionStorageAdapter. `load` returns the EXTENDED\n * PersistedSession (access token + expiry ride along) so hydration adopts\n * the full session without a refresh round-trip.\n */\nexport function cookieSessionStorage(environmentRef: string): SessionStorageAdapter {\n return {\n load(): PersistedSession | null {\n if (typeof document === 'undefined') return null;\n const jar = cookieJar();\n const stored = decodeSessionCookies((name) => jar.get(name), environmentRef);\n if (!stored) return null;\n // A refresh-only save round-trips as a:'' / e:0 — normalize back to\n // the legacy shape so hydration takes the expired-trick path cleanly.\n return stored.accessToken && stored.expiresAt > 0\n ? {\n refreshToken: stored.refreshToken,\n accessToken: stored.accessToken,\n expiresAt: stored.expiresAt,\n }\n : { refreshToken: stored.refreshToken };\n },\n save(session: PersistedSession): void {\n if (typeof document === 'undefined') return;\n const jar = cookieJar();\n // Delete every currently-present session cookie first (stale chunks of\n // a previously-larger session, or a stale base when the new write\n // chunks), then set the new cookie(s).\n for (const name of clearedSessionCookieNames(environmentRef, (n) => jar.has(n))) {\n deleteCookie(name);\n }\n const { set, clear } = encodeSessionCookies(environmentRef, {\n accessToken: session.accessToken ?? '',\n refreshToken: session.refreshToken,\n expiresAt: session.expiresAt ?? 0,\n });\n for (const { name, value } of set) {\n // biome-ignore lint/suspicious/noDocumentCookie: SessionStorageAdapter is a SYNC contract; the async Cookie Store API can't back it (and isn't universal).\n document.cookie = `${name}=${value}; ${WRITE_ATTRS}; Max-Age=${SESSION_MAX_AGE_S}`;\n }\n // Overflow guard (codec contract): delete one-past-the-end so a stale\n // orphan chunk behind a gap can never join a future chunk run.\n for (const name of clear) deleteCookie(name);\n },\n clear(): void {\n if (typeof document === 'undefined') return;\n const jar = cookieJar();\n for (const name of clearedSessionCookieNames(environmentRef, (n) => jar.has(n))) {\n deleteCookie(name);\n }\n },\n };\n}\n\n/**\n * One-liner for a client component/provider: re-configure the already-loaded\n * gen config (palbe.gen.ts must be imported first — throws the guided\n * notConfigured error otherwise) with cookie-backed session storage so the\n * browser and the server share the session. Calling it again simply\n * re-configures (safe, e.g. under fast refresh). When Next evaluates the\n * client component module server-side there is no document — no-op.\n */\nexport function setupPalbeNext(): void {\n if (typeof document === 'undefined') return;\n const config = getRuntime().config;\n __configure({\n ...config,\n storage: cookieSessionStorage(config.environmentRef),\n });\n}\n"],"mappings":";;;;;;;;;;;;;AAeA,IAAM,oBAAoB;AAW1B,IAAM,cAAc;AAGpB,SAAS,YAAiC;AACxC,QAAM,MAAM,oBAAI,IAAoB;AACpC,aAAW,QAAQ,SAAS,OAAO,MAAM,GAAG,GAAG;AAC7C,UAAM,KAAK,KAAK,QAAQ,GAAG;AAC3B,QAAI,OAAO,GAAI;AACf,UAAM,OAAO,KAAK,MAAM,GAAG,EAAE,EAAE,KAAK;AACpC,QAAI,KAAM,KAAI,IAAI,MAAM,KAAK,MAAM,KAAK,CAAC,EAAE,KAAK,CAAC;AAAA,EACnD;AACA,SAAO;AACT;AAEA,SAAS,aAAa,MAAoB;AAExC,WAAS,SAAS,GAAG,IAAI,MAAM,WAAW;AAC5C;AAOO,SAAS,qBAAqB,gBAA+C;AAClF,SAAO;AAAA,IACL,OAAgC;AAC9B,UAAI,OAAO,aAAa,YAAa,QAAO;AAC5C,YAAM,MAAM,UAAU;AACtB,YAAM,SAAS,qBAAqB,CAAC,SAAS,IAAI,IAAI,IAAI,GAAG,cAAc;AAC3E,UAAI,CAAC,OAAQ,QAAO;AAGpB,aAAO,OAAO,eAAe,OAAO,YAAY,IAC5C;AAAA,QACE,cAAc,OAAO;AAAA,QACrB,aAAa,OAAO;AAAA,QACpB,WAAW,OAAO;AAAA,MACpB,IACA,EAAE,cAAc,OAAO,aAAa;AAAA,IAC1C;AAAA,IACA,KAAK,SAAiC;AACpC,UAAI,OAAO,aAAa,YAAa;AACrC,YAAM,MAAM,UAAU;AAItB,iBAAW,QAAQ,0BAA0B,gBAAgB,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,GAAG;AAC/E,qBAAa,IAAI;AAAA,MACnB;AACA,YAAM,EAAE,KAAK,MAAM,IAAI,qBAAqB,gBAAgB;AAAA,QAC1D,aAAa,QAAQ,eAAe;AAAA,QACpC,cAAc,QAAQ;AAAA,QACtB,WAAW,QAAQ,aAAa;AAAA,MAClC,CAAC;AACD,iBAAW,EAAE,MAAM,MAAM,KAAK,KAAK;AAEjC,iBAAS,SAAS,GAAG,IAAI,IAAI,KAAK,KAAK,WAAW,aAAa,iBAAiB;AAAA,MAClF;AAGA,iBAAW,QAAQ,MAAO,cAAa,IAAI;AAAA,IAC7C;AAAA,IACA,QAAc;AACZ,UAAI,OAAO,aAAa,YAAa;AACrC,YAAM,MAAM,UAAU;AACtB,iBAAW,QAAQ,0BAA0B,gBAAgB,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,GAAG;AAC/E,qBAAa,IAAI;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AACF;AAUO,SAAS,iBAAuB;AACrC,MAAI,OAAO,aAAa,YAAa;AACrC,QAAM,SAAS,WAAW,EAAE;AAC5B,cAAY;AAAA,IACV,GAAG;AAAA,IACH,SAAS,qBAAqB,OAAO,cAAc;AAAA,EACrD,CAAC;AACH;","names":[]}
|
package/dist/next/index.cjs
CHANGED
|
@@ -57,8 +57,8 @@ function asWireAuthResult(raw) {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
// src/api-key.ts
|
|
60
|
-
var API_KEY_RE = /^pb_([a-z0-9]
|
|
61
|
-
var PUBLISHABLE_API_KEY_RE = /^pb_([a-z0-9]
|
|
60
|
+
var API_KEY_RE = /^pb_([a-z0-9]{4,24})_[cs][A-Za-z0-9]{20}$/;
|
|
61
|
+
var PUBLISHABLE_API_KEY_RE = /^pb_([a-z0-9]{4,24})_c[A-Za-z0-9]{20}$/;
|
|
62
62
|
function environmentRefFromApiKey(apiKey) {
|
|
63
63
|
const m = API_KEY_RE.exec(apiKey);
|
|
64
64
|
return m ? m[1] ?? "" : "";
|
|
@@ -168,7 +168,7 @@ var PalbaseError = class extends Error {
|
|
|
168
168
|
}
|
|
169
169
|
};
|
|
170
170
|
var PALBASE_DEFAULT_HOST = "api.palbase.studio";
|
|
171
|
-
var API_KEY_RE2 = /^pb_([a-z0-9]
|
|
171
|
+
var API_KEY_RE2 = /^pb_([a-z0-9]{4,24})_c[A-Za-z0-9]{20}$/;
|
|
172
172
|
function parseEnvironmentRef(apiKey) {
|
|
173
173
|
return API_KEY_RE2.exec(apiKey)?.[1] ?? null;
|
|
174
174
|
}
|
|
@@ -545,6 +545,11 @@ var PERF_EXCLUDED_PREFIX = "/v1/analytics/";
|
|
|
545
545
|
function isSelfTraced(path) {
|
|
546
546
|
return path.startsWith(PERF_EXCLUDED_PREFIX);
|
|
547
547
|
}
|
|
548
|
+
function isSessionKilled(status, code) {
|
|
549
|
+
if (status === 401) return code === "session_revoked";
|
|
550
|
+
if (status === 403) return code === "subject_fenced" || code === "subject_erased";
|
|
551
|
+
return false;
|
|
552
|
+
}
|
|
548
553
|
function nowMs() {
|
|
549
554
|
return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
550
555
|
}
|
|
@@ -580,7 +585,7 @@ async function palbeRequest(rt, method, path, spec = {}) {
|
|
|
580
585
|
let res;
|
|
581
586
|
try {
|
|
582
587
|
res = await attempt();
|
|
583
|
-
if (res.error?.status === 401 && rt.tokenManager.getRefreshToken() && rt.tokenManager.refreshFunction) {
|
|
588
|
+
if (res.error?.status === 401 && res.error.code !== "session_revoked" && rt.tokenManager.getRefreshToken() && rt.tokenManager.refreshFunction) {
|
|
584
589
|
try {
|
|
585
590
|
await rt.tokenManager.refreshSession();
|
|
586
591
|
} catch (refreshErr) {
|
|
@@ -600,6 +605,9 @@ async function palbeRequest(rt, method, path, spec = {}) {
|
|
|
600
605
|
if (!isAbort(e)) record(asPalbaseError(e)?.status ?? 0);
|
|
601
606
|
throw e;
|
|
602
607
|
}
|
|
608
|
+
if (res.error && isSessionKilled(res.error.status, res.error.code)) {
|
|
609
|
+
rt.auth.reactiveTeardown();
|
|
610
|
+
}
|
|
603
611
|
record(res.error?.status ?? 200);
|
|
604
612
|
return unwrap(res);
|
|
605
613
|
}
|
|
@@ -1478,7 +1486,8 @@ var PalbeAuth = class {
|
|
|
1478
1486
|
if (!this.signedInState) return;
|
|
1479
1487
|
this.signedInState = false;
|
|
1480
1488
|
this.cachedUser = null;
|
|
1481
|
-
const reason = this.signingOut ? "userInitiated" : "sessionExpired";
|
|
1489
|
+
const reason = this.nextSignOutReason ?? (this.signingOut ? "userInitiated" : "sessionExpired");
|
|
1490
|
+
this.nextSignOutReason = null;
|
|
1482
1491
|
this.emitState({ status: "signedOut" });
|
|
1483
1492
|
this.emitEvent({ type: "signedOut", reason });
|
|
1484
1493
|
} else if (event === "TOKEN_REFRESHED") {
|
|
@@ -1491,6 +1500,10 @@ var PalbeAuth = class {
|
|
|
1491
1500
|
rt;
|
|
1492
1501
|
cachedUser = null;
|
|
1493
1502
|
signingOut = false;
|
|
1503
|
+
// Explicit signedOut reason pinned for the NEXT session clear (deleteAccount /
|
|
1504
|
+
// reactiveTeardown set it before clearSession; the SIGNED_OUT handler consumes
|
|
1505
|
+
// it exactly once, then resets to null → normal signOut/expiry split resumes).
|
|
1506
|
+
nextSignOutReason = null;
|
|
1494
1507
|
signingIn = false;
|
|
1495
1508
|
// suppresses AuthClient's TOKEN_REFRESHED during re-signIn
|
|
1496
1509
|
signedInState = false;
|
|
@@ -1538,6 +1551,45 @@ var PalbeAuth = class {
|
|
|
1538
1551
|
this.cachedUser = null;
|
|
1539
1552
|
}
|
|
1540
1553
|
}
|
|
1554
|
+
/**
|
|
1555
|
+
* Self-service account erasure ("right to be forgotten"). Calls palauth
|
|
1556
|
+
* `DELETE /auth/user` (session-authed + fresh re-auth): password users pass
|
|
1557
|
+
* `{ password }`; passwordless/OAuth users rely on a freshly stepped-up
|
|
1558
|
+
* session. On 202 the erasure workflow is durably queued AND every session is
|
|
1559
|
+
* already revoked server-side — so we tear down local state (mirroring
|
|
1560
|
+
* `signOut()`'s clear, minus the pointless `/logout`) and emit
|
|
1561
|
+
* `signedOut{reason:'accountDeleted'}`.
|
|
1562
|
+
*
|
|
1563
|
+
* On 401 `reauth_required` / 503 `not_configured` (or `erasure_unavailable`)
|
|
1564
|
+
* the request throws BEFORE the teardown line, so the local session is left
|
|
1565
|
+
* fully intact — the deletion did not happen and the user is still signed in.
|
|
1566
|
+
*/
|
|
1567
|
+
async deleteAccount(params = {}) {
|
|
1568
|
+
const res = await palbeRequest(this.rt, "DELETE", "/auth/user", {
|
|
1569
|
+
body: params.password ? { password: params.password } : {}
|
|
1570
|
+
});
|
|
1571
|
+
this.nextSignOutReason = "accountDeleted";
|
|
1572
|
+
this.rt.tokenManager.clearSession();
|
|
1573
|
+
this.rt.storage.clear();
|
|
1574
|
+
this.cachedUser = null;
|
|
1575
|
+
return { erasureId: res.erasure_id };
|
|
1576
|
+
}
|
|
1577
|
+
/**
|
|
1578
|
+
* @internal — invoked by the transport choke point (`request.ts`), not app code.
|
|
1579
|
+
* Reactive teardown when the server reports the session is gone: a 403
|
|
1580
|
+
* `subject_fenced`/`subject_erased` (subject being erased) or a 401
|
|
1581
|
+
* `session_revoked`. Clears local state and emits
|
|
1582
|
+
* `signedOut{reason:'sessionInvalid'}` exactly once (deduped by
|
|
1583
|
+
* `signedInState`). An ordinary 403 authz denial does NOT reach here —
|
|
1584
|
+
* `request.ts` matches only the exact session-kill codes.
|
|
1585
|
+
*/
|
|
1586
|
+
reactiveTeardown() {
|
|
1587
|
+
if (!this.signedInState) return;
|
|
1588
|
+
this.nextSignOutReason = "sessionInvalid";
|
|
1589
|
+
this.rt.tokenManager.clearSession();
|
|
1590
|
+
this.rt.storage.clear();
|
|
1591
|
+
this.cachedUser = null;
|
|
1592
|
+
}
|
|
1541
1593
|
async getUser() {
|
|
1542
1594
|
const raw = await palbeRequest(this.rt, "GET", "/auth/user");
|
|
1543
1595
|
return mapWireUser(raw);
|
|
@@ -6477,31 +6529,29 @@ function date_now() {
|
|
|
6477
6529
|
}
|
|
6478
6530
|
|
|
6479
6531
|
// src/messaging/wasm/loader.ts
|
|
6480
|
-
var import_meta = {};
|
|
6481
6532
|
var GLUE_MODULE = "./palbe_mls_bg.js";
|
|
6482
6533
|
var SNIPPET_MODULE = "./snippets/mls-rs-core-f99cdecbb456b09c/inline0.js";
|
|
6483
6534
|
var inflight = null;
|
|
6484
6535
|
var ready = null;
|
|
6485
|
-
|
|
6486
|
-
|
|
6487
|
-
|
|
6488
|
-
const fsSpecifier = ["node", "fs/promises"].join(":");
|
|
6489
|
-
const { readFile } = await import(
|
|
6490
|
-
/* webpackIgnore: true */
|
|
6491
|
-
fsSpecifier
|
|
6492
|
-
);
|
|
6493
|
-
const bytes = await readFile(wasmUrl);
|
|
6494
|
-
return WebAssembly.compile(bytes);
|
|
6536
|
+
function decodeBase64(encoded) {
|
|
6537
|
+
if (typeof encoded !== "string" || encoded.length === 0 || typeof globalThis.atob !== "function") {
|
|
6538
|
+
throw new Error("palbe-mls WASM asset is invalid");
|
|
6495
6539
|
}
|
|
6496
|
-
|
|
6497
|
-
|
|
6498
|
-
|
|
6499
|
-
|
|
6500
|
-
|
|
6501
|
-
|
|
6540
|
+
let binary;
|
|
6541
|
+
try {
|
|
6542
|
+
binary = globalThis.atob(encoded);
|
|
6543
|
+
} catch {
|
|
6544
|
+
throw new Error("palbe-mls WASM asset is invalid");
|
|
6545
|
+
}
|
|
6546
|
+
const bytes = new Uint8Array(binary.length);
|
|
6547
|
+
for (let index = 0; index < binary.length; index += 1) {
|
|
6548
|
+
bytes[index] = binary.charCodeAt(index);
|
|
6502
6549
|
}
|
|
6503
|
-
|
|
6504
|
-
|
|
6550
|
+
return bytes.buffer;
|
|
6551
|
+
}
|
|
6552
|
+
async function loadWasmModule() {
|
|
6553
|
+
const asset = await import("#palbase-mls-wasm");
|
|
6554
|
+
return WebAssembly.compile(decodeBase64(asset.default));
|
|
6505
6555
|
}
|
|
6506
6556
|
function buildImports() {
|
|
6507
6557
|
return {
|
|
@@ -6512,7 +6562,7 @@ function buildImports() {
|
|
|
6512
6562
|
function initMls() {
|
|
6513
6563
|
if (ready) return Promise.resolve(ready);
|
|
6514
6564
|
if (inflight) return inflight;
|
|
6515
|
-
|
|
6565
|
+
const attempt = (async () => {
|
|
6516
6566
|
const module2 = await loadWasmModule();
|
|
6517
6567
|
const instance = await WebAssembly.instantiate(module2, buildImports());
|
|
6518
6568
|
const setWasm = __wbg_set_wasm;
|
|
@@ -6531,7 +6581,11 @@ function initMls() {
|
|
|
6531
6581
|
ready = g;
|
|
6532
6582
|
return g;
|
|
6533
6583
|
})();
|
|
6534
|
-
|
|
6584
|
+
inflight = attempt;
|
|
6585
|
+
void attempt.catch(() => {
|
|
6586
|
+
if (inflight === attempt) inflight = null;
|
|
6587
|
+
});
|
|
6588
|
+
return attempt;
|
|
6535
6589
|
}
|
|
6536
6590
|
function requireMls() {
|
|
6537
6591
|
if (!ready) {
|
|
@@ -8984,7 +9038,7 @@ function defaultSessionStorage(key) {
|
|
|
8984
9038
|
}
|
|
8985
9039
|
|
|
8986
9040
|
// src/version.ts
|
|
8987
|
-
var VERSION = "4.0.
|
|
9041
|
+
var VERSION = "4.0.2";
|
|
8988
9042
|
|
|
8989
9043
|
// src/runtime.ts
|
|
8990
9044
|
function buildRuntime(config) {
|