@auth/drizzle-adapter 1.0.0 → 1.1.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.
package/src/lib/pg.ts CHANGED
@@ -1,113 +1,117 @@
1
- import { and, eq } from "drizzle-orm"
1
+ import { and, eq, getTableColumns } from "drizzle-orm"
2
2
  import {
3
- timestamp,
4
- text,
5
- primaryKey,
6
- integer,
3
+ PgColumn,
7
4
  PgDatabase,
8
- pgTable,
9
- index,
10
5
  PgTableWithColumns,
11
6
  QueryResultHKT,
12
- TableConfig,
7
+ integer,
8
+ pgTable,
9
+ primaryKey,
10
+ text,
11
+ timestamp,
13
12
  } from "drizzle-orm/pg-core"
14
13
 
15
14
  import type {
16
15
  Adapter,
17
16
  AdapterAccount,
18
- AdapterUser,
17
+ AdapterAccountType,
19
18
  AdapterSession,
19
+ AdapterUser,
20
20
  VerificationToken,
21
21
  } from "@auth/core/adapters"
22
- import { randomUUID } from "crypto"
23
22
 
24
- export const postgresUsersTable = pgTable("user" as string, {
25
- id: text("id")
26
- .primaryKey()
27
- .$defaultFn(() => randomUUID()),
28
- name: text("name"),
29
- email: text("email").notNull().unique(),
30
- emailVerified: timestamp("emailVerified", { mode: "date" }),
31
- image: text("image"),
32
- })
23
+ export function defineTables(
24
+ schema: Partial<DefaultPostgresSchema> = {}
25
+ ): Required<DefaultPostgresSchema> {
26
+ const usersTable =
27
+ schema.usersTable ??
28
+ (pgTable("user", {
29
+ id: text("id")
30
+ .primaryKey()
31
+ .$defaultFn(() => crypto.randomUUID()),
32
+ name: text("name"),
33
+ email: text("email").notNull(),
34
+ emailVerified: timestamp("emailVerified", { mode: "date" }),
35
+ image: text("image"),
36
+ }) satisfies DefaultPostgresUsersTable)
33
37
 
34
- export const postgresAccountsTable = pgTable(
35
- "account" as string,
36
- {
37
- userId: text("userId")
38
- .notNull()
39
- .references(() => postgresUsersTable.id, { onDelete: "cascade" }),
40
- type: text("type").notNull(),
41
- provider: text("provider").notNull(),
42
- providerAccountId: text("providerAccountId").notNull(),
43
- refresh_token: text("refresh_token"),
44
- access_token: text("access_token"),
45
- expires_at: integer("expires_at"),
46
- token_type: text("token_type"),
47
- scope: text("scope"),
48
- id_token: text("id_token"),
49
- session_state: text("session_state"),
50
- },
51
- (table) => {
52
- return {
53
- userIdIdx: index().on(table.userId),
54
- compositePk: primaryKey({
55
- columns: [table.provider, table.providerAccountId],
56
- }),
57
- }
58
- }
59
- )
38
+ const accountsTable =
39
+ schema.accountsTable ??
40
+ (pgTable(
41
+ "account",
42
+ {
43
+ userId: text("userId")
44
+ .notNull()
45
+ .references(() => usersTable.id, { onDelete: "cascade" }),
46
+ type: text("type").$type<AdapterAccountType>().notNull(),
47
+ provider: text("provider").notNull(),
48
+ providerAccountId: text("providerAccountId").notNull(),
49
+ refresh_token: text("refresh_token"),
50
+ access_token: text("access_token"),
51
+ expires_at: integer("expires_at"),
52
+ token_type: text("token_type"),
53
+ scope: text("scope"),
54
+ id_token: text("id_token"),
55
+ session_state: text("session_state"),
56
+ },
57
+ (table) => {
58
+ return {
59
+ compositePk: primaryKey({
60
+ columns: [table.provider, table.providerAccountId],
61
+ }),
62
+ }
63
+ }
64
+ ) satisfies DefaultPostgresAccountsTable)
60
65
 
61
- export const postgresSessionsTable = pgTable(
62
- "session" as string,
63
- {
64
- id: text("id")
65
- .primaryKey()
66
- .$defaultFn(() => randomUUID()),
67
- sessionToken: text("sessionToken").notNull().unique(),
68
- userId: text("userId")
69
- .notNull()
70
- .references(() => postgresUsersTable.id, { onDelete: "cascade" }),
71
- expires: timestamp("expires", { mode: "date" }).notNull(),
72
- },
73
- (table) => {
74
- return {
75
- userIdIdx: index().on(table.userId),
76
- }
77
- }
78
- )
66
+ const sessionsTable =
67
+ schema.sessionsTable ??
68
+ (pgTable("session", {
69
+ sessionToken: text("sessionToken").primaryKey(),
70
+ userId: text("userId")
71
+ .notNull()
72
+ .references(() => usersTable.id, { onDelete: "cascade" }),
73
+ expires: timestamp("expires", { mode: "date" }).notNull(),
74
+ }) satisfies DefaultPostgresSessionsTable)
79
75
 
80
- export const postgresVerificationTokensTable = pgTable(
81
- "verificationToken" as string,
82
- {
83
- identifier: text("identifier").notNull(),
84
- token: text("token").notNull().unique(),
85
- expires: timestamp("expires", { mode: "date" }).notNull(),
86
- },
87
- (table) => {
88
- return {
89
- compositePk: primaryKey({ columns: [table.identifier, table.token] }),
90
- }
76
+ const verificationTokensTable =
77
+ schema.verificationTokensTable ??
78
+ (pgTable(
79
+ "verificationToken",
80
+ {
81
+ identifier: text("identifier").notNull(),
82
+ token: text("token").notNull(),
83
+ expires: timestamp("expires", { mode: "date" }).notNull(),
84
+ },
85
+ (table) => {
86
+ return {
87
+ compositePk: primaryKey({ columns: [table.identifier, table.token] }),
88
+ }
89
+ }
90
+ ) satisfies DefaultPostgresVerificationTokenTable)
91
+
92
+ return {
93
+ usersTable,
94
+ accountsTable,
95
+ sessionsTable,
96
+ verificationTokensTable,
91
97
  }
92
- )
98
+ }
93
99
 
94
100
  export function PostgresDrizzleAdapter(
95
101
  client: PgDatabase<QueryResultHKT, any>,
96
- schema: DefaultPostgresSchema = {
97
- usersTable: postgresUsersTable,
98
- accountsTable: postgresAccountsTable,
99
- sessionsTable: postgresSessionsTable,
100
- verificationTokensTable: postgresVerificationTokensTable,
101
- }
102
+ schema?: DefaultPostgresSchema
102
103
  ): Adapter {
103
104
  const { usersTable, accountsTable, sessionsTable, verificationTokensTable } =
104
- schema
105
+ defineTables(schema)
105
106
 
106
107
  return {
107
- async createUser(data: Omit<AdapterUser, "id">) {
108
+ async createUser(data: AdapterUser) {
109
+ const { id, ...insertData } = data
110
+ const hasDefaultId = getTableColumns(usersTable)["id"]["hasDefault"]
111
+
108
112
  return client
109
113
  .insert(usersTable)
110
- .values(data)
114
+ .values(hasDefaultId ? insertData : { ...insertData, id })
111
115
  .returning()
112
116
  .then((res) => res[0])
113
117
  },
@@ -239,18 +243,192 @@ export function PostgresDrizzleAdapter(
239
243
  }
240
244
  }
241
245
 
242
- export type PostgresTableFn<T extends TableConfig> = PgTableWithColumns<{
243
- name: T["name"]
244
- columns: T["columns"]
245
- dialect: T["dialect"]
246
+ type DefaultPostgresColumn<
247
+ T extends {
248
+ data: string | number | Date
249
+ dataType: "string" | "number" | "date"
250
+ notNull: boolean
251
+ columnType: "PgVarchar" | "PgText" | "PgTimestamp" | "PgInteger" | "PgUUID"
252
+ },
253
+ > = PgColumn<{
254
+ name: string
255
+ columnType: T["columnType"]
256
+ data: T["data"]
257
+ driverParam: string | number
258
+ notNull: T["notNull"]
259
+ hasDefault: boolean
260
+ enumValues: any
261
+ dataType: T["dataType"]
262
+ tableName: string
263
+ }>
264
+
265
+ export type DefaultPostgresUsersTable = PgTableWithColumns<{
266
+ name: string
267
+ columns: {
268
+ id: DefaultPostgresColumn<{
269
+ columnType: "PgVarchar" | "PgText" | "PgUUID"
270
+ data: string
271
+ notNull: true
272
+ dataType: "string"
273
+ }>
274
+ name: DefaultPostgresColumn<{
275
+ columnType: "PgVarchar" | "PgText"
276
+ data: string
277
+ notNull: boolean
278
+ dataType: "string"
279
+ }>
280
+ email: DefaultPostgresColumn<{
281
+ columnType: "PgVarchar" | "PgText"
282
+ data: string
283
+ notNull: true
284
+ dataType: "string"
285
+ }>
286
+ emailVerified: DefaultPostgresColumn<{
287
+ dataType: "date"
288
+ columnType: "PgTimestamp"
289
+ data: Date
290
+ notNull: boolean
291
+ }>
292
+ image: DefaultPostgresColumn<{
293
+ dataType: "string"
294
+ columnType: "PgVarchar" | "PgText"
295
+ data: string
296
+ notNull: boolean
297
+ }>
298
+ }
299
+ dialect: "pg"
300
+ schema: string | undefined
301
+ }>
302
+
303
+ export type DefaultPostgresAccountsTable = PgTableWithColumns<{
304
+ name: string
305
+ columns: {
306
+ userId: DefaultPostgresColumn<{
307
+ columnType: "PgVarchar" | "PgText" | "PgUUID"
308
+ data: string
309
+ notNull: true
310
+ dataType: "string"
311
+ }>
312
+ type: DefaultPostgresColumn<{
313
+ columnType: "PgVarchar" | "PgText"
314
+ data: string
315
+ notNull: true
316
+ dataType: "string"
317
+ }>
318
+ provider: DefaultPostgresColumn<{
319
+ columnType: "PgVarchar" | "PgText"
320
+ data: string
321
+ notNull: true
322
+ dataType: "string"
323
+ }>
324
+ providerAccountId: DefaultPostgresColumn<{
325
+ dataType: "string"
326
+ columnType: "PgVarchar" | "PgText"
327
+ data: string
328
+ notNull: true
329
+ }>
330
+ refresh_token: DefaultPostgresColumn<{
331
+ dataType: "string"
332
+ columnType: "PgVarchar" | "PgText"
333
+ data: string
334
+ notNull: boolean
335
+ }>
336
+ access_token: DefaultPostgresColumn<{
337
+ dataType: "string"
338
+ columnType: "PgVarchar" | "PgText"
339
+ data: string
340
+ notNull: boolean
341
+ }>
342
+ expires_at: DefaultPostgresColumn<{
343
+ dataType: "number"
344
+ columnType: "PgInteger"
345
+ data: number
346
+ notNull: boolean
347
+ }>
348
+ token_type: DefaultPostgresColumn<{
349
+ dataType: "string"
350
+ columnType: "PgVarchar" | "PgText"
351
+ data: string
352
+ notNull: boolean
353
+ }>
354
+ scope: DefaultPostgresColumn<{
355
+ dataType: "string"
356
+ columnType: "PgVarchar" | "PgText"
357
+ data: string
358
+ notNull: boolean
359
+ }>
360
+ id_token: DefaultPostgresColumn<{
361
+ dataType: "string"
362
+ columnType: "PgVarchar" | "PgText"
363
+ data: string
364
+ notNull: boolean
365
+ }>
366
+ session_state: DefaultPostgresColumn<{
367
+ dataType: "string"
368
+ columnType: "PgVarchar" | "PgText"
369
+ data: string
370
+ notNull: boolean
371
+ }>
372
+ }
373
+ dialect: "pg"
374
+ schema: string | undefined
375
+ }>
376
+
377
+ export type DefaultPostgresSessionsTable = PgTableWithColumns<{
378
+ name: string
379
+ columns: {
380
+ sessionToken: DefaultPostgresColumn<{
381
+ columnType: "PgVarchar" | "PgText"
382
+ data: string
383
+ notNull: true
384
+ dataType: "string"
385
+ }>
386
+ userId: DefaultPostgresColumn<{
387
+ columnType: "PgVarchar" | "PgText" | "PgUUID"
388
+ data: string
389
+ notNull: true
390
+ dataType: "string"
391
+ }>
392
+ expires: DefaultPostgresColumn<{
393
+ dataType: "date"
394
+ columnType: "PgTimestamp"
395
+ data: Date
396
+ notNull: true
397
+ }>
398
+ }
399
+ dialect: "pg"
400
+ schema: string | undefined
401
+ }>
402
+
403
+ export type DefaultPostgresVerificationTokenTable = PgTableWithColumns<{
404
+ name: string
405
+ columns: {
406
+ identifier: DefaultPostgresColumn<{
407
+ columnType: "PgVarchar" | "PgText"
408
+ data: string
409
+ notNull: true
410
+ dataType: "string"
411
+ }>
412
+ token: DefaultPostgresColumn<{
413
+ columnType: "PgVarchar" | "PgText"
414
+ data: string
415
+ notNull: true
416
+ dataType: "string"
417
+ }>
418
+ expires: DefaultPostgresColumn<{
419
+ dataType: "date"
420
+ columnType: "PgTimestamp"
421
+ data: Date
422
+ notNull: true
423
+ }>
424
+ }
425
+ dialect: "pg"
246
426
  schema: string | undefined
247
427
  }>
248
428
 
249
429
  export type DefaultPostgresSchema = {
250
- usersTable: PostgresTableFn<(typeof postgresUsersTable)["_"]["config"]>
251
- accountsTable: PostgresTableFn<(typeof postgresAccountsTable)["_"]["config"]>
252
- sessionsTable: PostgresTableFn<(typeof postgresSessionsTable)["_"]["config"]>
253
- verificationTokensTable: PostgresTableFn<
254
- (typeof postgresVerificationTokensTable)["_"]["config"]
255
- >
430
+ usersTable: DefaultPostgresUsersTable
431
+ accountsTable: DefaultPostgresAccountsTable
432
+ sessionsTable?: DefaultPostgresSessionsTable
433
+ verificationTokensTable?: DefaultPostgresVerificationTokenTable
256
434
  }