@palbase/web 7.2.2 → 7.3.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/dist/{analytics-facade-DLfnVVwL.d.ts → analytics-facade-BER0EyYT.d.ts} +8 -3
- package/dist/{analytics-facade-jyXv7Cu4.d.cts → analytics-facade-CQXCQSoF.d.cts} +8 -3
- package/dist/{chunk-IREKQSHT.js → chunk-YBURINUN.js} +60 -14
- package/dist/chunk-YBURINUN.js.map +1 -0
- package/dist/gen/cli.cjs +6 -12
- package/dist/gen/cli.cjs.map +1 -1
- package/dist/gen/cli.js +6 -12
- package/dist/gen/cli.js.map +1 -1
- package/dist/index.cjs +51 -4
- 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 +1 -1
- package/dist/internal.cjs +59 -13
- 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 +1 -1
- package/dist/next/client.cjs +67 -21
- package/dist/next/client.cjs.map +1 -1
- package/dist/next/client.js +5 -3
- package/dist/next/client.js.map +1 -1
- package/dist/next/index.cjs +73 -27
- package/dist/next/index.cjs.map +1 -1
- package/dist/next/index.d.cts +2 -22
- package/dist/next/index.d.ts +2 -22
- package/dist/next/index.js +5 -4
- package/dist/next/index.js.map +1 -1
- package/dist/{pb-DdzpEkPY.d.ts → pb-BRlmBIAm.d.ts} +1 -1
- package/dist/{pb-CfYQGEn0.d.cts → pb-WAQvwCfM.d.cts} +1 -1
- package/dist/react/index.cjs +50 -3
- 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 +1 -1
- package/package.json +13 -13
- package/LICENSE +0 -21
- package/dist/chunk-IREKQSHT.js.map +0 -1
package/dist/next/client.js
CHANGED
|
@@ -6,9 +6,11 @@ import {
|
|
|
6
6
|
import {
|
|
7
7
|
__configure,
|
|
8
8
|
getRuntime
|
|
9
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-YBURINUN.js";
|
|
10
10
|
import "../chunk-ACCJV6FV.js";
|
|
11
|
-
import
|
|
11
|
+
import {
|
|
12
|
+
environmentRefFromPublishableApiKey
|
|
13
|
+
} from "../chunk-CFDU23TB.js";
|
|
12
14
|
import "../chunk-PZ5AY32C.js";
|
|
13
15
|
|
|
14
16
|
// src/next/client.ts
|
|
@@ -70,7 +72,7 @@ function setupPalbeNext() {
|
|
|
70
72
|
const config = getRuntime().config;
|
|
71
73
|
__configure({
|
|
72
74
|
...config,
|
|
73
|
-
storage: cookieSessionStorage(config.
|
|
75
|
+
storage: cookieSessionStorage(environmentRefFromPublishableApiKey(config.apiKey))
|
|
74
76
|
});
|
|
75
77
|
}
|
|
76
78
|
export {
|
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.
|
|
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 { environmentRefFromPublishableApiKey } from '../api-key.js';\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(environmentRefFromPublishableApiKey(config.apiKey)),\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAgBA,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,oCAAoC,OAAO,MAAM,CAAC;AAAA,EAClF,CAAC;AACH;","names":[]}
|
package/dist/next/index.cjs
CHANGED
|
@@ -42,6 +42,18 @@ __export(next_exports, {
|
|
|
42
42
|
});
|
|
43
43
|
module.exports = __toCommonJS(next_exports);
|
|
44
44
|
|
|
45
|
+
// src/api-key.ts
|
|
46
|
+
var API_KEY_RE = /^pb_([a-z0-9]{4,24})_[cs][A-Za-z0-9]{20}$/;
|
|
47
|
+
var PUBLISHABLE_API_KEY_RE = /^pb_([a-z0-9]{4,24})_c[A-Za-z0-9]{20}$/;
|
|
48
|
+
function environmentRefFromApiKey(apiKey) {
|
|
49
|
+
const m = API_KEY_RE.exec(apiKey);
|
|
50
|
+
return m ? m[1] ?? "" : "";
|
|
51
|
+
}
|
|
52
|
+
function environmentRefFromPublishableApiKey(apiKey) {
|
|
53
|
+
const match = PUBLISHABLE_API_KEY_RE.exec(apiKey);
|
|
54
|
+
return match ? match[1] ?? "" : "";
|
|
55
|
+
}
|
|
56
|
+
|
|
45
57
|
// src/auth-wire.ts
|
|
46
58
|
function asWireAuthResult(raw) {
|
|
47
59
|
if (typeof raw !== "object" || raw === null) return null;
|
|
@@ -55,18 +67,6 @@ function asWireAuthResult(raw) {
|
|
|
55
67
|
return raw;
|
|
56
68
|
}
|
|
57
69
|
|
|
58
|
-
// src/api-key.ts
|
|
59
|
-
var API_KEY_RE = /^pb_([a-z0-9]{4,24})_[cs][A-Za-z0-9]{20}$/;
|
|
60
|
-
var PUBLISHABLE_API_KEY_RE = /^pb_([a-z0-9]{4,24})_c[A-Za-z0-9]{20}$/;
|
|
61
|
-
function environmentRefFromApiKey(apiKey) {
|
|
62
|
-
const m = API_KEY_RE.exec(apiKey);
|
|
63
|
-
return m ? m[1] ?? "" : "";
|
|
64
|
-
}
|
|
65
|
-
function environmentRefFromPublishableApiKey(apiKey) {
|
|
66
|
-
const match = PUBLISHABLE_API_KEY_RE.exec(apiKey);
|
|
67
|
-
return match ? match[1] ?? "" : "";
|
|
68
|
-
}
|
|
69
|
-
|
|
70
70
|
// src/next/cookie-codec.ts
|
|
71
71
|
var MAX_COOKIE_VALUE = 3500;
|
|
72
72
|
var SESSION_COOKIE_ATTRS = {
|
|
@@ -568,6 +568,47 @@ function redactUrl(rawUrl) {
|
|
|
568
568
|
return path.split("/").map((seg2) => isSensitiveSegment(seg2) ? ":id" : seg2).join("/");
|
|
569
569
|
}
|
|
570
570
|
|
|
571
|
+
// src/pow.ts
|
|
572
|
+
var POW_CHALLENGE_ID_HEADER = "X-PoW-Challenge-ID";
|
|
573
|
+
var POW_NONCE_HEADER = "X-PoW-Nonce";
|
|
574
|
+
function asPowChallenge(details) {
|
|
575
|
+
if (typeof details !== "object" || details === null) return null;
|
|
576
|
+
const env = details;
|
|
577
|
+
if (env.error !== "pow_required") return null;
|
|
578
|
+
const c = env.challenge;
|
|
579
|
+
if (typeof c !== "object" || c === null) return null;
|
|
580
|
+
const { id, prefix, difficulty } = c;
|
|
581
|
+
if (typeof id !== "string" || typeof prefix !== "string") return null;
|
|
582
|
+
if (typeof difficulty !== "number" || !Number.isInteger(difficulty) || difficulty < 0) return null;
|
|
583
|
+
return { id, prefix, difficulty };
|
|
584
|
+
}
|
|
585
|
+
var encoder = new TextEncoder();
|
|
586
|
+
function leadingZeroBits(hash) {
|
|
587
|
+
let bits = 0;
|
|
588
|
+
for (const byte of hash) {
|
|
589
|
+
if (byte === 0) {
|
|
590
|
+
bits += 8;
|
|
591
|
+
continue;
|
|
592
|
+
}
|
|
593
|
+
return bits + Math.clz32(byte) - 24;
|
|
594
|
+
}
|
|
595
|
+
return bits;
|
|
596
|
+
}
|
|
597
|
+
async function solvePowChallenge(challenge, maxIterations = 1 << 24) {
|
|
598
|
+
for (let nonce = 0; nonce < maxIterations; nonce++) {
|
|
599
|
+
const digest = await crypto.subtle.digest("SHA-256", encoder.encode(challenge.prefix + nonce));
|
|
600
|
+
if (leadingZeroBits(new Uint8Array(digest)) >= challenge.difficulty) {
|
|
601
|
+
return {
|
|
602
|
+
[POW_CHALLENGE_ID_HEADER]: challenge.id,
|
|
603
|
+
[POW_NONCE_HEADER]: String(nonce)
|
|
604
|
+
};
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
throw new Error(
|
|
608
|
+
`proof-of-work: no nonce found for difficulty ${challenge.difficulty} within ${maxIterations} attempts`
|
|
609
|
+
);
|
|
610
|
+
}
|
|
611
|
+
|
|
571
612
|
// src/request.ts
|
|
572
613
|
var MUTATING = /* @__PURE__ */ new Set(["POST", "PUT", "PATCH", "DELETE"]);
|
|
573
614
|
var PERF_EXCLUDED_PREFIX = "/v1/analytics/";
|
|
@@ -591,11 +632,11 @@ async function palbeRequest(rt, method, path, spec = {}) {
|
|
|
591
632
|
if (MUTATING.has(method) && !callerHasKey) {
|
|
592
633
|
headers["Idempotency-Key"] = crypto.randomUUID();
|
|
593
634
|
}
|
|
594
|
-
const attempt = async () => {
|
|
635
|
+
const attempt = async (extra) => {
|
|
595
636
|
try {
|
|
596
637
|
return await rt.http.request(method, path, {
|
|
597
638
|
body: spec.body,
|
|
598
|
-
headers,
|
|
639
|
+
headers: extra ? { ...headers, ...extra } : headers,
|
|
599
640
|
signal: spec.signal
|
|
600
641
|
});
|
|
601
642
|
} catch (e) {
|
|
@@ -630,6 +671,12 @@ async function palbeRequest(rt, method, path, spec = {}) {
|
|
|
630
671
|
}
|
|
631
672
|
res = await attempt();
|
|
632
673
|
}
|
|
674
|
+
if (res.error?.status === 403 && res.error.code === "pow_required") {
|
|
675
|
+
const challenge = asPowChallenge(res.error.details);
|
|
676
|
+
if (challenge) {
|
|
677
|
+
res = await attempt(await solvePowChallenge(challenge));
|
|
678
|
+
}
|
|
679
|
+
}
|
|
633
680
|
} catch (e) {
|
|
634
681
|
if (!isAbort(e)) record(asPalbaseError(e)?.status ?? 0);
|
|
635
682
|
throw e;
|
|
@@ -1287,7 +1334,7 @@ var AnalyticsState = class {
|
|
|
1287
1334
|
idKey;
|
|
1288
1335
|
optOutKey;
|
|
1289
1336
|
constructor(rt) {
|
|
1290
|
-
const ref = rt.
|
|
1337
|
+
const ref = rt.projectRef;
|
|
1291
1338
|
this.idKey = ref ? `palbe.analytics.id.${ref}` : "palbe.analytics.id";
|
|
1292
1339
|
this.optOutKey = ref ? `palbe.analytics.optout.${ref}` : "palbe.analytics.optout";
|
|
1293
1340
|
rt.auth.onAuthEvent((event) => {
|
|
@@ -2908,7 +2955,7 @@ var PalbeFlags = class {
|
|
|
2908
2955
|
constructor(rt) {
|
|
2909
2956
|
this.transport = new FlagsClient(rt.http);
|
|
2910
2957
|
const browser = typeof document !== "undefined";
|
|
2911
|
-
const ref = rt.
|
|
2958
|
+
const ref = rt.projectRef;
|
|
2912
2959
|
const options = {
|
|
2913
2960
|
auth: palbeAuthAdapter(rt.auth),
|
|
2914
2961
|
...ref ? { storageKey: `palbe.flags.${ref}` } : {},
|
|
@@ -9307,15 +9354,13 @@ function defaultSessionStorage(key) {
|
|
|
9307
9354
|
}
|
|
9308
9355
|
|
|
9309
9356
|
// src/version.ts
|
|
9310
|
-
var VERSION = "7.
|
|
9357
|
+
var VERSION = "7.3.0";
|
|
9311
9358
|
|
|
9312
9359
|
// src/runtime.ts
|
|
9313
9360
|
function buildRuntime(config) {
|
|
9314
|
-
const
|
|
9315
|
-
if (
|
|
9316
|
-
throw new Error("PalbeConfig.apiKey does not contain a valid publishable
|
|
9317
|
-
} else if (config.environmentRef !== keyEnvironmentRef) {
|
|
9318
|
-
throw new Error("PalbeConfig.environmentRef must match the Environment identity in apiKey");
|
|
9361
|
+
const projectRef = environmentRefFromPublishableApiKey(config.apiKey);
|
|
9362
|
+
if (projectRef === "") {
|
|
9363
|
+
throw new Error("PalbeConfig.apiKey does not contain a valid publishable project identity");
|
|
9319
9364
|
}
|
|
9320
9365
|
let runtimeURL;
|
|
9321
9366
|
try {
|
|
@@ -9323,8 +9368,8 @@ function buildRuntime(config) {
|
|
|
9323
9368
|
} catch {
|
|
9324
9369
|
throw new Error("PalbeConfig.url must be a valid URL");
|
|
9325
9370
|
}
|
|
9326
|
-
if (runtimeURL.hostname.endsWith(".palbase.studio") && runtimeURL.hostname.split(".")[0] !==
|
|
9327
|
-
throw new Error("PalbeConfig.url must match
|
|
9371
|
+
if (runtimeURL.hostname.endsWith(".palbase.studio") && runtimeURL.hostname.split(".")[0] !== projectRef) {
|
|
9372
|
+
throw new Error("PalbeConfig.url must match the project identity in apiKey for palbase.studio");
|
|
9328
9373
|
}
|
|
9329
9374
|
const http = new HttpClient(config.apiKey, {
|
|
9330
9375
|
url: config.url,
|
|
@@ -9334,7 +9379,7 @@ function buildRuntime(config) {
|
|
|
9334
9379
|
const tokenManager = new TokenManager();
|
|
9335
9380
|
http.tokenManager = tokenManager;
|
|
9336
9381
|
const authClient = new AuthClient(http, tokenManager);
|
|
9337
|
-
const ref =
|
|
9382
|
+
const ref = projectRef;
|
|
9338
9383
|
const storage = config.storage ?? defaultSessionStorage(ref ? `palbe.session.${ref}` : void 0);
|
|
9339
9384
|
const persisted = storage.load();
|
|
9340
9385
|
if (persisted) {
|
|
@@ -9379,6 +9424,7 @@ function buildRuntime(config) {
|
|
|
9379
9424
|
let perf;
|
|
9380
9425
|
const rt = {
|
|
9381
9426
|
config,
|
|
9427
|
+
projectRef,
|
|
9382
9428
|
http,
|
|
9383
9429
|
tokenManager,
|
|
9384
9430
|
authClient,
|
|
@@ -9790,7 +9836,7 @@ function handleAuthCallback(opts) {
|
|
|
9790
9836
|
const wire = asWireAuthResult(raw);
|
|
9791
9837
|
if (!wire) return redirect(fallback, { auth_error: "oauth_exchange_failed" });
|
|
9792
9838
|
const response = redirect(safeNextPath(params.get("next"), request.nextUrl.origin) ?? fallback);
|
|
9793
|
-
const write = encodeSessionCookiesDecoded(config.
|
|
9839
|
+
const write = encodeSessionCookiesDecoded(environmentRefFromPublishableApiKey(config.apiKey), {
|
|
9794
9840
|
accessToken: wire.access_token,
|
|
9795
9841
|
refreshToken: wire.refresh_token,
|
|
9796
9842
|
expiresAt: Date.now() + wire.expires_in * 1e3
|
|
@@ -9881,7 +9927,7 @@ async function pbServer(opts) {
|
|
|
9881
9927
|
"import the generated palbe.gen.ts once in app/layout.tsx \u2014 the root-layout import configures Server Components and Route Handlers too."
|
|
9882
9928
|
);
|
|
9883
9929
|
const store = opts?.cookies ?? await nextCookieStore();
|
|
9884
|
-
const ref = config.
|
|
9930
|
+
const ref = environmentRefFromPublishableApiKey(config.apiKey);
|
|
9885
9931
|
const rt = buildRuntime({ ...config, storage: serverCookieAdapter(store, ref) });
|
|
9886
9932
|
return createBoundClient(rt);
|
|
9887
9933
|
}
|