@ai-matrx/auth 0.0.0 → 0.1.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/CHANGELOG.md +25 -0
- package/LICENSE +21 -0
- package/README.md +31 -1
- package/dist/auth-cookie-DWx6Q3xo.d.cts +168 -0
- package/dist/auth-cookie-DWx6Q3xo.d.ts +168 -0
- package/dist/cookies.cjs +233 -0
- package/dist/cookies.d.cts +109 -0
- package/dist/cookies.d.ts +109 -0
- package/dist/cookies.js +210 -0
- package/dist/credentials.cjs +68 -0
- package/dist/credentials.d.cts +82 -0
- package/dist/credentials.d.ts +82 -0
- package/dist/credentials.js +47 -0
- package/dist/index.cjs +189 -0
- package/dist/index.d.cts +86 -0
- package/dist/index.d.ts +86 -0
- package/dist/index.js +166 -0
- package/dist/next.cjs +655 -0
- package/dist/next.d.cts +389 -0
- package/dist/next.d.ts +389 -0
- package/dist/next.js +637 -0
- package/dist/node.cjs +61 -0
- package/dist/node.d.cts +33 -0
- package/dist/node.d.ts +33 -0
- package/dist/node.js +36 -0
- package/dist/organizations.cjs +389 -0
- package/dist/organizations.d.cts +226 -0
- package/dist/organizations.d.ts +226 -0
- package/dist/organizations.js +366 -0
- package/dist/react.cjs +206 -0
- package/dist/react.d.cts +163 -0
- package/dist/react.d.ts +163 -0
- package/dist/react.js +186 -0
- package/dist/session-4rdIyV28.d.cts +102 -0
- package/dist/session-4rdIyV28.d.ts +102 -0
- package/dist/session-identity.cjs +125 -0
- package/dist/session-identity.d.cts +100 -0
- package/dist/session-identity.d.ts +100 -0
- package/dist/session-identity.js +104 -0
- package/dist/testing.cjs +67 -0
- package/dist/testing.d.cts +38 -0
- package/dist/testing.d.ts +38 -0
- package/dist/testing.js +46 -0
- package/package.json +186 -6
package/dist/next.d.ts
ADDED
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
import { createServerClient, createBrowserClient } from '@supabase/ssr';
|
|
2
|
+
import { b as AuthCookieValue, A as AuthCookie, a as AuthCookieOptions } from './auth-cookie-DWx6Q3xo.js';
|
|
3
|
+
export { C as CreateAuthCookieArgs, D as DEFAULT_AUTH_COOKIE_NAME, c as createAuthCookie } from './auth-cookie-DWx6Q3xo.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @ai-matrx/data/next — the Next.js Supabase binding.
|
|
7
|
+
*
|
|
8
|
+
* WHY THIS EXISTS (C22 / THE ALL-INCLUSIVE LAW): a Next.js app has FIVE
|
|
9
|
+
* distinct places that must construct a Supabase client — the browser, a
|
|
10
|
+
* Server Component, a Route Handler, the proxy/middleware, and an OAuth
|
|
11
|
+
* callback — and every one of them must pass the SAME auth-cookie options or
|
|
12
|
+
* it cannot see the session the others wrote. Before this module, matrx-frontend
|
|
13
|
+
* carried that construction five times, each with its own env guard, its own
|
|
14
|
+
* cookie adapter, and its own copy of the "do not run code between
|
|
15
|
+
* createServerClient and getUser()" hazard. Every app on the platform would
|
|
16
|
+
* have re-derived all five.
|
|
17
|
+
*
|
|
18
|
+
* The host now injects IDENTITY only — URL, publishable key, apex domain, the
|
|
19
|
+
* cookie names — and the package owns every hard part:
|
|
20
|
+
*
|
|
21
|
+
* - env validation with a named, actionable error (never `process.env.X!`,
|
|
22
|
+
* which fails as a cryptic `undefined.trim()` TypeError);
|
|
23
|
+
* - the domain-wide cookie option construction on every single door;
|
|
24
|
+
* - the SSR/browser split, including the Server-Component write that must be
|
|
25
|
+
* swallowed because only the proxy may set cookies there;
|
|
26
|
+
* - the browser singleton on a `globalThis` slot (module-level mutable state
|
|
27
|
+
* is banned — dual ESM/CJS bundles would otherwise instantiate two clients
|
|
28
|
+
* and split the session);
|
|
29
|
+
* - the middleware session dance in ONE call: legacy-key migration, the
|
|
30
|
+
* getUser() adjacency rule, session persistence under the new key, legacy
|
|
31
|
+
* cookie clearing at the issuing scope, the no-store response headers, and
|
|
32
|
+
* cookie carry-over onto redirects (dropping any one of these logs users
|
|
33
|
+
* out at random, which is exactly how it was found).
|
|
34
|
+
*
|
|
35
|
+
* NO `next/*` IMPORT LIVES HERE. Next's own primitives (`cookies()`,
|
|
36
|
+
* `NextResponse`) arrive through structural seams the host passes in, so this
|
|
37
|
+
* module builds and tests outside Next and cannot drag the framework into a
|
|
38
|
+
* non-Next consumer's graph.
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* A `Database` type as generated by Supabase. Deliberately structural: the
|
|
43
|
+
* package never imports a host's generated types, and a host that has not
|
|
44
|
+
* generated any still gets a working (untyped-rows) client.
|
|
45
|
+
*/
|
|
46
|
+
type DatabaseLike = Record<string, unknown>;
|
|
47
|
+
type NextBrowserClient<DB extends DatabaseLike> = ReturnType<typeof createBrowserClient<DB>>;
|
|
48
|
+
type NextServerClient<DB extends DatabaseLike> = ReturnType<typeof createServerClient<DB>>;
|
|
49
|
+
/** A cookie to write, as `@supabase/ssr` hands it to `setAll`. */
|
|
50
|
+
interface CookieToSet {
|
|
51
|
+
name: string;
|
|
52
|
+
value: string;
|
|
53
|
+
options?: Record<string, unknown> | undefined;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The subset of Next's `await cookies()` store this binding uses. Structural
|
|
57
|
+
* on purpose — `ReadonlyRequestCookies` satisfies it by shape.
|
|
58
|
+
*/
|
|
59
|
+
interface ServerCookieStore {
|
|
60
|
+
getAll(): readonly AuthCookieValue[];
|
|
61
|
+
set(name: string, value: string, options?: Record<string, unknown>): void;
|
|
62
|
+
}
|
|
63
|
+
/** The subset of `NextRequest["cookies"]` the middleware binding uses. */
|
|
64
|
+
interface RequestCookieJar {
|
|
65
|
+
getAll(): readonly AuthCookieValue[];
|
|
66
|
+
set(name: string, value: string): void;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* A cookie in Next's `ResponseCookies` shape: name, value, and every
|
|
70
|
+
* attribute FLAT on the same object.
|
|
71
|
+
*
|
|
72
|
+
* 🚨 THIS SHAPE IS LOAD-BEARING, and modelling it as `never` cost the platform
|
|
73
|
+
* a production outage (2026-09-01). `ResponseCookies.set` accepts either
|
|
74
|
+
* `(name, value, attrs)` or ONE flat object — it does NOT accept `@supabase/ssr`'s
|
|
75
|
+
* `{ name, value, options }`, and it does not throw on it either: it reads
|
|
76
|
+
* `name`/`value`, ignores the unknown `options` key, and serializes
|
|
77
|
+
* `sb-…-auth-v2.0=; Path=/`. Every attribute is lost. So:
|
|
78
|
+
* · a token refresh wrote a HOST-ONLY session cookie shadowing the real
|
|
79
|
+
* `.apex` one, and
|
|
80
|
+
* · every chunk REMOVAL (`value: ""`, `maxAge: 0`) became a PERSISTENT EMPTY
|
|
81
|
+
* host-only cookie instead of a deletion.
|
|
82
|
+
* Two same-name cookies then reach the server in one `Cookie` header, the
|
|
83
|
+
* empty one sorts first, `combineChunks`' `find()` takes it, and every server
|
|
84
|
+
* read answers anonymous while the tab still shows a signed-in user.
|
|
85
|
+
* `@supabase/ssr` cookies are converted with `toResponseCookie` at the single
|
|
86
|
+
* boundary below; the `never` that hid this is gone.
|
|
87
|
+
*/
|
|
88
|
+
interface ResponseCookie {
|
|
89
|
+
name: string;
|
|
90
|
+
value: string;
|
|
91
|
+
domain?: string | undefined;
|
|
92
|
+
path?: string | undefined;
|
|
93
|
+
maxAge?: number | undefined;
|
|
94
|
+
expires?: Date | number | undefined;
|
|
95
|
+
httpOnly?: boolean | undefined;
|
|
96
|
+
secure?: boolean | undefined;
|
|
97
|
+
sameSite?: boolean | "lax" | "strict" | "none" | undefined;
|
|
98
|
+
priority?: "low" | "medium" | "high" | undefined;
|
|
99
|
+
partitioned?: boolean | undefined;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* The subset of `NextResponse["cookies"]` the middleware binding uses.
|
|
103
|
+
*/
|
|
104
|
+
interface ResponseCookieJar {
|
|
105
|
+
getAll(): ResponseCookie[];
|
|
106
|
+
set(cookie: ResponseCookie): void;
|
|
107
|
+
}
|
|
108
|
+
/** The subset of a `NextResponse` the middleware binding drives. */
|
|
109
|
+
interface MiddlewareResponse {
|
|
110
|
+
cookies: ResponseCookieJar;
|
|
111
|
+
headers: {
|
|
112
|
+
get(name: string): string | null;
|
|
113
|
+
set(name: string, value: string): void;
|
|
114
|
+
/**
|
|
115
|
+
* Required for the split-jar heal. `ResponseCookies` keeps ONE entry per
|
|
116
|
+
* cookie NAME, so the same name cannot be expired at two Domain scopes
|
|
117
|
+
* through it — the second `set` replaces the first. The losing scope is
|
|
118
|
+
* expired with raw appended `Set-Cookie` headers instead.
|
|
119
|
+
*/
|
|
120
|
+
append(name: string, value: string): void;
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
interface NextSupabaseConfig {
|
|
124
|
+
/**
|
|
125
|
+
* `process.env.NEXT_PUBLIC_SUPABASE_URL` — read STATICALLY at the call site.
|
|
126
|
+
* Next only inlines `NEXT_PUBLIC_*` into client bundles for static member
|
|
127
|
+
* accesses; a dynamic lookup inside this package would be `undefined` in
|
|
128
|
+
* every browser bundle.
|
|
129
|
+
*/
|
|
130
|
+
supabaseUrl: string | undefined;
|
|
131
|
+
/** `process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY`, read statically. */
|
|
132
|
+
publishableKey: string | undefined;
|
|
133
|
+
/** The apex domain one login must span, e.g. `"aimatrx.com"`. */
|
|
134
|
+
apexDomain: string;
|
|
135
|
+
/** Auth cookie name. Defaults to the package's `sb-matrx-auth`. */
|
|
136
|
+
cookieName?: string;
|
|
137
|
+
/** A superseded storage key to migrate from and then clear. */
|
|
138
|
+
legacyCookieName?: string;
|
|
139
|
+
/**
|
|
140
|
+
* Host wrapper applied to the BROWSER client only — the one legitimate
|
|
141
|
+
* host seam here (diagnostics/error capture). It must not change query
|
|
142
|
+
* behavior; the package never inspects what it returns.
|
|
143
|
+
*
|
|
144
|
+
* `C extends object` because a Supabase client always IS one, and a real
|
|
145
|
+
* capture wrapper is a `Proxy` that must constrain the same way. Leaving
|
|
146
|
+
* `C` unconstrained made every honest host wrapper unassignable (found at
|
|
147
|
+
* matrx-frontend adoption, 0.5.1).
|
|
148
|
+
*/
|
|
149
|
+
wrapBrowserClient?: <C extends object>(client: C) => C;
|
|
150
|
+
}
|
|
151
|
+
/** Cache-defeating headers every auth-cookie-bearing response must carry. */
|
|
152
|
+
declare const AUTH_COOKIE_RESPONSE_HEADERS: Readonly<Record<string, string>>;
|
|
153
|
+
/**
|
|
154
|
+
* Stamped on any response whose auth cookie jar was found split and healed.
|
|
155
|
+
* A shell that already rendered may be wearing an identity this pass could not
|
|
156
|
+
* see, and must say so rather than paint a signed-in screen of anonymous data.
|
|
157
|
+
*/
|
|
158
|
+
declare const SPLIT_COOKIE_JAR_HEADER = "x-matrx-split-jar";
|
|
159
|
+
/**
|
|
160
|
+
* Stamped when this request's auth cookie jar held one storage key BOTH
|
|
161
|
+
* unchunked and chunked — see `AuthCookie.reconcile`. Distinct from
|
|
162
|
+
* `SPLIT_COOKIE_JAR_HEADER` because the person's experience is different and
|
|
163
|
+
* the screen must say the true thing:
|
|
164
|
+
*
|
|
165
|
+
* split jar → the tab still holds a session; the server just could not
|
|
166
|
+
* read it. "Sign in again" restores the page.
|
|
167
|
+
* ambiguous → we deliberately refused BOTH copies rather than risk
|
|
168
|
+
* resolving the wrong person, so this person has just been
|
|
169
|
+
* signed out BY US. That is an automatic intervention on
|
|
170
|
+
* somebody's session and it must not happen quietly: the
|
|
171
|
+
* browser's own read is anonymous too, so nothing else on the
|
|
172
|
+
* page can notice, and without this header the app shows a
|
|
173
|
+
* login screen with no explanation.
|
|
174
|
+
*/
|
|
175
|
+
declare const AMBIGUOUS_AUTH_COOKIE_HEADER = "x-matrx-auth-ambiguous";
|
|
176
|
+
/**
|
|
177
|
+
* `@supabase/ssr`'s `{ name, value, options }` → Next's flat `ResponseCookie`.
|
|
178
|
+
* The ONE conversion boundary; see {@link ResponseCookie} for what skipping it
|
|
179
|
+
* cost.
|
|
180
|
+
*/
|
|
181
|
+
declare function toResponseCookie(cookie: CookieToSet): ResponseCookie;
|
|
182
|
+
/**
|
|
183
|
+
* A `ResponseCookie` as a raw `Set-Cookie` header value, serialized the way
|
|
184
|
+
* Next's `ResponseCookies` serializes it. Needed because a response can only
|
|
185
|
+
* carry ONE entry per cookie NAME through `.cookies`, and `@supabase/ssr`
|
|
186
|
+
* deliberately writes some names TWICE — see `applyCookies`.
|
|
187
|
+
*/
|
|
188
|
+
declare function serializeSetCookie(cookie: ResponseCookie): string;
|
|
189
|
+
/**
|
|
190
|
+
* Thrown when identity is missing. Named and actionable — the alternative
|
|
191
|
+
* (`process.env.X!`) surfaces as `Cannot read properties of undefined
|
|
192
|
+
* (reading 'trim')` from inside Supabase, which taught nobody anything.
|
|
193
|
+
*/
|
|
194
|
+
declare class MissingSupabaseIdentityError extends Error {
|
|
195
|
+
readonly variable: string;
|
|
196
|
+
constructor(variable: string);
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* ONE budget for the WHOLE identity resolve of a request, not one per socket.
|
|
200
|
+
*
|
|
201
|
+
* The 0.17.0 budget aborted each `/auth/v1/` socket at 2.5s. That was not
|
|
202
|
+
* enough, and 2026-09-21 proved it: auth-js retries a token refresh with
|
|
203
|
+
* exponential backoff for up to 30s (`AUTO_REFRESH_TICK_DURATION_MS`), and a
|
|
204
|
+
* per-socket abort is exactly the retryable error that keeps that loop going —
|
|
205
|
+
* five aborted attempts plus their pauses is ~15.5s, past Vercel's 15s task
|
|
206
|
+
* cap, and the proxy answered `504` while believing it had a budget.
|
|
207
|
+
*
|
|
208
|
+
* This wrapper holds a deadline from the FIRST identity call. While the
|
|
209
|
+
* deadline is open every identity call gets what is LEFT of it, aborting the
|
|
210
|
+
* socket (a `Promise.race` would leave it hanging and holding the Lambda).
|
|
211
|
+
* The moment an attempt aborts, or the deadline passes, the budget is
|
|
212
|
+
* EXHAUSTED and every further identity call answers synchronously with a
|
|
213
|
+
* synthetic `408 auth_budget_exhausted` — a non-retryable auth error — so
|
|
214
|
+
* auth-js stops its loop at once instead of sleeping through it. The whole
|
|
215
|
+
* resolve therefore costs at most the budget plus one 200ms backoff.
|
|
216
|
+
*
|
|
217
|
+
* `exhausted` is also the cookie gate: an exhausted budget must never write,
|
|
218
|
+
* expire or heal a cookie, because auth-js clears the session on a
|
|
219
|
+
* non-retryable refresh failure once the access token has truly expired, and
|
|
220
|
+
* that write is a logout caused by a slow network.
|
|
221
|
+
*/
|
|
222
|
+
interface AuthBudget {
|
|
223
|
+
fetch: typeof fetch;
|
|
224
|
+
readonly exhausted: boolean;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* 🚨 A REFRESH THAT WAS SENT IS NEVER ABANDONED AT THE BUDGET (2026-10-07).
|
|
228
|
+
*
|
|
229
|
+
* `grant_type=refresh_token` ROTATES the refresh token on the auth server the
|
|
230
|
+
* moment it is processed. Aborting it at 2.5s did not stop the rotation — it only
|
|
231
|
+
* threw away the new tokens, so no cookie was written and the browser kept a
|
|
232
|
+
* refresh token the server had already spent. Past GoTrue's reuse window that
|
|
233
|
+
* token is refused and the person is signed out (and a server-rendered read made
|
|
234
|
+
* on the dropped session went out as `anon`: their own chats answered "sign in").
|
|
235
|
+
* So a refresh, once on the wire, runs to completion and its answer is used,
|
|
236
|
+
* bounded only by this ceiling — below Vercel's 15s proxy cap. A refresh that has
|
|
237
|
+
* NOT been sent yet still obeys the budget (nothing rotated, nothing lost).
|
|
238
|
+
*/
|
|
239
|
+
declare const AUTH_REFRESH_CEILING_MS = 8000;
|
|
240
|
+
declare function createAuthBudget(timeoutMs: number, options?: {
|
|
241
|
+
refreshCeilingMs?: number;
|
|
242
|
+
}): AuthBudget;
|
|
243
|
+
interface MiddlewareSessionArgs<Response> {
|
|
244
|
+
/** `Host` header of the incoming request. */
|
|
245
|
+
host: string | null | undefined;
|
|
246
|
+
/** `request.cookies` */
|
|
247
|
+
requestCookies: RequestCookieJar;
|
|
248
|
+
/**
|
|
249
|
+
* The raw `Cookie` header (`request.headers.get("cookie")`). REQUIRED to
|
|
250
|
+
* detect and heal a split jar — `request.cookies` has already collapsed the
|
|
251
|
+
* duplicates. Without it this pass cannot see the shadow and cannot expire
|
|
252
|
+
* it, which is exactly how the "healed" 0.7.x build still left poisoned
|
|
253
|
+
* browsers poisoned.
|
|
254
|
+
*/
|
|
255
|
+
cookieHeader?: string | null | undefined;
|
|
256
|
+
/** `() => NextResponse.next({ request })` — a FRESH response each call. */
|
|
257
|
+
createResponse: () => Response;
|
|
258
|
+
/** `(url) => NextResponse.redirect(url)` */
|
|
259
|
+
createRedirect: (url: URL) => Response;
|
|
260
|
+
}
|
|
261
|
+
interface MiddlewareSession<DB extends DatabaseLike, Response> {
|
|
262
|
+
/**
|
|
263
|
+
* The validated user, or `null`. Resolved via `getClaims()` — a local
|
|
264
|
+
* cryptographic verification of the access token, not a `getSession()` read.
|
|
265
|
+
*
|
|
266
|
+
* `null` is ambiguous on its own: check `authUnavailable` before treating it
|
|
267
|
+
* as "signed out". A transport failure produces `null` too, and acting on
|
|
268
|
+
* that as a logout is how a network blink bounces a signed-in person.
|
|
269
|
+
*/
|
|
270
|
+
user: ({
|
|
271
|
+
id: string;
|
|
272
|
+
} & Record<string, unknown>) | null;
|
|
273
|
+
/** The client, in case the caller needs a further authenticated read. */
|
|
274
|
+
client: NextServerClient<DB>;
|
|
275
|
+
/** The response carrying every session cookie written during this pass. */
|
|
276
|
+
response: Response;
|
|
277
|
+
/**
|
|
278
|
+
* A redirect that CARRIES the session cookies and cache headers. Building a
|
|
279
|
+
* bare `NextResponse.redirect` here drops refreshed tokens on the floor and
|
|
280
|
+
* logs the user out on the next request.
|
|
281
|
+
*/
|
|
282
|
+
redirect(url: URL): Response;
|
|
283
|
+
/**
|
|
284
|
+
* `true` when this request arrived with the same auth cookie at two Domain
|
|
285
|
+
* scopes. The response heals the jar, but the SHELL that already rendered
|
|
286
|
+
* may be holding an identity this pass could not see — a host that renders
|
|
287
|
+
* a signed-in shell must say so in words rather than paint a signed-in
|
|
288
|
+
* screen full of anonymous data.
|
|
289
|
+
*/
|
|
290
|
+
splitCookieJar: boolean;
|
|
291
|
+
/**
|
|
292
|
+
* `true` when a storage key arrived BOTH unchunked and chunked and this pass
|
|
293
|
+
* therefore refused both copies rather than risk resolving the wrong person.
|
|
294
|
+
* The person has been signed out by us and must be told so.
|
|
295
|
+
*/
|
|
296
|
+
ambiguousAuthCookies: boolean;
|
|
297
|
+
/**
|
|
298
|
+
* `true` when the auth authority could not be REACHED inside the resolve
|
|
299
|
+
* budget, so this pass has no opinion about who this is.
|
|
300
|
+
*
|
|
301
|
+
* The contract when it is set: `user` is `null` but the person is NOT signed
|
|
302
|
+
* out, not one auth cookie was written, expired or healed, and the host must
|
|
303
|
+
* neither bounce to login nor paint a signed-out screen as if it were
|
|
304
|
+
* settled. Let the request through; the client resolves auth itself and the
|
|
305
|
+
* next request re-resolves it here.
|
|
306
|
+
*/
|
|
307
|
+
authUnavailable: boolean;
|
|
308
|
+
}
|
|
309
|
+
interface NextSupabase<DB extends DatabaseLike> {
|
|
310
|
+
/** The auth-cookie primitive this binding is built on. */
|
|
311
|
+
readonly authCookie: AuthCookie;
|
|
312
|
+
readonly cookieName: string;
|
|
313
|
+
optionsForHost(host: string | null | undefined): AuthCookieOptions;
|
|
314
|
+
browserOptions(): AuthCookieOptions;
|
|
315
|
+
/**
|
|
316
|
+
* The browser client. Memoized on a `globalThis` slot keyed by identity, so
|
|
317
|
+
* the ESM and CJS graphs of this package share ONE client and therefore one
|
|
318
|
+
* auth state — a per-module singleton would silently split them.
|
|
319
|
+
*/
|
|
320
|
+
browserClient(): NextBrowserClient<DB>;
|
|
321
|
+
/**
|
|
322
|
+
* A Server Component / Server Action client over `await cookies()`.
|
|
323
|
+
* Cookie writes from a Server Component are swallowed by design: only the
|
|
324
|
+
* proxy may set cookies there, and it refreshes the session anyway.
|
|
325
|
+
*/
|
|
326
|
+
serverClient(args: {
|
|
327
|
+
cookieStore: ServerCookieStore;
|
|
328
|
+
host: string | null | undefined;
|
|
329
|
+
/**
|
|
330
|
+
* The raw `Cookie` request header (`(await headers()).get("cookie")`).
|
|
331
|
+
* REQUIRED to see a split jar: `cookies()` collapses two same-name cookies
|
|
332
|
+
* to one before this code runs. Omitting it degrades this door to the
|
|
333
|
+
* collapsed view, where the surviving copy is whichever the browser sent
|
|
334
|
+
* last — a coin flip between the session and anonymous.
|
|
335
|
+
*/
|
|
336
|
+
cookieHeader?: string | null | undefined;
|
|
337
|
+
/**
|
|
338
|
+
* See `routeClient`'s `appendSetCookie` — Next's `cookies()` store keys by
|
|
339
|
+
* NAME exactly like `ResponseCookies`, so a two-scope removal collapses
|
|
340
|
+
* here too. A Route Handler that signs somebody in MUST pass this (buffer
|
|
341
|
+
* the headers and append them onto the response it returns, last).
|
|
342
|
+
* A Server Component has no response to append to and its writes are
|
|
343
|
+
* swallowed anyway, so it correctly passes nothing.
|
|
344
|
+
*/
|
|
345
|
+
appendSetCookie?: (header: string) => void;
|
|
346
|
+
}): NextServerClient<DB>;
|
|
347
|
+
/**
|
|
348
|
+
* A Route Handler client: reads the request's cookies, writes onto the
|
|
349
|
+
* response you are about to return.
|
|
350
|
+
*/
|
|
351
|
+
routeClient(args: {
|
|
352
|
+
requestCookies: Pick<RequestCookieJar, "getAll">;
|
|
353
|
+
setCookie: (cookie: CookieToSet) => void;
|
|
354
|
+
host: string | null | undefined;
|
|
355
|
+
/** See `serverClient` — same collapse, same requirement. */
|
|
356
|
+
cookieHeader?: string | null | undefined;
|
|
357
|
+
/**
|
|
358
|
+
* `(header) => response.headers.append("Set-Cookie", header)`.
|
|
359
|
+
*
|
|
360
|
+
* 🚨 REQUIRED ON ANY DOOR THAT SIGNS SOMEBODY IN. `@supabase/ssr` removes a
|
|
361
|
+
* cookie at BOTH Domain scopes by emitting the SAME name twice, and every
|
|
362
|
+
* jar a host can pass to `setCookie` — `NextResponse.cookies`, Next's
|
|
363
|
+
* `cookies()` store — keeps ONE entry per NAME, so the second write
|
|
364
|
+
* REPLACES the first and the `.apex` removal is silently lost. That is how
|
|
365
|
+
* a stale UNCHUNKED auth cookie survives beside a fresh CHUNKED pair, and
|
|
366
|
+
* `combineChunks` then serves the STALE one — the previous person's
|
|
367
|
+
* session, to the person who just signed in (2026-09-08, R-O3).
|
|
368
|
+
*
|
|
369
|
+
* With this seam the duplicate goes out as a raw header instead. Without
|
|
370
|
+
* it the drop is announced loudly rather than swallowed.
|
|
371
|
+
*
|
|
372
|
+
* THE CALLER'S OBLIGATION: `ResponseCookies.set` re-serializes the whole
|
|
373
|
+
* `Set-Cookie` list from its own map and DISCARDS raw appends made since.
|
|
374
|
+
* Nothing may touch `response.cookies` after a header appended here.
|
|
375
|
+
*/
|
|
376
|
+
appendSetCookie?: (header: string) => void;
|
|
377
|
+
}): NextServerClient<DB>;
|
|
378
|
+
/**
|
|
379
|
+
* THE middleware/proxy auth pass, entire. Runs legacy-key migration, builds
|
|
380
|
+
* the client, resolves `getUser()` with nothing in between, persists a
|
|
381
|
+
* migrated session under the current key, clears the superseded key at the
|
|
382
|
+
* scope this host issued it on, and stamps no-store headers on any response
|
|
383
|
+
* that carries cookies.
|
|
384
|
+
*/
|
|
385
|
+
middlewareSession<Response extends MiddlewareResponse>(args: MiddlewareSessionArgs<Response>): Promise<MiddlewareSession<DB, Response>>;
|
|
386
|
+
}
|
|
387
|
+
declare function createNextSupabase<DB extends DatabaseLike = DatabaseLike>(config: NextSupabaseConfig): NextSupabase<DB>;
|
|
388
|
+
|
|
389
|
+
export { AMBIGUOUS_AUTH_COOKIE_HEADER, AUTH_COOKIE_RESPONSE_HEADERS, AUTH_REFRESH_CEILING_MS, type AuthBudget, AuthCookie, AuthCookieOptions, AuthCookieValue, type CookieToSet, type DatabaseLike, type MiddlewareResponse, type MiddlewareSession, type MiddlewareSessionArgs, MissingSupabaseIdentityError, type NextBrowserClient, type NextServerClient, type NextSupabase, type NextSupabaseConfig, type RequestCookieJar, type ResponseCookie, type ResponseCookieJar, SPLIT_COOKIE_JAR_HEADER, type ServerCookieStore, createAuthBudget, createNextSupabase, serializeSetCookie, toResponseCookie };
|