@palbase/web 2.0.1 → 3.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 (47) hide show
  1. package/README.md +11 -9
  2. package/dist/{analytics-facade-ChlBRcLZ.d.cts → analytics-facade-BOxQ8IP2.d.cts} +8 -16
  3. package/dist/{analytics-facade-G0il4NrT.d.ts → analytics-facade-yfMJ69vw.d.ts} +8 -16
  4. package/dist/{chunk-AIPUO4QX.js → chunk-3HVTEZ7N.js} +30 -36
  5. package/dist/chunk-3HVTEZ7N.js.map +1 -0
  6. package/dist/{chunk-VJXFABBW.js → chunk-6VGKMNXO.js} +11 -11
  7. package/dist/chunk-6VGKMNXO.js.map +1 -0
  8. package/dist/chunk-S7NAY3MW.js +24 -0
  9. package/dist/chunk-S7NAY3MW.js.map +1 -0
  10. package/dist/gen/cli.cjs +32 -6
  11. package/dist/gen/cli.cjs.map +1 -1
  12. package/dist/gen/cli.js +28 -7
  13. package/dist/gen/cli.js.map +1 -1
  14. package/dist/index.cjs +3 -10
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +3 -3
  17. package/dist/index.d.ts +3 -3
  18. package/dist/index.js +2 -2
  19. package/dist/internal.cjs +33 -32
  20. package/dist/internal.cjs.map +1 -1
  21. package/dist/internal.d.cts +3 -3
  22. package/dist/internal.d.ts +3 -3
  23. package/dist/internal.js +2 -2
  24. package/dist/next/client.cjs +50 -46
  25. package/dist/next/client.cjs.map +1 -1
  26. package/dist/next/client.d.cts +1 -1
  27. package/dist/next/client.d.ts +1 -1
  28. package/dist/next/client.js +12 -10
  29. package/dist/next/client.js.map +1 -1
  30. package/dist/next/index.cjs +53 -47
  31. package/dist/next/index.cjs.map +1 -1
  32. package/dist/next/index.d.cts +10 -10
  33. package/dist/next/index.d.ts +10 -10
  34. package/dist/next/index.js +14 -13
  35. package/dist/next/index.js.map +1 -1
  36. package/dist/{pb-B_6o5p79.d.cts → pb-B3h3NIPE.d.cts} +1 -1
  37. package/dist/{pb-nPBhqhJr.d.ts → pb-QRISxPd1.d.ts} +1 -1
  38. package/dist/react/index.cjs +1 -1
  39. package/dist/react/index.cjs.map +1 -1
  40. package/dist/react/index.d.cts +1 -1
  41. package/dist/react/index.d.ts +1 -1
  42. package/dist/react/index.js +2 -2
  43. package/package.json +2 -2
  44. package/dist/chunk-AIPUO4QX.js.map +0 -1
  45. package/dist/chunk-PZ5AY32C.js +0 -10
  46. package/dist/chunk-PZ5AY32C.js.map +0 -1
  47. package/dist/chunk-VJXFABBW.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  import { NextRequest, NextResponse } from 'next/server';
2
- import { P as PB } from '../pb-B_6o5p79.cjs';
3
- import '../analytics-facade-ChlBRcLZ.cjs';
2
+ import { P as PB } from '../pb-B3h3NIPE.cjs';
3
+ import '../analytics-facade-BOxQ8IP2.cjs';
4
4
  import 'livekit-client';
5
5
  import '../storage-BPaeSG8K.cjs';
6
6
  import './pooled-flags-4GtDtsiu.js';
@@ -40,7 +40,7 @@ interface HandleAuthCallbackOptions {
40
40
  */
41
41
  declare function handleAuthCallback(opts?: HandleAuthCallbackOptions): (request: NextRequest) => Promise<Response>;
42
42
 
43
- declare function endpointRefFromApiKey(apiKey: string): string;
43
+ declare function environmentRefFromApiKey(apiKey: string): string;
44
44
 
45
45
  /**
46
46
  * Session-cookie codec shared by EVERY palbe/next surface (browser storage
@@ -49,7 +49,7 @@ declare function endpointRefFromApiKey(apiKey: string): string;
49
49
  * provably read and write the SAME bytes.
50
50
  *
51
51
  * Format (P3 design contract):
52
- * - name: `palbe-session-<endpointRef>`; overflow chunk names append `.0`,
52
+ * - name: `palbe-session-<environmentRef>`; overflow chunk names append `.0`,
53
53
  * `.1`, … (cookie names otherwise avoid dots — tooling friendliness).
54
54
  * - value: `encodeURIComponent(JSON.stringify({ a, r, e }))` with a=access
55
55
  * token, r=refresh token, e=expiry (ms epoch).
@@ -78,7 +78,7 @@ declare const SESSION_COOKIE_ATTRS: {
78
78
  readonly secure: true;
79
79
  readonly maxAge: 2592000;
80
80
  };
81
- declare function sessionCookieName(endpointRef: string): string;
81
+ declare function sessionCookieName(environmentRef: string): string;
82
82
  interface SessionCookieWrite {
83
83
  /** Cookies to SET, in order. */
84
84
  set: Array<{
@@ -95,7 +95,7 @@ interface SessionCookieWrite {
95
95
  */
96
96
  clear: string[];
97
97
  }
98
- declare function encodeSessionCookies(endpointRef: string, session: StoredSession): SessionCookieWrite;
98
+ declare function encodeSessionCookies(environmentRef: string, session: StoredSession): SessionCookieWrite;
99
99
  /**
100
100
  * encodeSessionCookies for percent-ENCODING cookie stores. Next's request
101
101
  * and response cookie APIs apply encodeURIComponent to values when
@@ -107,7 +107,7 @@ declare function encodeSessionCookies(endpointRef: string, session: StoredSessio
107
107
  * escape), so an encoding store writes byte-identical cookies to a raw
108
108
  * writer like document.cookie.
109
109
  */
110
- declare function encodeSessionCookiesDecoded(endpointRef: string, session: StoredSession): SessionCookieWrite;
110
+ declare function encodeSessionCookiesDecoded(environmentRef: string, session: StoredSession): SessionCookieWrite;
111
111
  /**
112
112
  * Read the session back from a cookie getter: the base name wins; otherwise
113
113
  * `.0`, `.1`, … are concatenated until the first missing chunk. Tolerant:
@@ -122,14 +122,14 @@ declare function encodeSessionCookiesDecoded(endpointRef: string, session: Store
122
122
  * decode-first would silently corrupt a literal `%XX` run inside a token
123
123
  * (decodeURIComponent('%41') → 'A', no throw) or throw on an invalid escape.
124
124
  */
125
- declare function decodeSessionCookies(get: (name: string) => string | undefined, endpointRef: string): StoredSession | null;
125
+ declare function decodeSessionCookies(get: (name: string) => string | undefined, environmentRef: string): StoredSession | null;
126
126
  /**
127
127
  * Names a writer must delete before/while writing: the base name (when
128
128
  * present) plus every existing `.N` chunk, probed in order until the first
129
129
  * missing one (writes are always a contiguous `.0..n` run, so a gap means
130
130
  * the end of palbe-owned chunks).
131
131
  */
132
- declare function clearedSessionCookieNames(endpointRef: string, present: (name: string) => boolean): string[];
132
+ declare function clearedSessionCookieNames(environmentRef: string, present: (name: string) => boolean): string[];
133
133
 
134
134
  /**
135
135
  * palbeMiddleware — proactive cookie-session refresh in Next.js middleware.
@@ -228,4 +228,4 @@ declare function pbServer(opts?: {
228
228
  cookies?: CookieStoreLike;
229
229
  }): Promise<PB>;
230
230
 
231
- export { type CookieStoreLike, type HandleAuthCallbackOptions, type PalbeMiddlewareOptions, SESSION_COOKIE_ATTRS, type SessionCookieWrite, type StoredSession, clearedSessionCookieNames, decodeSessionCookies, encodeSessionCookies, encodeSessionCookiesDecoded, endpointRefFromApiKey, handleAuthCallback, palbeMiddleware, pbServer, sessionCookieName };
231
+ export { type CookieStoreLike, type HandleAuthCallbackOptions, type PalbeMiddlewareOptions, SESSION_COOKIE_ATTRS, type SessionCookieWrite, type StoredSession, clearedSessionCookieNames, decodeSessionCookies, encodeSessionCookies, encodeSessionCookiesDecoded, environmentRefFromApiKey, handleAuthCallback, palbeMiddleware, pbServer, sessionCookieName };
@@ -1,6 +1,6 @@
1
1
  import { NextRequest, NextResponse } from 'next/server';
2
- import { P as PB } from '../pb-nPBhqhJr.js';
3
- import '../analytics-facade-G0il4NrT.js';
2
+ import { P as PB } from '../pb-QRISxPd1.js';
3
+ import '../analytics-facade-yfMJ69vw.js';
4
4
  import 'livekit-client';
5
5
  import '../storage-BPaeSG8K.js';
6
6
  import './pooled-flags-4GtDtsiu.js';
@@ -40,7 +40,7 @@ interface HandleAuthCallbackOptions {
40
40
  */
41
41
  declare function handleAuthCallback(opts?: HandleAuthCallbackOptions): (request: NextRequest) => Promise<Response>;
42
42
 
43
- declare function endpointRefFromApiKey(apiKey: string): string;
43
+ declare function environmentRefFromApiKey(apiKey: string): string;
44
44
 
45
45
  /**
46
46
  * Session-cookie codec shared by EVERY palbe/next surface (browser storage
@@ -49,7 +49,7 @@ declare function endpointRefFromApiKey(apiKey: string): string;
49
49
  * provably read and write the SAME bytes.
50
50
  *
51
51
  * Format (P3 design contract):
52
- * - name: `palbe-session-<endpointRef>`; overflow chunk names append `.0`,
52
+ * - name: `palbe-session-<environmentRef>`; overflow chunk names append `.0`,
53
53
  * `.1`, … (cookie names otherwise avoid dots — tooling friendliness).
54
54
  * - value: `encodeURIComponent(JSON.stringify({ a, r, e }))` with a=access
55
55
  * token, r=refresh token, e=expiry (ms epoch).
@@ -78,7 +78,7 @@ declare const SESSION_COOKIE_ATTRS: {
78
78
  readonly secure: true;
79
79
  readonly maxAge: 2592000;
80
80
  };
81
- declare function sessionCookieName(endpointRef: string): string;
81
+ declare function sessionCookieName(environmentRef: string): string;
82
82
  interface SessionCookieWrite {
83
83
  /** Cookies to SET, in order. */
84
84
  set: Array<{
@@ -95,7 +95,7 @@ interface SessionCookieWrite {
95
95
  */
96
96
  clear: string[];
97
97
  }
98
- declare function encodeSessionCookies(endpointRef: string, session: StoredSession): SessionCookieWrite;
98
+ declare function encodeSessionCookies(environmentRef: string, session: StoredSession): SessionCookieWrite;
99
99
  /**
100
100
  * encodeSessionCookies for percent-ENCODING cookie stores. Next's request
101
101
  * and response cookie APIs apply encodeURIComponent to values when
@@ -107,7 +107,7 @@ declare function encodeSessionCookies(endpointRef: string, session: StoredSessio
107
107
  * escape), so an encoding store writes byte-identical cookies to a raw
108
108
  * writer like document.cookie.
109
109
  */
110
- declare function encodeSessionCookiesDecoded(endpointRef: string, session: StoredSession): SessionCookieWrite;
110
+ declare function encodeSessionCookiesDecoded(environmentRef: string, session: StoredSession): SessionCookieWrite;
111
111
  /**
112
112
  * Read the session back from a cookie getter: the base name wins; otherwise
113
113
  * `.0`, `.1`, … are concatenated until the first missing chunk. Tolerant:
@@ -122,14 +122,14 @@ declare function encodeSessionCookiesDecoded(endpointRef: string, session: Store
122
122
  * decode-first would silently corrupt a literal `%XX` run inside a token
123
123
  * (decodeURIComponent('%41') → 'A', no throw) or throw on an invalid escape.
124
124
  */
125
- declare function decodeSessionCookies(get: (name: string) => string | undefined, endpointRef: string): StoredSession | null;
125
+ declare function decodeSessionCookies(get: (name: string) => string | undefined, environmentRef: string): StoredSession | null;
126
126
  /**
127
127
  * Names a writer must delete before/while writing: the base name (when
128
128
  * present) plus every existing `.N` chunk, probed in order until the first
129
129
  * missing one (writes are always a contiguous `.0..n` run, so a gap means
130
130
  * the end of palbe-owned chunks).
131
131
  */
132
- declare function clearedSessionCookieNames(endpointRef: string, present: (name: string) => boolean): string[];
132
+ declare function clearedSessionCookieNames(environmentRef: string, present: (name: string) => boolean): string[];
133
133
 
134
134
  /**
135
135
  * palbeMiddleware — proactive cookie-session refresh in Next.js middleware.
@@ -228,4 +228,4 @@ declare function pbServer(opts?: {
228
228
  cookies?: CookieStoreLike;
229
229
  }): Promise<PB>;
230
230
 
231
- export { type CookieStoreLike, type HandleAuthCallbackOptions, type PalbeMiddlewareOptions, SESSION_COOKIE_ATTRS, type SessionCookieWrite, type StoredSession, clearedSessionCookieNames, decodeSessionCookies, encodeSessionCookies, encodeSessionCookiesDecoded, endpointRefFromApiKey, handleAuthCallback, palbeMiddleware, pbServer, sessionCookieName };
231
+ export { type CookieStoreLike, type HandleAuthCallbackOptions, type PalbeMiddlewareOptions, SESSION_COOKIE_ATTRS, type SessionCookieWrite, type StoredSession, clearedSessionCookieNames, decodeSessionCookies, encodeSessionCookies, encodeSessionCookiesDecoded, environmentRefFromApiKey, handleAuthCallback, palbeMiddleware, pbServer, sessionCookieName };
@@ -5,16 +5,17 @@ import {
5
5
  encodeSessionCookies,
6
6
  encodeSessionCookiesDecoded,
7
7
  sessionCookieName
8
- } from "../chunk-VJXFABBW.js";
8
+ } from "../chunk-6VGKMNXO.js";
9
9
  import {
10
10
  BackendError,
11
11
  asWireAuthResult,
12
12
  buildRuntime,
13
13
  createBoundClient,
14
- endpointRefFromApiKey,
15
14
  getRuntime
16
- } from "../chunk-AIPUO4QX.js";
17
- import "../chunk-PZ5AY32C.js";
15
+ } from "../chunk-3HVTEZ7N.js";
16
+ import {
17
+ environmentRefFromApiKey
18
+ } from "../chunk-S7NAY3MW.js";
18
19
 
19
20
  // src/next/shared.ts
20
21
  function requireGlobalConfig(hint) {
@@ -117,7 +118,7 @@ function handleAuthCallback(opts) {
117
118
  const wire = asWireAuthResult(raw);
118
119
  if (!wire) return redirect(fallback, { auth_error: "oauth_exchange_failed" });
119
120
  const response = redirect(safeNextPath(params.get("next"), request.nextUrl.origin) ?? fallback);
120
- const write = encodeSessionCookiesDecoded(endpointRefFromApiKey(config.apiKey), {
121
+ const write = encodeSessionCookiesDecoded(config.environmentRef, {
121
122
  accessToken: wire.access_token,
122
123
  refreshToken: wire.refresh_token,
123
124
  expiresAt: Date.now() + wire.expires_in * 1e3
@@ -180,7 +181,7 @@ async function palbeMiddleware(request, opts) {
180
181
  );
181
182
  const { NextResponse } = await importNextServer("palbeMiddleware");
182
183
  const passThrough = () => opts?.response ?? NextResponse.next({ request });
183
- const ref = endpointRefFromApiKey(config.apiKey);
184
+ const ref = config.environmentRef;
184
185
  const session = decodeSessionCookies((name) => request.cookies.get(name)?.value, ref);
185
186
  if (!session) return passThrough();
186
187
  if (session.expiresAt - Date.now() > (opts?.refreshMarginMs ?? DEFAULT_REFRESH_MARGIN_MS)) {
@@ -250,11 +251,11 @@ function removeCookie(store, name) {
250
251
  } catch {
251
252
  }
252
253
  }
253
- function serverCookieAdapter(store, endpointRef) {
254
+ function serverCookieAdapter(store, environmentRef) {
254
255
  const present = (name) => store.get(name) !== void 0;
255
256
  return {
256
257
  load() {
257
- const stored = decodeSessionCookies((name) => store.get(name)?.value, endpointRef);
258
+ const stored = decodeSessionCookies((name) => store.get(name)?.value, environmentRef);
258
259
  if (!stored) return null;
259
260
  return stored.accessToken && stored.expiresAt > 0 ? {
260
261
  refreshToken: stored.refreshToken,
@@ -264,10 +265,10 @@ function serverCookieAdapter(store, endpointRef) {
264
265
  },
265
266
  save(session) {
266
267
  if (!session.accessToken || !session.expiresAt) return;
267
- for (const name of clearedSessionCookieNames(endpointRef, present)) {
268
+ for (const name of clearedSessionCookieNames(environmentRef, present)) {
268
269
  removeCookie(store, name);
269
270
  }
270
- const { set, clear } = encodeSessionCookiesDecoded(endpointRef, {
271
+ const { set, clear } = encodeSessionCookiesDecoded(environmentRef, {
271
272
  accessToken: session.accessToken,
272
273
  refreshToken: session.refreshToken,
273
274
  expiresAt: session.expiresAt
@@ -281,7 +282,7 @@ function serverCookieAdapter(store, endpointRef) {
281
282
  for (const name of clear) removeCookie(store, name);
282
283
  },
283
284
  clear() {
284
- for (const name of clearedSessionCookieNames(endpointRef, present)) {
285
+ for (const name of clearedSessionCookieNames(environmentRef, present)) {
285
286
  removeCookie(store, name);
286
287
  }
287
288
  }
@@ -292,7 +293,7 @@ async function pbServer(opts) {
292
293
  "import the generated palbe.gen.ts once in app/layout.tsx \u2014 the root-layout import configures Server Components and Route Handlers too."
293
294
  );
294
295
  const store = opts?.cookies ?? await nextCookieStore();
295
- const ref = endpointRefFromApiKey(config.apiKey);
296
+ const ref = config.environmentRef;
296
297
  const rt = buildRuntime({ ...config, storage: serverCookieAdapter(store, ref) });
297
298
  return createBoundClient(rt);
298
299
  }
@@ -302,7 +303,7 @@ export {
302
303
  decodeSessionCookies,
303
304
  encodeSessionCookies,
304
305
  encodeSessionCookiesDecoded,
305
- endpointRefFromApiKey,
306
+ environmentRefFromApiKey,
306
307
  handleAuthCallback,
307
308
  palbeMiddleware,
308
309
  pbServer,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/next/shared.ts","../../src/next/callback.ts","../../src/next/middleware.ts","../../src/next/server.ts"],"sourcesContent":["/**\n * Cross-surface helpers for the palbe/next server entries (pbServer,\n * palbeMiddleware, handleAuthCallback): global-config lookup with a\n * surface-specific guided error, and the lazy 'next/server' import.\n */\nimport type { PalbeConfig } from '../config.js';\nimport { BackendError } from '../errors.js';\nimport { getRuntime } from '../internal.js';\n\n/**\n * Global config with a surface-specific guided error when absent. Each\n * surface names the import location that configures ITS module graph —\n * Next bundles middleware separately from the server graph, so the hint\n * matters (layout.tsx for Server Components / Route Handlers, middleware.ts\n * for the middleware).\n */\nexport function requireGlobalConfig(hint: string): PalbeConfig {\n try {\n return getRuntime().config;\n } catch {\n throw new BackendError('notConfigured', {\n code: 'not_configured',\n message: `Palbe is not configured in this module graph. Run 'palbase web link' and ${hint}`,\n });\n }\n}\n\nlet nextServerModule: Promise<typeof import('next/server')> | undefined;\n\n/**\n * Lazy 'next/server' import (MODULE-GRAPH RULE: never top-level — importing\n * palbe/next must work without next installed) with a guided failure.\n * The module promise is memoized: bundler dynamic-import machinery can take\n * macrotask-scale hops PER CALL, so without the cache two near-simultaneous\n * middleware invocations could straddle a refresh — every call after the\n * first now resolves in pure microtasks.\n */\nexport async function importNextServer(caller: string): Promise<typeof import('next/server')> {\n nextServerModule ??= import('next/server');\n try {\n return await nextServerModule;\n } catch (cause) {\n nextServerModule = undefined; // never poison later calls with a cached rejection\n const detail = cause instanceof Error && cause.message ? ` (${cause.message})` : '';\n throw new BackendError('validation', {\n code: 'next_required',\n message: `${caller}() requires Next.js — 'next/server' could not be resolved${detail}.`,\n });\n }\n}\n","/**\n * handleAuthCallback — the OAuth completion route handler factory.\n *\n * The app's redirect_uri (registered when calling signInWithOAuth with\n * `redirectTo: '<app>/auth/callback?provider=google&next=/dash'`) lands\n * here with `?code&state` from the provider. The handler exchanges them\n * SERVER-SIDE against palauth (PKCE verifier + state live server-side; the\n * browser never holds them), writes the session cookies onto a redirect\n * response, and sends the user on.\n *\n * ```ts\n * // app/auth/callback/route.ts\n * import { handleAuthCallback } from '@palbase/web/next';\n * export const GET = handleAuthCallback({ defaultNext: '/' });\n * ```\n *\n * MODULE-GRAPH RULE (same as ./index.ts): 'next/server' only lazily; the\n * type-only NextRequest import erases at build time.\n */\nimport type { NextRequest } from 'next/server';\nimport { asWireAuthResult } from '../auth-wire.js';\nimport {\n encodeSessionCookiesDecoded,\n endpointRefFromApiKey,\n SESSION_COOKIE_ATTRS,\n} from './cookie-codec.js';\nimport { importNextServer, requireGlobalConfig } from './shared.js';\n\nexport interface HandleAuthCallbackOptions {\n /** Where to land when the callback carries no (valid) `next` param — and on every error/MFA redirect. Default '/'. */\n defaultNext?: string;\n}\n\n/**\n * Open-redirect guard: `next` rides the OAuth redirect querystring, so it is\n * attacker-influencable — only same-origin, path-absolute relative paths are\n * honored, and the post-auth victim is never sent off-origin.\n *\n * A leading-'/' heuristic is NOT enough. The value is later resolved with\n * `new URL(next, base)`, and the WHATWG URL parser STRIPS ASCII tab (0x09),\n * LF (0x0A) and CR (0x0D) before parsing — so `/<TAB>/evil.com` slips past a\n * \"next[1] is not '/'\" check yet parses to `//evil.com` → `https://evil.com`\n * (CWE-601 open redirect). We defend with TWO independent gates that must\n * BOTH pass, matching OWASP unvalidated-redirect guidance:\n *\n * 1. RAW-STRING gate (reject before normalization can hide the payload):\n * - reject any C0 control char (\\x00-\\x1F, incl. \\t \\n \\r) or other\n * whitespace — these are exactly what URL parsing strips/normalizes\n * away;\n * - require a path-absolute prefix: a single '/' NOT followed by '/' or\n * '\\\\' (blocks '//host' protocol-relative and '/\\\\host' backslash\n * tricks);\n * - reject a scheme: any ':' appearing before the first '/' ('javascript:',\n * 'https:'). Path-absolute inputs start with '/', so this also rejects\n * bare 'foo:bar'.\n * 2. CANONICAL gate: resolve `new URL(next, origin)` and require the result\n * to land on the SAME origin. This is the authoritative check — it sees\n * exactly what the browser will, after normalization.\n *\n * Anything ambiguous returns null so the caller falls back to a safe default.\n */\nfunction safeNextPath(next: string | null, origin: string): string | null {\n if (!next) return null;\n // 1a. No control chars / whitespace — URL parsing would strip these and\n // change what the path means (the \\t \\n \\r open-redirect class).\n // biome-ignore lint/suspicious/noControlCharactersInRegex: rejecting C0 is the point of the guard.\n if (/[\\u0000-\\u0020\\u007f\\s]/.test(next)) return null;\n // 1b. Must be path-absolute: a single leading '/', not '//' or '/\\\\'.\n if (next[0] !== '/' || next[1] === '/' || next[1] === '\\\\') return null;\n // 1c. No scheme before the first path separator (defense in depth; a\n // path-absolute string can't carry one, but reject explicitly).\n const firstSlash = next.indexOf('/');\n const firstColon = next.indexOf(':');\n if (firstColon !== -1 && firstColon < firstSlash) return null;\n // 2. Canonical same-origin check — resolve as the browser/redirect helper\n // will and confirm we never leave this origin.\n try {\n if (new URL(next, origin).origin !== origin) return null;\n } catch {\n return null;\n }\n return next;\n}\n\nfunction wireErrorCode(raw: unknown): string {\n if (typeof raw === 'object' && raw !== null) {\n const code = (raw as Record<string, unknown>).error;\n if (typeof code === 'string' && code !== '') return code;\n }\n return 'oauth_exchange_failed';\n}\n\n/**\n * Build the callback route handler. Outcomes (all 307 redirects, all with\n * `Cache-Control: private, no-store` — auth outcomes must never cache):\n * - provider `error` param → `?auth_error=<error>` (+ `auth_error_description`)\n * - missing code/state/provider → `?auth_error=invalid_callback`\n * - exchanged AuthResult → session cookies on the redirect to `next ?? defaultNext ?? '/'`\n * - MFA union → `?mfa_token=…&mfa_factors=a,b` on defaultNext, NO cookies\n * - exchange failure → `?auth_error=<wire code | oauth_exchange_failed>`\n */\nexport function handleAuthCallback(\n opts?: HandleAuthCallbackOptions,\n): (request: NextRequest) => Promise<Response> {\n return async (request) => {\n const config = requireGlobalConfig(\n 'import the generated palbe.gen.ts once in app/layout.tsx — route handlers share the server module graph with the root layout.',\n );\n const { NextResponse } = await importNextServer('handleAuthCallback');\n const fallback = opts?.defaultNext ?? '/';\n\n const redirect = (path: string, query?: Record<string, string>) => {\n const url = new URL(path, request.nextUrl);\n for (const [key, value] of Object.entries(query ?? {})) url.searchParams.set(key, value);\n const response = NextResponse.redirect(url); // 307 — the callback GET stays a GET\n response.headers.set('cache-control', 'private, no-store');\n return response;\n };\n\n const params = request.nextUrl.searchParams;\n const providerError = params.get('error');\n if (providerError) {\n const query: Record<string, string> = { auth_error: providerError };\n const description = params.get('error_description');\n if (description) query.auth_error_description = description;\n return redirect(fallback, query);\n }\n\n const code = params.get('code');\n const state = params.get('state');\n const provider = params.get('provider');\n if (!code || !state || !provider) {\n return redirect(fallback, { auth_error: 'invalid_callback' });\n }\n\n let exchange: Response;\n try {\n exchange = await fetch(\n `${config.url}/auth/oauth/${encodeURIComponent(provider)}/callback` +\n `?code=${encodeURIComponent(code)}&state=${encodeURIComponent(state)}`,\n { headers: { apikey: config.apiKey } },\n );\n } catch {\n return redirect(fallback, { auth_error: 'oauth_exchange_failed' });\n }\n let raw: unknown = null;\n try {\n raw = await exchange.json();\n } catch {\n // malformed body — the shape checks below turn this into auth_error\n }\n if (!exchange.ok) return redirect(fallback, { auth_error: wireErrorCode(raw) });\n\n if (typeof raw === 'object' && raw !== null) {\n const obj = raw as Record<string, unknown>;\n // MFA union: relay the challenge to the app — NO cookies until it completes.\n if (obj.mfa_required === true && typeof obj.mfa_token === 'string') {\n const factors = Array.isArray(obj.mfa_factors)\n ? obj.mfa_factors.filter((f): f is string => typeof f === 'string')\n : [];\n return redirect(fallback, { mfa_token: obj.mfa_token, mfa_factors: factors.join(',') });\n }\n }\n\n // Zombie-session guard (shared with the auth facade): cookies are only\n // ever written for a FULLY-proven AuthResult.\n const wire = asWireAuthResult(raw);\n if (!wire) return redirect(fallback, { auth_error: 'oauth_exchange_failed' });\n\n const response = redirect(safeNextPath(params.get('next'), request.nextUrl.origin) ?? fallback);\n // DECODED codec values: NextResponse.cookies percent-encodes on write,\n // producing exactly the shared-codec wire bytes (encodeSessionCookiesDecoded).\n const write = encodeSessionCookiesDecoded(endpointRefFromApiKey(config.apiKey), {\n accessToken: wire.access_token,\n refreshToken: wire.refresh_token,\n expiresAt: Date.now() + wire.expires_in * 1000,\n });\n for (const { name, value } of write.set) {\n response.cookies.set(name, value, SESSION_COOKIE_ATTRS);\n }\n // Codec overflow guard: expire one-past-the-end of the written run.\n for (const name of write.clear) {\n response.cookies.set(name, '', { ...SESSION_COOKIE_ATTRS, maxAge: 0 });\n }\n return response;\n };\n}\n","/**\n * palbeMiddleware — proactive cookie-session refresh in Next.js middleware.\n *\n * REQUIRED — not optional — for session-bearing RSC apps. Server Components\n * cannot write cookies, so pbServer's reactive refresh cannot PERSIST a\n * rotated session there: every RSC render would re-refresh from the SAME\n * cookie refresh token, and once two of those land more than 30s apart\n * (outside palauth's rotation grace) the reuse detector REVOKES THE WHOLE\n * TOKEN FAMILY — the user is force-logged-out everywhere. This middleware\n * refreshes the cookie BEFORE the RSC tree renders, so pbServer hydrates a\n * still-valid session and never burns the token itself.\n *\n * MODULE-GRAPH RULES (same as ./index.ts): 'next/server' is imported only\n * lazily (the type-only NextRequest/NextResponse imports erase at build\n * time), and middleware.ts must import the generated palbe.gen.ts itself —\n * Next bundles middleware as its OWN module graph; the layout.tsx import\n * does not reach it.\n *\n * ```ts\n * // middleware.ts\n * import './palbe.gen';\n * import { palbeMiddleware } from '@palbase/web/next';\n * import type { NextRequest } from 'next/server';\n *\n * export function middleware(request: NextRequest) {\n * return palbeMiddleware(request);\n * }\n * export const config = { matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'] };\n * ```\n */\nimport type { NextRequest, NextResponse } from 'next/server';\nimport type { PalbeConfig } from '../config.js';\nimport {\n clearedSessionCookieNames,\n decodeSessionCookies,\n encodeSessionCookiesDecoded,\n endpointRefFromApiKey,\n SESSION_COOKIE_ATTRS,\n type StoredSession,\n} from './cookie-codec.js';\nimport { importNextServer, requireGlobalConfig } from './shared.js';\n\nconst DEFAULT_REFRESH_MARGIN_MS = 60_000;\n\nexport interface PalbeMiddlewareOptions {\n /** Refresh when the access token expires within this window. Default 60s. */\n refreshMarginMs?: number;\n /**\n * Pre-built response to decorate (e.g. from chained middleware) instead of\n * building `NextResponse.next({ request })`. Pass-through cases return it\n * UNMODIFIED. Caveat: a pre-built response snapshotted the request headers\n * at ITS creation, so a rotated cookie reaches the browser (Set-Cookie)\n * but not the downstream RSC render of THIS request — prefer omitting this\n * and building your response after palbeMiddleware when possible.\n */\n response?: NextResponse;\n}\n\ntype RefreshOutcome =\n | { kind: 'rotated'; session: StoredSession }\n | { kind: 'terminal' } // 400/401/403 — refresh token dead, sign out\n | { kind: 'transient' }; // network / 5xx / malformed — keep the session\n\n/**\n * Per-process single-flight: concurrent middleware invocations holding the\n * SAME refresh token (parallel tabs / prefetches) share one refresh call —\n * a per-token thundering herd would race palauth rotation. Multi-pod\n * concurrency is covered by palauth's 30s rotation grace (concurrent\n * refreshes of one token all succeed); per-process dedup is all that's\n * needed here (Studio precedent — don't over-engineer).\n */\nconst inflightRefreshes = new Map<string, Promise<RefreshOutcome>>();\n\nfunction refreshSingleFlight(config: PalbeConfig, refreshToken: string): Promise<RefreshOutcome> {\n const existing = inflightRefreshes.get(refreshToken);\n if (existing) return existing;\n const pending = refresh(config, refreshToken).finally(() => {\n inflightRefreshes.delete(refreshToken);\n });\n inflightRefreshes.set(refreshToken, pending);\n return pending;\n}\n\n/** Direct palauth refresh call (no runtime: middleware needs only this one wire). */\nasync function refresh(config: PalbeConfig, refreshToken: string): Promise<RefreshOutcome> {\n try {\n const res = await fetch(`${config.url}/auth/token/refresh`, {\n method: 'POST',\n headers: { apikey: config.apiKey, 'content-type': 'application/json' },\n body: JSON.stringify({ refresh_token: refreshToken }),\n });\n if (res.status === 400 || res.status === 401 || res.status === 403) {\n return { kind: 'terminal' };\n }\n if (!res.ok) return { kind: 'transient' };\n const raw: unknown = await res.json();\n if (typeof raw === 'object' && raw !== null) {\n const obj = raw as Record<string, unknown>;\n if (\n typeof obj.access_token === 'string' &&\n typeof obj.refresh_token === 'string' &&\n typeof obj.expires_in === 'number'\n ) {\n return {\n kind: 'rotated',\n session: {\n accessToken: obj.access_token,\n refreshToken: obj.refresh_token,\n expiresAt: Date.now() + obj.expires_in * 1000,\n },\n };\n }\n }\n return { kind: 'transient' }; // malformed 200 — never destroy a session over it\n } catch {\n return { kind: 'transient' }; // network failure\n }\n}\n\n/**\n * Keep the session cookie fresh for the request. No session / still-fresh\n * session → untouched pass-through (no cache-control changes). Stale or\n * expired → single-flight refresh, then the rotated (or cleared, on a dead\n * token) cookies are written onto BOTH the request (for the downstream RSC\n * render via `NextResponse.next({ request })`) and the response (for the\n * browser), with `Cache-Control: private, no-store` on touched responses.\n *\n * Cookie writes go through Next's cookie APIs with the DECODED codec values:\n * Next percent-encodes on serialization, so the wire bytes come out exactly\n * as the shared codec's (see encodeSessionCookiesDecoded). NextRequest's\n * cookie store is NOT a CookieStoreLike (its set is the 2-arg/RequestCookie\n * form), hence the direct codec calls here instead of the pbServer adapter.\n */\nexport async function palbeMiddleware(\n request: NextRequest,\n opts?: PalbeMiddlewareOptions,\n): Promise<NextResponse> {\n const config = requireGlobalConfig(\n 'import the generated palbe.gen.ts at the top of middleware.ts — Next bundles middleware as its own module graph, so the layout.tsx import does not reach it.',\n );\n const { NextResponse } = await importNextServer('palbeMiddleware');\n const passThrough = (): NextResponse => opts?.response ?? NextResponse.next({ request });\n\n const ref = endpointRefFromApiKey(config.apiKey);\n const session = decodeSessionCookies((name) => request.cookies.get(name)?.value, ref);\n if (!session) return passThrough();\n if (session.expiresAt - Date.now() > (opts?.refreshMarginMs ?? DEFAULT_REFRESH_MARGIN_MS)) {\n return passThrough();\n }\n\n const outcome = await refreshSingleFlight(config, session.refreshToken);\n if (outcome.kind === 'transient') return passThrough(); // keep the session over blips\n\n // Session-cookie names in the incoming jar — the browser's state mirror.\n const staleNames = clearedSessionCookieNames(ref, (name) => request.cookies.has(name));\n\n if (outcome.kind === 'terminal') {\n for (const name of staleNames) request.cookies.delete(name);\n const response = opts?.response ?? NextResponse.next({ request });\n for (const name of staleNames) {\n response.cookies.set(name, '', { ...SESSION_COOKIE_ATTRS, maxAge: 0 });\n }\n response.headers.set('cache-control', 'private, no-store');\n return response;\n }\n\n const write = encodeSessionCookiesDecoded(ref, outcome.session);\n for (const name of staleNames) request.cookies.delete(name);\n for (const { name, value } of write.set) request.cookies.set(name, value);\n for (const name of write.clear) request.cookies.delete(name);\n // Build AFTER the request-cookie mutation: NextResponse.next({ request })\n // snapshots the request headers for the downstream RSC render.\n const response = opts?.response ?? NextResponse.next({ request });\n const written = new Set(write.set.map((c) => c.name));\n for (const { name, value } of write.set) {\n response.cookies.set(name, value, SESSION_COOKIE_ATTRS);\n }\n // Browser-side cleanup: stale names not part of the new run (a shrunken /\n // grown chunk layout) + the codec's one-past-the-end overflow guard.\n for (const name of new Set([...write.clear, ...staleNames])) {\n if (!written.has(name)) {\n response.cookies.set(name, '', { ...SESSION_COOKIE_ATTRS, maxAge: 0 });\n }\n }\n response.headers.set('cache-control', 'private, no-store');\n return response;\n}\n","/**\n * pbServer — the per-request server client of the Next.js adapter.\n *\n * Every call builds a FRESH runtime over the request's cookie store and\n * returns a runtime-BOUND `PB` client: typed namespaces, `call`, `upload`\n * and `auth` all resolve that runtime, never the process-global slot — two\n * bound clients serving concurrent requests cannot leak each other's\n * sessions (see createBoundClient). The store itself is read lazily per\n * adapter operation, so nothing is snapshotted beyond the call.\n *\n * MODULE-GRAPH RULE (same as ./index.ts): 'next/headers' is imported ONLY\n * lazily inside the default-store path — importing this module, and using\n * pbServer with an injected store, must work without next installed.\n */\nimport { BackendError } from '../errors.js';\nimport { buildRuntime, createBoundClient } from '../internal.js';\nimport type { PB } from '../pb.js';\nimport type { PersistedSession, SessionStorageAdapter } from '../storage.js';\nimport {\n clearedSessionCookieNames,\n decodeSessionCookies,\n encodeSessionCookiesDecoded,\n endpointRefFromApiKey,\n SESSION_COOKIE_ATTRS,\n} from './cookie-codec.js';\nimport { requireGlobalConfig } from './shared.js';\n\n/**\n * Structural slice of Next's request cookie store (`await cookies()`); any\n * object honoring it works — the seam for tests and non-Next servers.\n * `set`/`delete` are optional because RSC-scope stores are read-only.\n */\nexport interface CookieStoreLike {\n get(name: string): { name: string; value: string } | undefined;\n getAll?(): Array<{ name: string; value: string }>;\n set?(name: string, value: string, options?: Record<string, unknown>): void;\n delete?(name: string): void;\n}\n\nfunction nextRequired(cause: unknown): BackendError {\n const detail = cause instanceof Error && cause.message ? ` (${cause.message})` : '';\n return new BackendError('validation', {\n code: 'next_required',\n message:\n 'pbServer() could not resolve a Next.js request cookie store: call it inside a Server Component, Server Action or Route Handler — or pass a store explicitly via pbServer({ cookies })' +\n `${detail}.`,\n });\n}\n\n/**\n * Next CONTROL-FLOW errors must pass through UNWRAPPED. During static\n * prerender (`next build`) `cookies()` throws DynamicServerError (digest\n * 'DYNAMIC_SERVER_USAGE'), which Next catches upstream to mark the route\n * dynamic — wrapping it into a BackendError would turn that bailout signal\n * into a real prerender error and FAIL THE BUILD of every page calling\n * pbServer (caught live in the P3 Next smoke). 'NEXT_'-prefixed digests are\n * the same sentinel family (redirect / not-found / static-gen bailout).\n * Genuine outside-request-scope errors carry no digest and still map to\n * next_required.\n */\nexport function isNextControlFlowError(err: unknown): boolean {\n if (typeof err !== 'object' || err === null) return false;\n const digest = (err as { digest?: unknown }).digest;\n return (\n typeof digest === 'string' && (digest === 'DYNAMIC_SERVER_USAGE' || digest.startsWith('NEXT_'))\n );\n}\n\n/** Lazy default store: `await (await import('next/headers')).cookies()`. */\nasync function nextCookieStore(): Promise<CookieStoreLike> {\n let cookies: () => Promise<CookieStoreLike>;\n try {\n ({ cookies } = await import('next/headers'));\n } catch (cause) {\n throw nextRequired(cause); // next not installed / not resolvable\n }\n try {\n return await cookies();\n } catch (cause) {\n if (isNextControlFlowError(cause)) throw cause; // static-prerender bailout etc.\n throw nextRequired(cause); // installed, but outside a request scope\n }\n}\n\n/** Delete one cookie: set-with-maxAge-0 when the store can set (parity with the browser side), else delete, else swallow (read-only RSC store). */\nfunction removeCookie(store: CookieStoreLike, name: string): void {\n try {\n if (store.set) store.set(name, '', { ...SESSION_COOKIE_ATTRS, maxAge: 0 });\n else store.delete?.(name);\n } catch {\n // RSC read-only store — cookie mutation is the middleware's job there\n }\n}\n\n/**\n * SessionStorageAdapter over the request cookie store.\n *\n * SAVE SEMANTICS (decision, documented): only FULL sessions (access token +\n * expiry present) are written; a refresh-only save is SKIPPED with no throw\n * rather than written as {a:'',e:0}. The cookie is SHARED with the browser —\n * degrading it would drop an access token the browser may still be using and\n * force a refresh per page-load. The refresh-only branch is a defensive\n * legacy path anyway: every successful refresh saves a full session.\n *\n * All writes swallow per-cookie failures: in RSC scope Next's store throws\n * on mutation; the request still proceeds with the in-memory session but the\n * rotated cookie is NOT persisted. palbeMiddleware is therefore REQUIRED —\n * not optional — for session-bearing RSC apps: without it every RSC render\n * re-refreshes from the SAME cookie refresh token, and once two such\n * refreshes land more than 30s apart (outside palauth's rotation grace) the\n * reuse detector REVOKES THE WHOLE TOKEN FAMILY — the user is\n * force-logged-out everywhere.\n *\n * Values are written DECODED (encodeSessionCookiesDecoded): Next's real\n * cookies() store percent-encodes on serialization, yielding exactly the\n * shared-codec wire bytes; a raw store (tests, custom servers) persists the\n * bare JSON, which the load path's decode tolerates identically (tokens are\n * %-free base64url, so decodeURIComponent is the identity on them).\n */\nfunction serverCookieAdapter(store: CookieStoreLike, endpointRef: string): SessionStorageAdapter {\n const present = (name: string): boolean => store.get(name) !== undefined;\n return {\n load(): PersistedSession | null {\n const stored = decodeSessionCookies((name) => store.get(name)?.value, endpointRef);\n if (!stored) return null;\n // A browser-side refresh-only write round-trips as a:'' / e:0 —\n // normalize to the legacy shape so hydration takes the expired-trick.\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 (!session.accessToken || !session.expiresAt) return; // see SAVE SEMANTICS above\n for (const name of clearedSessionCookieNames(endpointRef, present)) {\n removeCookie(store, name);\n }\n const { set, clear } = encodeSessionCookiesDecoded(endpointRef, {\n accessToken: session.accessToken,\n refreshToken: session.refreshToken,\n expiresAt: session.expiresAt,\n });\n for (const { name, value } of set) {\n try {\n store.set?.(name, value, { ...SESSION_COOKIE_ATTRS });\n } catch {\n // RSC read-only store\n }\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) removeCookie(store, name);\n },\n clear(): void {\n for (const name of clearedSessionCookieNames(endpointRef, present)) {\n removeCookie(store, name);\n }\n },\n };\n}\n\n/**\n * Build a per-request `PB` client over the request's cookies. Reads the\n * session the browser SDK wrote (shared cookie codec), refreshes pre-flight\n * when expired, and — where the store is writable (Server Actions, Route\n * Handlers) — persists the rotated session back.\n *\n * Each call builds a fresh runtime (a handful of small objects, no I/O) —\n * cheap enough to call per data access; code paths invoking it many times\n * within one request MAY memoize per-request (e.g. React's `cache()`), but\n * don't have to.\n *\n * ```ts\n * const pb = await pbServer();\n * const todos = await pb.todos.list();\n * ```\n */\nexport async function pbServer(opts?: { cookies?: CookieStoreLike }): Promise<PB> {\n const config = requireGlobalConfig(\n 'import the generated palbe.gen.ts once in app/layout.tsx — the root-layout import configures Server Components and Route Handlers too.',\n );\n const store = opts?.cookies ?? (await nextCookieStore());\n const ref = endpointRefFromApiKey(config.apiKey);\n const rt = buildRuntime({ ...config, storage: serverCookieAdapter(store, ref) });\n return createBoundClient(rt);\n}\n"],"mappings":"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","names":["response","response"]}
1
+ {"version":3,"sources":["../../src/next/shared.ts","../../src/next/callback.ts","../../src/next/middleware.ts","../../src/next/server.ts"],"sourcesContent":["/**\n * Cross-surface helpers for the palbe/next server entries (pbServer,\n * palbeMiddleware, handleAuthCallback): global-config lookup with a\n * surface-specific guided error, and the lazy 'next/server' import.\n */\nimport type { PalbeConfig } from '../config.js';\nimport { BackendError } from '../errors.js';\nimport { getRuntime } from '../internal.js';\n\n/**\n * Global config with a surface-specific guided error when absent. Each\n * surface names the import location that configures ITS module graph —\n * Next bundles middleware separately from the server graph, so the hint\n * matters (layout.tsx for Server Components / Route Handlers, middleware.ts\n * for the middleware).\n */\nexport function requireGlobalConfig(hint: string): PalbeConfig {\n try {\n return getRuntime().config;\n } catch {\n throw new BackendError('notConfigured', {\n code: 'not_configured',\n message: `Palbe is not configured in this module graph. Run 'palbase web link' and ${hint}`,\n });\n }\n}\n\nlet nextServerModule: Promise<typeof import('next/server')> | undefined;\n\n/**\n * Lazy 'next/server' import (MODULE-GRAPH RULE: never top-level — importing\n * palbe/next must work without next installed) with a guided failure.\n * The module promise is memoized: bundler dynamic-import machinery can take\n * macrotask-scale hops PER CALL, so without the cache two near-simultaneous\n * middleware invocations could straddle a refresh — every call after the\n * first now resolves in pure microtasks.\n */\nexport async function importNextServer(caller: string): Promise<typeof import('next/server')> {\n nextServerModule ??= import('next/server');\n try {\n return await nextServerModule;\n } catch (cause) {\n nextServerModule = undefined; // never poison later calls with a cached rejection\n const detail = cause instanceof Error && cause.message ? ` (${cause.message})` : '';\n throw new BackendError('validation', {\n code: 'next_required',\n message: `${caller}() requires Next.js — 'next/server' could not be resolved${detail}.`,\n });\n }\n}\n","/**\n * handleAuthCallback — the OAuth completion route handler factory.\n *\n * The app's redirect_uri (registered when calling signInWithOAuth with\n * `redirectTo: '<app>/auth/callback?provider=google&next=/dash'`) lands\n * here with `?code&state` from the provider. The handler exchanges them\n * SERVER-SIDE against palauth (PKCE verifier + state live server-side; the\n * browser never holds them), writes the session cookies onto a redirect\n * response, and sends the user on.\n *\n * ```ts\n * // app/auth/callback/route.ts\n * import { handleAuthCallback } from '@palbase/web/next';\n * export const GET = handleAuthCallback({ defaultNext: '/' });\n * ```\n *\n * MODULE-GRAPH RULE (same as ./index.ts): 'next/server' only lazily; the\n * type-only NextRequest import erases at build time.\n */\nimport type { NextRequest } from 'next/server';\nimport { asWireAuthResult } from '../auth-wire.js';\nimport { encodeSessionCookiesDecoded, SESSION_COOKIE_ATTRS } from './cookie-codec.js';\nimport { importNextServer, requireGlobalConfig } from './shared.js';\n\nexport interface HandleAuthCallbackOptions {\n /** Where to land when the callback carries no (valid) `next` param — and on every error/MFA redirect. Default '/'. */\n defaultNext?: string;\n}\n\n/**\n * Open-redirect guard: `next` rides the OAuth redirect querystring, so it is\n * attacker-influencable — only same-origin, path-absolute relative paths are\n * honored, and the post-auth victim is never sent off-origin.\n *\n * A leading-'/' heuristic is NOT enough. The value is later resolved with\n * `new URL(next, base)`, and the WHATWG URL parser STRIPS ASCII tab (0x09),\n * LF (0x0A) and CR (0x0D) before parsing — so `/<TAB>/evil.com` slips past a\n * \"next[1] is not '/'\" check yet parses to `//evil.com` → `https://evil.com`\n * (CWE-601 open redirect). We defend with TWO independent gates that must\n * BOTH pass, matching OWASP unvalidated-redirect guidance:\n *\n * 1. RAW-STRING gate (reject before normalization can hide the payload):\n * - reject any C0 control char (\\x00-\\x1F, incl. \\t \\n \\r) or other\n * whitespace — these are exactly what URL parsing strips/normalizes\n * away;\n * - require a path-absolute prefix: a single '/' NOT followed by '/' or\n * '\\\\' (blocks '//host' protocol-relative and '/\\\\host' backslash\n * tricks);\n * - reject a scheme: any ':' appearing before the first '/' ('javascript:',\n * 'https:'). Path-absolute inputs start with '/', so this also rejects\n * bare 'foo:bar'.\n * 2. CANONICAL gate: resolve `new URL(next, origin)` and require the result\n * to land on the SAME origin. This is the authoritative check — it sees\n * exactly what the browser will, after normalization.\n *\n * Anything ambiguous returns null so the caller falls back to a safe default.\n */\nfunction safeNextPath(next: string | null, origin: string): string | null {\n if (!next) return null;\n // 1a. No control chars / whitespace — URL parsing would strip these and\n // change what the path means (the \\t \\n \\r open-redirect class).\n // biome-ignore lint/suspicious/noControlCharactersInRegex: rejecting C0 is the point of the guard.\n if (/[\\u0000-\\u0020\\u007f\\s]/.test(next)) return null;\n // 1b. Must be path-absolute: a single leading '/', not '//' or '/\\\\'.\n if (next[0] !== '/' || next[1] === '/' || next[1] === '\\\\') return null;\n // 1c. No scheme before the first path separator (defense in depth; a\n // path-absolute string can't carry one, but reject explicitly).\n const firstSlash = next.indexOf('/');\n const firstColon = next.indexOf(':');\n if (firstColon !== -1 && firstColon < firstSlash) return null;\n // 2. Canonical same-origin check — resolve as the browser/redirect helper\n // will and confirm we never leave this origin.\n try {\n if (new URL(next, origin).origin !== origin) return null;\n } catch {\n return null;\n }\n return next;\n}\n\nfunction wireErrorCode(raw: unknown): string {\n if (typeof raw === 'object' && raw !== null) {\n const code = (raw as Record<string, unknown>).error;\n if (typeof code === 'string' && code !== '') return code;\n }\n return 'oauth_exchange_failed';\n}\n\n/**\n * Build the callback route handler. Outcomes (all 307 redirects, all with\n * `Cache-Control: private, no-store` — auth outcomes must never cache):\n * - provider `error` param → `?auth_error=<error>` (+ `auth_error_description`)\n * - missing code/state/provider → `?auth_error=invalid_callback`\n * - exchanged AuthResult → session cookies on the redirect to `next ?? defaultNext ?? '/'`\n * - MFA union → `?mfa_token=…&mfa_factors=a,b` on defaultNext, NO cookies\n * - exchange failure → `?auth_error=<wire code | oauth_exchange_failed>`\n */\nexport function handleAuthCallback(\n opts?: HandleAuthCallbackOptions,\n): (request: NextRequest) => Promise<Response> {\n return async (request) => {\n const config = requireGlobalConfig(\n 'import the generated palbe.gen.ts once in app/layout.tsx — route handlers share the server module graph with the root layout.',\n );\n const { NextResponse } = await importNextServer('handleAuthCallback');\n const fallback = opts?.defaultNext ?? '/';\n\n const redirect = (path: string, query?: Record<string, string>) => {\n const url = new URL(path, request.nextUrl);\n for (const [key, value] of Object.entries(query ?? {})) url.searchParams.set(key, value);\n const response = NextResponse.redirect(url); // 307 — the callback GET stays a GET\n response.headers.set('cache-control', 'private, no-store');\n return response;\n };\n\n const params = request.nextUrl.searchParams;\n const providerError = params.get('error');\n if (providerError) {\n const query: Record<string, string> = { auth_error: providerError };\n const description = params.get('error_description');\n if (description) query.auth_error_description = description;\n return redirect(fallback, query);\n }\n\n const code = params.get('code');\n const state = params.get('state');\n const provider = params.get('provider');\n if (!code || !state || !provider) {\n return redirect(fallback, { auth_error: 'invalid_callback' });\n }\n\n let exchange: Response;\n try {\n exchange = await fetch(\n `${config.url}/auth/oauth/${encodeURIComponent(provider)}/callback` +\n `?code=${encodeURIComponent(code)}&state=${encodeURIComponent(state)}`,\n { headers: { apikey: config.apiKey } },\n );\n } catch {\n return redirect(fallback, { auth_error: 'oauth_exchange_failed' });\n }\n let raw: unknown = null;\n try {\n raw = await exchange.json();\n } catch {\n // malformed body — the shape checks below turn this into auth_error\n }\n if (!exchange.ok) return redirect(fallback, { auth_error: wireErrorCode(raw) });\n\n if (typeof raw === 'object' && raw !== null) {\n const obj = raw as Record<string, unknown>;\n // MFA union: relay the challenge to the app — NO cookies until it completes.\n if (obj.mfa_required === true && typeof obj.mfa_token === 'string') {\n const factors = Array.isArray(obj.mfa_factors)\n ? obj.mfa_factors.filter((f): f is string => typeof f === 'string')\n : [];\n return redirect(fallback, { mfa_token: obj.mfa_token, mfa_factors: factors.join(',') });\n }\n }\n\n // Zombie-session guard (shared with the auth facade): cookies are only\n // ever written for a FULLY-proven AuthResult.\n const wire = asWireAuthResult(raw);\n if (!wire) return redirect(fallback, { auth_error: 'oauth_exchange_failed' });\n\n const response = redirect(safeNextPath(params.get('next'), request.nextUrl.origin) ?? fallback);\n // DECODED codec values: NextResponse.cookies percent-encodes on write,\n // producing exactly the shared-codec wire bytes (encodeSessionCookiesDecoded).\n const write = encodeSessionCookiesDecoded(config.environmentRef, {\n accessToken: wire.access_token,\n refreshToken: wire.refresh_token,\n expiresAt: Date.now() + wire.expires_in * 1000,\n });\n for (const { name, value } of write.set) {\n response.cookies.set(name, value, SESSION_COOKIE_ATTRS);\n }\n // Codec overflow guard: expire one-past-the-end of the written run.\n for (const name of write.clear) {\n response.cookies.set(name, '', { ...SESSION_COOKIE_ATTRS, maxAge: 0 });\n }\n return response;\n };\n}\n","/**\n * palbeMiddleware — proactive cookie-session refresh in Next.js middleware.\n *\n * REQUIRED — not optional — for session-bearing RSC apps. Server Components\n * cannot write cookies, so pbServer's reactive refresh cannot PERSIST a\n * rotated session there: every RSC render would re-refresh from the SAME\n * cookie refresh token, and once two of those land more than 30s apart\n * (outside palauth's rotation grace) the reuse detector REVOKES THE WHOLE\n * TOKEN FAMILY — the user is force-logged-out everywhere. This middleware\n * refreshes the cookie BEFORE the RSC tree renders, so pbServer hydrates a\n * still-valid session and never burns the token itself.\n *\n * MODULE-GRAPH RULES (same as ./index.ts): 'next/server' is imported only\n * lazily (the type-only NextRequest/NextResponse imports erase at build\n * time), and middleware.ts must import the generated palbe.gen.ts itself —\n * Next bundles middleware as its OWN module graph; the layout.tsx import\n * does not reach it.\n *\n * ```ts\n * // middleware.ts\n * import './palbe.gen';\n * import { palbeMiddleware } from '@palbase/web/next';\n * import type { NextRequest } from 'next/server';\n *\n * export function middleware(request: NextRequest) {\n * return palbeMiddleware(request);\n * }\n * export const config = { matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'] };\n * ```\n */\nimport type { NextRequest, NextResponse } from 'next/server';\nimport type { PalbeConfig } from '../config.js';\nimport {\n clearedSessionCookieNames,\n decodeSessionCookies,\n encodeSessionCookiesDecoded,\n SESSION_COOKIE_ATTRS,\n type StoredSession,\n} from './cookie-codec.js';\nimport { importNextServer, requireGlobalConfig } from './shared.js';\n\nconst DEFAULT_REFRESH_MARGIN_MS = 60_000;\n\nexport interface PalbeMiddlewareOptions {\n /** Refresh when the access token expires within this window. Default 60s. */\n refreshMarginMs?: number;\n /**\n * Pre-built response to decorate (e.g. from chained middleware) instead of\n * building `NextResponse.next({ request })`. Pass-through cases return it\n * UNMODIFIED. Caveat: a pre-built response snapshotted the request headers\n * at ITS creation, so a rotated cookie reaches the browser (Set-Cookie)\n * but not the downstream RSC render of THIS request — prefer omitting this\n * and building your response after palbeMiddleware when possible.\n */\n response?: NextResponse;\n}\n\ntype RefreshOutcome =\n | { kind: 'rotated'; session: StoredSession }\n | { kind: 'terminal' } // 400/401/403 — refresh token dead, sign out\n | { kind: 'transient' }; // network / 5xx / malformed — keep the session\n\n/**\n * Per-process single-flight: concurrent middleware invocations holding the\n * SAME refresh token (parallel tabs / prefetches) share one refresh call —\n * a per-token thundering herd would race palauth rotation. Multi-pod\n * concurrency is covered by palauth's 30s rotation grace (concurrent\n * refreshes of one token all succeed); per-process dedup is all that's\n * needed here (Studio precedent — don't over-engineer).\n */\nconst inflightRefreshes = new Map<string, Promise<RefreshOutcome>>();\n\nfunction refreshSingleFlight(config: PalbeConfig, refreshToken: string): Promise<RefreshOutcome> {\n const existing = inflightRefreshes.get(refreshToken);\n if (existing) return existing;\n const pending = refresh(config, refreshToken).finally(() => {\n inflightRefreshes.delete(refreshToken);\n });\n inflightRefreshes.set(refreshToken, pending);\n return pending;\n}\n\n/** Direct palauth refresh call (no runtime: middleware needs only this one wire). */\nasync function refresh(config: PalbeConfig, refreshToken: string): Promise<RefreshOutcome> {\n try {\n const res = await fetch(`${config.url}/auth/token/refresh`, {\n method: 'POST',\n headers: { apikey: config.apiKey, 'content-type': 'application/json' },\n body: JSON.stringify({ refresh_token: refreshToken }),\n });\n if (res.status === 400 || res.status === 401 || res.status === 403) {\n return { kind: 'terminal' };\n }\n if (!res.ok) return { kind: 'transient' };\n const raw: unknown = await res.json();\n if (typeof raw === 'object' && raw !== null) {\n const obj = raw as Record<string, unknown>;\n if (\n typeof obj.access_token === 'string' &&\n typeof obj.refresh_token === 'string' &&\n typeof obj.expires_in === 'number'\n ) {\n return {\n kind: 'rotated',\n session: {\n accessToken: obj.access_token,\n refreshToken: obj.refresh_token,\n expiresAt: Date.now() + obj.expires_in * 1000,\n },\n };\n }\n }\n return { kind: 'transient' }; // malformed 200 — never destroy a session over it\n } catch {\n return { kind: 'transient' }; // network failure\n }\n}\n\n/**\n * Keep the session cookie fresh for the request. No session / still-fresh\n * session → untouched pass-through (no cache-control changes). Stale or\n * expired → single-flight refresh, then the rotated (or cleared, on a dead\n * token) cookies are written onto BOTH the request (for the downstream RSC\n * render via `NextResponse.next({ request })`) and the response (for the\n * browser), with `Cache-Control: private, no-store` on touched responses.\n *\n * Cookie writes go through Next's cookie APIs with the DECODED codec values:\n * Next percent-encodes on serialization, so the wire bytes come out exactly\n * as the shared codec's (see encodeSessionCookiesDecoded). NextRequest's\n * cookie store is NOT a CookieStoreLike (its set is the 2-arg/RequestCookie\n * form), hence the direct codec calls here instead of the pbServer adapter.\n */\nexport async function palbeMiddleware(\n request: NextRequest,\n opts?: PalbeMiddlewareOptions,\n): Promise<NextResponse> {\n const config = requireGlobalConfig(\n 'import the generated palbe.gen.ts at the top of middleware.ts — Next bundles middleware as its own module graph, so the layout.tsx import does not reach it.',\n );\n const { NextResponse } = await importNextServer('palbeMiddleware');\n const passThrough = (): NextResponse => opts?.response ?? NextResponse.next({ request });\n\n const ref = config.environmentRef;\n const session = decodeSessionCookies((name) => request.cookies.get(name)?.value, ref);\n if (!session) return passThrough();\n if (session.expiresAt - Date.now() > (opts?.refreshMarginMs ?? DEFAULT_REFRESH_MARGIN_MS)) {\n return passThrough();\n }\n\n const outcome = await refreshSingleFlight(config, session.refreshToken);\n if (outcome.kind === 'transient') return passThrough(); // keep the session over blips\n\n // Session-cookie names in the incoming jar — the browser's state mirror.\n const staleNames = clearedSessionCookieNames(ref, (name) => request.cookies.has(name));\n\n if (outcome.kind === 'terminal') {\n for (const name of staleNames) request.cookies.delete(name);\n const response = opts?.response ?? NextResponse.next({ request });\n for (const name of staleNames) {\n response.cookies.set(name, '', { ...SESSION_COOKIE_ATTRS, maxAge: 0 });\n }\n response.headers.set('cache-control', 'private, no-store');\n return response;\n }\n\n const write = encodeSessionCookiesDecoded(ref, outcome.session);\n for (const name of staleNames) request.cookies.delete(name);\n for (const { name, value } of write.set) request.cookies.set(name, value);\n for (const name of write.clear) request.cookies.delete(name);\n // Build AFTER the request-cookie mutation: NextResponse.next({ request })\n // snapshots the request headers for the downstream RSC render.\n const response = opts?.response ?? NextResponse.next({ request });\n const written = new Set(write.set.map((c) => c.name));\n for (const { name, value } of write.set) {\n response.cookies.set(name, value, SESSION_COOKIE_ATTRS);\n }\n // Browser-side cleanup: stale names not part of the new run (a shrunken /\n // grown chunk layout) + the codec's one-past-the-end overflow guard.\n for (const name of new Set([...write.clear, ...staleNames])) {\n if (!written.has(name)) {\n response.cookies.set(name, '', { ...SESSION_COOKIE_ATTRS, maxAge: 0 });\n }\n }\n response.headers.set('cache-control', 'private, no-store');\n return response;\n}\n","/**\n * pbServer — the per-request server client of the Next.js adapter.\n *\n * Every call builds a FRESH runtime over the request's cookie store and\n * returns a runtime-BOUND `PB` client: typed namespaces, `call`, `upload`\n * and `auth` all resolve that runtime, never the process-global slot — two\n * bound clients serving concurrent requests cannot leak each other's\n * sessions (see createBoundClient). The store itself is read lazily per\n * adapter operation, so nothing is snapshotted beyond the call.\n *\n * MODULE-GRAPH RULE (same as ./index.ts): 'next/headers' is imported ONLY\n * lazily inside the default-store path — importing this module, and using\n * pbServer with an injected store, must work without next installed.\n */\nimport { BackendError } from '../errors.js';\nimport { buildRuntime, createBoundClient } from '../internal.js';\nimport type { PB } from '../pb.js';\nimport type { PersistedSession, SessionStorageAdapter } from '../storage.js';\nimport {\n clearedSessionCookieNames,\n decodeSessionCookies,\n encodeSessionCookiesDecoded,\n SESSION_COOKIE_ATTRS,\n} from './cookie-codec.js';\nimport { requireGlobalConfig } from './shared.js';\n\n/**\n * Structural slice of Next's request cookie store (`await cookies()`); any\n * object honoring it works — the seam for tests and non-Next servers.\n * `set`/`delete` are optional because RSC-scope stores are read-only.\n */\nexport interface CookieStoreLike {\n get(name: string): { name: string; value: string } | undefined;\n getAll?(): Array<{ name: string; value: string }>;\n set?(name: string, value: string, options?: Record<string, unknown>): void;\n delete?(name: string): void;\n}\n\nfunction nextRequired(cause: unknown): BackendError {\n const detail = cause instanceof Error && cause.message ? ` (${cause.message})` : '';\n return new BackendError('validation', {\n code: 'next_required',\n message:\n 'pbServer() could not resolve a Next.js request cookie store: call it inside a Server Component, Server Action or Route Handler — or pass a store explicitly via pbServer({ cookies })' +\n `${detail}.`,\n });\n}\n\n/**\n * Next CONTROL-FLOW errors must pass through UNWRAPPED. During static\n * prerender (`next build`) `cookies()` throws DynamicServerError (digest\n * 'DYNAMIC_SERVER_USAGE'), which Next catches upstream to mark the route\n * dynamic — wrapping it into a BackendError would turn that bailout signal\n * into a real prerender error and FAIL THE BUILD of every page calling\n * pbServer (caught live in the P3 Next smoke). 'NEXT_'-prefixed digests are\n * the same sentinel family (redirect / not-found / static-gen bailout).\n * Genuine outside-request-scope errors carry no digest and still map to\n * next_required.\n */\nexport function isNextControlFlowError(err: unknown): boolean {\n if (typeof err !== 'object' || err === null) return false;\n const digest = (err as { digest?: unknown }).digest;\n return (\n typeof digest === 'string' && (digest === 'DYNAMIC_SERVER_USAGE' || digest.startsWith('NEXT_'))\n );\n}\n\n/** Lazy default store: `await (await import('next/headers')).cookies()`. */\nasync function nextCookieStore(): Promise<CookieStoreLike> {\n let cookies: () => Promise<CookieStoreLike>;\n try {\n ({ cookies } = await import('next/headers'));\n } catch (cause) {\n throw nextRequired(cause); // next not installed / not resolvable\n }\n try {\n return await cookies();\n } catch (cause) {\n if (isNextControlFlowError(cause)) throw cause; // static-prerender bailout etc.\n throw nextRequired(cause); // installed, but outside a request scope\n }\n}\n\n/** Delete one cookie: set-with-maxAge-0 when the store can set (parity with the browser side), else delete, else swallow (read-only RSC store). */\nfunction removeCookie(store: CookieStoreLike, name: string): void {\n try {\n if (store.set) store.set(name, '', { ...SESSION_COOKIE_ATTRS, maxAge: 0 });\n else store.delete?.(name);\n } catch {\n // RSC read-only store — cookie mutation is the middleware's job there\n }\n}\n\n/**\n * SessionStorageAdapter over the request cookie store.\n *\n * SAVE SEMANTICS (decision, documented): only FULL sessions (access token +\n * expiry present) are written; a refresh-only save is SKIPPED with no throw\n * rather than written as {a:'',e:0}. The cookie is SHARED with the browser —\n * degrading it would drop an access token the browser may still be using and\n * force a refresh per page-load. The refresh-only branch is a defensive\n * legacy path anyway: every successful refresh saves a full session.\n *\n * All writes swallow per-cookie failures: in RSC scope Next's store throws\n * on mutation; the request still proceeds with the in-memory session but the\n * rotated cookie is NOT persisted. palbeMiddleware is therefore REQUIRED —\n * not optional — for session-bearing RSC apps: without it every RSC render\n * re-refreshes from the SAME cookie refresh token, and once two such\n * refreshes land more than 30s apart (outside palauth's rotation grace) the\n * reuse detector REVOKES THE WHOLE TOKEN FAMILY — the user is\n * force-logged-out everywhere.\n *\n * Values are written DECODED (encodeSessionCookiesDecoded): Next's real\n * cookies() store percent-encodes on serialization, yielding exactly the\n * shared-codec wire bytes; a raw store (tests, custom servers) persists the\n * bare JSON, which the load path's decode tolerates identically (tokens are\n * %-free base64url, so decodeURIComponent is the identity on them).\n */\nfunction serverCookieAdapter(\n store: CookieStoreLike,\n environmentRef: string,\n): SessionStorageAdapter {\n const present = (name: string): boolean => store.get(name) !== undefined;\n return {\n load(): PersistedSession | null {\n const stored = decodeSessionCookies((name) => store.get(name)?.value, environmentRef);\n if (!stored) return null;\n // A browser-side refresh-only write round-trips as a:'' / e:0 —\n // normalize to the legacy shape so hydration takes the expired-trick.\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 (!session.accessToken || !session.expiresAt) return; // see SAVE SEMANTICS above\n for (const name of clearedSessionCookieNames(environmentRef, present)) {\n removeCookie(store, name);\n }\n const { set, clear } = encodeSessionCookiesDecoded(environmentRef, {\n accessToken: session.accessToken,\n refreshToken: session.refreshToken,\n expiresAt: session.expiresAt,\n });\n for (const { name, value } of set) {\n try {\n store.set?.(name, value, { ...SESSION_COOKIE_ATTRS });\n } catch {\n // RSC read-only store\n }\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) removeCookie(store, name);\n },\n clear(): void {\n for (const name of clearedSessionCookieNames(environmentRef, present)) {\n removeCookie(store, name);\n }\n },\n };\n}\n\n/**\n * Build a per-request `PB` client over the request's cookies. Reads the\n * session the browser SDK wrote (shared cookie codec), refreshes pre-flight\n * when expired, and — where the store is writable (Server Actions, Route\n * Handlers) — persists the rotated session back.\n *\n * Each call builds a fresh runtime (a handful of small objects, no I/O) —\n * cheap enough to call per data access; code paths invoking it many times\n * within one request MAY memoize per-request (e.g. React's `cache()`), but\n * don't have to.\n *\n * ```ts\n * const pb = await pbServer();\n * const todos = await pb.todos.list();\n * ```\n */\nexport async function pbServer(opts?: { cookies?: CookieStoreLike }): Promise<PB> {\n const config = requireGlobalConfig(\n 'import the generated palbe.gen.ts once in app/layout.tsx — the root-layout import configures Server Components and Route Handlers too.',\n );\n const store = opts?.cookies ?? (await nextCookieStore());\n const ref = config.environmentRef;\n const rt = buildRuntime({ ...config, storage: serverCookieAdapter(store, ref) });\n return createBoundClient(rt);\n}\n"],"mappings":"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","names":["response","response"]}
@@ -1,4 +1,4 @@
1
- import { x as PalbeAuth, z as PalbeFlags, E as PalbeRealtime, w as PalbeAnalytics, y as PalbeCalls, B as PalbeMessaging, W as PalbePerf, d as PalbeRuntime } from './analytics-facade-ChlBRcLZ.cjs';
1
+ import { x as PalbeAuth, z as PalbeFlags, E as PalbeRealtime, w as PalbeAnalytics, y as PalbeCalls, B as PalbeMessaging, W as PalbePerf, d as PalbeRuntime } from './analytics-facade-BOxQ8IP2.cjs';
2
2
 
3
3
  interface CallOptions {
4
4
  headers?: Record<string, string>;
@@ -1,4 +1,4 @@
1
- import { x as PalbeAuth, z as PalbeFlags, E as PalbeRealtime, w as PalbeAnalytics, y as PalbeCalls, B as PalbeMessaging, W as PalbePerf, d as PalbeRuntime } from './analytics-facade-G0il4NrT.js';
1
+ import { x as PalbeAuth, z as PalbeFlags, E as PalbeRealtime, w as PalbeAnalytics, y as PalbeCalls, B as PalbeMessaging, W as PalbePerf, d as PalbeRuntime } from './analytics-facade-yfMJ69vw.js';
2
2
 
3
3
  interface CallOptions {
4
4
  headers?: Record<string, string>;
@@ -349,7 +349,7 @@ function applyBrowserOriginHeader(headers) {
349
349
  }
350
350
 
351
351
  // src/version.ts
352
- var VERSION = "2.0.1";
352
+ var VERSION = "3.0.0";
353
353
 
354
354
  // src/call.ts
355
355
  async function callEndpoint(resolveRt, name, input, options) {