@supabase/server 0.1.0-alpha.1 → 0.1.1-rc.25

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.
@@ -0,0 +1,227 @@
1
+ import { SupabaseClient } from "@supabase/supabase-js";
2
+
3
+ //#region src/types.d.ts
4
+ /**
5
+ * Authentication mode that determines what credentials a request must provide.
6
+ *
7
+ * - `"always"` — No credentials required. Every request is accepted.
8
+ * - `"public"` — Requires a valid publishable key in the `apikey` header.
9
+ * - `"secret"` — Requires a valid secret key in the `apikey` header (timing-safe comparison).
10
+ * - `"user"` — Requires a valid JWT in the `Authorization: Bearer <token>` header.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * // Single mode
15
+ * withSupabase({ allow: 'user' }, handler)
16
+ *
17
+ * // Multiple modes — the first match wins
18
+ * withSupabase({ allow: ['user', 'public'] }, handler)
19
+ * ```
20
+ */
21
+ type Allow = 'always' | 'public' | 'secret' | 'user';
22
+ /**
23
+ * Extended auth mode that supports targeting a specific named key.
24
+ *
25
+ * Use the colon syntax (`"public:web_app"`) to require a specific named key
26
+ * from the `SUPABASE_PUBLISHABLE_KEYS` or `SUPABASE_SECRET_KEYS` JSON object.
27
+ * Use `"public:*"` or `"secret:*"` to accept any key in the set.
28
+ *
29
+ * @example
30
+ * ```ts
31
+ * // Accept only the "mobile" publishable key
32
+ * withSupabase({ allow: 'public:mobile' }, handler)
33
+ *
34
+ * // Accept any secret key
35
+ * withSupabase({ allow: 'secret:*' }, handler)
36
+ *
37
+ * // Mix named keys with other modes
38
+ * withSupabase({ allow: ['user', 'public:web_app'] }, handler)
39
+ * ```
40
+ */
41
+ type AllowWithKey = Allow | `public:${string}` | `secret:${string}`;
42
+ /**
43
+ * Resolved Supabase environment configuration.
44
+ *
45
+ * Holds the project URL, API keys, and JWKS needed by every other primitive.
46
+ * Typically resolved automatically from environment variables by {@link resolveEnv},
47
+ * but can be passed explicitly via the `env` option.
48
+ *
49
+ * @see {@link resolveEnv} for how each field maps to environment variables.
50
+ */
51
+ interface SupabaseEnv {
52
+ /** Supabase project URL (e.g. `"https://<ref>.supabase.co"`). Sourced from `SUPABASE_URL`. */
53
+ url: string;
54
+ /**
55
+ * Named publishable (anon) keys. Sourced from `SUPABASE_PUBLISHABLE_KEYS` (JSON object)
56
+ * or `SUPABASE_PUBLISHABLE_KEY` (single key, stored as `{ default: "<value>" }`).
57
+ */
58
+ publishableKeys: Record<string, string>;
59
+ /**
60
+ * Named secret (service-role) keys. Sourced from `SUPABASE_SECRET_KEYS` (JSON object)
61
+ * or `SUPABASE_SECRET_KEY` (single key, stored as `{ default: "<value>" }`).
62
+ */
63
+ secretKeys: Record<string, string>;
64
+ /**
65
+ * JSON Web Key Set used for JWT verification. Sourced from `SUPABASE_JWKS`.
66
+ * Accepts both `{ keys: [...] }` and bare `[...]` array formats.
67
+ * `null` when no JWKS is configured (JWT verification will be unavailable).
68
+ */
69
+ jwks: JsonWebKeySet | null;
70
+ }
71
+ /**
72
+ * A JSON Web Key Set as defined by RFC 7517.
73
+ *
74
+ * @see https://datatracker.ietf.org/doc/html/rfc7517
75
+ */
76
+ interface JsonWebKeySet {
77
+ /** Array of JSON Web Keys. */
78
+ keys: JsonWebKey[];
79
+ }
80
+ /**
81
+ * Raw credentials extracted from an incoming HTTP request.
82
+ *
83
+ * Produced by {@link extractCredentials} from the `Authorization` and `apikey` headers.
84
+ *
85
+ * @see {@link extractCredentials}
86
+ */
87
+ interface Credentials {
88
+ /** Bearer token from the `Authorization: Bearer <token>` header, or `null` if absent. */
89
+ token: string | null;
90
+ /** API key from the `apikey` header, or `null` if absent. */
91
+ apikey: string | null;
92
+ }
93
+ /**
94
+ * Result of credential verification.
95
+ *
96
+ * Contains the resolved auth mode, the verified token (for `"user"` mode),
97
+ * decoded JWT claims, and the matched key name (for `"public"` / `"secret"` modes).
98
+ *
99
+ * @see {@link verifyCredentials}
100
+ * @see {@link verifyAuth}
101
+ */
102
+ interface AuthResult {
103
+ /** The auth mode that was successfully matched. */
104
+ authType: Allow;
105
+ /** The verified JWT, or `null` for non-user auth modes. */
106
+ token: string | null;
107
+ /** Normalized user identity derived from the JWT, or `null` when no JWT is present. */
108
+ userClaims: UserClaims | null;
109
+ /** Raw JWT payload, or `null` when no JWT is present. */
110
+ claims: JWTClaims | null;
111
+ /** Name of the matched key (e.g. `"default"`, `"mobile"`), or `null` for `"user"` / `"always"` modes. */
112
+ keyName?: string | null;
113
+ }
114
+ /**
115
+ * Standard JWT claims as defined by RFC 7519, extended with Supabase-specific fields.
116
+ *
117
+ * This is the raw JWT payload — use {@link UserClaims} for a normalized, camelCase view.
118
+ *
119
+ * @see https://datatracker.ietf.org/doc/html/rfc7519#section-4.1
120
+ */
121
+ interface JWTClaims {
122
+ /** Subject — the user's unique ID. */
123
+ sub: string;
124
+ /** Issuer — typically your Supabase project URL. */
125
+ iss?: string;
126
+ /** Audience — who the token is intended for. */
127
+ aud?: string | string[];
128
+ /** Expiration time (seconds since epoch). */
129
+ exp?: number;
130
+ /** Issued at (seconds since epoch). */
131
+ iat?: number;
132
+ /** Supabase role (e.g. `"authenticated"`, `"anon"`). */
133
+ role?: string;
134
+ /** User's email address from Supabase Auth. */
135
+ email?: string;
136
+ /** Application-level metadata set via Supabase Auth admin APIs. */
137
+ app_metadata?: Record<string, unknown>;
138
+ /** User-editable metadata set via Supabase Auth. */
139
+ user_metadata?: Record<string, unknown>;
140
+ /** Additional custom claims. */
141
+ [key: string]: unknown;
142
+ }
143
+ /**
144
+ * Normalized, camelCase view of the authenticated user's identity.
145
+ *
146
+ * Derived from {@link JWTClaims}. For the full Supabase `User` object
147
+ * (including email confirmation status, providers, etc.), call
148
+ * `supabase.auth.getUser()` using the context client.
149
+ */
150
+ interface UserClaims {
151
+ /** User's unique ID (same as `JWTClaims.sub`). */
152
+ id: string;
153
+ /** Supabase role (e.g. `"authenticated"`). */
154
+ role?: string;
155
+ /** User's email address. */
156
+ email?: string;
157
+ /** Application-level metadata (e.g. roles, permissions). */
158
+ appMetadata?: Record<string, unknown>;
159
+ /** User-editable profile metadata (e.g. display name, avatar). */
160
+ userMetadata?: Record<string, unknown>;
161
+ }
162
+ /**
163
+ * Configuration for {@link withSupabase} and {@link createSupabaseContext}.
164
+ *
165
+ * Controls which auth modes are accepted, environment overrides, and CORS behavior.
166
+ *
167
+ * @example
168
+ * ```ts
169
+ * // Require authenticated users, auto-CORS enabled (default)
170
+ * const config: WithSupabaseConfig = { allow: 'user' }
171
+ *
172
+ * // Accept users or service-to-service calls, custom CORS headers
173
+ * const config: WithSupabaseConfig = {
174
+ * allow: ['user', 'secret'],
175
+ * cors: { 'Access-Control-Allow-Origin': 'https://myapp.com' },
176
+ * }
177
+ *
178
+ * // No auth required, CORS disabled
179
+ * const config: WithSupabaseConfig = { allow: 'always', cors: false }
180
+ * ```
181
+ */
182
+ interface WithSupabaseConfig {
183
+ /**
184
+ * Auth mode(s) to accept. Modes are tried in order — the first match wins.
185
+ *
186
+ * @defaultValue `"user"`
187
+ */
188
+ allow?: AllowWithKey | AllowWithKey[];
189
+ /**
190
+ * Override auto-detected environment variables. Useful for testing
191
+ * or when running in environments without standard env var support.
192
+ */
193
+ env?: Partial<SupabaseEnv>;
194
+ /**
195
+ * CORS configuration for the `withSupabase` wrapper.
196
+ *
197
+ * - `true` (default) — uses `@supabase/supabase-js` default CORS headers.
198
+ * - `false` — disables CORS handling entirely.
199
+ * - `Record<string, string>` — custom CORS headers.
200
+ *
201
+ * @remarks Only applies to the top-level {@link withSupabase} wrapper.
202
+ * The Hono adapter handles CORS separately via Hono's own middleware.
203
+ *
204
+ * @defaultValue `true`
205
+ */
206
+ cors?: boolean | Record<string, string>;
207
+ }
208
+ /**
209
+ * The Supabase context created for each authenticated request.
210
+ *
211
+ * Contains pre-configured Supabase clients and the caller's identity.
212
+ * Identical regardless of which layer or adapter produced it.
213
+ */
214
+ interface SupabaseContext<Database = unknown> {
215
+ /** Supabase client scoped to the caller's identity. RLS policies apply. */
216
+ supabase: SupabaseClient<Database>;
217
+ /** Admin Supabase client that bypasses Row-Level Security. */
218
+ supabaseAdmin: SupabaseClient<Database>;
219
+ /** JWT-derived identity. For the full Supabase User object, call `supabase.auth.getUser()`. */
220
+ userClaims: UserClaims | null;
221
+ /** Raw JWT payload. `null` for non-user auth modes. */
222
+ claims: JWTClaims | null;
223
+ /** The auth mode that was used for this request. */
224
+ authType: Allow;
225
+ }
226
+ //#endregion
227
+ export { JWTClaims as a, UserClaims as c, Credentials as i, WithSupabaseConfig as l, AllowWithKey as n, SupabaseContext as o, AuthResult as r, SupabaseEnv as s, Allow as t };
@@ -0,0 +1,227 @@
1
+ import { SupabaseClient } from "@supabase/supabase-js";
2
+
3
+ //#region src/types.d.ts
4
+ /**
5
+ * Authentication mode that determines what credentials a request must provide.
6
+ *
7
+ * - `"always"` — No credentials required. Every request is accepted.
8
+ * - `"public"` — Requires a valid publishable key in the `apikey` header.
9
+ * - `"secret"` — Requires a valid secret key in the `apikey` header (timing-safe comparison).
10
+ * - `"user"` — Requires a valid JWT in the `Authorization: Bearer <token>` header.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * // Single mode
15
+ * withSupabase({ allow: 'user' }, handler)
16
+ *
17
+ * // Multiple modes — the first match wins
18
+ * withSupabase({ allow: ['user', 'public'] }, handler)
19
+ * ```
20
+ */
21
+ type Allow = 'always' | 'public' | 'secret' | 'user';
22
+ /**
23
+ * Extended auth mode that supports targeting a specific named key.
24
+ *
25
+ * Use the colon syntax (`"public:web_app"`) to require a specific named key
26
+ * from the `SUPABASE_PUBLISHABLE_KEYS` or `SUPABASE_SECRET_KEYS` JSON object.
27
+ * Use `"public:*"` or `"secret:*"` to accept any key in the set.
28
+ *
29
+ * @example
30
+ * ```ts
31
+ * // Accept only the "mobile" publishable key
32
+ * withSupabase({ allow: 'public:mobile' }, handler)
33
+ *
34
+ * // Accept any secret key
35
+ * withSupabase({ allow: 'secret:*' }, handler)
36
+ *
37
+ * // Mix named keys with other modes
38
+ * withSupabase({ allow: ['user', 'public:web_app'] }, handler)
39
+ * ```
40
+ */
41
+ type AllowWithKey = Allow | `public:${string}` | `secret:${string}`;
42
+ /**
43
+ * Resolved Supabase environment configuration.
44
+ *
45
+ * Holds the project URL, API keys, and JWKS needed by every other primitive.
46
+ * Typically resolved automatically from environment variables by {@link resolveEnv},
47
+ * but can be passed explicitly via the `env` option.
48
+ *
49
+ * @see {@link resolveEnv} for how each field maps to environment variables.
50
+ */
51
+ interface SupabaseEnv {
52
+ /** Supabase project URL (e.g. `"https://<ref>.supabase.co"`). Sourced from `SUPABASE_URL`. */
53
+ url: string;
54
+ /**
55
+ * Named publishable (anon) keys. Sourced from `SUPABASE_PUBLISHABLE_KEYS` (JSON object)
56
+ * or `SUPABASE_PUBLISHABLE_KEY` (single key, stored as `{ default: "<value>" }`).
57
+ */
58
+ publishableKeys: Record<string, string>;
59
+ /**
60
+ * Named secret (service-role) keys. Sourced from `SUPABASE_SECRET_KEYS` (JSON object)
61
+ * or `SUPABASE_SECRET_KEY` (single key, stored as `{ default: "<value>" }`).
62
+ */
63
+ secretKeys: Record<string, string>;
64
+ /**
65
+ * JSON Web Key Set used for JWT verification. Sourced from `SUPABASE_JWKS`.
66
+ * Accepts both `{ keys: [...] }` and bare `[...]` array formats.
67
+ * `null` when no JWKS is configured (JWT verification will be unavailable).
68
+ */
69
+ jwks: JsonWebKeySet | null;
70
+ }
71
+ /**
72
+ * A JSON Web Key Set as defined by RFC 7517.
73
+ *
74
+ * @see https://datatracker.ietf.org/doc/html/rfc7517
75
+ */
76
+ interface JsonWebKeySet {
77
+ /** Array of JSON Web Keys. */
78
+ keys: JsonWebKey[];
79
+ }
80
+ /**
81
+ * Raw credentials extracted from an incoming HTTP request.
82
+ *
83
+ * Produced by {@link extractCredentials} from the `Authorization` and `apikey` headers.
84
+ *
85
+ * @see {@link extractCredentials}
86
+ */
87
+ interface Credentials {
88
+ /** Bearer token from the `Authorization: Bearer <token>` header, or `null` if absent. */
89
+ token: string | null;
90
+ /** API key from the `apikey` header, or `null` if absent. */
91
+ apikey: string | null;
92
+ }
93
+ /**
94
+ * Result of credential verification.
95
+ *
96
+ * Contains the resolved auth mode, the verified token (for `"user"` mode),
97
+ * decoded JWT claims, and the matched key name (for `"public"` / `"secret"` modes).
98
+ *
99
+ * @see {@link verifyCredentials}
100
+ * @see {@link verifyAuth}
101
+ */
102
+ interface AuthResult {
103
+ /** The auth mode that was successfully matched. */
104
+ authType: Allow;
105
+ /** The verified JWT, or `null` for non-user auth modes. */
106
+ token: string | null;
107
+ /** Normalized user identity derived from the JWT, or `null` when no JWT is present. */
108
+ userClaims: UserClaims | null;
109
+ /** Raw JWT payload, or `null` when no JWT is present. */
110
+ claims: JWTClaims | null;
111
+ /** Name of the matched key (e.g. `"default"`, `"mobile"`), or `null` for `"user"` / `"always"` modes. */
112
+ keyName?: string | null;
113
+ }
114
+ /**
115
+ * Standard JWT claims as defined by RFC 7519, extended with Supabase-specific fields.
116
+ *
117
+ * This is the raw JWT payload — use {@link UserClaims} for a normalized, camelCase view.
118
+ *
119
+ * @see https://datatracker.ietf.org/doc/html/rfc7519#section-4.1
120
+ */
121
+ interface JWTClaims {
122
+ /** Subject — the user's unique ID. */
123
+ sub: string;
124
+ /** Issuer — typically your Supabase project URL. */
125
+ iss?: string;
126
+ /** Audience — who the token is intended for. */
127
+ aud?: string | string[];
128
+ /** Expiration time (seconds since epoch). */
129
+ exp?: number;
130
+ /** Issued at (seconds since epoch). */
131
+ iat?: number;
132
+ /** Supabase role (e.g. `"authenticated"`, `"anon"`). */
133
+ role?: string;
134
+ /** User's email address from Supabase Auth. */
135
+ email?: string;
136
+ /** Application-level metadata set via Supabase Auth admin APIs. */
137
+ app_metadata?: Record<string, unknown>;
138
+ /** User-editable metadata set via Supabase Auth. */
139
+ user_metadata?: Record<string, unknown>;
140
+ /** Additional custom claims. */
141
+ [key: string]: unknown;
142
+ }
143
+ /**
144
+ * Normalized, camelCase view of the authenticated user's identity.
145
+ *
146
+ * Derived from {@link JWTClaims}. For the full Supabase `User` object
147
+ * (including email confirmation status, providers, etc.), call
148
+ * `supabase.auth.getUser()` using the context client.
149
+ */
150
+ interface UserClaims {
151
+ /** User's unique ID (same as `JWTClaims.sub`). */
152
+ id: string;
153
+ /** Supabase role (e.g. `"authenticated"`). */
154
+ role?: string;
155
+ /** User's email address. */
156
+ email?: string;
157
+ /** Application-level metadata (e.g. roles, permissions). */
158
+ appMetadata?: Record<string, unknown>;
159
+ /** User-editable profile metadata (e.g. display name, avatar). */
160
+ userMetadata?: Record<string, unknown>;
161
+ }
162
+ /**
163
+ * Configuration for {@link withSupabase} and {@link createSupabaseContext}.
164
+ *
165
+ * Controls which auth modes are accepted, environment overrides, and CORS behavior.
166
+ *
167
+ * @example
168
+ * ```ts
169
+ * // Require authenticated users, auto-CORS enabled (default)
170
+ * const config: WithSupabaseConfig = { allow: 'user' }
171
+ *
172
+ * // Accept users or service-to-service calls, custom CORS headers
173
+ * const config: WithSupabaseConfig = {
174
+ * allow: ['user', 'secret'],
175
+ * cors: { 'Access-Control-Allow-Origin': 'https://myapp.com' },
176
+ * }
177
+ *
178
+ * // No auth required, CORS disabled
179
+ * const config: WithSupabaseConfig = { allow: 'always', cors: false }
180
+ * ```
181
+ */
182
+ interface WithSupabaseConfig {
183
+ /**
184
+ * Auth mode(s) to accept. Modes are tried in order — the first match wins.
185
+ *
186
+ * @defaultValue `"user"`
187
+ */
188
+ allow?: AllowWithKey | AllowWithKey[];
189
+ /**
190
+ * Override auto-detected environment variables. Useful for testing
191
+ * or when running in environments without standard env var support.
192
+ */
193
+ env?: Partial<SupabaseEnv>;
194
+ /**
195
+ * CORS configuration for the `withSupabase` wrapper.
196
+ *
197
+ * - `true` (default) — uses `@supabase/supabase-js` default CORS headers.
198
+ * - `false` — disables CORS handling entirely.
199
+ * - `Record<string, string>` — custom CORS headers.
200
+ *
201
+ * @remarks Only applies to the top-level {@link withSupabase} wrapper.
202
+ * The Hono adapter handles CORS separately via Hono's own middleware.
203
+ *
204
+ * @defaultValue `true`
205
+ */
206
+ cors?: boolean | Record<string, string>;
207
+ }
208
+ /**
209
+ * The Supabase context created for each authenticated request.
210
+ *
211
+ * Contains pre-configured Supabase clients and the caller's identity.
212
+ * Identical regardless of which layer or adapter produced it.
213
+ */
214
+ interface SupabaseContext<Database = unknown> {
215
+ /** Supabase client scoped to the caller's identity. RLS policies apply. */
216
+ supabase: SupabaseClient<Database>;
217
+ /** Admin Supabase client that bypasses Row-Level Security. */
218
+ supabaseAdmin: SupabaseClient<Database>;
219
+ /** JWT-derived identity. For the full Supabase User object, call `supabase.auth.getUser()`. */
220
+ userClaims: UserClaims | null;
221
+ /** Raw JWT payload. `null` for non-user auth modes. */
222
+ claims: JWTClaims | null;
223
+ /** The auth mode that was used for this request. */
224
+ authType: Allow;
225
+ }
226
+ //#endregion
227
+ export { JWTClaims as a, UserClaims as c, Credentials as i, WithSupabaseConfig as l, AllowWithKey as n, SupabaseContext as o, AuthResult as r, SupabaseEnv as s, Allow as t };