convex-zen 0.0.1

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 (142) hide show
  1. package/dist/cli/generate.d.ts +14 -0
  2. package/dist/cli/generate.d.ts.map +1 -0
  3. package/dist/cli/generate.js +297 -0
  4. package/dist/cli/generate.js.map +1 -0
  5. package/dist/cli/index.d.ts +3 -0
  6. package/dist/cli/index.d.ts.map +1 -0
  7. package/dist/cli/index.js +111 -0
  8. package/dist/cli/index.js.map +1 -0
  9. package/dist/client/index.d.ts +300 -0
  10. package/dist/client/index.d.ts.map +1 -0
  11. package/dist/client/index.js +434 -0
  12. package/dist/client/index.js.map +1 -0
  13. package/dist/client/plugins/admin.d.ts +92 -0
  14. package/dist/client/plugins/admin.d.ts.map +1 -0
  15. package/dist/client/plugins/admin.js +165 -0
  16. package/dist/client/plugins/admin.js.map +1 -0
  17. package/dist/client/primitives.d.ts +57 -0
  18. package/dist/client/primitives.d.ts.map +1 -0
  19. package/dist/client/primitives.js +64 -0
  20. package/dist/client/primitives.js.map +1 -0
  21. package/dist/client/providers.d.ts +14 -0
  22. package/dist/client/providers.d.ts.map +1 -0
  23. package/dist/client/providers.js +25 -0
  24. package/dist/client/providers.js.map +1 -0
  25. package/dist/client/react.d.ts +23 -0
  26. package/dist/client/react.d.ts.map +1 -0
  27. package/dist/client/react.js +48 -0
  28. package/dist/client/react.js.map +1 -0
  29. package/dist/client/tanstack-start-client-plugins.d.ts +34 -0
  30. package/dist/client/tanstack-start-client-plugins.d.ts.map +1 -0
  31. package/dist/client/tanstack-start-client-plugins.js +32 -0
  32. package/dist/client/tanstack-start-client-plugins.js.map +1 -0
  33. package/dist/client/tanstack-start-client.d.ts +52 -0
  34. package/dist/client/tanstack-start-client.d.ts.map +1 -0
  35. package/dist/client/tanstack-start-client.js +130 -0
  36. package/dist/client/tanstack-start-client.js.map +1 -0
  37. package/dist/client/tanstack-start-plugins.d.ts +27 -0
  38. package/dist/client/tanstack-start-plugins.d.ts.map +1 -0
  39. package/dist/client/tanstack-start-plugins.js +145 -0
  40. package/dist/client/tanstack-start-plugins.js.map +1 -0
  41. package/dist/client/tanstack-start.d.ts +130 -0
  42. package/dist/client/tanstack-start.d.ts.map +1 -0
  43. package/dist/client/tanstack-start.js +331 -0
  44. package/dist/client/tanstack-start.js.map +1 -0
  45. package/dist/component/_generated/api.d.ts +50 -0
  46. package/dist/component/_generated/api.d.ts.map +1 -0
  47. package/dist/component/_generated/api.js +31 -0
  48. package/dist/component/_generated/api.js.map +1 -0
  49. package/dist/component/_generated/component.d.ts +92 -0
  50. package/dist/component/_generated/component.d.ts.map +1 -0
  51. package/dist/component/_generated/component.js +11 -0
  52. package/dist/component/_generated/component.js.map +1 -0
  53. package/dist/component/_generated/dataModel.d.ts +46 -0
  54. package/dist/component/_generated/dataModel.d.ts.map +1 -0
  55. package/dist/component/_generated/dataModel.js +11 -0
  56. package/dist/component/_generated/dataModel.js.map +1 -0
  57. package/dist/component/_generated/server.d.ts +121 -0
  58. package/dist/component/_generated/server.d.ts.map +1 -0
  59. package/dist/component/_generated/server.js +78 -0
  60. package/dist/component/_generated/server.js.map +1 -0
  61. package/dist/component/convex.config.d.ts +3 -0
  62. package/dist/component/convex.config.d.ts.map +1 -0
  63. package/dist/component/convex.config.js +4 -0
  64. package/dist/component/convex.config.js.map +1 -0
  65. package/dist/component/core/sessions.d.ts +33 -0
  66. package/dist/component/core/sessions.d.ts.map +1 -0
  67. package/dist/component/core/sessions.js +186 -0
  68. package/dist/component/core/sessions.js.map +1 -0
  69. package/dist/component/core/users.d.ts +19 -0
  70. package/dist/component/core/users.d.ts.map +1 -0
  71. package/dist/component/core/users.js +154 -0
  72. package/dist/component/core/users.js.map +1 -0
  73. package/dist/component/core/verifications.d.ts +34 -0
  74. package/dist/component/core/verifications.d.ts.map +1 -0
  75. package/dist/component/core/verifications.js +135 -0
  76. package/dist/component/core/verifications.js.map +1 -0
  77. package/dist/component/gateway.d.ts +16 -0
  78. package/dist/component/gateway.d.ts.map +1 -0
  79. package/dist/component/gateway.js +229 -0
  80. package/dist/component/gateway.js.map +1 -0
  81. package/dist/component/lib/crypto.d.ts +24 -0
  82. package/dist/component/lib/crypto.d.ts.map +1 -0
  83. package/dist/component/lib/crypto.js +57 -0
  84. package/dist/component/lib/crypto.js.map +1 -0
  85. package/dist/component/lib/rateLimit.d.ts +26 -0
  86. package/dist/component/lib/rateLimit.d.ts.map +1 -0
  87. package/dist/component/lib/rateLimit.js +96 -0
  88. package/dist/component/lib/rateLimit.js.map +1 -0
  89. package/dist/component/lib/validators.d.ts +19 -0
  90. package/dist/component/lib/validators.d.ts.map +1 -0
  91. package/dist/component/lib/validators.js +12 -0
  92. package/dist/component/lib/validators.js.map +1 -0
  93. package/dist/component/plugins/admin.d.ts +72 -0
  94. package/dist/component/plugins/admin.d.ts.map +1 -0
  95. package/dist/component/plugins/admin.js +152 -0
  96. package/dist/component/plugins/admin.js.map +1 -0
  97. package/dist/component/providers/emailPassword.d.ts +49 -0
  98. package/dist/component/providers/emailPassword.d.ts.map +1 -0
  99. package/dist/component/providers/emailPassword.js +316 -0
  100. package/dist/component/providers/emailPassword.js.map +1 -0
  101. package/dist/component/providers/oauth.d.ts +33 -0
  102. package/dist/component/providers/oauth.d.ts.map +1 -0
  103. package/dist/component/providers/oauth.js +256 -0
  104. package/dist/component/providers/oauth.js.map +1 -0
  105. package/dist/component/schema.d.ts +132 -0
  106. package/dist/component/schema.d.ts.map +1 -0
  107. package/dist/component/schema.js +82 -0
  108. package/dist/component/schema.js.map +1 -0
  109. package/dist/types.d.ts +67 -0
  110. package/dist/types.d.ts.map +1 -0
  111. package/dist/types.js +5 -0
  112. package/dist/types.js.map +1 -0
  113. package/package.json +121 -0
  114. package/src/cli/generate.ts +360 -0
  115. package/src/cli/index.ts +133 -0
  116. package/src/client/index.ts +707 -0
  117. package/src/client/plugins/admin.ts +205 -0
  118. package/src/client/primitives.ts +100 -0
  119. package/src/client/providers.ts +35 -0
  120. package/src/client/react.ts +97 -0
  121. package/src/client/tanstack-start-client-plugins.ts +113 -0
  122. package/src/client/tanstack-start-client.ts +259 -0
  123. package/src/client/tanstack-start-plugins.ts +203 -0
  124. package/src/client/tanstack-start.ts +535 -0
  125. package/src/component/_generated/api.ts +70 -0
  126. package/src/component/_generated/component.ts +184 -0
  127. package/src/component/_generated/dataModel.ts +60 -0
  128. package/src/component/_generated/server.ts +156 -0
  129. package/src/component/convex.config.ts +5 -0
  130. package/src/component/core/sessions.ts +228 -0
  131. package/src/component/core/users.ts +199 -0
  132. package/src/component/core/verifications.ts +173 -0
  133. package/src/component/gateway.ts +321 -0
  134. package/src/component/lib/crypto.ts +63 -0
  135. package/src/component/lib/internalApi.ts +66 -0
  136. package/src/component/lib/rateLimit.ts +111 -0
  137. package/src/component/lib/validators.ts +12 -0
  138. package/src/component/plugins/admin.ts +178 -0
  139. package/src/component/providers/emailPassword.ts +374 -0
  140. package/src/component/providers/oauth.ts +324 -0
  141. package/src/component/schema.ts +88 -0
  142. package/src/types.ts +68 -0
@@ -0,0 +1,96 @@
1
+ import { v } from "convex/values";
2
+ import { internalMutation, internalQuery } from "../_generated/server";
3
+ /** Window duration: 10 minutes in milliseconds. */
4
+ const WINDOW_MS = 10 * 60 * 1000;
5
+ /** Max failures before lockout. */
6
+ const MAX_FAILURES = 10;
7
+ /** Lockout duration: 10 minutes. */
8
+ const LOCKOUT_MS = 10 * 60 * 1000;
9
+ /**
10
+ * Check if a key is currently rate limited.
11
+ * Returns { limited: true, retryAfter } if locked, { limited: false } otherwise.
12
+ */
13
+ export const check = internalQuery({
14
+ args: {
15
+ key: v.string(),
16
+ },
17
+ handler: async (ctx, { key }) => {
18
+ const now = Date.now();
19
+ const record = await ctx.db
20
+ .query("rateLimits")
21
+ .withIndex("by_key", (q) => q.eq("key", key))
22
+ .unique();
23
+ if (!record) {
24
+ return { limited: false };
25
+ }
26
+ // Check hard lockout
27
+ if (record.lockedUntil !== undefined && record.lockedUntil > now) {
28
+ return { limited: true, retryAfter: record.lockedUntil - now };
29
+ }
30
+ // Check sliding window count
31
+ const windowAge = now - record.windowStart;
32
+ if (windowAge < WINDOW_MS && record.count >= MAX_FAILURES) {
33
+ return { limited: true, retryAfter: WINDOW_MS - windowAge };
34
+ }
35
+ return { limited: false };
36
+ },
37
+ });
38
+ /**
39
+ * Increment failure count for a key. Applies lockout if threshold reached.
40
+ */
41
+ export const increment = internalMutation({
42
+ args: {
43
+ key: v.string(),
44
+ },
45
+ handler: async (ctx, { key }) => {
46
+ const now = Date.now();
47
+ const record = await ctx.db
48
+ .query("rateLimits")
49
+ .withIndex("by_key", (q) => q.eq("key", key))
50
+ .unique();
51
+ if (!record) {
52
+ await ctx.db.insert("rateLimits", {
53
+ key,
54
+ count: 1,
55
+ windowStart: now,
56
+ });
57
+ return;
58
+ }
59
+ const windowAge = now - record.windowStart;
60
+ let newCount;
61
+ let windowStart;
62
+ if (windowAge >= WINDOW_MS) {
63
+ // New window
64
+ newCount = 1;
65
+ windowStart = now;
66
+ }
67
+ else {
68
+ newCount = record.count + 1;
69
+ windowStart = record.windowStart;
70
+ }
71
+ const lockedUntil = newCount >= MAX_FAILURES ? now + LOCKOUT_MS : record.lockedUntil;
72
+ await ctx.db.patch(record._id, {
73
+ count: newCount,
74
+ windowStart,
75
+ lockedUntil,
76
+ });
77
+ },
78
+ });
79
+ /**
80
+ * Reset rate limit for a key (called on successful auth).
81
+ */
82
+ export const reset = internalMutation({
83
+ args: {
84
+ key: v.string(),
85
+ },
86
+ handler: async (ctx, { key }) => {
87
+ const record = await ctx.db
88
+ .query("rateLimits")
89
+ .withIndex("by_key", (q) => q.eq("key", key))
90
+ .unique();
91
+ if (record) {
92
+ await ctx.db.delete(record._id);
93
+ }
94
+ },
95
+ });
96
+ //# sourceMappingURL=rateLimit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rateLimit.js","sourceRoot":"","sources":["../../../src/component/lib/rateLimit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /** Runtime validator for OAuth provider configuration payloads. */
2
+ export declare const oauthProviderConfigValidator: import("convex/values").VObject<{
3
+ id: string;
4
+ clientId: string;
5
+ clientSecret: string;
6
+ authorizationUrl: string;
7
+ tokenUrl: string;
8
+ userInfoUrl: string;
9
+ scopes: string[];
10
+ }, {
11
+ id: import("convex/values").VString<string, "required">;
12
+ clientId: import("convex/values").VString<string, "required">;
13
+ clientSecret: import("convex/values").VString<string, "required">;
14
+ authorizationUrl: import("convex/values").VString<string, "required">;
15
+ tokenUrl: import("convex/values").VString<string, "required">;
16
+ userInfoUrl: import("convex/values").VString<string, "required">;
17
+ scopes: import("convex/values").VArray<string[], import("convex/values").VString<string, "required">, "required">;
18
+ }, "required", "id" | "clientId" | "clientSecret" | "authorizationUrl" | "tokenUrl" | "userInfoUrl" | "scopes">;
19
+ //# sourceMappingURL=validators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../../../src/component/lib/validators.ts"],"names":[],"mappings":"AAEA,mEAAmE;AACnE,eAAO,MAAM,4BAA4B;;;;;;;;;;;;;;;;+GAQvC,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { v } from "convex/values";
2
+ /** Runtime validator for OAuth provider configuration payloads. */
3
+ export const oauthProviderConfigValidator = v.object({
4
+ id: v.string(),
5
+ clientId: v.string(),
6
+ clientSecret: v.string(),
7
+ authorizationUrl: v.string(),
8
+ tokenUrl: v.string(),
9
+ userInfoUrl: v.string(),
10
+ scopes: v.array(v.string()),
11
+ });
12
+ //# sourceMappingURL=validators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validators.js","sourceRoot":"","sources":["../../../src/component/lib/validators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,eAAe,CAAC;AAElC,mEAAmE;AACnE,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,CAAC,MAAM,CAAC;IACnD,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;IACxB,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE;IAC5B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE;IACvB,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;CAC5B,CAAC,CAAC"}
@@ -0,0 +1,72 @@
1
+ /** List users with cursor-based pagination.
2
+ *
3
+ * paginate() is not available in components, so we use _creationTime as a
4
+ * cursor with .filter() + .take(). The cursor is a stringified _creationTime.
5
+ */
6
+ export declare const listUsers: import("convex/server").RegisteredQuery<"internal", {
7
+ limit?: number;
8
+ cursor?: string;
9
+ actorUserId: import("convex/values").GenericId<"users">;
10
+ }, Promise<{
11
+ users: {
12
+ _id: import("convex/values").GenericId<"users">;
13
+ _creationTime: number;
14
+ name?: string;
15
+ image?: string;
16
+ role?: string;
17
+ banned?: boolean;
18
+ banReason?: string;
19
+ banExpires?: number;
20
+ email: string;
21
+ emailVerified: boolean;
22
+ createdAt: number;
23
+ updatedAt: number;
24
+ }[];
25
+ cursor: string | null;
26
+ isDone: boolean;
27
+ }>>;
28
+ /** Get a single user by ID (admin view). */
29
+ export declare const getUser: import("convex/server").RegisteredQuery<"internal", {
30
+ userId: import("convex/values").GenericId<"users">;
31
+ actorUserId: import("convex/values").GenericId<"users">;
32
+ }, Promise<{
33
+ _id: import("convex/values").GenericId<"users">;
34
+ _creationTime: number;
35
+ name?: string;
36
+ image?: string;
37
+ role?: string;
38
+ banned?: boolean;
39
+ banReason?: string;
40
+ banExpires?: number;
41
+ email: string;
42
+ emailVerified: boolean;
43
+ createdAt: number;
44
+ updatedAt: number;
45
+ } | null>>;
46
+ /**
47
+ * Ban a user. Sets banned=true, banReason, and optional banExpires.
48
+ * Also invalidates all active sessions.
49
+ */
50
+ export declare const banUser: import("convex/server").RegisteredMutation<"internal", {
51
+ expiresAt?: number;
52
+ reason?: string;
53
+ userId: import("convex/values").GenericId<"users">;
54
+ actorUserId: import("convex/values").GenericId<"users">;
55
+ }, Promise<void>>;
56
+ /** Unban a user. Clears ban fields. */
57
+ export declare const unbanUser: import("convex/server").RegisteredMutation<"internal", {
58
+ userId: import("convex/values").GenericId<"users">;
59
+ actorUserId: import("convex/values").GenericId<"users">;
60
+ }, Promise<void>>;
61
+ /** Set a user's role. */
62
+ export declare const setRole: import("convex/server").RegisteredMutation<"internal", {
63
+ role: string;
64
+ userId: import("convex/values").GenericId<"users">;
65
+ actorUserId: import("convex/values").GenericId<"users">;
66
+ }, Promise<void>>;
67
+ /** Delete a user and all associated data. */
68
+ export declare const deleteUser: import("convex/server").RegisteredMutation<"internal", {
69
+ userId: import("convex/values").GenericId<"users">;
70
+ actorUserId: import("convex/values").GenericId<"users">;
71
+ }, Promise<void>>;
72
+ //# sourceMappingURL=admin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin.d.ts","sourceRoot":"","sources":["../../../src/component/plugins/admin.ts"],"names":[],"mappings":"AAiBA;;;;GAIG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;GAkCpB,CAAC;AAEH,4CAA4C;AAC5C,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;UASlB,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,OAAO;;;;;iBA6BlB,CAAC;AAEH,uCAAuC;AACvC,eAAO,MAAM,SAAS;;;iBAkBpB,CAAC;AAEH,yBAAyB;AACzB,eAAO,MAAM,OAAO;;;;iBAiBlB,CAAC;AAEH,6CAA6C;AAC7C,eAAO,MAAM,UAAU;;;iBA6BrB,CAAC"}
@@ -0,0 +1,152 @@
1
+ import { v } from "convex/values";
2
+ import { internalMutation, internalQuery } from "../_generated/server";
3
+ async function assertAdminActor(ctx, actorUserId) {
4
+ const actor = await ctx.db.get(actorUserId);
5
+ if (!actor) {
6
+ throw new Error("Unauthorized");
7
+ }
8
+ if (actor.role !== "admin") {
9
+ throw new Error("Forbidden");
10
+ }
11
+ }
12
+ /** List users with cursor-based pagination.
13
+ *
14
+ * paginate() is not available in components, so we use _creationTime as a
15
+ * cursor with .filter() + .take(). The cursor is a stringified _creationTime.
16
+ */
17
+ export const listUsers = internalQuery({
18
+ args: {
19
+ actorUserId: v.id("users"),
20
+ limit: v.optional(v.number()),
21
+ cursor: v.optional(v.string()),
22
+ },
23
+ handler: async (ctx, args) => {
24
+ await assertAdminActor(ctx, args.actorUserId);
25
+ const limit = args.limit ?? 20;
26
+ let query = ctx.db.query("users").order("asc");
27
+ if (args.cursor) {
28
+ const cursorTime = parseFloat(args.cursor);
29
+ query = query.filter((q) => q.gt(q.field("_creationTime"), cursorTime));
30
+ }
31
+ const rows = await query.take(limit + 1);
32
+ const hasMore = rows.length > limit;
33
+ const page = hasMore ? rows.slice(0, limit) : rows;
34
+ const nextCursor = hasMore && page.length > 0
35
+ ? String(page[page.length - 1]._creationTime)
36
+ : null;
37
+ return {
38
+ users: page,
39
+ cursor: nextCursor,
40
+ isDone: !hasMore,
41
+ };
42
+ },
43
+ });
44
+ /** Get a single user by ID (admin view). */
45
+ export const getUser = internalQuery({
46
+ args: {
47
+ actorUserId: v.id("users"),
48
+ userId: v.id("users"),
49
+ },
50
+ handler: async (ctx, { actorUserId, userId }) => {
51
+ await assertAdminActor(ctx, actorUserId);
52
+ return await ctx.db.get(userId);
53
+ },
54
+ });
55
+ /**
56
+ * Ban a user. Sets banned=true, banReason, and optional banExpires.
57
+ * Also invalidates all active sessions.
58
+ */
59
+ export const banUser = internalMutation({
60
+ args: {
61
+ actorUserId: v.id("users"),
62
+ userId: v.id("users"),
63
+ reason: v.optional(v.string()),
64
+ expiresAt: v.optional(v.number()), // timestamp; undefined = permanent
65
+ },
66
+ handler: async (ctx, { actorUserId, userId, reason, expiresAt }) => {
67
+ await assertAdminActor(ctx, actorUserId);
68
+ const user = await ctx.db.get(userId);
69
+ if (!user)
70
+ throw new Error("User not found");
71
+ await ctx.db.patch(userId, {
72
+ banned: true,
73
+ banReason: reason,
74
+ banExpires: expiresAt,
75
+ updatedAt: Date.now(),
76
+ });
77
+ // Invalidate all active sessions
78
+ const sessions = await ctx.db
79
+ .query("sessions")
80
+ .withIndex("by_userId", (q) => q.eq("userId", userId))
81
+ .collect();
82
+ for (const session of sessions) {
83
+ await ctx.db.delete(session._id);
84
+ }
85
+ },
86
+ });
87
+ /** Unban a user. Clears ban fields. */
88
+ export const unbanUser = internalMutation({
89
+ args: {
90
+ actorUserId: v.id("users"),
91
+ userId: v.id("users"),
92
+ },
93
+ handler: async (ctx, { actorUserId, userId }) => {
94
+ await assertAdminActor(ctx, actorUserId);
95
+ const user = await ctx.db.get(userId);
96
+ if (!user)
97
+ throw new Error("User not found");
98
+ await ctx.db.patch(userId, {
99
+ banned: false,
100
+ banReason: undefined,
101
+ banExpires: undefined,
102
+ updatedAt: Date.now(),
103
+ });
104
+ },
105
+ });
106
+ /** Set a user's role. */
107
+ export const setRole = internalMutation({
108
+ args: {
109
+ actorUserId: v.id("users"),
110
+ userId: v.id("users"),
111
+ role: v.string(),
112
+ },
113
+ handler: async (ctx, { actorUserId, userId, role }) => {
114
+ await assertAdminActor(ctx, actorUserId);
115
+ const user = await ctx.db.get(userId);
116
+ if (!user)
117
+ throw new Error("User not found");
118
+ await ctx.db.patch(userId, {
119
+ role,
120
+ updatedAt: Date.now(),
121
+ });
122
+ },
123
+ });
124
+ /** Delete a user and all associated data. */
125
+ export const deleteUser = internalMutation({
126
+ args: {
127
+ actorUserId: v.id("users"),
128
+ userId: v.id("users"),
129
+ },
130
+ handler: async (ctx, { actorUserId, userId }) => {
131
+ await assertAdminActor(ctx, actorUserId);
132
+ // Delete accounts
133
+ const accounts = await ctx.db
134
+ .query("accounts")
135
+ .withIndex("by_userId", (q) => q.eq("userId", userId))
136
+ .collect();
137
+ for (const account of accounts) {
138
+ await ctx.db.delete(account._id);
139
+ }
140
+ // Delete sessions
141
+ const sessions = await ctx.db
142
+ .query("sessions")
143
+ .withIndex("by_userId", (q) => q.eq("userId", userId))
144
+ .collect();
145
+ for (const session of sessions) {
146
+ await ctx.db.delete(session._id);
147
+ }
148
+ // Delete the user
149
+ await ctx.db.delete(userId);
150
+ },
151
+ });
152
+ //# sourceMappingURL=admin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin.js","sourceRoot":"","sources":["../../../src/component/plugins/admin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Sign up with email and password.
3
+ *
4
+ * Returns the verification code so the host app (via ConvexAuth client)
5
+ * can send the email. Functions cannot be passed as Convex args.
6
+ *
7
+ * Flow:
8
+ * 1. Validate email
9
+ * 2. Check IP rate limit
10
+ * 3. Check email not already registered
11
+ * 4. Hash password with Argon2id
12
+ * 5. Create user + account
13
+ * 6. Generate verification code
14
+ * 7. Return { status: "verification_required", verificationCode }
15
+ */
16
+ export declare const signUp: any;
17
+ /**
18
+ * Sign in with email and password.
19
+ *
20
+ * Flow:
21
+ * 1. Check rate limits (IP + email)
22
+ * 2. Look up account by email
23
+ * 3. Verify Argon2id hash
24
+ * 4. Check banned status
25
+ * 5. Create session
26
+ * 6. Return { sessionToken, userId }
27
+ */
28
+ export declare const signIn: any;
29
+ /**
30
+ * Verify email address with a verification code.
31
+ */
32
+ export declare const verifyEmail: any;
33
+ /**
34
+ * Request a password reset code.
35
+ * Returns the reset code so the host app can send the email.
36
+ * Always returns { status: "sent" } to prevent email enumeration.
37
+ * Returns resetCode only when a real user was found.
38
+ */
39
+ export declare const requestPasswordReset: any;
40
+ /**
41
+ * Reset password using a verification code.
42
+ */
43
+ export declare const resetPassword: any;
44
+ /** Internal mutation to update password hash on an account. */
45
+ export declare const updatePasswordHash: import("convex/server").RegisteredMutation<"internal", {
46
+ accountId: any;
47
+ passwordHash: string;
48
+ }, Promise<void>>;
49
+ //# sourceMappingURL=emailPassword.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emailPassword.d.ts","sourceRoot":"","sources":["../../../src/component/providers/emailPassword.ts"],"names":[],"mappings":"AA4BA;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,MAAM,KA0EjB,CAAC;AAEH;;;;;;;;;;GAUG;AACH,eAAO,MAAM,MAAM,KAyFjB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,WAAW,KA+BtB,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,KA+C/B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,aAAa,KA4CxB,CAAC;AAEH,+DAA+D;AAC/D,eAAO,MAAM,kBAAkB;;;iBAW7B,CAAC"}