create-z3 0.0.40 → 0.0.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/templates/nextjs/convex/auth/adapter/index.ts +14 -3
- package/templates/nextjs/convex/schema.ts +5 -1
- package/templates/tanstack-start/convex/auth/adapter/index.ts +15 -4
- package/templates/tanstack-start/convex/auth/plugins/index.ts +6 -1
- package/templates/tanstack-start/convex/schema.ts +6 -2
- package/templates/tanstack-start/src/lib/auth/client.ts +2 -1
package/package.json
CHANGED
|
@@ -189,15 +189,26 @@ export const convexAdapter = <DataModel extends GenericDataModel>(
|
|
|
189
189
|
if (data && fieldAttributes.type === "date") {
|
|
190
190
|
return new Date(data).getTime();
|
|
191
191
|
}
|
|
192
|
-
// Handle array fields - Better Auth
|
|
192
|
+
// Handle array fields - Better Auth may send single values or arrays
|
|
193
193
|
if ((fieldAttributes.type as string)?.endsWith("[]")) {
|
|
194
|
+
// If already an array, return as-is
|
|
195
|
+
if (Array.isArray(data)) {
|
|
196
|
+
return data
|
|
197
|
+
}
|
|
198
|
+
// If it's a string that looks like JSON array, parse it
|
|
194
199
|
if (typeof data === "string") {
|
|
195
200
|
try {
|
|
196
|
-
|
|
201
|
+
const parsed = JSON.parse(data)
|
|
202
|
+
return Array.isArray(parsed) ? parsed : [data]
|
|
197
203
|
} catch {
|
|
198
|
-
|
|
204
|
+
// If parsing fails, wrap the string in an array
|
|
205
|
+
return [data]
|
|
199
206
|
}
|
|
200
207
|
}
|
|
208
|
+
// For any other value type, wrap in array
|
|
209
|
+
if (data !== null && data !== undefined) {
|
|
210
|
+
return [data]
|
|
211
|
+
}
|
|
201
212
|
}
|
|
202
213
|
return data;
|
|
203
214
|
},
|
|
@@ -6,6 +6,9 @@ import { TABLE_SLUG_ACCOUNTS, TABLE_SLUG_JWKS, TABLE_SLUG_SESSIONS, TABLE_SLUG_U
|
|
|
6
6
|
export default defineSchema({
|
|
7
7
|
// Better Auth component tables (type definitions only - actual tables are in component)
|
|
8
8
|
[TABLE_SLUG_USERS]: defineTable({
|
|
9
|
+
banExpires: v.optional(v.number()), // admin plugin
|
|
10
|
+
banned: v.optional(v.boolean()), // admin plugin
|
|
11
|
+
banReason: v.optional(v.string()), // admin plugin
|
|
9
12
|
displayUsername: v.optional(v.union(v.null(), v.string())),
|
|
10
13
|
name: v.string(),
|
|
11
14
|
username: v.optional(v.union(v.null(), v.string())),
|
|
@@ -16,7 +19,7 @@ export default defineSchema({
|
|
|
16
19
|
isAnonymous: v.optional(v.union(v.null(), v.boolean())),
|
|
17
20
|
phoneNumber: v.optional(v.union(v.null(), v.string())),
|
|
18
21
|
phoneNumberVerified: v.optional(v.union(v.null(), v.boolean())),
|
|
19
|
-
role: v.array(v.string()),
|
|
22
|
+
role: v.array(v.string()), // admin plugin
|
|
20
23
|
twoFactorEnabled: v.optional(v.union(v.null(), v.boolean())),
|
|
21
24
|
updatedAt: v.number(),
|
|
22
25
|
userId: v.optional(v.union(v.null(), v.string()))
|
|
@@ -43,6 +46,7 @@ export default defineSchema({
|
|
|
43
46
|
[TABLE_SLUG_SESSIONS]: defineTable({
|
|
44
47
|
createdAt: v.number(),
|
|
45
48
|
expiresAt: v.number(),
|
|
49
|
+
impersonatedBy: v.optional(v.id(TABLE_SLUG_USERS)), // admin plugin
|
|
46
50
|
ipAddress: v.optional(v.string()),
|
|
47
51
|
token: v.string(),
|
|
48
52
|
updatedAt: v.number(),
|
|
@@ -185,15 +185,26 @@ export const convexAdapter = <DataModel extends GenericDataModel>(
|
|
|
185
185
|
if (data && fieldAttributes.type === "date") {
|
|
186
186
|
return new Date(data).getTime();
|
|
187
187
|
}
|
|
188
|
-
// Handle array fields - Better Auth
|
|
189
|
-
if (fieldAttributes.type
|
|
188
|
+
// Handle array fields - Better Auth may send single values or arrays
|
|
189
|
+
if ((fieldAttributes.type as string)?.endsWith("[]")) {
|
|
190
|
+
// If already an array, return as-is
|
|
191
|
+
if (Array.isArray(data)) {
|
|
192
|
+
return data
|
|
193
|
+
}
|
|
194
|
+
// If it's a string that looks like JSON array, parse it
|
|
190
195
|
if (typeof data === "string") {
|
|
191
196
|
try {
|
|
192
|
-
|
|
197
|
+
const parsed = JSON.parse(data)
|
|
198
|
+
return Array.isArray(parsed) ? parsed : [data]
|
|
193
199
|
} catch {
|
|
194
|
-
|
|
200
|
+
// If parsing fails, wrap the string in an array
|
|
201
|
+
return [data]
|
|
195
202
|
}
|
|
196
203
|
}
|
|
204
|
+
// For any other value type, wrap in array
|
|
205
|
+
if (data !== null && data !== undefined) {
|
|
206
|
+
return [data]
|
|
207
|
+
}
|
|
197
208
|
}
|
|
198
209
|
return data;
|
|
199
210
|
},
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
import { apiKey } from "better-auth/plugins"
|
|
1
|
+
import { admin, apiKey } from "better-auth/plugins"
|
|
2
|
+
import { USER_ROLES } from "~/db/constants"
|
|
2
3
|
|
|
3
4
|
const plugins = [
|
|
5
|
+
admin({
|
|
6
|
+
adminRoles: [USER_ROLES.admin],
|
|
7
|
+
defaultRole: USER_ROLES.user
|
|
8
|
+
}),
|
|
4
9
|
apiKey(),
|
|
5
10
|
]
|
|
6
11
|
|
|
@@ -16,10 +16,13 @@ export default defineSchema({
|
|
|
16
16
|
isAnonymous: v.optional(v.union(v.null(), v.boolean())),
|
|
17
17
|
phoneNumber: v.optional(v.union(v.null(), v.string())),
|
|
18
18
|
phoneNumberVerified: v.optional(v.union(v.null(), v.boolean())),
|
|
19
|
-
role: v.array(v.string()),
|
|
20
19
|
twoFactorEnabled: v.optional(v.union(v.null(), v.boolean())),
|
|
21
20
|
updatedAt: v.number(),
|
|
22
|
-
userId: v.optional(v.union(v.null(), v.string()))
|
|
21
|
+
userId: v.optional(v.union(v.null(), v.string())),
|
|
22
|
+
banExpires: v.optional(v.number()), // admin plugin
|
|
23
|
+
banned: v.optional(v.boolean()), // admin plugin
|
|
24
|
+
banReason: v.optional(v.string()), // admin plugin
|
|
25
|
+
role: v.array(v.string()), // admin plugin
|
|
23
26
|
})
|
|
24
27
|
.index("by_email", ["email"]),
|
|
25
28
|
|
|
@@ -48,6 +51,7 @@ export default defineSchema({
|
|
|
48
51
|
updatedAt: v.number(),
|
|
49
52
|
userAgent: v.optional(v.string()),
|
|
50
53
|
userId: v.id(TABLE_SLUG_USERS),
|
|
54
|
+
impersonatedBy: v.optional(v.id(TABLE_SLUG_USERS)), // admin plugin
|
|
51
55
|
})
|
|
52
56
|
.index("by_token", ["token"]),
|
|
53
57
|
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { createAuthClient } from "better-auth/react"
|
|
2
|
-
import { apiKeyClient } from "better-auth/client/plugins"
|
|
2
|
+
import { adminClient, apiKeyClient } from "better-auth/client/plugins"
|
|
3
3
|
import { env } from '~/env';
|
|
4
4
|
|
|
5
5
|
export const authClient = createAuthClient({
|
|
6
6
|
basePath: "/api/auth",
|
|
7
7
|
baseURL: env.VITE_SITE_URL, // Point to TanStack Start, which proxies to Convex
|
|
8
8
|
plugins: [
|
|
9
|
+
adminClient(),
|
|
9
10
|
apiKeyClient()
|
|
10
11
|
]
|
|
11
12
|
})
|