@robelest/convex-auth 0.0.4-preview.27 → 0.0.4-preview.28

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 (88) hide show
  1. package/README.md +3 -5
  2. package/dist/bin.js +6488 -1571
  3. package/dist/browser/index.js +10 -7
  4. package/dist/browser/locks.js +3 -5
  5. package/dist/browser/navigation.js +7 -10
  6. package/dist/browser/runtime.js +35 -33
  7. package/dist/client/core/types.js +17 -0
  8. package/dist/client/factors/device.js +26 -19
  9. package/dist/client/index.js +151 -163
  10. package/dist/client/runtime/proxy.js +6 -6
  11. package/dist/client/services/adapters.js +3 -7
  12. package/dist/client/services/http.js +2 -5
  13. package/dist/client/services/resolve.js +5 -11
  14. package/dist/client/services/runtime.js +2 -5
  15. package/dist/component/_generated/component.d.ts +46 -0
  16. package/dist/component/index.d.ts +3 -3
  17. package/dist/component/model.d.ts +25 -25
  18. package/dist/component/public/identity/sessions.js +38 -1
  19. package/dist/component/public/identity/tokens.js +81 -3
  20. package/dist/component/public/identity/verifiers.js +9 -3
  21. package/dist/component/public.js +3 -3
  22. package/dist/component/schema.d.ts +320 -320
  23. package/dist/core/index.d.ts +380 -0
  24. package/dist/core/index.js +83 -0
  25. package/dist/otel.d.ts +13 -17
  26. package/dist/otel.js +39 -49
  27. package/dist/providers/email.d.ts +2 -2
  28. package/dist/providers/password.js +8 -16
  29. package/dist/providers/phone.js +2 -9
  30. package/dist/server/auth-context.d.ts +204 -0
  31. package/dist/server/auth-context.js +76 -0
  32. package/dist/server/auth.d.ts +25 -187
  33. package/dist/server/auth.js +5 -96
  34. package/dist/server/componentContext.d.ts +12 -0
  35. package/dist/server/componentContext.js +1 -0
  36. package/dist/server/config.js +1 -12
  37. package/dist/server/constants.js +6 -0
  38. package/dist/server/contract.d.ts +1 -1
  39. package/dist/server/core.js +5 -14
  40. package/dist/server/crypto.js +26 -18
  41. package/dist/server/db.js +6 -1
  42. package/dist/server/device.js +88 -78
  43. package/dist/server/http.d.ts +4 -3
  44. package/dist/server/http.js +74 -86
  45. package/dist/server/index.d.ts +2 -1
  46. package/dist/server/limits.js +22 -15
  47. package/dist/server/mounts.d.ts +103 -103
  48. package/dist/server/mutations/account.js +6 -4
  49. package/dist/server/mutations/invalidate.js +3 -6
  50. package/dist/server/mutations/oauth.js +86 -88
  51. package/dist/server/mutations/refresh.js +45 -87
  52. package/dist/server/mutations/register.js +19 -19
  53. package/dist/server/mutations/retrieve.js +17 -15
  54. package/dist/server/mutations/signature.js +9 -13
  55. package/dist/server/mutations/signin.js +7 -3
  56. package/dist/server/mutations/signout.js +10 -15
  57. package/dist/server/mutations/store.js +22 -12
  58. package/dist/server/mutations/verifier.js +11 -6
  59. package/dist/server/mutations/verify.js +55 -46
  60. package/dist/server/oauth/runtime.js +27 -25
  61. package/dist/server/passkey.js +299 -250
  62. package/dist/server/prefetch.js +283 -281
  63. package/dist/server/refresh.js +7 -60
  64. package/dist/server/runtime.d.ts +82 -206
  65. package/dist/server/runtime.js +63 -56
  66. package/dist/server/services/config.js +5 -3
  67. package/dist/server/services/logger.js +2 -4
  68. package/dist/server/services/providers.js +2 -4
  69. package/dist/server/services/refresh.js +2 -4
  70. package/dist/server/services/resolve.js +15 -14
  71. package/dist/server/services/signin.js +2 -4
  72. package/dist/server/sessions.js +32 -33
  73. package/dist/server/signin.js +177 -142
  74. package/dist/server/sso/domain.d.ts +20 -68
  75. package/dist/server/sso/domain.js +444 -413
  76. package/dist/server/sso/http.js +53 -59
  77. package/dist/server/sso/oidc.js +94 -80
  78. package/dist/server/tokens.js +13 -3
  79. package/dist/server/totp.js +153 -116
  80. package/dist/server/types.d.ts +2 -2
  81. package/dist/server/users.js +18 -23
  82. package/dist/server/utils/cache.js +51 -0
  83. package/dist/server/utils/dispatch.js +36 -0
  84. package/dist/server/utils/retry.js +24 -0
  85. package/dist/server/utils/span.js +32 -0
  86. package/dist/shared/errors.js +9 -3
  87. package/dist/shared/log.js +20 -22
  88. package/package.json +41 -33
@@ -0,0 +1,380 @@
1
+ import { ComponentCtx, ComponentReadCtx } from "../server/componentContext.js";
2
+ import { AuthAuthorizationConfig, ConvexAuthConfig, KeyDoc, KeyScope, ScopeChecker, UserOrderBy, UserWhere } from "../server/types.js";
3
+ import { AuthProfile } from "../server/payloads.js";
4
+ import { AuthConfig, AuthContext, AuthContextConfig, AuthContextFactory as AuthContextFactory$1, AuthContextResolver as AuthContextResolver$1, OptionalAuthContext, UserDoc } from "../server/auth-context.js";
5
+ import "../component/index.js";
6
+ import * as convex_values0 from "convex/values";
7
+ import * as convex_server0 from "convex/server";
8
+ import * as fluent_convex0 from "fluent-convex";
9
+
10
+ //#region src/core/index.d.ts
11
+ type AuthContextResolver = AuthContextResolver$1;
12
+ type AuthContextFactory = AuthContextFactory$1;
13
+ /**
14
+ * Create a lightweight auth context object.
15
+ *
16
+ * Returns the same `user`, `session`, `member`, `group`, `account`,
17
+ * `invite`, `key`, `context`, and `ctx` APIs as `createAuth`, but
18
+ * without `signIn`, `signOut`, `store`, `http`, or provider logic.
19
+ *
20
+ * Use this in query/mutation files that only need to resolve the
21
+ * current user — it avoids loading provider, OAuth, and crypto code.
22
+ *
23
+ * @example
24
+ * ```ts
25
+ * // convex/auth-core.ts
26
+ * import { createAuthContext } from "@robelest/convex-auth/core";
27
+ * import { components } from "./_generated/api";
28
+ *
29
+ * export const auth = createAuthContext(components.auth);
30
+ *
31
+ * // convex/functions.ts
32
+ * import { auth } from "./auth-core";
33
+ * export const authQuery = customQuery(query, auth.ctx());
34
+ * ```
35
+ */
36
+ declare function createAuthContext(component: ConvexAuthConfig["component"], config?: Omit<AuthConfig, "providers"> & {
37
+ authorization?: AuthAuthorizationConfig;
38
+ }): {
39
+ user: {
40
+ get: (ctx: ComponentReadCtx, userId: string) => Promise<any>;
41
+ list: (ctx: ComponentReadCtx, opts?: {
42
+ where?: UserWhere;
43
+ limit?: number;
44
+ cursor?: string | null;
45
+ orderBy?: UserOrderBy;
46
+ order?: "asc" | "desc";
47
+ }) => Promise<any>;
48
+ viewer: (ctx: ComponentReadCtx & {
49
+ auth: convex_server0.Auth;
50
+ }) => Promise<any>;
51
+ update: (ctx: ComponentCtx, userId: string, data: Record<string, unknown>) => Promise<{
52
+ userId: string;
53
+ }>;
54
+ setActiveGroup: (ctx: ComponentCtx, opts: {
55
+ userId: string;
56
+ groupId: string | null;
57
+ }) => Promise<{
58
+ userId: string;
59
+ groupId: null;
60
+ } | {
61
+ userId: string;
62
+ groupId: string;
63
+ }>;
64
+ getActiveGroup: (ctx: ComponentReadCtx, opts: {
65
+ userId: string;
66
+ }) => Promise<string | null>;
67
+ delete: (ctx: ComponentCtx, userId: string, opts?: {
68
+ cascade?: boolean;
69
+ }) => Promise<{
70
+ userId: string;
71
+ }>;
72
+ };
73
+ session: {
74
+ current: (ctx: {
75
+ auth: convex_server0.Auth;
76
+ }) => Promise<convex_values0.GenericId<"Session"> | null>;
77
+ invalidate: <DataModel extends fluent_convex0.GenericDataModel>(ctx: convex_server0.GenericActionCtx<DataModel>, args: {
78
+ userId: convex_values0.GenericId<"User">;
79
+ except?: convex_values0.GenericId<"Session">[];
80
+ }) => Promise<{
81
+ userId: convex_values0.GenericId<"User">;
82
+ except: convex_values0.GenericId<"Session">[];
83
+ }>;
84
+ get: (ctx: ComponentReadCtx, sessionId: string) => Promise<any>;
85
+ list: (ctx: ComponentReadCtx, opts: {
86
+ userId: string;
87
+ }) => Promise<any>;
88
+ };
89
+ account: {
90
+ create: <DataModel extends fluent_convex0.GenericDataModel>(ctx: convex_server0.GenericActionCtx<DataModel>, args: {
91
+ provider: string;
92
+ account: {
93
+ id: string;
94
+ secret?: string;
95
+ };
96
+ profile: AuthProfile;
97
+ shouldLinkViaEmail?: boolean;
98
+ shouldLinkViaPhone?: boolean;
99
+ }) => Promise<{
100
+ account: {
101
+ _id: string;
102
+ userId: string;
103
+ secret?: string | null;
104
+ };
105
+ user: Record<string, unknown>;
106
+ }>;
107
+ get: <DataModel extends fluent_convex0.GenericDataModel>(ctx: convex_server0.GenericActionCtx<DataModel>, args: {
108
+ provider: string;
109
+ account: {
110
+ id: string;
111
+ secret?: string;
112
+ };
113
+ }) => Promise<{
114
+ account: {
115
+ _id: string;
116
+ userId: string;
117
+ secret?: string | null;
118
+ };
119
+ user: Record<string, unknown>;
120
+ } | null>;
121
+ update: <DataModel extends fluent_convex0.GenericDataModel>(ctx: convex_server0.GenericActionCtx<DataModel>, args: {
122
+ provider: string;
123
+ account: {
124
+ id: string;
125
+ secret: string;
126
+ };
127
+ }) => Promise<{
128
+ accountId: string;
129
+ }>;
130
+ delete: (ctx: ComponentCtx, accountId: string) => Promise<{
131
+ accountId: string;
132
+ }>;
133
+ listPasskeys: (ctx: ComponentReadCtx, opts: {
134
+ userId: string;
135
+ }) => Promise<any>;
136
+ renamePasskey: (ctx: ComponentCtx, passkeyId: string, name: string) => Promise<{
137
+ passkeyId: string;
138
+ }>;
139
+ deletePasskey: (ctx: ComponentCtx, passkeyId: string) => Promise<{
140
+ passkeyId: string;
141
+ }>;
142
+ listTotps: (ctx: ComponentReadCtx, opts: {
143
+ userId: string;
144
+ }) => Promise<any>;
145
+ deleteTotp: (ctx: ComponentCtx, totpId: string) => Promise<{
146
+ totpId: string;
147
+ }>;
148
+ };
149
+ group: {
150
+ create: (ctx: ComponentCtx, data: {
151
+ name: string;
152
+ slug?: string;
153
+ type?: string;
154
+ parentGroupId?: string;
155
+ tags?: Array<{
156
+ key: string;
157
+ value: string;
158
+ }>;
159
+ extend?: Record<string, unknown>;
160
+ }) => Promise<{
161
+ groupId: string;
162
+ }>;
163
+ get: (ctx: ComponentReadCtx, groupId: string) => Promise<any>;
164
+ list: (ctx: ComponentReadCtx, opts?: {
165
+ where?: {
166
+ slug?: string;
167
+ type?: string;
168
+ parentGroupId?: string;
169
+ name?: string;
170
+ isRoot?: boolean;
171
+ tagsAll?: Array<{
172
+ key: string;
173
+ value: string;
174
+ }>;
175
+ tagsAny?: Array<{
176
+ key: string;
177
+ value: string;
178
+ }>;
179
+ };
180
+ limit?: number;
181
+ cursor?: string | null;
182
+ orderBy?: "_creationTime" | "name" | "slug" | "type";
183
+ order?: "asc" | "desc";
184
+ }) => Promise<any>;
185
+ update: (ctx: ComponentCtx, groupId: string, data: Record<string, unknown>) => Promise<{
186
+ groupId: string;
187
+ }>;
188
+ delete: (ctx: ComponentCtx, groupId: string) => Promise<{
189
+ groupId: string;
190
+ }>;
191
+ ancestors: (ctx: ComponentReadCtx, opts: {
192
+ groupId: string;
193
+ maxDepth?: number;
194
+ includeSelf?: boolean;
195
+ }) => Promise<{
196
+ ancestors: Record<string, unknown>[];
197
+ cycleDetected: boolean;
198
+ maxDepthReached: boolean;
199
+ }>;
200
+ };
201
+ member: {
202
+ create: (ctx: ComponentCtx, data: {
203
+ groupId: string;
204
+ userId: string;
205
+ roleIds?: string[];
206
+ status?: string;
207
+ extend?: Record<string, unknown>;
208
+ }) => Promise<{
209
+ memberId: string;
210
+ }>;
211
+ get: (ctx: ComponentReadCtx, memberId: string) => Promise<any>;
212
+ list: (ctx: ComponentReadCtx, opts?: {
213
+ where?: {
214
+ groupId?: string;
215
+ userId?: string;
216
+ roleId?: string;
217
+ status?: string;
218
+ };
219
+ limit?: number;
220
+ cursor?: string | null;
221
+ orderBy?: "_creationTime" | "status";
222
+ order?: "asc" | "desc";
223
+ }) => Promise<any>;
224
+ delete: (ctx: ComponentCtx, memberId: string) => Promise<{
225
+ memberId: string;
226
+ }>;
227
+ update: (ctx: ComponentCtx, memberId: string, data: Record<string, unknown>) => Promise<{
228
+ memberId: string;
229
+ }>;
230
+ inspect: (ctx: ComponentReadCtx, opts: {
231
+ userId: string;
232
+ groupId: string;
233
+ ancestry?: boolean;
234
+ maxDepth?: number;
235
+ }) => Promise<{
236
+ membership: null;
237
+ roleIds: string[];
238
+ grants: string[];
239
+ } | {
240
+ membership: {
241
+ _id: string;
242
+ _creationTime: number;
243
+ groupId: string;
244
+ userId: string;
245
+ role?: string;
246
+ roleIds?: string[];
247
+ status?: string;
248
+ extend?: Record<string, unknown>;
249
+ };
250
+ roleIds: string[];
251
+ grants: string[];
252
+ }>;
253
+ require: (ctx: ComponentReadCtx, opts: {
254
+ userId: string;
255
+ groupId: string;
256
+ ancestry?: boolean;
257
+ roleIds?: string[];
258
+ grants?: string[];
259
+ maxDepth?: number;
260
+ }) => Promise<{
261
+ membership: {
262
+ _id: string;
263
+ _creationTime: number;
264
+ groupId: string;
265
+ userId: string;
266
+ role?: string;
267
+ roleIds?: string[];
268
+ status?: string;
269
+ extend?: Record<string, unknown>;
270
+ };
271
+ roleIds: string[];
272
+ grants: string[];
273
+ }>;
274
+ };
275
+ invite: {
276
+ create: (ctx: ComponentCtx, data: {
277
+ groupId?: string;
278
+ invitedByUserId?: string;
279
+ email?: string;
280
+ roleIds?: string[];
281
+ expiresTime?: number;
282
+ extend?: Record<string, unknown>;
283
+ }) => Promise<{
284
+ inviteId: string;
285
+ token: string;
286
+ }>;
287
+ get: (ctx: ComponentReadCtx, inviteId: string) => Promise<any>;
288
+ token: {
289
+ get: (ctx: ComponentReadCtx, token: string) => Promise<any>;
290
+ accept: (ctx: ComponentCtx, args: {
291
+ token: string;
292
+ acceptedByUserId: string;
293
+ }) => Promise<any>;
294
+ };
295
+ list: (ctx: ComponentReadCtx, opts?: {
296
+ where?: {
297
+ tokenHash?: string;
298
+ groupId?: string;
299
+ status?: "pending" | "accepted" | "revoked" | "expired";
300
+ email?: string;
301
+ invitedByUserId?: string;
302
+ roleId?: string;
303
+ acceptedByUserId?: string;
304
+ };
305
+ limit?: number;
306
+ cursor?: string | null;
307
+ orderBy?: "_creationTime" | "status" | "email" | "expiresTime" | "acceptedTime";
308
+ order?: "asc" | "desc";
309
+ }) => Promise<any>;
310
+ accept: (ctx: ComponentCtx, inviteId: string, acceptedByUserId?: string) => Promise<{
311
+ inviteId: string;
312
+ acceptedByUserId: string | null;
313
+ }>;
314
+ revoke: (ctx: ComponentCtx, inviteId: string) => Promise<{
315
+ inviteId: string;
316
+ }>;
317
+ };
318
+ key: {
319
+ create: (ctx: ComponentCtx, opts: {
320
+ userId: string;
321
+ name: string;
322
+ scopes: KeyScope[];
323
+ rateLimit?: {
324
+ maxRequests: number;
325
+ windowMs: number;
326
+ };
327
+ expiresAt?: number;
328
+ metadata?: Record<string, unknown>;
329
+ }) => Promise<{
330
+ keyId: string;
331
+ secret: string;
332
+ }>;
333
+ verify: (ctx: ComponentCtx, rawKey: string) => Promise<{
334
+ userId: string;
335
+ keyId: string;
336
+ scopes: ScopeChecker;
337
+ }>;
338
+ list: (ctx: ComponentReadCtx, opts?: {
339
+ where?: {
340
+ userId?: string;
341
+ revoked?: boolean;
342
+ name?: string;
343
+ prefix?: string;
344
+ };
345
+ limit?: number;
346
+ cursor?: string | null;
347
+ orderBy?: "_creationTime" | "name" | "lastUsedAt" | "expiresAt" | "revoked";
348
+ order?: "asc" | "desc";
349
+ }) => Promise<any>;
350
+ get: (ctx: ComponentReadCtx, keyId: string) => Promise<KeyDoc | null>;
351
+ update: (ctx: ComponentCtx, keyId: string, data: {
352
+ name?: string;
353
+ scopes?: KeyScope[];
354
+ rateLimit?: {
355
+ maxRequests: number;
356
+ windowMs: number;
357
+ };
358
+ }) => Promise<{
359
+ keyId: string;
360
+ }>;
361
+ revoke: (ctx: ComponentCtx, keyId: string) => Promise<{
362
+ keyId: string;
363
+ }>;
364
+ delete: (ctx: ComponentCtx, keyId: string) => Promise<{
365
+ keyId: string;
366
+ }>;
367
+ rotate: (ctx: ComponentCtx, keyId: string, opts?: {
368
+ name?: string;
369
+ expiresAt?: number;
370
+ }) => Promise<{
371
+ keyId: string;
372
+ secret: string;
373
+ }>;
374
+ };
375
+ context: AuthContextResolver;
376
+ ctx: AuthContextFactory;
377
+ };
378
+ //#endregion
379
+ export { type AuthContext, type AuthContextConfig, type OptionalAuthContext, type UserDoc, createAuthContext };
380
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,83 @@
1
+ import { assertAuthResolverContext, createAuthContextCustomization, createPublicAuthContext } from "../server/auth-context.js";
2
+ import { configDefaults } from "../server/config.js";
3
+ import { createCoreDomains } from "../server/core.js";
4
+ import { callModifyAccount } from "../server/mutations/account.js";
5
+ import { callInvalidateSessions } from "../server/mutations/invalidate.js";
6
+ import { callCreateAccountFromCredentials } from "../server/mutations/register.js";
7
+ import { callRetrieveAccountWithCredentials } from "../server/mutations/retrieve.js";
8
+
9
+ //#region src/core/index.ts
10
+ /**
11
+ * Lightweight auth context entry point for `@robelest/convex-auth/core`.
12
+ *
13
+ * Provides auth context resolution, user/session/member/group lookups,
14
+ * and authorization helpers without pulling in provider implementations,
15
+ * OAuth, crypto, or sign-in logic.
16
+ *
17
+ * @module
18
+ */
19
+ /**
20
+ * Create a lightweight auth context object.
21
+ *
22
+ * Returns the same `user`, `session`, `member`, `group`, `account`,
23
+ * `invite`, `key`, `context`, and `ctx` APIs as `createAuth`, but
24
+ * without `signIn`, `signOut`, `store`, `http`, or provider logic.
25
+ *
26
+ * Use this in query/mutation files that only need to resolve the
27
+ * current user — it avoids loading provider, OAuth, and crypto code.
28
+ *
29
+ * @example
30
+ * ```ts
31
+ * // convex/auth-core.ts
32
+ * import { createAuthContext } from "@robelest/convex-auth/core";
33
+ * import { components } from "./_generated/api";
34
+ *
35
+ * export const auth = createAuthContext(components.auth);
36
+ *
37
+ * // convex/functions.ts
38
+ * import { auth } from "./auth-core";
39
+ * export const authQuery = customQuery(query, auth.ctx());
40
+ * ```
41
+ */
42
+ function createAuthContext(component, config) {
43
+ const fullConfig = configDefaults({
44
+ component,
45
+ providers: [],
46
+ ...config
47
+ });
48
+ const INVITE_TOKEN_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
49
+ const INVITE_TOKEN_LENGTH = 48;
50
+ const enrichCtx = (ctx) => ctx;
51
+ const domains = createCoreDomains({
52
+ config: fullConfig,
53
+ callInvalidateSessions,
54
+ callCreateAccountFromCredentials,
55
+ callRetrieveAccountWithCredentials,
56
+ callModifyAccount,
57
+ getEnrichCtx: () => enrichCtx,
58
+ inviteTokenAlphabet: INVITE_TOKEN_ALPHABET,
59
+ inviteTokenLength: INVITE_TOKEN_LENGTH
60
+ });
61
+ const authLike = {
62
+ user: domains.user,
63
+ member: domains.member
64
+ };
65
+ return {
66
+ user: domains.user,
67
+ session: domains.session,
68
+ account: domains.account,
69
+ group: domains.group,
70
+ member: domains.member,
71
+ invite: domains.invite,
72
+ key: domains.key,
73
+ context: ((ctx, config$1) => {
74
+ assertAuthResolverContext(ctx);
75
+ return createPublicAuthContext(authLike, ctx, config$1);
76
+ }),
77
+ ctx: ((config$1) => createAuthContextCustomization(authLike, config$1))
78
+ };
79
+ }
80
+
81
+ //#endregion
82
+ export { createAuthContext };
83
+ //# sourceMappingURL=index.js.map
package/dist/otel.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import * as _effect_opentelemetry_Resource0 from "@effect/opentelemetry/Resource";
2
- import * as effect_Layer0 from "effect/Layer";
3
1
  import { Attributes } from "@opentelemetry/api";
2
+ import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
3
+ import { WebTracerProvider } from "@opentelemetry/sdk-trace-web";
4
4
  import { LogRecordProcessor } from "@opentelemetry/sdk-logs";
5
5
  import { MetricReader } from "@opentelemetry/sdk-metrics";
6
6
  import { SpanProcessor, TracerConfig } from "@opentelemetry/sdk-trace-base";
@@ -10,7 +10,7 @@ import { SpanProcessor, TracerConfig } from "@opentelemetry/sdk-trace-base";
10
10
  * Consumer-provided telemetry configuration for Convex Auth spans.
11
11
  *
12
12
  * The host application decides the service name, exporters, processors, and
13
- * readers. Convex Auth only turns this configuration into an Effect layer.
13
+ * readers.
14
14
  */
15
15
  type TelemetryConfig = {
16
16
  /** Service name reported to the telemetry backend. */serviceName: string; /** Optional service version reported alongside the service name. */
@@ -22,52 +22,48 @@ type TelemetryConfig = {
22
22
  logRecordProcessor?: LogRecordProcessor | ReadonlyArray<LogRecordProcessor>;
23
23
  };
24
24
  /**
25
- * Build a Node.js OpenTelemetry layer for an app using Convex Auth.
25
+ * Build a Node.js OpenTelemetry tracer provider for an app using Convex Auth.
26
26
  *
27
- * Convex Auth does not install this layer automatically. Provide it from your
27
+ * Convex Auth does not install this provider automatically. Provide it from your
28
28
  * application runtime when you want server-side spans, metrics, or logs to be
29
29
  * exported.
30
30
  *
31
31
  * @param config - Telemetry configuration supplied by the host application.
32
- * @returns An Effect layer that installs the Node OpenTelemetry SDK.
32
+ * @returns A registered {@link NodeTracerProvider}.
33
33
  *
34
34
  * @example
35
35
  * ```ts
36
- * import { NodeRuntime } from "@effect/platform-node";
37
36
  * import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";
38
37
  * import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
39
38
  * import { nodeTelemetry } from "@robelest/convex-auth/otel";
40
- * import { Effect } from "effect";
41
39
  *
42
- * const telemetry = nodeTelemetry({
40
+ * const provider = nodeTelemetry({
43
41
  * serviceName: "my-app",
44
42
  * spanProcessor: new BatchSpanProcessor(new OTLPTraceExporter()),
45
43
  * });
46
- *
47
- * Effect.log("ready").pipe(Effect.provide(telemetry), NodeRuntime.runMain);
48
44
  * ```
49
45
  */
50
- declare function nodeTelemetry(config: TelemetryConfig): effect_Layer0.Layer<_effect_opentelemetry_Resource0.Resource, never, never>;
46
+ declare function nodeTelemetry(config: TelemetryConfig): NodeTracerProvider;
51
47
  /**
52
- * Build a browser OpenTelemetry layer for an app using Convex Auth.
48
+ * Build a browser OpenTelemetry tracer provider for an app using Convex Auth.
53
49
  *
54
- * Convex Auth does not install this layer automatically. Provide it from your
50
+ * Convex Auth does not install this provider automatically. Provide it from your
55
51
  * browser runtime when you want client-side Convex Auth spans to be exported.
56
52
  *
57
53
  * @param config - Telemetry configuration supplied by the host application.
58
- * @returns An Effect layer that installs the browser OpenTelemetry SDK.
54
+ * @returns A registered {@link WebTracerProvider}.
59
55
  *
60
56
  * @example
61
57
  * ```ts
62
58
  * import { browserTelemetry } from "@robelest/convex-auth/otel";
63
59
  *
64
- * const telemetry = browserTelemetry({
60
+ * const provider = browserTelemetry({
65
61
  * serviceName: "my-web-app",
66
62
  * attributes: { deployment: "production" },
67
63
  * });
68
64
  * ```
69
65
  */
70
- declare function browserTelemetry(config: TelemetryConfig): effect_Layer0.Layer<_effect_opentelemetry_Resource0.Resource, never, never>;
66
+ declare function browserTelemetry(config: TelemetryConfig): WebTracerProvider;
71
67
  //#endregion
72
68
  export { TelemetryConfig, browserTelemetry, nodeTelemetry };
73
69
  //# sourceMappingURL=otel.d.ts.map
package/dist/otel.js CHANGED
@@ -1,90 +1,80 @@
1
- import { Effect } from "effect";
2
- import * as NodeSdk from "@effect/opentelemetry/NodeSdk";
3
- import * as WebSdk from "@effect/opentelemetry/WebSdk";
1
+ import { resourceFromAttributes } from "@opentelemetry/resources";
2
+ import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
3
+ import { WebTracerProvider } from "@opentelemetry/sdk-trace-web";
4
+ import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from "@opentelemetry/semantic-conventions";
4
5
 
5
6
  //#region src/otel.ts
7
+ function resolveProcessors(input) {
8
+ if (input === void 0) return [];
9
+ if (Array.isArray(input)) return [...input];
10
+ return [input];
11
+ }
6
12
  /**
7
- * OpenTelemetry integration helpers for Convex Auth.
8
- *
9
- * @module
10
- *
11
- * Convex Auth exposes tracing hooks through Effect spans, but it does not
12
- * automatically install OpenTelemetry exporters or boot a telemetry runtime for
13
- * consumers. The application using Convex Auth owns telemetry setup.
14
- *
15
- * Use the helpers in this module when you want Convex Auth spans to participate
16
- * in your app's existing OpenTelemetry pipeline.
17
- */
18
- /**
19
- * Build a Node.js OpenTelemetry layer for an app using Convex Auth.
13
+ * Build a Node.js OpenTelemetry tracer provider for an app using Convex Auth.
20
14
  *
21
- * Convex Auth does not install this layer automatically. Provide it from your
15
+ * Convex Auth does not install this provider automatically. Provide it from your
22
16
  * application runtime when you want server-side spans, metrics, or logs to be
23
17
  * exported.
24
18
  *
25
19
  * @param config - Telemetry configuration supplied by the host application.
26
- * @returns An Effect layer that installs the Node OpenTelemetry SDK.
20
+ * @returns A registered {@link NodeTracerProvider}.
27
21
  *
28
22
  * @example
29
23
  * ```ts
30
- * import { NodeRuntime } from "@effect/platform-node";
31
24
  * import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";
32
25
  * import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
33
26
  * import { nodeTelemetry } from "@robelest/convex-auth/otel";
34
- * import { Effect } from "effect";
35
27
  *
36
- * const telemetry = nodeTelemetry({
28
+ * const provider = nodeTelemetry({
37
29
  * serviceName: "my-app",
38
30
  * spanProcessor: new BatchSpanProcessor(new OTLPTraceExporter()),
39
31
  * });
40
- *
41
- * Effect.log("ready").pipe(Effect.provide(telemetry), NodeRuntime.runMain);
42
32
  * ```
43
33
  */
44
34
  function nodeTelemetry(config) {
45
- return NodeSdk.layer(Effect.sync(() => ({
46
- resource: {
47
- serviceName: config.serviceName,
48
- serviceVersion: config.serviceVersion,
49
- attributes: config.attributes
50
- },
51
- spanProcessor: config.spanProcessor,
52
- tracerConfig: config.tracerConfig,
53
- metricReader: config.metricReader,
54
- logRecordProcessor: config.logRecordProcessor
55
- })));
35
+ const provider = new NodeTracerProvider({
36
+ resource: resourceFromAttributes({
37
+ [ATTR_SERVICE_NAME]: config.serviceName,
38
+ ...config.serviceVersion ? { [ATTR_SERVICE_VERSION]: config.serviceVersion } : {},
39
+ ...config.attributes
40
+ }),
41
+ spanProcessors: resolveProcessors(config.spanProcessor),
42
+ ...config.tracerConfig
43
+ });
44
+ provider.register();
45
+ return provider;
56
46
  }
57
47
  /**
58
- * Build a browser OpenTelemetry layer for an app using Convex Auth.
48
+ * Build a browser OpenTelemetry tracer provider for an app using Convex Auth.
59
49
  *
60
- * Convex Auth does not install this layer automatically. Provide it from your
50
+ * Convex Auth does not install this provider automatically. Provide it from your
61
51
  * browser runtime when you want client-side Convex Auth spans to be exported.
62
52
  *
63
53
  * @param config - Telemetry configuration supplied by the host application.
64
- * @returns An Effect layer that installs the browser OpenTelemetry SDK.
54
+ * @returns A registered {@link WebTracerProvider}.
65
55
  *
66
56
  * @example
67
57
  * ```ts
68
58
  * import { browserTelemetry } from "@robelest/convex-auth/otel";
69
59
  *
70
- * const telemetry = browserTelemetry({
60
+ * const provider = browserTelemetry({
71
61
  * serviceName: "my-web-app",
72
62
  * attributes: { deployment: "production" },
73
63
  * });
74
64
  * ```
75
65
  */
76
66
  function browserTelemetry(config) {
77
- return WebSdk.layer(Effect.sync(() => ({
78
- resource: {
79
- serviceName: config.serviceName,
80
- serviceVersion: config.serviceVersion,
81
- attributes: config.attributes
82
- },
83
- spanProcessor: config.spanProcessor,
84
- tracerConfig: config.tracerConfig,
85
- metricReader: config.metricReader,
86
- logRecordProcessor: config.logRecordProcessor
87
- })));
67
+ const provider = new WebTracerProvider({
68
+ resource: resourceFromAttributes({
69
+ [ATTR_SERVICE_NAME]: config.serviceName,
70
+ ...config.serviceVersion ? { [ATTR_SERVICE_VERSION]: config.serviceVersion } : {},
71
+ ...config.attributes
72
+ }),
73
+ spanProcessors: resolveProcessors(config.spanProcessor),
74
+ ...config.tracerConfig
75
+ });
76
+ provider.register();
77
+ return provider;
88
78
  }
89
79
 
90
80
  //#endregion
@@ -1,5 +1,5 @@
1
1
  import { EmailConfig } from "../server/types.js";
2
- import { GenericActionCtx, GenericDataModel } from "convex/server";
2
+ import { AnyDataModel, GenericActionCtx } from "convex/server";
3
3
 
4
4
  //#region src/providers/email.d.ts
5
5
  /** Configuration for the {@link email} provider. */
@@ -7,7 +7,7 @@ interface EmailProviderConfig {
7
7
  /** Sender address used for outgoing verification emails. */
8
8
  from: string;
9
9
  /** Delivery callback that actually sends the rendered verification email. */
10
- send: (ctx: GenericActionCtx<GenericDataModel>, opts: {
10
+ send: (ctx: GenericActionCtx<AnyDataModel>, opts: {
11
11
  from: string;
12
12
  to: string;
13
13
  subject: string;