From e332a4105ebf66507dd538cd96bc5dfbcf7f2def Mon Sep 17 00:00:00 2001
From: ndom91
Date: Tue, 7 May 2024 13:24:09 +0200
Subject: [PATCH 01/44] chore(docs): specify exact version for simpleweabuthn
peer dep installation
---
docs/pages/getting-started/authentication/webauthn.mdx | 2 +-
docs/pages/getting-started/providers/passkey.mdx | 2 +-
packages/core/src/providers/passkey.ts | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/docs/pages/getting-started/authentication/webauthn.mdx b/docs/pages/getting-started/authentication/webauthn.mdx
index 6b9ac2b2fd..23b51ef342 100644
--- a/docs/pages/getting-started/authentication/webauthn.mdx
+++ b/docs/pages/getting-started/authentication/webauthn.mdx
@@ -25,7 +25,7 @@ Support for more frameworks and adapters are coming soon.
### Install peer dependencies
```bash npm2yarn
-npm install @simplewebauthn/server @simplewebauthn/browser
+npm install @simplewebauthn/server@9.0.3 @simplewebauthn/browser@9.0.1
```
The `@simplewebauthn/browser` peer dependency **is only required for custom signin pages**. If you're using the Auth.js default pages, you can skip installing that peer dependency.
diff --git a/docs/pages/getting-started/providers/passkey.mdx b/docs/pages/getting-started/providers/passkey.mdx
index 77afbcbbb5..9e05bca799 100644
--- a/docs/pages/getting-started/providers/passkey.mdx
+++ b/docs/pages/getting-started/providers/passkey.mdx
@@ -25,7 +25,7 @@ Support for more frameworks and adapters are coming soon.{" "}
### Install peer dependencies
```bash npm2yarn
-npm install @simplewebauthn/browser @simplewebauthn/server
+npm install @simplewebauthn/browser@9.0.1 @simplewebauthn/server@9.0.3
```
The `@simplewebauthn/browser` peer dependency is only required for custom signin pages. If you're using the Auth.js default pages, you can skip installing that peer dependency.
diff --git a/packages/core/src/providers/passkey.ts b/packages/core/src/providers/passkey.ts
index bc388abbf7..d7ff698715 100644
--- a/packages/core/src/providers/passkey.ts
+++ b/packages/core/src/providers/passkey.ts
@@ -22,7 +22,7 @@ import WebAuthn, {
* Install the required peer dependency.
*
* ```npm2yarn
- * npm install @simplewebauthn/browser
+ * npm install @simplewebauthn/browser@9.0.1
* ```
*
* #### Configuration
From ddd82099be86241fdc984e1508adcf0ffef9230a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bal=C3=A1zs=20Orb=C3=A1n?=
Date: Wed, 8 May 2024 14:33:14 +0200
Subject: [PATCH 02/44] chore: Update vercel.json
---
docs/vercel.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/vercel.json b/docs/vercel.json
index 8035482ed4..c3296f0939 100644
--- a/docs/vercel.json
+++ b/docs/vercel.json
@@ -80,7 +80,7 @@
{
"source": "/",
"has": [{ "type": "host", "value": "discord.authjs.dev" }],
- "destination": "https://discord.gg/CGAPMawPng"
+ "destination": "https://discord.gg/nwgKuTPJmj"
},
{
"source": "/reference/next-auth:path(.*)",
From aecc221836fdb15d96ebcb3f5eb30997de1f8614 Mon Sep 17 00:00:00 2001
From: Mykhailo <87205530+realmikesolo@users.noreply.github.com>
Date: Wed, 8 May 2024 18:07:25 +0200
Subject: [PATCH 03/44] fix(drizzle): update schema type & fix issue with
default id (#10750)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: Nico Domino
Co-authored-by: Balázs Orbán
Co-authored-by: Noam Honig
---
.../getting-started/adapters/drizzle.mdx | 15 +-
packages/adapter-drizzle/package.json | 2 +-
packages/adapter-drizzle/src/index.ts | 19 ++-
packages/adapter-drizzle/src/lib/mysql.ts | 142 ++++++++++--------
packages/adapter-drizzle/src/lib/pg.ts | 142 ++++++++++--------
packages/adapter-drizzle/src/lib/sqlite.ts | 136 +++++++++--------
.../test/mysql-multi-project-schema/schema.ts | 41 ++---
.../adapter-drizzle/test/mysql/index.test.ts | 8 +-
packages/adapter-drizzle/test/mysql/schema.ts | 14 +-
.../test/pg-multi-project-schema/schema.ts | 37 ++---
.../adapter-drizzle/test/pg/index.test.ts | 8 +-
packages/adapter-drizzle/test/pg/schema.ts | 14 +-
.../sqlite-multi-project-schema/index.test.ts | 2 +
.../sqlite-multi-project-schema/schema.ts | 37 ++---
.../adapter-drizzle/test/sqlite/index.test.ts | 10 +-
.../adapter-drizzle/test/sqlite/schema.ts | 14 +-
pnpm-lock.yaml | 8 +-
17 files changed, 338 insertions(+), 311 deletions(-)
diff --git a/docs/pages/getting-started/adapters/drizzle.mdx b/docs/pages/getting-started/adapters/drizzle.mdx
index 48aa092cb0..fad55d0b83 100644
--- a/docs/pages/getting-started/adapters/drizzle.mdx
+++ b/docs/pages/getting-started/adapters/drizzle.mdx
@@ -35,7 +35,8 @@ To use this adapter, you must have setup Drizzle ORM and Drizzle Kit in your pro
2. Install a supported database driver to your project, like `@libsql/client`, `mysql2` or `postgres`.
3. Create a `drizzle.config.ts` [file](https://orm.drizzle.team/kit-docs/conf).
4. Generate the initial migration from your schema file with a command like, `drizzle-kit generate:pg`.
-5. Push that migration to your configured database with a command like, `drizzle-kit push:pg`.
+5. Apply migrations by using `migrate()` function or push changes directly to your database with a command like, `drizzle-kit push:pg`.
+6. If your schemas differ from the default ones, pass them as the second parameter to the adapter.
#### Schemas
@@ -53,7 +54,7 @@ import {
} from "drizzle-orm/pg-core"
import postgres from "postgres"
import { drizzle } from "drizzle-orm/postgres-js"
-import type { AdapterAccount } from "next-auth/adapters"
+import type { AdapterAccountType } from "@auth/core/adapters"
const connectionString = "postgres://postgres:postgres@localhost:5432/drizzle"
const pool = postgres(connectionString, { max: 1 })
@@ -76,7 +77,7 @@ export const accounts = pgTable(
userId: text("userId")
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
- type: text("type").$type().notNull(),
+ type: text("type").$type().notNull(),
provider: text("provider").notNull(),
providerAccountId: text("providerAccountId").notNull(),
refresh_token: text("refresh_token"),
@@ -129,7 +130,7 @@ import {
} from "drizzle-orm/mysql-core"
import mysql from "mysql2/promise"
import { drizzle } from "drizzle-orm/mysql2"
-import type { AdapterAccount } from "next-auth/adapters"
+import type { AdapterAccountType } from "@auth/core/adapters"
export const connection = await mysql.createConnection({
host: "host",
@@ -160,7 +161,7 @@ export const accounts = mysqlTable(
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
type: varchar("type", { length: 255 })
- .$type()
+ .$type()
.notNull(),
provider: varchar("provider", { length: 255 }).notNull(),
providerAccountId: varchar("providerAccountId", { length: 255 }).notNull(),
@@ -208,7 +209,7 @@ If you want to modify the schema or add additional fields, you can use the follo
import { integer, sqliteTable, text, primaryKey } from "drizzle-orm/sqlite-core"
import { createClient } from "@libsql/client"
import { drizzle } from "drizzle-orm/libsql"
-import type { AdapterAccount } from "next-auth/adapters"
+import type { AdapterAccountType } from "@auth/core/adapters"
const client = createClient({
url: "DATABASE_URL",
@@ -232,7 +233,7 @@ export const accounts = sqliteTable(
userId: text("userId")
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
- type: text("type").$type().notNull(),
+ type: text("type").$type().notNull(),
provider: text("provider").notNull(),
providerAccountId: text("providerAccountId").notNull(),
refresh_token: text("refresh_token"),
diff --git a/packages/adapter-drizzle/package.json b/packages/adapter-drizzle/package.json
index 5b6a737113..66ab3c7615 100644
--- a/packages/adapter-drizzle/package.json
+++ b/packages/adapter-drizzle/package.json
@@ -53,7 +53,7 @@
"@types/uuid": "^8.3.3",
"better-sqlite3": "^9.4.0",
"drizzle-kit": "^0.20.17",
- "drizzle-orm": "^0.30.8",
+ "drizzle-orm": "^0.30.9",
"mysql2": "^3.9.7",
"postgres": "^3.4.3",
"tsx": "^4.7.0"
diff --git a/packages/adapter-drizzle/src/index.ts b/packages/adapter-drizzle/src/index.ts
index b6df99ed2a..024a72228a 100644
--- a/packages/adapter-drizzle/src/index.ts
+++ b/packages/adapter-drizzle/src/index.ts
@@ -83,11 +83,10 @@ import type { Adapter } from "@auth/core/adapters"
* primaryKey,
* integer
* } from "drizzle-orm/pg-core"
- * import type { AdapterAccount } from '@auth/core/adapters'
- * import { randomUUID } from "crypto"
+ * import type { AdapterAccountType } from '@auth/core/adapters'
*
* export const users = pgTable("user", {
- * id: text("id").primaryKey().$defaultFn(() => randomUUID()),
+ * id: text("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
* name: text("name"),
* email: text("email").notNull(),
* emailVerified: timestamp("emailVerified", { mode: "date" }),
@@ -100,7 +99,7 @@ import type { Adapter } from "@auth/core/adapters"
* userId: text("userId")
* .notNull()
* .references(() => users.id, { onDelete: "cascade" }),
- * type: text("type").notNull(),
+ * type: text("type").$type().notNull(),
* provider: text("provider").notNull(),
* providerAccountId: text("providerAccountId").notNull(),
* refresh_token: text("refresh_token"),
@@ -149,10 +148,10 @@ import type { Adapter } from "@auth/core/adapters"
* primaryKey,
* varchar,
* } from "drizzle-orm/mysql-core"
- * import type { AdapterAccount } from "@auth/core/adapters"
+ * import type { AdapterAccountType } from "@auth/core/adapters"
*
* export const users = mysqlTable("user", {
- * id: varchar("id", { length: 255 }).primaryKey().$defaultFn(() => randomUUID()),
+ * id: varchar("id", { length: 255 }).primaryKey().$defaultFn(() => crypto.randomUUID()),
* name: varchar("name", { length: 255 }),
* email: varchar("email", { length: 255 }).notNull(),
* emailVerified: timestamp("emailVerified", { mode: "date", fsp: 3 }),
@@ -165,7 +164,7 @@ import type { Adapter } from "@auth/core/adapters"
* userId: varchar("userId", { length: 255 })
* .notNull()
* .references(() => users.id, { onDelete: "cascade" }),
- * type: varchar("type", { length: 255 }).notNull(),
+ * type: varchar("type", { length: 255 }).$type().notNull(),
* provider: varchar("provider", { length: 255 }).notNull(),
* providerAccountId: varchar("providerAccountId", { length: 255 }).notNull(),
* refresh_token: varchar("refresh_token", { length: 255 }),
@@ -208,10 +207,10 @@ import type { Adapter } from "@auth/core/adapters"
*
* ```ts title="schema.ts"
* import { integer, sqliteTable, text, primaryKey } from "drizzle-orm/sqlite-core"
- * import type { AdapterAccount } from "@auth/core/adapters"
+ * import type { AdapterAccountType } from "@auth/core/adapters"
*
* export const users = sqliteTable("user", {
- * id: text("id").primaryKey().$defaultFn(() => randomUUID()),
+ * id: text("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
* name: text("name"),
* email: text("email").notNull(),
* emailVerified: integer("emailVerified", { mode: "timestamp_ms" }),
@@ -224,7 +223,7 @@ import type { Adapter } from "@auth/core/adapters"
* userId: text("userId")
* .notNull()
* .references(() => users.id, { onDelete: "cascade" }),
- * type: text("type").notNull(),
+ * type: text("type").$type().notNull(),
* provider: text("provider").notNull(),
* providerAccountId: text("providerAccountId").notNull(),
* refresh_token: text("refresh_token"),
diff --git a/packages/adapter-drizzle/src/lib/mysql.ts b/packages/adapter-drizzle/src/lib/mysql.ts
index 1a786347ff..ba63afa032 100644
--- a/packages/adapter-drizzle/src/lib/mysql.ts
+++ b/packages/adapter-drizzle/src/lib/mysql.ts
@@ -15,86 +15,104 @@ import {
import type {
Adapter,
AdapterAccount,
+ AdapterAccountType,
AdapterSession,
AdapterUser,
VerificationToken,
} from "@auth/core/adapters"
-export const mysqlUsersTable = mysqlTable("user", {
- id: varchar("id", { length: 255 })
- .primaryKey()
- .$defaultFn(() => crypto.randomUUID()),
- name: varchar("name", { length: 255 }),
- email: varchar("email", { length: 255 }).notNull(),
- emailVerified: timestamp("emailVerified", { mode: "date", fsp: 3 }),
- image: varchar("image", { length: 255 }),
-}) satisfies DefaultMySqlUsersTable
+export function defineTables(
+ schema: Partial = {}
+): Required {
+ const usersTable =
+ schema.usersTable ??
+ (mysqlTable("user", {
+ id: varchar("id", { length: 255 })
+ .primaryKey()
+ .$defaultFn(() => crypto.randomUUID()),
+ name: varchar("name", { length: 255 }),
+ email: varchar("email", { length: 255 }).notNull(),
+ emailVerified: timestamp("emailVerified", { mode: "date", fsp: 3 }),
+ image: varchar("image", { length: 255 }),
+ }) satisfies DefaultMySqlUsersTable)
-export const mysqlAccountsTable = mysqlTable(
- "account",
- {
- userId: varchar("userId", { length: 255 })
- .notNull()
- .references(() => mysqlUsersTable.id, { onDelete: "cascade" }),
- type: varchar("type", { length: 255 })
- .$type()
- .notNull(),
- provider: varchar("provider", { length: 255 }).notNull(),
- providerAccountId: varchar("providerAccountId", { length: 255 }).notNull(),
- refresh_token: varchar("refresh_token", { length: 255 }),
- access_token: varchar("access_token", { length: 255 }),
- expires_at: int("expires_at"),
- token_type: varchar("token_type", { length: 255 }),
- scope: varchar("scope", { length: 255 }),
- id_token: varchar("id_token", { length: 2048 }),
- session_state: varchar("session_state", { length: 255 }),
- },
- (account) => ({
- compositePk: primaryKey({
- columns: [account.provider, account.providerAccountId],
- }),
- })
-) satisfies DefaultMySqlAccountsTable
+ const accountsTable =
+ schema.accountsTable ??
+ (mysqlTable(
+ "account",
+ {
+ userId: varchar("userId", { length: 255 })
+ .notNull()
+ .references(() => usersTable.id, { onDelete: "cascade" }),
+ type: varchar("type", { length: 255 })
+ .$type()
+ .notNull(),
+ provider: varchar("provider", { length: 255 }).notNull(),
+ providerAccountId: varchar("providerAccountId", {
+ length: 255,
+ }).notNull(),
+ refresh_token: varchar("refresh_token", { length: 255 }),
+ access_token: varchar("access_token", { length: 255 }),
+ expires_at: int("expires_at"),
+ token_type: varchar("token_type", { length: 255 }),
+ scope: varchar("scope", { length: 255 }),
+ id_token: varchar("id_token", { length: 2048 }),
+ session_state: varchar("session_state", { length: 255 }),
+ },
+ (account) => ({
+ compositePk: primaryKey({
+ columns: [account.provider, account.providerAccountId],
+ }),
+ })
+ ) satisfies DefaultMySqlAccountsTable)
-export const mysqlSessionsTable = mysqlTable("session", {
- sessionToken: varchar("sessionToken", { length: 255 }).primaryKey(),
- userId: varchar("userId", { length: 255 })
- .notNull()
- .references(() => mysqlUsersTable.id, { onDelete: "cascade" }),
- expires: timestamp("expires", { mode: "date" }).notNull(),
-}) satisfies DefaultMySqlSessionsTable
+ const sessionsTable =
+ schema.sessionsTable ??
+ (mysqlTable("session", {
+ sessionToken: varchar("sessionToken", { length: 255 }).primaryKey(),
+ userId: varchar("userId", { length: 255 })
+ .notNull()
+ .references(() => usersTable.id, { onDelete: "cascade" }),
+ expires: timestamp("expires", { mode: "date" }).notNull(),
+ }) satisfies DefaultMySqlSessionsTable)
-export const mysqlVerificationTokensTable = mysqlTable(
- "verificationToken",
- {
- identifier: varchar("identifier", { length: 255 }).notNull(),
- token: varchar("token", { length: 255 }).notNull(),
- expires: timestamp("expires", { mode: "date" }).notNull(),
- },
- (vt) => ({
- compositePk: primaryKey({ columns: [vt.identifier, vt.token] }),
- })
-) satisfies DefaultMySqlVerificationTokenTable
+ const verificationTokensTable =
+ schema.verificationTokensTable ??
+ (mysqlTable(
+ "verificationToken",
+ {
+ identifier: varchar("identifier", { length: 255 }).notNull(),
+ token: varchar("token", { length: 255 }).notNull(),
+ expires: timestamp("expires", { mode: "date" }).notNull(),
+ },
+ (vt) => ({
+ compositePk: primaryKey({ columns: [vt.identifier, vt.token] }),
+ })
+ ) satisfies DefaultMySqlVerificationTokenTable)
+
+ return {
+ usersTable,
+ accountsTable,
+ sessionsTable,
+ verificationTokensTable,
+ }
+}
export function MySqlDrizzleAdapter(
client: MySqlDatabase,
- schema: DefaultMySqlSchema = {
- usersTable: mysqlUsersTable,
- accountsTable: mysqlAccountsTable,
- sessionsTable: mysqlSessionsTable,
- verificationTokensTable: mysqlVerificationTokensTable,
- }
+ schema?: DefaultMySqlSchema
): Adapter {
const { usersTable, accountsTable, sessionsTable, verificationTokensTable } =
- schema
+ defineTables(schema)
return {
async createUser(data: AdapterUser) {
+ const { id, ...insertData } = data
const hasDefaultId = getTableColumns(usersTable)["id"]["hasDefault"]
await client
.insert(usersTable)
- .values(hasDefaultId ? data : { ...data, id: crypto.randomUUID() })
+ .values(hasDefaultId ? insertData : { ...insertData, id })
return client
.select()
@@ -442,6 +460,6 @@ export type DefaultMySqlVerificationTokenTable = MySqlTableWithColumns<{
export type DefaultMySqlSchema = {
usersTable: DefaultMySqlUsersTable
accountsTable: DefaultMySqlAccountsTable
- sessionsTable: DefaultMySqlSessionsTable
- verificationTokensTable: DefaultMySqlVerificationTokenTable
+ sessionsTable?: DefaultMySqlSessionsTable
+ verificationTokensTable?: DefaultMySqlVerificationTokenTable
}
diff --git a/packages/adapter-drizzle/src/lib/pg.ts b/packages/adapter-drizzle/src/lib/pg.ts
index a345a17c66..334be1dfd9 100644
--- a/packages/adapter-drizzle/src/lib/pg.ts
+++ b/packages/adapter-drizzle/src/lib/pg.ts
@@ -14,88 +14,104 @@ import {
import type {
Adapter,
AdapterAccount,
+ AdapterAccountType,
AdapterSession,
AdapterUser,
VerificationToken,
} from "@auth/core/adapters"
-export const postgresUsersTable = pgTable("user", {
- id: text("id")
- .primaryKey()
- .$defaultFn(() => crypto.randomUUID()),
- name: text("name"),
- email: text("email").notNull(),
- emailVerified: timestamp("emailVerified", { mode: "date" }),
- image: text("image"),
-}) satisfies DefaultPostgresUsersTable
+export function defineTables(
+ schema: Partial = {}
+): Required {
+ const usersTable =
+ schema.usersTable ??
+ (pgTable("user", {
+ id: text("id")
+ .primaryKey()
+ .$defaultFn(() => crypto.randomUUID()),
+ name: text("name"),
+ email: text("email").notNull(),
+ emailVerified: timestamp("emailVerified", { mode: "date" }),
+ image: text("image"),
+ }) satisfies DefaultPostgresUsersTable)
-export const postgresAccountsTable = pgTable(
- "account",
- {
- userId: text("userId")
- .notNull()
- .references(() => postgresUsersTable.id, { onDelete: "cascade" }),
- type: text("type").$type().notNull(),
- provider: text("provider").notNull(),
- providerAccountId: text("providerAccountId").notNull(),
- refresh_token: text("refresh_token"),
- access_token: text("access_token"),
- expires_at: integer("expires_at"),
- token_type: text("token_type"),
- scope: text("scope"),
- id_token: text("id_token"),
- session_state: text("session_state"),
- },
- (table) => {
- return {
- compositePk: primaryKey({
- columns: [table.provider, table.providerAccountId],
- }),
- }
- }
-) satisfies DefaultPostgresAccountsTable
+ const accountsTable =
+ schema.accountsTable ??
+ (pgTable(
+ "account",
+ {
+ userId: text("userId")
+ .notNull()
+ .references(() => usersTable.id, { onDelete: "cascade" }),
+ type: text("type").$type().notNull(),
+ provider: text("provider").notNull(),
+ providerAccountId: text("providerAccountId").notNull(),
+ refresh_token: text("refresh_token"),
+ access_token: text("access_token"),
+ expires_at: integer("expires_at"),
+ token_type: text("token_type"),
+ scope: text("scope"),
+ id_token: text("id_token"),
+ session_state: text("session_state"),
+ },
+ (table) => {
+ return {
+ compositePk: primaryKey({
+ columns: [table.provider, table.providerAccountId],
+ }),
+ }
+ }
+ ) satisfies DefaultPostgresAccountsTable)
-export const postgresSessionsTable = pgTable("session", {
- sessionToken: text("sessionToken").primaryKey(),
- userId: text("userId")
- .notNull()
- .references(() => postgresUsersTable.id, { onDelete: "cascade" }),
- expires: timestamp("expires", { mode: "date" }).notNull(),
-}) satisfies DefaultPostgresSessionsTable
+ const sessionsTable =
+ schema.sessionsTable ??
+ (pgTable("session", {
+ sessionToken: text("sessionToken").primaryKey(),
+ userId: text("userId")
+ .notNull()
+ .references(() => usersTable.id, { onDelete: "cascade" }),
+ expires: timestamp("expires", { mode: "date" }).notNull(),
+ }) satisfies DefaultPostgresSessionsTable)
-export const postgresVerificationTokensTable = pgTable(
- "verificationToken",
- {
- identifier: text("identifier").notNull(),
- token: text("token").notNull(),
- expires: timestamp("expires", { mode: "date" }).notNull(),
- },
- (table) => {
- return {
- compositePk: primaryKey({ columns: [table.identifier, table.token] }),
- }
+ const verificationTokensTable =
+ schema.verificationTokensTable ??
+ (pgTable(
+ "verificationToken",
+ {
+ identifier: text("identifier").notNull(),
+ token: text("token").notNull(),
+ expires: timestamp("expires", { mode: "date" }).notNull(),
+ },
+ (table) => {
+ return {
+ compositePk: primaryKey({ columns: [table.identifier, table.token] }),
+ }
+ }
+ ) satisfies DefaultPostgresVerificationTokenTable)
+
+ return {
+ usersTable,
+ accountsTable,
+ sessionsTable,
+ verificationTokensTable,
}
-) satisfies DefaultPostgresVerificationTokenTable
+}
export function PostgresDrizzleAdapter(
client: PgDatabase,
- schema: DefaultPostgresSchema = {
- usersTable: postgresUsersTable,
- accountsTable: postgresAccountsTable,
- sessionsTable: postgresSessionsTable,
- verificationTokensTable: postgresVerificationTokensTable,
- }
+ schema?: DefaultPostgresSchema
): Adapter {
const { usersTable, accountsTable, sessionsTable, verificationTokensTable } =
- schema
+ defineTables(schema)
return {
async createUser(data: AdapterUser) {
+ const { id, ...insertData } = data
const hasDefaultId = getTableColumns(usersTable)["id"]["hasDefault"]
return client
.insert(usersTable)
- .values(hasDefaultId ? data : { ...data, id: crypto.randomUUID() })
+ .values(hasDefaultId ? insertData : { ...insertData, id })
.returning()
.then((res) => res[0])
},
@@ -413,6 +429,6 @@ export type DefaultPostgresVerificationTokenTable = PgTableWithColumns<{
export type DefaultPostgresSchema = {
usersTable: DefaultPostgresUsersTable
accountsTable: DefaultPostgresAccountsTable
- sessionsTable: DefaultPostgresSessionsTable
- verificationTokensTable: DefaultPostgresVerificationTokenTable
+ sessionsTable?: DefaultPostgresSessionsTable
+ verificationTokensTable?: DefaultPostgresVerificationTokenTable
}
diff --git a/packages/adapter-drizzle/src/lib/sqlite.ts b/packages/adapter-drizzle/src/lib/sqlite.ts
index 64e79267eb..c92c61b7cc 100644
--- a/packages/adapter-drizzle/src/lib/sqlite.ts
+++ b/packages/adapter-drizzle/src/lib/sqlite.ts
@@ -12,84 +12,100 @@ import {
import type {
Adapter,
AdapterAccount,
+ AdapterAccountType,
AdapterSession,
AdapterUser,
VerificationToken,
} from "@auth/core/adapters"
-export const sqliteUsersTable = sqliteTable("user", {
- id: text("id")
- .primaryKey()
- .$defaultFn(() => crypto.randomUUID()),
- name: text("name"),
- email: text("email").notNull(),
- emailVerified: integer("emailVerified", { mode: "timestamp_ms" }),
- image: text("image"),
-}) satisfies DefaultSQLiteUsersTable
+export function defineTables(
+ schema: Partial = {}
+): Required {
+ const usersTable =
+ schema.usersTable ??
+ (sqliteTable("user", {
+ id: text("id")
+ .primaryKey()
+ .$defaultFn(() => crypto.randomUUID()),
+ name: text("name"),
+ email: text("email").notNull(),
+ emailVerified: integer("emailVerified", { mode: "timestamp_ms" }),
+ image: text("image"),
+ }) satisfies DefaultSQLiteUsersTable)
-export const sqliteAccountsTable = sqliteTable(
- "account",
- {
- userId: text("userId")
- .notNull()
- .references(() => sqliteUsersTable.id, { onDelete: "cascade" }),
- type: text("type").$type().notNull(),
- provider: text("provider").notNull(),
- providerAccountId: text("providerAccountId").notNull(),
- refresh_token: text("refresh_token"),
- access_token: text("access_token"),
- expires_at: integer("expires_at"),
- token_type: text("token_type"),
- scope: text("scope"),
- id_token: text("id_token"),
- session_state: text("session_state"),
- },
- (account) => ({
- compositePk: primaryKey({
- columns: [account.provider, account.providerAccountId],
- }),
- })
-) satisfies DefaultSQLiteAccountsTable
+ const accountsTable =
+ schema.accountsTable ??
+ (sqliteTable(
+ "account",
+ {
+ userId: text("userId")
+ .notNull()
+ .references(() => usersTable.id, { onDelete: "cascade" }),
+ type: text("type").$type().notNull(),
+ provider: text("provider").notNull(),
+ providerAccountId: text("providerAccountId").notNull(),
+ refresh_token: text("refresh_token"),
+ access_token: text("access_token"),
+ expires_at: integer("expires_at"),
+ token_type: text("token_type"),
+ scope: text("scope"),
+ id_token: text("id_token"),
+ session_state: text("session_state"),
+ },
+ (account) => ({
+ compositePk: primaryKey({
+ columns: [account.provider, account.providerAccountId],
+ }),
+ })
+ ) satisfies DefaultSQLiteAccountsTable)
-export const sqliteSessionsTable = sqliteTable("session", {
- sessionToken: text("sessionToken").primaryKey(),
- userId: text("userId")
- .notNull()
- .references(() => sqliteUsersTable.id, { onDelete: "cascade" }),
- expires: integer("expires", { mode: "timestamp_ms" }).notNull(),
-}) satisfies DefaultSQLiteSessionsTable
+ const sessionsTable =
+ schema.sessionsTable ??
+ (sqliteTable("session", {
+ sessionToken: text("sessionToken").primaryKey(),
+ userId: text("userId")
+ .notNull()
+ .references(() => usersTable.id, { onDelete: "cascade" }),
+ expires: integer("expires", { mode: "timestamp_ms" }).notNull(),
+ }) satisfies DefaultSQLiteSessionsTable)
-export const sqliteVerificationTokensTable = sqliteTable(
- "verificationToken",
- {
- identifier: text("identifier").notNull(),
- token: text("token").notNull(),
- expires: integer("expires", { mode: "timestamp_ms" }).notNull(),
- },
- (vt) => ({
- compositePk: primaryKey({ columns: [vt.identifier, vt.token] }),
- })
-) satisfies DefaultSQLiteVerificationTokenTable
+ const verificationTokensTable =
+ schema.verificationTokensTable ??
+ (sqliteTable(
+ "verificationToken",
+ {
+ identifier: text("identifier").notNull(),
+ token: text("token").notNull(),
+ expires: integer("expires", { mode: "timestamp_ms" }).notNull(),
+ },
+ (vt) => ({
+ compositePk: primaryKey({ columns: [vt.identifier, vt.token] }),
+ })
+ ) satisfies DefaultSQLiteVerificationTokenTable)
+
+ return {
+ usersTable,
+ accountsTable,
+ sessionsTable,
+ verificationTokensTable,
+ }
+}
export function SQLiteDrizzleAdapter(
client: BaseSQLiteDatabase<"sync" | "async", any, any>,
- schema: DefaultSQLiteSchema = {
- usersTable: sqliteUsersTable,
- accountsTable: sqliteAccountsTable,
- sessionsTable: sqliteSessionsTable,
- verificationTokensTable: sqliteVerificationTokensTable,
- }
+ schema?: DefaultSQLiteSchema
): Adapter {
const { usersTable, accountsTable, sessionsTable, verificationTokensTable } =
- schema
+ defineTables(schema)
return {
async createUser(data: AdapterUser) {
+ const { id, ...insertData } = data
const hasDefaultId = getTableColumns(usersTable)["id"]["hasDefault"]
return client
.insert(usersTable)
- .values(hasDefaultId ? data : { ...data, id: crypto.randomUUID() })
+ .values(hasDefaultId ? insertData : { ...insertData, id })
.returning()
.get()
},
@@ -416,6 +432,6 @@ export type DefaultSQLiteVerificationTokenTable = SQLiteTableWithColumns<{
export type DefaultSQLiteSchema = {
usersTable: DefaultSQLiteUsersTable
accountsTable: DefaultSQLiteAccountsTable
- sessionsTable: DefaultSQLiteSessionsTable
- verificationTokensTable: DefaultSQLiteVerificationTokenTable
+ sessionsTable?: DefaultSQLiteSessionsTable
+ verificationTokensTable?: DefaultSQLiteVerificationTokenTable
}
diff --git a/packages/adapter-drizzle/test/mysql-multi-project-schema/schema.ts b/packages/adapter-drizzle/test/mysql-multi-project-schema/schema.ts
index a50c910d3c..2a2537d829 100644
--- a/packages/adapter-drizzle/test/mysql-multi-project-schema/schema.ts
+++ b/packages/adapter-drizzle/test/mysql-multi-project-schema/schema.ts
@@ -1,6 +1,5 @@
-import { randomUUID } from "crypto"
+import type { AdapterAccountType } from "@auth/core/adapters"
import {
- index,
int,
mysqlTableCreator,
primaryKey,
@@ -24,9 +23,9 @@ const mysqlTable = mysqlTableCreator((name) => `project1_${name}`)
export const users = mysqlTable("user", {
id: varchar("id", { length: 255 })
.primaryKey()
- .$defaultFn(() => randomUUID()),
+ .$defaultFn(() => crypto.randomUUID()),
name: varchar("name", { length: 255 }),
- email: varchar("email", { length: 255 }).notNull().unique(),
+ email: varchar("email", { length: 255 }).notNull(),
emailVerified: timestamp("emailVerified", { mode: "date", fsp: 3 }),
image: varchar("image", { length: 255 }),
})
@@ -37,7 +36,9 @@ export const accounts = mysqlTable(
userId: varchar("userId", { length: 255 })
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
- type: varchar("type", { length: 255 }).notNull(),
+ type: varchar("type", { length: 255 })
+ .$type()
+ .notNull(),
provider: varchar("provider", { length: 255 }).notNull(),
providerAccountId: varchar("providerAccountId", { length: 255 }).notNull(),
refresh_token: varchar("refresh_token", { length: 255 }),
@@ -49,38 +50,28 @@ export const accounts = mysqlTable(
session_state: varchar("session_state", { length: 255 }),
},
(account) => ({
- compoundKey: primaryKey({
+ compositePk: primaryKey({
columns: [account.provider, account.providerAccountId],
}),
- userIdIdx: index("Account_userId_index").on(account.userId),
})
)
-export const sessions = mysqlTable(
- "session",
- {
- id: varchar("id", { length: 255 })
- .primaryKey()
- .$defaultFn(() => randomUUID()),
- sessionToken: varchar("sessionToken", { length: 255 }).notNull().unique(),
- userId: varchar("userId", { length: 255 })
- .notNull()
- .references(() => users.id, { onDelete: "cascade" }),
- expires: timestamp("expires", { mode: "date" }).notNull(),
- },
- (session) => ({
- userIdIdx: index("Session_userId_index").on(session.userId),
- })
-)
+export const sessions = mysqlTable("session", {
+ sessionToken: varchar("sessionToken", { length: 255 }).primaryKey(),
+ userId: varchar("userId", { length: 255 })
+ .notNull()
+ .references(() => users.id, { onDelete: "cascade" }),
+ expires: timestamp("expires", { mode: "date" }).notNull(),
+})
export const verificationTokens = mysqlTable(
"verificationToken",
{
identifier: varchar("identifier", { length: 255 }).notNull(),
- token: varchar("token", { length: 255 }).notNull().unique(),
+ token: varchar("token", { length: 255 }).notNull(),
expires: timestamp("expires", { mode: "date" }).notNull(),
},
(vt) => ({
- compoundKey: primaryKey({ columns: [vt.identifier, vt.token] }),
+ compositePk: primaryKey({ columns: [vt.identifier, vt.token] }),
})
)
diff --git a/packages/adapter-drizzle/test/mysql/index.test.ts b/packages/adapter-drizzle/test/mysql/index.test.ts
index f8f155caa3..b4f524a9d8 100644
--- a/packages/adapter-drizzle/test/mysql/index.test.ts
+++ b/packages/adapter-drizzle/test/mysql/index.test.ts
@@ -2,10 +2,10 @@ import { runBasicTests } from "utils/adapter"
import { DrizzleAdapter } from "../../src"
import {
db,
- mysqlSessionsTable as sessions,
- mysqlVerificationTokensTable as verificationTokens,
- mysqlAccountsTable as accounts,
- mysqlUsersTable as users,
+ sessionsTable as sessions,
+ verificationTokensTable as verificationTokens,
+ accountsTable as accounts,
+ usersTable as users,
} from "./schema"
import { eq, and } from "drizzle-orm"
import { fixtures } from "../fixtures"
diff --git a/packages/adapter-drizzle/test/mysql/schema.ts b/packages/adapter-drizzle/test/mysql/schema.ts
index da9c829014..70b07a4d1f 100644
--- a/packages/adapter-drizzle/test/mysql/schema.ts
+++ b/packages/adapter-drizzle/test/mysql/schema.ts
@@ -1,11 +1,13 @@
import { drizzle } from "drizzle-orm/mysql2"
import { createPool } from "mysql2"
-export {
- mysqlUsersTable,
- mysqlAccountsTable,
- mysqlSessionsTable,
- mysqlVerificationTokensTable,
-} from "../../src/lib/mysql"
+import { defineTables } from "../../src/lib/mysql"
+
+export const {
+ usersTable,
+ accountsTable,
+ sessionsTable,
+ verificationTokensTable,
+} = defineTables({})
const poolConnection = createPool({
host: "localhost",
diff --git a/packages/adapter-drizzle/test/pg-multi-project-schema/schema.ts b/packages/adapter-drizzle/test/pg-multi-project-schema/schema.ts
index add88125a6..263f5d561a 100644
--- a/packages/adapter-drizzle/test/pg-multi-project-schema/schema.ts
+++ b/packages/adapter-drizzle/test/pg-multi-project-schema/schema.ts
@@ -1,6 +1,5 @@
-import { randomUUID } from "crypto"
+import type { AdapterAccountType } from "@auth/core/adapters"
import {
- index,
integer,
pgTableCreator,
primaryKey,
@@ -20,9 +19,9 @@ const pgTable = pgTableCreator((name) => `project1_${name}`)
export const users = pgTable("user", {
id: text("id")
.primaryKey()
- .$defaultFn(() => randomUUID()),
+ .$defaultFn(() => crypto.randomUUID()),
name: text("name"),
- email: text("email").notNull().unique(),
+ email: text("email").notNull(),
emailVerified: timestamp("emailVerified", { mode: "date" }),
image: text("image"),
})
@@ -33,7 +32,7 @@ export const accounts = pgTable(
userId: text("userId")
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
- type: text("type").notNull(),
+ type: text("type").$type().notNull(),
provider: text("provider").notNull(),
providerAccountId: text("providerAccountId").notNull(),
refresh_token: text("refresh_token"),
@@ -46,7 +45,6 @@ export const accounts = pgTable(
},
(table) => {
return {
- userIdIdx: index().on(table.userId),
compositePk: primaryKey({
columns: [table.provider, table.providerAccountId],
}),
@@ -54,30 +52,19 @@ export const accounts = pgTable(
}
)
-export const sessions = pgTable(
- "session",
- {
- id: text("id")
- .primaryKey()
- .$defaultFn(() => randomUUID()),
- sessionToken: text("sessionToken").notNull().unique(),
- userId: text("userId")
- .notNull()
- .references(() => users.id, { onDelete: "cascade" }),
- expires: timestamp("expires", { mode: "date" }).notNull(),
- },
- (table) => {
- return {
- userIdIdx: index().on(table.userId),
- }
- }
-)
+export const sessions = pgTable("session", {
+ sessionToken: text("sessionToken").primaryKey(),
+ userId: text("userId")
+ .notNull()
+ .references(() => users.id, { onDelete: "cascade" }),
+ expires: timestamp("expires", { mode: "date" }).notNull(),
+})
export const verificationTokens = pgTable(
"verificationToken",
{
identifier: text("identifier").notNull(),
- token: text("token").notNull().unique(),
+ token: text("token").notNull(),
expires: timestamp("expires", { mode: "date" }).notNull(),
},
(table) => {
diff --git a/packages/adapter-drizzle/test/pg/index.test.ts b/packages/adapter-drizzle/test/pg/index.test.ts
index b8c6352cac..b26278d350 100644
--- a/packages/adapter-drizzle/test/pg/index.test.ts
+++ b/packages/adapter-drizzle/test/pg/index.test.ts
@@ -2,10 +2,10 @@ import { runBasicTests } from "utils/adapter"
import { DrizzleAdapter } from "../../src"
import {
db,
- postgresAccountsTable as accounts,
- postgresSessionsTable as sessions,
- postgresUsersTable as users,
- postgresVerificationTokensTable as verificationTokens,
+ accountsTable as accounts,
+ sessionsTable as sessions,
+ usersTable as users,
+ verificationTokensTable as verificationTokens,
} from "./schema"
import { eq, and } from "drizzle-orm"
import { fixtures } from "../fixtures"
diff --git a/packages/adapter-drizzle/test/pg/schema.ts b/packages/adapter-drizzle/test/pg/schema.ts
index 1fab8377af..a24fe43a35 100644
--- a/packages/adapter-drizzle/test/pg/schema.ts
+++ b/packages/adapter-drizzle/test/pg/schema.ts
@@ -1,11 +1,13 @@
import { drizzle } from "drizzle-orm/postgres-js"
import postgres from "postgres"
-export {
- postgresUsersTable,
- postgresAccountsTable,
- postgresSessionsTable,
- postgresVerificationTokensTable,
-} from "../../src/lib/pg"
+import { defineTables } from "../../src/lib/pg"
+
+export const {
+ usersTable,
+ accountsTable,
+ sessionsTable,
+ verificationTokensTable,
+} = defineTables({})
const connectionString = "postgres://nextauth:nextauth@localhost:5432/nextauth"
const sql = postgres(connectionString)
diff --git a/packages/adapter-drizzle/test/sqlite-multi-project-schema/index.test.ts b/packages/adapter-drizzle/test/sqlite-multi-project-schema/index.test.ts
index f4c7913c73..aa93674721 100644
--- a/packages/adapter-drizzle/test/sqlite-multi-project-schema/index.test.ts
+++ b/packages/adapter-drizzle/test/sqlite-multi-project-schema/index.test.ts
@@ -2,6 +2,7 @@ import { runBasicTests } from "utils/adapter"
import { DrizzleAdapter } from "../../src"
import { db, accounts, sessions, users, verificationTokens } from "./schema"
import { eq, and } from "drizzle-orm"
+import { fixtures } from "../fixtures"
runBasicTests({
adapter: DrizzleAdapter(db, {
@@ -10,6 +11,7 @@ runBasicTests({
sessionsTable: sessions,
verificationTokensTable: verificationTokens,
}),
+ fixtures,
db: {
connect: async () => {
await Promise.all([
diff --git a/packages/adapter-drizzle/test/sqlite-multi-project-schema/schema.ts b/packages/adapter-drizzle/test/sqlite-multi-project-schema/schema.ts
index 8e11d9a0c4..f65c3449f5 100644
--- a/packages/adapter-drizzle/test/sqlite-multi-project-schema/schema.ts
+++ b/packages/adapter-drizzle/test/sqlite-multi-project-schema/schema.ts
@@ -1,13 +1,12 @@
-import { drizzle } from "drizzle-orm/better-sqlite3"
+import { AdapterAccountType } from "@auth/core/adapters"
import Database from "better-sqlite3"
+import { drizzle } from "drizzle-orm/better-sqlite3"
import {
- index,
integer,
primaryKey,
sqliteTableCreator,
text,
} from "drizzle-orm/sqlite-core"
-import { randomUUID } from "crypto"
const sqlite = new Database("db.sqlite")
@@ -18,9 +17,9 @@ const sqliteTable = sqliteTableCreator((name) => `foobar_${name}`)
export const users = sqliteTable("user", {
id: text("id")
.primaryKey()
- .$defaultFn(() => randomUUID()),
+ .$defaultFn(() => crypto.randomUUID()),
name: text("name"),
- email: text("email").notNull().unique(),
+ email: text("email").notNull(),
emailVerified: integer("emailVerified", { mode: "timestamp_ms" }),
image: text("image"),
})
@@ -31,7 +30,7 @@ export const accounts = sqliteTable(
userId: text("userId")
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
- type: text("type").notNull(),
+ type: text("type").$type().notNull(),
provider: text("provider").notNull(),
providerAccountId: text("providerAccountId").notNull(),
refresh_token: text("refresh_token"),
@@ -43,35 +42,25 @@ export const accounts = sqliteTable(
session_state: text("session_state"),
},
(account) => ({
- userIdIdx: index("Account_userId_index").on(account.userId),
compositePk: primaryKey({
columns: [account.provider, account.providerAccountId],
}),
})
)
-export const sessions = sqliteTable(
- "session",
- {
- id: text("id")
- .primaryKey()
- .$defaultFn(() => randomUUID()),
- sessionToken: text("sessionToken").notNull().unique(),
- userId: text("userId")
- .notNull()
- .references(() => users.id, { onDelete: "cascade" }),
- expires: integer("expires", { mode: "timestamp_ms" }).notNull(),
- },
- (table) => ({
- userIdIdx: index("Session_userId_index").on(table.userId),
- })
-)
+export const sessions = sqliteTable("session", {
+ sessionToken: text("sessionToken").primaryKey(),
+ userId: text("userId")
+ .notNull()
+ .references(() => users.id, { onDelete: "cascade" }),
+ expires: integer("expires", { mode: "timestamp_ms" }).notNull(),
+})
export const verificationTokens = sqliteTable(
"verificationToken",
{
identifier: text("identifier").notNull(),
- token: text("token").notNull().unique(),
+ token: text("token").notNull(),
expires: integer("expires", { mode: "timestamp_ms" }).notNull(),
},
(vt) => ({
diff --git a/packages/adapter-drizzle/test/sqlite/index.test.ts b/packages/adapter-drizzle/test/sqlite/index.test.ts
index f75eec9401..b442c38e8c 100644
--- a/packages/adapter-drizzle/test/sqlite/index.test.ts
+++ b/packages/adapter-drizzle/test/sqlite/index.test.ts
@@ -2,15 +2,17 @@ import { runBasicTests } from "utils/adapter"
import { DrizzleAdapter } from "../../src"
import {
db,
- sqliteAccountsTable as accounts,
- sqliteSessionsTable as sessions,
- sqliteUsersTable as users,
- sqliteVerificationTokensTable as verificationTokens,
+ accountsTable as accounts,
+ sessionsTable as sessions,
+ usersTable as users,
+ verificationTokensTable as verificationTokens,
} from "./schema"
import { eq, and } from "drizzle-orm"
+import { fixtures } from "../fixtures"
runBasicTests({
adapter: DrizzleAdapter(db),
+ fixtures,
db: {
connect: async () => {
await Promise.all([
diff --git a/packages/adapter-drizzle/test/sqlite/schema.ts b/packages/adapter-drizzle/test/sqlite/schema.ts
index 51f69c6794..0a0f6a461c 100644
--- a/packages/adapter-drizzle/test/sqlite/schema.ts
+++ b/packages/adapter-drizzle/test/sqlite/schema.ts
@@ -1,11 +1,13 @@
import { drizzle } from "drizzle-orm/better-sqlite3"
import Database from "better-sqlite3"
-export {
- sqliteUsersTable,
- sqliteAccountsTable,
- sqliteSessionsTable,
- sqliteVerificationTokensTable,
-} from "../../src/lib/sqlite"
+import { defineTables } from "../../src/lib/sqlite.ts"
+
+export const {
+ usersTable,
+ accountsTable,
+ sessionsTable,
+ verificationTokensTable,
+} = defineTables({})
const sqlite = new Database("db.sqlite")
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index b7f9a473cc..c43790bed5 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -315,8 +315,8 @@ importers:
specifier: ^0.20.17
version: 0.20.17
drizzle-orm:
- specifier: ^0.30.8
- version: 0.30.8(@types/better-sqlite3@7.6.9)(better-sqlite3@9.5.0)(mysql2@3.9.7)(postgres@3.4.3)
+ specifier: ^0.30.9
+ version: 0.30.9(@types/better-sqlite3@7.6.9)(better-sqlite3@9.5.0)(mysql2@3.9.7)(postgres@3.4.3)
mysql2:
specifier: ^3.9.7
version: 3.9.7
@@ -13041,8 +13041,8 @@ packages:
- supports-color
dev: true
- /drizzle-orm@0.30.8(@types/better-sqlite3@7.6.9)(better-sqlite3@9.5.0)(mysql2@3.9.7)(postgres@3.4.3):
- resolution: {integrity: sha512-9pBJA0IjnpPpzZ6s9jlS1CQAbKoBmbn2GJesPhXaVblAA/joOJ4AWWevYcqvLGj9SvThBAl7WscN8Zwgg5mnTw==}
+ /drizzle-orm@0.30.9(@types/better-sqlite3@7.6.9)(better-sqlite3@9.5.0)(mysql2@3.9.7)(postgres@3.4.3):
+ resolution: {integrity: sha512-VOiCFsexErmgqvNCOmbzmqDCZzZsHoz6SkWAjTFxsTr1AllKDbDJ2+GgedLXsXMDgpg/ljDG1zItIFeZtiO2LA==}
peerDependencies:
'@aws-sdk/client-rds-data': '>=3'
'@cloudflare/workers-types': '>=3'
From 09a369192b77a9edce874e33ced07133f0978182 Mon Sep 17 00:00:00 2001
From: ndom91
Date: Wed, 8 May 2024 18:26:15 +0200
Subject: [PATCH 04/44] chore(docs): cleanup Drizzle adapter doc page
---
.../getting-started/adapters/drizzle.mdx | 30 +++++++++++++++++--
1 file changed, 27 insertions(+), 3 deletions(-)
diff --git a/docs/pages/getting-started/adapters/drizzle.mdx b/docs/pages/getting-started/adapters/drizzle.mdx
index fad55d0b83..c0f6e9b695 100644
--- a/docs/pages/getting-started/adapters/drizzle.mdx
+++ b/docs/pages/getting-started/adapters/drizzle.mdx
@@ -54,7 +54,7 @@ import {
} from "drizzle-orm/pg-core"
import postgres from "postgres"
import { drizzle } from "drizzle-orm/postgres-js"
-import type { AdapterAccountType } from "@auth/core/adapters"
+import type { AdapterAccountType } from "next-auth/adapters"
const connectionString = "postgres://postgres:postgres@localhost:5432/drizzle"
const pool = postgres(connectionString, { max: 1 })
@@ -130,7 +130,7 @@ import {
} from "drizzle-orm/mysql-core"
import mysql from "mysql2/promise"
import { drizzle } from "drizzle-orm/mysql2"
-import type { AdapterAccountType } from "@auth/core/adapters"
+import type { AdapterAccountType } from "next-auth/adapters"
export const connection = await mysql.createConnection({
host: "host",
@@ -209,7 +209,7 @@ If you want to modify the schema or add additional fields, you can use the follo
import { integer, sqliteTable, text, primaryKey } from "drizzle-orm/sqlite-core"
import { createClient } from "@libsql/client"
import { drizzle } from "drizzle-orm/libsql"
-import type { AdapterAccountType } from "@auth/core/adapters"
+import type { AdapterAccountType } from "next-auth/adapters"
const client = createClient({
url: "DATABASE_URL",
@@ -328,6 +328,30 @@ app.use(
+#### Passing your own Schemas
+
+If you want to use your own tables, you can pass them as a second argument to `DrizzleAdapter`.
+
+- The `sessionsTable` is optional and only required if you're using the database session strategy.
+- The `verificationTokensTable` is optional and only required if you're using a Magic Link provider.
+
+```ts filename="auth.ts"
+import NextAuth from "next-auth"
+import Google from "next-auth/providers/google"
+import { DrizzleAdapter } from "@auth/drizzle-adapter"
+import { db, accounts, sessions, users, verificationTokens } from "./schema"
+
+export const { handlers, auth } = NextAuth({
+ adapter: DrizzleAdapter(db, {
+ usersTable: users,
+ accountsTable: accounts,
+ sessionsTable: sessions,
+ verificationTokensTable: verificationTokens,
+ }),
+ providers: [Google],
+})
+```
+
### Migrating your database
With your schema now described in your code, you'll need to migrate your database to your schema. An example `migrate.ts` file looks like this. For more information, check out Drizzle's migration [quick start guide](https://orm.drizzle.team/docs/migrations).
From b7d1f9edd1dfa888a5e72e240fc4810dccc46537 Mon Sep 17 00:00:00 2001
From: ndom91
Date: Wed, 8 May 2024 19:13:41 +0200
Subject: [PATCH 05/44] chore(docs): minor adapter docs cleanup
---
docs/pages/getting-started/adapters/typeorm.mdx | 2 +-
docs/pages/getting-started/adapters/upstash-redis.mdx | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/pages/getting-started/adapters/typeorm.mdx b/docs/pages/getting-started/adapters/typeorm.mdx
index 01483bbda1..03a1e429cf 100644
--- a/docs/pages/getting-started/adapters/typeorm.mdx
+++ b/docs/pages/getting-started/adapters/typeorm.mdx
@@ -83,7 +83,7 @@ You can override the default entities and add additional fields with a custom en
1. Create a file containing your modified entities:
-```ts filename="lib/entities.ts"
+```ts filename="lib/entities.ts" {38-39}
import {
Entity,
PrimaryGeneratedColumn,
diff --git a/docs/pages/getting-started/adapters/upstash-redis.mdx b/docs/pages/getting-started/adapters/upstash-redis.mdx
index 8ac8dd39f2..6f87915113 100644
--- a/docs/pages/getting-started/adapters/upstash-redis.mdx
+++ b/docs/pages/getting-started/adapters/upstash-redis.mdx
@@ -122,7 +122,7 @@ const defaultOptions = {
Usually changing the `baseKeyPrefix` should be enough for this scenario, but for more custom setups, you can also change the prefixes of every single key.
```ts
-export default NextAuth({
+export const { handlers, auth, signIn, signOut } = NextAuth({
adapter: UpstashRedisAdapter(redis, { baseKeyPrefix: "app2:" }),
})
```
From fbc89ea1f4e5f8edae58a28313abd32e36a35a29 Mon Sep 17 00:00:00 2001
From: Nico Domino
Date: Wed, 8 May 2024 19:36:48 +0200
Subject: [PATCH 06/44] chore(apps): add separate `apps/dev/express` app
(#10736)
---
apps/dev/express/.env.example | 7 +
apps/dev/express/.gitignore | 21 +
apps/dev/express/.prettierignore | 14 +
apps/dev/express/README.md | 28 ++
apps/dev/express/api/index.js | 3 +
apps/dev/express/package.json | 35 ++
apps/dev/express/public/css/style.css | 5 +
apps/dev/express/src/app.ts | 71 +++
apps/dev/express/src/config/auth.config.ts | 69 +++
apps/dev/express/src/errors.ts | 14 +
.../express/src/middleware/auth.middleware.ts | 29 ++
.../src/middleware/error.middleware.ts | 24 +
apps/dev/express/src/server.ts | 9 +
apps/dev/express/tsconfig.json | 16 +
apps/dev/express/views/error.pug | 5 +
apps/dev/express/views/index.pug | 11 +
apps/dev/express/views/layout.pug | 34 ++
apps/dev/express/views/protected.pug | 15 +
package.json | 8 +-
pnpm-lock.yaml | 429 ++++++++++++++----
20 files changed, 754 insertions(+), 93 deletions(-)
create mode 100644 apps/dev/express/.env.example
create mode 100644 apps/dev/express/.gitignore
create mode 100644 apps/dev/express/.prettierignore
create mode 100644 apps/dev/express/README.md
create mode 100644 apps/dev/express/api/index.js
create mode 100644 apps/dev/express/package.json
create mode 100644 apps/dev/express/public/css/style.css
create mode 100644 apps/dev/express/src/app.ts
create mode 100644 apps/dev/express/src/config/auth.config.ts
create mode 100644 apps/dev/express/src/errors.ts
create mode 100644 apps/dev/express/src/middleware/auth.middleware.ts
create mode 100644 apps/dev/express/src/middleware/error.middleware.ts
create mode 100644 apps/dev/express/src/server.ts
create mode 100644 apps/dev/express/tsconfig.json
create mode 100644 apps/dev/express/views/error.pug
create mode 100644 apps/dev/express/views/index.pug
create mode 100644 apps/dev/express/views/layout.pug
create mode 100644 apps/dev/express/views/protected.pug
diff --git a/apps/dev/express/.env.example b/apps/dev/express/.env.example
new file mode 100644
index 0000000000..6959cc6e03
--- /dev/null
+++ b/apps/dev/express/.env.example
@@ -0,0 +1,7 @@
+AUTH_SECRET=
+
+AUTH_GITHUB_ID=
+AUTH_GITHUB_SECRET=
+
+AUTH_GOOGLE_ID=
+AUTH_GOOGLE_SECRET=
\ No newline at end of file
diff --git a/apps/dev/express/.gitignore b/apps/dev/express/.gitignore
new file mode 100644
index 0000000000..01fd4ed6db
--- /dev/null
+++ b/apps/dev/express/.gitignore
@@ -0,0 +1,21 @@
+# API keys and secrets
+.env
+
+# Dependency directory
+node_modules
+
+# Editors
+.idea
+*.iml
+.vscode/settings.json
+
+# OS metadata
+.DS_Store
+Thumbs.db
+
+# Ignore built ts files
+dist/**/*
+
+# Ignore built css files
+/public/css/output.css
+
diff --git a/apps/dev/express/.prettierignore b/apps/dev/express/.prettierignore
new file mode 100644
index 0000000000..f97e266fdd
--- /dev/null
+++ b/apps/dev/express/.prettierignore
@@ -0,0 +1,14 @@
+
+.DS_Store
+node_modules
+/dist
+/.turbo
+/package
+.env
+.env.*
+!.env.example
+
+# Ignore files for PNPM, NPM and YARN
+pnpm-lock.yaml
+package-lock.json
+yarn.lock
diff --git a/apps/dev/express/README.md b/apps/dev/express/README.md
new file mode 100644
index 0000000000..caa05d73fb
--- /dev/null
+++ b/apps/dev/express/README.md
@@ -0,0 +1,28 @@
+> The example repository is maintained from a [monorepo](https://github.com/nextauthjs/next-auth/tree/main/apps/examples/express). Pull Requests should be opened against [`nextauthjs/next-auth`](https://github.com/nextauthjs/next-auth).
+
+
+
+
+
Auth.js Example App with Express
+
+ Open Source. Full Stack. Own Your Data.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Documentation
+
+- [express.authjs.dev](https://express.authjs.dev)
diff --git a/apps/dev/express/api/index.js b/apps/dev/express/api/index.js
new file mode 100644
index 0000000000..37795e6772
--- /dev/null
+++ b/apps/dev/express/api/index.js
@@ -0,0 +1,3 @@
+import { app } from "../src/app.js"
+
+export default app
diff --git a/apps/dev/express/package.json b/apps/dev/express/package.json
new file mode 100644
index 0000000000..23f4fce1fd
--- /dev/null
+++ b/apps/dev/express/package.json
@@ -0,0 +1,35 @@
+{
+ "name": "express-auth-app",
+ "description": "Express + Auth.js Developer app",
+ "type": "module",
+ "private": true,
+ "scripts": {
+ "start": "node --env-file=.env dist/server.js",
+ "clean": "rm -rf dist",
+ "build": "pnpm build:ts && pnpm build:css",
+ "build:ts": "tsc",
+ "build:css": "tailwindcss -i ./public/css/style.css -o ./public/css/output.css",
+ "dev": "tsx watch --env-file=.env src/server.ts & pnpm build:css -w",
+ "lint": "eslint src/*.ts --fix",
+ "prettier": "prettier src/*.ts --write"
+ },
+ "author": "Auth.js Team (https://authjs.dev/contributors)",
+ "license": "MIT",
+ "dependencies": {
+ "@auth/express": "workspace:*",
+ "express": "^4.19.2",
+ "morgan": "^1.10.0",
+ "pug": "^3.0.2"
+ },
+ "devDependencies": {
+ "@prettier/plugin-pug": "^3.0.0",
+ "@types/express": "^4.17.21",
+ "@types/morgan": "^1.9.9",
+ "@types/pug": "^2.0.10",
+ "tsx": "^4.7.3",
+ "typescript": "5.4.5"
+ },
+ "engines": {
+ "node": ">=20.11.0"
+ }
+}
diff --git a/apps/dev/express/public/css/style.css b/apps/dev/express/public/css/style.css
new file mode 100644
index 0000000000..7f393742af
--- /dev/null
+++ b/apps/dev/express/public/css/style.css
@@ -0,0 +1,5 @@
+@tailwind base;
+
+@tailwind components;
+
+@tailwind utilities;
diff --git a/apps/dev/express/src/app.ts b/apps/dev/express/src/app.ts
new file mode 100644
index 0000000000..27cc8db60c
--- /dev/null
+++ b/apps/dev/express/src/app.ts
@@ -0,0 +1,71 @@
+import express, { type Request, type Response } from "express"
+import logger from "morgan"
+import { join } from "node:path"
+
+import {
+ errorHandler,
+ errorNotFoundHandler,
+} from "./middleware/error.middleware.js"
+
+import {
+ authenticatedUser,
+ currentSession,
+} from "./middleware/auth.middleware.js"
+import { ExpressAuth } from "@auth/express"
+import { authConfig } from "./config/auth.config.js"
+import * as pug from "pug"
+
+export const app = express()
+
+app.set("port", process.env.PORT || 3004)
+
+// @ts-expect-error (https://stackoverflow.com/questions/45342307/error-cannot-find-module-pug)
+app.engine("pug", pug.__express)
+app.set("views", join(import.meta.dirname, "..", "views"))
+app.set("view engine", "pug")
+
+// Trust Proxy for Proxies (Heroku, Render.com, Docker behind Nginx, etc)
+// https://stackoverflow.com/questions/40459511/in-express-js-req-protocol-is-not-picking-up-https-for-my-secure-link-it-alwa
+app.set("trust proxy", true)
+
+app.use(logger("dev"))
+
+// Serve static files
+// NB: Uncomment this out if you want Express to serve static files for you vs. using a
+// hosting provider which does so for you (for example through a CDN).
+// app.use(express.static(join(import.meta.dirname, "..", "public")))
+
+// Parse incoming requests data
+app.use(express.urlencoded({ extended: true }))
+app.use(express.json())
+
+// Set session in res.locals
+app.use(currentSession)
+
+// Set up ExpressAuth to handle authentication
+// IMPORTANT: It is highly encouraged set up rate limiting on this route
+app.use("/api/auth/*", ExpressAuth(authConfig))
+
+// Routes
+app.get("/protected", async (_req: Request, res: Response) => {
+ res.render("protected", { session: res.locals.session })
+})
+
+app.get(
+ "/api/protected",
+ authenticatedUser,
+ async (_req: Request, res: Response) => {
+ res.json(res.locals.session)
+ },
+)
+
+app.get("/", async (_req: Request, res: Response) => {
+ res.render("index", {
+ title: "Express Auth Example",
+ user: res.locals.session?.user,
+ })
+})
+
+// Error handlers
+app.use(errorNotFoundHandler)
+app.use(errorHandler)
diff --git a/apps/dev/express/src/config/auth.config.ts b/apps/dev/express/src/config/auth.config.ts
new file mode 100644
index 0000000000..a85bb2d1f7
--- /dev/null
+++ b/apps/dev/express/src/config/auth.config.ts
@@ -0,0 +1,69 @@
+import Apple from "@auth/express/providers/apple"
+import Auth0 from "@auth/express/providers/auth0"
+import AzureB2C from "@auth/express/providers/azure-ad-b2c"
+import BoxyHQSAML from "@auth/express/providers/boxyhq-saml"
+import Cognito from "@auth/express/providers/cognito"
+import Coinbase from "@auth/express/providers/coinbase"
+import Discord from "@auth/express/providers/discord"
+import Dropbox from "@auth/express/providers/dropbox"
+import Facebook from "@auth/express/providers/facebook"
+import GitHub from "@auth/express/providers/github"
+import Gitlab from "@auth/express/providers/gitlab"
+import Google from "@auth/express/providers/google"
+import Hubspot from "@auth/express/providers/hubspot"
+import Keycloak from "@auth/express/providers/keycloak"
+import LinkedIn from "@auth/express/providers/linkedin"
+import Netlify from "@auth/express/providers/netlify"
+import Okta from "@auth/express/providers/okta"
+import Passage from "@auth/express/providers/passage"
+import Pinterest from "@auth/express/providers/pinterest"
+import Reddit from "@auth/express/providers/reddit"
+import Slack from "@auth/express/providers/slack"
+import Spotify from "@auth/express/providers/spotify"
+import Twitch from "@auth/express/providers/twitch"
+import Twitter from "@auth/express/providers/twitter"
+import WorkOS from "@auth/express/providers/workos"
+import Zoom from "@auth/express/providers/zoom"
+
+export const authConfig = {
+ trustHost: true,
+ debug: process.env.NODE_ENV !== "production" ? true : false,
+ providers: [
+ Apple,
+ Auth0,
+ AzureB2C({
+ clientId: process.env.AUTH_AZURE_AD_B2C_ID,
+ clientSecret: process.env.AUTH_AZURE_AD_B2C_SECRET,
+ issuer: process.env.AUTH_AZURE_AD_B2C_ISSUER,
+ }),
+ BoxyHQSAML({
+ clientId: "dummy",
+ clientSecret: "dummy",
+ issuer: process.env.AUTH_BOXYHQ_SAML_ISSUER,
+ }),
+ Cognito,
+ Coinbase,
+ Discord,
+ Dropbox,
+ Facebook,
+ GitHub,
+ Gitlab,
+ Google,
+ Hubspot,
+ Keycloak,
+ LinkedIn,
+ Netlify,
+ Okta,
+ Passage,
+ Pinterest,
+ Reddit,
+ Slack,
+ Spotify,
+ Twitch,
+ Twitter,
+ WorkOS({
+ connection: process.env.AUTH_WORKOS_CONNECTION!,
+ }),
+ Zoom,
+ ],
+}
diff --git a/apps/dev/express/src/errors.ts b/apps/dev/express/src/errors.ts
new file mode 100644
index 0000000000..43853cfe84
--- /dev/null
+++ b/apps/dev/express/src/errors.ts
@@ -0,0 +1,14 @@
+export class HttpError extends Error {
+ status: number
+ constructor(status: number, message: string) {
+ super(message)
+ this.status = status
+ }
+}
+
+export class NotFoundError extends HttpError {
+ constructor(message: string, status = 404) {
+ super(status, message)
+ this.name = "NotFoundError"
+ }
+}
diff --git a/apps/dev/express/src/middleware/auth.middleware.ts b/apps/dev/express/src/middleware/auth.middleware.ts
new file mode 100644
index 0000000000..3279ce41da
--- /dev/null
+++ b/apps/dev/express/src/middleware/auth.middleware.ts
@@ -0,0 +1,29 @@
+import { getSession } from "@auth/express"
+import { authConfig } from "../config/auth.config.js"
+import type { NextFunction, Request, Response } from "express"
+
+export async function authenticatedUser(
+ req: Request,
+ res: Response,
+ next: NextFunction
+) {
+ const session = res.locals.session ?? (await getSession(req, authConfig))
+
+ res.locals.session = session
+
+ if (session) {
+ return next()
+ }
+
+ res.status(400).json({ message: "Not Authenticated" })
+}
+
+export async function currentSession(
+ req: Request,
+ res: Response,
+ next: NextFunction
+) {
+ const session = await getSession(req, authConfig)
+ res.locals.session = session
+ return next()
+}
diff --git a/apps/dev/express/src/middleware/error.middleware.ts b/apps/dev/express/src/middleware/error.middleware.ts
new file mode 100644
index 0000000000..6a69bcf02a
--- /dev/null
+++ b/apps/dev/express/src/middleware/error.middleware.ts
@@ -0,0 +1,24 @@
+import type { NextFunction, Request, Response } from "express"
+import { HttpError, NotFoundError } from "../errors.js"
+
+export const errorHandler = (
+ err: HttpError | Error,
+ _req: Request,
+ res: Response,
+ _next: NextFunction
+): void => {
+ // Render the error page
+ res.status(("status" in err && err.status) || 500)
+ res.render("error", {
+ title: "status" in err ? err.status : err.name,
+ message: err.message,
+ })
+}
+
+export const errorNotFoundHandler = (
+ _req: Request,
+ _res: Response,
+ next: NextFunction
+): void => {
+ next(new NotFoundError("Not Found"))
+}
diff --git a/apps/dev/express/src/server.ts b/apps/dev/express/src/server.ts
new file mode 100644
index 0000000000..98895c376c
--- /dev/null
+++ b/apps/dev/express/src/server.ts
@@ -0,0 +1,9 @@
+import { app } from "./app.js"
+
+const port = app.get("port")
+
+const server = app.listen(port, () => {
+ console.log(`Listening on port ${port}`)
+})
+
+export default server
diff --git a/apps/dev/express/tsconfig.json b/apps/dev/express/tsconfig.json
new file mode 100644
index 0000000000..6b8858be5f
--- /dev/null
+++ b/apps/dev/express/tsconfig.json
@@ -0,0 +1,16 @@
+{
+ "compilerOptions": {
+ "module": "NodeNext",
+ "esModuleInterop": true,
+ "target": "esnext",
+ "noImplicitAny": true,
+ "moduleResolution": "NodeNext",
+ "sourceMap": true,
+ "outDir": "dist",
+ "baseUrl": ".",
+ "skipLibCheck": true,
+ "strict": true
+ },
+ "include": ["src/**/*.ts"],
+ "exclude": ["node_modules"]
+}
diff --git a/apps/dev/express/views/error.pug b/apps/dev/express/views/error.pug
new file mode 100644
index 0000000000..4d62885b53
--- /dev/null
+++ b/apps/dev/express/views/error.pug
@@ -0,0 +1,5 @@
+extends layout
+
+block content
+ h1=title
+ p=message
diff --git a/apps/dev/express/views/index.pug b/apps/dev/express/views/index.pug
new file mode 100644
index 0000000000..46708a98ee
--- /dev/null
+++ b/apps/dev/express/views/index.pug
@@ -0,0 +1,11 @@
+extends layout
+
+block content
+ h1=title
+ p
+ | This is an example site to demonstrate how to use #{ ' ' }
+ a(href="https://expressjs.com/") Express
+ | #{ ' ' } with #{ ' ' }
+ a(href="https://authjs.dev/reference/express") Express Auth
+ |
+ | for authentication.
diff --git a/apps/dev/express/views/layout.pug b/apps/dev/express/views/layout.pug
new file mode 100644
index 0000000000..ed1bf74915
--- /dev/null
+++ b/apps/dev/express/views/layout.pug
@@ -0,0 +1,34 @@
+doctype html
+html
+ head
+ title=title
+ meta(name="viewport" content="width=device-width, initial-scale=1.0")
+ body
+ div
+ div
+ if session
+ div
+ if session.user.image
+ img(src=`${session.user.image}` style="width:64px;border-radius:50%;")
+ span
+ | Signed in as #{ ' ' }
+ strong= session.user.email || session.user.name
+ a(
+ href="/api/auth/signout"
+ ) Sign out
+ else
+ span You are not signed in #{ ' ' }
+ a#sign-indiv(
+ href="/api/auth/signin"
+ ) Sign in
+
+ nav
+ ul
+ li
+ a(href="/") Home
+ li
+ a(href="/protected") Protected
+ li
+ a(href="/api/protected") Protected (API)
+
+ block content
diff --git a/apps/dev/express/views/protected.pug b/apps/dev/express/views/protected.pug
new file mode 100644
index 0000000000..97790e3b32
--- /dev/null
+++ b/apps/dev/express/views/protected.pug
@@ -0,0 +1,15 @@
+extends layout
+
+block content
+ if session
+ h1 Protected page
+ p
+ | This is a protected content. You can access this content because you are
+ | signed in.
+ p Session expiry: #{ session.expires ? session.expires : '' }
+ else
+ h1 Access Denied
+ p
+ | You must be #{ ' ' }
+ a(href="/api/auth/signin") signed in
+ | #{ ' ' } to view this page
diff --git a/package.json b/package.json
index 6d9a3e993f..8578292e71 100644
--- a/package.json
+++ b/package.json
@@ -11,12 +11,11 @@
"test:e2e": "turbo run test:e2e",
"test:e2e:watch": "turbo run test:e2e -- --ui",
"clean": "turbo run clean --no-cache",
- "dev:example": "turbo run dev --parallel --continue --filter=nextjs-example-app... --filter=!./packages/adapter-*",
- "dev:db": "turbo run dev --parallel --continue --filter=next-auth-app...",
"dev": "turbo run dev --parallel --continue --filter=next-auth-app... --filter=@auth/core --filter=!./packages/adapter-*",
- "dev-v4:db": "turbo run dev --parallel --continue --filter=next-auth-app-v4...",
- "dev-v4": "turbo run dev --parallel --continue --filter=next-auth-app-v4... --filter=!./packages/adapter-*",
+ "dev:db": "turbo run dev --parallel --continue --filter=next-auth-app...",
"dev:kit": "turbo run dev --parallel --continue --filter=sveltekit-auth-app...",
+ "dev:express": "turbo run dev --parallel --continue --filter=express-auth-app...",
+ "dev:example": "turbo run dev --parallel --continue --filter=nextjs-example-app... --filter=!./packages/adapter-*",
"dev:docs": "turbo run dev --filter=docs",
"dev:docs:adapters": "turbo run dev --filter=docs",
"email": "fake-smtp-server",
@@ -26,7 +25,6 @@
"release": "release",
"peek": "pnpm release --peek",
"version:pr": "node ./config/version-pr",
- "e2e": "turbo run e2e --filter=next-auth-app",
"setup-fw-integration": "pnpm clean --filter=@auth/frameworks-template && node packages/utils/scripts/setup-fw-integration.js"
},
"devDependencies": {
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index c43790bed5..a56c6fc05b 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -101,6 +101,40 @@ importers:
specifier: 1.2.2
version: 1.2.2(@types/node@20.11.7)(@vitest/ui@1.2.2)
+ apps/dev/express:
+ dependencies:
+ '@auth/express':
+ specifier: workspace:*
+ version: link:../../../packages/frameworks-express
+ express:
+ specifier: ^4.19.2
+ version: 4.19.2
+ morgan:
+ specifier: ^1.10.0
+ version: 1.10.0
+ pug:
+ specifier: ^3.0.2
+ version: 3.0.2
+ devDependencies:
+ '@prettier/plugin-pug':
+ specifier: ^3.0.0
+ version: 3.0.0(prettier@3.1.1)
+ '@types/express':
+ specifier: ^4.17.21
+ version: 4.17.21
+ '@types/morgan':
+ specifier: ^1.9.9
+ version: 1.9.9
+ '@types/pug':
+ specifier: ^2.0.10
+ version: 2.0.10
+ tsx:
+ specifier: ^4.7.3
+ version: 4.7.3
+ typescript:
+ specifier: 5.4.5
+ version: 5.4.5
+
apps/dev/nextjs:
dependencies:
'@auth/prisma-adapter':
@@ -182,7 +216,7 @@ importers:
version: 0.4.5(react-dom@18.2.0)(react@18.2.0)
'@inkeep/widgets':
specifier: ^0.2.272
- version: 0.2.272(@internationalized/date@3.5.2)(@types/react@18.2.78)(prop-types@15.8.1)(react-dom@18.2.0)(react@18.2.0)(typescript@5.3.3)
+ version: 0.2.272(@internationalized/date@3.5.2)(@types/react@18.2.78)(prop-types@15.8.1)(react-dom@18.2.0)(react@18.2.0)(typescript@5.4.5)
'@next/third-parties':
specifier: ^14.2.1
version: 14.2.1(next@14.2.1)(react@18.2.0)
@@ -252,7 +286,7 @@ importers:
version: 3.4.3
typedoc:
specifier: ^0.25.13
- version: 0.25.13(typescript@5.3.3)
+ version: 0.25.13(typescript@5.4.5)
typedoc-plugin-markdown:
specifier: 4.0.0-next.54
version: 4.0.0-next.54(typedoc@0.25.13)
@@ -361,7 +395,7 @@ importers:
version: 1.3.1
fauna-shell:
specifier: 1.2.1
- version: 1.2.1(@types/node@20.12.7)(typescript@5.3.3)
+ version: 1.2.1(@types/node@20.12.7)(typescript@5.4.5)
packages/adapter-firebase:
dependencies:
@@ -592,7 +626,7 @@ importers:
devDependencies:
'@xata.io/client':
specifier: ^0.13.0
- version: 0.13.4(typescript@5.3.3)
+ version: 0.13.4(typescript@5.4.5)
packages/core:
dependencies:
@@ -647,7 +681,7 @@ importers:
version: 12.0.2(postcss@8.4.19)
typedoc:
specifier: ^0.25.12
- version: 0.25.12(typescript@5.3.3)
+ version: 0.25.12(typescript@5.4.5)
typedoc-plugin-markdown:
specifier: 4.0.0-next.53
version: 4.0.0-next.53(typedoc@0.25.12)
@@ -707,7 +741,7 @@ importers:
version: 2.4.3(@sveltejs/vite-plugin-svelte@3.0.1)(svelte@4.2.9)(vite@5.0.13)
'@sveltejs/package':
specifier: ^2.0.0
- version: 2.2.6(svelte@4.2.9)(typescript@5.3.3)
+ version: 2.2.6(svelte@4.2.9)(typescript@5.4.5)
'@sveltejs/vite-plugin-svelte':
specifier: ^3.0.0
version: 3.0.1(svelte@4.2.9)(vite@5.0.13)
@@ -725,7 +759,7 @@ importers:
version: 2.6.2
typedoc:
specifier: ^0.25.12
- version: 0.25.12(typescript@5.3.3)
+ version: 0.25.12(typescript@5.4.5)
typedoc-plugin-markdown:
specifier: 4.0.0-next.53
version: 4.0.0-next.53(typedoc@0.25.12)
@@ -5172,7 +5206,7 @@ packages:
react-dom: 18.2.0(react@18.2.0)
dev: false
- /@inkeep/components@0.0.23(@ark-ui/react@0.15.0)(@internationalized/date@3.5.2)(react-dom@18.2.0)(react@18.2.0)(typescript@5.3.3):
+ /@inkeep/components@0.0.23(@ark-ui/react@0.15.0)(@internationalized/date@3.5.2)(react-dom@18.2.0)(react@18.2.0)(typescript@5.4.5):
resolution: {integrity: sha512-JwMdEB2JoMNQwJocYq4ontMOlatYBSkv9AIgPBnxcO9+IkguIQTE5821mrRQJsOtpS58LuFzt+fYcuGX6sqtWw==}
peerDependencies:
'@ark-ui/react': '>=0.15.0'
@@ -5180,11 +5214,11 @@ packages:
react-dom: ^18.2.0
dependencies:
'@ark-ui/react': 0.15.0(@internationalized/date@3.5.2)(react-dom@18.2.0)(react@18.2.0)
- '@inkeep/preset': 0.0.23(@internationalized/date@3.5.2)(typescript@5.3.3)
- '@inkeep/preset-chakra': 0.0.23(@internationalized/date@3.5.2)(typescript@5.3.3)
+ '@inkeep/preset': 0.0.23(@internationalized/date@3.5.2)(typescript@5.4.5)
+ '@inkeep/preset-chakra': 0.0.23(@internationalized/date@3.5.2)(typescript@5.4.5)
'@inkeep/shared': 0.0.24
'@inkeep/styled-system': 0.0.37
- '@pandacss/dev': 0.22.1(typescript@5.3.3)
+ '@pandacss/dev': 0.22.1(typescript@5.4.5)
framer-motion: 10.18.0(react-dom@18.2.0)(react@18.2.0)
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
@@ -5194,25 +5228,25 @@ packages:
- typescript
dev: false
- /@inkeep/preset-chakra@0.0.23(@internationalized/date@3.5.2)(typescript@5.3.3):
+ /@inkeep/preset-chakra@0.0.23(@internationalized/date@3.5.2)(typescript@5.4.5):
resolution: {integrity: sha512-3RxQPV28mqBmOJliBJAZlL3lemcIGdZvYs7a2jGESjKUfD19ARNnCXZ+NaXjvdONGB/NiwNsFtBUKEn3YixvQg==}
dependencies:
'@ark-ui/anatomy': 0.1.0(@internationalized/date@3.5.2)
'@inkeep/shared': 0.0.24
- '@pandacss/dev': 0.22.1(typescript@5.3.3)
+ '@pandacss/dev': 0.22.1(typescript@5.4.5)
transitivePeerDependencies:
- '@internationalized/date'
- jsdom
- typescript
dev: false
- /@inkeep/preset@0.0.23(@internationalized/date@3.5.2)(typescript@5.3.3):
+ /@inkeep/preset@0.0.23(@internationalized/date@3.5.2)(typescript@5.4.5):
resolution: {integrity: sha512-LGI6y3PZq/jJawDA8uUpudbmugKnEpJxvBwxBKpDZ1+DsqKeAx+45DUwLHv3Bd0yrPAZPqnhjumBhoD/uIjrgg==}
dependencies:
'@ark-ui/anatomy': 0.1.0(@internationalized/date@3.5.2)
- '@inkeep/preset-chakra': 0.0.23(@internationalized/date@3.5.2)(typescript@5.3.3)
+ '@inkeep/preset-chakra': 0.0.23(@internationalized/date@3.5.2)(typescript@5.4.5)
'@inkeep/shared': 0.0.24
- '@pandacss/dev': 0.22.1(typescript@5.3.3)
+ '@pandacss/dev': 0.22.1(typescript@5.4.5)
colorjs.io: 0.4.5
transitivePeerDependencies:
- '@internationalized/date'
@@ -5232,7 +5266,7 @@ packages:
resolution: {integrity: sha512-jQ8u/FMRa/7tTtF5uhKiVxSIQjLtazWFdPFr7+aI8Yj/O4ERqXaV98S7852neikQ3cxREYv5mAnaMH8bMMSqNg==}
dev: false
- /@inkeep/widgets@0.2.272(@internationalized/date@3.5.2)(@types/react@18.2.78)(prop-types@15.8.1)(react-dom@18.2.0)(react@18.2.0)(typescript@5.3.3):
+ /@inkeep/widgets@0.2.272(@internationalized/date@3.5.2)(@types/react@18.2.78)(prop-types@15.8.1)(react-dom@18.2.0)(react@18.2.0)(typescript@5.4.5):
resolution: {integrity: sha512-4uXGVqXGxMXAAx105QOCgWuhCa0JgALQICVcEF+Q/TBulZBKGwBJKoyb9TTAGLdB/cq6+8FFif1RizBqdf3jUw==}
peerDependencies:
react: ^18.2.0
@@ -5241,9 +5275,9 @@ packages:
'@apollo/client': 3.9.5(@types/react@18.2.78)(graphql-ws@5.14.3)(graphql@16.8.1)(react-dom@18.2.0)(react@18.2.0)
'@ark-ui/react': 0.15.0(@internationalized/date@3.5.2)(react-dom@18.2.0)(react@18.2.0)
'@inkeep/color-mode': 0.0.23(react-dom@18.2.0)(react@18.2.0)
- '@inkeep/components': 0.0.23(@ark-ui/react@0.15.0)(@internationalized/date@3.5.2)(react-dom@18.2.0)(react@18.2.0)(typescript@5.3.3)
- '@inkeep/preset': 0.0.23(@internationalized/date@3.5.2)(typescript@5.3.3)
- '@inkeep/preset-chakra': 0.0.23(@internationalized/date@3.5.2)(typescript@5.3.3)
+ '@inkeep/components': 0.0.23(@ark-ui/react@0.15.0)(@internationalized/date@3.5.2)(react-dom@18.2.0)(react@18.2.0)(typescript@5.4.5)
+ '@inkeep/preset': 0.0.23(@internationalized/date@3.5.2)(typescript@5.4.5)
+ '@inkeep/preset-chakra': 0.0.23(@internationalized/date@3.5.2)(typescript@5.4.5)
'@inkeep/shared': 0.0.24
'@inkeep/styled-system': 0.0.40
'@types/lodash.isequal': 4.5.8
@@ -6200,7 +6234,7 @@ packages:
tslib: 2.6.2
dev: true
- /@oclif/core@2.15.0(@types/node@20.12.7)(typescript@5.3.3):
+ /@oclif/core@2.15.0(@types/node@20.12.7)(typescript@5.4.5):
resolution: {integrity: sha512-fNEMG5DzJHhYmI3MgpByTvltBOMyFcnRIUMxbiz2ai8rhaYgaTHMG3Q38HcosfIvtw9nCjxpcQtC8MN8QtVCcA==}
engines: {node: '>=14.0.0'}
dependencies:
@@ -6227,7 +6261,7 @@ packages:
strip-ansi: 6.0.1
supports-color: 8.1.1
supports-hyperlinks: 2.3.0
- ts-node: 10.9.2(@types/node@20.12.7)(typescript@5.3.3)
+ ts-node: 10.9.2(@types/node@20.12.7)(typescript@5.4.5)
tslib: 2.6.2
widest-line: 3.1.0
wordwrap: 1.0.0
@@ -6255,11 +6289,11 @@ packages:
resolution: {integrity: sha512-Ups2dShK52xXa8w6iBWLgcjPJWjais6KPJQq3gQ/88AY6BXoTX+MIGFPrWQO1KLMiQfoTpcLnUwloN4brrVUHw==}
dev: true
- /@oclif/plugin-help@5.2.20(@types/node@20.12.7)(typescript@5.3.3):
+ /@oclif/plugin-help@5.2.20(@types/node@20.12.7)(typescript@5.4.5):
resolution: {integrity: sha512-u+GXX/KAGL9S10LxAwNUaWdzbEBARJ92ogmM7g3gDVud2HioCmvWQCDohNRVZ9GYV9oKwZ/M8xwd6a1d95rEKQ==}
engines: {node: '>=12.0.0'}
dependencies:
- '@oclif/core': 2.15.0(@types/node@20.12.7)(typescript@5.3.3)
+ '@oclif/core': 2.15.0(@types/node@20.12.7)(typescript@5.4.5)
transitivePeerDependencies:
- '@swc/core'
- '@swc/wasm'
@@ -6267,12 +6301,12 @@ packages:
- typescript
dev: true
- /@oclif/plugin-plugins@2.4.7(@types/node@20.12.7)(typescript@5.3.3):
+ /@oclif/plugin-plugins@2.4.7(@types/node@20.12.7)(typescript@5.4.5):
resolution: {integrity: sha512-6fzUDLWrSK7n6+EBrEekEEYrYTCneRoOF9TzojkjuFn1+ailvUlr98G90bblxKOyy8fqMe7QjvqwTgIDQ9ZIzg==}
engines: {node: '>=12.0.0'}
dependencies:
'@oclif/color': 1.0.13
- '@oclif/core': 2.15.0(@types/node@20.12.7)(typescript@5.3.3)
+ '@oclif/core': 2.15.0(@types/node@20.12.7)(typescript@5.4.5)
chalk: 4.1.2
debug: 4.3.4(supports-color@8.1.1)
fs-extra: 9.1.0
@@ -6323,7 +6357,7 @@ packages:
escalade: 3.1.1
jiti: 1.21.0
merge-anything: 5.1.7
- typescript: 5.3.3
+ typescript: 5.4.5
dev: false
/@pandacss/core@0.22.1:
@@ -6348,7 +6382,7 @@ packages:
ts-pattern: 5.0.5
dev: false
- /@pandacss/dev@0.22.1(typescript@5.3.3):
+ /@pandacss/dev@0.22.1(typescript@5.4.5):
resolution: {integrity: sha512-/w6OUwDeL4lM2mVYGBcX/sBcGYaPNLoakTRbLBjo/V/Kc/tTpycuGpag9wHG/ZD58upe6dl4biJ33oFW3B7X4A==}
hasBin: true
dependencies:
@@ -6356,8 +6390,8 @@ packages:
'@pandacss/config': 0.22.1
'@pandacss/error': 0.22.1
'@pandacss/logger': 0.22.1
- '@pandacss/node': 0.22.1(typescript@5.3.3)
- '@pandacss/postcss': 0.22.1(typescript@5.3.3)
+ '@pandacss/node': 0.22.1(typescript@5.4.5)
+ '@pandacss/postcss': 0.22.1(typescript@5.4.5)
'@pandacss/preset-panda': 0.22.1
'@pandacss/shared': 0.22.1
'@pandacss/token-dictionary': 0.22.1
@@ -6374,10 +6408,10 @@ packages:
resolution: {integrity: sha512-o9vlQBvkaM+4wHhnC8qDBk0GxrCj8KIipheU8BDwLke3ZBq4neL5IMSXB+Vpl/7GFCJFZ/C7TThA1nrAmTa9hg==}
dev: false
- /@pandacss/extractor@0.22.1(typescript@5.3.3):
+ /@pandacss/extractor@0.22.1(typescript@5.4.5):
resolution: {integrity: sha512-OgPJ0gtGRFExsQQWjIWpsMfMM2XzfafkYh3Q86fR0ap+M4XXcsd3pR9fuoCquZeYnCSe4vpot4TLVwqvB3Ft2Q==}
dependencies:
- ts-evaluator: 1.2.0(typescript@5.3.3)
+ ts-evaluator: 1.2.0(typescript@5.4.5)
ts-morph: 19.0.0
transitivePeerDependencies:
- jsdom
@@ -6412,17 +6446,17 @@ packages:
lil-fp: 1.4.5
dev: false
- /@pandacss/node@0.22.1(typescript@5.3.3):
+ /@pandacss/node@0.22.1(typescript@5.4.5):
resolution: {integrity: sha512-a+Lq6SXP4BLPFtE2mq8TrEA4knaPltFccs/F9oyoEBOpgLwJstKj/lqf/Q1iXVdMAAVkPGNtjfdox5kxoGGzrw==}
dependencies:
'@pandacss/config': 0.22.1
'@pandacss/core': 0.22.1
'@pandacss/error': 0.22.1
- '@pandacss/extractor': 0.22.1(typescript@5.3.3)
+ '@pandacss/extractor': 0.22.1(typescript@5.4.5)
'@pandacss/generator': 0.22.1
'@pandacss/is-valid-prop': 0.22.1
'@pandacss/logger': 0.22.1
- '@pandacss/parser': 0.22.1(typescript@5.3.3)
+ '@pandacss/parser': 0.22.1(typescript@5.4.5)
'@pandacss/shared': 0.22.1
'@pandacss/token-dictionary': 0.22.1
'@pandacss/types': 0.22.1
@@ -6447,17 +6481,17 @@ packages:
prettier: 2.8.8
ts-morph: 19.0.0
ts-pattern: 5.0.5
- tsconfck: 2.1.2(typescript@5.3.3)
+ tsconfck: 2.1.2(typescript@5.4.5)
transitivePeerDependencies:
- jsdom
- typescript
dev: false
- /@pandacss/parser@0.22.1(typescript@5.3.3):
+ /@pandacss/parser@0.22.1(typescript@5.4.5):
resolution: {integrity: sha512-uKSpQeVDtG5uF4M1It/SOBjFmyKnDbFaJINVa/wFy5kgETn63jalOaenFTi0YEEzeaIIrElb1mIW6AlqhgYEKw==}
dependencies:
'@pandacss/config': 0.22.1
- '@pandacss/extractor': 0.22.1(typescript@5.3.3)
+ '@pandacss/extractor': 0.22.1(typescript@5.4.5)
'@pandacss/is-valid-prop': 0.22.1
'@pandacss/logger': 0.22.1
'@pandacss/shared': 0.22.1
@@ -6472,10 +6506,10 @@ packages:
- typescript
dev: false
- /@pandacss/postcss@0.22.1(typescript@5.3.3):
+ /@pandacss/postcss@0.22.1(typescript@5.4.5):
resolution: {integrity: sha512-DzPT8zwsRrPtfzoVXkt2x576veN7bzyF3wERPIOYUtbEkd8uUCunqLoazcMyuUfOaUv9X5pqQkPqsH1glSJ6Dg==}
dependencies:
- '@pandacss/node': 0.22.1(typescript@5.3.3)
+ '@pandacss/node': 0.22.1(typescript@5.4.5)
postcss: 8.4.38
transitivePeerDependencies:
- jsdom
@@ -7436,11 +7470,11 @@ packages:
/@shikijs/core@1.3.0:
resolution: {integrity: sha512-7fedsBfuILDTBmrYZNFI8B6ATTxhQAasUHllHmjvSZPnoq4bULWoTpHwmuQvZ8Aq03/tAa2IGo6RXqWtHdWaCA==}
- /@shikijs/twoslash@1.2.4(typescript@5.3.3):
+ /@shikijs/twoslash@1.2.4(typescript@5.4.5):
resolution: {integrity: sha512-4F2gNlCFN9HY0jV3J/IBfqkI7w2HBwycwUBx9fLYGYxzbfu0gYRJdQYWtvJC/sG2rYTYlJrS5BpWdXYoMHwbXw==}
dependencies:
'@shikijs/core': 1.2.4
- twoslash: 0.2.5(typescript@5.3.3)
+ twoslash: 0.2.5(typescript@5.4.5)
transitivePeerDependencies:
- supports-color
- typescript
@@ -8031,7 +8065,7 @@ packages:
vite: 5.0.13(@types/node@20.11.7)
dev: true
- /@sveltejs/package@2.2.6(svelte@4.2.9)(typescript@5.3.3):
+ /@sveltejs/package@2.2.6(svelte@4.2.9)(typescript@5.4.5):
resolution: {integrity: sha512-rhKL/96M7LCvFI2xN94qsqHtEWr/ypcMGiii3s6dRW7ADt3tiDm8UfExjRR8v5jW3Femz0+VJ0TNevxI4Q9Quw==}
engines: {node: ^16.14 || >=18}
hasBin: true
@@ -8043,7 +8077,7 @@ packages:
sade: 1.8.1
semver: 7.5.4
svelte: 4.2.9
- svelte2tsx: 0.7.0(svelte@4.2.9)(typescript@5.3.3)
+ svelte2tsx: 0.7.0(svelte@4.2.9)(typescript@5.4.5)
transitivePeerDependencies:
- typescript
dev: true
@@ -8610,6 +8644,12 @@ packages:
resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==}
dev: true
+ /@types/morgan@1.9.9:
+ resolution: {integrity: sha512-iRYSDKVaC6FkGSpEVVIvrRGw0DfJMiQzIn3qr2G5B3C//AWkulhXgaBd7tS9/J79GWSYMTHGs7PfI5b3Y8m+RQ==}
+ dependencies:
+ '@types/node': 20.12.7
+ dev: true
+
/@types/ms@0.7.34:
resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==}
@@ -9388,12 +9428,12 @@ packages:
tslib: 2.6.2
dev: false
- /@xata.io/client@0.13.4(typescript@5.3.3):
+ /@xata.io/client@0.13.4(typescript@5.4.5):
resolution: {integrity: sha512-eODWMjW185bPR3YcBSWOHeH5FlxsVSq8lbCoHxrjt8TZAthXb9MHwEUhgh39GrkwcQ181XRz2XwKDJAipIRg6A==}
peerDependencies:
typescript: '>=4.5'
dependencies:
- typescript: 5.3.3
+ typescript: 5.4.5
dev: true
/@xmldom/xmldom@0.8.10:
@@ -10553,7 +10593,6 @@ packages:
resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==}
engines: {node: '>=0.4.0'}
hasBin: true
- dev: true
/acorn@8.11.3:
resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==}
@@ -10901,7 +10940,6 @@ packages:
/asap@2.0.6:
resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==}
- dev: true
/asn1js@3.0.5:
resolution: {integrity: sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==}
@@ -10911,6 +10949,10 @@ packages:
pvutils: 1.1.3
tslib: 2.6.2
+ /assert-never@1.2.1:
+ resolution: {integrity: sha512-TaTivMB6pYI1kXwrFlEhLeGfOqoDNdTxjCdwRfFFkEA30Eu+k48W34nlok2EYWJfFFzqaEmichdNM7th6M5HNw==}
+ dev: false
+
/assertion-error@1.1.0:
resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==}
dev: true
@@ -11158,6 +11200,13 @@ packages:
babel-plugin-jsx-dom-expressions: 0.37.16(@babel/core@7.23.9)
dev: true
+ /babel-walk@3.0.0-canary-5:
+ resolution: {integrity: sha512-GAwkz0AihzY5bkwIY5QDR+LvsRQgB/B+1foMPvi0FZPMl5fjD7ICiznUiBdLYMH1QYe6vqu4gWYytZOccLouFw==}
+ engines: {node: '>= 10.0.0'}
+ dependencies:
+ '@babel/types': 7.23.9
+ dev: false
+
/bail@2.0.2:
resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==}
dev: false
@@ -11181,7 +11230,6 @@ packages:
engines: {node: '>= 0.8'}
dependencies:
safe-buffer: 5.1.2
- dev: true
/better-react-mathjax@2.0.3(react@18.2.0):
resolution: {integrity: sha512-wfifT8GFOKb1TWm2+E50I6DJpLZ5kLbch283Lu043EJtwSv0XvZDjr4YfR4d2MjAhqP6SH4VjjrKgbX8R00oCQ==}
@@ -11273,6 +11321,26 @@ packages:
unpipe: 1.0.0
transitivePeerDependencies:
- supports-color
+ dev: false
+
+ /body-parser@1.20.2:
+ resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==}
+ engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
+ dependencies:
+ bytes: 3.1.2
+ content-type: 1.0.5
+ debug: 2.6.9
+ depd: 2.0.0
+ destroy: 1.2.0
+ http-errors: 2.0.0
+ iconv-lite: 0.4.24
+ on-finished: 2.4.1
+ qs: 6.11.0
+ raw-body: 2.5.2
+ type-is: 1.6.18
+ unpipe: 1.0.0
+ transitivePeerDependencies:
+ - supports-color
/boolbase@1.0.0:
resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
@@ -11677,7 +11745,6 @@ packages:
resolution: {integrity: sha512-+UqJQjFEFaTAs3bNsF2j2kEN1baG/zghZbdqoYEDxGZtJo9LBzl1A+m0D4n3qKx8N2FNv8/Xp6yV9mQmBuptaw==}
dependencies:
is-regex: 1.1.4
- dev: true
/character-reference-invalid@2.0.1:
resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==}
@@ -12105,6 +12172,13 @@ packages:
upper-case: 2.0.2
dev: true
+ /constantinople@4.0.1:
+ resolution: {integrity: sha512-vCrqcSIq4//Gx74TXXCGnHpulY1dskqLTFGDmhrGxzeXL8lF8kvXv6mpNWlJj1uD4DW23D4ljAqbY4RRaaUZIw==}
+ dependencies:
+ '@babel/parser': 7.23.9
+ '@babel/types': 7.23.9
+ dev: false
+
/content-disposition@0.5.4:
resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==}
engines: {node: '>= 0.6'}
@@ -12145,6 +12219,7 @@ packages:
/cookie@0.5.0:
resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==}
engines: {node: '>= 0.6'}
+ dev: false
/cookie@0.6.0:
resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==}
@@ -12940,6 +13015,10 @@ packages:
esutils: 2.0.3
dev: true
+ /doctypes@1.1.0:
+ resolution: {integrity: sha512-LLBi6pEqS6Do3EKQ3J0NqHWV5hhb78Pi8vvESYwyOy2c31ZEZVdtitdzsQsKb7878PEERhzUk0ftqGhG6Mz+pQ==}
+ dev: false
+
/dom-serializer@2.0.0:
resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==}
dependencies:
@@ -14202,6 +14281,45 @@ packages:
vary: 1.1.2
transitivePeerDependencies:
- supports-color
+ dev: false
+
+ /express@4.19.2:
+ resolution: {integrity: sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==}
+ engines: {node: '>= 0.10.0'}
+ dependencies:
+ accepts: 1.3.8
+ array-flatten: 1.1.1
+ body-parser: 1.20.2
+ content-disposition: 0.5.4
+ content-type: 1.0.5
+ cookie: 0.6.0
+ cookie-signature: 1.0.6
+ debug: 2.6.9
+ depd: 2.0.0
+ encodeurl: 1.0.2
+ escape-html: 1.0.3
+ etag: 1.8.1
+ finalhandler: 1.2.0
+ fresh: 0.5.2
+ http-errors: 2.0.0
+ merge-descriptors: 1.0.1
+ methods: 1.1.2
+ on-finished: 2.4.1
+ parseurl: 1.3.3
+ path-to-regexp: 0.1.7
+ proxy-addr: 2.0.7
+ qs: 6.11.0
+ range-parser: 1.2.1
+ safe-buffer: 5.2.1
+ send: 0.18.0
+ serve-static: 1.15.0
+ setprototypeof: 1.2.0
+ statuses: 2.0.1
+ type-is: 1.6.18
+ utils-merge: 1.0.1
+ vary: 1.1.2
+ transitivePeerDependencies:
+ - supports-color
/ext@1.7.0:
resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==}
@@ -14245,7 +14363,7 @@ packages:
hasBin: true
dependencies:
cli: 1.0.1
- express: 4.18.2
+ express: 4.19.2
express-basic-auth: 1.2.1
lodash: 4.17.21
mailparser: 3.6.6
@@ -14331,15 +14449,15 @@ packages:
format: 0.2.2
dev: false
- /fauna-shell@1.2.1(@types/node@20.12.7)(typescript@5.3.3):
+ /fauna-shell@1.2.1(@types/node@20.12.7)(typescript@5.4.5):
resolution: {integrity: sha512-JY48qkliJbbrkdeUlKT8Z/NDyZCAsgsiGI+bXIy7tDwTURsNpQ4biNK2X5nqKgdNfULrRn6NkSessdcI+RnoHA==}
engines: {node: '>=10.0.0'}
hasBin: true
dependencies:
'@inquirer/prompts': 3.3.2
- '@oclif/core': 2.15.0(@types/node@20.12.7)(typescript@5.3.3)
- '@oclif/plugin-help': 5.2.20(@types/node@20.12.7)(typescript@5.3.3)
- '@oclif/plugin-plugins': 2.4.7(@types/node@20.12.7)(typescript@5.3.3)
+ '@oclif/core': 2.15.0(@types/node@20.12.7)(typescript@5.4.5)
+ '@oclif/plugin-help': 5.2.20(@types/node@20.12.7)(typescript@5.4.5)
+ '@oclif/plugin-plugins': 2.4.7(@types/node@20.12.7)(typescript@5.4.5)
chalk: 4.1.2
cli-table: 0.3.11
cli-ux: 4.9.3
@@ -15226,7 +15344,6 @@ packages:
engines: {node: '>= 0.4'}
dependencies:
has-symbols: 1.0.3
- dev: true
/has-unicode@2.0.1:
resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==}
@@ -16007,7 +16124,6 @@ packages:
resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==}
dependencies:
hasown: 2.0.0
- dev: true
/is-date-object@1.0.5:
resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==}
@@ -16036,7 +16152,6 @@ packages:
dependencies:
acorn: 7.4.1
object-assign: 4.1.1
- dev: true
/is-extendable@0.1.1:
resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==}
@@ -16147,7 +16262,6 @@ packages:
/is-promise@2.2.2:
resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==}
- dev: true
/is-property@1.0.2:
resolution: {integrity: sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==}
@@ -16164,7 +16278,6 @@ packages:
dependencies:
call-bind: 1.0.5
has-tostringtag: 1.0.0
- dev: true
/is-relative@1.0.0:
resolution: {integrity: sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==}
@@ -16425,6 +16538,10 @@ packages:
resolution: {integrity: sha512-dwXFwByc/ajSV6m5bcKAPwe4yDDF6D614pxmIi5odytzxRlwqF6nwoiCek80Ixc7Cvma5awClxrzFtxCQvcM8w==}
dev: true
+ /js-stringify@1.0.2:
+ resolution: {integrity: sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g==}
+ dev: false
+
/js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
@@ -16616,6 +16733,13 @@ packages:
ms: 2.1.3
semver: 7.5.4
+ /jstransformer@1.0.0:
+ resolution: {integrity: sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A==}
+ dependencies:
+ is-promise: 2.2.2
+ promise: 7.3.1
+ dev: false
+
/jsx-ast-utils@3.3.5:
resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==}
engines: {node: '>=4.0'}
@@ -18621,6 +18745,19 @@ packages:
mongodb-connection-string-url: 3.0.0
dev: true
+ /morgan@1.10.0:
+ resolution: {integrity: sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==}
+ engines: {node: '>= 0.8.0'}
+ dependencies:
+ basic-auth: 2.0.1
+ debug: 2.6.9
+ depd: 2.0.0
+ on-finished: 2.3.0
+ on-headers: 1.0.2
+ transitivePeerDependencies:
+ - supports-color
+ dev: false
+
/mri@1.2.0:
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
engines: {node: '>=4'}
@@ -18959,7 +19096,7 @@ packages:
'@mdx-js/mdx': 3.0.0
'@mdx-js/react': 3.0.0(@types/react@18.2.78)(react@18.2.0)
'@napi-rs/simple-git': 0.1.16
- '@shikijs/twoslash': 1.2.4(typescript@5.3.3)
+ '@shikijs/twoslash': 1.2.4(typescript@5.4.5)
'@theguild/remark-mermaid': 0.0.5(react@18.2.0)
'@theguild/remark-npm2yarn': 0.3.0
better-react-mathjax: 2.0.3(react@18.2.0)
@@ -19363,7 +19500,6 @@ packages:
engines: {node: '>= 0.8'}
dependencies:
ee-first: 1.1.1
- dev: true
/on-finished@2.4.1:
resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
@@ -19374,7 +19510,6 @@ packages:
/on-headers@1.0.2:
resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==}
engines: {node: '>= 0.8'}
- dev: true
/once@1.4.0:
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
@@ -19694,7 +19829,6 @@ packages:
/path-parse@1.0.7:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
- dev: true
/path-root-regex@0.1.2:
resolution: {integrity: sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==}
@@ -20534,7 +20668,6 @@ packages:
resolution: {integrity: sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==}
dependencies:
asap: 2.0.6
- dev: true
/prop-types@15.8.1:
resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
@@ -20640,9 +20773,39 @@ packages:
resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==}
dev: true
+ /pug-attrs@3.0.0:
+ resolution: {integrity: sha512-azINV9dUtzPMFQktvTXciNAfAuVh/L/JCl0vtPCwvOA21uZrC08K/UnmrL+SXGEVc1FwzjW62+xw5S/uaLj6cA==}
+ dependencies:
+ constantinople: 4.0.1
+ js-stringify: 1.0.2
+ pug-runtime: 3.0.1
+ dev: false
+
+ /pug-code-gen@3.0.2:
+ resolution: {integrity: sha512-nJMhW16MbiGRiyR4miDTQMRWDgKplnHyeLvioEJYbk1RsPI3FuA3saEP8uwnTb2nTJEKBU90NFVWJBk4OU5qyg==}
+ dependencies:
+ constantinople: 4.0.1
+ doctypes: 1.1.0
+ js-stringify: 1.0.2
+ pug-attrs: 3.0.0
+ pug-error: 2.0.0
+ pug-runtime: 3.0.1
+ void-elements: 3.1.0
+ with: 7.0.2
+ dev: false
+
/pug-error@2.0.0:
resolution: {integrity: sha512-sjiUsi9M4RAGHktC1drQfCr5C5eriu24Lfbt4s+7SykztEOwVZtbFk1RRq0tzLxcMxMYTBR+zMQaG07J/btayQ==}
- dev: true
+
+ /pug-filters@4.0.0:
+ resolution: {integrity: sha512-yeNFtq5Yxmfz0f9z2rMXGw/8/4i1cCFecw/Q7+D0V2DdtII5UvqE12VaZ2AY7ri6o5RNXiweGH79OCq+2RQU4A==}
+ dependencies:
+ constantinople: 4.0.1
+ jstransformer: 1.0.0
+ pug-error: 2.0.0
+ pug-walk: 2.0.0
+ resolve: 1.22.8
+ dev: false
/pug-lexer@5.0.1:
resolution: {integrity: sha512-0I6C62+keXlZPZkOJeVam9aBLVP2EnbeDw3An+k0/QlqdwH6rv8284nko14Na7c0TtqtogfWXcRoFE4O4Ff20w==}
@@ -20650,7 +20813,54 @@ packages:
character-parser: 2.2.0
is-expression: 4.0.0
pug-error: 2.0.0
- dev: true
+
+ /pug-linker@4.0.0:
+ resolution: {integrity: sha512-gjD1yzp0yxbQqnzBAdlhbgoJL5qIFJw78juN1NpTLt/mfPJ5VgC4BvkoD3G23qKzJtIIXBbcCt6FioLSFLOHdw==}
+ dependencies:
+ pug-error: 2.0.0
+ pug-walk: 2.0.0
+ dev: false
+
+ /pug-load@3.0.0:
+ resolution: {integrity: sha512-OCjTEnhLWZBvS4zni/WUMjH2YSUosnsmjGBB1An7CsKQarYSWQ0GCVyd4eQPMFJqZ8w9xgs01QdiZXKVjk92EQ==}
+ dependencies:
+ object-assign: 4.1.1
+ pug-walk: 2.0.0
+ dev: false
+
+ /pug-parser@6.0.0:
+ resolution: {integrity: sha512-ukiYM/9cH6Cml+AOl5kETtM9NR3WulyVP2y4HOU45DyMim1IeP/OOiyEWRr6qk5I5klpsBnbuHpwKmTx6WURnw==}
+ dependencies:
+ pug-error: 2.0.0
+ token-stream: 1.0.0
+ dev: false
+
+ /pug-runtime@3.0.1:
+ resolution: {integrity: sha512-L50zbvrQ35TkpHwv0G6aLSuueDRwc/97XdY8kL3tOT0FmhgG7UypU3VztfV/LATAvmUfYi4wNxSajhSAeNN+Kg==}
+ dev: false
+
+ /pug-strip-comments@2.0.0:
+ resolution: {integrity: sha512-zo8DsDpH7eTkPHCXFeAk1xZXJbyoTfdPlNR0bK7rpOMuhBYb0f5qUVCO1xlsitYd3w5FQTK7zpNVKb3rZoUrrQ==}
+ dependencies:
+ pug-error: 2.0.0
+ dev: false
+
+ /pug-walk@2.0.0:
+ resolution: {integrity: sha512-yYELe9Q5q9IQhuvqsZNwA5hfPkMJ8u92bQLIMcsMxf/VADjNtEYptU+inlufAFYcWdHlwNfZOEnOOQrZrcyJCQ==}
+ dev: false
+
+ /pug@3.0.2:
+ resolution: {integrity: sha512-bp0I/hiK1D1vChHh6EfDxtndHji55XP/ZJKwsRqrz6lRia6ZC2OZbdAymlxdVFwd1L70ebrVJw4/eZ79skrIaw==}
+ dependencies:
+ pug-code-gen: 3.0.2
+ pug-filters: 4.0.0
+ pug-lexer: 5.0.1
+ pug-linker: 4.0.0
+ pug-load: 3.0.0
+ pug-parser: 6.0.0
+ pug-runtime: 3.0.1
+ pug-strip-comments: 2.0.0
+ dev: false
/pump@3.0.0:
resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==}
@@ -20726,6 +20936,16 @@ packages:
http-errors: 2.0.0
iconv-lite: 0.4.24
unpipe: 1.0.0
+ dev: false
+
+ /raw-body@2.5.2:
+ resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==}
+ engines: {node: '>= 0.8'}
+ dependencies:
+ bytes: 3.1.2
+ http-errors: 2.0.0
+ iconv-lite: 0.4.24
+ unpipe: 1.0.0
/rc@1.2.8:
resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==}
@@ -21362,7 +21582,6 @@ packages:
is-core-module: 2.13.1
path-parse: 1.0.7
supports-preserve-symlinks-flag: 1.0.0
- dev: true
/resolve@2.0.0-next.5:
resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==}
@@ -21590,7 +21809,6 @@ packages:
/safe-buffer@5.1.2:
resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==}
- dev: true
/safe-buffer@5.2.1:
resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
@@ -22700,7 +22918,6 @@ packages:
/supports-preserve-symlinks-flag@1.0.0:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
- dev: true
/surrealdb.js@0.11.0:
resolution: {integrity: sha512-x/Qd0UYyNilwY27JZlWgP8NsCdBzDtextRzP9oIm7xO27qsZvE5Rh4wnYN0xD68zgRAE4W8Jsufbm+hKbaGsTg==}
@@ -22843,7 +23060,7 @@ packages:
sorcery: 0.10.0
strip-indent: 3.0.0
svelte: 4.2.9
- typescript: 5.3.3
+ typescript: 5.4.5
dev: true
/svelte-preprocess@5.1.3(postcss@8.4.38)(svelte@4.2.9)(typescript@5.2.2):
@@ -22891,10 +23108,10 @@ packages:
sorcery: 0.11.0
strip-indent: 3.0.0
svelte: 4.2.9
- typescript: 5.2.2
+ typescript: 5.4.5
dev: true
- /svelte2tsx@0.7.0(svelte@4.2.9)(typescript@5.3.3):
+ /svelte2tsx@0.7.0(svelte@4.2.9)(typescript@5.4.5):
resolution: {integrity: sha512-qAelcydnmuiDvD1HsrWi23RWx24RZTKRv6n4JaGC/pkoJfbLkJPQT2wa1qN0ZyfKTNLSyoj2FW9z62l/AUzUNA==}
peerDependencies:
svelte: ^3.55 || ^4.0.0-next.0 || ^4.0 || ^5.0.0-next.0
@@ -22903,7 +23120,7 @@ packages:
dedent-js: 1.0.1
pascal-case: 3.1.2
svelte: 4.2.9
- typescript: 5.3.3
+ typescript: 5.4.5
dev: true
/svelte@4.2.9:
@@ -23215,6 +23432,10 @@ packages:
resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
engines: {node: '>=0.6'}
+ /token-stream@1.0.0:
+ resolution: {integrity: sha512-VSsyNPPW74RpHwR8Fc21uubwHY7wMDeJLys2IX5zJNih+OnAnaifKHo+1LHT7DAdloQ7apeaaWg8l7qnf/TnEg==}
+ dev: false
+
/toposort-class@1.0.1:
resolution: {integrity: sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg==}
dev: true
@@ -23289,7 +23510,7 @@ packages:
engines: {node: '>=6.10'}
dev: false
- /ts-evaluator@1.2.0(typescript@5.3.3):
+ /ts-evaluator@1.2.0(typescript@5.4.5):
resolution: {integrity: sha512-ncSGek1p92bj2ifB7s9UBgryHCkU9vwC5d+Lplt12gT9DH+e41X8dMoHRQjIMeAvyG7j9dEnuHmwgOtuRIQL+Q==}
engines: {node: '>=14.19.0'}
peerDependencies:
@@ -23302,7 +23523,7 @@ packages:
ansi-colors: 4.1.3
crosspath: 2.0.0
object-path: 0.11.8
- typescript: 5.3.3
+ typescript: 5.4.5
dev: false
/ts-interface-checker@0.1.13:
@@ -23327,7 +23548,7 @@ packages:
code-block-writer: 12.0.0
dev: false
- /ts-node@10.9.2(@types/node@20.12.7)(typescript@5.3.3):
+ /ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5):
resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==}
hasBin: true
peerDependencies:
@@ -23353,7 +23574,7 @@ packages:
create-require: 1.1.1
diff: 4.0.2
make-error: 1.3.6
- typescript: 5.3.3
+ typescript: 5.4.5
v8-compile-cache-lib: 3.0.1
yn: 3.1.1
dev: true
@@ -23362,7 +23583,7 @@ packages:
resolution: {integrity: sha512-tL0w8U/pgaacOmkb9fRlYzWEUDCfVjjv9dD4wHTgZ61MjhuMt46VNWTG747NqW6vRzoWIKABVhFSOJ82FvXrfA==}
dev: false
- /tsconfck@2.1.2(typescript@5.3.3):
+ /tsconfck@2.1.2(typescript@5.4.5):
resolution: {integrity: sha512-ghqN1b0puy3MhhviwO2kGF8SeMDNhEbnKxjK7h6+fvY9JAxqvXi8y5NAHSQv687OVboS2uZIByzGd45/YxrRHg==}
engines: {node: ^14.13.1 || ^16 || >=18}
hasBin: true
@@ -23372,7 +23593,7 @@ packages:
typescript:
optional: true
dependencies:
- typescript: 5.3.3
+ typescript: 5.4.5
dev: false
/tsconfig-paths@3.15.0:
@@ -23415,6 +23636,17 @@ packages:
fsevents: 2.3.3
dev: true
+ /tsx@4.7.3:
+ resolution: {integrity: sha512-+fQnMqIp/jxZEXLcj6WzYy9FhcS5/Dfk8y4AtzJ6ejKcKqmfTF8Gso/jtrzDggCF2zTU20gJa6n8XqPYwDAUYQ==}
+ engines: {node: '>=18.0.0'}
+ hasBin: true
+ dependencies:
+ esbuild: 0.19.12
+ get-tsconfig: 4.7.2
+ optionalDependencies:
+ fsevents: 2.3.3
+ dev: true
+
/tunnel-agent@0.6.0:
resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==}
dependencies:
@@ -23490,14 +23722,14 @@ packages:
resolution: {integrity: sha512-oUr5ZAn37CgNa6p1mrCuuR/pINffsnGCee2aS170Uj1IObxCjsHzu6sgdPUdxGLLn6++gd/qjNH1/iR6RrfLeg==}
dev: false
- /twoslash@0.2.5(typescript@5.3.3):
+ /twoslash@0.2.5(typescript@5.4.5):
resolution: {integrity: sha512-U8rqsfVh8jQMO1NJekUtglb52b7xD9+FrzeFrgzpHsRTKl8IQgqnZP6ld4PeKaHXhLfoZPuju9K50NXJ7wom8g==}
peerDependencies:
typescript: '*'
dependencies:
'@typescript/vfs': 1.5.0
twoslash-protocol: 0.2.5
- typescript: 5.3.3
+ typescript: 5.4.5
transitivePeerDependencies:
- supports-color
dev: false
@@ -23610,7 +23842,7 @@ packages:
peerDependencies:
typedoc: 0.25.x
dependencies:
- typedoc: 0.25.12(typescript@5.3.3)
+ typedoc: 0.25.12(typescript@5.4.5)
dev: true
/typedoc-plugin-markdown@4.0.0-next.54(typedoc@0.25.13):
@@ -23618,10 +23850,10 @@ packages:
peerDependencies:
typedoc: 0.25.x
dependencies:
- typedoc: 0.25.13(typescript@5.3.3)
+ typedoc: 0.25.13(typescript@5.4.5)
dev: true
- /typedoc@0.25.12(typescript@5.3.3):
+ /typedoc@0.25.12(typescript@5.4.5):
resolution: {integrity: sha512-F+qhkK2VoTweDXd1c42GS/By2DvI2uDF4/EpG424dTexSHdtCH52C6IcAvMA6jR3DzAWZjHpUOW+E02kyPNUNw==}
engines: {node: '>= 16'}
hasBin: true
@@ -23632,10 +23864,10 @@ packages:
marked: 4.3.0
minimatch: 9.0.3
shiki: 0.14.7
- typescript: 5.3.3
+ typescript: 5.4.5
dev: true
- /typedoc@0.25.13(typescript@5.3.3):
+ /typedoc@0.25.13(typescript@5.4.5):
resolution: {integrity: sha512-pQqiwiJ+Z4pigfOnnysObszLiU3mVLWAExSPf+Mu06G/qsc3wzbuM56SZQvONhHLncLUhYzOVkjFFpFfL5AzhQ==}
engines: {node: '>= 16'}
hasBin: true
@@ -23646,7 +23878,7 @@ packages:
marked: 4.3.0
minimatch: 9.0.3
shiki: 0.14.7
- typescript: 5.3.3
+ typescript: 5.4.5
dev: true
/typeorm-naming-strategies@4.1.0(typeorm@0.3.17):
@@ -23747,6 +23979,12 @@ packages:
resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==}
engines: {node: '>=14.17'}
hasBin: true
+ dev: true
+
+ /typescript@5.4.5:
+ resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==}
+ engines: {node: '>=14.17'}
+ hasBin: true
/ua-parser-js@1.0.37:
resolution: {integrity: sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ==}
@@ -24635,6 +24873,11 @@ packages:
- terser
dev: true
+ /void-elements@3.1.0:
+ resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==}
+ engines: {node: '>=0.10.0'}
+ dev: false
+
/vscode-oniguruma@1.7.0:
resolution: {integrity: sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==}
dev: true
@@ -24855,6 +25098,16 @@ packages:
string-width: 4.2.3
dev: true
+ /with@7.0.2:
+ resolution: {integrity: sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w==}
+ engines: {node: '>= 10.0.0'}
+ dependencies:
+ '@babel/parser': 7.23.9
+ '@babel/types': 7.23.9
+ assert-never: 1.2.1
+ babel-walk: 3.0.0-canary-5
+ dev: false
+
/wkx@0.5.0:
resolution: {integrity: sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==}
dependencies:
From 8751fa4541d6a1246f6d7a6e545998e7a34f86bd Mon Sep 17 00:00:00 2001
From: Nico Domino
Date: Thu, 9 May 2024 11:58:02 +0200
Subject: [PATCH 07/44] chore(adapters): cleanup extraneous documentation in
adapter and fix testing and release GHA (#10854)
---
.github/workflows/release.yml | 28 +-
apps/dev/express/src/app.ts | 2 +-
apps/examples/nextjs/Dockerfile | 6 +-
apps/examples/nextjs/app/[...proxy]/route.tsx | 2 +-
apps/examples/nextjs/docker-compose.yml | 17 +
apps/examples/nextjs/test-docker.sh | 30 ++
packages/adapter-azure-tables/src/index.ts | 43 +--
packages/adapter-d1/src/index.ts | 2 +-
packages/adapter-drizzle/src/index.ts | 245 +--------------
packages/adapter-drizzle/test/mysql/schema.ts | 2 +-
packages/adapter-drizzle/test/mysql/test.sh | 11 +-
packages/adapter-drizzle/test/pg/schema.ts | 2 +-
packages/adapter-dynamodb/src/index.ts | 178 +----------
packages/adapter-edgedb/src/index.ts | 218 +------------
packages/adapter-fauna/src/index.ts | 177 +----------
packages/adapter-firebase/src/index.ts | 71 -----
packages/adapter-hasura/src/index.ts | 97 +-----
packages/adapter-kysely/src/index.ts | 183 +----------
packages/adapter-mikro-orm/src/index.ts | 109 +------
packages/adapter-mongodb/src/index.ts | 56 +---
packages/adapter-neo4j/src/index.ts | 111 +------
packages/adapter-pg/src/index.ts | 81 +----
packages/adapter-pouchdb/src/index.ts | 55 +---
packages/adapter-sequelize/src/index.ts | 79 +----
packages/adapter-supabase/src/index.ts | 290 +-----------------
packages/adapter-surrealdb/src/index.ts | 87 +-----
packages/adapter-typeorm/src/index.ts | 214 +------------
packages/adapter-unstorage/src/index.ts | 76 +----
packages/adapter-upstash-redis/src/index.ts | 60 +---
packages/adapter-xata/src/index.ts | 216 +------------
packages/core/test/e2e/basic-auth.spec.ts | 10 +-
31 files changed, 102 insertions(+), 2656 deletions(-)
create mode 100644 apps/examples/nextjs/docker-compose.yml
create mode 100755 apps/examples/nextjs/test-docker.sh
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 37c43671ca..127d2241ca 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -74,7 +74,7 @@ env:
jobs:
test:
- name: Run release
+ name: Test
runs-on: ubuntu-latest
steps:
- name: Init
@@ -82,7 +82,7 @@ jobs:
with:
fetch-depth: 0
- name: Install pnpm
- uses: pnpm/action-setup@v2.2.4
+ uses: pnpm/action-setup@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
@@ -114,7 +114,7 @@ jobs:
if: steps.playwright-cache.outputs.cache-hit != 'true' && github.repository == 'nextauthjs/next-auth'
run: |
pnpm exec playwright install --with-deps chromium
- - name: Run Docker E2E
+ - name: Run E2E tests (Nextjs-Docker)
continue-on-error: true
if: false
timeout-minutes: 15
@@ -148,7 +148,7 @@ jobs:
name: playwright-traces
path: "**/packages/utils/test-results/*/trace.zip"
retention-days: 7
- - uses: codecov/codecov-action@v3
+ - uses: codecov/codecov-action@v4
if: always()
name: Coverage
with:
@@ -156,21 +156,22 @@ jobs:
release-branch:
name: Publish branch
+ timeout-minutes: 120
runs-on: ubuntu-latest
needs: test
if: ${{ github.event_name == 'push' }}
environment: Production
steps:
- name: Init
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
with:
fetch-depth: 0
# Please upvote https://github.com/orgs/community/discussions/13836
token: ${{ secrets.GH_PAT }}
- name: Install pnpm
- uses: pnpm/action-setup@v2.2.4
+ uses: pnpm/action-setup@v4
- name: Setup Node
- uses: actions/setup-node@v3
+ uses: actions/setup-node@v4
with:
cache: "pnpm"
- name: Install dependencies
@@ -183,17 +184,18 @@ jobs:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
release-pr:
name: Publish PR
+ timeout-minutes: 120
runs-on: ubuntu-latest
needs: test
if: ${{ github.event_name == 'pull_request' }}
environment: Preview
steps:
- name: Init
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Install pnpm
- uses: pnpm/action-setup@v2.2.4
+ uses: pnpm/action-setup@v4
- name: Setup Node
- uses: actions/setup-node@v3
+ uses: actions/setup-node@v4
with:
node-version: 18
cache: "pnpm"
@@ -228,11 +230,11 @@ jobs:
if: ${{ github.event_name == 'workflow_dispatch' }}
steps:
- name: Init
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Install pnpm
- uses: pnpm/action-setup@v2.2.4
+ uses: pnpm/action-setup@v4
- name: Setup Node
- uses: actions/setup-node@v3
+ uses: actions/setup-node@v4
with:
node-version: 18
cache: "pnpm"
diff --git a/apps/dev/express/src/app.ts b/apps/dev/express/src/app.ts
index 27cc8db60c..6157373064 100644
--- a/apps/dev/express/src/app.ts
+++ b/apps/dev/express/src/app.ts
@@ -56,7 +56,7 @@ app.get(
authenticatedUser,
async (_req: Request, res: Response) => {
res.json(res.locals.session)
- },
+ }
)
app.get("/", async (_req: Request, res: Response) => {
diff --git a/apps/examples/nextjs/Dockerfile b/apps/examples/nextjs/Dockerfile
index 525aaea3e4..2c27bcee0a 100644
--- a/apps/examples/nextjs/Dockerfile
+++ b/apps/examples/nextjs/Dockerfile
@@ -7,8 +7,8 @@ RUN apk add --no-cache libc6-compat
WORKDIR /app
# Install dependencies
-COPY package.json ./
-RUN npm i
+COPY package.json pnpm-lock.yaml ./
+RUN corepack enable && pnpm install
# Rebuild the source code only when needed
@@ -54,4 +54,4 @@ ENV PORT 3000
# server.js is created by next build from the standalone output
# https://nextjs.org/docs/pages/api-reference/next-config-js/output
-CMD HOSTNAME="0.0.0.0" node server.js
\ No newline at end of file
+CMD HOSTNAME="0.0.0.0" node server.js
diff --git a/apps/examples/nextjs/app/[...proxy]/route.tsx b/apps/examples/nextjs/app/[...proxy]/route.tsx
index 6e28669335..26f1449ae0 100644
--- a/apps/examples/nextjs/app/[...proxy]/route.tsx
+++ b/apps/examples/nextjs/app/[...proxy]/route.tsx
@@ -13,7 +13,7 @@ function stripContentEncoding(result: Response) {
})
}
-export async function handler(request: NextRequest) {
+async function handler(request: NextRequest) {
const session = await auth()
const headers = new Headers(request.headers)
diff --git a/apps/examples/nextjs/docker-compose.yml b/apps/examples/nextjs/docker-compose.yml
new file mode 100644
index 0000000000..e5408dd83f
--- /dev/null
+++ b/apps/examples/nextjs/docker-compose.yml
@@ -0,0 +1,17 @@
+version: "3"
+
+services:
+ authjs-docker-test:
+ environment:
+ - TEST_KEYCLOAK_USERNAME
+ - TEST_KEYCLOAK_PASSWORD
+ - AUTH_KEYCLOAK_ID
+ - AUTH_KEYCLOAK_SECRET
+ - AUTH_KEYCLOAK_ISSUER
+ - AUTH_SECRET="MohY0/2zSQw/psWEnejC2ka3Al0oifvY4YjOkUaFfnI="
+ - AUTH_URL=http://localhost:3000/auth
+ build:
+ context: .
+ dockerfile: Dockerfile
+ ports:
+ - "3000:3000"
diff --git a/apps/examples/nextjs/test-docker.sh b/apps/examples/nextjs/test-docker.sh
new file mode 100755
index 0000000000..824fdb3e9f
--- /dev/null
+++ b/apps/examples/nextjs/test-docker.sh
@@ -0,0 +1,30 @@
+#!/usr/bin/env bash
+
+# Easier to read `docker-compose up` output
+# export BUILDKIT_PROGRESS=plain
+
+args=("-f" "docker-compose.yml")
+if [[ -z "${CI}" ]]; then
+ args+=("--env-file" ".env")
+fi
+args+=("up" "--detach" "--build")
+
+echo "Running: docker-compose ${args[*]}"
+
+if ! docker-compose "${args[@]}"; then
+ echo "Failed to start container"
+ exit 1
+fi
+
+echo "waiting 10 seconds for container to start..."
+sleep 10
+
+# Used to control which env vars to load in the playwright process
+export TEST_DOCKER=1
+
+# Always stop container, but exit with 1 when tests are failing
+if playwright test -c ../../../packages/utils/playwright.config.ts; then
+ docker-compose down
+else
+ docker-compose down && exit 1
+fi
diff --git a/packages/adapter-azure-tables/src/index.ts b/packages/adapter-azure-tables/src/index.ts
index 232beef223..d96c6a5769 100644
--- a/packages/adapter-azure-tables/src/index.ts
+++ b/packages/adapter-azure-tables/src/index.ts
@@ -1,6 +1,6 @@
/**
*
- *
An official Azure Table Storage adapter for Auth.js / NextAuth.js.
+ *
An official Azure Table Storage adapter for Auth.js / NextAuth.js.
*
*
*
@@ -51,46 +51,7 @@ export function withoutKeys
(
return entity
}
-/**
- *
- * 1. Create a table for authentication data, `auth` in the example below.
- *
- * ```js title="auth.ts"
- * import type { AuthConfig } from "next-auth"
- * import { TableStorageAdapter } from "@next-auth/azure-tables-adapter"
- * import { AzureNamedKeyCredential, TableClient } from "@azure/data-tables"
- *
- * const credential = new AzureNamedKeyCredential(
- * process.env.AZURE_ACCOUNT,
- * process.env.AZURE_ACCESS_KEY
- * )
- * const authClient = new TableClient(
- * process.env.AZURE_TABLES_ENDPOINT,
- * "auth",
- * credential
- * )
- *
- * // For more information on each option (and a full list of options) go to
- * // https://authjs.dev/reference/core/types#authconfig
- * export default const authConfig = {
- * // https://authjs.dev/getting-started/authentication/oauth
- * providers: [
- * // ...
- * ],
- * adapter: TableStorageAdapter(authClient),
- * // ...
- * } satisfies AuthConfig
- * ```
- *
- * Environment variable are as follows:
- *
- * ```
- * AZURE_ACCOUNT=storageaccountname
- * AZURE_ACCESS_KEY=longRandomKey
- * AZURE_TABLES_ENDPOINT=https://$AZURE_ACCOUNT.table.core.windows.net
- * ```
- *
- */
+
export const TableStorageAdapter = (client: TableClient): Adapter => {
return {
async createUser(user) {
diff --git a/packages/adapter-d1/src/index.ts b/packages/adapter-d1/src/index.ts
index 8b75db41f9..cfa496ddf3 100644
--- a/packages/adapter-d1/src/index.ts
+++ b/packages/adapter-d1/src/index.ts
@@ -1,6 +1,6 @@
/**
*
- *
An official Cloudflare D1 adapter for Auth.js / NextAuth.js.
+ *
An official Cloudflare D1 adapter for Auth.js / NextAuth.js.
*
*
*
diff --git a/packages/adapter-drizzle/src/index.ts b/packages/adapter-drizzle/src/index.ts
index 024a72228a..6fa34f49bc 100644
--- a/packages/adapter-drizzle/src/index.ts
+++ b/packages/adapter-drizzle/src/index.ts
@@ -1,6 +1,6 @@
/**
*
- *
Official Drizzle ORM adapter for Auth.js / NextAuth.js.
+ *
Official Drizzle ORM adapter for Auth.js / NextAuth.js.
*
*
*
@@ -26,250 +26,7 @@ import { DefaultSQLiteSchema, SQLiteDrizzleAdapter } from "./lib/sqlite.js"
import { DefaultSchema, SqlFlavorOptions } from "./lib/utils.js"
import type { Adapter } from "@auth/core/adapters"
-/**
- * Create db instance and pass it to adapter. Add this adapter to your `auth.ts` Auth.js configuration object:
- *
- * ```ts title="auth.ts"
- * import NextAuth from "next-auth"
- * import Google from "next-auth/providers/google"
- * import { DrizzleAdapter } from "@auth/drizzle-adapter"
- * import { db } from "./db.ts"
- *
- * export const { handlers, auth } = NextAuth({
- * adapter: DrizzleAdapter(db),
- * providers: [
- * Google,
- * ],
- * })
- * ```
- *
- * Follow the Drizzle documentation for [PostgreSQL setup](https://orm.drizzle.team/docs/get-started-postgresql), [MySQL setup](https://orm.drizzle.team/docs/get-started-mysql) and [SQLite setup](https://orm.drizzle.team/docs/get-started-sqlite).
- *
- * :::info
- * If you want to use your own tables, you can pass them as a second argument. If you add non-nullable columns, make sure to provide a default value or rewrite functions to handle the missing values.
- * :::
- *
- * ```ts title="auth.ts"
- * import NextAuth from "next-auth"
- * import Google from "next-auth/providers/google"
- * import { DrizzleAdapter } from "@auth/drizzle-adapter"
- * import { accounts, sessions, users, verificationTokens } from "./schema"
- * import { db } from "./db.ts"
- *
- * export const { handlers, auth } = NextAuth({
- * adapter: DrizzleAdapter(db, { usersTable: users, accountsTable: accounts, sessionsTable: sessions, verificationTokensTable: verificationTokens }),
- * providers: [
- * Google,
- * ],
- * })
- * ```
- *
- * ## Setup
- *
- * First, create a schema that includes [the minimum requirements for a `next-auth` adapter](/reference/core/adapters#models). You can select your favorite SQL flavor below and copy it.
- * Additionally, you may extend the schema from the minimum requirements to suit your needs.
- *
- * - [Postgres](#postgres)
- * - [MySQL](#mysql)
- * - [SQLite](#sqlite)
- *
- * ### Postgres
- * ```ts title="schema.ts"
- * import {
- * timestamp,
- * pgTable,
- * text,
- * primaryKey,
- * integer
- * } from "drizzle-orm/pg-core"
- * import type { AdapterAccountType } from '@auth/core/adapters'
- *
- * export const users = pgTable("user", {
- * id: text("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
- * name: text("name"),
- * email: text("email").notNull(),
- * emailVerified: timestamp("emailVerified", { mode: "date" }),
- * image: text("image"),
- * })
- *
- * export const accounts = pgTable(
- * "account",
- * {
- * userId: text("userId")
- * .notNull()
- * .references(() => users.id, { onDelete: "cascade" }),
- * type: text("type").$type
().notNull(),
- * provider: text("provider").notNull(),
- * providerAccountId: text("providerAccountId").notNull(),
- * refresh_token: text("refresh_token"),
- * access_token: text("access_token"),
- * expires_at: integer("expires_at"),
- * token_type: text("token_type"),
- * scope: text("scope"),
- * id_token: text("id_token"),
- * session_state: text("session_state"),
- * },
- * (account) => ({
- * compoundKey: primaryKey({ columns: [account.provider, account.providerAccountId] }),
- * })
- * )
- *
- * export const sessions = pgTable("session", {
- * sessionToken: text("sessionToken").primaryKey(),
- * userId: text("userId")
- * .notNull()
- * .references(() => users.id, { onDelete: "cascade" }),
- * expires: timestamp("expires", { mode: "date" }).notNull(),
- * })
- *
- * export const verificationTokens = pgTable(
- * "verificationToken",
- * {
- * identifier: text("identifier").notNull(),
- * token: text("token").notNull(),
- * expires: timestamp("expires", { mode: "date" }).notNull(),
- * },
- * (vt) => ({
- * compoundKey: primaryKey({ columns: [vt.identifier, vt.token] }),
- * })
- * )
- * ```
- *
- * ### MySQL
- *
- * In MySQL, there's no `returning` clause, so in the `createUser` function, we first insert a new user and then search by `email` to get the user's data. To make the search faster, we suggest adding an index to the `email` column.
- *
- * ```ts title="schema.ts"
- * import {
- * int,
- * timestamp,
- * mysqlTable,
- * primaryKey,
- * varchar,
- * } from "drizzle-orm/mysql-core"
- * import type { AdapterAccountType } from "@auth/core/adapters"
- *
- * export const users = mysqlTable("user", {
- * id: varchar("id", { length: 255 }).primaryKey().$defaultFn(() => crypto.randomUUID()),
- * name: varchar("name", { length: 255 }),
- * email: varchar("email", { length: 255 }).notNull(),
- * emailVerified: timestamp("emailVerified", { mode: "date", fsp: 3 }),
- * image: varchar("image", { length: 255 }),
- * })
- *
- * export const accounts = mysqlTable(
- * "account",
- * {
- * userId: varchar("userId", { length: 255 })
- * .notNull()
- * .references(() => users.id, { onDelete: "cascade" }),
- * type: varchar("type", { length: 255 }).$type().notNull(),
- * provider: varchar("provider", { length: 255 }).notNull(),
- * providerAccountId: varchar("providerAccountId", { length: 255 }).notNull(),
- * refresh_token: varchar("refresh_token", { length: 255 }),
- * access_token: varchar("access_token", { length: 255 }),
- * expires_at: int("expires_at"),
- * token_type: varchar("token_type", { length: 255 }),
- * scope: varchar("scope", { length: 255 }),
- * id_token: varchar("id_token", { length: 2048 }),
- * session_state: varchar("session_state", { length: 255 }),
- * },
- * (account) => ({
- * compoundKey: primaryKey({
- columns: [account.provider, account.providerAccountId],
- })
- * })
- * )
- *
- * export const sessions = mysqlTable("session", {
- * sessionToken: varchar("sessionToken", { length: 255 }).primaryKey(),
- * userId: varchar("userId", { length: 255 })
- * .notNull()
- * .references(() => users.id, { onDelete: "cascade" }),
- * expires: timestamp("expires", { mode: "date" }).notNull(),
- * })
- *
- * export const verificationTokens = mysqlTable(
- * "verificationToken",
- * {
- * identifier: varchar("identifier", { length: 255 }).notNull(),
- * token: varchar("token", { length: 255 }).notNull(),
- * expires: timestamp("expires", { mode: "date" }).notNull(),
- * },
- * (vt) => ({
- * compoundKey: primaryKey({ columns: [vt.identifier, vt.token] }),
- * })
- * )
- * ```
- *
- * ### SQLite
- *
- * ```ts title="schema.ts"
- * import { integer, sqliteTable, text, primaryKey } from "drizzle-orm/sqlite-core"
- * import type { AdapterAccountType } from "@auth/core/adapters"
- *
- * export const users = sqliteTable("user", {
- * id: text("id").primaryKey().$defaultFn(() => crypto.randomUUID()),
- * name: text("name"),
- * email: text("email").notNull(),
- * emailVerified: integer("emailVerified", { mode: "timestamp_ms" }),
- * image: text("image"),
- * })
- *
- * export const accounts = sqliteTable(
- * "account",
- * {
- * userId: text("userId")
- * .notNull()
- * .references(() => users.id, { onDelete: "cascade" }),
- * type: text("type").$type().notNull(),
- * provider: text("provider").notNull(),
- * providerAccountId: text("providerAccountId").notNull(),
- * refresh_token: text("refresh_token"),
- * access_token: text("access_token"),
- * expires_at: integer("expires_at"),
- * token_type: text("token_type"),
- * scope: text("scope"),
- * id_token: text("id_token"),
- * session_state: text("session_state"),
- * },
- * (account) => ({
- * compoundKey: primaryKey({
- columns: [account.provider, account.providerAccountId],
- })
- * })
- * )
- *
- * export const sessions = sqliteTable("session", {
- * sessionToken: text("sessionToken").primaryKey(),
- * userId: text("userId")
- * .notNull()
- * .references(() => users.id, { onDelete: "cascade" }),
- * expires: integer("expires", { mode: "timestamp_ms" }).notNull(),
- * })
- *
- * export const verificationTokens = sqliteTable(
- * "verificationToken",
- * {
- * identifier: text("identifier").notNull(),
- * token: text("token").notNull(),
- * expires: integer("expires", { mode: "timestamp_ms" }).notNull(),
- * },
- * (vt) => ({
- * compoundKey: primaryKey({ columns: [vt.identifier, vt.token] }),
- * })
- * )
- * ```
- *
- * ## Migrating your database
- * With your schema now described in your code, you'll need to migrate your database to your schema.
- *
- * For full documentation on how to run migrations with Drizzle, [visit the Drizzle documentation](https://orm.drizzle.team/kit-docs/overview#running-migrations) or check how to apply changes directly to the database with [push command](https://orm.drizzle.team/kit-docs/overview#prototyping-with-db-push).
- *
- * ---
- *
- **/
export function DrizzleAdapter(
db: SqlFlavor,
schema?: DefaultSchema
diff --git a/packages/adapter-drizzle/test/mysql/schema.ts b/packages/adapter-drizzle/test/mysql/schema.ts
index 70b07a4d1f..6cd768417d 100644
--- a/packages/adapter-drizzle/test/mysql/schema.ts
+++ b/packages/adapter-drizzle/test/mysql/schema.ts
@@ -10,7 +10,7 @@ export const {
} = defineTables({})
const poolConnection = createPool({
- host: "localhost",
+ host: "127.0.0.1",
user: "root",
password: "password",
database: "next-auth",
diff --git a/packages/adapter-drizzle/test/mysql/test.sh b/packages/adapter-drizzle/test/mysql/test.sh
index b2ea3b3628..c59896e813 100755
--- a/packages/adapter-drizzle/test/mysql/test.sh
+++ b/packages/adapter-drizzle/test/mysql/test.sh
@@ -11,16 +11,17 @@ docker run -d --rm \
-e MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} \
--name "${MYSQL_CONTAINER_NAME}" \
-p 3306:3306 \
- mysql:8 \
- --default-authentication-plugin=mysql_native_password
+ mysql:8
-echo "Waiting 10s for db to start..." && sleep 10
+echo "Waiting 15s for db to start..." && sleep 15
-# Push schema and seed
+# Generate Migration from Schema
drizzle-kit generate:mysql --config=./test/mysql/drizzle.config.ts
-NODE_OPTIONS='--import tsx'
+
+# Push Schema to DB
tsx ./test/mysql/migrator.ts
+# Run Tests
if vitest run -c ../utils/vitest.config.ts ./test/mysql/index.test.ts; then
docker stop ${MYSQL_CONTAINER_NAME}
else
diff --git a/packages/adapter-drizzle/test/pg/schema.ts b/packages/adapter-drizzle/test/pg/schema.ts
index a24fe43a35..e69ec01af2 100644
--- a/packages/adapter-drizzle/test/pg/schema.ts
+++ b/packages/adapter-drizzle/test/pg/schema.ts
@@ -9,7 +9,7 @@ export const {
verificationTokensTable,
} = defineTables({})
-const connectionString = "postgres://nextauth:nextauth@localhost:5432/nextauth"
+const connectionString = "postgres://nextauth:nextauth@127.0.0.1:5432/nextauth"
const sql = postgres(connectionString)
export const db = drizzle(sql)
diff --git a/packages/adapter-dynamodb/src/index.ts b/packages/adapter-dynamodb/src/index.ts
index 2db86bc553..53d3de3127 100644
--- a/packages/adapter-dynamodb/src/index.ts
+++ b/packages/adapter-dynamodb/src/index.ts
@@ -1,6 +1,6 @@
/**
*
- *
Official DynamoDB adapter for Auth.js / NextAuth.js.
+ *
Official DynamoDB adapter for Auth.js / NextAuth.js.
*
*
*
@@ -36,182 +36,6 @@ export interface DynamoDBAdapterOptions {
indexSortKey?: string
}
-/**
- * ## Setup
- *
- * By default, the adapter expects a table with a partition key `pk` and a sort key `sk`, as well as a global secondary index named `GSI1` with `GSI1PK` as partition key and `GSI1SK` as sorting key. To automatically delete sessions and verification requests after they expire using [dynamodb TTL](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/TTL.html) you should [enable the TTL](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/time-to-live-ttl-how-to.html) with attribute name 'expires'. You can set whatever you want as the table name and the billing method.
- * You can find the full schema in the table structure section below.
- *
- * ### Configuring Auth.js
- *
- * You need to pass `DynamoDBDocument` client from the modular [`aws-sdk`](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/dynamodb-example-dynamodb-utilities.html) v3 to the adapter.
- * The default table name is `next-auth`, but you can customise that by passing `{ tableName: 'your-table-name' }` as the second parameter in the adapter.
- *
- * ```js title="pages/api/auth/[...nextauth].js"
- * import { DynamoDB, DynamoDBClientConfig } from "@aws-sdk/client-dynamodb"
- * import { DynamoDBDocument } from "@aws-sdk/lib-dynamodb"
- * import NextAuth from "next-auth";
- * import Providers from "next-auth/providers";
- * import { DynamoDBAdapter } from "@auth/dynamodb-adapter"
- *
- * const config: DynamoDBClientConfig = {
- * credentials: {
- * accessKeyId: process.env.NEXT_AUTH_AWS_ACCESS_KEY,
- * secretAccessKey: process.env.NEXT_AUTH_AWS_SECRET_KEY,
- * },
- * region: process.env.NEXT_AUTH_AWS_REGION,
- * };
- *
- * const client = DynamoDBDocument.from(new DynamoDB(config), {
- * marshallOptions: {
- * convertEmptyValues: true,
- * removeUndefinedValues: true,
- * convertClassInstanceToMap: true,
- * },
- * })
- *
- * export default NextAuth({
- * // Configure one or more authentication providers
- * providers: [
- * Providers.GitHub({
- * clientId: process.env.GITHUB_ID,
- * clientSecret: process.env.GITHUB_SECRET,
- * }),
- * Providers.Email({
- * server: process.env.EMAIL_SERVER,
- * from: process.env.EMAIL_FROM,
- * }),
- * // ...add more providers here
- * ],
- * adapter: DynamoDBAdapter(
- * client
- * ),
- * });
- * ```
- *
- * (AWS secrets start with `NEXT_AUTH_` in order to not conflict with [Vercel's reserved environment variables](https://vercel.com/docs/environment-variables#reserved-environment-variables).)
- *
- * ## AWS Credentials
- *
- * :::note
- * Always follow the **principle of least privilege** when giving access to AWS
- * services/resources -> identities should only be permitted to perform the
- * smallest set of actions necessary to fulfill a specific task.
- * :::
- *
- * 1. Open the [AWS console](https://console.aws.amazon.com/) and go to "IAM", then "Users".
- * 2. Create a new user. The purpose of this user is to give programmatic access to DynamoDB.
- * 3. Create an Access Key and then copy Key ID and Secret to your `.env`/`.env.local` file.
- * 4. Select "Add Permission" and "Create Inline Policy".
- * 5. Copy the JSON below into the JSON input and replace `region`, `account_id` and `table_name` with your values.
- *
- * ```json
- * {
- * "Version": "2012-10-17",
- * "Statement": [
- * {
- * "Sid": "DynamoDBAccess",
- * "Effect": "Allow",
- * "Action": [
- * "dynamodb:BatchGetItem",
- * "dynamodb:BatchWriteItem",
- * "dynamodb:Describe*",
- * "dynamodb:List*",
- * "dynamodb:PutItem",
- * "dynamodb:DeleteItem",
- * "dynamodb:GetItem",
- * "dynamodb:Scan",
- * "dynamodb:Query",
- * "dynamodb:UpdateItem"
- * ],
- * "Resource": [
- * "arn:aws:dynamodb:{region}:{account_id}:table/{table_name}",
- * "arn:aws:dynamodb:{region}:{account_id}:table/{table_name}/index/GSI1"
- * ]
- * }
- * ]
- * }
- * ```
- *
- * ## Advanced usage
- *
- * ### Default schema
- *
- * The table respects the single table design pattern. This has many advantages:
- *
- * - Only one table to manage, monitor and provision.
- * - Querying relations is faster than with multi-table schemas (for eg. retrieving all sessions for a user).
- * - Only one table needs to be replicated if you want to go multi-region.
- *
- * > This schema is adapted for use in DynamoDB and based upon our main [schema](https://authjs.dev/reference/core/adapters#models)
- *
- * ![DynamoDB Table](https://i.imgur.com/hGZtWDq.png)
- *
- * You can create this table with infrastructure as code using [`aws-cdk`](https://github.com/aws/aws-cdk) with the following table definition:
- *
- * ```js title="stack.ts"
- * new dynamodb.Table(this, `NextAuthTable`, {
- * tableName: "next-auth",
- * partitionKey: { name: "pk", type: dynamodb.AttributeType.STRING },
- * sortKey: { name: "sk", type: dynamodb.AttributeType.STRING },
- * timeToLiveAttribute: "expires",
- * }).addGlobalSecondaryIndex({
- * indexName: "GSI1",
- * partitionKey: { name: "GSI1PK", type: dynamodb.AttributeType.STRING },
- * sortKey: { name: "GSI1SK", type: dynamodb.AttributeType.STRING },
- * })
- * ```
- *
- * Alternatively, you can use this cloudformation template:
- *
- * ```yaml title=cloudformation.yaml
- * NextAuthTable:
- * Type: "AWS::DynamoDB::Table"
- * Properties:
- * TableName: next-auth
- * AttributeDefinitions:
- * - AttributeName: pk
- * AttributeType: S
- * - AttributeName: sk
- * AttributeType: S
- * - AttributeName: GSI1PK
- * AttributeType: S
- * - AttributeName: GSI1SK
- * AttributeType: S
- * KeySchema:
- * - AttributeName: pk
- * KeyType: HASH
- * - AttributeName: sk
- * KeyType: RANGE
- * GlobalSecondaryIndexes:
- * - IndexName: GSI1
- * Projection:
- * ProjectionType: ALL
- * KeySchema:
- * - AttributeName: GSI1PK
- * KeyType: HASH
- * - AttributeName: GSI1SK
- * KeyType: RANGE
- * TimeToLiveSpecification:
- * AttributeName: expires
- * Enabled: true
- * ```
- *
- * ### Using a custom schema
- *
- * You can configure your custom table schema by passing the `options` key to the adapter constructor:
- *
- * ```js
- * const adapter = DynamoDBAdapter(client, {
- * tableName: "custom-table-name",
- * partitionKey: "custom-pk",
- * sortKey: "custom-sk",
- * indexName: "custom-index-name",
- * indexPartitionKey: "custom-index-pk",
- * indexSortKey: "custom-index-sk",
- * })
- * ```
- **/
export function DynamoDBAdapter(
client: DynamoDBDocument,
options?: DynamoDBAdapterOptions
diff --git a/packages/adapter-edgedb/src/index.ts b/packages/adapter-edgedb/src/index.ts
index 7f61593499..4e13a41f56 100644
--- a/packages/adapter-edgedb/src/index.ts
+++ b/packages/adapter-edgedb/src/index.ts
@@ -1,6 +1,6 @@
/**
*
- *
Official Edge DB adapter for Auth.js / NextAuth.js.
+ *
Official Edge DB adapter for Auth.js / NextAuth.js.
*
*
*
@@ -24,222 +24,6 @@ import type {
} from "@auth/core/adapters"
import type { Client } from "edgedb"
-/**
- *
- * To use this Adapter, you need to install `edgedb`, `@edgedb/generate`, and the separate `@auth/edgedb-adapter` package:
- *
- * ```bash npm2yarn
- * npm install edgedb @auth/edgedb-adapter
- * npm install @edgedb/generate --save-dev
- * ```
- *
- * ## Installation
- *
- * First, ensure you have the EdgeDB CLI installed.
- *
- * Follow the instructions below, or read the [EdgeDB quickstart](https://www.edgedb.com/docs/intro/quickstart) to install the EdgeDB CLI and initialize a project
- *
- * ### Linux or macOS
- *
- * ```bash
- * curl --proto '=https' --tlsv1.2 -sSf https://sh.edgedb.com | sh
- * ```
- *
- * ### Windows
- *
- * ```powershell
- * iwr https://ps1.edgedb.com -useb | iex
- * ```
- *
- * Check that the CLI is available with the `edgedb --version` command. If you get a `Command not found` error, you may need to open a new terminal window before the `edgedb` command is available.
- *
- * Once the CLI is installed, initialize a project from the application’s root directory. You’ll be presented with a series of prompts.
- *
- * ```bash
- * edgedb project init
- * ```
- *
- * This process will spin up an EdgeDB instance and [“link”](https://www.edgedb.com/docs/cli/edgedb_instance/edgedb_instance_link#edgedb-instance-link) it with your current directory. As long as you’re inside that directory, CLI commands and client libraries will be able to connect to the linked instance automatically, without additional configuration.
- *
- * ## Setup
- *
- * ### NextAuth.js configuration
- *
- * Configure your NextAuth.js to use the EdgeDB Adapter:
- *
- * ```js title="pages/api/auth/[...nextauth].js"
- * import NextAuth from "next-auth"
- * import GoogleProvider from "next-auth/providers/google"
- * import { EdgeDBAdapter } from "@auth/edgedb-adapter"
- * import { createClient } from "edgedb"
- *
- * const client = createClient()
- *
- * export default NextAuth({
- * adapter: EdgeDBAdapter(client),
- * providers: [
- * GoogleProvider({
- * clientId: process.env.GOOGLE_CLIENT_ID,
- * clientSecret: process.env.GOOGLE_CLIENT_SECRET,
- * }),
- * ],
- * })
- * ```
- *
- * ### Create the EdgeDB schema
- *
- * Replace the contents of the auto-generated file in `dbschema/default.esdl` with the following:
- *
- * > This schema is adapted for use in EdgeDB and based upon our main [schema](https://authjs.dev/getting-started/adapters#models)
- *
- * ```json title="default.esdl"
- * module default {
- * type User {
- * property name -> str;
- * required property email -> str {
- * constraint exclusive;
- * };
- * property emailVerified -> datetime;
- * property image -> str;
- * multi link accounts := .
datetime {
- * default := datetime_current();
- * };
- * }
- *
- * type Account {
- * required property userId := .user.id;
- * required property type -> str;
- * required property provider -> str;
- * required property providerAccountId -> str {
- * constraint exclusive;
- * };
- * property refresh_token -> str;
- * property access_token -> str;
- * property expires_at -> int64;
- * property token_type -> str;
- * property scope -> str;
- * property id_token -> str;
- * property session_state -> str;
- * required link user -> User {
- * on target delete delete source;
- * };
- * property createdAt -> datetime {
- * default := datetime_current();
- * };
- * constraint exclusive on ((.provider, .providerAccountId));
- * }
- *
- * type Session {
- * required property sessionToken -> str {
- * constraint exclusive;
- * };
- * required property userId := .user.id;
- * required property expires -> datetime;
- * required link user -> User {
- * on target delete delete source;
- * };
- * property createdAt -> datetime {
- * default := datetime_current();
- * };
- * }
- *
- * type VerificationToken {
- * required property identifier -> str;
- * required property token -> str {
- * constraint exclusive;
- * };
- * required property expires -> datetime;
- * property createdAt -> datetime {
- * default := datetime_current();
- * };
- *
- * constraint exclusive on ((.identifier, .token));
- * }
- * }
- *
- * # Disable the application of access policies within access policies
- * # themselves. This behavior will become the default in EdgeDB 3.0.
- * # See: https://www.edgedb.com/docs/reference/ddl/access_policies#nonrecursive
- *
- * using future nonrecursive_access_policies;
- * ```
- *
- * ### Migrate the database schema
- *
- * 1. Create a migration
- *
- * ```bash
- * edgedb migration create
- * ```
- *
- * 2. Apply the migration
- *
- * ```bash
- * edgedb migrate
- * ```
- *
- * To learn more about [EdgeDB migrations](https://www.edgedb.com/docs/intro/migrations#generate-a-migration) check out the [Migrations docs](https://www.edgedb.com/docs/intro/migrations).
- *
- * ### Generate the query builder
- *
- * ```bash
- * npx @edgedb/generate edgeql-js
- * ```
- *
- * This will generate the [query builder](https://www.edgedb.com/docs/clients/js/querybuilder) so that you can write fully typed EdgeQL queries with TypeScript in a code-first way.
- *
- * ```ts
- * const query = e.select(e.User, () => ({
- * id: true,
- * email: true,
- * emailVerified: true,
- * name: true,
- * image: true,
- * filter_single: { email: "johndoe@example.com" },
- * }));
- *
- * return await query.run(client);
- * ```
- *
- * ## Deploying
- *
- * ### Deploy EdgeDB
- *
- * First deploy an EdgeDB instance on your preferred cloud provider:
- *
- * - [AWS](https://www.edgedb.com/docs/guides/deployment/aws_aurora_ecs)
- * - [Google Cloud](https://www.edgedb.com/docs/guides/deployment/gcp)
- * - [Azure](https://www.edgedb.com/docs/guides/deployment/azure_flexibleserver)
- * - [DigitalOcean](https://www.edgedb.com/docs/guides/deployment/digitalocean)
- * - [Fly.io](https://www.edgedb.com/docs/guides/deployment/fly_io)
- * - [Docker](https://www.edgedb.com/docs/guides/deployment/docker) (cloud-agnostic)
- *
- * ### Find your instance’s DSN
- *
- * The DSN is also known as a connection string. It will have the format `edgedb://username:password@hostname:port`. The exact instructions for this depend on which cloud provider your'e deploying to.
- *
- * ### Set an environment variable
- *
- * ```
- * EDGEDB_DSN="edgedb://johndoe:supersecure@myhost.com:420"
- * ```
- *
- * ### Apply migrations
- *
- * Use the DSN to apply migrations against your remote instance.
- *
- * ```bash
- * edgedb migrate --dsn
- * ```
- *
- * ### Set up a `prebuild` script
- *
- * Add the following `prebuild` script to your `package.json`. When your hosting provider initializes the build, it will trigger this script which will generate the query builder. The `npx @edgedb/generate edgeql-js` command will read the value of the `EDGEDB_DSN` environment variable, connect to the database, and generate the query builder before your hosting provider starts building the project.
- *
- *
- */
export function EdgeDBAdapter(client: Client): Adapter {
return {
async createUser({ email, emailVerified, name, image }) {
diff --git a/packages/adapter-fauna/src/index.ts b/packages/adapter-fauna/src/index.ts
index a2a731fd0b..12142ab9a1 100644
--- a/packages/adapter-fauna/src/index.ts
+++ b/packages/adapter-fauna/src/index.ts
@@ -1,8 +1,8 @@
/**
*
- *
Official Fauna adapter for Auth.js / NextAuth.js.
+ *
Official Fauna adapter for Auth.js / NextAuth.js.
*
- *
+ *
*
*
*
@@ -63,179 +63,6 @@ const defaultCollectionNames = {
verificationToken: "VerificationToken",
}
-/**
- *
- * ## Setup
- *
- * This is the Fauna Adapter for [Auth.js](https://authjs.dev). This package can only be used in conjunction with the primary `next-auth` and other framework packages. It is not a standalone package.
- *
- * You can find the Fauna schema and seed information in the docs at [authjs.dev/reference/adapter/fauna](https://authjs.dev/reference/adapter/fauna).
- *
- * ### Configure Auth.js
- *
- * ```js title="pages/api/auth/[...nextauth].js"
- * import NextAuth from "next-auth"
- * import { Client } from "fauna"
- * import { FaunaAdapter } from "@auth/fauna-adapter"
- *
- * const client = new Client({
- * secret: "secret",
- * endpoint: new URL('http://localhost:8443')
- * })
- *
- * // For more information on each option (and a full list of options) go to
- * // https://authjs.dev/reference/core/types#authconfig
- * export default NextAuth({
- * // https://authjs.dev/getting-started/authentication/oauth
- * providers: [],
- * adapter: FaunaAdapter(client)
- * })
- * ```
- *
- * ### Schema
- *
- * Run the following FQL code inside the `Shell` tab in the Fauna dashboard to set up the appropriate collections and indexes.
- *
- * ```javascript
- * Collection.create({
- * name: "Account",
- * indexes: {
- * byUserId: {
- * terms: [
- * { field: "userId" }
- * ]
- * },
- * byProviderAndProviderAccountId: {
- * terms [
- * { field: "provider" },
- * { field: "providerAccountId" }
- * ]
- * },
- * }
- * })
- * Collection.create({
- * name: "Session",
- * constraints: [
- * {
- * unique: ["sessionToken"],
- * status: "active",
- * }
- * ],
- * indexes: {
- * bySessionToken: {
- * terms: [
- * { field: "sessionToken" }
- * ]
- * },
- * byUserId: {
- * terms [
- * { field: "userId" }
- * ]
- * },
- * }
- * })
- * Collection.create({
- * name: "User",
- * constraints: [
- * {
- * unique: ["email"],
- * status: "active",
- * }
- * ],
- * indexes: {
- * byEmail: {
- * terms [
- * { field: "email" }
- * ]
- * },
- * }
- * })
- * Collection.create({
- * name: "VerificationToken",
- * indexes: {
- * byIdentifierAndToken: {
- * terms [
- * { field: "identifier" },
- * { field: "token" }
- * ]
- * },
- * }
- * })
- * ```
- *
- * > This schema is adapted for use in Fauna and based upon our main [schema](https://authjs.dev/reference/core/adapters#models)
- *
- * #### Custom collection names
- * If you want to use custom collection names, you can pass them as an option to the adapter, like this:
- *
- * ```javascript
- * FaunaAdapter(client, {
- * collectionNames: {
- * user: "CustomUser",
- * account: "CustomAccount",
- * session: "CustomSession",
- * verificationToken: "CustomVerificationToken",
- * }
- * })
- * ```
- *
- * Make sure the collection names you pass to the provider match the collection names of your Fauna database.
- *
- * ### Migrating from v1
- * In v2, we've renamed the collections to use uppercase naming, in accordance with Fauna best practices. If you're migrating from v1, you'll need to rename your collections to match the new naming scheme.
- * Additionally, we've renamed the indexes to match the new method-like index names.
- *
- * #### Migration script
- * Run this FQL script inside a Fauna shell for the database you're migrating from v1 to v2 (it will rename your collections and indexes to match):
- *
- * ```javascript
- * Collection.byName("accounts")!.update({
- * name: "Account"
- * indexes: {
- * byUserId: {
- * terms: [{ field: "userId" }]
- * },
- * byProviderAndProviderAccountId: {
- * terms: [{ field: "provider" }, { field: "providerAccountId" }]
- * },
- * account_by_provider_and_provider_account_id: null,
- * accounts_by_user_id: null
- * }
- * })
- * Collection.byName("sessions")!.update({
- * name: "Session",
- * indexes: {
- * bySessionToken: {
- * terms: [{ field: "sessionToken" }]
- * },
- * byUserId: {
- * terms: [{ field: "userId" }]
- * },
- * session_by_session_token: null,
- * sessions_by_user_id: null
- * }
- * })
- * Collection.byName("users")!.update({
- * name: "User",
- * indexes: {
- * byEmail: {
- * terms: [{ field: "email" }]
- * },
- * user_by_email: null
- * }
- * })
- * Collection.byName("verification_tokens")!.update({
- * name: "VerificationToken",
- * indexes: {
- * byIdentifierAndToken: {
- * terms: [{ field: "identifier" }, { field: "token" }]
- * },
- * verification_token_by_identifier_and_token: null
- * }
- * })
- * ```
- *
- **/
export function FaunaAdapter(client: Client, config?: AdapterConfig): Adapter {
const { collectionNames = defaultCollectionNames } = config || {}
diff --git a/packages/adapter-firebase/src/index.ts b/packages/adapter-firebase/src/index.ts
index 41ac8a21f0..5aa4196e3d 100644
--- a/packages/adapter-firebase/src/index.ts
+++ b/packages/adapter-firebase/src/index.ts
@@ -57,77 +57,6 @@ export interface FirebaseAdapterConfig extends AppOptions {
namingStrategy?: "snake_case" | "default"
}
-/**
- * ## Setup
- *
- * First, create a Firebase project and generate a service account key. Visit: `https://console.firebase.google.com/u/0/project/{project-id}/settings/serviceaccounts/adminsdk` (replace `{project-id}` with your project's id)
- *
- * Now you have a few options to authenticate with the Firebase Admin SDK in your app:
- *
- * ### Environment variables
- * - Download the service account key and save it in your project. (Make sure to add the file to your `.gitignore`!)
- * - Add [`GOOGLE_APPLICATION_CREDENTIALS`](https://cloud.google.com/docs/authentication/application-default-credentials#GAC) to your environment variables and point it to the service account key file.
- * - The adapter will automatically pick up the environment variable and use it to authenticate with the Firebase Admin SDK.
- *
- * @example
- * ```ts title="pages/api/auth/[...nextauth].ts"
- * import NextAuth from "next-auth"
- * import { FirestoreAdapter } from "@auth/firebase-adapter"
- *
- * export default NextAuth({
- * adapter: FirestoreAdapter(),
- * // ...
- * })
- * ```
- *
- * ### Service account values
- *
- * - Download the service account key to a temporary location. (Make sure to not commit this file to your repository!)
- * - Add the following environment variables to your project: `FIREBASE_PROJECT_ID`, `FIREBASE_CLIENT_EMAIL`, `FIREBASE_PRIVATE_KEY`.
- * - Pass the config to the adapter, using the environment variables as shown in the example below.
- *
- * @example
- * ```ts title="pages/api/auth/[...nextauth].ts"
- * import NextAuth from "next-auth"
- * import { FirestoreAdapter } from "@auth/firebase-adapter"
- * import { cert } from "firebase-admin/app"
- *
- * export default NextAuth({
- * adapter: FirestoreAdapter({
- * credential: cert({
- * projectId: process.env.FIREBASE_PROJECT_ID,
- * clientEmail: process.env.FIREBASE_CLIENT_EMAIL,
- * privateKey: process.env.FIREBASE_PRIVATE_KEY,
- * })
- * })
- * // ...
- * })
- * ```
- *
- * ### Using an existing Firestore instance
- *
- * If you already have a Firestore instance, you can pass that to the adapter directly instead.
- *
- * :::note
- * When passing an instance and in a serverless environment, remember to handle duplicate app initialization.
- * :::
- *
- * :::tip
- * You can use the {@link initFirestore} utility to initialize the app and get an instance safely.
- * :::
- *
- * @example
- * ```ts title="pages/api/auth/[...nextauth].ts"
- * import NextAuth from "next-auth"
- * import { FirestoreAdapter } from "@auth/firebase-adapter"
- * import { firestore } from "lib/firestore"
- *
- * export default NextAuth({
- * adapter: FirestoreAdapter(firestore),
- * // ...
- * })
- * ```
- */
export function FirestoreAdapter(
config?: FirebaseAdapterConfig | Firestore
): Adapter {
diff --git a/packages/adapter-hasura/src/index.ts b/packages/adapter-hasura/src/index.ts
index 8686369ed5..7f4ea29528 100644
--- a/packages/adapter-hasura/src/index.ts
+++ b/packages/adapter-hasura/src/index.ts
@@ -1,6 +1,6 @@
/**
*
- *
Official Hasura adapter for Auth.js / NextAuth.js.
+ *
Official Hasura adapter for Auth.js / NextAuth.js.
*
*
*
@@ -42,101 +42,6 @@ import {
VerificationTokenFragmentDoc,
} from "./lib/generated/graphql.js"
-/**
- *
- * ## Setup
- *
- * 1. Create the Auth.js schema in your database using SQL.
- *
- * ```sql
- * CREATE TABLE accounts (
- * id uuid DEFAULT gen_random_uuid() NOT NULL,
- * type text NOT NULL,
- * provider text NOT NULL,
- * "providerAccountId" text NOT NULL,
- * refresh_token text,
- * access_token text,
- * expires_at integer,
- * token_type text,
- * scope text,
- * id_token text,
- * session_state text,
- * "userId" uuid NOT NULL
- * );
- *
- * CREATE TABLE sessions (
- * id uuid DEFAULT gen_random_uuid() NOT NULL,
- * "sessionToken" text NOT NULL,
- * "userId" uuid NOT NULL,
- * expires timestamptz NOT NULL
- * );
- *
- * CREATE TABLE users (
- * id uuid DEFAULT gen_random_uuid() NOT NULL,
- * name text,
- * email text NOT NULL,
- * "emailVerified" timestamptz,
- * image text
- * );
- *
- * CREATE TABLE verification_tokens (
- * token text NOT NULL,
- * identifier text NOT NULL,
- * expires timestamptz NOT NULL
- * );
- *
- * CREATE TABLE provider_type (
- * value text NOT NULL
- * );
- *
- * ALTER TABLE ONLY accounts
- * ADD CONSTRAINT accounts_pkey PRIMARY KEY (id);
- *
- * ALTER TABLE ONLY sessions
- * ADD CONSTRAINT sessions_pkey PRIMARY KEY ("sessionToken");
- *
- * ALTER TABLE ONLY users
- * ADD CONSTRAINT users_email_key UNIQUE (email);
- *
- * ALTER TABLE ONLY users
- * ADD CONSTRAINT users_pkey PRIMARY KEY (id);
- *
- * ALTER TABLE ONLY verification_tokens
- * ADD CONSTRAINT verification_tokens_pkey PRIMARY KEY (token);
- *
- * ALTER TABLE ONLY provider_type
- * ADD CONSTRAINT provider_type_pkey PRIMARY KEY (value);
- *
- * ALTER TABLE ONLY accounts
- * ADD CONSTRAINT "accounts_userId_fkey" FOREIGN KEY ("userId") REFERENCES public.users(id) ON UPDATE RESTRICT ON DELETE CASCADE;
- *
- * ALTER TABLE ONLY sessions
- * ADD CONSTRAINT "sessions_userId_fkey" FOREIGN KEY ("userId") REFERENCES public.users(id) ON UPDATE RESTRICT ON DELETE CASCADE;
- *
- * INSERT INTO provider_type (value) VALUES ('credentials'), ('email'), ('oauth'), ('oidc');
- *
- * ALTER TABLE ONLY accounts
- * ADD CONSTRAINT "accounts_type_fkey" FOREIGN KEY ("type") REFERENCES public.provider_type(value) ON UPDATE RESTRICT ON DELETE RESTRICT;
- * ```
- *
- * :::info
- * Tips: [Track all the tables and relationships in Hasura](https://hasura.io/docs/latest/schema/postgres/using-existing-database/#step-1-track-tablesviews)
- * :::
- *
- * 2. Add the adapter to your `pages/api/[...nextauth].ts` next-auth configuration object.
- *
- * ```js title="pages/api/auth/[...nextauth].js"
- * import NextAuth from "next-auth"
- * import { HasuraAdapter } from "@auth/hasura-adapter"
- *
- * export default NextAuth({
- * adapter: HasuraAdapter({
- * endpoint: "
",
- * adminSecret: "",
- * }),
- * })
- * ```
- */
export function HasuraAdapter(client: HasuraAdapterClient): Adapter {
const c = hasuraClient(client)
diff --git a/packages/adapter-kysely/src/index.ts b/packages/adapter-kysely/src/index.ts
index 8a12720fef..014a5f7021 100644
--- a/packages/adapter-kysely/src/index.ts
+++ b/packages/adapter-kysely/src/index.ts
@@ -1,6 +1,6 @@
/**
*
- *
Official Kysely adapter for Auth.js / NextAuth.js.
+ *
Official Kysely adapter for Auth.js / NextAuth.js.
*
*
*
@@ -57,187 +57,6 @@ export const format = {
},
}
-/**
- *
- * ## Setup
- *
- * This adapter supports the same first party dialects that Kysely (as of v0.24.2) supports: PostgreSQL, MySQL, and SQLite. The examples below use PostgreSQL with the [pg](https://www.npmjs.com/package/pg) client.
- *
- * ```bash npm2yarn
- * npm install pg
- * npm install --save-dev @types/pg
- * ```
- *
- * ```ts title="pages/api/auth/[...nextauth].ts"
- * import NextAuth from "next-auth"
- * import GoogleProvider from "next-auth/providers/google"
- * import { KyselyAdapter } from "@auth/kysely-adapter"
- * import { db } from "../../../db"
- *
- * export default NextAuth({
- * adapter: KyselyAdapter(db),
- * providers: [
- * GoogleProvider({
- * clientId: process.env.GOOGLE_CLIENT_ID,
- * clientSecret: process.env.GOOGLE_CLIENT_SECRET,
- * }),
- * ],
- * })
- * ```
- *
- * Kysely's constructor requires a database interface that contains an entry with an interface for each of your tables. You can define these types manually, or use `kysely-codegen` / `prisma-kysely` to automatically generate them. Check out the default [models](/reference/core/adapters#models) required by Auth.js.
- *
- * ```ts title="db.ts"
- * import { PostgresDialect } from "kysely"
- * import { Pool } from "pg"
- *
- * // This adapter exports a wrapper of the original `Kysely` class called `KyselyAuth`,
- * // that can be used to provide additional type-safety.
- * // While using it isn't required, it is recommended as it will verify
- * // that the database interface has all the fields that Auth.js expects.
- * import { KyselyAuth } from "@auth/kysely-adapter"
- *
- * import type { GeneratedAlways } from "kysely"
- *
- * interface Database {
- * User: {
- * id: GeneratedAlways
- * name: string | null
- * email: string
- * emailVerified: Date | null
- * image: string | null
- * }
- * Account: {
- * id: GeneratedAlways
- * userId: string
- * type: string
- * provider: string
- * providerAccountId: string
- * refresh_token: string | null
- * access_token: string | null
- * expires_at: number | null
- * token_type: string | null
- * scope: string | null
- * id_token: string | null
- * session_state: string | null
- * }
- * Session: {
- * id: GeneratedAlways
- * userId: string
- * sessionToken: string
- * expires: Date
- * }
- * VerificationToken: {
- * identifier: string
- * token: string
- * expires: Date
- * }
- * }
- *
- * export const db = new KyselyAuth({
- * dialect: new PostgresDialect({
- * pool: new Pool({
- * host: process.env.DATABASE_HOST,
- * database: process.env.DATABASE_NAME,
- * user: process.env.DATABASE_USER,
- * password: process.env.DATABASE_PASSWORD,
- * }),
- * }),
- * })
- * ```
- *
- * :::note
- * An alternative to manually defining types is generating them from the database schema using [kysely-codegen](https://github.com/RobinBlomberg/kysely-codegen), or from Prisma schemas using [prisma-kysely](https://github.com/valtyr/prisma-kysely). When using generated types with `KyselyAuth`, import `Codegen` and pass it as the second generic arg:
- *
- * ```ts
- * import type { Codegen } from "@auth/kysely-adapter"
- * new KyselyAuth): Promise {
- * await db.schema
- * .createTable("User")
- * .addColumn("id", "uuid", (col) =>
- * col.primaryKey().defaultTo(sql`gen_random_uuid()`)
- * )
- * .addColumn("name", "text")
- * .addColumn("email", "text", (col) => col.unique().notNull())
- * .addColumn("emailVerified", "timestamptz")
- * .addColumn("image", "text")
- * .execute()
- *
- * await db.schema
- * .createTable("Account")
- * .addColumn("id", "uuid", (col) =>
- * col.primaryKey().defaultTo(sql`gen_random_uuid()`)
- * )
- * .addColumn("userId", "uuid", (col) =>
- * col.references("User.id").onDelete("cascade").notNull()
- * )
- * .addColumn("type", "text", (col) => col.notNull())
- * .addColumn("provider", "text", (col) => col.notNull())
- * .addColumn("providerAccountId", "text", (col) => col.notNull())
- * .addColumn("refresh_token", "text")
- * .addColumn("access_token", "text")
- * .addColumn("expires_at", "bigint")
- * .addColumn("token_type", "text")
- * .addColumn("scope", "text")
- * .addColumn("id_token", "text")
- * .addColumn("session_state", "text")
- * .execute()
- *
- * await db.schema
- * .createTable("Session")
- * .addColumn("id", "uuid", (col) =>
- * col.primaryKey().defaultTo(sql`gen_random_uuid()`)
- * )
- * .addColumn("userId", "uuid", (col) =>
- * col.references("User.id").onDelete("cascade").notNull()
- * )
- * .addColumn("sessionToken", "text", (col) => col.notNull().unique())
- * .addColumn("expires", "timestamptz", (col) => col.notNull())
- * .execute()
- *
- * await db.schema
- * .createTable("VerificationToken")
- * .addColumn("identifier", "text", (col) => col.notNull())
- * .addColumn("token", "text", (col) => col.notNull().unique())
- * .addColumn("expires", "timestamptz", (col) => col.notNull())
- * .execute()
- *
- * await db.schema
- * .createIndex("Account_userId_index")
- * .on("Account")
- * .column("userId")
- * .execute()
- *
- * await db.schema
- * .createIndex("Session_userId_index")
- * .on("Session")
- * .column("userId")
- * .execute()
- * }
- *
- * export async function down(db: Kysely): Promise {
- * await db.schema.dropTable("Account").ifExists().execute()
- * await db.schema.dropTable("Session").ifExists().execute()
- * await db.schema.dropTable("User").ifExists().execute()
- * await db.schema.dropTable("VerificationToken").ifExists().execute()
- * }
- * ```
- *
- * > This schema is adapted for use in Kysely and is based upon our main [schema](/reference/core/adapters#models).
- *
- * For more information about creating and running migrations with Kysely, refer to the [Kysely migrations documentation](https://kysely.dev/docs/migrations).
- *
- * ### Naming conventions
- * If mixed snake_case and camelCase column names is an issue for you and/or your underlying database system, we recommend using Kysely's `CamelCasePlugin` ([see the documentation here](https://kysely-org.github.io/kysely-apidoc/classes/CamelCasePlugin.html)) feature to change the field names. This won't affect NextAuth.js, but will allow you to have consistent casing when using Kysely.
- */
export function KyselyAdapter(db: Kysely): Adapter {
const { adapter } = db.getExecutor()
const { supportsReturning } = adapter
diff --git a/packages/adapter-mikro-orm/src/index.ts b/packages/adapter-mikro-orm/src/index.ts
index 246d03defa..1cfa87bb62 100644
--- a/packages/adapter-mikro-orm/src/index.ts
+++ b/packages/adapter-mikro-orm/src/index.ts
@@ -1,8 +1,8 @@
/**
*
- *
Official MikroORM adapter for Auth.js / NextAuth.js.
+ *
Official MikroORM adapter for Auth.js / NextAuth.js.
*
- *
+ *
*
*
*
@@ -28,111 +28,6 @@ import * as defaultEntities from "./lib/entities.js"
export { defaultEntities }
-/**
- * ## Setup
- *
- * Configure Auth.js to use the MikroORM Adapter:
- *
- * ```ts title="pages/api/auth/[...nextauth].ts"
- * import NextAuth from "next-auth"
- * import { MikroOrmAdapter } from "@auth/mikro-orm-adapter"
- *
- * export default NextAuth({
- * adapter: MikroOrmAdapter({
- * // MikroORM options object. Ref: https://mikro-orm.io/docs/next/configuration#driver
- * dbName: "./db.sqlite",
- * type: "sqlite",
- * debug: process.env.DEBUG === "true" || process.env.DEBUG?.includes("db"),
- * }),
- * providers: [],
- * })
- * ```
- *
- * ## Advanced usage
- *
- * ### Passing custom entities
- *
- * The MikroORM adapter ships with its own set of entities. If you'd like to extend them, you can optionally pass them to the adapter.
- *
- * > This schema is adapted for use in MikroORM and based upon our main [schema](https://authjs.dev/reference/core/adapters#models)
- *
- * ```ts title="pages/api/auth/[...nextauth].ts"
- * import config from "config/mikro-orm.ts"
- * import {
- * Cascade,
- * Collection,
- * Entity,
- * OneToMany,
- * PrimaryKey,
- * Property,
- * Unique,
- * } from "@mikro-orm/core"
- * import { defaultEntities } from "@auth/mikro-orm-adapter"
- *
- * const { Account, Session } = defaultEntities
- *
- * @Entity()
- * export class User implements defaultEntities.User {
- * @PrimaryKey()
- * id: string = randomUUID()
- *
- * @Property({ nullable: true })
- * name?: string
- *
- * @Property({ nullable: true })
- * @Unique()
- * email?: string
- *
- * @Property({ type: "Date", nullable: true })
- * emailVerified: Date | null = null
- *
- * @Property({ nullable: true })
- * image?: string
- *
- * @OneToMany({
- * entity: () => Session,
- * mappedBy: (session) => session.user,
- * hidden: true,
- * orphanRemoval: true,
- * cascade: [Cascade.ALL],
- * })
- * sessions = new Collection(this)
- *
- * @OneToMany({
- * entity: () => Account,
- * mappedBy: (account) => account.user,
- * hidden: true,
- * orphanRemoval: true,
- * cascade: [Cascade.ALL],
- * })
- * accounts = new Collection(this)
- *
- * @Enum({ hidden: true })
- * role = "ADMIN"
- * }
- *
- * export default NextAuth({
- * adapter: MikroOrmAdapter(config, { entities: { User } }),
- * })
- * ```
- *
- * ### Including default entities
- *
- * You may want to include the defaultEntities in your MikroORM configuration to include them in Migrations etc.
- *
- * To achieve that include them in your "entities" array:
- *
- * ```ts title="config/mikro-orm.ts"
- * import { Options } from "@mikro-orm/core";
- * import { defaultEntities } from "@auth/mikro-orm-adapter"
- *
- * const config: Options = {
- * entities: [VeryImportantEntity, ...Object.values(defaultEntities)],
- * };
- *
- * export default config;
- * ```
- */
export function MikroOrmAdapter<
D extends IDatabaseDriver = IDatabaseDriver,
>(
diff --git a/packages/adapter-mongodb/src/index.ts b/packages/adapter-mongodb/src/index.ts
index a63434a55e..9ded9c92c8 100644
--- a/packages/adapter-mongodb/src/index.ts
+++ b/packages/adapter-mongodb/src/index.ts
@@ -1,6 +1,6 @@
/**
*
- *
Official MongoDB adapter for Auth.js / NextAuth.js.
+ *
Official MongoDB adapter for Auth.js / NextAuth.js.
*
*
*
@@ -88,60 +88,6 @@ export function _id(hex?: string) {
return new ObjectId(hex)
}
-/**
- * ## Setup
- *
- * The MongoDB adapter does not handle connections automatically, so you will have to make sure that you pass the Adapter a `MongoClient` that is connected already. Below you can see an example how to do this.
- *
- * ### Add the MongoDB client
- *
- * ```ts
- * // This approach is taken from https://github.com/vercel/next.js/tree/canary/examples/with-mongodb
- * import { MongoClient } from "mongodb"
- *
- * if (!process.env.MONGODB_URI) {
- * throw new Error('Invalid/Missing environment variable: "MONGODB_URI"')
- * }
- *
- * const uri = process.env.MONGODB_URI
- * const options = {}
- *
- * let client
- * let clientPromise: Promise
- *
- * if (process.env.NODE_ENV === "development") {
- * // In development mode, use a global variable so that the value
- * // is preserved across module reloads caused by HMR (Hot Module Replacement).
- * if (!global._mongoClientPromise) {
- * client = new MongoClient(uri, options)
- * global._mongoClientPromise = client.connect()
- * }
- * clientPromise = global._mongoClientPromise
- * } else {
- * // In production mode, it's best to not use a global variable.
- * client = new MongoClient(uri, options)
- * clientPromise = client.connect()
- * }
- *
- * // Export a module-scoped MongoClient promise. By doing this in a
- * // separate module, the client can be shared across functions.
- * export default clientPromise
- * ```
- *
- * ### Configure Auth.js
- *
- * ```js
- * import NextAuth from "next-auth"
- * import { MongoDBAdapter } from "@auth/mongodb-adapter"
- * import clientPromise from "../../../lib/mongodb"
- *
- * // For more information on each option (and a full list of options) go to
- * // https://authjs.dev/reference/providers/oauth
- * export default NextAuth({
- * adapter: MongoDBAdapter(clientPromise),
- * })
- * ```
- **/
export function MongoDBAdapter(
client: Promise,
options: MongoDBAdapterOptions = {}
diff --git a/packages/adapter-neo4j/src/index.ts b/packages/adapter-neo4j/src/index.ts
index 6d787a3b88..d421adf974 100644
--- a/packages/adapter-neo4j/src/index.ts
+++ b/packages/adapter-neo4j/src/index.ts
@@ -1,8 +1,8 @@
/**
*
- *
Official Neo4j adapter for Auth.js / NextAuth.js.
+ *
Official Neo4j adapter for Auth.js / NextAuth.js.
*
- *
+ *
*
*
*
@@ -22,113 +22,6 @@ import type { Adapter } from "@auth/core/adapters"
**/
export interface Neo4jOptions extends Session {}
-/**
- * ## Setup
- *
- * Add this adapter to your `pages/api/[...nextauth].js` Auth.js configuration object.
- *
- * ```js title="pages/api/auth/[...nextauth].js"
- * import neo4j from "neo4j-driver"
- * import { Neo4jAdapter } from "@auth/neo4j-adapter"
- *
- * const driver = neo4j.driver(
- * "bolt://localhost",
- * neo4j.auth.basic("neo4j", "password")
- * )
- *
- * const neo4jSession = driver.session()
- *
- * // For more information on each option (and a full list of options) go to
- * // https://authjs.dev/reference/core/types#authconfig
- * export default NextAuth({
- * // https://authjs.dev/getting-started/authentication/oauth
- * providers: [],
- * adapter: Neo4jAdapter(neo4jSession),
- * })
- * ```
- *
- * ## Advanced usage
- *
- * ### Schema
- *
- * #### Node labels
- *
- * The following node labels are used.
- *
- * - User
- * - Account
- * - Session
- * - VerificationToken
- *
- * #### Relationships
- *
- * The following relationships and relationship labels are used.
- *
- * - `(:User)-[:HAS_ACCOUNT]->(:Account)`
- * - `(:User)-[:HAS_SESSION]->(:Session)`
- *
- * #### Properties
- *
- * This schema is adapted for use in Neo4j and is based upon our main [models](https://authjs.dev/reference/core/adapters#models). Please check there for the node properties. Relationships have no properties.
- *
- * #### Indexes
- *
- * Optimum indexes will vary on your edition of Neo4j i.e. community or enterprise, and in case you have your own additional data on the nodes. Below are basic suggested indexes.
- *
- * 1. For **both** Community Edition & Enterprise Edition create constraints and indexes
- *
- * ```sql
- * CREATE CONSTRAINT user_id_constraint IF NOT EXISTS
- * ON (u:User) ASSERT u.id IS UNIQUE;
- *
- * CREATE INDEX user_id_index IF NOT EXISTS
- * FOR (u:User) ON (u.id);
- *
- * CREATE INDEX user_email_index IF NOT EXISTS
- * FOR (u:User) ON (u.email);
- *
- * CREATE CONSTRAINT session_session_token_constraint IF NOT EXISTS
- * ON (s:Session) ASSERT s.sessionToken IS UNIQUE;
- *
- * CREATE INDEX session_session_token_index IF NOT EXISTS
- * FOR (s:Session) ON (s.sessionToken);
- * ```
- *
- * 2. Indexes
- *
- * 2.1. For Community Edition **only** create single-property indexes
- *
- * ```sql
- * CREATE INDEX account_provider_index IF NOT EXISTS
- * FOR (a:Account) ON (a.provider);
- *
- * CREATE INDEX account_provider_account_id_index IF NOT EXISTS
- * FOR (a:Account) ON (a.providerAccountId);
- *
- * CREATE INDEX verification_token_identifier_index IF NOT EXISTS
- * FOR (v:VerificationToken) ON (v.identifier);
- *
- * CREATE INDEX verification_token_token_index IF NOT EXISTS
- * FOR (v:VerificationToken) ON (v.token);
- * ```
- *
- * 2.2. For Enterprise Edition **only** create composite node key constraints and indexes
- *
- * ```sql
- * CREATE CONSTRAINT account_provider_composite_constraint IF NOT EXISTS
- * ON (a:Account) ASSERT (a.provider, a.providerAccountId) IS NODE KEY;
- *
- * CREATE INDEX account_provider_composite_index IF NOT EXISTS
- * FOR (a:Account) ON (a.provider, a.providerAccountId);
- *
- * CREATE CONSTRAINT verification_token_composite_constraint IF NOT EXISTS
- * ON (v:VerificationToken) ASSERT (v.identifier, v.token) IS NODE KEY;
- *
- * CREATE INDEX verification_token_composite_index IF NOT EXISTS
- * FOR (v:VerificationToken) ON (v.identifier, v.token);
- * ```
- *
- */
export function Neo4jAdapter(session: Session): Adapter {
const { read, write } = client(session)
diff --git a/packages/adapter-pg/src/index.ts b/packages/adapter-pg/src/index.ts
index c17c3bf037..f1ec092f3e 100644
--- a/packages/adapter-pg/src/index.ts
+++ b/packages/adapter-pg/src/index.ts
@@ -1,8 +1,8 @@
/**
*
*
@@ -31,83 +31,6 @@ export function mapExpiresAt(account: any): any {
}
}
-/**
- * ## Setup
- *
- * The SQL schema for the tables used by this adapter is as follows. Learn more about the models at our doc page on [Database Models](https://authjs.dev/getting-started/database#models).
- *
- * ```sql
- * CREATE TABLE verification_token (
- * identifier TEXT NOT NULL,
- * expires TIMESTAMPTZ NOT NULL,
- * token TEXT NOT NULL,
- *
- * PRIMARY KEY (identifier, token)
- * );
- *
- * CREATE TABLE accounts (
- * id SERIAL,
- * "userId" INTEGER NOT NULL,
- * type VARCHAR(255) NOT NULL,
- * provider VARCHAR(255) NOT NULL,
- * "providerAccountId" VARCHAR(255) NOT NULL,
- * refresh_token TEXT,
- * access_token TEXT,
- * expires_at BIGINT,
- * id_token TEXT,
- * scope TEXT,
- * session_state TEXT,
- * token_type TEXT,
- *
- * PRIMARY KEY (id)
- * );
- *
- * CREATE TABLE sessions (
- * id SERIAL,
- * "userId" INTEGER NOT NULL,
- * expires TIMESTAMPTZ NOT NULL,
- * "sessionToken" VARCHAR(255) NOT NULL,
- *
- * PRIMARY KEY (id)
- * );
- *
- * CREATE TABLE users (
- * id SERIAL,
- * name VARCHAR(255),
- * email VARCHAR(255),
- * "emailVerified" TIMESTAMPTZ,
- * image TEXT,
- *
- * PRIMARY KEY (id)
- * );
- * ```
- *
- * ```ts title="auth.ts"
- * import NextAuth from "next-auth"
- * import GoogleProvider from "next-auth/providers/google"
- * import PostgresAdapter from "@auth/pg-adapter"
- * import { Pool } from 'pg'
- *
- * const pool = new Pool({
- * host: 'localhost',
- * user: 'database-user',
- * max: 20,
- * idleTimeoutMillis: 30000,
- * connectionTimeoutMillis: 2000,
- * })
- *
- * export default NextAuth({
- * adapter: PostgresAdapter(pool),
- * providers: [
- * GoogleProvider({
- * clientId: process.env.GOOGLE_CLIENT_ID,
- * clientSecret: process.env.GOOGLE_CLIENT_SECRET,
- * }),
- * ],
- * })
- * ```
- *
- */
export default function PostgresAdapter(client: Pool): Adapter {
return {
async createVerificationToken(
diff --git a/packages/adapter-pouchdb/src/index.ts b/packages/adapter-pouchdb/src/index.ts
index e1d8c37436..6c2d864fcb 100644
--- a/packages/adapter-pouchdb/src/index.ts
+++ b/packages/adapter-pouchdb/src/index.ts
@@ -1,6 +1,6 @@
/**
*
- *
Official PouchDB adapter for Auth.js / NextAuth.js.
+ *
Official PouchDB adapter for Auth.js / NextAuth.js.
*
*
*
@@ -82,59 +82,6 @@ export interface PouchDBAdapterOptions {
indexes?: IndexConfig
}
-/**
- * :::info
- * Depending on your architecture you can use PouchDB's http adapter to reach any database compliant with the CouchDB protocol (CouchDB, Cloudant, etc.) or use any other PouchDB compatible adapter (leveldb, in-memory, etc.)
- * :::
- *
- * ## Setup
- *
- * :::note
- * Your PouchDB instance MUST provide the `pouchdb-find` plugin since it is used internally by the adapter to build and manage indexes
- * :::
- *
- * Add this adapter to your `pages/api/auth/[...nextauth].js` next-auth configuration object:
- *
- * ```js title="pages/api/auth/[...nextauth].js"
- * import NextAuth from "next-auth"
- * import GoogleProvider from "next-auth/providers/google"
- * import { PouchDBAdapter } from "@auth/pouchdb-adapter"
- * import PouchDB from "pouchdb"
- *
- * // Setup your PouchDB instance and database
- * PouchDB
- * .plugin(require("pouchdb-adapter-leveldb")) // Or any other adapter
- * .plugin(require("pouchdb-find")) // Don't forget the `pouchdb-find` plugin
- *
- * const pouchdb = new PouchDB("auth_db", { adapter: "leveldb" })
- *
- * // For more information on each option (and a full list of options) go to
- * // https://authjs.dev/reference/core/types#authconfig
- * export default NextAuth({
- * // https://authjs.dev/getting-started/authentication/oauth
- * providers: [
- * GoogleProvider({
- * clientId: process.env.GOOGLE_ID,
- * clientSecret: process.env.GOOGLE_SECRET,
- * }),
- * ],
- * adapter: PouchDBAdapter(pouchdb),
- * })
- * ```
- *
- * ## Advanced usage
- *
- * ### Memory-First Caching Strategy
- *
- * If you need to boost your authentication layer performance, you may use PouchDB's powerful sync features and various adapters, to build a memory-first caching strategy.
- *
- * Use an in-memory PouchDB as your main authentication database, and synchronize it with any other persisted PouchDB. You may do a one way, one-off replication at startup from the persisted PouchDB into the in-memory PouchDB, then two-way, continuous sync.
- *
- * This will most likely not increase performance much in a serverless environment due to various reasons such as concurrency, function startup time increases, etc.
- *
- * For more details, please see https://pouchdb.com/api.html#sync
- *
- */
export function PouchDBAdapter(options: PouchDBAdapterOptions): Adapter {
const { pouchdb } = options
const {
diff --git a/packages/adapter-sequelize/src/index.ts b/packages/adapter-sequelize/src/index.ts
index bebcc6744a..701d9a08b2 100644
--- a/packages/adapter-sequelize/src/index.ts
+++ b/packages/adapter-sequelize/src/index.ts
@@ -1,6 +1,6 @@
/**
*
- *
Official Sequilize adapter for Auth.js / NextAuth.js.
+ *
Official Sequilize adapter for Auth.js / NextAuth.js.
*
*
*
@@ -58,83 +58,6 @@ export interface SequelizeAdapterOptions {
}>
}
-/**
- * :::warning
- * You'll also have to manually install [the driver for your database](https://sequelize.org/master/manual/getting-started.html) of choice.
- * :::
- *
- * ## Setup
- *
- * ### Configuring Auth.js
- *
- * Add this adapter to your `pages/api/[...nextauth].js` next-auth configuration object.
- *
- * ```js title="pages/api/auth/[...nextauth].js"
- * import NextAuth from "next-auth"
- * import SequelizeAdapter from "@auth/sequelize-adapter"
- * import { Sequelize } from "sequelize"
- *
- * // https://sequelize.org/master/manual/getting-started.html#connecting-to-a-database
- * const sequelize = new Sequelize("yourconnectionstring")
- *
- * // For more information on each option (and a full list of options) go to
- * // https://authjs.dev/reference/core#authconfig
- * export default NextAuth({
- * // https://authjs.dev/reference/providers/
- * providers: [],
- * adapter: SequelizeAdapter(sequelize),
- * })
- * ```
- *
- * ### Updating the database schema
- *
- * By default, the sequelize adapter will not create tables in your database. In production, best practice is to create the [required tables](https://authjs.dev/reference/core/adapters#models) in your database via [migrations](https://sequelize.org/master/manual/migrations.html). In development, you are able to call [`sequelize.sync()`](https://sequelize.org/master/manual/model-basics.html#model-synchronization) to have sequelize create the necessary tables, foreign keys and indexes:
- *
- * > This schema is adapted for use in Sequelize and based upon our main [schema](https://authjs.dev/reference/core/adapters#models)
- *
- * ```js
- * import NextAuth from "next-auth"
- * import SequelizeAdapter from "@auth/sequelize-adapter"
- * import Sequelize from 'sequelize'
- *
- * const sequelize = new Sequelize("sqlite::memory:")
- * const adapter = SequelizeAdapter(sequelize)
- *
- * // Calling sync() is not recommended in production
- * sequelize.sync()
- *
- * export default NextAuth({
- * adapter
- * })
- * ```
- *
- * ## Advanced usage
- *
- * ### Using custom models
- *
- * Sequelize models are option to customization like so:
- *
- * ```js
- * import NextAuth from "next-auth"
- * import SequelizeAdapter, { models } from "@auth/sequelize-adapter"
- * import Sequelize, { DataTypes } from "sequelize"
- *
- * const sequelize = new Sequelize("sqlite::memory:")
- *
- * export default NextAuth({
- * // https://authjs.dev/reference/providers/
- * providers: [],
- * adapter: SequelizeAdapter(sequelize, {
- * models: {
- * User: sequelize.define("user", {
- * ...models.User,
- * phoneNumber: DataTypes.STRING,
- * }),
- * },
- * }),
- * })
- * ```
- */
export default function SequelizeAdapter(
client: Sequelize,
options?: SequelizeAdapterOptions
diff --git a/packages/adapter-supabase/src/index.ts b/packages/adapter-supabase/src/index.ts
index d94faffc7f..54f96e336a 100644
--- a/packages/adapter-supabase/src/index.ts
+++ b/packages/adapter-supabase/src/index.ts
@@ -1,6 +1,6 @@
/**
*
- *
Official Supabase adapter for Auth.js / NextAuth.js.
+ *
Official Supabase adapter for Auth.js / NextAuth.js.
*
*
*
@@ -56,294 +56,6 @@ export interface SupabaseAdapterOptions {
secret: string
}
-/**
- * :::note
- * This adapter is developed by the community and not officially maintained or supported by Supabase. It uses the Supabase Database to store user and session data in a separate `next_auth` schema. It is a standalone Auth server that does not interface with Supabase Auth and therefore provides a different feature set.
- *
- * If you're looking for an officially maintained Auth server with additional features like [built-in email server](https://supabase.com/docs/guides/auth/auth-email#configure-email-settings?utm_source=authjs-docs&medium=referral&campaign=authjs), [phone auth](https://supabase.com/docs/guides/auth/auth-twilio?utm_source=authjs-docs&medium=referral&campaign=authjs), and [Multi Factor Authentication (MFA / 2FA)](https://supabase.com/contact/mfa?utm_source=authjs-docs&medium=referral&campaign=authjs), please use [Supabase Auth](https://supabase.com/auth) with the [Auth Helpers for Next.js](https://supabase.com/docs/guides/auth/auth-helpers/nextjs?utm_source=authjs-docs&medium=referral&campaign=authjs).
- * :::
- *
- * ## Setup
- *
- * ### Configure Auth.js
- *
- * Add this adapter to your `pages/api/[...nextauth].js` next-auth configuration object.
- *
- * ```js title="pages/api/auth/[...nextauth].js"
- * import NextAuth from "next-auth"
- * import { SupabaseAdapter } from "@auth/supabase-adapter"
- *
- * // For more information on each option (and a full list of options) go to
- * // https://authjs.dev/reference/core#authconfig
- * export default NextAuth({
- * // https://authjs.dev/reference/core/providers
- * providers: [],
- * adapter: SupabaseAdapter({
- * url: process.env.NEXT_PUBLIC_SUPABASE_URL,
- * secret: process.env.SUPABASE_SERVICE_ROLE_KEY,
- * }),
- * })
- * ```
- *
- * ### Create the NextAuth schema in Supabase
- *
- * Setup your database as described in our main [schema](https://authjs.dev/reference/core/adapters#models), by copying the SQL schema below in the Supabase [SQL Editor](https://app.supabase.com/project/_/sql).
- *
- * Alternatively you can select the NextAuth Quickstart card on the [SQL Editor page](https://app.supabase.com/project/_/sql), or [create a migration with the Supabase CLI](https://supabase.com/docs/guides/cli/local-development#database-migrations?utm_source=authjs-docs&medium=referral&campaign=authjs).
- *
- * ```sql
- * --
- * -- Name: next_auth; Type: SCHEMA;
- * --
- * CREATE SCHEMA next_auth;
- *
- * GRANT USAGE ON SCHEMA next_auth TO service_role;
- * GRANT ALL ON SCHEMA next_auth TO postgres;
- *
- * --
- * -- Create users table
- * --
- * CREATE TABLE IF NOT EXISTS next_auth.users
- * (
- * id uuid NOT NULL DEFAULT uuid_generate_v4(),
- * name text,
- * email text,
- * "emailVerified" timestamp with time zone,
- * image text,
- * CONSTRAINT users_pkey PRIMARY KEY (id),
- * CONSTRAINT email_unique UNIQUE (email)
- * );
- *
- * GRANT ALL ON TABLE next_auth.users TO postgres;
- * GRANT ALL ON TABLE next_auth.users TO service_role;
- *
- * --- uid() function to be used in RLS policies
- * CREATE FUNCTION next_auth.uid() RETURNS uuid
- * LANGUAGE sql STABLE
- * AS $$
- * select
- * coalesce(
- * nullif(current_setting('request.jwt.claim.sub', true), ''),
- * (nullif(current_setting('request.jwt.claims', true), '')::jsonb ->> 'sub')
- * )::uuid
- * $$;
- *
- * --
- * -- Create sessions table
- * --
- * CREATE TABLE IF NOT EXISTS next_auth.sessions
- * (
- * id uuid NOT NULL DEFAULT uuid_generate_v4(),
- * expires timestamp with time zone NOT NULL,
- * "sessionToken" text NOT NULL,
- * "userId" uuid,
- * CONSTRAINT sessions_pkey PRIMARY KEY (id),
- * CONSTRAINT sessionToken_unique UNIQUE ("sessionToken"),
- * CONSTRAINT "sessions_userId_fkey" FOREIGN KEY ("userId")
- * REFERENCES next_auth.users (id) MATCH SIMPLE
- * ON UPDATE NO ACTION
- * ON DELETE CASCADE
- * );
- *
- * GRANT ALL ON TABLE next_auth.sessions TO postgres;
- * GRANT ALL ON TABLE next_auth.sessions TO service_role;
- *
- * --
- * -- Create accounts table
- * --
- * CREATE TABLE IF NOT EXISTS next_auth.accounts
- * (
- * id uuid NOT NULL DEFAULT uuid_generate_v4(),
- * type text NOT NULL,
- * provider text NOT NULL,
- * "providerAccountId" text NOT NULL,
- * refresh_token text,
- * access_token text,
- * expires_at bigint,
- * token_type text,
- * scope text,
- * id_token text,
- * session_state text,
- * oauth_token_secret text,
- * oauth_token text,
- * "userId" uuid,
- * CONSTRAINT accounts_pkey PRIMARY KEY (id),
- * CONSTRAINT provider_unique UNIQUE (provider, "providerAccountId"),
- * CONSTRAINT "accounts_userId_fkey" FOREIGN KEY ("userId")
- * REFERENCES next_auth.users (id) MATCH SIMPLE
- * ON UPDATE NO ACTION
- * ON DELETE CASCADE
- * );
- *
- * GRANT ALL ON TABLE next_auth.accounts TO postgres;
- * GRANT ALL ON TABLE next_auth.accounts TO service_role;
- *
- * --
- * -- Create verification_tokens table
- * --
- * CREATE TABLE IF NOT EXISTS next_auth.verification_tokens
- * (
- * identifier text,
- * token text,
- * expires timestamp with time zone NOT NULL,
- * CONSTRAINT verification_tokens_pkey PRIMARY KEY (token),
- * CONSTRAINT token_unique UNIQUE (token),
- * CONSTRAINT token_identifier_unique UNIQUE (token, identifier)
- * );
- *
- * GRANT ALL ON TABLE next_auth.verification_tokens TO postgres;
- * GRANT ALL ON TABLE next_auth.verification_tokens TO service_role;
- * ```
- *
- * ### Expose the NextAuth schema in Supabase
- *
- * Expose the `next_auth` schema via the Serverless API in the [API settings](https://app.supabase.com/project/_/settings/api) by adding `next_auth` to the "Exposed schemas" list.
- *
- * When developing locally add `next_auth` to the `schemas` array in the `config.toml` file in the `supabase` folder that was generated by the [Supabase CLI](https://supabase.com/docs/guides/cli/local-development#initialize-your-project?utm_source=authjs-docs&medium=referral&campaign=authjs).
- *
- * ## Advanced usage
- *
- * ### Enabling Row Level Security (RLS)
- *
- * Postgres provides a powerful feature called [Row Level Security (RLS)](https://supabase.com/docs/guides/auth/row-level-security?utm_source=authjs-docs&medium=referral&campaign=authjs) to limit access to data.
- *
- * This works by sending a signed JWT to your [Supabase Serverless API](https://supabase.com/docs/guides/api?utm_source=authjs-docs&medium=referral&campaign=authjs). There is two steps to make this work with NextAuth:
- *
- * #### Generate the Supabase `access_token` JWT in the session callback
- *
- * To sign the JWT use the `jsonwebtoken` package:
- *
- * ```bash npm2yarn
- * npm install jsonwebtoken
- * ```
- *
- * Using the [NexthAuth.js Session callback](https://authjs.dev/reference/core/types#session) create the Supabase `access_token` and append it to the `session` object.
- *
- * To sign the JWT use the Supabase JWT secret which can be found in the [API settings](https://app.supabase.com/project/_/settings/api)
- *
- * ```js title="pages/api/auth/[...nextauth].js"
- * import NextAuth from "next-auth"
- * import { SupabaseAdapter } from "@auth/supabase-adapter"
- * import jwt from "jsonwebtoken"
- *
- * // For more information on each option (and a full list of options) go to
- * // https://authjs.dev/reference/core/types#authconfig
- * export default NextAuth({
- * // https://authjs.dev/getting-started/authentication/oauth
- * providers: [],
- * adapter: SupabaseAdapter({
- * url: process.env.NEXT_PUBLIC_SUPABASE_URL,
- * secret: process.env.SUPABASE_SERVICE_ROLE_KEY,
- * }),
- * callbacks: {
- * async session({ session, user }) {
- * const signingSecret = process.env.SUPABASE_JWT_SECRET
- * if (signingSecret) {
- * const payload = {
- * aud: "authenticated",
- * exp: Math.floor(new Date(session.expires).getTime() / 1000),
- * sub: user.id,
- * email: user.email,
- * role: "authenticated",
- * }
- * session.supabaseAccessToken = jwt.sign(payload, signingSecret)
- * }
- * return session
- * },
- * },
- * })
- * ```
- *
- * #### Inject the Supabase `access_token` JWT into the client
- *
- * For example, given the following public schema:
- *
- * ```sql
- * -- Note: This table contains user data. Users should only be able to view and update their own data.
- * create table users (
- * -- UUID from next_auth.users
- * id uuid not null primary key,
- * name text,
- * email text,
- * image text,
- * constraint "users_id_fkey" foreign key ("id")
- * references next_auth.users (id) match simple
- * on update no action
- * on delete cascade -- if a user is deleted in NextAuth they will also be deleted in our public table.
- * );
- * alter table users enable row level security;
- * create policy "Can view own user data." on users for select using (next_auth.uid() = id);
- * create policy "Can update own user data." on users for update using (next_auth.uid() = id);
- *
- * -- This trigger automatically creates a user entry when a new user signs up via NextAuth.
- * create function public.handle_new_user()
- * returns trigger as $$
- * begin
- * insert into public.users (id, name, email, image)
- * values (new.id, new.name, new.email, new.image);
- * return new;
- * end;
- * $$ language plpgsql security definer;
- * create trigger on_auth_user_created
- * after insert on next_auth.users
- * for each row execute procedure public.handle_new_user();
- * ```
- *
- * The `supabaseAccessToken` is now available on the `session` object and can be passed to the supabase-js client. This works in any environment: client-side, server-side (API routes, SSR), as well as in middleware edge functions!
- *
- * ```js
- * // Use `useSession()` or `unstable_getServerSession()` to get the NextAuth session.
- *
- * const { supabaseAccessToken } = session
- *
- * const supabase = createClient(
- * process.env.NEXT_PUBLIC_SUPABASE_URL,
- * process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY,
- * {
- * global: {
- * headers: {
- * Authorization: `Bearer ${supabaseAccessToken}`,
- * },
- * },
- * }
- * )
- * // Now you can query with RLS enabled.
- * const { data, error } = await supabase.from("users").select("*")
- * ```
- *
- * ### Usage with TypeScript
- *
- * You can pass types that were generated with the Supabase CLI to the Supabase Client to get enhanced type safety and auto-completion.
- *
- * Creating a new supabase client object:
- *
- * ```tsx
- * import { createClient } from "@supabase/supabase-js"
- * import { Database } from "../database.types"
- *
- * const supabase = createClient
()
- * ```
- *
- * #### Extend the session type with the `supabaseAccessToken`
- *
- * In order to extend the `session` object with the `supabaseAccessToken` we need to extend the `session` interface in a `types/next-auth.d.ts` file:
- *
- * ```ts title="types/next-auth.d.ts"
- * import NextAuth, { DefaultSession } from "next-auth"
- *
- * declare module "next-auth" {
- * // Returned by `useSession`, `getSession` and received as a prop on the `SessionProvider` React Context
- * interface Session {
- * // A JWT which can be used as Authorization header with supabase-js for RLS.
- * supabaseAccessToken?: string
- * user: {
- * // The user's postal address
- * address: string
- * } & DefaultSession["user"]
- * }
- * }
- * ```
- */
export function SupabaseAdapter(options: SupabaseAdapterOptions): Adapter {
const { url, secret } = options
const supabase = createClient(url, secret, {
diff --git a/packages/adapter-surrealdb/src/index.ts b/packages/adapter-surrealdb/src/index.ts
index 56b6d91e75..2110b23d6e 100644
--- a/packages/adapter-surrealdb/src/index.ts
+++ b/packages/adapter-surrealdb/src/index.ts
@@ -1,8 +1,8 @@
/**
*
*
@@ -118,89 +118,6 @@ export const toId = (surrealId: string) => {
return surrealId.replace(/^⟨(.+)⟩$/, "$1")
}
-/**
- * ## Setup
- *
- * The SurrealDB adapter does not handle connections automatically, so you will have to make sure that you pass the Adapter a `SurrealDBClient` that is connected already. Below you can see an example how to do this.
- *
- * ### Add the SurrealDB client
- *
- * #### Option 1/2 – Using RPC:
- *
- * ```js
- * import { Surreal } from "surrealdb.js";
- *
- * const connectionString = "http://0.0.0.0:8000"
- * const username = ""
- * const password = ""
- * const namespace = ""
- * const database = ""
- *
- * const clientPromise = new Promise(async (resolve, reject) => {
- * const db = new Surreal();
- * try {
- * await db.connect(`${connectionString}/rpc`, {
- * namespace,
- * database,
- * auth: { username, password }
- * })
- * resolve(db)
- * } catch (e) {
- * reject(e)
- * }
- * })
- *
- * // Export a module-scoped MongoClient promise. By doing this in a
- * // separate module, the client can be shared across functions.
- * export default clientPromise
- * ```
- *
- * #### Option 2/2 – Using HTTP:
- *
- * Usefull in serverlees environments like Vercel.
- *
- * ```js
- * import { ExperimentalSurrealHTTP } from "surrealdb.js"
- *
- * const connectionString = "http://0.0.0.0:8000"
- * const username = ""
- * const password = ""
- * const namespace = ""
- * const database = ""
- *
- * const clientPromise = new Promise>(async (resolve, reject) => {
- * try {
- * const db = new ExperimentalSurrealHTTP(connectionString, {
- * fetch,
- * namespace,
- * database,
- * auth: { username, password }
- * })
- * resolve(db)
- * } catch (e) {
- * reject(e)
- * }
- * })
- *
- * // Export a module-scoped MongoClient promise. By doing this in a
- * // separate module, the client can be shared across functions.
- * export default clientPromise
- * ```
- *
- * ### Configure Auth.js
- *
- * ```js
- * import NextAuth from "next-auth"
- * import { SurrealDBAdapter } from "@auth/surrealdb-adapter"
- * import clientPromise from "../../../lib/surrealdb"
- *
- * // For more information on each option (and a full list of options) go to
- * // https://authjs.dev/reference/providers/oauth
- * export default NextAuth({
- * adapter: SurrealDBAdapter(clientPromise),
- * })
- * ```
- **/
export function SurrealDBAdapter(
client: Promise>
// options = {}
diff --git a/packages/adapter-typeorm/src/index.ts b/packages/adapter-typeorm/src/index.ts
index 3e6b0c1c20..0cb2ad6f3f 100644
--- a/packages/adapter-typeorm/src/index.ts
+++ b/packages/adapter-typeorm/src/index.ts
@@ -1,6 +1,6 @@
/**
*
- *
Official TypeORM adapter for Auth.js / NextAuth.js.
+ *
Official TypeORM adapter for Auth.js / NextAuth.js.
*
*
*
@@ -64,218 +64,6 @@ export async function getManager(options: {
return manager
}
-/**
- * ## Setup
- *
- * Configure Auth.js to use the TypeORM Adapter:
- *
- * ```ts title="pages/api/auth/[...nextauth].ts"
- * import NextAuth from "next-auth"
- * import { TypeORMAdapter } from "@auth/typeorm-adapter"
- *
- * export default NextAuth({
- * adapter: TypeORMAdapter("yourconnectionstring"),
- * })
- * ```
- *
- * `TypeORMAdapter` takes either a connection string, or a [`ConnectionOptions`](https://github.com/typeorm/typeorm/blob/master/docs/connection-options.md) object as its first parameter.
- *
- * ## Advanced usage
- *
- * ### Custom models
- *
- * The TypeORM adapter uses [`Entity` classes](https://github.com/typeorm/typeorm/blob/master/docs/entities.md) to define the shape of your data.
- *
- * If you want to override the default entities (for example to add a `role` field to your `UserEntity`), you will have to do the following:
- *
- * 1. Create a file containing your modified entities:
- *
- * (The file below is based on the [default entities](https://github.com/nextauthjs/next-auth/blob/main/packages/adapter-typeorm/src/entities.ts))
- *
- * ```ts title="lib/entities.ts" {37-38}
- * import {
- * Entity,
- * PrimaryGeneratedColumn,
- * Column,
- * ManyToOne,
- * OneToMany,
- * ValueTransformer,
- * } from "typeorm"
- *
- * const transformer: Record<"date" | "bigint", ValueTransformer> = {
- * date: {
- * from: (date: string | null) => date && new Date(parseInt(date, 10)),
- * to: (date?: Date) => date?.valueOf().toString(),
- * },
- * bigint: {
- * from: (bigInt: string | null) => bigInt && parseInt(bigInt, 10),
- * to: (bigInt?: number) => bigInt?.toString(),
- * },
- * }
- *
- * @Entity({ name: "users" })
- * export class UserEntity {
- * @PrimaryGeneratedColumn("uuid")
- * id!: string
- *
- * @Column({ type: "varchar", nullable: true })
- * name!: string | null
- *
- * @Column({ type: "varchar", nullable: true, unique: true })
- * email!: string | null
- *
- * @Column({ type: "varchar", nullable: true, transformer: transformer.date })
- * emailVerified!: string | null
- *
- * @Column({ type: "varchar", nullable: true })
- * image!: string | null
- *
- * @Column({ type: "varchar", nullable: true })
- * role!: string | null
- *
- * @OneToMany(() => SessionEntity, (session) => session.userId)
- * sessions!: SessionEntity[]
- *
- * @OneToMany(() => AccountEntity, (account) => account.userId)
- * accounts!: AccountEntity[]
- * }
- *
- * @Entity({ name: "accounts" })
- * export class AccountEntity {
- * @PrimaryGeneratedColumn("uuid")
- * id!: string
- *
- * @Column({ type: "uuid" })
- * userId!: string
- *
- * @Column()
- * type!: string
- *
- * @Column()
- * provider!: string
- *
- * @Column()
- * providerAccountId!: string
- *
- * @Column({ type: "varchar", nullable: true })
- * refresh_token!: string | null
- *
- * @Column({ type: "varchar", nullable: true })
- * access_token!: string | null
- *
- * @Column({
- * nullable: true,
- * type: "bigint",
- * transformer: transformer.bigint,
- * })
- * expires_at!: number | null
- *
- * @Column({ type: "varchar", nullable: true })
- * token_type!: string | null
- *
- * @Column({ type: "varchar", nullable: true })
- * scope!: string | null
- *
- * @Column({ type: "varchar", nullable: true })
- * id_token!: string | null
- *
- * @Column({ type: "varchar", nullable: true })
- * session_state!: string | null
- *
- * @Column({ type: "varchar", nullable: true })
- * oauth_token_secret!: string | null
- *
- * @Column({ type: "varchar", nullable: true })
- * oauth_token!: string | null
- *
- * @ManyToOne(() => UserEntity, (user) => user.accounts, {
- * createForeignKeyConstraints: true,
- * })
- * user!: UserEntity
- * }
- *
- * @Entity({ name: "sessions" })
- * export class SessionEntity {
- * @PrimaryGeneratedColumn("uuid")
- * id!: string
- *
- * @Column({ unique: true })
- * sessionToken!: string
- *
- * @Column({ type: "uuid" })
- * userId!: string
- *
- * @Column({ transformer: transformer.date })
- * expires!: string
- *
- * @ManyToOne(() => UserEntity, (user) => user.sessions)
- * user!: UserEntity
- * }
- *
- * @Entity({ name: "verification_tokens" })
- * export class VerificationTokenEntity {
- * @PrimaryGeneratedColumn("uuid")
- * id!: string
- *
- * @Column()
- * token!: string
- *
- * @Column()
- * identifier!: string
- *
- * @Column({ transformer: transformer.date })
- * expires!: string
- * }
- * ```
- *
- * 2. Pass them to `TypeORMAdapter`
- *
- * ```js title="pages/api/auth/[...nextauth].js"
- * import NextAuth from "next-auth"
- * import { TypeORMAdapter } from "@auth/typeorm-adapter"
- * import * as entities from "lib/entities"
- *
- * export default NextAuth({
- * adapter: TypeORMAdapter("yourconnectionstring", { entities })
- * })
- * ```
- *
- * :::tip Synchronize your database
- * The `synchronize: true` option in TypeORM will generate SQL that exactly matches the entities. This will automatically apply any changes it finds in the entity model. This is a useful option in development.
- * :::
- *
- * :::warning Using synchronize in production
- * The option `synchronize: true` should not be enabled against production databases as it may cause data loss if the configured schema does not match the expected schema! We recommend that you synchronize/migrate your production database at build-time.
- * :::
- *
- * ### Naming Conventions
- *
- * If mixed snake_case and camelCase column names are an issue for you and/or your underlying database system, we recommend using TypeORM's naming strategy feature to change the target field names. There is a package called `typeorm-naming-strategies` which includes a `snake_case` strategy which will translate the fields from how Auth.js expects them, to snake_case in the actual database.
- *
- * For example, you can add the naming convention option to the connection object in your NextAuth config.
- *
- * ```js title="pages/api/auth/[...nextauth].js"
- * import NextAuth from "next-auth"
- * import { TypeORMAdapter } from "@auth/typeorm-adapter"
- * import { SnakeNamingStrategy } from 'typeorm-naming-strategies'
- * import { ConnectionOptions } from "typeorm"
- *
- * const connection: ConnectionOptions = {
- * type: "mysql",
- * host: "localhost",
- * port: 3306,
- * username: "test",
- * password: "test",
- * database: "test",
- * namingStrategy: new SnakeNamingStrategy()
- * }
- *
- * export default NextAuth({
- * adapter: TypeORMAdapter(connection)
- * })
- * ```
- *
- */
export function TypeORMAdapter(
dataSource: string | DataSourceOptions,
options?: TypeORMAdapterOptions
diff --git a/packages/adapter-unstorage/src/index.ts b/packages/adapter-unstorage/src/index.ts
index f909ec8d42..27f39ff775 100644
--- a/packages/adapter-unstorage/src/index.ts
+++ b/packages/adapter-unstorage/src/index.ts
@@ -1,6 +1,6 @@
/**
*
- *
Official Unstorage adapter for Auth.js / NextAuth.js.
+ *
Official Unstorage adapter for Auth.js / NextAuth.js.
*
*
*
@@ -101,80 +101,6 @@ export function hydrateDates(json: object) {
}, {} as any)
}
-/**
- * ## Setup
- *
- * Configure Auth.js to use the Unstorage Adapter.
- *
- * ```js title="pages/api/auth/[...nextauth].js"
- * import NextAuth from "next-auth"
- * import GoogleProvider from "next-auth/providers/google"
- * import { UnstorageAdapter } from "@auth/unstorage-adapter"
- * import { createStorage } from "unstorage";
- *
- * const storage = createStorage();
- *
- * export default NextAuth({
- * adapter: UnstorageAdapter(storage),
- * providers: [
- * GoogleProvider({
- * clientId: process.env.GOOGLE_CLIENT_ID,
- * clientSecret: process.env.GOOGLE_CLIENT_SECRET,
- * }),
- * ],
- * })
- * ```
- *
- * ## Advanced usage
- *
- * ### Using multiple apps with a single storage
- *
- * If you have multiple Auth.js connected apps using the same storage, you need different key prefixes for every app.
- *
- * You can change the prefixes by passing an `options` object as the second argument to the adapter factory function.
- *
- * The default values for this object are:
- *
- * ```js
- * const defaultOptions = {
- * baseKeyPrefix: "",
- * accountKeyPrefix: "user:account:",
- * accountByUserIdPrefix: "user:account:by-user-id:",
- * emailKeyPrefix: "user:email:",
- * sessionKeyPrefix: "user:session:",
- * sessionByUserIdKeyPrefix: "user:session:by-user-id:",
- * userKeyPrefix: "user:",
- * verificationTokenKeyPrefix: "user:token:",
- * authenticatorKeyPrefix: "authenticator:id:",
- * authenticatorUserKeyPrefix: "authenticator:by-user-id:",
- * }
- * ```
- *
- * Usually changing the `baseKeyPrefix` should be enough for this scenario, but for more custom setups, you can also change the prefixes of every single key.
- *
- * Example:
- *
- * ```js
- * export default NextAuth({
- * adapter: UnstorageAdapter(storage, {baseKeyPrefix: "app2:"})
- * })
- * ```
- *
- * ### Using getItemRaw/setItemRaw instead of getItem/setItem
- *
- * If you are using storage that supports JSON, you can make it use `getItemRaw/setItemRaw` instead of `getItem/setItem`.
- *
- * This is an experimental feature. Please check [unjs/unstorage#142](https://github.com/unjs/unstorage/issues/142) for more information.
- *
- * You can enable this functionality by passing `useItemRaw: true` (default: false) in the `options` object as the second argument to the adapter factory function.
- *
- * ```js
- * export default NextAuth({
- * adapter: UnstorageAdapter(storage, {useItemRaw: true})
- * })
- * ```
- *
- */
export function UnstorageAdapter(
storage: Storage,
options: UnstorageAdapterOptions = {}
diff --git a/packages/adapter-upstash-redis/src/index.ts b/packages/adapter-upstash-redis/src/index.ts
index 6f044768a7..656b401ee2 100644
--- a/packages/adapter-upstash-redis/src/index.ts
+++ b/packages/adapter-upstash-redis/src/index.ts
@@ -1,6 +1,6 @@
/**
*
- *
Official Upstash Redis adapter for Auth.js / NextAuth.js.
+ *
Official Upstash Redis adapter for Auth.js / NextAuth.js.
*
*
*
@@ -83,64 +83,6 @@ export function hydrateDates(json: object) {
}, {} as any)
}
-/**
- * ## Setup
- *
- * Configure Auth.js to use the Upstash Redis Adapter:
- *
- * ```js title="pages/api/auth/[...nextauth].js"
- * import NextAuth from "next-auth"
- * import GoogleProvider from "next-auth/providers/google"
- * import { UpstashRedisAdapter } from "@auth/upstash-redis-adapter"
- * import upstashRedisClient from "@upstash/redis"
- *
- * const redis = upstashRedisClient(
- * process.env.UPSTASH_REDIS_URL,
- * process.env.UPSTASH_REDIS_TOKEN
- * )
- *
- * export default NextAuth({
- * adapter: UpstashRedisAdapter(redis),
- * providers: [
- * GoogleProvider({
- * clientId: process.env.GOOGLE_CLIENT_ID,
- * clientSecret: process.env.GOOGLE_CLIENT_SECRET,
- * }),
- * ],
- * })
- * ```
- *
- * ## Advanced usage
- *
- * ### Using multiple apps with a single Upstash Redis instance
- *
- * The Upstash free-tier allows for only one Redis instance. If you have multiple Auth.js connected apps using this instance, you need different key prefixes for every app.
- *
- * You can change the prefixes by passing an `options` object as the second argument to the adapter factory function.
- *
- * The default values for this object are:
- *
- * ```js
- * const defaultOptions = {
- * baseKeyPrefix: "",
- * accountKeyPrefix: "user:account:",
- * accountByUserIdPrefix: "user:account:by-user-id:",
- * emailKeyPrefix: "user:email:",
- * sessionKeyPrefix: "user:session:",
- * sessionByUserIdKeyPrefix: "user:session:by-user-id:",
- * userKeyPrefix: "user:",
- * verificationTokenKeyPrefix: "user:token:",
- * }
- * ```
- *
- * Usually changing the `baseKeyPrefix` should be enough for this scenario, but for more custom setups, you can also change the prefixes of every single key.
- *
- * ```js
- * export default NextAuth({
- * adapter: UpstashRedisAdapter(redis, {baseKeyPrefix: "app2:"})
- * })
- * ```
- */
export function UpstashRedisAdapter(
client: Redis,
options: UpstashRedisAdapterOptions = {}
diff --git a/packages/adapter-xata/src/index.ts b/packages/adapter-xata/src/index.ts
index 2f9a4640ba..09cd813b86 100644
--- a/packages/adapter-xata/src/index.ts
+++ b/packages/adapter-xata/src/index.ts
@@ -1,6 +1,6 @@
/**
*
- *
Official Xata adapter for Auth.js / NextAuth.js.
+ *
Official Xata adapter for Auth.js / NextAuth.js.
*
*
*
@@ -30,222 +30,8 @@
*/
import type { Adapter } from "@auth/core/adapters"
-
import type { XataClient } from "./xata"
-/**
- * ## Setup
- *
- * This adapter allows using Auth.js with Xata as a database to store users, sessions, and more. The preferred way to create a Xata project and use Xata databases is using the [Xata Command Line Interface (CLI)](https://docs.xata.io/cli/getting-started).
- *
- * The CLI allows generating a `XataClient` that will help you work with Xata in a safe way, and that this adapter depends on.
- *
- * When you're ready, let's create a new Xata project using our Auth.js schema that the Xata adapter can work with. To do that, copy and paste this schema file into your project's directory:
- *
- * ```json title="schema.json"
- * {
- * "tables": [
- * {
- * "name": "nextauth_users",
- * "columns": [
- * {
- * "name": "email",
- * "type": "email"
- * },
- * {
- * "name": "emailVerified",
- * "type": "datetime"
- * },
- * {
- * "name": "name",
- * "type": "string"
- * },
- * {
- * "name": "image",
- * "type": "string"
- * }
- * ]
- * },
- * {
- * "name": "nextauth_accounts",
- * "columns": [
- * {
- * "name": "user",
- * "type": "link",
- * "link": {
- * "table": "nextauth_users"
- * }
- * },
- * {
- * "name": "type",
- * "type": "string"
- * },
- * {
- * "name": "provider",
- * "type": "string"
- * },
- * {
- * "name": "providerAccountId",
- * "type": "string"
- * },
- * {
- * "name": "refresh_token",
- * "type": "string"
- * },
- * {
- * "name": "access_token",
- * "type": "string"
- * },
- * {
- * "name": "expires_at",
- * "type": "int"
- * },
- * {
- * "name": "token_type",
- * "type": "string"
- * },
- * {
- * "name": "scope",
- * "type": "string"
- * },
- * {
- * "name": "id_token",
- * "type": "text"
- * },
- * {
- * "name": "session_state",
- * "type": "string"
- * }
- * ]
- * },
- * {
- * "name": "nextauth_verificationTokens",
- * "columns": [
- * {
- * "name": "identifier",
- * "type": "string"
- * },
- * {
- * "name": "token",
- * "type": "string"
- * },
- * {
- * "name": "expires",
- * "type": "datetime"
- * }
- * ]
- * },
- * {
- * "name": "nextauth_users_accounts",
- * "columns": [
- * {
- * "name": "user",
- * "type": "link",
- * "link": {
- * "table": "nextauth_users"
- * }
- * },
- * {
- * "name": "account",
- * "type": "link",
- * "link": {
- * "table": "nextauth_accounts"
- * }
- * }
- * ]
- * },
- * {
- * "name": "nextauth_users_sessions",
- * "columns": [
- * {
- * "name": "user",
- * "type": "link",
- * "link": {
- * "table": "nextauth_users"
- * }
- * },
- * {
- * "name": "session",
- * "type": "link",
- * "link": {
- * "table": "nextauth_sessions"
- * }
- * }
- * ]
- * },
- * {
- * "name": "nextauth_sessions",
- * "columns": [
- * {
- * "name": "sessionToken",
- * "type": "string"
- * },
- * {
- * "name": "expires",
- * "type": "datetime"
- * },
- * {
- * "name": "user",
- * "type": "link",
- * "link": {
- * "table": "nextauth_users"
- * }
- * }
- * ]
- * }
- * ]
- * }
- * ```
- *
- * Now, run the following command:
- *
- * ```bash
- * xata init --schema=./path/to/your/schema.json
- * ```
- *
- * The CLI will walk you through a setup process where you choose a [workspace](https://xata.io/docs/api-reference/workspaces) (kind of like a GitHub org or a Vercel team) and an appropriate database. We recommend using a fresh database for this, as we'll augment it with tables that Auth.js needs.
- *
- * Once you're done, you can continue using Auth.js in your project as expected, like creating a `./pages/api/auth/[...nextauth]` route.
- *
- * ```ts title="pages/api/auth/[...nextauth].ts"
- * import NextAuth from "next-auth"
- * import GoogleProvider from "next-auth/providers/google"
- *
- * const client = new XataClient()
- *
- * export default NextAuth({
- * providers: [
- * GoogleProvider({
- * clientId: process.env.GOOGLE_CLIENT_ID,
- * clientSecret: process.env.GOOGLE_CLIENT_SECRET,
- * }),
- * ],
- * })
- * ```
- *
- * Now to Xata-fy this route, let's add the Xata client and adapter:
- *
- * ```diff
- * import NextAuth from "next-auth"
- * import GoogleProvider from "next-auth/providers/google"
- * + import { XataAdapter } from "@auth/xata-adapter"
- * + import { XataClient } from "../../../xata" // or wherever you've chosen to create the client
- *
- * + const client = new XataClient()
- *
- * export default NextAuth({
- * + adapter: XataAdapter(client),
- * providers: [
- * GoogleProvider({
- * clientId: process.env.GOOGLE_CLIENT_ID,
- * clientSecret: process.env.GOOGLE_CLIENT_SECRET,
- * }),
- * ],
- * })
- * ```
- *
- * This fully sets up your Auth.js app to work with Xata.
- */
export function XataAdapter(client: XataClient): Adapter {
return {
async createUser(user) {
diff --git a/packages/core/test/e2e/basic-auth.spec.ts b/packages/core/test/e2e/basic-auth.spec.ts
index fc33bf9559..681e082c9f 100644
--- a/packages/core/test/e2e/basic-auth.spec.ts
+++ b/packages/core/test/e2e/basic-auth.spec.ts
@@ -14,10 +14,6 @@ test.describe("Basic Auth", () => {
user: {
email: "test@example.com",
name: "Test User",
- sub: expect.any(String),
- iat: expect.any(Number),
- exp: expect.any(Number),
- jti: expect.any(String),
},
expires: expect.any(String),
})
@@ -58,11 +54,7 @@ test.describe("Basic Auth", () => {
user: {
email: "bob@alice.com",
name: "Bob Alice",
- picture: "https://avatars.githubusercontent.com/u/67470890?s=200&v=4",
- sub: expect.any(String),
- iat: expect.any(Number),
- exp: expect.any(Number),
- jti: expect.any(String),
+ image: "https://avatars.githubusercontent.com/u/67470890?s=200&v=4",
},
expires: expect.any(String),
})
From 5136b3fc005d7fa655e8969beffacfef8fbff625 Mon Sep 17 00:00:00 2001
From: Nico Domino
Date: Thu, 9 May 2024 12:37:08 +0200
Subject: [PATCH 08/44] chore(typeorm): cleanup adapter testing files (#10833)
---
.../test/mysql-multi-project-schema/test.sh | 1 -
.../test/pg-multi-project-schema/test.sh | 1 -
packages/adapter-drizzle/test/pg/test.sh | 1 -
packages/adapter-drizzle/test/sqlite/test.sh | 3 --
packages/adapter-typeorm/package.json | 10 +++---
packages/adapter-typeorm/test/init.sh | 30 ----------------
packages/adapter-typeorm/test/mysql/test.sh | 34 +++++++++++++++---
.../adapter-typeorm/test/postgresql/test.sh | 35 ++++++++++++++++---
packages/adapter-typeorm/test/sqlite/test.sh | 14 ++++++--
packages/adapter-typeorm/test/test.sh | 35 -------------------
10 files changed, 77 insertions(+), 87 deletions(-)
delete mode 100755 packages/adapter-typeorm/test/init.sh
delete mode 100755 packages/adapter-typeorm/test/test.sh
diff --git a/packages/adapter-drizzle/test/mysql-multi-project-schema/test.sh b/packages/adapter-drizzle/test/mysql-multi-project-schema/test.sh
index 6785032f94..7f1e5aa78e 100755
--- a/packages/adapter-drizzle/test/mysql-multi-project-schema/test.sh
+++ b/packages/adapter-drizzle/test/mysql-multi-project-schema/test.sh
@@ -18,7 +18,6 @@ echo "Waiting 10s for db to start..." && sleep 10
# Push schema and seed
drizzle-kit generate:mysql --config=./test/mysql-multi-project-schema/drizzle.config.ts
-NODE_OPTIONS='--import tsx'
tsx ./test/mysql-multi-project-schema/migrator.ts
if vitest run -c ../utils/vitest.config.ts ./test/mysql-multi-project-schema/index.test.ts; then
diff --git a/packages/adapter-drizzle/test/pg-multi-project-schema/test.sh b/packages/adapter-drizzle/test/pg-multi-project-schema/test.sh
index 08689093fe..66acddac31 100755
--- a/packages/adapter-drizzle/test/pg-multi-project-schema/test.sh
+++ b/packages/adapter-drizzle/test/pg-multi-project-schema/test.sh
@@ -21,7 +21,6 @@ echo "Waiting 5s for db to start..." && sleep 5
# Push schema and seed
drizzle-kit generate:pg --config=./test/pg-multi-project-schema/drizzle.config.ts
-NODE_OPTIONS='--import tsx'
tsx ./test/pg-multi-project-schema/migrator.ts
if vitest run -c ../utils/vitest.config.ts ./test/pg-multi-project-schema/index.test.ts; then
diff --git a/packages/adapter-drizzle/test/pg/test.sh b/packages/adapter-drizzle/test/pg/test.sh
index 3c46a8f0fd..72441cf233 100755
--- a/packages/adapter-drizzle/test/pg/test.sh
+++ b/packages/adapter-drizzle/test/pg/test.sh
@@ -21,7 +21,6 @@ echo "Waiting 5s for db to start..." && sleep 5
# Push schema and seed
drizzle-kit generate:pg --config=./test/pg/drizzle.config.ts
-NODE_OPTIONS='--import tsx'
tsx ./test/pg/migrator.ts
if vitest run -c ../utils/vitest.config.ts ./test/pg/index.test.ts; then
diff --git a/packages/adapter-drizzle/test/sqlite/test.sh b/packages/adapter-drizzle/test/sqlite/test.sh
index acea7dcbab..3959b2e94d 100755
--- a/packages/adapter-drizzle/test/sqlite/test.sh
+++ b/packages/adapter-drizzle/test/sqlite/test.sh
@@ -7,11 +7,8 @@ echo "Running SQLite tests."
rm -f db.sqlite
drizzle-kit generate:sqlite --config=./test/sqlite/drizzle.config.ts
-NODE_OPTIONS='--import tsx'
tsx ./test/sqlite/migrator.ts
-vitest run -c ../utils/vitest.config.ts ./test/sqlite/index.test.ts
-
if vitest run -c ../utils/vitest.config.ts ./test/sqlite/index.test.ts; then
rm -f db.sqlite
else
diff --git a/packages/adapter-typeorm/package.json b/packages/adapter-typeorm/package.json
index fd2e743de8..3f30f66124 100644
--- a/packages/adapter-typeorm/package.json
+++ b/packages/adapter-typeorm/package.json
@@ -39,12 +39,10 @@
"build": "tsc",
"dev": "tsc -w",
"clean": "rm -rf dist",
- "init:db": "test/init.sh",
- "mysql": "pnpm init:db && test/mysql/test.sh",
- "postgres": "pnpm init:db && test/postgresql/test.sh",
- "sqlite": "test/sqlite/test.sh",
- "test:containers": "test/test.sh",
- "test": "test/test.sh"
+ "test": "pnpm test:mysql && pnpm test:sqlite && pnpm test:pg",
+ "test:mysql": "pnpm clean && ./test/mysql/test.sh",
+ "test:pg": "pnpm clean && ./test/postgresql/test.sh",
+ "test:sqlite": "pnpm clean && ./test/sqlite/test.sh"
},
"dependencies": {
"@auth/core": "workspace:*"
diff --git a/packages/adapter-typeorm/test/init.sh b/packages/adapter-typeorm/test/init.sh
deleted file mode 100755
index 430883d386..0000000000
--- a/packages/adapter-typeorm/test/init.sh
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/usr/bin/env bash
-
-# Init PostgreSQL container
-echo "Initializing container for PostgreSQL tests"
-
-PGUSER=nextauth
-PGDATABASE=nextauth
-PG_CONTAINER_NAME=next-auth-postgres-test
-
-docker run -d --rm \
- -e POSTGRES_USER=${PGUSER} \
- -e POSTGRES_DB=${PGDATABASE} \
- -e POSTGRES_HOST_AUTH_METHOD=trust \
- --name "${PG_CONTAINER_NAME}" \
- -p 5432:5432 \
- postgres:13.3
-
-# Init MyDQL container
-echo "Initializing container for MySQL tests"
-
-MYSQL_DATABASE=next-auth
-MYSQL_ROOT_PASSWORD=password
-MYSQL_CONTAINER_NAME=next-auth-mysql-test
-
-docker run -d --rm \
- -e MYSQL_DATABASE=${MYSQL_DATABASE} \
- -e MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} \
- --name "${MYSQL_CONTAINER_NAME}" \
- -p 3306:3306 \
- mysql:8 --default-authentication-plugin=mysql_native_password
diff --git a/packages/adapter-typeorm/test/mysql/test.sh b/packages/adapter-typeorm/test/mysql/test.sh
index a052bd4dea..3257b9cefc 100755
--- a/packages/adapter-typeorm/test/mysql/test.sh
+++ b/packages/adapter-typeorm/test/mysql/test.sh
@@ -1,13 +1,39 @@
#!/usr/bin/env bash
set -eu
-echo "Waiting 5s for db to start..."
-sleep 5
+# Init MySQL container
+echo "Initializing container for MySQL tests"
+MYSQL_DATABASE=next-auth
+MYSQL_ROOT_PASSWORD=password
+MYSQL_CONTAINER_NAME=next-auth-mysql-test
+
+function startDatabase {
+ docker run -d --rm \
+ -e MYSQL_DATABASE=${MYSQL_DATABASE} \
+ -e MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} \
+ --name "${MYSQL_CONTAINER_NAME}" \
+ -p 3306:3306 \
+ mysql:8 --default-authentication-plugin=mysql_native_password
+
+ echo "Waiting 5s for db to start..."
+ sleep 5
+}
+
+startDatabase
echo "Started running MySQL tests with default models."
-vitest run -c ../utils/vitest.config.ts mysql/index.test.ts
+if vitest run -c ../utils/vitest.config.ts mysql/index.test.ts; then
+ docker stop ${MYSQL_CONTAINER_NAME}
+else
+ docker stop ${MYSQL_CONTAINER_NAME} && exit 1
+fi
echo "Finished running MySQL tests with default models."
+startDatabase
echo "Started running MySQL tests with custom models."
-CUSTOM_MODEL=1 vitest run -c ../utils/vitest.config.ts mysql/index.custom.test.ts
+if CUSTOM_MODEL=1 vitest run -c ../utils/vitest.config.ts mysql/index.custom.test.ts; then
+ docker stop ${MYSQL_CONTAINER_NAME}
+else
+ docker stop ${MYSQL_CONTAINER_NAME} && exit 1
+fi
echo "Finished running MySQL tests with custom models."
diff --git a/packages/adapter-typeorm/test/postgresql/test.sh b/packages/adapter-typeorm/test/postgresql/test.sh
index 8f34a3236a..9368fb55e6 100755
--- a/packages/adapter-typeorm/test/postgresql/test.sh
+++ b/packages/adapter-typeorm/test/postgresql/test.sh
@@ -1,13 +1,40 @@
#!/usr/bin/env bash
set -eu
-echo "Waiting 5s for db to start..."
-sleep 5
+# Init PostgreSQL container
+echo "Initializing container for PostgreSQL tests"
+PGUSER=nextauth
+PGDATABASE=nextauth
+PG_CONTAINER_NAME=next-auth-postgres-test
+
+function startDatabase {
+ docker run -d --rm \
+ -e POSTGRES_USER=${PGUSER} \
+ -e POSTGRES_DB=${PGDATABASE} \
+ -e POSTGRES_HOST_AUTH_METHOD=trust \
+ --name "${PG_CONTAINER_NAME}" \
+ -p 5432:5432 \
+ postgres:13.3
+
+ echo "Waiting 5s for db to start..."
+ sleep 5
+}
+
+startDatabase
echo "Started running PostgreSQL tests with default models."
-vitest run -c ../utils/vitest.config.ts postgresql/index.test.ts
+if vitest run -c ../utils/vitest.config.ts postgresql/index.test.ts; then
+ docker stop ${PG_CONTAINER_NAME}
+else
+ docker stop ${PG_CONTAINER_NAME} && exit 1
+fi
echo "Finished running PostgreSQL tests with default models."
+startDatabase
echo "Started running PostgreSQL tests with custom models."
-CUSTOM_MODEL=1 vitest run -c ../utils/vitest.config.ts postgresql/index.custom.test.ts
+if CUSTOM_MODEL=1 vitest run -c ../utils/vitest.config.ts postgresql/index.custom.test.ts; then
+ docker stop ${PG_CONTAINER_NAME}
+else
+ docker stop ${PG_CONTAINER_NAME} && exit 1
+fi
echo "Finished running PostgreSQL tests with custom models."
diff --git a/packages/adapter-typeorm/test/sqlite/test.sh b/packages/adapter-typeorm/test/sqlite/test.sh
index 8ffbf3f5b1..8c8f1f7bf5 100755
--- a/packages/adapter-typeorm/test/sqlite/test.sh
+++ b/packages/adapter-typeorm/test/sqlite/test.sh
@@ -4,11 +4,21 @@ set -eu
rm -f test/sqlite/dev.db
echo "Started running SQLite tests with default models."
-vitest run -c ../utils/vitest.config.ts sqlite/index.test.ts
+if vitest run -c ../utils/vitest.config.ts sqlite/index.test.ts; then
+ rm -f db.sqlite
+else
+ rm -f db.sqlite && exit 1
+fi
echo "Finished running SQLite tests with default models."
rm -f test/sqlite/dev.db
echo "Started running SQLite tests with custom models."
-CUSTOM_MODEL=1 vitest run -c ../utils/vitest.config.ts sqlite/index.custom.test.ts
+if CUSTOM_MODEL=1 vitest run -c ../utils/vitest.config.ts sqlite/index.custom.test.ts; then
+ rm -f db.sqlite
+else
+ rm -f db.sqlite && exit 1
+fi
echo "Finished running SQLite tests with custom models."
+
+rm -f test/sqlite/dev.db
diff --git a/packages/adapter-typeorm/test/test.sh b/packages/adapter-typeorm/test/test.sh
deleted file mode 100755
index 96a6737e49..0000000000
--- a/packages/adapter-typeorm/test/test.sh
+++ /dev/null
@@ -1,35 +0,0 @@
-#! /usr/bin/env bash
-#
-# Run parallel commands and fail if any of them fails.
-# shellcheck disable=SC2046
-# Based on: https://gist.github.com/mjambon/79adfc5cf6b11252e78b75df50793f24#gistcomment-3861511
-
-set -eu
-
-pids=()
-
-./test/init.sh
-
-./test/sqlite/test.sh & pids+=($!)
-
-./test/postgresql/test.sh & pids+=($!)
-
-./test/mysql/test.sh & pids+=($!)
-
-for _ in "${pids[@]}"; do
- if wait -n; then
- :
- else
- status=$?
- echo "One of the subprocesses exited with nonzero status $status. Aborting."
- for pid in "${pids[@]}"; do
- # Send a termination signal to all the children, and ignore errors
- # due to children that no longer exist.
- kill "$pid" 2> /dev/null || :
- done
- docker kill $(docker ps -q)
- exit "$status"
- fi
-done
-
-docker kill $(docker ps -q)
From 5bd304369382d2cbb62fbbf3e7d87ee12999073c Mon Sep 17 00:00:00 2001
From: Nico Domino
Date: Thu, 9 May 2024 12:55:03 +0200
Subject: [PATCH 09/44] chore(prisma): cleanup adapter jsdoc (#10862)
---
.../pages/getting-started/adapters/prisma.mdx | 7 +-
packages/adapter-prisma/src/index.ts | 212 ------------------
2 files changed, 4 insertions(+), 215 deletions(-)
diff --git a/docs/pages/getting-started/adapters/prisma.mdx b/docs/pages/getting-started/adapters/prisma.mdx
index e06bac9309..9f44474ed2 100644
--- a/docs/pages/getting-started/adapters/prisma.mdx
+++ b/docs/pages/getting-started/adapters/prisma.mdx
@@ -27,9 +27,10 @@ DATABASE_URL=postgres://postgres:adminadmin@0.0.0.0:5432/db
### Configuration
-
- We recommend using version `@prisma/client@5.9.1` or above if using middleware
- or any other edge runtime(s).
+
+ We recommend using version `@prisma/client@5.12.0` or above if using
+ middleware or any other edge runtime(s). See [edge
+ compatibility](#edge-compatibility) below for more information.
diff --git a/packages/adapter-prisma/src/index.ts b/packages/adapter-prisma/src/index.ts
index 2e53c83690..60fc22fb49 100644
--- a/packages/adapter-prisma/src/index.ts
+++ b/packages/adapter-prisma/src/index.ts
@@ -24,218 +24,6 @@ import type {
AdapterUser,
} from "@auth/core/adapters"
-/**
- * ## Setup
- *
- * Add this adapter to your `auth.ts` Auth.js configuration object:
- *
- * ```js title="auth.ts"
- * import NextAuth from "next-auth"
- * import Google from "next-auth/providers/google"
- * import { PrismaAdapter } from "@auth/prisma-adapter"
- * import { PrismaClient } from "@prisma/client"
- *
- * const prisma = new PrismaClient()
- *
- * export const { handlers, auth, signIn, signOut } = NextAuth({
- * adapter: PrismaAdapter(prisma),
- * providers: [
- * Google,
- * ],
- * })
- * ```
- *
- * ### Create the Prisma schema from scratch
- *
- * You need to use at least Prisma 2.26.0. Create a schema file in `prisma/schema.prisma` similar to this one:
- *
- * > This schema is adapted for use in Prisma and based upon our main [schema](https://authjs.dev/reference/core/adapters#models)
- *
- * ```json title="schema.prisma"
- * datasource db {
- * provider = "postgresql"
- * url = env("DATABASE_URL")
- * shadowDatabaseUrl = env("SHADOW_DATABASE_URL") // Only needed when using a cloud provider that doesn't support the creation of new databases, like Heroku. Learn more: https://pris.ly/d/migrate-shadow
- * }
- *
- * generator client {
- * provider = "prisma-client-js"
- * previewFeatures = ["referentialActions"] // You won't need this in Prisma 3.X or higher.
- * }
- *
- * model Account {
- * id String @id @default(cuid())
- * userId String
- * type String
- * provider String
- * providerAccountId String
- * refresh_token String? @db.Text
- * access_token String? @db.Text
- * expires_at Int?
- * token_type String?
- * scope String?
- * id_token String? @db.Text
- * session_state String?
- *
- * user User @relation(fields: [userId], references: [id], onDelete: Cascade)
- *
- * @@unique([provider, providerAccountId])
- * }
- *
- * model Session {
- * id String @id @default(cuid())
- * sessionToken String @unique
- * userId String
- * expires DateTime
- * user User @relation(fields: [userId], references: [id], onDelete: Cascade)
- * }
- *
- * model User {
- * id String @id @default(cuid())
- * name String?
- * email String? @unique
- * emailVerified DateTime?
- * image String?
- * accounts Account[]
- * sessions Session[]
- * }
- *
- * model VerificationToken {
- * identifier String
- * token String @unique
- * expires DateTime
- *
- * @@unique([identifier, token])
- * }
- * ```
- *
- * :::note
- * When using the MySQL connector for Prisma, the [Prisma `String` type](https://www.prisma.io/docs/reference/api-reference/prisma-schema-reference#string) gets mapped to `varchar(191)` which may not be long enough to store fields such as `id_token` in the `Account` model. This can be avoided by explicitly using the `Text` type with `@db.Text`.
- * :::
- *
- *
- * ### Create the Prisma schema with `prisma migrate`
- *
- * This will create an SQL migration file and execute it:
- *
- * ```
- * npx prisma migrate dev
- * ```
- *
- * Note that you will need to specify your database connection string in the environment variable `DATABASE_URL`. You can do this by setting it in a `.env` file at the root of your project.
- *
- * To learn more about [Prisma Migrate](https://www.prisma.io/migrate), check out the [Migrate docs](https://www.prisma.io/docs/concepts/components/prisma-migrate).
- *
- * ### Generating the Prisma Client
- *
- * Once you have saved your schema, use the Prisma CLI to generate the Prisma Client:
- *
- * ```
- * npx prisma generate
- * ```
- *
- * To configure your database to use the new schema (i.e. create tables and columns) use the `prisma migrate` command:
- *
- * ```
- * npx prisma migrate dev
- * ```
- *
- * ### MongoDB support
- *
- * Prisma supports MongoDB, and so does Auth.js. Following the instructions of the [Prisma documentation](https://www.prisma.io/docs/concepts/database-connectors/mongodb) on the MongoDB connector, things you have to change are:
- *
- * 1. Make sure that the id fields are mapped correctly
- *
- * ```prisma
- * id String @id @default(auto()) @map("_id") @db.ObjectId
- * ```
- *
- * 2. The Native database type attribute to `@db.String` from `@db.Text` and userId to `@db.ObjectId`.
- *
- * ```prisma
- * user_id String @db.ObjectId
- * refresh_token String? @db.String
- * access_token String? @db.String
- * id_token String? @db.String
- * ```
- *
- * Everything else should be the same.
- *
- * ### Naming Conventions
- *
- * If mixed snake_case and camelCase column names is an issue for you and/or your underlying database system, we recommend using Prisma's `@map()`([see the documentation here](https://www.prisma.io/docs/concepts/components/prisma-schema/names-in-underlying-database)) feature to change the field names. This won't affect Auth.js, but will allow you to customize the column names to whichever naming convention you wish.
- *
- * For example, moving to `snake_case` and plural table names.
- *
- * ```json title="schema.prisma"
- * model Account {
- * id String @id @default(cuid())
- * userId String @map("user_id")
- * type String
- * provider String
- * providerAccountId String @map("provider_account_id")
- * refresh_token String? @db.Text
- * access_token String? @db.Text
- * expires_at Int?
- * token_type String?
- * scope String?
- * id_token String? @db.Text
- * session_state String?
- *
- * user User @relation(fields: [userId], references: [id], onDelete: Cascade)
- *
- * @@unique([provider, providerAccountId])
- * @@map("accounts")
- * }
- *
- * model Session {
- * id String @id @default(cuid())
- * sessionToken String @unique @map("session_token")
- * userId String @map("user_id")
- * expires DateTime
- * user User @relation(fields: [userId], references: [id], onDelete: Cascade)
- *
- * @@map("sessions")
- * }
- *
- * model User {
- * id String @id @default(cuid())
- * name String?
- * email String? @unique
- * emailVerified DateTime? @map("email_verified")
- * image String?
- * accounts Account[]
- * sessions Session[]
- * authenticators Authenticator[]
- *
- * @@map("users")
- * }
- *
- * model VerificationToken {
- * identifier String
- * token String @unique
- * expires DateTime
- *
- * @@unique([identifier, token])
- * @@map("verificationtokens")
- * }
- *
- * model Authenticator {
- * id String @id @default(cuid())
- * credentialID String @unique
- * userId String
- * providerAccountId String
- * credentialPublicKey String
- * counter Int
- * credentialDeviceType String
- * credentialBackedUp Boolean
- * transports String?
- *
- * user User @relation(fields: [userId], references: [id], onDelete: Cascade)
- * }
- * ```
- *
- **/
export function PrismaAdapter(
prisma: PrismaClient | ReturnType
): Adapter {
From 05a5cc7adb2844598e22a62c70596a21883e39f0 Mon Sep 17 00:00:00 2001
From: Nico Domino
Date: Thu, 9 May 2024 16:48:32 +0200
Subject: [PATCH 10/44] chore(adapters): cleanup `sqlite3` + `better-sqlite3`
for `libsql` (#10813)
---
apps/dev/nextjs/package.json | 6 +-
packages/adapter-d1/package.json | 2 +-
packages/adapter-drizzle/package.json | 3 +-
.../sqlite-multi-project-schema/schema.ts | 2 +-
.../adapter-drizzle/test/sqlite/schema.ts | 2 +-
packages/adapter-kysely/package.json | 3 +-
packages/adapter-kysely/test/index.test.ts | 2 +-
packages/adapter-typeorm/package.json | 10 +-
.../test/sqlite/index.custom.test.ts | 2 +-
packages/adapter-typeorm/tsconfig.json | 2 +-
packages/utils/vitest.config.ts | 2 +-
pnpm-lock.yaml | 406 ++++++++++++------
12 files changed, 295 insertions(+), 147 deletions(-)
diff --git a/apps/dev/nextjs/package.json b/apps/dev/nextjs/package.json
index 8d84f264b7..d15a52276c 100644
--- a/apps/dev/nextjs/package.json
+++ b/apps/dev/nextjs/package.json
@@ -14,16 +14,16 @@
"dependencies": {
"@auth/prisma-adapter": "workspace:*",
"@prisma/client": "^5",
- "next": "14.2.0-canary.47",
+ "next": "14.2.3",
"next-auth": "workspace:*",
"nodemailer": "^6.9.3",
"react": "^18",
"react-dom": "^18"
},
"devDependencies": {
+ "@libsql/client": "^0.6.0",
"@types/react": "^18.2.23",
"@types/react-dom": "^18.2.8",
- "prisma": "^5",
- "sqlite3": "^5.0.8"
+ "prisma": "^5"
}
}
diff --git a/packages/adapter-d1/package.json b/packages/adapter-d1/package.json
index c23f0e0f5d..fbea6a9fe4 100644
--- a/packages/adapter-d1/package.json
+++ b/packages/adapter-d1/package.json
@@ -47,6 +47,6 @@
"devDependencies": {
"@cloudflare/workers-types": "^4.20230321.0",
"@miniflare/d1": "^2.12.2",
- "better-sqlite3": "^8.6.0"
+ "better-sqlite3": "^9.6.0"
}
}
diff --git a/packages/adapter-drizzle/package.json b/packages/adapter-drizzle/package.json
index 66ab3c7615..fa8849f919 100644
--- a/packages/adapter-drizzle/package.json
+++ b/packages/adapter-drizzle/package.json
@@ -49,11 +49,10 @@
"@auth/core": "workspace:*"
},
"devDependencies": {
- "@types/better-sqlite3": "^7.6.4",
"@types/uuid": "^8.3.3",
- "better-sqlite3": "^9.4.0",
"drizzle-kit": "^0.20.17",
"drizzle-orm": "^0.30.9",
+ "libsql": "^0.3.18",
"mysql2": "^3.9.7",
"postgres": "^3.4.3",
"tsx": "^4.7.0"
diff --git a/packages/adapter-drizzle/test/sqlite-multi-project-schema/schema.ts b/packages/adapter-drizzle/test/sqlite-multi-project-schema/schema.ts
index f65c3449f5..b197f1ede7 100644
--- a/packages/adapter-drizzle/test/sqlite-multi-project-schema/schema.ts
+++ b/packages/adapter-drizzle/test/sqlite-multi-project-schema/schema.ts
@@ -1,6 +1,6 @@
import { AdapterAccountType } from "@auth/core/adapters"
-import Database from "better-sqlite3"
import { drizzle } from "drizzle-orm/better-sqlite3"
+import Database from "libsql"
import {
integer,
primaryKey,
diff --git a/packages/adapter-drizzle/test/sqlite/schema.ts b/packages/adapter-drizzle/test/sqlite/schema.ts
index 0a0f6a461c..dacf274209 100644
--- a/packages/adapter-drizzle/test/sqlite/schema.ts
+++ b/packages/adapter-drizzle/test/sqlite/schema.ts
@@ -1,5 +1,5 @@
import { drizzle } from "drizzle-orm/better-sqlite3"
-import Database from "better-sqlite3"
+import Database from "libsql"
import { defineTables } from "../../src/lib/sqlite.ts"
export const {
diff --git a/packages/adapter-kysely/package.json b/packages/adapter-kysely/package.json
index 7adc43a430..5682ef137f 100644
--- a/packages/adapter-kysely/package.json
+++ b/packages/adapter-kysely/package.json
@@ -40,10 +40,9 @@
"kysely": "^0.26.1"
},
"devDependencies": {
- "@types/better-sqlite3": "^7.6.3",
"@types/pg": "^8.6.5",
- "better-sqlite3": "^8.6.0",
"kysely": "^0.24.2",
+ "libsql": "^0.3.18",
"mysql2": "^3.9.7",
"pg": "^8.10.0"
}
diff --git a/packages/adapter-kysely/test/index.test.ts b/packages/adapter-kysely/test/index.test.ts
index 776b6a600f..40134e039e 100644
--- a/packages/adapter-kysely/test/index.test.ts
+++ b/packages/adapter-kysely/test/index.test.ts
@@ -10,7 +10,7 @@ import {
SqliteDialect,
} from "kysely"
import { createPool } from "mysql2"
-import SqliteDatabase from "better-sqlite3"
+import SqliteDatabase from "libsql"
import { KyselyAdapter, KyselyAuth } from "../src"
import type { Database } from "../src"
diff --git a/packages/adapter-typeorm/package.json b/packages/adapter-typeorm/package.json
index 3f30f66124..876504ba3b 100644
--- a/packages/adapter-typeorm/package.json
+++ b/packages/adapter-typeorm/package.json
@@ -48,21 +48,24 @@
"@auth/core": "workspace:*"
},
"devDependencies": {
+ "libsql": "^0.3.18",
"mssql": "^7.2.1",
"mysql": "^2.18.1",
"pg": "^8.7.3",
- "sqlite3": "^5.0.8",
"typeorm": "0.3.17",
"typeorm-naming-strategies": "^4.1.0"
},
"peerDependencies": {
+ "libsql": "^0.3.18",
"mssql": "^6.2.1 || ^7 || ^8 || ^9",
"mysql": "^2.18.1 || ^3",
"pg": "^8.2.1",
- "sqlite3": "^5.0.2",
"typeorm": "^0.3.7"
},
"peerDependenciesMeta": {
+ "libsql": {
+ "optional": true
+ },
"mysql": {
"optional": true
},
@@ -71,9 +74,6 @@
},
"pg": {
"optional": true
- },
- "sqlite3": {
- "optional": true
}
}
}
diff --git a/packages/adapter-typeorm/test/sqlite/index.custom.test.ts b/packages/adapter-typeorm/test/sqlite/index.custom.test.ts
index 426074e77b..4e9053abb2 100644
--- a/packages/adapter-typeorm/test/sqlite/index.custom.test.ts
+++ b/packages/adapter-typeorm/test/sqlite/index.custom.test.ts
@@ -4,7 +4,7 @@ import * as entities from "../custom-entities"
import { db } from "../helpers"
const sqliteConfig = {
- type: "sqlite" as const,
+ type: "better-sqlite3" as const,
name: "next-auth-test-memory",
database: "./test/sqlite/dev.db",
synchronize: true,
diff --git a/packages/adapter-typeorm/tsconfig.json b/packages/adapter-typeorm/tsconfig.json
index df8621c516..0a25c050db 100644
--- a/packages/adapter-typeorm/tsconfig.json
+++ b/packages/adapter-typeorm/tsconfig.json
@@ -5,5 +5,5 @@
"rootDir": "src"
},
"exclude": ["*.js", "*.d.ts"],
- "include": ["src/**/*"]
+ "include": ["src/*"]
}
diff --git a/packages/utils/vitest.config.ts b/packages/utils/vitest.config.ts
index 2c2bb24cc8..7ec404c1cc 100644
--- a/packages/utils/vitest.config.ts
+++ b/packages/utils/vitest.config.ts
@@ -17,5 +17,5 @@ export default defineConfig({
},
setupFiles: ["../utils/vitest-setup.ts"],
},
- plugins: [swc.vite(), preact()],
+ plugins: [swc.vite(), preact({ include: ["**/*[jt]sx"] })],
})
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index a56c6fc05b..b053d9db16 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -144,8 +144,8 @@ importers:
specifier: ^5
version: 5.8.1(prisma@5.8.1)
next:
- specifier: 14.2.0-canary.47
- version: 14.2.0-canary.47(@playwright/test@1.41.2)(react-dom@18.2.0)(react@18.2.0)
+ specifier: 14.2.3
+ version: 14.2.3(@playwright/test@1.41.2)(react-dom@18.2.0)(react@18.2.0)
next-auth:
specifier: workspace:*
version: link:../../../packages/next-auth
@@ -159,6 +159,9 @@ importers:
specifier: ^18
version: 18.2.0(react@18.2.0)
devDependencies:
+ '@libsql/client':
+ specifier: ^0.6.0
+ version: 0.6.0
'@types/react':
specifier: ^18.2.23
version: 18.2.48
@@ -168,9 +171,6 @@ importers:
prisma:
specifier: ^5
version: 5.8.1
- sqlite3:
- specifier: ^5.0.8
- version: 5.1.7
apps/dev/sveltekit:
dependencies:
@@ -314,8 +314,8 @@ importers:
specifier: ^2.12.2
version: 2.14.2
better-sqlite3:
- specifier: ^8.6.0
- version: 8.7.0
+ specifier: ^9.6.0
+ version: 9.6.0
packages/adapter-dgraph:
dependencies:
@@ -336,21 +336,18 @@ importers:
specifier: workspace:*
version: link:../core
devDependencies:
- '@types/better-sqlite3':
- specifier: ^7.6.4
- version: 7.6.9
'@types/uuid':
specifier: ^8.3.3
version: 8.3.4
- better-sqlite3:
- specifier: ^9.4.0
- version: 9.5.0
drizzle-kit:
specifier: ^0.20.17
version: 0.20.17
drizzle-orm:
specifier: ^0.30.9
version: 0.30.9(@types/better-sqlite3@7.6.9)(better-sqlite3@9.5.0)(mysql2@3.9.7)(postgres@3.4.3)
+ libsql:
+ specifier: ^0.3.18
+ version: 0.3.18
mysql2:
specifier: ^3.9.7
version: 3.9.7
@@ -429,18 +426,15 @@ importers:
specifier: workspace:*
version: link:../core
devDependencies:
- '@types/better-sqlite3':
- specifier: ^7.6.3
- version: 7.6.9
'@types/pg':
specifier: ^8.6.5
version: 8.11.0
- better-sqlite3:
- specifier: ^8.6.0
- version: 8.7.0
kysely:
specifier: ^0.24.2
version: 0.24.2
+ libsql:
+ specifier: ^0.3.18
+ version: 0.3.18
mysql2:
specifier: ^3.9.7
version: 3.9.7
@@ -570,6 +564,9 @@ importers:
specifier: workspace:*
version: link:../core
devDependencies:
+ libsql:
+ specifier: ^0.3.18
+ version: 0.3.18
mssql:
specifier: ^7.2.1
version: 7.3.5
@@ -579,12 +576,9 @@ importers:
pg:
specifier: ^8.7.3
version: 8.11.3
- sqlite3:
- specifier: ^5.0.8
- version: 5.1.7
typeorm:
specifier: 0.3.17
- version: 0.3.17(mssql@7.3.5)(pg@8.11.3)(sqlite3@5.1.7)
+ version: 0.3.17(mssql@7.3.5)(pg@8.11.3)
typeorm-naming-strategies:
specifier: ^4.1.0
version: 4.1.0(typeorm@0.3.17)
@@ -5431,7 +5425,7 @@ packages:
/@internationalized/date@3.5.2:
resolution: {integrity: sha512-vo1yOMUt2hzp63IutEaTUxROdvQg1qlMRsbCvbay2AK2Gai7wIgCyK5weEX3nHkiLgo4qCXHijFNC/ILhlRpOQ==}
dependencies:
- '@swc/helpers': 0.5.2
+ '@swc/helpers': 0.5.5
dev: false
/@ioredis/commands@1.2.0:
@@ -5517,6 +5511,106 @@ packages:
resolution: {integrity: sha512-gbkePEBupNydxCelHCESvFSFM8XPh1Zs/OAVRW/rKpEqPAl5PbOM90Si8mv9bvnR53uPD2s/FiRxdvSejpRJew==}
dev: true
+ /@libsql/client@0.6.0:
+ resolution: {integrity: sha512-qhQzTG/y2IEVbL3+9PULDvlQFWJ/RnjFXECr/Nc3nRngGiiMysDaOV5VUzYk7DulUX98EA4wi+z3FspKrUplUA==}
+ dependencies:
+ '@libsql/core': 0.6.0
+ '@libsql/hrana-client': 0.6.0
+ js-base64: 3.7.7
+ libsql: 0.3.18
+ transitivePeerDependencies:
+ - bufferutil
+ - utf-8-validate
+ dev: true
+
+ /@libsql/core@0.6.0:
+ resolution: {integrity: sha512-affAB8vSqQwqI9NBDJ5uJCVaHoOAS2pOpbv1kWConh1SBbmJBnHHd4KG73RAJ2sgd2+NbT9WA+XJBqxgp28YSw==}
+ dependencies:
+ js-base64: 3.7.7
+ dev: true
+
+ /@libsql/darwin-arm64@0.3.18:
+ resolution: {integrity: sha512-Zt49dt+cwhPCkuoWgvjbQd4ckNfCJR5xzIAyhgHl3CBZqZaEuaXTOGKLNQT7bnFRPuQcdLt5PBT1cenKu2N6pA==}
+ cpu: [arm64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@libsql/darwin-x64@0.3.18:
+ resolution: {integrity: sha512-faq6HUGDaNaueeqPei5cypHaD/hhazUyfHo094CXiEeRZq6ZKtNl5PHdlr8jE/Uw8USNpVVQaLdnvSgKcpRPHw==}
+ cpu: [x64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@libsql/hrana-client@0.6.0:
+ resolution: {integrity: sha512-k+fqzdjqg3IvWfKmVJK5StsbjeTcyNAXFelUbXbGNz3yH1gEVT9mZ6kmhsIXP30ZSyVV0AE1Gi25p82mxC9hwg==}
+ dependencies:
+ '@libsql/isomorphic-fetch': 0.2.1
+ '@libsql/isomorphic-ws': 0.1.5
+ js-base64: 3.7.7
+ node-fetch: 3.3.2
+ transitivePeerDependencies:
+ - bufferutil
+ - utf-8-validate
+ dev: true
+
+ /@libsql/isomorphic-fetch@0.2.1:
+ resolution: {integrity: sha512-Sv07QP1Aw8A5OOrmKgRUBKe2fFhF2hpGJhtHe3d1aRnTESZCGkn//0zDycMKTGamVWb3oLYRroOsCV8Ukes9GA==}
+ dev: true
+
+ /@libsql/isomorphic-ws@0.1.5:
+ resolution: {integrity: sha512-DtLWIH29onUYR00i0GlQ3UdcTRC6EP4u9w/h9LxpUZJWRMARk6dQwZ6Jkd+QdwVpuAOrdxt18v0K2uIYR3fwFg==}
+ dependencies:
+ '@types/ws': 8.5.10
+ ws: 8.16.0
+ transitivePeerDependencies:
+ - bufferutil
+ - utf-8-validate
+ dev: true
+
+ /@libsql/linux-arm64-gnu@0.3.18:
+ resolution: {integrity: sha512-5m9xtDAhoyLSV54tho9uQ2ZIDeJWc0vU3Xpe/VK4+6bpURISs23qNhXiCrZnnq3oV0hFlBfcIgQUIATmb6jD2A==}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@libsql/linux-arm64-musl@0.3.18:
+ resolution: {integrity: sha512-oYD5+oM2gPEalp+EoR5DVQBRtdGjLsocjsRbQs5O2m4WOBJKER7VUfDYZHsifLGZoBSc11Yo6s9IR9rjGWy20w==}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@libsql/linux-x64-gnu@0.3.18:
+ resolution: {integrity: sha512-QDSSP60nS8KIldGE7H3bpEflQHiL1erwED6huoVJdmDFxsyDJX2CYdWUWW8Za0ZUOvUbnEWAOyMhp6j1dBbZqw==}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@libsql/linux-x64-musl@0.3.18:
+ resolution: {integrity: sha512-5SXwTlaLCUPzxYyq+P0c7Ko7tcEjpd1X6RZKe1DuRFmJPg6f7j2+LrPEhMSIbqKcrl5ACUUAyoKmGZqNYwz23w==}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@libsql/win32-x64-msvc@0.3.18:
+ resolution: {integrity: sha512-9EEIHz+e8tTbx9TMkb8ByZnzxc0pYFirK1nSbqC6cFEST95fiY0NCfQ/zAzJxe90KckbjifX6BbO69eWIi3TAg==}
+ cpu: [x64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
/@manypkg/find-root@1.1.0:
resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==}
dependencies:
@@ -5915,6 +6009,10 @@ packages:
'@napi-rs/simple-git-win32-x64-msvc': 0.1.16
dev: false
+ /@neon-rs/load@0.0.4:
+ resolution: {integrity: sha512-kTPhdZyTQxB+2wpiRcFWrDcejc4JI6tkPuS7UZCG4l6Zvc5kU/gGQ/ozvHTh1XR5tS+UlfAfGuPajjzQjCiHCw==}
+ dev: true
+
/@next/env@13.5.6:
resolution: {integrity: sha512-Yac/bV5sBGkkEXmAX5FWPS9Mmo2rthrOPRQQNfycJPkjUAUclomCPH7QFVCDQ4Mp2k2K1SSM6m0zrxYrOwtFQw==}
dev: false
@@ -5923,14 +6021,14 @@ packages:
resolution: {integrity: sha512-T4+xt6KrOjbod0kuVYC0T/1o7VokwUNawHJivISUxYX1Byke0YRySkgvCKdimcEP5bMukyzLPHuR6XoFcgVP0g==}
dev: true
- /@next/env@14.2.0-canary.47:
- resolution: {integrity: sha512-AURjF/V33qm2JSik8jS6wz4R0kl4uhi1m8k1z4x8wxYi0KbO5YgFvqWRFr7hKy1wr9pJW39kwFgci2XftxDFww==}
- dev: false
-
/@next/env@14.2.1:
resolution: {integrity: sha512-qsHJle3GU3CmVx7pUoXcghX4sRN+vINkbLdH611T8ZlsP//grzqVW87BSUgOZeSAD4q7ZdZicdwNe/20U2janA==}
dev: false
+ /@next/env@14.2.3:
+ resolution: {integrity: sha512-W7fd7IbkfmeeY2gXrzJYDx8D2lWKbVoTIj1o1ScPHNzvp30s1AuoEFSdr39bC5sjxJaxTtq3OTCZboNp0lNWHA==}
+ dev: false
+
/@next/swc-darwin-arm64@14.0.3-canary.1:
resolution: {integrity: sha512-Ebq88nIIrMVigWTYt8xWhksfzsKzTVwQqbHU0c4b1aGRW6gpul1zL2mK9u7scMx+3zC/6TVDqThb5LQlLrSSJQ==}
engines: {node: '>= 10'}
@@ -5940,8 +6038,8 @@ packages:
dev: true
optional: true
- /@next/swc-darwin-arm64@14.2.0-canary.47:
- resolution: {integrity: sha512-9nemlI7DMtq1OB3r4pxuVz1nU8rMEk/e7QBO1Hc+Ss+Z98HhvlqzFIShmS6LwQKa0q6KEKOdufFwtU9WG5FXTw==}
+ /@next/swc-darwin-arm64@14.2.1:
+ resolution: {integrity: sha512-kGjnjcIJehEcd3rT/3NAATJQndAEELk0J9GmGMXHSC75TMnvpOhONcjNHbjtcWE5HUQnIHy5JVkatrnYm1QhVw==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [darwin]
@@ -5949,8 +6047,8 @@ packages:
dev: false
optional: true
- /@next/swc-darwin-arm64@14.2.1:
- resolution: {integrity: sha512-kGjnjcIJehEcd3rT/3NAATJQndAEELk0J9GmGMXHSC75TMnvpOhONcjNHbjtcWE5HUQnIHy5JVkatrnYm1QhVw==}
+ /@next/swc-darwin-arm64@14.2.3:
+ resolution: {integrity: sha512-3pEYo/RaGqPP0YzwnlmPN2puaF2WMLM3apt5jLW2fFdXD9+pqcoTzRk+iZsf8ta7+quAe4Q6Ms0nR0SFGFdS1A==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [darwin]
@@ -5967,8 +6065,8 @@ packages:
dev: true
optional: true
- /@next/swc-darwin-x64@14.2.0-canary.47:
- resolution: {integrity: sha512-eq3ZnKg/h9Nmy7ocTOp+3v8F9id2Ar10TCBMz/JZmreeKNpNfUznIMsdNVMgqXbXoFCpLDbIMLf4qmVF3+OlQg==}
+ /@next/swc-darwin-x64@14.2.1:
+ resolution: {integrity: sha512-dAdWndgdQi7BK2WSXrx4lae7mYcOYjbHJUhvOUnJjMNYrmYhxbbvJ2xElZpxNxdfA6zkqagIB9He2tQk+l16ew==}
engines: {node: '>= 10'}
cpu: [x64]
os: [darwin]
@@ -5976,8 +6074,8 @@ packages:
dev: false
optional: true
- /@next/swc-darwin-x64@14.2.1:
- resolution: {integrity: sha512-dAdWndgdQi7BK2WSXrx4lae7mYcOYjbHJUhvOUnJjMNYrmYhxbbvJ2xElZpxNxdfA6zkqagIB9He2tQk+l16ew==}
+ /@next/swc-darwin-x64@14.2.3:
+ resolution: {integrity: sha512-6adp7waE6P1TYFSXpY366xwsOnEXM+y1kgRpjSRVI2CBDOcbRjsJ67Z6EgKIqWIue52d2q/Mx8g9MszARj8IEA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [darwin]
@@ -5994,8 +6092,8 @@ packages:
dev: true
optional: true
- /@next/swc-linux-arm64-gnu@14.2.0-canary.47:
- resolution: {integrity: sha512-CopkMncPw34uIh11KK9XtKjSjCS/R40TDRjXI+nq33y0WPfamQMKY5HgjL27qi6Yt5XbJwZhBVZx13vSC5u1Aw==}
+ /@next/swc-linux-arm64-gnu@14.2.1:
+ resolution: {integrity: sha512-2ZctfnyFOGvTkoD6L+DtQtO3BfFz4CapoHnyLTXkOxbZkVRgg3TQBUjTD/xKrO1QWeydeo8AWfZRg8539qNKrg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
@@ -6003,8 +6101,8 @@ packages:
dev: false
optional: true
- /@next/swc-linux-arm64-gnu@14.2.1:
- resolution: {integrity: sha512-2ZctfnyFOGvTkoD6L+DtQtO3BfFz4CapoHnyLTXkOxbZkVRgg3TQBUjTD/xKrO1QWeydeo8AWfZRg8539qNKrg==}
+ /@next/swc-linux-arm64-gnu@14.2.3:
+ resolution: {integrity: sha512-cuzCE/1G0ZSnTAHJPUT1rPgQx1w5tzSX7POXSLaS7w2nIUJUD+e25QoXD/hMfxbsT9rslEXugWypJMILBj/QsA==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
@@ -6021,8 +6119,8 @@ packages:
dev: true
optional: true
- /@next/swc-linux-arm64-musl@14.2.0-canary.47:
- resolution: {integrity: sha512-T0Z8ECr3QerlsDAYjreyg3A6gof12dCC7sdCeTBMhLZw4JjhITfg1jrUUVWFJrASBQaYwEip001jJpyIt7NPmg==}
+ /@next/swc-linux-arm64-musl@14.2.1:
+ resolution: {integrity: sha512-jazZXctiaanemy4r+TPIpFP36t1mMwWCKMsmrTRVChRqE6putyAxZA4PDujx0SnfvZHosjdkx9xIq9BzBB5tWg==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
@@ -6030,8 +6128,8 @@ packages:
dev: false
optional: true
- /@next/swc-linux-arm64-musl@14.2.1:
- resolution: {integrity: sha512-jazZXctiaanemy4r+TPIpFP36t1mMwWCKMsmrTRVChRqE6putyAxZA4PDujx0SnfvZHosjdkx9xIq9BzBB5tWg==}
+ /@next/swc-linux-arm64-musl@14.2.3:
+ resolution: {integrity: sha512-0D4/oMM2Y9Ta3nGuCcQN8jjJjmDPYpHX9OJzqk42NZGJocU2MqhBq5tWkJrUQOQY9N+In9xOdymzapM09GeiZw==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
@@ -6048,8 +6146,8 @@ packages:
dev: true
optional: true
- /@next/swc-linux-x64-gnu@14.2.0-canary.47:
- resolution: {integrity: sha512-IqaXu8km8fH3/tzluq5Arc6Yt2GaZuFF/P+uCY82MunLN+TN5FGdLpRRUbCnzlGuxTomhY4z9mRNL+3xSJP/Jg==}
+ /@next/swc-linux-x64-gnu@14.2.1:
+ resolution: {integrity: sha512-VjCHWCjsAzQAAo8lkBOLEIkBZFdfW+Z18qcQ056kL4KpUYc8o59JhLDCBlhg+hINQRgzQ2UPGma2AURGOH0+Qg==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
@@ -6057,8 +6155,8 @@ packages:
dev: false
optional: true
- /@next/swc-linux-x64-gnu@14.2.1:
- resolution: {integrity: sha512-VjCHWCjsAzQAAo8lkBOLEIkBZFdfW+Z18qcQ056kL4KpUYc8o59JhLDCBlhg+hINQRgzQ2UPGma2AURGOH0+Qg==}
+ /@next/swc-linux-x64-gnu@14.2.3:
+ resolution: {integrity: sha512-ENPiNnBNDInBLyUU5ii8PMQh+4XLr4pG51tOp6aJ9xqFQ2iRI6IH0Ds2yJkAzNV1CfyagcyzPfROMViS2wOZ9w==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
@@ -6075,8 +6173,8 @@ packages:
dev: true
optional: true
- /@next/swc-linux-x64-musl@14.2.0-canary.47:
- resolution: {integrity: sha512-0UluZrjveAaTmW9sNZcbhgL8Hyi1hiQzS4njau7T480M6L+dPSWx3c4W029dSBJrBVquB5mwUzjtcIQoFZPCWw==}
+ /@next/swc-linux-x64-musl@14.2.1:
+ resolution: {integrity: sha512-7HZKYKvAp4nAHiHIbY04finRqjeYvkITOGOurP1aLMexIFG/1+oCnqhGogBdc4lao/lkMW1c+AkwWSzSlLasqw==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
@@ -6084,8 +6182,8 @@ packages:
dev: false
optional: true
- /@next/swc-linux-x64-musl@14.2.1:
- resolution: {integrity: sha512-7HZKYKvAp4nAHiHIbY04finRqjeYvkITOGOurP1aLMexIFG/1+oCnqhGogBdc4lao/lkMW1c+AkwWSzSlLasqw==}
+ /@next/swc-linux-x64-musl@14.2.3:
+ resolution: {integrity: sha512-BTAbq0LnCbF5MtoM7I/9UeUu/8ZBY0i8SFjUMCbPDOLv+un67e2JgyN4pmgfXBwy/I+RHu8q+k+MCkDN6P9ViQ==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
@@ -6102,8 +6200,8 @@ packages:
dev: true
optional: true
- /@next/swc-win32-arm64-msvc@14.2.0-canary.47:
- resolution: {integrity: sha512-dEHvVCNlKUOMD2w8jXMIQy+/0OQHU5EHycamS5zL9cleHX2JJEyy0V0amJYJsc+26NRRSCUDC26xjCQNL27x6g==}
+ /@next/swc-win32-arm64-msvc@14.2.1:
+ resolution: {integrity: sha512-YGHklaJ/Cj/F0Xd8jxgj2p8po4JTCi6H7Z3Yics3xJhm9CPIqtl8erlpK1CLv+HInDqEWfXilqatF8YsLxxA2Q==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [win32]
@@ -6111,8 +6209,8 @@ packages:
dev: false
optional: true
- /@next/swc-win32-arm64-msvc@14.2.1:
- resolution: {integrity: sha512-YGHklaJ/Cj/F0Xd8jxgj2p8po4JTCi6H7Z3Yics3xJhm9CPIqtl8erlpK1CLv+HInDqEWfXilqatF8YsLxxA2Q==}
+ /@next/swc-win32-arm64-msvc@14.2.3:
+ resolution: {integrity: sha512-AEHIw/dhAMLNFJFJIJIyOFDzrzI5bAjI9J26gbO5xhAKHYTZ9Or04BesFPXiAYXDNdrwTP2dQceYA4dL1geu8A==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [win32]
@@ -6129,8 +6227,8 @@ packages:
dev: true
optional: true
- /@next/swc-win32-ia32-msvc@14.2.0-canary.47:
- resolution: {integrity: sha512-BJP9qLYP4n9XXOzj/mTpPRS3F4/+fduDrr5HfGp++lo898MX3wG9Mq4mrkr7WWzzlU3nuehHE9DLEwyFHtyi9w==}
+ /@next/swc-win32-ia32-msvc@14.2.1:
+ resolution: {integrity: sha512-o+ISKOlvU/L43ZhtAAfCjwIfcwuZstiHVXq/BDsZwGqQE0h/81td95MPHliWCnFoikzWcYqh+hz54ZB2FIT8RA==}
engines: {node: '>= 10'}
cpu: [ia32]
os: [win32]
@@ -6138,8 +6236,8 @@ packages:
dev: false
optional: true
- /@next/swc-win32-ia32-msvc@14.2.1:
- resolution: {integrity: sha512-o+ISKOlvU/L43ZhtAAfCjwIfcwuZstiHVXq/BDsZwGqQE0h/81td95MPHliWCnFoikzWcYqh+hz54ZB2FIT8RA==}
+ /@next/swc-win32-ia32-msvc@14.2.3:
+ resolution: {integrity: sha512-vga40n1q6aYb0CLrM+eEmisfKCR45ixQYXuBXxOOmmoV8sYST9k7E3US32FsY+CkkF7NtzdcebiFT4CHuMSyZw==}
engines: {node: '>= 10'}
cpu: [ia32]
os: [win32]
@@ -6156,8 +6254,8 @@ packages:
dev: true
optional: true
- /@next/swc-win32-x64-msvc@14.2.0-canary.47:
- resolution: {integrity: sha512-Ee/xNaiP2S0y9emmumoqa9poi6e7oWxYZajJpbXcRIT8hURzRYgAN0+YaX86Y33M2XJ9UIX0KcUSXjCQ9zPQuA==}
+ /@next/swc-win32-x64-msvc@14.2.1:
+ resolution: {integrity: sha512-GmRoTiLcvCLifujlisknv4zu9/C4i9r0ktsA8E51EMqJL4bD4CpO7lDYr7SrUxCR0tS4RVcrqKmCak24T0ohaw==}
engines: {node: '>= 10'}
cpu: [x64]
os: [win32]
@@ -6165,8 +6263,8 @@ packages:
dev: false
optional: true
- /@next/swc-win32-x64-msvc@14.2.1:
- resolution: {integrity: sha512-GmRoTiLcvCLifujlisknv4zu9/C4i9r0ktsA8E51EMqJL4bD4CpO7lDYr7SrUxCR0tS4RVcrqKmCak24T0ohaw==}
+ /@next/swc-win32-x64-msvc@14.2.3:
+ resolution: {integrity: sha512-Q1/zm43RWynxrO7lW4ehciQVj+5ePBhOK+/K2P7pLFX3JaJ/IZVC69SHidrmZSOkqz7ECIOhhy7XhAFG4JYyHA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [win32]
@@ -6208,7 +6306,7 @@ packages:
requiresBuild: true
dependencies:
'@gar/promisify': 1.1.3
- semver: 7.5.4
+ semver: 7.6.0
dev: true
optional: true
@@ -8277,6 +8375,7 @@ packages:
resolution: {integrity: sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==}
dependencies:
tslib: 2.6.2
+ dev: true
/@swc/helpers@0.5.5:
resolution: {integrity: sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==}
@@ -11240,16 +11339,8 @@ packages:
react: 18.2.0
dev: false
- /better-sqlite3@8.7.0:
- resolution: {integrity: sha512-99jZU4le+f3G6aIl6PmmV0cxUIWqKieHxsiF7G34CVFiE+/UabpYqkU0NJIkY/96mQKikHeBjtR27vFfs5JpEw==}
- requiresBuild: true
- dependencies:
- bindings: 1.5.0
- prebuild-install: 7.1.1
- dev: true
-
- /better-sqlite3@9.5.0:
- resolution: {integrity: sha512-01qVcM4gPNwE+PX7ARNiHINwzVuD6nx0gdldaAAcu+MrzyIAukQ31ZDKEpzRO/CNA9sHpxoTZ8rdjoyAin4dyg==}
+ /better-sqlite3@9.6.0:
+ resolution: {integrity: sha512-yR5HATnqeYNVnkaUTf4bOP2dJSnyhP4puJN/QPRyx4YkBEEUxib422n2XzPqDEHjQQqazoYoADdAm5vE15+dAQ==}
requiresBuild: true
dependencies:
bindings: 1.5.0
@@ -11283,6 +11374,7 @@ packages:
/bl@4.1.0:
resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==}
+ requiresBuild: true
dependencies:
buffer: 5.7.1
inherits: 2.0.4
@@ -11452,6 +11544,7 @@ packages:
/buffer@5.7.1:
resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
+ requiresBuild: true
dependencies:
base64-js: 1.5.1
ieee754: 1.2.1
@@ -11467,7 +11560,7 @@ packages:
/builtins@5.0.1:
resolution: {integrity: sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==}
dependencies:
- semver: 7.5.4
+ semver: 7.6.0
dev: true
/bundle-n-require@1.1.1:
@@ -11776,6 +11869,7 @@ packages:
/chownr@1.1.4:
resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==}
+ requiresBuild: true
dev: true
/chownr@2.0.0:
@@ -12708,6 +12802,11 @@ packages:
lodash-es: 4.17.21
dev: false
+ /data-uri-to-buffer@4.0.1:
+ resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==}
+ engines: {node: '>= 12'}
+ dev: true
+
/dataloader@2.2.2:
resolution: {integrity: sha512-8YnDaaf7N3k/q5HnTJVuzSyLETjoZjVmHc4AeKAzOvKHEFQKcn64OKBfzHYtE9zGjctNM7V9I0MfnUVLpi7M5g==}
dev: true
@@ -12800,6 +12899,7 @@ packages:
/decompress-response@6.0.0:
resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==}
engines: {node: '>=10'}
+ requiresBuild: true
dependencies:
mimic-response: 3.1.0
dev: true
@@ -12818,6 +12918,7 @@ packages:
/deep-extend@0.6.0:
resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==}
engines: {node: '>=4.0.0'}
+ requiresBuild: true
dev: true
/deep-is@0.1.4:
@@ -13200,8 +13301,6 @@ packages:
sqlite3:
optional: true
dependencies:
- '@types/better-sqlite3': 7.6.9
- better-sqlite3: 9.5.0
mysql2: 3.9.7
postgres: 3.4.3
dev: true
@@ -14231,6 +14330,7 @@ packages:
/expand-template@2.0.3:
resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==}
engines: {node: '>=6'}
+ requiresBuild: true
dev: true
/exponential-backoff@3.1.1:
@@ -14541,6 +14641,14 @@ packages:
- encoding
dev: true
+ /fetch-blob@3.2.0:
+ resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==}
+ engines: {node: ^12.20 || >= 14.13}
+ dependencies:
+ node-domexception: 1.0.0
+ web-streams-polyfill: 3.3.2
+ dev: true
+
/fetch-cookie@0.11.0:
resolution: {integrity: sha512-BQm7iZLFhMWFy5CZ/162sAGjBfdNWb7a8LEqqnzsHFhxT/X/SVj/z2t2nu3aJvjlbQkrAlTUApplPRjWyH4mhA==}
engines: {node: '>=8'}
@@ -14742,6 +14850,13 @@ packages:
engines: {node: '>=0.4.x'}
dev: false
+ /formdata-polyfill@4.0.10:
+ resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==}
+ engines: {node: '>=12.20.0'}
+ dependencies:
+ fetch-blob: 3.2.0
+ dev: true
+
/formidable@2.1.2:
resolution: {integrity: sha512-CM3GuJ57US06mlpQ47YcunuUZ9jpm8Vx+P2CGt2j7HpgkKZO/DJYQ0Bobim8G6PFQmK5lOqOOdUXboU+h73A4g==}
dependencies:
@@ -14782,6 +14897,7 @@ packages:
/fs-constants@1.0.0:
resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==}
+ requiresBuild: true
dev: true
/fs-extra@11.1.1:
@@ -15027,6 +15143,7 @@ packages:
/github-from-package@0.0.0:
resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==}
+ requiresBuild: true
dev: true
/github-slugger@2.0.0:
@@ -15922,6 +16039,7 @@ packages:
/ini@1.3.8:
resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==}
+ requiresBuild: true
dev: true
/inline-style-parser@0.1.1:
@@ -16534,6 +16652,10 @@ packages:
/jose@5.2.0:
resolution: {integrity: sha512-oW3PCnvyrcm1HMvGTzqjxxfnEs9EoFOFWi2HsEGhlFVOXxTE3K9GKWVMFoFw06yPUqwpvEWic1BmtUZBI/tIjw==}
+ /js-base64@3.7.7:
+ resolution: {integrity: sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==}
+ dev: true
+
/js-sdsl@4.4.2:
resolution: {integrity: sha512-dwXFwByc/ajSV6m5bcKAPwe4yDDF6D614pxmIi5odytzxRlwqF6nwoiCek80Ixc7Cvma5awClxrzFtxCQvcM8w==}
dev: true
@@ -17044,6 +17166,23 @@ packages:
resolution: {integrity: sha512-Ka0eC5LkF3IPNQHJmYBWljJsw0UvM6j+QdKRbWyCdTmYwvIDE6a7bCm0UkTAL/K+3KXK5qXT/ClcInU01OpdLg==}
dev: true
+ /libsql@0.3.18:
+ resolution: {integrity: sha512-lvhKr7WV3NLWRbXkjn/MeKqXOAqWKU0PX9QYrvDh7fneukapj+iUQ4qgJASrQyxcCrEsClXCQiiK5W6OoYPAlA==}
+ cpu: [x64, arm64, wasm32]
+ os: [darwin, linux, win32]
+ dependencies:
+ '@neon-rs/load': 0.0.4
+ detect-libc: 2.0.2
+ optionalDependencies:
+ '@libsql/darwin-arm64': 0.3.18
+ '@libsql/darwin-x64': 0.3.18
+ '@libsql/linux-arm64-gnu': 0.3.18
+ '@libsql/linux-arm64-musl': 0.3.18
+ '@libsql/linux-x64-gnu': 0.3.18
+ '@libsql/linux-x64-musl': 0.3.18
+ '@libsql/win32-x64-msvc': 0.3.18
+ dev: true
+
/lil-fp@1.4.5:
resolution: {integrity: sha512-RrMQ2dB7SDXriFPZMMHEmroaSP6lFw3QEV7FOfSkf19kvJnDzHqKMc2P9HOf5uE8fOp5YxodSrq7XxWjdeC2sw==}
dev: false
@@ -18505,6 +18644,7 @@ packages:
/mimic-response@3.1.0:
resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==}
engines: {node: '>=10'}
+ requiresBuild: true
dev: true
/min-indent@1.0.1:
@@ -18635,6 +18775,7 @@ packages:
/mkdirp-classic@0.5.3:
resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==}
+ requiresBuild: true
dev: true
/mkdirp@0.3.0:
@@ -18860,6 +19001,7 @@ packages:
/napi-build-utils@1.0.2:
resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==}
+ requiresBuild: true
dev: true
/napi-macros@2.0.0:
@@ -18974,8 +19116,8 @@ packages:
- babel-plugin-macros
dev: true
- /next@14.2.0-canary.47(@playwright/test@1.41.2)(react-dom@18.2.0)(react@18.2.0):
- resolution: {integrity: sha512-gtOUWhd+diNCTeRQAMFVRFx2Fo6WKCfFWZ+yg/2TgUnF1dc+tMFU0OYjXM1NRs4Yc6jdyqzeanH3oYYSokwg1w==}
+ /next@14.2.1(@babel/core@7.23.9)(@playwright/test@1.41.2)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-SF3TJnKdH43PMkCcErLPv+x/DY1YCklslk3ZmwaVoyUfDgHKexuKlf9sEfBQ69w+ue8jQ3msLb+hSj1T19hGag==}
engines: {node: '>=18.17.0'}
hasBin: true
peerDependencies:
@@ -18992,33 +19134,33 @@ packages:
sass:
optional: true
dependencies:
- '@next/env': 14.2.0-canary.47
+ '@next/env': 14.2.1
'@playwright/test': 1.41.2
'@swc/helpers': 0.5.5
busboy: 1.6.0
- caniuse-lite: 1.0.30001609
+ caniuse-lite: 1.0.30001594
graceful-fs: 4.2.11
postcss: 8.4.31
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
styled-jsx: 5.1.1(@babel/core@7.23.9)(react@18.2.0)
optionalDependencies:
- '@next/swc-darwin-arm64': 14.2.0-canary.47
- '@next/swc-darwin-x64': 14.2.0-canary.47
- '@next/swc-linux-arm64-gnu': 14.2.0-canary.47
- '@next/swc-linux-arm64-musl': 14.2.0-canary.47
- '@next/swc-linux-x64-gnu': 14.2.0-canary.47
- '@next/swc-linux-x64-musl': 14.2.0-canary.47
- '@next/swc-win32-arm64-msvc': 14.2.0-canary.47
- '@next/swc-win32-ia32-msvc': 14.2.0-canary.47
- '@next/swc-win32-x64-msvc': 14.2.0-canary.47
+ '@next/swc-darwin-arm64': 14.2.1
+ '@next/swc-darwin-x64': 14.2.1
+ '@next/swc-linux-arm64-gnu': 14.2.1
+ '@next/swc-linux-arm64-musl': 14.2.1
+ '@next/swc-linux-x64-gnu': 14.2.1
+ '@next/swc-linux-x64-musl': 14.2.1
+ '@next/swc-win32-arm64-msvc': 14.2.1
+ '@next/swc-win32-ia32-msvc': 14.2.1
+ '@next/swc-win32-x64-msvc': 14.2.1
transitivePeerDependencies:
- '@babel/core'
- babel-plugin-macros
dev: false
- /next@14.2.1(@babel/core@7.23.9)(@playwright/test@1.41.2)(react-dom@18.2.0)(react@18.2.0):
- resolution: {integrity: sha512-SF3TJnKdH43PMkCcErLPv+x/DY1YCklslk3ZmwaVoyUfDgHKexuKlf9sEfBQ69w+ue8jQ3msLb+hSj1T19hGag==}
+ /next@14.2.3(@playwright/test@1.41.2)(react-dom@18.2.0)(react@18.2.0):
+ resolution: {integrity: sha512-dowFkFTR8v79NPJO4QsBUtxv0g9BrS/phluVpMAt2ku7H+cbcBJlopXjkWlwxrk/xGqMemr7JkGPGemPrLLX7A==}
engines: {node: '>=18.17.0'}
hasBin: true
peerDependencies:
@@ -19035,26 +19177,26 @@ packages:
sass:
optional: true
dependencies:
- '@next/env': 14.2.1
+ '@next/env': 14.2.3
'@playwright/test': 1.41.2
'@swc/helpers': 0.5.5
busboy: 1.6.0
- caniuse-lite: 1.0.30001594
+ caniuse-lite: 1.0.30001609
graceful-fs: 4.2.11
postcss: 8.4.31
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
styled-jsx: 5.1.1(@babel/core@7.23.9)(react@18.2.0)
optionalDependencies:
- '@next/swc-darwin-arm64': 14.2.1
- '@next/swc-darwin-x64': 14.2.1
- '@next/swc-linux-arm64-gnu': 14.2.1
- '@next/swc-linux-arm64-musl': 14.2.1
- '@next/swc-linux-x64-gnu': 14.2.1
- '@next/swc-linux-x64-musl': 14.2.1
- '@next/swc-win32-arm64-msvc': 14.2.1
- '@next/swc-win32-ia32-msvc': 14.2.1
- '@next/swc-win32-x64-msvc': 14.2.1
+ '@next/swc-darwin-arm64': 14.2.3
+ '@next/swc-darwin-x64': 14.2.3
+ '@next/swc-linux-arm64-gnu': 14.2.3
+ '@next/swc-linux-arm64-musl': 14.2.3
+ '@next/swc-linux-x64-gnu': 14.2.3
+ '@next/swc-linux-x64-musl': 14.2.3
+ '@next/swc-win32-arm64-msvc': 14.2.3
+ '@next/swc-win32-ia32-msvc': 14.2.3
+ '@next/swc-win32-x64-msvc': 14.2.3
transitivePeerDependencies:
- '@babel/core'
- babel-plugin-macros
@@ -19150,8 +19292,9 @@ packages:
/node-abi@3.54.0:
resolution: {integrity: sha512-p7eGEiQil0YUV3ItH4/tBb781L5impVmmx2E9FRKF7d18XXzp4PGT2tdYMFY6wQqgxD0IwNZOiSJ0/K0fSi/OA==}
engines: {node: '>=10'}
+ requiresBuild: true
dependencies:
- semver: 7.5.4
+ semver: 7.6.0
dev: true
/node-abort-controller@2.0.0:
@@ -19164,12 +19307,18 @@ packages:
/node-addon-api@4.3.0:
resolution: {integrity: sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==}
+ requiresBuild: true
dev: true
/node-addon-api@7.1.0:
resolution: {integrity: sha512-mNcltoe1R8o7STTegSOHdnJNN7s5EUvhoS7ShnTHDyOSd+8H+UdWODq6qSv67PjC8Zc5JRT8+oLAMCr0SIXw7g==}
engines: {node: ^16 || ^18 || >= 20}
+ /node-domexception@1.0.0:
+ resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
+ engines: {node: '>=10.5.0'}
+ dev: true
+
/node-eval@2.0.0:
resolution: {integrity: sha512-Ap+L9HznXAVeJj3TJ1op6M6bg5xtTq8L5CU/PJxtkhea/DrIxdTknGKIECKd/v/Lgql95iuMAYvIzBNd0pmcMg==}
engines: {node: '>= 4'}
@@ -19204,6 +19353,15 @@ packages:
dependencies:
whatwg-url: 5.0.0
+ /node-fetch@3.3.2:
+ resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ dependencies:
+ data-uri-to-buffer: 4.0.1
+ fetch-blob: 3.2.0
+ formdata-polyfill: 4.0.10
+ dev: true
+
/node-forge@1.3.1:
resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==}
engines: {node: '>= 6.13.0'}
@@ -19302,7 +19460,7 @@ packages:
dependencies:
hosted-git-info: 4.1.0
is-core-module: 2.13.1
- semver: 7.5.4
+ semver: 7.6.0
validate-npm-package-license: 3.0.4
dev: true
@@ -20480,6 +20638,7 @@ packages:
resolution: {integrity: sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==}
engines: {node: '>=10'}
hasBin: true
+ requiresBuild: true
dependencies:
detect-libc: 2.0.2
expand-template: 2.0.3
@@ -20705,7 +20864,7 @@ packages:
jsdoc: 4.0.2
minimist: 1.2.8
protobufjs: 7.2.4
- semver: 7.5.4
+ semver: 7.6.0
tmp: 0.2.1
uglify-js: 3.17.4
dev: true
@@ -20864,6 +21023,7 @@ packages:
/pump@3.0.0:
resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==}
+ requiresBuild: true
dependencies:
end-of-stream: 1.4.4
once: 1.4.0
@@ -20950,6 +21110,7 @@ packages:
/rc@1.2.8:
resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==}
hasBin: true
+ requiresBuild: true
dependencies:
deep-extend: 0.6.0
ini: 1.3.8
@@ -21901,6 +22062,7 @@ packages:
resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==}
engines: {node: '>=10'}
hasBin: true
+ requiresBuild: true
dependencies:
lru-cache: 6.0.0
dev: true
@@ -22135,10 +22297,12 @@ packages:
/simple-concat@1.0.1:
resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==}
+ requiresBuild: true
dev: true
/simple-get@4.0.1:
resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==}
+ requiresBuild: true
dependencies:
decompress-response: 6.0.0
once: 1.4.0
@@ -22477,24 +22641,6 @@ packages:
- supports-color
dev: true
- /sqlite3@5.1.7:
- resolution: {integrity: sha512-GGIyOiFaG+TUra3JIfkI/zGP8yZYLPQ0pl1bH+ODjiX57sPhrLU5sQJn1y9bDKZUFYkX1crlrPfSYt0BKKdkog==}
- requiresBuild: true
- peerDependenciesMeta:
- node-gyp:
- optional: true
- dependencies:
- bindings: 1.5.0
- node-addon-api: 7.1.0
- prebuild-install: 7.1.1
- tar: 6.2.0
- optionalDependencies:
- node-gyp: 8.4.1
- transitivePeerDependencies:
- - bluebird
- - supports-color
- dev: true
-
/sqlstring-sqlite@0.1.1:
resolution: {integrity: sha512-9CAYUJ0lEUPYJrswqiqdINNSfq3jqWo/bFJ7tufdoNeSK0Fy+d1kFTxjqO9PIqza0Kri+ZtYMfPVf1aZaFOvrQ==}
engines: {node: '>= 0.6'}
@@ -22719,6 +22865,7 @@ packages:
/strip-json-comments@2.0.1:
resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==}
engines: {node: '>=0.10.0'}
+ requiresBuild: true
dev: true
/strip-json-comments@3.1.1:
@@ -23195,6 +23342,7 @@ packages:
/tar-fs@2.1.1:
resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==}
+ requiresBuild: true
dependencies:
chownr: 1.1.4
mkdirp-classic: 0.5.3
@@ -23205,6 +23353,7 @@ packages:
/tar-stream@2.2.0:
resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==}
engines: {node: '>=6'}
+ requiresBuild: true
dependencies:
bl: 4.1.0
end-of-stream: 1.4.4
@@ -23649,6 +23798,7 @@ packages:
/tunnel-agent@0.6.0:
resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==}
+ requiresBuild: true
dependencies:
safe-buffer: 5.2.1
dev: true
@@ -23886,10 +24036,10 @@ packages:
peerDependencies:
typeorm: ^0.2.0 || ^0.3.0
dependencies:
- typeorm: 0.3.17(mssql@7.3.5)(pg@8.11.3)(sqlite3@5.1.7)
+ typeorm: 0.3.17(mssql@7.3.5)(pg@8.11.3)
dev: true
- /typeorm@0.3.17(mssql@7.3.5)(pg@8.11.3)(sqlite3@5.1.7):
+ /typeorm@0.3.17(mssql@7.3.5)(pg@8.11.3):
resolution: {integrity: sha512-UDjUEwIQalO9tWw9O2A4GU+sT3oyoUXheHJy4ft+RFdnRdQctdQ34L9SqE2p7LdwzafHx1maxT+bqXON+Qnmig==}
engines: {node: '>= 12.9.0'}
hasBin: true
@@ -23961,7 +24111,6 @@ packages:
pg: 8.11.3
reflect-metadata: 0.1.14
sha.js: 2.4.11
- sqlite3: 5.1.7
tslib: 2.6.2
uuid: 9.0.1
yargs: 17.7.2
@@ -25233,6 +25382,7 @@ packages:
/yallist@4.0.0:
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
+ requiresBuild: true
/yaml-ast-parser@0.0.43:
resolution: {integrity: sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==}
From 86e354dd3ad202f6224d9501d40ee5675ea907a1 Mon Sep 17 00:00:00 2001
From: ndom91
Date: Fri, 10 May 2024 15:00:24 +0200
Subject: [PATCH 11/44] chore(docs): add security.txt
---
docs/public/.well-known/security.txt | 31 ++++++++++++++++++++++++++++
docs/vercel.json | 5 +++++
2 files changed, 36 insertions(+)
create mode 100644 docs/public/.well-known/security.txt
diff --git a/docs/public/.well-known/security.txt b/docs/public/.well-known/security.txt
new file mode 100644
index 0000000000..e9c259de96
--- /dev/null
+++ b/docs/public/.well-known/security.txt
@@ -0,0 +1,31 @@
+Contact: mailto:info@balazsorban.com
+Contact: mailto:hi@thvu.dev
+Contact: mailto:authjs-security@ndo.dev
+Acknowledgments: https://authjs.dev/security
+Preferred-Languages: en
+Canonical: https://authjs.dev/.well-known/security.txt
+
+# Security Policy
+
+NextAuth.js practices responsible disclosure.
+
+## Reporting a Vulnerability
+
+We request that you contact us directly to report serious issues that might impact the security of sites using NextAuth.js.
+
+If you contact us regarding a serious issue:
+
+- We will endeavor to get back to you within 72 hours.
+- We will aim to publish a fix within 30 days.
+- We will disclose the issue (and credit you, with your consent) once a fix to resolve the issue has been released.
+- If 90 days has elapsed and we still don't have a fix, we will disclose the issue publicly.
+
+The best way to report an issue is by contacting us via email at hi@thvu.dev, info@balazsorban.com and yo@ndo.dev, or raise a public issue requesting someone get in touch with you via whatever means you prefer for more details. (Please do not disclose sensitive details publicly at this stage.)
+
+> For less serious issues (e.g. RFC compliance for unsupported flows or potential issues that may cause a problem in the future) it is appropriate to submit these publicly as bug reports or feature requests or to raise a question to open a discussion around them.
+
+## Supported Versions
+
+Security updates are only released for the current version.
+
+Old releases are not maintained and do not receive updates.
diff --git a/docs/vercel.json b/docs/vercel.json
index c3296f0939..b90828fe9c 100644
--- a/docs/vercel.json
+++ b/docs/vercel.json
@@ -12,6 +12,11 @@
}
],
"redirects": [
+ {
+ "source": "/security.txt",
+ "destination": "/.well-known/security.txt",
+ "permanent": true
+ },
{
"source": "/new/provider-issue",
"destination": "https://github.com/nextauthjs/next-auth/issues/new?assignees=&labels=triage%2Cproviders&template=2_bug_provider.yml",
From de586f6d94217138ca9d76b776f6136a5a1bf1ad Mon Sep 17 00:00:00 2001
From: Mike Chung
Date: Fri, 10 May 2024 15:36:01 +0200
Subject: [PATCH 12/44] chore(provider): SailPoint Identity Secure Cloud (ISC)
(#10723)
Co-authored-by: Nico Domino
---
.../getting-started/providers/sailpoint.mdx | 172 ++++++++++++++++++
docs/public/img/providers/sailpoint.svg | 26 +++
2 files changed, 198 insertions(+)
create mode 100644 docs/pages/getting-started/providers/sailpoint.mdx
create mode 100644 docs/public/img/providers/sailpoint.svg
diff --git a/docs/pages/getting-started/providers/sailpoint.mdx b/docs/pages/getting-started/providers/sailpoint.mdx
new file mode 100644
index 0000000000..706cfe69ca
--- /dev/null
+++ b/docs/pages/getting-started/providers/sailpoint.mdx
@@ -0,0 +1,172 @@
+import { Callout } from "nextra/components"
+import { Code } from "@/components/Code"
+
+
+
+# SailPoint Identity Secure Cloud Provider
+
+SailPoint Identity Secure Cloud (ISC) is an enterprise SaaS platform for identity and security. In order to use this OAuth integration, you will need an ISC tenant. If you're a SailPoint customer or partner, please talk to your SailPoint account manager for more details. If you are a developer, you can check out the [SailPoint Developer Community](https://developer.sailpoint.com/discuss/).
+
+## Resources
+
+- [SailPoint Identity Secure Cloud Authentication](https://developer.sailpoint.com/docs/api/authentication#choose-authorization-grant-flow)
+- [Managing API Keys and Personal Access Tokens](https://documentation.sailpoint.com/saas/help/common/api_keys.html?h=oauth+client#creating-an-api-key)
+- [SailPoint Developer Community](https://developer.sailpoint.com/discuss/)
+
+## Setup
+
+### Callback URL
+
+
+
+
+```bash
+https://example.com/api/auth/callback/identitySecureCloud
+```
+
+
+
+
+```bash
+https://example.com/auth/callback/identitySecureCloud
+```
+
+
+
+
+### Create OAuth Client
+
+Find your Identity Secure Cloud Tenant OAuth Information which can be found at `https://{tenant}.api.identitynow.com/oauth/info`. Create an OAuth Client (following this [guide](https://documentation.sailpoint.com/saas/help/common/api_keys.html?h=oauth+client#creating-an-api-key)) with grant types: `AUTHORIZATION_TOKEN` and `REFRESH_TOKEN`. Redirect URL should match your version of the Callback URL above. Finally, select the scopes `sp:scope:all`. Note down the generated `clientId` and `clientSecret`.
+
+### Environment Variables
+
+```
+ISC_BASE_API_URL=https://{tenant}.api.identitynow.com
+ISC_BASE_URL=https://{tenant}.identitynow.com
+ISC_CLIENT_ID=
+ISC_CLIENT_SECRET=
+```
+
+### Configuration
+
+
+
+
+```ts filename="/auth.ts"
+import NextAuth from "next-auth"
+
+export const { handlers, auth, signIn, signOut } = NextAuth({
+ providers: [
+ {
+ id: "identitySecureCloud",
+ name: "Identity Secure Cloud",
+ type: "oauth",
+ clientId: process.env.ISC_CLIENT_ID!,
+ clientSecret: process.env.ISC_CLIENT_SECRET!,
+ authorization: {
+ url: `${process.env.ISC_BASE_URL!}/oauth/authorize`,
+ params: { scope: 'sp:scopes:all' },
+ },
+ token: `${process.env.ISC_BASE_API_URL!}/oauth/token`,
+ userinfo: `${process.env.ISC_BASE_API_URL!}/oauth/userinfo`,
+ profile(profile) {
+ return {
+ id: profile.id,
+ email: profile.email,
+ name: profile.uid,
+ image: null
+ }
+ },
+ style: { text: "#011E69", bg: "#fff", logo: "sailpoint.svg" },
+ },
+ ],
+})
+```
+
+
+
+
+```ts filename="/src/auth.ts"
+import { SvelteKitAuth } from "@auth/sveltekit"
+import { env } from "$env/dynamic/prviate"
+
+export const { handle, signIn, signOut } = SvelteKitAuth({
+ providers: [
+ {
+ id: "identitySecureCloud",
+ name: "Identity Secure Cloud",
+ type: "oauth",
+ clientId: env.ISC_CLIENT_ID!,
+ clientSecret: env.ISC_CLIENT_SECRET!,
+ authorization: {
+ url: `${env.ISC_BASE_URL!}/oauth/authorize`,
+ params: { scope: 'sp:scopes:all' },
+ },
+ token: `${env.ISC_BASE_API_URL!}/oauth/token`,
+ userinfo: `${env.ISC_BASE_API_URL!}/oauth/userinfo`,
+ profile(profile) {
+ return {
+ id: profile.id,
+ email: profile.email,
+ name: profile.uid,
+ image: null
+ }
+ },
+ style: { text: "#011E69", bg: "#fff", logo: "sailpoint.svg" },
+ },
+ ],
+})
+```
+
+
+
+
+```ts filename="/src/app.ts"
+import { ExpressAuth } from "@auth/express"
+
+app.use("/auth/*", ExpressAuth({ providers: [
+ {
+ id: "identitySecureCloud",
+ name: "Identity Secure Cloud",
+ type: "oauth",
+ clientId: process.env.ISC_CLIENT_ID!,
+ clientSecret: process.env.ISC_CLIENT_SECRET!,
+ authorization: {
+ url: `${process.env.ISC_BASE_URL!}/oauth/authorize`,
+ params: { scope: 'sp:scopes:all' },
+ },
+ token: `${process.env.ISC_BASE_API_URL!}/oauth/token`,
+ userinfo: `${process.env.ISC_BASE_API_URL!}/oauth/userinfo`,
+ profile(profile) {
+ return {
+ id: profile.id,
+ email: profile.email,
+ name: profile.uid,
+ image: null
+ }
+ },
+ style: { text: "#011E69", bg: "#fff", logo: "sailpoint.svg" },
+ },
+] }))
+```
+
+
+
+
+Your `userprofile` endpoint will return more fields, but by default the [User table](https://authjs.dev/getting-started/database#models) only supports `id`, `name`, `email`, and `image`. Therefore, if you'd like to use any of the following fields, make sure you modify the `User` table schema in whichever adapter / database you're using.
+
+```ts
+tenant: profile.tenant,
+id: profile.id,
+uid: profile.uid,
+email: profile.email,
+phone: profile.phone,
+workPhone: profile.workPhone,
+firstname: profile.firstname,
+lastname: profile.lastname,
+capabilities: profile.capabilities,
+displayName: profile.displayName,
+name: profile.uid
+```
+
+The above fields will all be available in the `profile` callback.
diff --git a/docs/public/img/providers/sailpoint.svg b/docs/public/img/providers/sailpoint.svg
new file mode 100644
index 0000000000..8fd89e1f70
--- /dev/null
+++ b/docs/public/img/providers/sailpoint.svg
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
From 0f2cec5ba824e4db644b03e86c69d644537cbea8 Mon Sep 17 00:00:00 2001
From: ndom91
Date: Fri, 10 May 2024 15:35:00 +0200
Subject: [PATCH 13/44] chore(sailpoint): cleanup sailpoint page
---
.../getting-started/providers/sailpoint.mdx | 159 +++++++++++-------
1 file changed, 96 insertions(+), 63 deletions(-)
diff --git a/docs/pages/getting-started/providers/sailpoint.mdx b/docs/pages/getting-started/providers/sailpoint.mdx
index 706cfe69ca..49c7efdd98 100644
--- a/docs/pages/getting-started/providers/sailpoint.mdx
+++ b/docs/pages/getting-started/providers/sailpoint.mdx
@@ -3,9 +3,19 @@ import { Code } from "@/components/Code"
-# SailPoint Identity Secure Cloud Provider
+# SailPoint ISC Provider
-SailPoint Identity Secure Cloud (ISC) is an enterprise SaaS platform for identity and security. In order to use this OAuth integration, you will need an ISC tenant. If you're a SailPoint customer or partner, please talk to your SailPoint account manager for more details. If you are a developer, you can check out the [SailPoint Developer Community](https://developer.sailpoint.com/discuss/).
+SailPoint Identity Secure Cloud (ISC) is an enterprise SaaS platform for identity and security. In order to use this OAuth integration, you will need an ISC tenant. If you're a SailPoint customer or partner, please talk to your SailPoint account manager for more details. If you are a developer, check out the [SailPoint Developer Community](https://developer.sailpoint.com/discuss/).
+
+
+ This provider is not shipped with any of the Auth.js packages because it is an
+ enterprise provider for which we cannot obtain a tenant to test and ensure
+ compatibility. That being said, we'd like to make providers like these
+ available to our users, so we will share a copy and paste version of the
+ provider on respective docs pages like this. The provider configuration below
+ is provided as-is and has been submitted by a community member with access to
+ a SailPoint tenant.
+
## Resources
@@ -21,34 +31,48 @@ SailPoint Identity Secure Cloud (ISC) is an enterprise SaaS platform for identit
```bash
-https://example.com/api/auth/callback/identitySecureCloud
+https://example.com/api/auth/callback/sailpoint
```
```bash
-https://example.com/auth/callback/identitySecureCloud
+https://example.com/auth/callback/sailpoint
```
+
+
+```bash
+https://example.com/auth/callback/sailpoint
+```
+
+
### Create OAuth Client
-Find your Identity Secure Cloud Tenant OAuth Information which can be found at `https://{tenant}.api.identitynow.com/oauth/info`. Create an OAuth Client (following this [guide](https://documentation.sailpoint.com/saas/help/common/api_keys.html?h=oauth+client#creating-an-api-key)) with grant types: `AUTHORIZATION_TOKEN` and `REFRESH_TOKEN`. Redirect URL should match your version of the Callback URL above. Finally, select the scopes `sp:scope:all`. Note down the generated `clientId` and `clientSecret`.
+First, you'll need to create a client in your SailPoint admin console in order to get your `clientId` and `clientSecret`. You can follow this [guide](https://documentation.sailpoint.com/saas/help/common/api_keys.html?h=oauth+client#creating-an-api-key), or follow the main steps below.
+
+1. Create an OAuth Client () with grant types: `AUTHORIZATION_TOKEN` and `REFRESH_TOKEN`.
+2. Set the redirect URL to match your callback URL, based on the example above.
+3. Finally, select the scopes `sp:scope:all`.
+4. Click "**Create**" and note down the generated `clientId` and `clientSecret`.
### Environment Variables
-```
-ISC_BASE_API_URL=https://{tenant}.api.identitynow.com
-ISC_BASE_URL=https://{tenant}.identitynow.com
-ISC_CLIENT_ID=
-ISC_CLIENT_SECRET=
+```sh
+AUTH_SAILPOINT_ID=
+AUTH_SAILPOINT_SECRET=
+AUTH_SAILPOINT_BASE_URL=https://{tenant}.identitynow.com
+AUTH_SAILPOINT_BASE_API_URL=https://{tenant}.api.identitynow.com
```
### Configuration
+Unlike other Auth.js providers, this cannot be imported from the package (see the note at the top of this page for more details). However, you can copy and paste the following object into your `providers` array to enable this provider.
+
@@ -58,26 +82,26 @@ import NextAuth from "next-auth"
export const { handlers, auth, signIn, signOut } = NextAuth({
providers: [
{
- id: "identitySecureCloud",
- name: "Identity Secure Cloud",
+ id: "sailpoint",
+ name: "SailPoint",
type: "oauth",
- clientId: process.env.ISC_CLIENT_ID!,
- clientSecret: process.env.ISC_CLIENT_SECRET!,
+ clientId: process.env.AUTH_SAILPOINT_ID!,
+ clientSecret: process.env.AUTH_SAILPOINT_SECRET!,
authorization: {
- url: `${process.env.ISC_BASE_URL!}/oauth/authorize`,
- params: { scope: 'sp:scopes:all' },
+ url: `${process.env.AUTH_SAILPOINT_BASE_URL!}/oauth/authorize`,
+ params: { scope: "sp:scopes:all" },
},
- token: `${process.env.ISC_BASE_API_URL!}/oauth/token`,
- userinfo: `${process.env.ISC_BASE_API_URL!}/oauth/userinfo`,
+ token: `${process.env.AUTH_SAILPOINT_BASE_API_URL!}/oauth/token`,
+ userinfo: `${process.env.AUTH_SAILPOINT_BASE_API_URL!}/oauth/userinfo`,
profile(profile) {
return {
- id: profile.id,
- email: profile.email,
- name: profile.uid,
- image: null
+ id: profile.id,
+ email: profile.email,
+ name: profile.uid,
+ image: null,
}
},
- style: { text: "#011E69", bg: "#fff", logo: "sailpoint.svg" },
+ style: { brandColor: "#011E69", logo: "sailpoint.svg" },
},
],
})
@@ -100,19 +124,19 @@ export const { handle, signIn, signOut } = SvelteKitAuth({
clientSecret: env.ISC_CLIENT_SECRET!,
authorization: {
url: `${env.ISC_BASE_URL!}/oauth/authorize`,
- params: { scope: 'sp:scopes:all' },
+ params: { scope: "sp:scopes:all" },
},
token: `${env.ISC_BASE_API_URL!}/oauth/token`,
userinfo: `${env.ISC_BASE_API_URL!}/oauth/userinfo`,
profile(profile) {
return {
- id: profile.id,
- email: profile.email,
- name: profile.uid,
- image: null
+ id: profile.id,
+ email: profile.email,
+ name: profile.uid,
+ image: null,
}
},
- style: { text: "#011E69", bg: "#fff", logo: "sailpoint.svg" },
+ style: { brandColor: "#011E69", logo: "sailpoint.svg" },
},
],
})
@@ -124,49 +148,58 @@ export const { handle, signIn, signOut } = SvelteKitAuth({
```ts filename="/src/app.ts"
import { ExpressAuth } from "@auth/express"
-app.use("/auth/*", ExpressAuth({ providers: [
- {
- id: "identitySecureCloud",
- name: "Identity Secure Cloud",
- type: "oauth",
- clientId: process.env.ISC_CLIENT_ID!,
- clientSecret: process.env.ISC_CLIENT_SECRET!,
- authorization: {
- url: `${process.env.ISC_BASE_URL!}/oauth/authorize`,
- params: { scope: 'sp:scopes:all' },
- },
- token: `${process.env.ISC_BASE_API_URL!}/oauth/token`,
- userinfo: `${process.env.ISC_BASE_API_URL!}/oauth/userinfo`,
- profile(profile) {
- return {
+app.use(
+ "/auth/*",
+ ExpressAuth({
+ providers: [
+ {
+ id: "identitySecureCloud",
+ name: "Identity Secure Cloud",
+ type: "oauth",
+ clientId: process.env.ISC_CLIENT_ID!,
+ clientSecret: process.env.ISC_CLIENT_SECRET!,
+ authorization: {
+ url: `${process.env.ISC_BASE_URL!}/oauth/authorize`,
+ params: { scope: "sp:scopes:all" },
+ },
+ token: `${process.env.ISC_BASE_API_URL!}/oauth/token`,
+ userinfo: `${process.env.ISC_BASE_API_URL!}/oauth/userinfo`,
+ profile(profile) {
+ return {
id: profile.id,
email: profile.email,
name: profile.uid,
- image: null
- }
+ image: null,
+ }
+ },
+ style: { brandColor: "#011E69", logo: "sailpoint.svg" },
},
- style: { text: "#011E69", bg: "#fff", logo: "sailpoint.svg" },
- },
-] }))
+ ],
+ })
+)
```
-Your `userprofile` endpoint will return more fields, but by default the [User table](https://authjs.dev/getting-started/database#models) only supports `id`, `name`, `email`, and `image`. Therefore, if you'd like to use any of the following fields, make sure you modify the `User` table schema in whichever adapter / database you're using.
+### Profile
+
+The SailPoint `userprofile` endpoint will return more fields, but by default the [User table](/getting-started/database#models) only supports `id`, `name`, `email`, and `image`. Therefore, if you'd like to use any of the following fields and you're using a database adapter with Auth.js, make sure you modify the `User` table schema in whichever adapter and database you're using. Then you can additionally return any of these fields from the `profile` callback above.
+
+The available fields from the SailPoint `userprofile` endpoint response include the following.
```ts
-tenant: profile.tenant,
-id: profile.id,
-uid: profile.uid,
-email: profile.email,
-phone: profile.phone,
-workPhone: profile.workPhone,
-firstname: profile.firstname,
-lastname: profile.lastname,
-capabilities: profile.capabilities,
-displayName: profile.displayName,
-name: profile.uid
+type SailPointProfile = {
+ tenant: string
+ id: string
+ uid: string
+ email: string
+ phone: string
+ workPhone: string
+ firstname: string
+ lastname: string
+ capabilities: string
+ displayName: string
+ name: string
+}
```
-
-The above fields will all be available in the `profile` callback.
From 4bec0462b42b6879d3a3ccc8a1f9b7ba48658f15 Mon Sep 17 00:00:00 2001
From: ndom91
Date: Fri, 10 May 2024 15:45:38 +0200
Subject: [PATCH 14/44] chore(sailpoint): cleanup example code
---
.../getting-started/providers/sailpoint.mdx | 28 +++++++++----------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/docs/pages/getting-started/providers/sailpoint.mdx b/docs/pages/getting-started/providers/sailpoint.mdx
index 49c7efdd98..2c41317b9c 100644
--- a/docs/pages/getting-started/providers/sailpoint.mdx
+++ b/docs/pages/getting-started/providers/sailpoint.mdx
@@ -117,17 +117,17 @@ import { env } from "$env/dynamic/prviate"
export const { handle, signIn, signOut } = SvelteKitAuth({
providers: [
{
- id: "identitySecureCloud",
- name: "Identity Secure Cloud",
+ id: "sailpoint",
+ name: "SailPoint",
type: "oauth",
- clientId: env.ISC_CLIENT_ID!,
- clientSecret: env.ISC_CLIENT_SECRET!,
+ clientId: env.AUTH_SAILPOINT_ID!,
+ clientSecret: env.AUTH_SAILPOINT_SECRET!,
authorization: {
- url: `${env.ISC_BASE_URL!}/oauth/authorize`,
+ url: `${env.AUTH_SAILPOINT_BASE_URL!}/oauth/authorize`,
params: { scope: "sp:scopes:all" },
},
- token: `${env.ISC_BASE_API_URL!}/oauth/token`,
- userinfo: `${env.ISC_BASE_API_URL!}/oauth/userinfo`,
+ token: `${env.AUTH_SAILPOINT_BASE_API_URL!}/oauth/token`,
+ userinfo: `${env.AUTH_SAILPOINT_BASE_API_URL!}/oauth/userinfo`,
profile(profile) {
return {
id: profile.id,
@@ -153,17 +153,17 @@ app.use(
ExpressAuth({
providers: [
{
- id: "identitySecureCloud",
- name: "Identity Secure Cloud",
+ id: "sailpoint",
+ name: "SailPoint",
type: "oauth",
- clientId: process.env.ISC_CLIENT_ID!,
- clientSecret: process.env.ISC_CLIENT_SECRET!,
+ clientId: process.env.AUTH_SAILPOINT_ID!,
+ clientSecret: process.env.AUTH_SAILPOINT_SECRET!,
authorization: {
- url: `${process.env.ISC_BASE_URL!}/oauth/authorize`,
+ url: `${process.env.AUTH_SAILPOINT_BASE_URL!}/oauth/authorize`,
params: { scope: "sp:scopes:all" },
},
- token: `${process.env.ISC_BASE_API_URL!}/oauth/token`,
- userinfo: `${process.env.ISC_BASE_API_URL!}/oauth/userinfo`,
+ token: `${process.env.AUTH_SAILPOINT_BASE_API_URL!}/oauth/token`,
+ userinfo: `${process.env.AUTH_SAILPOINT_BASE_API_URL!}/oauth/userinfo`,
profile(profile) {
return {
id: profile.id,
From 5e55331c6e425dffc14e8d6d21547b3f8443d1f9 Mon Sep 17 00:00:00 2001
From: Nico Domino
Date: Fri, 10 May 2024 15:49:56 +0200
Subject: [PATCH 15/44] fix(core): update WebAuthn `authenticator` schemas and
types (#10861)
Co-authored-by: Julius Marminge
---
.../pages/getting-started/adapters/prisma.mdx | 12 ++-
.../authentication/webauthn.mdx | 3 +-
packages/adapter-prisma/prisma/schema.prisma | 3 +-
packages/adapter-prisma/src/index.ts | 43 +++--------
packages/adapter-unstorage/src/index.ts | 74 +++++++------------
.../adapter-unstorage/test/filesystem.test.ts | 19 +++--
.../adapter-unstorage/test/memory.test.ts | 16 ++--
.../adapter-unstorage/test/redis-json.test.ts | 15 ++--
packages/adapter-unstorage/test/redis.test.ts | 20 ++---
packages/adapter-unstorage/test/test.sh | 2 +-
packages/core/src/lib/utils/webauthn-utils.ts | 2 +-
packages/core/src/types.ts | 2 +-
packages/utils/adapter.ts | 4 +-
pnpm-lock.yaml | 33 ++++++---
14 files changed, 112 insertions(+), 136 deletions(-)
diff --git a/docs/pages/getting-started/adapters/prisma.mdx b/docs/pages/getting-started/adapters/prisma.mdx
index 9f44474ed2..3dc0d21a59 100644
--- a/docs/pages/getting-started/adapters/prisma.mdx
+++ b/docs/pages/getting-started/adapters/prisma.mdx
@@ -222,7 +222,6 @@ model VerificationToken {
// Optional for WebAuthn support
model Authenticator {
- id String @id @default(cuid())
credentialID String @unique
userId String
providerAccountId String
@@ -233,6 +232,8 @@ model Authenticator {
transports String?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
+
+ @@id([userId, credentialID])
}
```
@@ -311,7 +312,6 @@ model VerificationToken {
// Optional for WebAuthn support
model Authenticator {
- id String @id @default(cuid())
credentialID String @unique
userId String
providerAccountId String
@@ -322,6 +322,8 @@ model Authenticator {
transports String?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
+
+ @@id([userId, credentialID])
}
```
@@ -405,7 +407,6 @@ model VerificationToken {
// Optional for WebAuthn support
model Authenticator {
- id String @id @default(cuid())
credentialID String @unique
userId String
providerAccountId String
@@ -416,6 +417,8 @@ model Authenticator {
transports String?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
+
+ @@id([userId, credentialID])
}
```
@@ -491,7 +494,6 @@ model VerificationToken {
// Optional for WebAuthn support
model Authenticator {
- id String @id @default(auto()) @map("_id") @db.ObjectId
credentialID String @unique
userId String @db.ObjectId
providerAccountId String
@@ -502,6 +504,8 @@ model Authenticator {
transports String?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
+
+ @@id([userId, credentialID])
}
```
diff --git a/docs/pages/getting-started/authentication/webauthn.mdx b/docs/pages/getting-started/authentication/webauthn.mdx
index 23b51ef342..a24f227c8e 100644
--- a/docs/pages/getting-started/authentication/webauthn.mdx
+++ b/docs/pages/getting-started/authentication/webauthn.mdx
@@ -39,7 +39,6 @@ In short, the Passkeys provider requires an additional table called `Authenticat
```sql filename="./migration/add-webauthn-authenticator-table.sql"
-- CreateTable
CREATE TABLE "Authenticator" (
- "id" TEXT NOT NULL PRIMARY KEY,
"credentialID" TEXT NOT NULL,
"userId" TEXT NOT NULL,
"providerAccountId" TEXT NOT NULL,
@@ -48,9 +47,11 @@ CREATE TABLE "Authenticator" (
"credentialDeviceType" TEXT NOT NULL,
"credentialBackedUp" BOOLEAN NOT NULL,
"transports" TEXT,
+ PRIMARY KEY ("userId", "credentialID"),
CONSTRAINT "Authenticator_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE
);
+
-- CreateIndex
CREATE UNIQUE INDEX "Authenticator_credentialID_key" ON "Authenticator"("credentialID");
```
diff --git a/packages/adapter-prisma/prisma/schema.prisma b/packages/adapter-prisma/prisma/schema.prisma
index 8e084ba6fc..60e5a0841b 100644
--- a/packages/adapter-prisma/prisma/schema.prisma
+++ b/packages/adapter-prisma/prisma/schema.prisma
@@ -52,7 +52,6 @@ model VerificationToken {
}
model Authenticator {
- id String @id @default(cuid())
credentialID String @unique
userId String
providerAccountId String
@@ -63,4 +62,6 @@ model Authenticator {
transports String?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
+
+ @@id([userId, credentialID])
}
diff --git a/packages/adapter-prisma/src/index.ts b/packages/adapter-prisma/src/index.ts
index 60fc22fb49..e3a74e04a2 100644
--- a/packages/adapter-prisma/src/index.ts
+++ b/packages/adapter-prisma/src/index.ts
@@ -19,7 +19,6 @@ import type { PrismaClient, Prisma } from "@prisma/client"
import type {
Adapter,
AdapterAccount,
- AdapterAuthenticator,
AdapterSession,
AdapterUser,
} from "@auth/core/adapters"
@@ -94,49 +93,25 @@ export function PrismaAdapter(
}) as Promise
},
async createAuthenticator(authenticator) {
- return p.authenticator
- .create({
- data: authenticator,
- })
- .then(fromDBAuthenticator)
+ return p.authenticator.create({
+ data: authenticator,
+ })
},
async getAuthenticator(credentialID) {
- const authenticator = await p.authenticator.findUnique({
+ return p.authenticator.findUnique({
where: { credentialID },
})
- return authenticator ? fromDBAuthenticator(authenticator) : null
},
async listAuthenticatorsByUserId(userId) {
- const authenticators = await p.authenticator.findMany({
+ return p.authenticator.findMany({
where: { userId },
})
-
- return authenticators.map(fromDBAuthenticator)
},
async updateAuthenticatorCounter(credentialID, counter) {
- return p.authenticator
- .update({
- where: { credentialID: credentialID },
- data: { counter },
- })
- .then(fromDBAuthenticator)
+ return p.authenticator.update({
+ where: { credentialID },
+ data: { counter },
+ })
},
}
}
-
-type BasePrismaAuthenticator = Parameters<
- PrismaClient["authenticator"]["create"]
->[0]["data"]
-type PrismaAuthenticator = BasePrismaAuthenticator &
- Required>
-
-function fromDBAuthenticator(
- authenticator: PrismaAuthenticator
-): AdapterAuthenticator {
- const { transports, id, user, ...other } = authenticator
-
- return {
- ...other,
- transports: transports || undefined,
- }
-}
diff --git a/packages/adapter-unstorage/src/index.ts b/packages/adapter-unstorage/src/index.ts
index 27f39ff775..41a164fc3e 100644
--- a/packages/adapter-unstorage/src/index.ts
+++ b/packages/adapter-unstorage/src/index.ts
@@ -83,7 +83,7 @@ export const defaultOptions = {
sessionByUserIdKeyPrefix: "user:session:by-user-id:",
userKeyPrefix: "user:",
verificationTokenKeyPrefix: "user:token:",
- authenticatorKeyPrefix: "authenticator:id:",
+ authenticatorKeyPrefix: "authenticator:",
authenticatorUserKeyPrefix: "authenticator:by-user-id:",
useItemRaw: false,
}
@@ -94,7 +94,7 @@ function isDate(value: any) {
return value && isoDateRE.test(value) && !isNaN(Date.parse(value))
}
-export function hydrateDates(json: object) {
+export function hydrateDates(json: Record) {
return Object.entries(json).reduce((acc, [key, val]) => {
acc[key] = isDate(val) ? new Date(val as string) : val
return acc
@@ -134,15 +134,6 @@ export function UnstorageAdapter(
}
}
- async function getItems(key: string[]) {
- if (mergedOptions.useItemRaw) {
- // Unstorage missing method to get multiple items raw, i.e. `getItemsRaw`
- return JSON.stringify(await storage.getItems(key))
- } else {
- return await storage.getItems(key)
- }
- }
-
async function setItem(key: string, value: string) {
if (mergedOptions.useItemRaw) {
return await storage.setItemRaw(key, value)
@@ -151,7 +142,7 @@ export function UnstorageAdapter(
}
}
- const setObjectAsJson = async (key: string, obj: any) => {
+ const setObjectAsJson = async (key: string, obj: Record) => {
if (mergedOptions.useItemRaw) {
await storage.setItemRaw(key, obj)
} else {
@@ -213,11 +204,21 @@ export function UnstorageAdapter(
credentialId: string,
authenticator: AdapterAuthenticator
): Promise => {
+ let newCredsToSet = [credentialId]
+
+ const getItemReturn = await getItem(
+ `${authenticatorUserKeyPrefix}${authenticator.userId}`
+ )
+
+ if (getItemReturn && getItemReturn[0] !== newCredsToSet[0]) {
+ newCredsToSet.push(...getItemReturn)
+ }
+
await Promise.all([
setObjectAsJson(authenticatorKeyPrefix + credentialId, authenticator),
setItem(
`${authenticatorUserKeyPrefix}${authenticator.userId}`,
- credentialId
+ JSON.stringify(newCredsToSet)
),
])
return authenticator
@@ -231,24 +232,19 @@ export function UnstorageAdapter(
return hydrateDates(authenticator)
}
- // TODO: This one doesn't really work with KV storage, as we can't set the same
- // key multiple times, they'll just overwrite one another. Maybe with some
- // additional logic to write an array as the value instead of overwriting
- // the pre-existing value. Probably in `setItems` implementation.
const getAuthenticatorByUserId = async (
userId: string
): Promise => {
- const credentialIds = await getItems([
- `${authenticatorUserKeyPrefix}${userId}`,
- ])
- if (!credentialIds.length) return []
+ const credentialIds = await getItem(
+ `${authenticatorUserKeyPrefix}${userId}`
+ )
- const authenticators = []
- for (const credentialId of credentialIds) {
- const credentialValue =
- typeof credentialId === "string" ? credentialId : credentialId.value
+ if (!credentialIds) return []
- const authenticator = await getAuthenticator(credentialValue as string)
+ const authenticators: AdapterAuthenticator[] = []
+
+ for (const credentialId of credentialIds) {
+ const authenticator = await getAuthenticator(credentialId)
if (authenticator) {
hydrateDates(authenticator)
@@ -362,36 +358,22 @@ export function UnstorageAdapter(
])
},
async createAuthenticator(authenticator) {
- setAuthenticator(authenticator.credentialID, authenticator)
- return fromDBAuthenticator(authenticator)!
+ await setAuthenticator(authenticator.credentialID, authenticator)
+ return authenticator
},
async getAuthenticator(credentialID) {
- const authenticator = await getAuthenticator(credentialID)
- return fromDBAuthenticator(authenticator)
+ return getAuthenticator(credentialID)
},
async listAuthenticatorsByUserId(userId) {
const user = await getUser(userId)
if (!user) return []
- const authenticators = await getAuthenticatorByUserId(user.id)
- return authenticators
+ return getAuthenticatorByUserId(user.id)
},
async updateAuthenticatorCounter(credentialID, counter) {
const authenticator = await getAuthenticator(credentialID)
authenticator.counter = Number(counter)
- setAuthenticator(credentialID, authenticator)
- return fromDBAuthenticator(authenticator)!
+ await setAuthenticator(credentialID, authenticator)
+ return authenticator
},
}
}
-
-function fromDBAuthenticator(
- authenticator: AdapterAuthenticator & { id?: string; user?: string }
-): AdapterAuthenticator | null {
- if (!authenticator) return null
- const { transports, id, user, ...other } = authenticator
-
- return {
- ...other,
- transports: transports || undefined,
- }
-}
diff --git a/packages/adapter-unstorage/test/filesystem.test.ts b/packages/adapter-unstorage/test/filesystem.test.ts
index ed60d36c2b..bd0c805806 100644
--- a/packages/adapter-unstorage/test/filesystem.test.ts
+++ b/packages/adapter-unstorage/test/filesystem.test.ts
@@ -9,41 +9,40 @@ const storage = createStorage({
runBasicTests({
adapter: UnstorageAdapter(storage, { baseKeyPrefix: "testApp:" }),
- // TODO: Reenable; failing in CI, passing locally
- testWebAuthnMethods: false,
- // Currently not fully implemented in KV Store
- skipTests: ["listAuthenticatorsByUserId"],
+ testWebAuthnMethods: true,
db: {
disconnect: storage.dispose,
async user(id: string) {
- const data = await storage.getItem(`testApp:user:${id}`)
+ const data = await storage.getItem>(
+ `testApp:user:${id}`
+ )
if (!data) return null
return hydrateDates(data)
},
async account({ provider, providerAccountId }) {
- const data = await storage.getItem(
+ const data = await storage.getItem>(
`testApp:user:account:${provider}:${providerAccountId}`
)
if (!data) return null
return hydrateDates(data)
},
async session(sessionToken) {
- const data = await storage.getItem(
+ const data = await storage.getItem>(
`testApp:user:session:${sessionToken}`
)
if (!data) return null
return hydrateDates(data)
},
async verificationToken(where) {
- const data = await storage.getItem(
+ const data = await storage.getItem>(
`testApp:user:token:${where.identifier}:${where.token}`
)
if (!data) return null
return hydrateDates(data)
},
async authenticator(id) {
- const data = await storage.getItem(
- `testApp:authenticator:id:${id}`
+ const data = await storage.getItem>(
+ `testApp:authenticator:${id}`
)
if (!data) return null
return hydrateDates(data)
diff --git a/packages/adapter-unstorage/test/memory.test.ts b/packages/adapter-unstorage/test/memory.test.ts
index 0ad1c52d47..d05725e5a7 100644
--- a/packages/adapter-unstorage/test/memory.test.ts
+++ b/packages/adapter-unstorage/test/memory.test.ts
@@ -7,39 +7,39 @@ const storage = createStorage()
runBasicTests({
adapter: UnstorageAdapter(storage, { baseKeyPrefix: "testApp:" }),
testWebAuthnMethods: true,
- // Currently not fully implemented in KV Store
- skipTests: ["listAuthenticatorsByUserId"],
db: {
disconnect: storage.dispose,
async user(id: string) {
- const data = await storage.getItem(`testApp:user:${id}`)
+ const data = await storage.getItem>(
+ `testApp:user:${id}`
+ )
if (!data) return null
return hydrateDates(data)
},
async account({ provider, providerAccountId }) {
- const data = await storage.getItem(
+ const data = await storage.getItem>(
`testApp:user:account:${provider}:${providerAccountId}`
)
if (!data) return null
return hydrateDates(data)
},
async session(sessionToken) {
- const data = await storage.getItem(
+ const data = await storage.getItem>(
`testApp:user:session:${sessionToken}`
)
if (!data) return null
return hydrateDates(data)
},
async verificationToken(where) {
- const data = await storage.getItem(
+ const data = await storage.getItem>(
`testApp:user:token:${where.identifier}:${where.token}`
)
if (!data) return null
return hydrateDates(data)
},
async authenticator(id) {
- const data = await storage.getItem(
- `testApp:authenticator:id:${id}`
+ const data = await storage.getItem>(
+ `testApp:authenticator:${id}`
)
if (!data) return null
return hydrateDates(data)
diff --git a/packages/adapter-unstorage/test/redis-json.test.ts b/packages/adapter-unstorage/test/redis-json.test.ts
index 78f221153d..5c5e5c2c2f 100644
--- a/packages/adapter-unstorage/test/redis-json.test.ts
+++ b/packages/adapter-unstorage/test/redis-json.test.ts
@@ -6,7 +6,6 @@ import { createClient } from "redis"
import type { RedisClientType, RedisClientOptions } from "redis"
// TODO: These tests just hang and time out so currently we are skipping them
-
const redisJSONDriver = defineDriver((options: RedisClientOptions) => {
let redisClient: RedisClientType
const getRedisClient = async () => {
@@ -72,34 +71,36 @@ runBasicTests({
db: {
disconnect: storage.dispose,
async user(id: string) {
- const data = await storage.getItemRaw(`testApp:user:${id}`)
+ const data = await storage.getItemRaw>(
+ `testApp:user:${id}`
+ )
if (!data) return null
return hydrateDates(data)
},
async account({ provider, providerAccountId }) {
- const data = await storage.getItemRaw(
+ const data = await storage.getItemRaw>(
`testApp:user:account:${provider}:${providerAccountId}`
)
if (!data) return null
return hydrateDates(data)
},
async session(sessionToken) {
- const data = await storage.getItemRaw(
+ const data = await storage.getItemRaw>(
`testApp:user:session:${sessionToken}`
)
if (!data) return null
return hydrateDates(data)
},
async verificationToken(where) {
- const data = await storage.getItemRaw(
+ const data = await storage.getItemRaw>(
`testApp:user:token:${where.identifier}:${where.token}`
)
if (!data) return null
return hydrateDates(data)
},
async authenticator(id) {
- const data = await storage.getItemRaw(
- `testApp:authenticator:id:${id}`
+ const data = await storage.getItemRaw>(
+ `testApp:authenticator:${id}`
)
if (!data) return null
return hydrateDates(data)
diff --git a/packages/adapter-unstorage/test/redis.test.ts b/packages/adapter-unstorage/test/redis.test.ts
index 07b47008c2..19be636f0c 100644
--- a/packages/adapter-unstorage/test/redis.test.ts
+++ b/packages/adapter-unstorage/test/redis.test.ts
@@ -4,45 +4,47 @@ import { hydrateDates, UnstorageAdapter } from "../src"
import redisDriver from "unstorage/drivers/redis"
const storage = createStorage({
- driver: redisDriver({ username: "default" }),
+ driver: redisDriver({
+ username: "default",
+ }),
})
runBasicTests({
adapter: UnstorageAdapter(storage, { baseKeyPrefix: "testApp:" }),
testWebAuthnMethods: true,
- // Currently not fully implemented in KV Store
- skipTests: ["listAuthenticatorsByUserId"],
db: {
disconnect: storage.dispose,
async user(id: string) {
- const data = await storage.getItem(`testApp:user:${id}`)
+ const data = await storage.getItem>(
+ `testApp:user:${id}`
+ )
if (!data) return null
return hydrateDates(data)
},
async account({ provider, providerAccountId }) {
- const data = await storage.getItem(
+ const data = await storage.getItem>(
`testApp:user:account:${provider}:${providerAccountId}`
)
if (!data) return null
return hydrateDates(data)
},
async session(sessionToken) {
- const data = await storage.getItem(
+ const data = await storage.getItem>(
`testApp:user:session:${sessionToken}`
)
if (!data) return null
return hydrateDates(data)
},
async verificationToken(where) {
- const data = await storage.getItem(
+ const data = await storage.getItem>(
`testApp:user:token:${where.identifier}:${where.token}`
)
if (!data) return null
return hydrateDates(data)
},
async authenticator(id) {
- const data = await storage.getItem(
- `testApp:authenticator:id:${id}`
+ const data = await storage.getItem>(
+ `testApp:authenticator:${id}`
)
if (!data) return null
return hydrateDates(data)
diff --git a/packages/adapter-unstorage/test/test.sh b/packages/adapter-unstorage/test/test.sh
index 1f22f51e64..256517e5dc 100755
--- a/packages/adapter-unstorage/test/test.sh
+++ b/packages/adapter-unstorage/test/test.sh
@@ -6,7 +6,7 @@ CONTAINER_NAME=authjs-unstorage-test
docker run -d --rm \
-p 6379:6379 \
--name ${CONTAINER_NAME} \
- redis/redis-stack-server:6.2.6-v10
+ redis/redis-stack:7.2.0-v10
sleep 10
diff --git a/packages/core/src/lib/utils/webauthn-utils.ts b/packages/core/src/lib/utils/webauthn-utils.ts
index 01ae7f1931..eaa3b0febb 100644
--- a/packages/core/src/lib/utils/webauthn-utils.ts
+++ b/packages/core/src/lib/utils/webauthn-utils.ts
@@ -523,7 +523,7 @@ export function transportsToString(
}
export function stringToTransports(
- tstring: string | undefined
+ tstring: string | undefined | null
): InternalAuthenticator["transports"] {
return tstring
? (tstring.split(",") as InternalAuthenticator["transports"])
diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts
index be2f78f545..88d8465d7e 100644
--- a/packages/core/src/types.ts
+++ b/packages/core/src/types.ts
@@ -389,7 +389,7 @@ export interface Authenticator {
/**
* Concatenated transport flags.
*/
- transports?: string
+ transports?: string | null
/**
* Device type of the authenticator.
*/
diff --git a/packages/utils/adapter.ts b/packages/utils/adapter.ts
index b4124468f3..edcbc2a1ec 100644
--- a/packages/utils/adapter.ts
+++ b/packages/utils/adapter.ts
@@ -548,8 +548,8 @@ export async function runBasicTests(options: TestOptions) {
const authenticators1 = await adapter.listAuthenticatorsByUserId(user1.id)
expect(authenticators1).not.toBeNull()
- expect([authenticator1, authenticator2]).toMatchObject(
- authenticators1 || []
+ expect([authenticator2, authenticator1]).toEqual(
+ expect.arrayContaining(authenticators1 || [])
)
const authenticators2 = await adapter.listAuthenticatorsByUserId(user2.id)
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index b053d9db16..0ee84388cb 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -246,7 +246,7 @@ importers:
version: 4.2.3(next@14.2.1)
nextra:
specifier: 3.0.0-alpha.22
- version: 3.0.0-alpha.22(@types/react@18.2.78)(next@14.2.1)(react-dom@18.2.0)(react@18.2.0)(typescript@5.3.3)
+ version: 3.0.0-alpha.22(@types/react@18.2.78)(next@14.2.1)(react-dom@18.2.0)(react@18.2.0)(typescript@5.4.5)
nextra-theme-docs:
specifier: 3.0.0-alpha.22
version: 3.0.0-alpha.22(next@14.2.1)(nextra@3.0.0-alpha.22)(react-dom@18.2.0)(react@18.2.0)
@@ -344,7 +344,7 @@ importers:
version: 0.20.17
drizzle-orm:
specifier: ^0.30.9
- version: 0.30.9(@types/better-sqlite3@7.6.9)(better-sqlite3@9.5.0)(mysql2@3.9.7)(postgres@3.4.3)
+ version: 0.30.9(mysql2@3.9.7)(postgres@3.4.3)
libsql:
specifier: ^0.3.18
version: 0.3.18
@@ -12852,6 +12852,17 @@ packages:
ms: 2.1.3
dev: true
+ /debug@4.3.4:
+ resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+ dependencies:
+ ms: 2.1.2
+
/debug@4.3.4(supports-color@5.5.0):
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
engines: {node: '>=6.0'}
@@ -13221,7 +13232,7 @@ packages:
- supports-color
dev: true
- /drizzle-orm@0.30.9(@types/better-sqlite3@7.6.9)(better-sqlite3@9.5.0)(mysql2@3.9.7)(postgres@3.4.3):
+ /drizzle-orm@0.30.9(mysql2@3.9.7)(postgres@3.4.3):
resolution: {integrity: sha512-VOiCFsexErmgqvNCOmbzmqDCZzZsHoz6SkWAjTFxsTr1AllKDbDJ2+GgedLXsXMDgpg/ljDG1zItIFeZtiO2LA==}
peerDependencies:
'@aws-sdk/client-rds-data': '>=3'
@@ -16131,13 +16142,13 @@ packages:
loose-envify: 1.4.0
dev: true
- /ioredis@5.3.2:
- resolution: {integrity: sha512-1DKMMzlIHM02eBBVOFQ1+AolGjs6+xEcM4PDL7NqOS6szq7H9jSaEkIUH6/a5Hl241LzW6JLSiAbNvTQjUupUA==}
+ /ioredis@5.4.1:
+ resolution: {integrity: sha512-2YZsvl7jopIa1gaePkeMtd9rAcSjOOjPtpcLlOeusyO+XH2SK5ZcT+UCrElPP+WVIInh2TzeI4XW9ENaSLVVHA==}
engines: {node: '>=12.22.0'}
dependencies:
'@ioredis/commands': 1.2.0
cluster-key-slot: 1.1.2
- debug: 4.3.4(supports-color@8.1.1)
+ debug: 4.3.4
denque: 2.1.0
lodash.defaults: 4.2.0
lodash.isarguments: 3.1.0
@@ -19219,14 +19230,14 @@ packages:
intersection-observer: 0.12.2
next: 14.2.1(@babel/core@7.23.9)(@playwright/test@1.41.2)(react-dom@18.2.0)(react@18.2.0)
next-themes: 0.2.1(next@14.2.1)(react-dom@18.2.0)(react@18.2.0)
- nextra: 3.0.0-alpha.22(@types/react@18.2.78)(next@14.2.1)(react-dom@18.2.0)(react@18.2.0)(typescript@5.3.3)
+ nextra: 3.0.0-alpha.22(@types/react@18.2.78)(next@14.2.1)(react-dom@18.2.0)(react@18.2.0)(typescript@5.4.5)
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
scroll-into-view-if-needed: 3.1.0
zod: 3.22.4
dev: false
- /nextra@3.0.0-alpha.22(@types/react@18.2.78)(next@14.2.1)(react-dom@18.2.0)(react@18.2.0)(typescript@5.3.3):
+ /nextra@3.0.0-alpha.22(@types/react@18.2.78)(next@14.2.1)(react-dom@18.2.0)(react@18.2.0)(typescript@5.4.5):
resolution: {integrity: sha512-4V1kLs0MiQ1KE/Dh1cnLc100Ibyo/PY46v1NdRzrYe7uzCBcSGTiG9OwHTE/34wUwbM5N7TptiDOlV79BBZ0Ng==}
engines: {node: '>=18'}
peerDependencies:
@@ -23207,7 +23218,7 @@ packages:
sorcery: 0.10.0
strip-indent: 3.0.0
svelte: 4.2.9
- typescript: 5.4.5
+ typescript: 5.3.3
dev: true
/svelte-preprocess@5.1.3(postcss@8.4.38)(svelte@4.2.9)(typescript@5.2.2):
@@ -23255,7 +23266,7 @@ packages:
sorcery: 0.11.0
strip-indent: 3.0.0
svelte: 4.2.9
- typescript: 5.4.5
+ typescript: 5.2.2
dev: true
/svelte2tsx@0.7.0(svelte@4.2.9)(typescript@5.4.5):
@@ -24491,7 +24502,7 @@ packages:
chokidar: 3.5.3
destr: 2.0.2
h3: 1.10.1
- ioredis: 5.3.2
+ ioredis: 5.4.1
listhen: 1.5.6
lru-cache: 10.2.0
mri: 1.2.0
From 4dda6affbb2f1fa40ef9ede8764ca331024a3092 Mon Sep 17 00:00:00 2001
From: Nico Domino
Date: Fri, 10 May 2024 18:55:57 +0200
Subject: [PATCH 16/44] chore(docs): add default `og:image` (#10777)
---
docs/app/api/og/Inter-Black.ttf | Bin 0 -> 294396 bytes
docs/app/api/og/Inter-Bold.ttf | Bin 0 -> 293448 bytes
docs/app/api/og/Inter-Light.ttf | Bin 0 -> 288088 bytes
docs/app/api/og/route.tsx | 155 ++++++++++++++++++
.../{Docsearch => DocSearch}/hit.tsx | 0
.../{Docsearch => DocSearch}/index.tsx | 0
.../{Docsearch => DocSearch}/searchInput.tsx | 0
.../{Docsearch => DocSearch}/wrapper.tsx | 4 +-
docs/components/Footer/index.tsx | 2 +-
docs/components/LogosMarquee/index.tsx | 4 +-
.../content/index.tsx | 6 +-
docs/components/RichTabs/useRichTabs.ts | 6 +-
docs/components/Tooltip/index.tsx | 2 +-
docs/next-env.d.ts | 1 +
docs/theme.config.tsx | 10 +-
docs/tsconfig.json | 11 +-
docs/utils/useInkeepSettings.ts | 6 +-
17 files changed, 187 insertions(+), 20 deletions(-)
create mode 100644 docs/app/api/og/Inter-Black.ttf
create mode 100644 docs/app/api/og/Inter-Bold.ttf
create mode 100644 docs/app/api/og/Inter-Light.ttf
create mode 100644 docs/app/api/og/route.tsx
rename docs/components/{Docsearch => DocSearch}/hit.tsx (100%)
rename docs/components/{Docsearch => DocSearch}/index.tsx (100%)
rename docs/components/{Docsearch => DocSearch}/searchInput.tsx (100%)
rename docs/components/{Docsearch => DocSearch}/wrapper.tsx (96%)
diff --git a/docs/app/api/og/Inter-Black.ttf b/docs/app/api/og/Inter-Black.ttf
new file mode 100644
index 0000000000000000000000000000000000000000..565375773523cf29adce38a9fbf71a3badf2082c
GIT binary patch
literal 294396
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