@palbase/web 1.0.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.
Files changed (45) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +292 -0
  3. package/dist/analytics-facade-DkOwkEpi.d.ts +454 -0
  4. package/dist/analytics-facade-t6UrFdn7.d.cts +454 -0
  5. package/dist/chunk-JVT65V4E.js +3384 -0
  6. package/dist/chunk-JVT65V4E.js.map +1 -0
  7. package/dist/chunk-VJXFABBW.js +94 -0
  8. package/dist/chunk-VJXFABBW.js.map +1 -0
  9. package/dist/errors-fDoNdTrJ.d.cts +35 -0
  10. package/dist/errors-fDoNdTrJ.d.ts +35 -0
  11. package/dist/index.cjs +2394 -0
  12. package/dist/index.cjs.map +1 -0
  13. package/dist/index.d.cts +11 -0
  14. package/dist/index.d.ts +11 -0
  15. package/dist/index.js +27 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/internal.cjs +3403 -0
  18. package/dist/internal.cjs.map +1 -0
  19. package/dist/internal.d.cts +49 -0
  20. package/dist/internal.d.ts +49 -0
  21. package/dist/internal.js +19 -0
  22. package/dist/internal.js.map +1 -0
  23. package/dist/next/client.cjs +3131 -0
  24. package/dist/next/client.cjs.map +1 -0
  25. package/dist/next/client.d.cts +19 -0
  26. package/dist/next/client.d.ts +19 -0
  27. package/dist/next/client.js +75 -0
  28. package/dist/next/client.js.map +1 -0
  29. package/dist/next/index.cjs +3680 -0
  30. package/dist/next/index.cjs.map +1 -0
  31. package/dist/next/index.d.cts +238 -0
  32. package/dist/next/index.d.ts +238 -0
  33. package/dist/next/index.js +301 -0
  34. package/dist/next/index.js.map +1 -0
  35. package/dist/pb-BmgkAe97.d.ts +54 -0
  36. package/dist/pb-Cudze7Kb.d.cts +54 -0
  37. package/dist/react/index.cjs +649 -0
  38. package/dist/react/index.cjs.map +1 -0
  39. package/dist/react/index.d.cts +86 -0
  40. package/dist/react/index.d.ts +86 -0
  41. package/dist/react/index.js +156 -0
  42. package/dist/react/index.js.map +1 -0
  43. package/dist/storage-BPaeSG8K.d.cts +21 -0
  44. package/dist/storage-BPaeSG8K.d.ts +21 -0
  45. package/package.json +123 -0
@@ -0,0 +1,94 @@
1
+ // src/next/cookie-codec.ts
2
+ var MAX_COOKIE_VALUE = 3500;
3
+ var SESSION_COOKIE_ATTRS = {
4
+ path: "/",
5
+ sameSite: "lax",
6
+ secure: true,
7
+ maxAge: 2592e3
8
+ };
9
+ function sessionCookieName(endpointRef) {
10
+ return `palbe-session-${endpointRef}`;
11
+ }
12
+ function encodeSessionCookies(endpointRef, session) {
13
+ const name = sessionCookieName(endpointRef);
14
+ const value = encodeURIComponent(
15
+ JSON.stringify({ a: session.accessToken, r: session.refreshToken, e: session.expiresAt })
16
+ );
17
+ if (value.length <= MAX_COOKIE_VALUE) {
18
+ return { set: [{ name, value }], clear: [`${name}.0`] };
19
+ }
20
+ const chunks = [];
21
+ for (let start = 0; start < value.length; ) {
22
+ let end = Math.min(start + MAX_COOKIE_VALUE, value.length);
23
+ if (end < value.length) {
24
+ if (value[end - 1] === "%") end -= 1;
25
+ else if (value[end - 2] === "%") end -= 2;
26
+ }
27
+ chunks.push({ name: `${name}.${chunks.length}`, value: value.slice(start, end) });
28
+ start = end;
29
+ }
30
+ return { set: chunks, clear: [`${name}.${chunks.length}`] };
31
+ }
32
+ function encodeSessionCookiesDecoded(endpointRef, session) {
33
+ const { set, clear } = encodeSessionCookies(endpointRef, session);
34
+ return {
35
+ set: set.map(({ name, value }) => ({ name, value: decodeURIComponent(value) })),
36
+ clear
37
+ };
38
+ }
39
+ function decodeSessionCookies(get, endpointRef) {
40
+ const base = sessionCookieName(endpointRef);
41
+ let encoded = get(base);
42
+ if (encoded === void 0) {
43
+ let joined = "";
44
+ for (let i = 0; ; i++) {
45
+ const part = get(`${base}.${i}`);
46
+ if (part === void 0) break;
47
+ joined += part;
48
+ }
49
+ if (joined === "") return null;
50
+ encoded = joined;
51
+ }
52
+ const raw = parseStoredSession(encoded);
53
+ if (raw !== null) return raw;
54
+ try {
55
+ return parseStoredSession(decodeURIComponent(encoded));
56
+ } catch {
57
+ return null;
58
+ }
59
+ }
60
+ function parseStoredSession(json) {
61
+ try {
62
+ const parsed = JSON.parse(json);
63
+ if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
64
+ const obj = parsed;
65
+ if (typeof obj.a === "string" && typeof obj.r === "string" && typeof obj.e === "number") {
66
+ return { accessToken: obj.a, refreshToken: obj.r, expiresAt: obj.e };
67
+ }
68
+ }
69
+ return null;
70
+ } catch {
71
+ return null;
72
+ }
73
+ }
74
+ function clearedSessionCookieNames(endpointRef, present) {
75
+ const base = sessionCookieName(endpointRef);
76
+ const names = [];
77
+ if (present(base)) names.push(base);
78
+ for (let i = 0; ; i++) {
79
+ const chunk = `${base}.${i}`;
80
+ if (!present(chunk)) break;
81
+ names.push(chunk);
82
+ }
83
+ return names;
84
+ }
85
+
86
+ export {
87
+ SESSION_COOKIE_ATTRS,
88
+ sessionCookieName,
89
+ encodeSessionCookies,
90
+ encodeSessionCookiesDecoded,
91
+ decodeSessionCookies,
92
+ clearedSessionCookieNames
93
+ };
94
+ //# sourceMappingURL=chunk-VJXFABBW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/next/cookie-codec.ts"],"sourcesContent":["/**\n * Session-cookie codec shared by EVERY palbe/next surface (browser storage\n * adapter, pbServer cookie adapter, middleware, auth callback). Pure\n * functions — no 'next' imports, no palbe runtime imports — so both sides\n * provably read and write the SAME bytes.\n *\n * Format (P3 design contract):\n * - name: `palbe-session-<endpointRef>`; overflow chunk names append `.0`,\n * `.1`, … (cookie names otherwise avoid dots — tooling friendliness).\n * - value: `encodeURIComponent(JSON.stringify({ a, r, e }))` with a=access\n * token, r=refresh token, e=expiry (ms epoch).\n * - one cookie when the encoded value fits MAX_COOKIE_VALUE chars, else\n * chunks ONLY (the base name must not coexist with chunks — callers clear\n * stale names via clearedSessionCookieNames before writing, then honor the\n * encode result's `clear` overflow guard after writing).\n */\n\nexport { endpointRefFromApiKey } from '../api-key.js';\n\nexport interface StoredSession {\n accessToken: string;\n refreshToken: string;\n /** ms epoch */\n expiresAt: number;\n}\n\n/** Browsers cap a cookie at ~4096 bytes incl. name + attributes; 3500 leaves headroom. */\nconst MAX_COOKIE_VALUE = 3500;\n\n/**\n * The P3 cookie contract attributes, shared by every server-side writer\n * (pbServer adapter, middleware, callback); the browser writer mirrors them\n * in document.cookie string form (next/client.ts). NOT HttpOnly by design —\n * the browser SDK must read/write the session (Supabase-paradigm tradeoff);\n * Max-Age = 30d = the refresh-token TTL.\n */\nexport const SESSION_COOKIE_ATTRS = {\n path: '/',\n sameSite: 'lax',\n secure: true,\n maxAge: 2_592_000,\n} as const;\n\nexport function sessionCookieName(endpointRef: string): string {\n return `palbe-session-${endpointRef}`;\n}\n\nexport interface SessionCookieWrite {\n /** Cookies to SET, in order. */\n set: Array<{ name: string; value: string }>;\n /**\n * Names to DELETE alongside the set: the one-past-the-end OVERFLOW GUARD\n * (base write → `.0`; chunks `.0..n` → `.(n+1)`). Decode stops at the\n * first missing chunk, so deleting exactly one-past-the-end guarantees a\n * stale orphan chunk (left behind a gap, where presence-probing cleanup\n * cannot see it) can never concatenate into the freshly written run.\n * Writers MUST honor both lists.\n */\n clear: string[];\n}\n\nexport function encodeSessionCookies(\n endpointRef: string,\n session: StoredSession,\n): SessionCookieWrite {\n const name = sessionCookieName(endpointRef);\n const value = encodeURIComponent(\n JSON.stringify({ a: session.accessToken, r: session.refreshToken, e: session.expiresAt }),\n );\n if (value.length <= MAX_COOKIE_VALUE) {\n return { set: [{ name, value }], clear: [`${name}.0`] };\n }\n const chunks: Array<{ name: string; value: string }> = [];\n // Chunk WITHOUT splitting a %XX escape (every '%' in the encoded value\n // starts one — encodeURIComponent never emits a bare '%'). Next's cookie\n // layer percent-DECODES values on read and silently DROPS a cookie whose\n // value is an invalid escape sequence, so a split escape would lose that\n // chunk server-side; independent decodability also lets\n // encodeSessionCookiesDecoded mirror this run byte-exactly.\n for (let start = 0; start < value.length; ) {\n let end = Math.min(start + MAX_COOKIE_VALUE, value.length);\n if (end < value.length) {\n if (value[end - 1] === '%') end -= 1;\n else if (value[end - 2] === '%') end -= 2;\n }\n chunks.push({ name: `${name}.${chunks.length}`, value: value.slice(start, end) });\n start = end;\n }\n return { set: chunks, clear: [`${name}.${chunks.length}`] };\n}\n\n/**\n * encodeSessionCookies for percent-ENCODING cookie stores. Next's request\n * and response cookie APIs apply encodeURIComponent to values when\n * serializing (and decodeURIComponent on read) — handing them the codec's\n * already-encoded values would DOUBLE-encode the wire bytes and break the\n * browser-side reader. This variant returns the same cookie run with\n * DECODED values: `encodeURIComponent(value)` reproduces the\n * encodeSessionCookies bytes exactly (chunk boundaries never split an\n * escape), so an encoding store writes byte-identical cookies to a raw\n * writer like document.cookie.\n */\nexport function encodeSessionCookiesDecoded(\n endpointRef: string,\n session: StoredSession,\n): SessionCookieWrite {\n const { set, clear } = encodeSessionCookies(endpointRef, session);\n return {\n set: set.map(({ name, value }) => ({ name, value: decodeURIComponent(value) })),\n clear,\n };\n}\n\n/**\n * Read the session back from a cookie getter: the base name wins; otherwise\n * `.0`, `.1`, … are concatenated until the first missing chunk. Tolerant:\n * malformed URI escapes / JSON / shape → null (treated as \"no session\").\n *\n * Accepts BOTH value forms. Next's cookie stores percent-DECODE values once\n * on read, so server-side callers (pbServer adapter, middleware) hand us the\n * already-decoded JSON; raw readers (document.cookie) hand us the encoded\n * form. The raw (already-decoded) parse runs FIRST because it is\n * unambiguous — an encoded value can never raw-parse as JSON\n * (encodeURIComponent escapes `{` itself, so it starts with `%7B`) — whereas\n * decode-first would silently corrupt a literal `%XX` run inside a token\n * (decodeURIComponent('%41') → 'A', no throw) or throw on an invalid escape.\n */\nexport function decodeSessionCookies(\n get: (name: string) => string | undefined,\n endpointRef: string,\n): StoredSession | null {\n const base = sessionCookieName(endpointRef);\n let encoded = get(base);\n if (encoded === undefined) {\n let joined = '';\n for (let i = 0; ; i++) {\n const part = get(`${base}.${i}`);\n if (part === undefined) break;\n joined += part;\n }\n if (joined === '') return null;\n encoded = joined;\n }\n const raw = parseStoredSession(encoded);\n if (raw !== null) return raw;\n try {\n return parseStoredSession(decodeURIComponent(encoded));\n } catch {\n return null;\n }\n}\n\n/** JSON-parse + shape-check one candidate value; malformed → null. */\nfunction parseStoredSession(json: string): StoredSession | null {\n try {\n const parsed: unknown = JSON.parse(json);\n if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {\n const obj = parsed as Record<string, unknown>;\n if (typeof obj.a === 'string' && typeof obj.r === 'string' && typeof obj.e === 'number') {\n return { accessToken: obj.a, refreshToken: obj.r, expiresAt: obj.e };\n }\n }\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Names a writer must delete before/while writing: the base name (when\n * present) plus every existing `.N` chunk, probed in order until the first\n * missing one (writes are always a contiguous `.0..n` run, so a gap means\n * the end of palbe-owned chunks).\n */\nexport function clearedSessionCookieNames(\n endpointRef: string,\n present: (name: string) => boolean,\n): string[] {\n const base = sessionCookieName(endpointRef);\n const names: string[] = [];\n if (present(base)) names.push(base);\n for (let i = 0; ; i++) {\n const chunk = `${base}.${i}`;\n if (!present(chunk)) break;\n names.push(chunk);\n }\n return names;\n}\n\n/**\n * Parse the canonical chunk index out of `palbe-session-<ref>.N`; non-chunk\n * names (the bare base, a foreign ref, junk suffixes like `.x` / `.01` /\n * `.-1`) → null. The index is a non-negative integer with NO leading zeros\n * (the encoder emits `.0`, `.1`, … verbatim), so `String(n) === suffix`\n * round-trips it exactly.\n */\nfunction chunkIndex(base: string, name: string): number | null {\n if (!name.startsWith(`${base}.`)) return null;\n const suffix = name.slice(base.length + 1);\n if (!/^\\d+$/.test(suffix)) return null;\n const idx = Number.parseInt(suffix, 10);\n return String(idx) === suffix ? idx : null;\n}\n\n/**\n * getAll-powered orphan sweep — the deletion list a writer with the FULL\n * cookie jar should clear, catching crash-orphans that presence-probing\n * (clearedSessionCookieNames, which stops at the first gap) CANNOT see.\n *\n * Given every cookie name in the jar, returns the `palbe-session-<ref>`-family\n * names that are NOT part of a single valid session:\n * - A valid session is EITHER the bare base alone, OR the contiguous chunk\n * run `.0, .1, …, n` (starting at `.0`, no gaps).\n * - Any `.N` beyond the first gap from `.0` is an orphan (incl. ALL chunks\n * when `.0` is absent — no run exists).\n * - The base coexisting with ANY chunk is inconsistent (the contract forbids\n * it; decode lets the base win and silently strands the chunks): the base\n * is kept, the chunks are swept (a fresh write replaces the base in place).\n *\n * Only canonical `.N` names count; foreign refs and malformed suffixes are\n * ignored. Output order: base (if inconsistent) first, then chunks ascending.\n */\nexport function orphanSessionCookieNames(endpointRef: string, allNames: string[]): string[] {\n const base = sessionCookieName(endpointRef);\n const hasBase = allNames.includes(base);\n const indices = new Set<number>();\n for (const name of allNames) {\n const idx = chunkIndex(base, name);\n if (idx !== null) indices.add(idx);\n }\n if (indices.size === 0) return []; // unchunked (base alone) or no palbe cookies\n\n // Length of the contiguous run from .0 (0 when .0 is missing).\n let runLen = 0;\n while (indices.has(runLen)) runLen++;\n\n const orphans: string[] = [];\n // Base coexisting with chunks: base wins on decode → chunks are stale.\n // Sweep the base too only when there are NO chunks behind the run to keep\n // (the contract forbids the mix; clearing chunks alone resolves it, but if\n // the run itself is invalid—no .0—the base is the real session and stays).\n // Decision: when base coexists with ANY chunk, the chunks are orphans; the\n // base is the live session and is kept — UNLESS the chunk set forms a valid\n // run AND there is also a gap-orphan, in which case both base+gap-orphan are\n // inconsistent leftovers. Concretely: keep it simple and SAFE — the base is\n // only swept when it sits alongside a partial/gapped chunk set (a crash mid\n // base→chunk migration), never when chunks form a clean run the base shadows.\n const everyChunkContiguous = indices.size === runLen && runLen > 0;\n if (hasBase && !everyChunkContiguous) orphans.push(base);\n\n for (const idx of [...indices].sort((a, b) => a - b)) {\n if (idx >= runLen) orphans.push(`${base}.${idx}`);\n }\n // Base + clean contiguous run: base wins on decode, chunks are stranded.\n if (hasBase && everyChunkContiguous) {\n for (let i = 0; i < runLen; i++) orphans.push(`${base}.${i}`);\n }\n return orphans;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,35 @@
1
+ interface FieldError {
2
+ field: string;
3
+ message: string;
4
+ }
5
+ type BackendErrorKind = 'notConfigured' | 'validation' | 'unauthorized' | 'rateLimited' | 'server' | 'network' | 'decode';
6
+ interface BackendErrorParams {
7
+ code: string;
8
+ message: string;
9
+ status?: number;
10
+ requestId?: string;
11
+ fields?: FieldError[];
12
+ retryAfter?: number;
13
+ data?: unknown;
14
+ }
15
+ declare class BackendError extends Error {
16
+ readonly kind: BackendErrorKind;
17
+ readonly code: string;
18
+ readonly status: number;
19
+ readonly requestId?: string;
20
+ readonly fields?: FieldError[];
21
+ readonly retryAfter?: number;
22
+ readonly data?: unknown;
23
+ constructor(kind: BackendErrorKind, params: BackendErrorParams);
24
+ static notConfigured(): BackendError;
25
+ }
26
+ /**
27
+ * Type guard for BackendError that survives module-identity splits.
28
+ * This package ships dual ESM + CJS builds; if both end up loaded (or the
29
+ * package is installed twice), two distinct BackendError classes coexist and
30
+ * `instanceof` fails for errors thrown by "the other" copy. Falls back to a
31
+ * structural check on `name` + `kind`.
32
+ */
33
+ declare function isBackendError(e: unknown): e is BackendError;
34
+
35
+ export { BackendError as B, type FieldError as F, type BackendErrorKind as a, isBackendError as i };
@@ -0,0 +1,35 @@
1
+ interface FieldError {
2
+ field: string;
3
+ message: string;
4
+ }
5
+ type BackendErrorKind = 'notConfigured' | 'validation' | 'unauthorized' | 'rateLimited' | 'server' | 'network' | 'decode';
6
+ interface BackendErrorParams {
7
+ code: string;
8
+ message: string;
9
+ status?: number;
10
+ requestId?: string;
11
+ fields?: FieldError[];
12
+ retryAfter?: number;
13
+ data?: unknown;
14
+ }
15
+ declare class BackendError extends Error {
16
+ readonly kind: BackendErrorKind;
17
+ readonly code: string;
18
+ readonly status: number;
19
+ readonly requestId?: string;
20
+ readonly fields?: FieldError[];
21
+ readonly retryAfter?: number;
22
+ readonly data?: unknown;
23
+ constructor(kind: BackendErrorKind, params: BackendErrorParams);
24
+ static notConfigured(): BackendError;
25
+ }
26
+ /**
27
+ * Type guard for BackendError that survives module-identity splits.
28
+ * This package ships dual ESM + CJS builds; if both end up loaded (or the
29
+ * package is installed twice), two distinct BackendError classes coexist and
30
+ * `instanceof` fails for errors thrown by "the other" copy. Falls back to a
31
+ * structural check on `name` + `kind`.
32
+ */
33
+ declare function isBackendError(e: unknown): e is BackendError;
34
+
35
+ export { BackendError as B, type FieldError as F, type BackendErrorKind as a, isBackendError as i };