@kevinmarrec/create-app 0.4.0 → 0.6.0

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 (43) hide show
  1. package/dist/index.js +1 -1
  2. package/package.json +12 -11
  3. package/template/.vscode/extensions.json +2 -1
  4. package/template/.vscode/settings.json +4 -0
  5. package/template/backend/.env.development +3 -1
  6. package/template/backend/package.json +9 -8
  7. package/template/backend/src/auth/index.ts +23 -0
  8. package/template/backend/src/database/drizzle/config.ts +9 -0
  9. package/template/backend/src/database/index.ts +4 -4
  10. package/template/backend/src/database/migrations/0000_violet_enchantress.sql +49 -0
  11. package/template/backend/src/database/migrations/meta/0000_snapshot.json +292 -7
  12. package/template/backend/src/database/migrations/meta/_journal.json +2 -2
  13. package/template/backend/src/database/schema/accounts.ts +20 -0
  14. package/template/backend/src/database/schema/index.ts +3 -0
  15. package/template/backend/src/database/schema/sessions.ts +15 -0
  16. package/template/backend/src/database/schema/users.ts +7 -3
  17. package/template/backend/src/database/schema/verifications.ts +11 -0
  18. package/template/backend/{env.d.ts → src/env.d.ts} +2 -0
  19. package/template/backend/src/{server.ts → main.ts} +13 -19
  20. package/template/backend/src/orpc/index.ts +65 -0
  21. package/template/backend/src/orpc/middlewares/auth.ts +33 -0
  22. package/template/backend/src/orpc/middlewares/index.ts +1 -0
  23. package/template/backend/src/orpc/router/auth.ts +54 -0
  24. package/template/backend/src/{router → orpc/router}/index.ts +2 -2
  25. package/template/backend/src/{logger.ts → utils/logger.ts} +1 -3
  26. package/template/frontend/package.json +12 -13
  27. package/template/frontend/src/App.vue +96 -10
  28. package/template/frontend/src/composables/auth.ts +31 -0
  29. package/template/frontend/src/composables/index.ts +1 -0
  30. package/template/frontend/src/lib/orpc.ts +6 -1
  31. package/template/knip.config.ts +1 -1
  32. package/template/package.json +9 -9
  33. package/template/backend/src/config/database.ts +0 -11
  34. package/template/backend/src/config/drizzle.ts +0 -10
  35. package/template/backend/src/config/logger.ts +0 -19
  36. package/template/backend/src/config/server.ts +0 -40
  37. package/template/backend/src/database/migrations/0000_white_bishop.sql +0 -6
  38. package/template/backend/src/lib/orpc.ts +0 -10
  39. package/template/backend/src/router/welcome.ts +0 -11
  40. package/template/frontend/src/queries/index.ts +0 -1
  41. package/template/frontend/src/queries/welcome.ts +0 -10
  42. package/template/frontend/src/utils.ts +0 -1
  43. /package/template/frontend/{env.d.ts → src/env.d.ts} +0 -0
package/dist/index.js CHANGED
@@ -8,7 +8,7 @@ import { x } from "tinyexec";
8
8
  import fs from "node:fs/promises";
9
9
 
10
10
  //#region package.json
11
- var version = "0.4.0";
11
+ var version = "0.6.0";
12
12
 
13
13
  //#endregion
14
14
  //#region src/utils/fs.ts
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "@kevinmarrec/create-app",
3
3
  "type": "module",
4
- "version": "0.4.0",
4
+ "version": "0.6.0",
5
+ "packageManager": "bun@1.2.22",
5
6
  "description": "CLI that scaffolds an opinionated Bun & Vue fullstack application.",
6
7
  "author": "Kevin Marrec <kevin@marrec.io>",
7
8
  "license": "MIT",
@@ -49,19 +50,19 @@
49
50
  },
50
51
  "devDependencies": {
51
52
  "@faker-js/faker": "^10.0.0",
52
- "@kevinmarrec/eslint-config": "^1.1.0",
53
- "@kevinmarrec/stylelint-config": "^1.0.0",
54
- "@kevinmarrec/tsconfig": "^1.0.0",
55
- "@types/bun": "^1.2.21",
53
+ "@kevinmarrec/eslint-config": "^1.5.0",
54
+ "@kevinmarrec/stylelint-config": "^1.2.0",
55
+ "@kevinmarrec/tsconfig": "^1.1.0",
56
+ "@types/bun": "^1.2.22",
56
57
  "@vitest/coverage-v8": "^3.2.4",
57
58
  "bumpp": "^10.2.3",
58
- "eslint": "^9.34.0",
59
- "knip": "^5.63.0",
60
- "stylelint": "^16.23.1",
61
- "taze": "^19.4.0",
62
- "tsdown": "^0.14.2",
59
+ "eslint": "^9.36.0",
60
+ "knip": "^5.63.1",
61
+ "stylelint": "^16.24.0",
62
+ "taze": "^19.7.0",
63
+ "tsdown": "^0.15.4",
63
64
  "typescript": "^5.9.2",
64
65
  "vitest": "^3.2.4",
65
- "vue-tsc": "^3.0.6"
66
+ "vue-tsc": "^3.0.7"
66
67
  }
67
68
  }
@@ -6,13 +6,14 @@
6
6
  "antfu.unocss",
7
7
  "dbaeumer.vscode-eslint",
8
8
  "eamodio.gitlens",
9
- "github.copilot",
9
+ "github.vscode-github-actions",
10
10
  "lokalise.i18n-ally",
11
11
  "mikestead.dotenv",
12
12
  "ms-azuretools.vscode-docker",
13
13
  "pkief.material-icon-theme",
14
14
  "redhat.vscode-yaml",
15
15
  "stylelint.vscode-stylelint",
16
+ "vitest.explorer",
16
17
  "vue.volar",
17
18
  "yoavbls.pretty-ts-errors"
18
19
  ]
@@ -51,6 +51,10 @@
51
51
  "vue"
52
52
  ],
53
53
 
54
+ "material-icon-theme.folders.associations": {
55
+ "orpc": "context"
56
+ },
57
+
54
58
  "javascript.format.semicolons": "remove",
55
59
  "javascript.preferences.quoteStyle": "single",
56
60
  "typescript.format.semicolons": "remove",
@@ -1,2 +1,4 @@
1
- NODE_ENV=development
1
+ BETTER_AUTH_SECRET=foo
2
+ BETTER_AUTH_URL=http://localhost:5137
2
3
  DATABASE_URL=dev.db
4
+ NODE_ENV=development
@@ -3,20 +3,21 @@
3
3
  "type": "module",
4
4
  "private": true,
5
5
  "scripts": {
6
- "dev": "bun --watch --no-clear-screen src/server.ts",
7
- "build": "bun build src/server.ts --compile --minify --sourcemap --outfile dist/server",
8
- "db:generate": "bun --bun run drizzle-kit generate --config src/config/drizzle.ts",
9
- "db:migrate": "bun --bun run drizzle-kit migrate --config src/config/drizzle.ts"
6
+ "dev": "bun --watch --no-clear-screen src/main.ts",
7
+ "build": "bun build src/main.ts --compile --minify --sourcemap --outfile dist/server",
8
+ "db:generate": "bun --bun run drizzle-kit generate --config src/database/drizzle/config.ts",
9
+ "db:migrate": "bun --bun run drizzle-kit migrate --config src/database/drizzle/config.ts"
10
10
  },
11
11
  "dependencies": {
12
- "@orpc/server": "^1.8.6",
12
+ "@orpc/server": "^1.8.9",
13
+ "better-auth": "^1.3.13",
13
14
  "drizzle-orm": "^0.44.5",
14
- "pino": "^9.9.0",
15
+ "pino": "^9.11.0",
15
16
  "valibot": "^1.1.0"
16
17
  },
17
18
  "devDependencies": {
18
- "@libsql/client": "^0.15.14",
19
- "@types/bun": "^1.2.21",
19
+ "@libsql/client": "^0.15.15",
20
+ "@types/bun": "^1.2.22",
20
21
  "drizzle-kit": "^0.31.4",
21
22
  "pino-pretty": "^13.1.1"
22
23
  }
@@ -0,0 +1,23 @@
1
+ import { betterAuth } from 'better-auth'
2
+ import { type DB, drizzleAdapter } from 'better-auth/adapters/drizzle'
3
+ import type { BaseLogger } from 'pino'
4
+
5
+ export function createBetterAuth({ db, logger }: { db: DB, logger: BaseLogger }) {
6
+ return betterAuth({
7
+ database: drizzleAdapter(db, {
8
+ provider: 'sqlite',
9
+ usePlural: true,
10
+ }),
11
+ logger: {
12
+ log: (level, message) => {
13
+ if (level === 'error') return
14
+ logger[level](message)
15
+ },
16
+ },
17
+ emailAndPassword: {
18
+ enabled: true,
19
+ },
20
+ })
21
+ }
22
+
23
+ export type Auth = ReturnType<typeof createBetterAuth>
@@ -0,0 +1,9 @@
1
+ import { defineConfig } from 'drizzle-kit'
2
+
3
+ export default defineConfig({
4
+ casing: 'snake_case',
5
+ dialect: 'sqlite',
6
+ dbCredentials: { url: import.meta.env.DATABASE_URL },
7
+ schema: 'src/database/schema',
8
+ out: 'src/database/migrations',
9
+ })
@@ -1,16 +1,16 @@
1
- import { url } from '@backend/config/database'
2
- import { logger } from '@backend/logger'
1
+ import { logger } from '@backend/utils/logger'
3
2
  import { drizzle } from 'drizzle-orm/bun-sqlite'
4
3
 
5
4
  import * as schema from './schema'
6
5
 
7
- export const db = drizzle(url, {
6
+ export const db = drizzle(import.meta.env.DATABASE_URL, {
7
+ casing: 'snake_case',
8
8
  schema,
9
9
  logger: {
10
10
  logQuery: (query, params) => {
11
11
  let msg = `[SQL] ${query}`
12
12
  msg += params.length ? ` [${params}]` : ''
13
- logger.info(msg)
13
+ logger.debug(msg)
14
14
  },
15
15
  },
16
16
  })
@@ -0,0 +1,49 @@
1
+ CREATE TABLE `accounts` (
2
+ `id` text PRIMARY KEY NOT NULL,
3
+ `user_id` text NOT NULL,
4
+ `account_id` text NOT NULL,
5
+ `provider_id` text NOT NULL,
6
+ `id_token` text,
7
+ `access_token` text,
8
+ `access_token_expires_at` integer,
9
+ `refresh_token` text,
10
+ `refresh_token_expires_at` integer,
11
+ `scope` text,
12
+ `password` text,
13
+ `created_at` integer NOT NULL,
14
+ `updated_at` integer NOT NULL,
15
+ FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE cascade
16
+ );
17
+ --> statement-breakpoint
18
+ CREATE TABLE `sessions` (
19
+ `id` text PRIMARY KEY NOT NULL,
20
+ `user_id` text NOT NULL,
21
+ `token` text NOT NULL,
22
+ `expires_at` integer NOT NULL,
23
+ `ip_address` text,
24
+ `user_agent` text,
25
+ `created_at` integer NOT NULL,
26
+ `updated_at` integer NOT NULL,
27
+ FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE cascade
28
+ );
29
+ --> statement-breakpoint
30
+ CREATE UNIQUE INDEX `sessions_token_unique` ON `sessions` (`token`);--> statement-breakpoint
31
+ CREATE TABLE `users` (
32
+ `id` text PRIMARY KEY NOT NULL,
33
+ `name` text NOT NULL,
34
+ `email` text NOT NULL,
35
+ `email_verified` integer DEFAULT false NOT NULL,
36
+ `image` text,
37
+ `created_at` integer NOT NULL,
38
+ `updated_at` integer NOT NULL
39
+ );
40
+ --> statement-breakpoint
41
+ CREATE UNIQUE INDEX `users_email_unique` ON `users` (`email`);--> statement-breakpoint
42
+ CREATE TABLE `verifications` (
43
+ `id` text PRIMARY KEY NOT NULL,
44
+ `identifier` text NOT NULL,
45
+ `value` text NOT NULL,
46
+ `expires_at` integer NOT NULL,
47
+ `created_at` integer NOT NULL,
48
+ `updated_at` integer NOT NULL
49
+ );
@@ -1,18 +1,221 @@
1
1
  {
2
2
  "version": "6",
3
3
  "dialect": "sqlite",
4
- "id": "2570ada9-1704-45ba-b294-429e89874a79",
4
+ "id": "28ff26ce-b417-459e-b30f-4ec14ab62876",
5
5
  "prevId": "00000000-0000-0000-0000-000000000000",
6
6
  "tables": {
7
+ "accounts": {
8
+ "name": "accounts",
9
+ "columns": {
10
+ "id": {
11
+ "name": "id",
12
+ "type": "text",
13
+ "primaryKey": true,
14
+ "notNull": true,
15
+ "autoincrement": false
16
+ },
17
+ "user_id": {
18
+ "name": "user_id",
19
+ "type": "text",
20
+ "primaryKey": false,
21
+ "notNull": true,
22
+ "autoincrement": false
23
+ },
24
+ "account_id": {
25
+ "name": "account_id",
26
+ "type": "text",
27
+ "primaryKey": false,
28
+ "notNull": true,
29
+ "autoincrement": false
30
+ },
31
+ "provider_id": {
32
+ "name": "provider_id",
33
+ "type": "text",
34
+ "primaryKey": false,
35
+ "notNull": true,
36
+ "autoincrement": false
37
+ },
38
+ "id_token": {
39
+ "name": "id_token",
40
+ "type": "text",
41
+ "primaryKey": false,
42
+ "notNull": false,
43
+ "autoincrement": false
44
+ },
45
+ "access_token": {
46
+ "name": "access_token",
47
+ "type": "text",
48
+ "primaryKey": false,
49
+ "notNull": false,
50
+ "autoincrement": false
51
+ },
52
+ "access_token_expires_at": {
53
+ "name": "access_token_expires_at",
54
+ "type": "integer",
55
+ "primaryKey": false,
56
+ "notNull": false,
57
+ "autoincrement": false
58
+ },
59
+ "refresh_token": {
60
+ "name": "refresh_token",
61
+ "type": "text",
62
+ "primaryKey": false,
63
+ "notNull": false,
64
+ "autoincrement": false
65
+ },
66
+ "refresh_token_expires_at": {
67
+ "name": "refresh_token_expires_at",
68
+ "type": "integer",
69
+ "primaryKey": false,
70
+ "notNull": false,
71
+ "autoincrement": false
72
+ },
73
+ "scope": {
74
+ "name": "scope",
75
+ "type": "text",
76
+ "primaryKey": false,
77
+ "notNull": false,
78
+ "autoincrement": false
79
+ },
80
+ "password": {
81
+ "name": "password",
82
+ "type": "text",
83
+ "primaryKey": false,
84
+ "notNull": false,
85
+ "autoincrement": false
86
+ },
87
+ "created_at": {
88
+ "name": "created_at",
89
+ "type": "integer",
90
+ "primaryKey": false,
91
+ "notNull": true,
92
+ "autoincrement": false
93
+ },
94
+ "updated_at": {
95
+ "name": "updated_at",
96
+ "type": "integer",
97
+ "primaryKey": false,
98
+ "notNull": true,
99
+ "autoincrement": false
100
+ }
101
+ },
102
+ "indexes": {},
103
+ "foreignKeys": {
104
+ "accounts_user_id_users_id_fk": {
105
+ "name": "accounts_user_id_users_id_fk",
106
+ "tableFrom": "accounts",
107
+ "tableTo": "users",
108
+ "columnsFrom": [
109
+ "user_id"
110
+ ],
111
+ "columnsTo": [
112
+ "id"
113
+ ],
114
+ "onDelete": "cascade",
115
+ "onUpdate": "no action"
116
+ }
117
+ },
118
+ "compositePrimaryKeys": {},
119
+ "uniqueConstraints": {},
120
+ "checkConstraints": {}
121
+ },
122
+ "sessions": {
123
+ "name": "sessions",
124
+ "columns": {
125
+ "id": {
126
+ "name": "id",
127
+ "type": "text",
128
+ "primaryKey": true,
129
+ "notNull": true,
130
+ "autoincrement": false
131
+ },
132
+ "user_id": {
133
+ "name": "user_id",
134
+ "type": "text",
135
+ "primaryKey": false,
136
+ "notNull": true,
137
+ "autoincrement": false
138
+ },
139
+ "token": {
140
+ "name": "token",
141
+ "type": "text",
142
+ "primaryKey": false,
143
+ "notNull": true,
144
+ "autoincrement": false
145
+ },
146
+ "expires_at": {
147
+ "name": "expires_at",
148
+ "type": "integer",
149
+ "primaryKey": false,
150
+ "notNull": true,
151
+ "autoincrement": false
152
+ },
153
+ "ip_address": {
154
+ "name": "ip_address",
155
+ "type": "text",
156
+ "primaryKey": false,
157
+ "notNull": false,
158
+ "autoincrement": false
159
+ },
160
+ "user_agent": {
161
+ "name": "user_agent",
162
+ "type": "text",
163
+ "primaryKey": false,
164
+ "notNull": false,
165
+ "autoincrement": false
166
+ },
167
+ "created_at": {
168
+ "name": "created_at",
169
+ "type": "integer",
170
+ "primaryKey": false,
171
+ "notNull": true,
172
+ "autoincrement": false
173
+ },
174
+ "updated_at": {
175
+ "name": "updated_at",
176
+ "type": "integer",
177
+ "primaryKey": false,
178
+ "notNull": true,
179
+ "autoincrement": false
180
+ }
181
+ },
182
+ "indexes": {
183
+ "sessions_token_unique": {
184
+ "name": "sessions_token_unique",
185
+ "columns": [
186
+ "token"
187
+ ],
188
+ "isUnique": true
189
+ }
190
+ },
191
+ "foreignKeys": {
192
+ "sessions_user_id_users_id_fk": {
193
+ "name": "sessions_user_id_users_id_fk",
194
+ "tableFrom": "sessions",
195
+ "tableTo": "users",
196
+ "columnsFrom": [
197
+ "user_id"
198
+ ],
199
+ "columnsTo": [
200
+ "id"
201
+ ],
202
+ "onDelete": "cascade",
203
+ "onUpdate": "no action"
204
+ }
205
+ },
206
+ "compositePrimaryKeys": {},
207
+ "uniqueConstraints": {},
208
+ "checkConstraints": {}
209
+ },
7
210
  "users": {
8
211
  "name": "users",
9
212
  "columns": {
10
213
  "id": {
11
214
  "name": "id",
12
- "type": "integer",
215
+ "type": "text",
13
216
  "primaryKey": true,
14
217
  "notNull": true,
15
- "autoincrement": true
218
+ "autoincrement": false
16
219
  },
17
220
  "name": {
18
221
  "name": "name",
@@ -21,15 +224,97 @@
21
224
  "notNull": true,
22
225
  "autoincrement": false
23
226
  },
24
- "createdAt": {
25
- "name": "createdAt",
227
+ "email": {
228
+ "name": "email",
229
+ "type": "text",
230
+ "primaryKey": false,
231
+ "notNull": true,
232
+ "autoincrement": false
233
+ },
234
+ "email_verified": {
235
+ "name": "email_verified",
236
+ "type": "integer",
237
+ "primaryKey": false,
238
+ "notNull": true,
239
+ "autoincrement": false,
240
+ "default": false
241
+ },
242
+ "image": {
243
+ "name": "image",
244
+ "type": "text",
245
+ "primaryKey": false,
246
+ "notNull": false,
247
+ "autoincrement": false
248
+ },
249
+ "created_at": {
250
+ "name": "created_at",
251
+ "type": "integer",
252
+ "primaryKey": false,
253
+ "notNull": true,
254
+ "autoincrement": false
255
+ },
256
+ "updated_at": {
257
+ "name": "updated_at",
258
+ "type": "integer",
259
+ "primaryKey": false,
260
+ "notNull": true,
261
+ "autoincrement": false
262
+ }
263
+ },
264
+ "indexes": {
265
+ "users_email_unique": {
266
+ "name": "users_email_unique",
267
+ "columns": [
268
+ "email"
269
+ ],
270
+ "isUnique": true
271
+ }
272
+ },
273
+ "foreignKeys": {},
274
+ "compositePrimaryKeys": {},
275
+ "uniqueConstraints": {},
276
+ "checkConstraints": {}
277
+ },
278
+ "verifications": {
279
+ "name": "verifications",
280
+ "columns": {
281
+ "id": {
282
+ "name": "id",
283
+ "type": "text",
284
+ "primaryKey": true,
285
+ "notNull": true,
286
+ "autoincrement": false
287
+ },
288
+ "identifier": {
289
+ "name": "identifier",
290
+ "type": "text",
291
+ "primaryKey": false,
292
+ "notNull": true,
293
+ "autoincrement": false
294
+ },
295
+ "value": {
296
+ "name": "value",
297
+ "type": "text",
298
+ "primaryKey": false,
299
+ "notNull": true,
300
+ "autoincrement": false
301
+ },
302
+ "expires_at": {
303
+ "name": "expires_at",
304
+ "type": "integer",
305
+ "primaryKey": false,
306
+ "notNull": true,
307
+ "autoincrement": false
308
+ },
309
+ "created_at": {
310
+ "name": "created_at",
26
311
  "type": "integer",
27
312
  "primaryKey": false,
28
313
  "notNull": true,
29
314
  "autoincrement": false
30
315
  },
31
- "updatedAt": {
32
- "name": "updatedAt",
316
+ "updated_at": {
317
+ "name": "updated_at",
33
318
  "type": "integer",
34
319
  "primaryKey": false,
35
320
  "notNull": true,
@@ -5,8 +5,8 @@
5
5
  {
6
6
  "idx": 0,
7
7
  "version": "6",
8
- "when": 1751572351628,
9
- "tag": "0000_white_bishop",
8
+ "when": 1756502742132,
9
+ "tag": "0000_violet_enchantress",
10
10
  "breakpoints": true
11
11
  }
12
12
  ]
@@ -0,0 +1,20 @@
1
+ import { sqliteTable } from 'drizzle-orm/sqlite-core'
2
+
3
+ import { users } from './users'
4
+
5
+ // https://www.better-auth.com/docs/concepts/database#account
6
+ export const accounts = sqliteTable('accounts', t => ({
7
+ id: t.text().primaryKey(),
8
+ userId: t.text().notNull().references(() => users.id, { onDelete: 'cascade' }),
9
+ accountId: t.text().notNull(),
10
+ providerId: t.text().notNull(),
11
+ idToken: t.text(),
12
+ accessToken: t.text(),
13
+ accessTokenExpiresAt: t.integer({ mode: 'timestamp' }),
14
+ refreshToken: t.text(),
15
+ refreshTokenExpiresAt: t.integer({ mode: 'timestamp' }),
16
+ scope: t.text(),
17
+ password: t.text(),
18
+ createdAt: t.integer({ mode: 'timestamp' }).notNull().$defaultFn(() => new Date()),
19
+ updatedAt: t.integer({ mode: 'timestamp' }).notNull().$defaultFn(() => new Date()).$onUpdate(() => new Date()),
20
+ }))
@@ -1 +1,4 @@
1
+ export * from './accounts'
2
+ export * from './sessions'
1
3
  export * from './users'
4
+ export * from './verifications'
@@ -0,0 +1,15 @@
1
+ import { sqliteTable } from 'drizzle-orm/sqlite-core'
2
+
3
+ import { users } from './users'
4
+
5
+ // https://www.better-auth.com/docs/concepts/database#session
6
+ export const sessions = sqliteTable('sessions', t => ({
7
+ id: t.text().primaryKey(),
8
+ userId: t.text().notNull().references(() => users.id, { onDelete: 'cascade' }),
9
+ token: t.text().notNull().unique(),
10
+ expiresAt: t.integer({ mode: 'timestamp' }).notNull(),
11
+ ipAddress: t.text(),
12
+ userAgent: t.text(),
13
+ createdAt: t.integer({ mode: 'timestamp' }).notNull().$defaultFn(() => new Date()),
14
+ updatedAt: t.integer({ mode: 'timestamp' }).notNull().$defaultFn(() => new Date()).$onUpdate(() => new Date()),
15
+ }))
@@ -1,8 +1,12 @@
1
1
  import { sqliteTable } from 'drizzle-orm/sqlite-core'
2
2
 
3
+ // https://www.better-auth.com/docs/concepts/database#user
3
4
  export const users = sqliteTable('users', t => ({
4
- id: t.integer().primaryKey({ autoIncrement: true }),
5
+ id: t.text().primaryKey(),
5
6
  name: t.text().notNull(),
6
- createdAt: t.integer({ mode: 'timestamp_ms' }).notNull().$defaultFn(() => new Date()),
7
- updatedAt: t.integer({ mode: 'timestamp_ms' }).notNull().$defaultFn(() => new Date()).$onUpdate(() => new Date()),
7
+ email: t.text().notNull().unique(),
8
+ emailVerified: t.integer({ mode: 'boolean' }).notNull().default(false),
9
+ image: t.text(),
10
+ createdAt: t.integer({ mode: 'timestamp' }).notNull().$defaultFn(() => new Date()),
11
+ updatedAt: t.integer({ mode: 'timestamp' }).notNull().$defaultFn(() => new Date()).$onUpdate(() => new Date()),
8
12
  }))
@@ -0,0 +1,11 @@
1
+ import { sqliteTable } from 'drizzle-orm/sqlite-core'
2
+
3
+ // https://www.better-auth.com/docs/concepts/database#verification
4
+ export const verifications = sqliteTable('verifications', t => ({
5
+ id: t.text().primaryKey(),
6
+ identifier: t.text().notNull(),
7
+ value: t.text().notNull(),
8
+ expiresAt: t.integer({ mode: 'timestamp' }).notNull(),
9
+ createdAt: t.integer({ mode: 'timestamp' }).notNull().$defaultFn(() => new Date()),
10
+ updatedAt: t.integer({ mode: 'timestamp' }).notNull().$defaultFn(() => new Date()).$onUpdate(() => new Date()),
11
+ }))
@@ -1,4 +1,6 @@
1
1
  interface ImportMetaEnv {
2
+ readonly BETTER_AUTH_SECRET: string
3
+ readonly BETTER_AUTH_URL: string
2
4
  readonly DATABASE_URL: string
3
5
  readonly LOG_LEVEL: string
4
6
  readonly NODE_ENV: string