@robelest/convex-auth 0.0.4-preview.23 → 0.0.4-preview.24

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 (72) hide show
  1. package/README.md +10 -11
  2. package/dist/component/index.js +2 -2
  3. package/dist/component/model.d.ts.map +1 -1
  4. package/dist/component/schema.d.ts +5 -5
  5. package/dist/component/server/auth.d.ts +103 -103
  6. package/dist/component/server/auth.d.ts.map +1 -1
  7. package/dist/component/server/auth.js +70 -68
  8. package/dist/component/server/auth.js.map +1 -1
  9. package/dist/component/server/context.js +53 -0
  10. package/dist/component/server/context.js.map +1 -0
  11. package/dist/component/server/core.js +2 -20
  12. package/dist/component/server/core.js.map +1 -1
  13. package/dist/component/server/device.js +1 -1
  14. package/dist/component/server/http.d.ts +85 -0
  15. package/dist/component/server/http.d.ts.map +1 -0
  16. package/dist/component/server/http.js +59 -1
  17. package/dist/component/server/http.js.map +1 -1
  18. package/dist/component/server/runtime.d.ts +4 -4
  19. package/dist/component/server/runtime.d.ts.map +1 -1
  20. package/dist/component/server/runtime.js +110 -109
  21. package/dist/component/server/runtime.js.map +1 -1
  22. package/dist/server/auth.d.ts +103 -103
  23. package/dist/server/auth.d.ts.map +1 -1
  24. package/dist/server/auth.js +70 -68
  25. package/dist/server/auth.js.map +1 -1
  26. package/dist/server/context.d.ts +1 -0
  27. package/dist/server/context.js +53 -0
  28. package/dist/server/context.js.map +1 -0
  29. package/dist/server/core.d.ts +3 -36
  30. package/dist/server/core.d.ts.map +1 -1
  31. package/dist/server/core.js +2 -20
  32. package/dist/server/core.js.map +1 -1
  33. package/dist/server/device.js +1 -1
  34. package/dist/server/http.d.ts +81 -3
  35. package/dist/server/http.d.ts.map +1 -1
  36. package/dist/server/http.js +59 -1
  37. package/dist/server/http.js.map +1 -1
  38. package/dist/server/index.d.ts +3 -2
  39. package/dist/server/index.js +2 -2
  40. package/dist/server/mounts.d.ts +7 -7
  41. package/dist/server/mounts.d.ts.map +1 -1
  42. package/dist/server/mounts.js +1 -1
  43. package/dist/server/mounts.js.map +1 -1
  44. package/dist/server/mutations/account.d.ts +6 -6
  45. package/dist/server/mutations/account.d.ts.map +1 -1
  46. package/dist/server/mutations/code.d.ts +12 -12
  47. package/dist/server/mutations/invalidate.d.ts +4 -4
  48. package/dist/server/mutations/invalidate.d.ts.map +1 -1
  49. package/dist/server/mutations/oauth.d.ts +7 -7
  50. package/dist/server/mutations/oauth.d.ts.map +1 -1
  51. package/dist/server/mutations/refresh.d.ts +3 -3
  52. package/dist/server/mutations/register.d.ts +9 -9
  53. package/dist/server/mutations/register.d.ts.map +1 -1
  54. package/dist/server/mutations/retrieve.d.ts +6 -6
  55. package/dist/server/mutations/signature.d.ts +4 -4
  56. package/dist/server/mutations/signin.d.ts +5 -5
  57. package/dist/server/mutations/signin.d.ts.map +1 -1
  58. package/dist/server/mutations/store.d.ts +77 -77
  59. package/dist/server/mutations/verify.d.ts +7 -7
  60. package/dist/server/runtime.d.ts +9 -9
  61. package/dist/server/runtime.d.ts.map +1 -1
  62. package/dist/server/runtime.js +110 -109
  63. package/dist/server/runtime.js.map +1 -1
  64. package/package.json +1 -1
  65. package/src/component/index.ts +8 -2
  66. package/src/server/auth.ts +183 -147
  67. package/src/server/context.ts +90 -0
  68. package/src/server/core.ts +5 -60
  69. package/src/server/http.ts +253 -0
  70. package/src/server/index.ts +8 -2
  71. package/src/server/mounts.ts +9 -6
  72. package/src/server/runtime.ts +287 -264
package/README.md CHANGED
@@ -20,7 +20,7 @@ one setup API, full TypeScript support.
20
20
  - **Groups, memberships, invites** — hierarchical multi-tenancy with roles.
21
21
  - **SSR support** — framework-agnostic httpOnly cookie API (SvelteKit, TanStack
22
22
  Start, Next.js).
23
- - **Context enrichment** — zero-boilerplate `ctx.auth.userId` via `AuthCtx`.
23
+ - **Context enrichment** — zero-boilerplate `ctx.auth.userId` via `auth.ctx()`.
24
24
 
25
25
  ## Install
26
26
 
@@ -105,11 +105,11 @@ import { auth } from "./auth";
105
105
 
106
106
  const convex = createBuilder<DataModel>();
107
107
 
108
+ // `auth.context(ctx)` resolves { userId, user, groupId, role, grants }
109
+ // and throws before the handler runs when unauthenticated.
108
110
  const withRequiredAuth = convex.createMiddleware<any, { auth: any }>(
109
111
  async (ctx, next) => {
110
- const userId = await auth.user.require(ctx);
111
- const user = await auth.user.get(ctx, userId);
112
- return next({ ...ctx, auth: { ...ctx.auth, userId, user } });
112
+ return next({ ...ctx, auth: await auth.context(ctx) });
113
113
  },
114
114
  );
115
115
 
@@ -117,19 +117,18 @@ export const query = convex.query().use(withRequiredAuth).extend(WithZod);
117
117
  export const mutation = convex.mutation().use(withRequiredAuth).extend(WithZod);
118
118
  ```
119
119
 
120
- `AuthCtx` from `@robelest/convex-auth/component` remains supported if your
121
- project already uses `convex-helpers`.
120
+ `auth.ctx()` works with `convex-helpers` and other custom builder setups.
122
121
 
123
122
  ## Providers
124
123
 
125
124
  | Provider | Import |
126
125
  | ----------------- | ----------------------------------------------------------------------- |
127
126
  | OAuth (Arctic) | `import { OAuth } from "@robelest/convex-auth/providers"` |
128
- | Password | `import { Password } from "@robelest/convex-auth/providers/password"` |
129
- | Passkey | `import { Passkey } from "@robelest/convex-auth/providers/passkey"` |
130
- | TOTP | `import { Totp } from "@robelest/convex-auth/providers/totp"` |
131
- | Phone/SMS | `import { phone } from "@robelest/convex-auth/providers/phone"` |
132
- | Anonymous | `import { Anonymous } from "@robelest/convex-auth/providers/anonymous"` |
127
+ | Password | `import { Password } from "@robelest/convex-auth/providers"` |
128
+ | Passkey | `import { Passkey } from "@robelest/convex-auth/providers"` |
129
+ | TOTP | `import { Totp } from "@robelest/convex-auth/providers"` |
130
+ | Phone/SMS | `import { Phone } from "@robelest/convex-auth/providers"` |
131
+ | Anonymous | `import { Anonymous } from "@robelest/convex-auth/providers"` |
133
132
  | Device (RFC 8628) | `import { Device } from "@robelest/convex-auth/providers"` |
134
133
 
135
134
  ## Enterprise
@@ -1,3 +1,3 @@
1
- import { AuthCtx, createAuth } from "./server/auth.js";
1
+ import { createAuth } from "./server/auth.js";
2
2
 
3
- export { AuthCtx, createAuth };
3
+ export { createAuth };
@@ -1 +1 @@
1
- {"version":3,"file":"model.d.ts","names":[],"sources":["../../src/component/model.ts"],"mappings":";;;cAqMa,gBAAA,mBAAgB,OAAA;cAI3B,gBAAA,CAAA,SAAA;;;;;;;;;;cAqBW,WAAA,mBAAW,OAAA;;;;UAatB,gBAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;cAEW,cAAA,mBAAc,OAAA;;;UAUzB,gBAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;cA8CW,UAAA,mBAAU,OAAA;;;;;;;;;;;;;UAcrB,gBAAA,CAAA,SAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAEW,cAAA,mBAAc,OAAA;WAUzB,gBAAA,CAAA,SAAA"}
1
+ {"version":3,"file":"model.d.ts","names":[],"sources":["../../src/component/model.ts"],"mappings":"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"}
@@ -15,10 +15,10 @@ declare const _default: convex_server66.SchemaDefinition<{
15
15
  * and multiple concurrent sessions.
16
16
  */
17
17
  User: convex_server66.TableDefinition<convex_values121.VObject<{
18
- phone?: string | undefined;
18
+ email?: string | undefined;
19
19
  extend?: any;
20
20
  name?: string | undefined;
21
- email?: string | undefined;
21
+ phone?: string | undefined;
22
22
  image?: string | undefined;
23
23
  emailVerificationTime?: number | undefined;
24
24
  phoneVerificationTime?: number | undefined;
@@ -32,7 +32,7 @@ declare const _default: convex_server66.SchemaDefinition<{
32
32
  phoneVerificationTime: convex_values121.VFloat64<number | undefined, "optional">;
33
33
  isAnonymous: convex_values121.VBoolean<boolean | undefined, "optional">;
34
34
  extend: convex_values121.VAny<any, "optional", string>;
35
- }, "required", "phone" | "extend" | "name" | "email" | "image" | "emailVerificationTime" | "phoneVerificationTime" | "isAnonymous" | `extend.${string}`>, {
35
+ }, "required", "email" | "extend" | "name" | "phone" | "image" | "emailVerificationTime" | "phoneVerificationTime" | "isAnonymous" | `extend.${string}`>, {
36
36
  email: ["email", "_creationTime"];
37
37
  email_verified: ["email", "emailVerificationTime", "_creationTime"];
38
38
  phone: ["phone", "_creationTime"];
@@ -336,9 +336,9 @@ declare const _default: convex_server66.SchemaDefinition<{
336
336
  * invite links where neither is known upfront.
337
337
  */
338
338
  GroupInvite: convex_server66.TableDefinition<convex_values121.VObject<{
339
+ email?: string | undefined;
339
340
  groupId?: convex_values121.GenericId<"Group"> | undefined;
340
341
  extend?: any;
341
- email?: string | undefined;
342
342
  role?: string | undefined;
343
343
  roleIds?: string[] | undefined;
344
344
  invitedByUserId?: convex_values121.GenericId<"User"> | undefined;
@@ -359,7 +359,7 @@ declare const _default: convex_server66.SchemaDefinition<{
359
359
  acceptedByUserId: convex_values121.VId<convex_values121.GenericId<"User"> | undefined, "optional">;
360
360
  acceptedTime: convex_values121.VFloat64<number | undefined, "optional">;
361
361
  extend: convex_values121.VAny<any, "optional", string>;
362
- }, "required", "groupId" | "extend" | "status" | "email" | `extend.${string}` | "role" | "roleIds" | "invitedByUserId" | "tokenHash" | "expiresTime" | "acceptedByUserId" | "acceptedTime">, {
362
+ }, "required", "email" | "groupId" | "extend" | "status" | `extend.${string}` | "role" | "roleIds" | "invitedByUserId" | "tokenHash" | "expiresTime" | "acceptedByUserId" | "acceptedTime">, {
363
363
  token_hash: ["tokenHash", "_creationTime"];
364
364
  status: ["status", "_creationTime"];
365
365
  email_status: ["email", "status", "_creationTime"];
@@ -87,9 +87,12 @@ type AuthApiBase<TAuthorization extends AuthAuthorizationConfig | undefined = un
87
87
  * this in fluent-convex middleware, custom wrappers, or anywhere you
88
88
  * need the current `{ userId, user, groupId, role, grants }` object.
89
89
  *
90
- * Throws a structured `ConvexError` when unauthenticated.
90
+ * Throws a structured `ConvexError` when unauthenticated by default.
91
+ * Pass `{ optional: true }` to get a null-shaped auth object instead.
91
92
  *
92
93
  * @param ctx - Convex query, mutation, or action context.
94
+ * @param config - Optional auth resolution config. Supports `optional`,
95
+ * `resolve`, and `authResolve`.
93
96
  * @returns The current auth context.
94
97
  *
95
98
  * @example fluent-convex middleware
@@ -100,12 +103,20 @@ type AuthApiBase<TAuthorization extends AuthAuthorizationConfig | undefined = un
100
103
  * ```
101
104
  *
102
105
  * @example Direct usage in a handler
103
- * ```ts
104
- * const authContext = await auth.context(ctx);
105
- * const { userId, grants } = authContext;
106
- * ```
107
- */
108
- context: (ctx: any) => Promise<AuthContext>;
106
+ * ```ts
107
+ * const authContext = await auth.context(ctx);
108
+ * const { userId, grants } = authContext;
109
+ * ```
110
+ *
111
+ * @example Optional usage
112
+ * ```ts
113
+ * const authContext = await auth.context(ctx, { optional: true });
114
+ * if (authContext.userId === null) {
115
+ * return null;
116
+ * }
117
+ * ```
118
+ */
119
+ context: AuthContextResolver;
109
120
  /**
110
121
  * Context enrichment for convex-helpers `customQuery` / `customMutation` /
111
122
  * `customAction`.
@@ -144,21 +155,13 @@ type AuthApiBase<TAuthorization extends AuthAuthorizationConfig | undefined = un
144
155
  * });
145
156
  * ```
146
157
  */
147
- ctx: () => {
148
- args: Record<string, never>;
149
- input: (ctx: any) => Promise<{
150
- ctx: {
151
- auth: AuthContext;
152
- };
153
- args: Record<string, never>;
154
- }>;
155
- };
158
+ ctx: AuthContextFactory;
156
159
  };
157
160
  /**
158
- * Current request auth context injected into `ctx.auth` by `auth.ctx()` and
159
- * {@link AuthCtx}. This is the authenticated auth shape returned by
160
- * {@link createAuth().context}. Optional context builders may still surface
161
- * nullable fields when `optional: true` is used.
161
+ * Current request auth context injected into `ctx.auth` by `auth.ctx()`. This
162
+ * is the authenticated auth shape returned by {@link createAuth().context}.
163
+ * Optional context builders may still surface nullable fields when
164
+ * `optional: true` is used.
162
165
  *
163
166
  * - `groupId` is `null` when the user has no active group set.
164
167
  * - `role` is `null` when no active group or no membership is resolved.
@@ -184,16 +187,59 @@ type AuthContext = {
184
187
  role: string | null; /** Resolved grant strings from the user's role definitions. */
185
188
  grants: string[];
186
189
  };
187
- type AuthCtxBase = {
190
+ /**
191
+ * Nullable auth context returned by `auth.context(ctx, { optional: true })`
192
+ * and injected by `auth.ctx({ optional: true })`.
193
+ *
194
+ * Use this when callers may be unauthenticated but you still want a stable
195
+ * auth-shaped object.
196
+ *
197
+ * - `userId` and `user` are `null` when unauthenticated.
198
+ * - `groupId` and `role` are `null` when no active group is resolved.
199
+ * - `grants` is `[]` when no membership is resolved.
200
+ *
201
+ * @example
202
+ * ```ts
203
+ * const authContext = await auth.context(ctx, { optional: true });
204
+ * if (authContext.userId === null) {
205
+ * return null;
206
+ * }
207
+ * ```
208
+ */
209
+ type OptionalAuthContext = {
210
+ /** The authenticated user's document ID, or `null` when unauthenticated. */userId: GenericId<"User"> | null; /** The authenticated user's full document, or `null` when unauthenticated. */
211
+ user: UserDoc | null; /** The user's active group ID, or `null` if none is set. */
212
+ groupId: string | null; /** The user's primary role in the active group, or `null`. */
213
+ role: string | null; /** Resolved grant strings for the active membership, or `[]`. */
214
+ grants: string[];
215
+ };
216
+ type AuthContextBase = {
188
217
  getUserIdentity: () => Promise<UserIdentity | null>;
189
218
  };
190
- type RequiredAuthCtxState = AuthCtxBase & AuthContext;
191
- type OptionalAuthCtxState = AuthCtxBase & {
192
- userId: GenericId<"User"> | null;
193
- user: UserDoc | null;
194
- groupId: string | null;
195
- role: string | null;
196
- grants: string[];
219
+ type RequiredAuthContextState = AuthContextBase & AuthContext;
220
+ type OptionalAuthContextState = AuthContextBase & OptionalAuthContext;
221
+ type ResolvedAuthContext<TResolve> = AuthContext & TResolve;
222
+ type ResolvedOptionalAuthContext<TResolve> = OptionalAuthContext & TResolve;
223
+ type AuthContextResolver = {
224
+ <TResolve extends Record<string, unknown> = Record<string, never>>(ctx: any, config: AuthContextConfig<TResolve> & {
225
+ optional: true;
226
+ }): Promise<ResolvedOptionalAuthContext<TResolve>>;
227
+ <TResolve extends Record<string, unknown> = Record<string, never>>(ctx: any, config?: AuthContextConfig<TResolve>): Promise<ResolvedAuthContext<TResolve>>;
228
+ };
229
+ type AuthContextCustomization<TAuth> = {
230
+ args: {};
231
+ input: (ctx: any, _args: any, _extra?: any) => Promise<{
232
+ ctx: {
233
+ auth: TAuth;
234
+ };
235
+ args: {};
236
+ }>;
237
+ };
238
+ type AuthContextFactory = {
239
+ <TResolve extends Record<string, unknown> = Record<string, never>>(config: AuthContextConfig<TResolve> & {
240
+ optional: true;
241
+ }): AuthContextCustomization<OptionalAuthContextState & TResolve>;
242
+ <TResolve extends Record<string, unknown> = Record<string, never>>(config?: AuthContextConfig<TResolve>): AuthContextCustomization<RequiredAuthContextState & TResolve>;
197
243
  };
198
244
  type InternalSsoApi = ReturnType<typeof Auth>["auth"]["sso"];
199
245
  type PublicSsoAdminApi = {
@@ -309,20 +355,38 @@ declare function createAuth<P extends AuthProviderConfig[], TAuthorization exten
309
355
  authorization?: TAuthorization;
310
356
  }): ConvexAuthResult<P, TAuthorization>;
311
357
  /**
312
- * Configuration for {@link AuthCtx} context enrichment.
358
+ * Configuration for {@link createAuth().ctx} context enrichment.
359
+ *
360
+ * The same config shape is also used by {@link createAuth().context}.
313
361
  *
314
362
  * @typeParam TResolve - Extra fields returned from `resolve()` and merged into
315
363
  * the resulting `ctx.auth` object.
364
+ *
365
+ * @example
366
+ * ```ts
367
+ * const authContext = await auth.context(ctx, {
368
+ * resolve: async (_ctx, user, authState) => ({
369
+ * email: user.email,
370
+ * canWrite: authState.grants.includes("posts.write"),
371
+ * }),
372
+ * });
373
+ * ```
316
374
  */
317
- type AuthCtxConfig<TResolve extends Record<string, unknown> = Record<string, never>> = {
318
- /** Allow unauthenticated callers and return `userId: null` / `user: null`. */optional?: boolean;
375
+ type AuthContextConfig<TResolve extends Record<string, unknown> = Record<string, never>> = {
376
+ /**
377
+ * Allow unauthenticated callers and return a null-shaped auth object instead
378
+ * of throwing `NOT_SIGNED_IN`.
379
+ */
380
+ optional?: boolean;
319
381
  /**
320
382
  * Attach additional derived fields to the auth context after the base auth
321
383
  * context is resolved.
384
+ *
385
+ * This callback runs only when a user is authenticated.
322
386
  */
323
387
  resolve?: (ctx: any, user: UserDoc, auth: AuthContext) => Promise<TResolve> | TResolve;
324
388
  /**
325
- * Override or wrap the base auth resolution used by {@link AuthCtx}.
389
+ * Override or wrap the base auth resolution used by {@link createAuth().ctx}.
326
390
  *
327
391
  * Return `undefined` to fall back to the built-in resolver,
328
392
  * `null` for an explicit unauthenticated state, or an
@@ -332,12 +396,12 @@ type AuthCtxConfig<TResolve extends Record<string, unknown> = Record<string, nev
332
396
  * Convex auth tables.
333
397
  *
334
398
  * @param ctx - The Convex function context.
335
- * @param fallback - The built-in auth resolver used by {@link AuthCtx}.
399
+ * @param fallback - The built-in auth resolver used by {@link createAuth().ctx}.
336
400
  * @returns Resolved auth state, `null`, or `undefined` to use the fallback.
337
401
  *
338
402
  * @example
339
403
  * ```ts
340
- * const authCtx = AuthCtx(auth, {
404
+ * const authCtx = auth.ctx({
341
405
  * authResolve: async (ctx, fallback) => {
342
406
  * const injected = getInjectedAuth(ctx);
343
407
  * return injected ?? (await fallback());
@@ -348,85 +412,21 @@ type AuthCtxConfig<TResolve extends Record<string, unknown> = Record<string, nev
348
412
  authResolve?: (ctx: any, fallback: () => Promise<AuthContext | null>) => Promise<AuthContext | null | undefined> | AuthContext | null | undefined;
349
413
  };
350
414
  /**
351
- * Create a context enrichment for `customQuery` / `customMutation` optional auth.
352
- *
353
- * When `optional: true` is set, unauthenticated requests are allowed.
354
- * The enriched `ctx.auth` will have `userId: null`, `user: null`,
355
- * `groupId: null`, `role: null`, and `grants: []` for unauthenticated callers.
356
- *
357
- * @param auth - The auth API object returned by {@link createAuth}.
358
- * @param config - Configuration with `optional: true` and an optional
359
- * `resolve` callback for attaching extra fields to the auth context.
360
- * @returns An object with `args` and `input` compatible with Convex
361
- * custom function builders.
362
- *
363
- * @example
364
- * ```ts
365
- * const authCtx = AuthCtx(auth, {
366
- * optional: true,
367
- * resolve: async (_ctx, user) => ({ plan: user?.extend?.plan ?? null }),
368
- * });
369
- * ```
370
- *
371
- * @see {@link createAuth}
372
- */
373
- declare function AuthCtx<TResolve extends Record<string, unknown> = Record<string, never>>(auth: AuthLike, config: AuthCtxConfig<TResolve> & {
374
- optional: true;
375
- }): {
376
- args: {};
377
- input: (ctx: any, _args: any, _extra?: any) => Promise<{
378
- ctx: {
379
- auth: OptionalAuthCtxState & TResolve;
380
- };
381
- args: {};
382
- }>;
383
- };
384
- /**
385
- * Create a context enrichment for `customQuery` / `customMutation` — required auth (default).
386
- *
387
- * When `optional` is omitted or `false`, unauthenticated requests throw a
388
- * structured `ConvexError` before your handler runs.
389
- *
390
- * @param auth - The auth API object returned by {@link createAuth}.
391
- * @param config - Optional configuration with a `resolve` callback
392
- * for attaching extra fields to the auth context.
393
- * @returns An object with `args` and `input` compatible with Convex
394
- * custom function builders.
395
- *
396
- * @example
397
- * ```ts
398
- * const authCtx = AuthCtx(auth, {
399
- * resolve: async (_ctx, user) => ({ email: user.email }),
400
- * });
401
- * ```
402
- *
403
- * @see {@link createAuth}
404
- */
405
- declare function AuthCtx<TResolve extends Record<string, unknown> = Record<string, never>>(auth: AuthLike, config?: AuthCtxConfig<TResolve>): {
406
- args: {};
407
- input: (ctx: any, _args: any, _extra?: any) => Promise<{
408
- ctx: {
409
- auth: RequiredAuthCtxState & TResolve;
410
- };
411
- args: {};
412
- }>;
413
- };
414
- /**
415
- * Extract the resolved `auth` context type from an {@link AuthCtx} instance.
415
+ * Extract the resolved `auth` context type from an `auth.ctx()` customization.
416
416
  *
417
417
  * Use this to type function parameters or variables that receive the
418
- * enriched auth context produced by `AuthCtx`. The inferred type includes
418
+ * enriched auth context produced by `auth.ctx()`. The inferred type includes
419
419
  * `userId`, `user`, `groupId`, `role`, `grants`, `getUserIdentity`, and any
420
420
  * additional fields added by the `resolve` callback. This is the generic
421
421
  * utility for reusing the enriched auth shape without manually duplicating
422
422
  * conditional auth types.
423
423
  *
424
- * @typeParam T - An `AuthCtx` return value (must have an `input` method
424
+ * @typeParam T - An `auth.ctx()` return value (must have an `input` method
425
425
  * that returns `{ ctx: { auth: ... } }`).
426
426
  *
427
427
  * @example
428
428
  * ```ts
429
- * const authCtx = AuthCtx(auth, {
429
+ * const authCtx = auth.ctx({
430
430
  * resolve: async (ctx, user) => ({ orgId: user.orgId }),
431
431
  * });
432
432
  * type Auth = InferAuth<typeof authCtx>;
@@ -443,5 +443,5 @@ type InferAuth<T extends {
443
443
  }>;
444
444
  }> = Awaited<ReturnType<T["input"]>>["ctx"]["auth"];
445
445
  //#endregion
446
- export { AuthApi, AuthConfig, AuthContext, AuthCtx, AuthCtxConfig, InferAuth, UserDoc, createAuth };
446
+ export { AuthApi, AuthConfig, AuthContext, AuthContextConfig, InferAuth, OptionalAuthContext, UserDoc, createAuth };
447
447
  //# sourceMappingURL=auth.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","names":[],"sources":["../../../src/server/auth.ts"],"mappings":"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"}
1
+ {"version":3,"file":"auth.d.ts","names":[],"sources":["../../../src/server/auth.ts"],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { createUnauthenticatedAuthContext, getAuthContext } from "./context.js";
1
2
  import { Auth } from "./runtime.js";
2
3
  import { Cv } from "@robelest/fx/convex";
3
4
 
@@ -31,41 +32,29 @@ import { Cv } from "@robelest/fx/convex";
31
32
  * });
32
33
  * ```
33
34
  *
34
- * @see {@link AuthCtx}
35
+ * @see {@link AuthContextConfig}
35
36
  */
36
- /**
37
- * Resolve auth context for the current user. Returns the enriched
38
- * `ctx.auth` object or `null` when unauthenticated.
39
- *
40
- * Resolution flow:
41
- * 1. `user.id(ctx)` → userId or null (exit early)
42
- * 2. `user.get(ctx, userId)` → user doc (cached per-execution)
43
- * 3. `user.getActiveGroup(ctx, { userId })` → groupId or null
44
- * 4. If groupId → `member.inspect(ctx, { userId, groupId })` → role + grants
45
- */
46
- async function getAuthContext(auth, ctx) {
47
- const userId = await auth.user.id(ctx);
48
- if (!userId) return null;
49
- const user = await auth.user.get(ctx, userId);
50
- const groupId = await auth.user.getActiveGroup(ctx, { userId });
51
- let role = null;
52
- let grants = [];
53
- if (groupId) {
54
- const resolved = await auth.member.inspect(ctx, {
55
- userId,
56
- groupId
57
- });
58
- if (resolved.membership) {
59
- role = resolved.roleIds[0] ?? null;
60
- grants = resolved.grants;
61
- }
37
+ async function resolveConfiguredAuthContext(auth, ctx, config) {
38
+ const fallback = () => getAuthContext(auth, ctx);
39
+ const authOverride = config?.authResolve ? await config.authResolve(ctx, fallback) : void 0;
40
+ return authOverride === void 0 ? await fallback() : authOverride;
41
+ }
42
+ function createNotSignedInError() {
43
+ return Cv.error({
44
+ code: "NOT_SIGNED_IN",
45
+ message: "Authentication required."
46
+ });
47
+ }
48
+ async function createPublicAuthContext(auth, ctx, config) {
49
+ const resolved = await resolveConfiguredAuthContext(auth, ctx, config);
50
+ if (resolved === null) {
51
+ if (config?.optional !== true) throw createNotSignedInError();
52
+ return createUnauthenticatedAuthContext();
62
53
  }
54
+ const extra = config?.resolve ? await config.resolve(ctx, resolved.user, resolved) : {};
63
55
  return {
64
- userId,
65
- user,
66
- groupId,
67
- role,
68
- grants
56
+ ...resolved,
57
+ ...extra
69
58
  };
70
59
  }
71
60
  function createAuth(component, config) {
@@ -184,52 +173,65 @@ function createAuth(component, config) {
184
173
  validate: scimApi.validate
185
174
  } },
186
175
  http: authResult.auth.http,
187
- context: async (ctx) => {
188
- const authContext = await getAuthContext(authResult.auth, ctx);
189
- if (authContext === null) throw Cv.error({
190
- code: "NOT_SIGNED_IN",
191
- message: "Authentication required."
192
- });
193
- return authContext;
194
- },
195
- ctx: () => ({
196
- args: {},
197
- input: async (ctx) => {
198
- const authCtx = await getAuthContext(authResult.auth, ctx);
199
- if (authCtx === null) throw Cv.error({
200
- code: "NOT_SIGNED_IN",
201
- message: "Authentication required."
202
- });
203
- return {
204
- ctx: { auth: authCtx },
205
- args: {}
206
- };
207
- }
208
- })
176
+ context: ((ctx, config$1) => createPublicAuthContext(authResult.auth, ctx, config$1)),
177
+ ctx: ((config$1) => createAuthContextCustomization(authResult.auth, config$1))
209
178
  };
210
179
  }
211
- function AuthCtx(auth, config) {
180
+ /**
181
+ * Create a context enrichment for `customQuery` / `customMutation` — optional auth.
182
+ *
183
+ * When `optional: true` is set, unauthenticated requests are allowed.
184
+ * The enriched `ctx.auth` will have `userId: null`, `user: null`,
185
+ * `groupId: null`, `role: null`, and `grants: []` for unauthenticated callers.
186
+ *
187
+ * @param config - Configuration with `optional: true` and an optional
188
+ * `resolve` callback for attaching extra fields to the auth context.
189
+ * @returns An object with `args` and `input` compatible with Convex
190
+ * custom function builders.
191
+ *
192
+ * @example
193
+ * ```ts
194
+ * const authCtx = auth.ctx({
195
+ * optional: true,
196
+ * resolve: async (_ctx, user) => ({ plan: user.extend?.plan ?? null }),
197
+ * });
198
+ * ```
199
+ *
200
+ * @see {@link createAuth}
201
+ */
202
+ /**
203
+ * Create a context enrichment for `customQuery` / `customMutation` — required auth (default).
204
+ *
205
+ * When `optional` is omitted or `false`, unauthenticated requests throw a
206
+ * structured `ConvexError` before your handler runs.
207
+ *
208
+ * @param config - Optional configuration with a `resolve` callback
209
+ * for attaching extra fields to the auth context.
210
+ * @returns An object with `args` and `input` compatible with Convex
211
+ * custom function builders.
212
+ *
213
+ * @example
214
+ * ```ts
215
+ * const authCtx = auth.ctx({
216
+ * resolve: async (_ctx, user) => ({ email: user.email }),
217
+ * });
218
+ * ```
219
+ *
220
+ * @see {@link createAuth}
221
+ */
222
+ function createAuthContextCustomization(auth, config) {
212
223
  return {
213
224
  args: {},
214
225
  input: async (ctx, _args, _extra) => {
215
226
  const nativeAuth = ctx.auth;
216
227
  const getUserIdentity = nativeAuth.getUserIdentity.bind(nativeAuth);
217
- const fallback = () => getAuthContext(auth, ctx);
218
- const authOverride = config?.authResolve ? await config.authResolve(ctx, fallback) : void 0;
219
- const resolved = authOverride === void 0 ? await fallback() : authOverride;
228
+ const resolved = await resolveConfiguredAuthContext(auth, ctx, config);
220
229
  if (resolved === null) {
221
- if (config?.optional !== true) throw Cv.error({
222
- code: "NOT_SIGNED_IN",
223
- message: "Authentication required."
224
- });
230
+ if (config?.optional !== true) throw createNotSignedInError();
225
231
  return {
226
232
  ctx: { auth: {
227
233
  getUserIdentity,
228
- userId: null,
229
- user: null,
230
- groupId: null,
231
- role: null,
232
- grants: []
234
+ ...createUnauthenticatedAuthContext()
233
235
  } },
234
236
  args: {}
235
237
  };
@@ -248,5 +250,5 @@ function AuthCtx(auth, config) {
248
250
  }
249
251
 
250
252
  //#endregion
251
- export { AuthCtx, createAuth };
253
+ export { createAuth };
252
254
  //# sourceMappingURL=auth.js.map