create-vexcms 0.0.20 → 0.1.0-alpha.2
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/LICENSE +202 -0
- package/README.md +93 -83
- package/dist/index.js +246 -81
- package/dist/index.mjs +30976 -0
- package/package.json +35 -15
- package/templates/base-nextjs/README.md +53 -205
- package/templates/base-nextjs/_env.example +7 -9
- package/templates/base-nextjs/_gitignore +41 -1
- package/templates/base-nextjs/convex/_generated/api.d.ts +6 -62
- package/templates/base-nextjs/convex/_generated/server.d.ts +19 -0
- package/templates/base-nextjs/convex/_generated/server.js +8 -0
- package/templates/base-nextjs/convex/auth/api.ts +49 -3
- package/templates/base-nextjs/convex/auth/db.ts +42 -300
- package/templates/base-nextjs/convex/auth/index.ts +11 -7
- package/templates/base-nextjs/convex/auth/options.ts +5 -29
- package/templates/base-nextjs/convex/auth/plugins/index.ts +15 -5
- package/templates/base-nextjs/convex/auth/sessions.ts +9 -15
- package/templates/base-nextjs/convex/http.ts +18 -3
- package/templates/base-nextjs/convex/schema.ts +104 -2
- package/templates/base-nextjs/convex/vex/firstUser.ts +10 -84
- package/templates/base-nextjs/convex/vex/globals.ts +19 -82
- package/templates/base-nextjs/convex/vex/media.ts +19 -246
- package/templates/base-nextjs/convex/vex.schema.ts +138 -0
- package/templates/base-nextjs/convex/vex.ts +19 -0
- package/templates/base-nextjs/convex.json +6 -0
- package/templates/base-nextjs/eslint.config.mjs +1 -21
- package/templates/base-nextjs/next.config.ts +10 -0
- package/templates/base-nextjs/package.json +47 -48
- package/templates/base-nextjs/src/app/(frontend)/@auth/(...)auth/[pathname]/view.tsx +17 -5
- package/templates/base-nextjs/src/app/(frontend)/auth/[pathname]/view.tsx +2 -4
- package/templates/base-nextjs/src/app/(frontend)/layout.tsx +12 -2
- package/templates/base-nextjs/src/app/(frontend)/page.tsx +2 -113
- package/templates/base-nextjs/src/app/(vexcms)/admin/[[...path]]/page.tsx +40 -0
- package/templates/base-nextjs/src/app/(vexcms)/admin/clientProviders.tsx +22 -0
- package/templates/base-nextjs/src/app/(vexcms)/admin/layout.tsx +19 -0
- package/templates/base-nextjs/src/app/globals.css +240 -104
- package/templates/base-nextjs/src/app/layout.tsx +23 -13
- package/templates/base-nextjs/src/app/unauthorized/page.tsx +24 -0
- package/templates/base-nextjs/src/auth/access.ts +46 -0
- package/templates/base-nextjs/src/auth/client.tsx +17 -5
- package/templates/base-nextjs/src/auth/hasPermission.ts +39 -0
- package/templates/base-nextjs/src/auth/serverUtils.ts +15 -25
- package/templates/base-nextjs/src/components/WelcomePage.tsx +116 -0
- package/templates/base-nextjs/src/components/component-example.tsx +56 -464
- package/templates/base-nextjs/src/components/providers/auth.tsx +13 -0
- package/templates/base-nextjs/src/components/providers/client.tsx +6 -1
- package/templates/base-nextjs/src/components/providers/convex.tsx +53 -21
- package/templates/base-nextjs/src/components/providers/server.tsx +10 -7
- package/templates/{marketing-site → base-nextjs}/src/components/ui/accordion.tsx +30 -32
- package/templates/base-nextjs/src/components/ui/badge.tsx +10 -13
- package/templates/base-nextjs/src/components/ui/input.tsx +35 -5
- package/templates/base-nextjs/src/context/AuthContext.tsx +29 -0
- package/templates/base-nextjs/src/db/constants/auth.ts +0 -1
- package/templates/base-nextjs/src/db/constants/index.ts +22 -35
- package/templates/base-nextjs/src/lib/utils.ts +0 -12
- package/templates/base-nextjs/src/proxy.ts +97 -12
- package/templates/base-nextjs/src/vex.config.ts +35 -0
- package/templates/base-nextjs/src/vex.types.ts +293 -0
- package/templates/base-nextjs/src/vexcms/collections/images.ts +15 -0
- package/templates/base-nextjs/src/vexcms/collections/index.ts +2 -1
- package/templates/base-nextjs/src/vexcms/collections/users.ts +7 -35
- package/templates/base-nextjs/tsconfig.json +3 -0
- package/templates/marketing-site/convex/_generated/api.d.ts +81 -0
- package/templates/marketing-site/convex/_generated/api.js +23 -0
- package/templates/marketing-site/convex/_generated/dataModel.d.ts +60 -0
- package/templates/marketing-site/convex/_generated/server.d.ts +162 -0
- package/templates/marketing-site/convex/_generated/server.js +101 -0
- package/templates/marketing-site/convex/footers.ts +11 -7
- package/templates/marketing-site/convex/headers.ts +15 -5
- package/templates/marketing-site/convex/pages.ts +20 -35
- package/templates/marketing-site/convex/schema.ts +119 -0
- package/templates/marketing-site/convex/seed.ts +582 -35
- package/templates/marketing-site/convex/siteSettings.ts +19 -5
- package/templates/marketing-site/convex/theme.ts +55 -61
- package/templates/marketing-site/convex/vex.schema.ts +355 -0
- package/templates/marketing-site/src/app/(frontend)/PageContent.tsx +27 -160
- package/templates/marketing-site/src/app/(frontend)/[slug]/page.tsx +6 -9
- package/templates/marketing-site/src/app/(frontend)/layout.tsx +4 -2
- package/templates/marketing-site/src/app/(frontend)/page.tsx +2 -5
- package/templates/marketing-site/src/components/SiteFooter.tsx +6 -3
- package/templates/marketing-site/src/components/SiteHeader.tsx +6 -3
- package/templates/marketing-site/src/components/ThemeLive.tsx +59 -0
- package/templates/marketing-site/src/components/ThemeStyle.tsx +45 -89
- package/templates/marketing-site/src/lib/metadata.ts +51 -72
- package/templates/marketing-site/src/vex.config.ts +35 -0
- package/templates/marketing-site/src/vex.types.ts +634 -0
- package/templates/marketing-site/src/vexcms/api.ts +23 -0
- package/templates/marketing-site/src/vexcms/blocks/CTA/config.ts +3 -3
- package/templates/marketing-site/src/vexcms/blocks/CTA/index.tsx +2 -2
- package/templates/marketing-site/src/vexcms/blocks/FAQ/config.ts +4 -4
- package/templates/marketing-site/src/vexcms/blocks/FAQ/index.tsx +2 -2
- package/templates/marketing-site/src/vexcms/blocks/Features/config.ts +4 -8
- package/templates/marketing-site/src/vexcms/blocks/Features/index.tsx +2 -2
- package/templates/marketing-site/src/vexcms/blocks/Footer/config.ts +7 -11
- package/templates/marketing-site/src/vexcms/blocks/Footer/index.tsx +1 -1
- package/templates/marketing-site/src/vexcms/blocks/Header/config.ts +9 -9
- package/templates/marketing-site/src/vexcms/blocks/Header/index.tsx +4 -5
- package/templates/marketing-site/src/vexcms/blocks/Hero/config.ts +3 -4
- package/templates/marketing-site/src/vexcms/blocks/Hero/index.tsx +10 -19
- package/templates/marketing-site/src/vexcms/blocks/HowItWorks/config.ts +4 -9
- package/templates/marketing-site/src/vexcms/blocks/HowItWorks/index.tsx +3 -6
- package/templates/marketing-site/src/vexcms/blocks/Roadmap/config.ts +28 -68
- package/templates/marketing-site/src/vexcms/blocks/Roadmap/index.tsx +13 -43
- package/templates/marketing-site/src/vexcms/blocks/config.ts +7 -22
- package/templates/marketing-site/src/vexcms/blocks/constants.ts +2 -3
- package/templates/marketing-site/src/vexcms/blocks/index.ts +9 -8
- package/templates/marketing-site/src/vexcms/collections/footers.ts +1 -1
- package/templates/marketing-site/src/vexcms/collections/headers.ts +1 -1
- package/templates/marketing-site/src/vexcms/collections/index.ts +2 -1
- package/templates/marketing-site/src/vexcms/collections/pages.ts +12 -21
- package/templates/marketing-site/src/vexcms/collections/themeColors.ts +118 -0
- package/templates/marketing-site/src/vexcms/collections/themes.ts +29 -111
- package/templates/marketing-site/src/vexcms/globals/index.ts +1 -1
- package/templates/marketing-site/src/vexcms/globals/siteSettings.ts +43 -27
- package/templates/base-nextjs/convex/auth/adapter/index.ts +0 -230
- package/templates/base-nextjs/convex/auth/adapter/utils.ts +0 -547
- package/templates/base-nextjs/convex/auth/config.ts +0 -10
- package/templates/base-nextjs/convex/vex/auth.ts +0 -38
- package/templates/base-nextjs/convex/vex/collections.ts +0 -333
- package/templates/base-nextjs/convex/vex/helpers.ts +0 -33
- package/templates/base-nextjs/convex/vex/impersonation.ts +0 -51
- package/templates/base-nextjs/convex/vex/migrate.ts +0 -74
- package/templates/base-nextjs/convex/vex/model/collections.ts +0 -196
- package/templates/base-nextjs/convex/vex/model/media.ts +0 -87
- package/templates/base-nextjs/convex/vex/model/versions.ts +0 -254
- package/templates/base-nextjs/convex/vex/previewSnapshot.ts +0 -53
- package/templates/base-nextjs/convex/vex/versions.ts +0 -648
- package/templates/base-nextjs/src/app/admin/AdminLayoutWrapper.tsx +0 -33
- package/templates/base-nextjs/src/app/admin/AdminPageWrapper.tsx +0 -38
- package/templates/base-nextjs/src/app/admin/RichTextFieldWithMedia.tsx +0 -101
- package/templates/base-nextjs/src/app/admin/[[...path]]/page.tsx +0 -15
- package/templates/base-nextjs/src/app/admin/layout.tsx +0 -51
- package/templates/base-nextjs/src/app/favicon.ico +0 -0
- package/templates/base-nextjs/src/components/providers/theme.tsx +0 -11
- package/templates/base-nextjs/src/components/ui/theme-toggle.tsx +0 -67
- package/templates/base-nextjs/src/db/types.ts +0 -6
- package/templates/base-nextjs/src/vexcms/access.ts +0 -44
- package/templates/base-nextjs/src/vexcms/auth.ts +0 -4
- package/templates/base-nextjs/src/vexcms/collections/media.ts +0 -15
- package/templates/base-nextjs/vex.config.ts +0 -25
- package/templates/marketing-site/public/favicons/favicon.ico +0 -0
- package/templates/marketing-site/src/app/(frontend)/preview/[slug]/PreviewPageContent.tsx +0 -55
- package/templates/marketing-site/src/app/(frontend)/preview/[slug]/page.tsx +0 -27
- package/templates/marketing-site/src/app/(frontend)/preview/layout.tsx +0 -18
- package/templates/marketing-site/src/app/admin/AdminLayoutWrapper.tsx +0 -71
- package/templates/marketing-site/src/components/ThemeInjector.tsx +0 -128
- package/templates/marketing-site/src/components/admin/IconPickerField.tsx +0 -134
- package/templates/marketing-site/src/components/admin/ThemeImport.tsx +0 -174
- package/templates/marketing-site/src/components/admin/ThemeImportField.tsx +0 -33
- package/templates/marketing-site/src/db/constants/index.ts +0 -52
- package/templates/marketing-site/src/lib/colorConvert.ts +0 -171
- package/templates/marketing-site/src/vexcms/access.ts +0 -36
- package/templates/marketing-site/vex.config.ts +0 -32
|
@@ -1,57 +1,73 @@
|
|
|
1
1
|
import { defineGlobal, relationship, text, upload } from "@vexcms/core"
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { TABLE_SLUG_IMAGES, TABLE_SLUG_THEMES } from "~/db/constants"
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Site-wide settings — a singleton `vex_globals` row, not a collection.
|
|
7
|
+
*
|
|
8
|
+
* `activeTheme` is what makes the `themes` collection do something: the root
|
|
9
|
+
* layout follows it. `adminTheme` is optional — leaving it unset (the
|
|
10
|
+
* default) means the admin panel wears the site's theme, matching
|
|
11
|
+
* `apps/test/convex/theme.ts`'s `getAdmin` fallback.
|
|
12
|
+
*/
|
|
5
13
|
export const siteSettings = defineGlobal({
|
|
6
|
-
slug:
|
|
14
|
+
slug: "siteSettings",
|
|
15
|
+
label: "Site Settings",
|
|
7
16
|
admin: {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
url: "/preview/home",
|
|
11
|
-
},
|
|
12
|
-
useAsTitle: "name",
|
|
17
|
+
icon: "Settings",
|
|
18
|
+
description: "Site name, SEO defaults, and the themes applied to the site and the admin panel.",
|
|
13
19
|
},
|
|
14
20
|
fields: {
|
|
15
21
|
name: text({
|
|
16
22
|
label: "Site Name",
|
|
17
23
|
required: true,
|
|
24
|
+
description: "Used as fallback for logo text, page titles, and meta tags.",
|
|
25
|
+
}),
|
|
26
|
+
description: text({
|
|
27
|
+
label: "Site Description",
|
|
18
28
|
}),
|
|
19
29
|
activeTheme: relationship({
|
|
30
|
+
collection: { slug: TABLE_SLUG_THEMES },
|
|
31
|
+
hasMany: false,
|
|
20
32
|
label: "Active Theme",
|
|
21
|
-
|
|
33
|
+
description: "The theme applied to the public site.",
|
|
22
34
|
}),
|
|
23
|
-
|
|
24
|
-
|
|
35
|
+
adminTheme: relationship({
|
|
36
|
+
collection: { slug: TABLE_SLUG_THEMES },
|
|
37
|
+
hasMany: false,
|
|
38
|
+
label: "Admin Theme",
|
|
39
|
+
description: "Optional. Leave empty and the admin panel uses the Active Theme.",
|
|
25
40
|
}),
|
|
26
41
|
favicon: upload({
|
|
27
|
-
|
|
42
|
+
to: TABLE_SLUG_IMAGES,
|
|
28
43
|
label: "Favicon",
|
|
29
|
-
|
|
44
|
+
description: "Site favicon image",
|
|
30
45
|
}),
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
46
|
+
metaTitle: text({
|
|
47
|
+
label: "Meta Title",
|
|
48
|
+
description: "Default <title> tag for the site",
|
|
49
|
+
admin: { position: "sidebar" },
|
|
34
50
|
}),
|
|
35
51
|
metaDescription: text({
|
|
36
|
-
admin: { description: "Default meta description for SEO" },
|
|
37
52
|
label: "Meta Description",
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
admin: { description: "Default <title> tag for the site" },
|
|
41
|
-
label: "Meta Title",
|
|
53
|
+
description: "Default meta description for SEO",
|
|
54
|
+
admin: { position: "sidebar" },
|
|
42
55
|
}),
|
|
43
56
|
ogImage: upload({
|
|
44
|
-
|
|
57
|
+
to: TABLE_SLUG_IMAGES,
|
|
45
58
|
label: "OG Image",
|
|
46
|
-
|
|
59
|
+
description: "Default Open Graph image for social sharing",
|
|
60
|
+
admin: { position: "sidebar" },
|
|
47
61
|
}),
|
|
48
62
|
twitterHandle: text({
|
|
49
|
-
admin: { description: "@handle for Twitter cards" },
|
|
50
63
|
label: "Twitter Handle",
|
|
64
|
+
description: "@handle for Twitter cards",
|
|
65
|
+
admin: { position: "sidebar" },
|
|
66
|
+
}),
|
|
67
|
+
googleAnalyticsId: text({
|
|
68
|
+
label: "Google Analytics ID",
|
|
69
|
+
description: "GA4 measurement ID (G-XXXXXXXXXX)",
|
|
70
|
+
admin: { position: "sidebar" },
|
|
51
71
|
}),
|
|
52
|
-
},
|
|
53
|
-
label: "Site Settings",
|
|
54
|
-
versions: {
|
|
55
|
-
drafts: true,
|
|
56
72
|
},
|
|
57
73
|
})
|
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
|
2
|
-
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
|
3
|
-
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
|
4
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
5
|
-
import type { Where } from "better-auth/types"
|
|
6
|
-
import type { GenericActionCtx, GenericDataModel, SchemaDefinition } from "convex/server"
|
|
7
|
-
|
|
8
|
-
import { createAdapterFactory, type DBAdapterDebugLogOption } from "better-auth/adapters"
|
|
9
|
-
import { getAuthTables } from "better-auth/db"
|
|
10
|
-
|
|
11
|
-
import { internal } from "../../_generated/api"
|
|
12
|
-
|
|
13
|
-
type ConvexCleanedWhere = Where & {
|
|
14
|
-
value: boolean | null | number | number[] | string | string[]
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const parseWhere = (where?: Where[]): ConvexCleanedWhere[] => {
|
|
18
|
-
return (where?.map((where) => {
|
|
19
|
-
if (where.value instanceof Date) {
|
|
20
|
-
return {
|
|
21
|
-
...where,
|
|
22
|
-
value: where.value.getTime(),
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
return where
|
|
26
|
-
}) ?? []) as ConvexCleanedWhere[]
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export const convexAdapter = <DataModel extends GenericDataModel>(
|
|
30
|
-
ctx: GenericActionCtx<DataModel>,
|
|
31
|
-
_schema: SchemaDefinition<any, any>,
|
|
32
|
-
config: {
|
|
33
|
-
debugLogs?: DBAdapterDebugLogOption
|
|
34
|
-
} = {}
|
|
35
|
-
) => {
|
|
36
|
-
return createAdapterFactory({
|
|
37
|
-
adapter: ({ options }) => {
|
|
38
|
-
options.telemetry = { enabled: false }
|
|
39
|
-
|
|
40
|
-
// Extract Better Auth schema from the options passed by Better Auth
|
|
41
|
-
const betterAuthSchema = getAuthTables(options)
|
|
42
|
-
const betterAuthSchemaJson = JSON.stringify(betterAuthSchema)
|
|
43
|
-
|
|
44
|
-
return {
|
|
45
|
-
id: "convex",
|
|
46
|
-
|
|
47
|
-
create: async ({ data, model, select }): Promise<any> => {
|
|
48
|
-
return await ctx.runMutation(internal.auth.db.dbCreate, {
|
|
49
|
-
betterAuthSchema: betterAuthSchemaJson,
|
|
50
|
-
data,
|
|
51
|
-
model,
|
|
52
|
-
select,
|
|
53
|
-
})
|
|
54
|
-
},
|
|
55
|
-
|
|
56
|
-
findOne: async ({ model, select, where }): Promise<any> => {
|
|
57
|
-
const parsedWhere = parseWhere(where)
|
|
58
|
-
|
|
59
|
-
return await ctx.runQuery(internal.auth.db.dbFindOne, {
|
|
60
|
-
betterAuthSchema: betterAuthSchemaJson,
|
|
61
|
-
model,
|
|
62
|
-
select,
|
|
63
|
-
where: parsedWhere,
|
|
64
|
-
})
|
|
65
|
-
},
|
|
66
|
-
|
|
67
|
-
findMany: async ({ limit, model, offset, sortBy, where }): Promise<any[]> => {
|
|
68
|
-
if (offset) {
|
|
69
|
-
throw new Error("offset not supported")
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const parsedWhere = parseWhere(where)
|
|
73
|
-
|
|
74
|
-
return await ctx.runQuery(internal.auth.db.dbFindMany, {
|
|
75
|
-
betterAuthSchema: betterAuthSchemaJson,
|
|
76
|
-
limit,
|
|
77
|
-
model,
|
|
78
|
-
sortBy,
|
|
79
|
-
where: parsedWhere,
|
|
80
|
-
})
|
|
81
|
-
},
|
|
82
|
-
|
|
83
|
-
count: async ({ model, where }): Promise<number> => {
|
|
84
|
-
const parsedWhere = parseWhere(where)
|
|
85
|
-
|
|
86
|
-
return await ctx.runQuery(internal.auth.db.dbCount, {
|
|
87
|
-
betterAuthSchema: betterAuthSchemaJson,
|
|
88
|
-
model,
|
|
89
|
-
where: parsedWhere,
|
|
90
|
-
})
|
|
91
|
-
},
|
|
92
|
-
|
|
93
|
-
update: async ({ model, update, where }): Promise<any> => {
|
|
94
|
-
const parsedWhere = parseWhere(where)
|
|
95
|
-
|
|
96
|
-
return await ctx.runMutation(internal.auth.db.dbUpdate, {
|
|
97
|
-
betterAuthSchema: betterAuthSchemaJson,
|
|
98
|
-
model,
|
|
99
|
-
update,
|
|
100
|
-
where: parsedWhere,
|
|
101
|
-
})
|
|
102
|
-
},
|
|
103
|
-
|
|
104
|
-
updateMany: async ({ model, update, where }): Promise<number> => {
|
|
105
|
-
const parsedWhere = parseWhere(where)
|
|
106
|
-
|
|
107
|
-
return await ctx.runMutation(internal.auth.db.dbUpdateMany, {
|
|
108
|
-
betterAuthSchema: betterAuthSchemaJson,
|
|
109
|
-
model,
|
|
110
|
-
update,
|
|
111
|
-
where: parsedWhere,
|
|
112
|
-
})
|
|
113
|
-
},
|
|
114
|
-
|
|
115
|
-
delete: async ({ model, where }): Promise<void> => {
|
|
116
|
-
const parsedWhere = parseWhere(where)
|
|
117
|
-
|
|
118
|
-
await ctx.runMutation(internal.auth.db.dbDelete, {
|
|
119
|
-
betterAuthSchema: betterAuthSchemaJson,
|
|
120
|
-
model,
|
|
121
|
-
where: parsedWhere,
|
|
122
|
-
})
|
|
123
|
-
},
|
|
124
|
-
|
|
125
|
-
deleteMany: async ({ model, where }): Promise<number> => {
|
|
126
|
-
const parsedWhere = parseWhere(where)
|
|
127
|
-
|
|
128
|
-
return await ctx.runMutation(internal.auth.db.dbDeleteMany, {
|
|
129
|
-
betterAuthSchema: betterAuthSchemaJson,
|
|
130
|
-
model,
|
|
131
|
-
where: parsedWhere,
|
|
132
|
-
})
|
|
133
|
-
},
|
|
134
|
-
|
|
135
|
-
// @ts-expect-error - Better Auth adapter interface doesn't export transaction callback type
|
|
136
|
-
transaction: async (callback) => {
|
|
137
|
-
// Convex doesn't support traditional transactions
|
|
138
|
-
// All operations in a single mutation are atomic
|
|
139
|
-
|
|
140
|
-
return callback({
|
|
141
|
-
id: "convex",
|
|
142
|
-
// @ts-expect-error - Transaction method args type not exported, unused in stub implementation
|
|
143
|
-
count: async (_args) => {
|
|
144
|
-
throw new Error("Cannot query within transaction")
|
|
145
|
-
},
|
|
146
|
-
// @ts-expect-error - Transaction method args type not exported, unused in stub implementation
|
|
147
|
-
create: async (_args) => {
|
|
148
|
-
throw new Error("Nested transactions not supported")
|
|
149
|
-
},
|
|
150
|
-
// @ts-expect-error - Transaction method args type not exported, unused in stub implementation
|
|
151
|
-
delete: async (_args) => {
|
|
152
|
-
throw new Error("Deletes within transactions not supported")
|
|
153
|
-
},
|
|
154
|
-
// @ts-expect-error - Transaction method args type not exported, unused in stub implementation
|
|
155
|
-
deleteMany: async (_args) => {
|
|
156
|
-
throw new Error("Deletes within transactions not supported")
|
|
157
|
-
},
|
|
158
|
-
// @ts-expect-error - Transaction method args type not exported, unused in stub implementation
|
|
159
|
-
findMany: async (_args) => {
|
|
160
|
-
throw new Error("Cannot query within transaction")
|
|
161
|
-
},
|
|
162
|
-
// @ts-expect-error - Transaction method args type not exported, unused in stub implementation
|
|
163
|
-
findOne: async (_args) => {
|
|
164
|
-
throw new Error("Cannot query within transaction")
|
|
165
|
-
},
|
|
166
|
-
// @ts-expect-error - Transaction method args type not exported, unused in stub implementation
|
|
167
|
-
update: async (_args) => {
|
|
168
|
-
throw new Error("Updates within transactions not supported")
|
|
169
|
-
},
|
|
170
|
-
// @ts-expect-error - Transaction method args type not exported, unused in stub implementation
|
|
171
|
-
updateMany: async (_args) => {
|
|
172
|
-
throw new Error("Updates within transactions not supported")
|
|
173
|
-
},
|
|
174
|
-
})
|
|
175
|
-
},
|
|
176
|
-
}
|
|
177
|
-
},
|
|
178
|
-
config: {
|
|
179
|
-
adapterId: "convex",
|
|
180
|
-
adapterName: "Convex Adapter (Action-based - Full Featured)",
|
|
181
|
-
customTransformInput: ({ data, fieldAttributes }) => {
|
|
182
|
-
if (data && fieldAttributes.type === "date") {
|
|
183
|
-
return new Date(data).getTime()
|
|
184
|
-
}
|
|
185
|
-
// Handle array fields - Better Auth may send single values or arrays
|
|
186
|
-
if ((fieldAttributes.type as string)?.endsWith("[]")) {
|
|
187
|
-
// If already an array, return as-is
|
|
188
|
-
if (Array.isArray(data)) {
|
|
189
|
-
return data
|
|
190
|
-
}
|
|
191
|
-
// If it's a string that looks like JSON array, parse it
|
|
192
|
-
if (typeof data === "string") {
|
|
193
|
-
try {
|
|
194
|
-
const parsed = JSON.parse(data)
|
|
195
|
-
return Array.isArray(parsed) ? parsed : [data]
|
|
196
|
-
} catch {
|
|
197
|
-
// If parsing fails, wrap the string in an array
|
|
198
|
-
return [data]
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
// For any other value type, wrap in array
|
|
202
|
-
if (data !== null && data !== undefined) {
|
|
203
|
-
return [data]
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
return data
|
|
207
|
-
},
|
|
208
|
-
customTransformOutput: ({ data, fieldAttributes }) => {
|
|
209
|
-
if (data && fieldAttributes.type === "date") {
|
|
210
|
-
return new Date(data).getTime()
|
|
211
|
-
}
|
|
212
|
-
// Arrays are stored natively in Convex, no transformation needed for output
|
|
213
|
-
return data
|
|
214
|
-
},
|
|
215
|
-
debugLogs: config.debugLogs ?? false,
|
|
216
|
-
disableIdGeneration: true,
|
|
217
|
-
mapKeysTransformInput: {
|
|
218
|
-
id: "_id",
|
|
219
|
-
},
|
|
220
|
-
mapKeysTransformOutput: {
|
|
221
|
-
_id: "id",
|
|
222
|
-
},
|
|
223
|
-
supportsDates: false,
|
|
224
|
-
supportsJSON: true,
|
|
225
|
-
supportsNumericIds: false,
|
|
226
|
-
transaction: false,
|
|
227
|
-
usePlural: false,
|
|
228
|
-
},
|
|
229
|
-
})
|
|
230
|
-
}
|