From 748d7dc8fb4d8188d81b5e171a21943369ada642 Mon Sep 17 00:00:00 2001
From: Luke Jones
Date: Sun, 19 Sep 2021 17:54:03 +1000
Subject: [PATCH 01/13] Sequelize adapter
---
.github/labeler.yml | 3 +
packages/sequelize/CHANGELOG.md | 4 +
packages/sequelize/README.md | 63 ++++++++++
packages/sequelize/jest.config.js | 1 +
packages/sequelize/logo.svg | 1 +
packages/sequelize/package.json | 38 ++++++
packages/sequelize/src/index.ts | 156 +++++++++++++++++++++++++
packages/sequelize/src/schema.ts | 39 +++++++
packages/sequelize/tests/index.test.ts | 45 +++++++
packages/sequelize/tsconfig.json | 8 ++
yarn.lock | 71 ++++++++++-
11 files changed, 426 insertions(+), 3 deletions(-)
create mode 100644 packages/sequelize/CHANGELOG.md
create mode 100644 packages/sequelize/README.md
create mode 100644 packages/sequelize/jest.config.js
create mode 100644 packages/sequelize/logo.svg
create mode 100644 packages/sequelize/package.json
create mode 100644 packages/sequelize/src/index.ts
create mode 100644 packages/sequelize/src/schema.ts
create mode 100644 packages/sequelize/tests/index.test.ts
create mode 100644 packages/sequelize/tsconfig.json
diff --git a/.github/labeler.yml b/.github/labeler.yml
index 9be9e25c..9d234437 100644
--- a/.github/labeler.yml
+++ b/.github/labeler.yml
@@ -17,6 +17,9 @@ firebase:
pouchdb:
- packages/pouchdb/**/*
+sequelize:
+ - packages/sequelize/**/*
+
documentation:
- ./**/*.md
diff --git a/packages/sequelize/CHANGELOG.md b/packages/sequelize/CHANGELOG.md
new file mode 100644
index 00000000..e4d87c4d
--- /dev/null
+++ b/packages/sequelize/CHANGELOG.md
@@ -0,0 +1,4 @@
+# Change Log
+
+All notable changes to this project will be documented in this file.
+See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
diff --git a/packages/sequelize/README.md b/packages/sequelize/README.md
new file mode 100644
index 00000000..21cbb098
--- /dev/null
+++ b/packages/sequelize/README.md
@@ -0,0 +1,63 @@
+
+
+
+
Sequelize Adapter - NextAuth.js
+
+ Open Source. Full Stack. Own Your Data.
+
+
+
+
+
+
+
+
+## Overview
+
+This is the Sequelize Adapter for [`next-auth`](https://next-auth.js.org). This package can only be used in conjunction with the primary `next-auth` package. It is not a standalone package.
+
+You can find the Sequelize schema in the docs at [next-auth.js.org/adapters/sequelize](https://next-auth.js.org/adapters/sequelize).
+
+## Getting Started
+
+1. Install `next-auth` and `@next-auth/sequelize-adapter` as well as `sequelize` and your [database driver](https://sequelize.org/master/manual/getting-started.html) of choice.
+
+```js
+npm install next-auth @next-auth/sequeluze-adapter sequelize sqlite3
+npm install --save-dev sequelize
+```
+
+2. Add this adapter to your `pages/api/[...nextauth].js` next-auth configuration object.
+
+```js
+import NextAuth from "next-auth"
+import Providers from "next-auth/providers"
+import SequelizeAdapter, { userSchema } from "@next-auth/sequelize-adapter"
+
+const sequelize = new Sequelize("sqlite::memory:")
+
+// To override the existing models, make your new models available like so:
+sequelize.models.User = sequelize.define("user", { ...userSchema, ...myCustomUserSchema })
+
+// For more information on each option (and a full list of options) go to
+// https://next-auth.js.org/configuration/options
+export default NextAuth({
+ // https://next-auth.js.org/configuration/providers
+ providers: [
+ Providers.Google({
+ clientId: process.env.GOOGLE_ID,
+ clientSecret: process.env.GOOGLE_SECRET,
+ }),
+ ],
+ adapter: SequelizeAdapter(sequelize)
+ ...
+})
+```
+
+## Contributing
+
+We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/adapters/blob/main/CONTRIBUTING.md).
+
+## License
+
+ISC
diff --git a/packages/sequelize/jest.config.js b/packages/sequelize/jest.config.js
new file mode 100644
index 00000000..219c8d17
--- /dev/null
+++ b/packages/sequelize/jest.config.js
@@ -0,0 +1 @@
+module.exports = require("../../jest.config")
diff --git a/packages/sequelize/logo.svg b/packages/sequelize/logo.svg
new file mode 100644
index 00000000..ab9c11fc
--- /dev/null
+++ b/packages/sequelize/logo.svg
@@ -0,0 +1 @@
+
diff --git a/packages/sequelize/package.json b/packages/sequelize/package.json
new file mode 100644
index 00000000..98a76796
--- /dev/null
+++ b/packages/sequelize/package.json
@@ -0,0 +1,38 @@
+{
+ "name": "@next-auth/sequelize-adapter",
+ "version": "1.0.0",
+ "description": "Sequelize adapter for next-auth.",
+ "homepage": "https://next-auth.js.org",
+ "repository": "https://github.com/nextauthjs/adapters",
+ "bugs": {
+ "url": "https://github.com/nextauthjs/next-auth/issues"
+ },
+ "author": "github.com/luke-j",
+ "main": "dist/index.js",
+ "license": "ISC",
+ "keywords": [
+ "next-auth",
+ "next.js",
+ "oauth",
+ "sequelize"
+ ],
+ "private": false,
+ "publishConfig": {
+ "access": "public"
+ },
+ "scripts": {
+ "test": "yarn build && jest",
+ "build": "tsc"
+ },
+ "files": [
+ "README.md",
+ "dist"
+ ],
+ "peerDependencies": {
+ "next-auth": ">=4",
+ "sequelize": "^6.6.5"
+ },
+ "devDependencies": {
+ "sequelize": "^6.6.5"
+ }
+}
diff --git a/packages/sequelize/src/index.ts b/packages/sequelize/src/index.ts
new file mode 100644
index 00000000..3028dbe4
--- /dev/null
+++ b/packages/sequelize/src/index.ts
@@ -0,0 +1,156 @@
+import type { Account as ApadterAccount } from "next-auth"
+import type {
+ Adapter,
+ AdapterUser,
+ AdapterSession,
+ VerificationToken,
+} from "next-auth/adapters"
+import { Sequelize, Model, ModelCtor } from "sequelize"
+import {
+ accountSchema,
+ userSchema,
+ sessionSchema,
+ verificationTokenSchema,
+} from "./schema"
+
+// @see https://sequelize.org/master/manual/typescript.html
+interface AccountInstance
+ extends Model>,
+ ApadterAccount {}
+interface UserInstance
+ extends Model>,
+ AdapterUser {}
+interface SessionInstance
+ extends Model>,
+ AdapterSession {}
+interface VerificationTokenInstance
+ extends Model>,
+ VerificationToken {}
+
+export { accountSchema, userSchema, sessionSchema, verificationTokenSchema }
+
+export default function SequelizeAdapter(client: Sequelize): Adapter {
+ const tableOptions = { underscored: true, timestamps: false }
+
+ const Account =
+ (client.models.Account as ModelCtor) ||
+ client.define("account", accountSchema, tableOptions)
+ const User =
+ (client.models.User as ModelCtor) ||
+ client.define("user", userSchema, tableOptions)
+ const Session =
+ (client.models.Session as ModelCtor) ||
+ client.define("session", sessionSchema, tableOptions)
+ const VerificationToken =
+ (client.models.VerificationToken as ModelCtor) ||
+ client.define(
+ "verificationToken",
+ verificationTokenSchema,
+ tableOptions
+ )
+
+ Account.belongsTo(User, { onDelete: "cascade" })
+ Session.belongsTo(User, { onDelete: "cascade" })
+
+ return {
+ async createUser(user) {
+ return await User.create(user)
+ },
+ async getUser(id) {
+ const userInstance = await User.findByPk(id)
+
+ return userInstance?.get({ plain: true }) ?? null
+ },
+ async getUserByEmail(email) {
+ const userInstance = await User.findOne({
+ where: { email },
+ })
+
+ return userInstance?.get({ plain: true }) ?? null
+ },
+ async getUserByAccount({ provider, providerAccountId }) {
+ const accountInstance = await Account.findOne({
+ where: { provider, providerAccountId },
+ })
+
+ if (!accountInstance) {
+ return null
+ }
+
+ const userInstance = await User.findByPk(accountInstance.userId)
+
+ return userInstance?.get({ plain: true }) ?? null
+ },
+ async updateUser(user) {
+ await User.update(user, { where: { id: user.id } })
+ const userInstance = await User.findByPk(user.id)
+
+ if (!userInstance) {
+ throw new Error("User does not exist")
+ }
+
+ return userInstance
+ },
+ async deleteUser(userId) {
+ const userInstance = await User.findByPk(userId)
+
+ await User.destroy({ where: { id: userId } })
+
+ return userInstance
+ },
+ async linkAccount(account) {
+ await Account.create(account)
+ },
+ async unlinkAccount({ provider, providerAccountId }) {
+ await Account.destroy({
+ where: { provider, providerAccountId },
+ })
+ },
+ async createSession(session) {
+ return await Session.create(session)
+ },
+ async getSessionAndUser(sessionToken) {
+ const sessionInstance = await Session.findOne({
+ where: { sessionToken },
+ })
+
+ if (!sessionInstance) {
+ return null
+ }
+
+ const userInstance = await User.findByPk(sessionInstance.userId)
+
+ if (!userInstance) {
+ return null
+ }
+
+ return {
+ session: sessionInstance?.get({ plain: true }),
+ user: userInstance?.get({ plain: true }),
+ }
+ },
+ async updateSession({ sessionToken, expires }) {
+ await Session.update(
+ { expires, sessionToken },
+ { where: { sessionToken } }
+ )
+
+ return await Session.findOne({ where: { sessionToken } })
+ },
+ async deleteSession(sessionToken) {
+ await Session.destroy({ where: { sessionToken } })
+ },
+ async createVerificationToken(token) {
+ return await VerificationToken.create(token)
+ },
+ async useVerificationToken({ identifier, token }) {
+ const tokenInstance = await VerificationToken.findOne({
+ where: { identifier, token },
+ })
+
+ await VerificationToken.destroy({ where: { identifier } })
+
+ return tokenInstance?.get({ plain: true }) ?? null
+ },
+ }
+}
diff --git a/packages/sequelize/src/schema.ts b/packages/sequelize/src/schema.ts
new file mode 100644
index 00000000..6309cfbb
--- /dev/null
+++ b/packages/sequelize/src/schema.ts
@@ -0,0 +1,39 @@
+import { DataTypes } from "sequelize"
+
+export const accountSchema = {
+ id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
+ type: { type: DataTypes.STRING, allowNull: false },
+ provider: { type: DataTypes.STRING, allowNull: false },
+ providerAccountId: { type: DataTypes.STRING, allowNull: false },
+ refresh_token: { type: DataTypes.STRING },
+ access_token: { type: DataTypes.STRING },
+ expires_at: { type: DataTypes.INTEGER },
+ token_type: { type: DataTypes.STRING },
+ scope: { type: DataTypes.STRING },
+ id_token: { type: DataTypes.STRING },
+ oauth_token_secret: { type: DataTypes.STRING },
+ oauth_token: { type: DataTypes.STRING },
+ session_state: { type: DataTypes.STRING },
+ userId: { type: DataTypes.INTEGER },
+}
+
+export const userSchema = {
+ id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
+ name: { type: DataTypes.STRING },
+ email: { type: DataTypes.STRING, unique: true },
+ emailVerified: { type: DataTypes.DATE },
+ image: { type: DataTypes.STRING },
+}
+
+export const sessionSchema = {
+ id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
+ expires: { type: DataTypes.DATE, allowNull: false },
+ sessionToken: { type: DataTypes.STRING, unique: true, allowNull: false },
+ userId: { type: DataTypes.INTEGER },
+}
+
+export const verificationTokenSchema = {
+ token: { type: DataTypes.STRING, primaryKey: true },
+ identifier: { type: DataTypes.STRING, allowNull: false },
+ expires: { type: DataTypes.DATE, allowNull: false },
+}
diff --git a/packages/sequelize/tests/index.test.ts b/packages/sequelize/tests/index.test.ts
new file mode 100644
index 00000000..ca92afd8
--- /dev/null
+++ b/packages/sequelize/tests/index.test.ts
@@ -0,0 +1,45 @@
+import { Sequelize } from "sequelize"
+import { runBasicTests } from "../../../basic-tests"
+import SequelizeAdapter from "../src"
+
+const sequelize = new Sequelize({
+ logging: false,
+ dialect: "sqlite",
+ storage: ":memory:",
+})
+
+runBasicTests({
+ adapter: SequelizeAdapter(sequelize),
+ db: {
+ connect: async () => {
+ return await sequelize.sync({ force: true })
+ },
+ verificationToken: async ({ identifier, token }) => {
+ const verificationToken =
+ await sequelize.models.verificationToken.findOne({
+ where: { identifier, token },
+ })
+
+ return verificationToken?.get({ plain: true }) || null
+ },
+ user: async (id) => {
+ const user = await sequelize.models.user.findByPk(id)
+
+ return user?.get({ plain: true }) || null
+ },
+ account: async ({ provider, providerAccountId }) => {
+ const account = await sequelize.models.account.findOne({
+ where: { provider, providerAccountId },
+ })
+
+ return account?.get({ plain: true }) || null
+ },
+ session: async (sessionToken) => {
+ const session = await sequelize.models.session.findOne({
+ where: { sessionToken },
+ })
+
+ return session?.get({ plain: true }) || null
+ },
+ },
+})
diff --git a/packages/sequelize/tsconfig.json b/packages/sequelize/tsconfig.json
new file mode 100644
index 00000000..4bf53b42
--- /dev/null
+++ b/packages/sequelize/tsconfig.json
@@ -0,0 +1,8 @@
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "rootDir": "src",
+ "outDir": "dist"
+ },
+ "exclude": ["tests", "dist"]
+}
diff --git a/yarn.lock b/yarn.lock
index 6b75014b..12bf0d11 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3597,7 +3597,7 @@ ansicolors@~0.3.2:
resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz#665597de86a9ffe3aa9bfbe6cae5c6ea426b4979"
integrity sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=
-any-promise@^1.0.0, any-promise@^1.1.0, any-promise@~1.3.0:
+any-promise@^1.0.0, any-promise@^1.1.0, any-promise@^1.3.0, any-promise@~1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
integrity sha1-q8av7tzqUugJzcA3au0845Y10X8=
@@ -5512,6 +5512,11 @@ dotenv@^8.2.0:
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b"
integrity sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==
+dottie@^2.0.0:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/dottie/-/dottie-2.0.2.tgz#cc91c0726ce3a054ebf11c55fbc92a7f266dd154"
+ integrity sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg==
+
double-ended-queue@2.1.0-0:
version "2.1.0-0"
resolved "https://registry.yarnpkg.com/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz#103d3527fd31528f40188130c841efdd78264e5c"
@@ -7416,6 +7421,11 @@ infer-owner@^1.0.4:
resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467"
integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==
+inflection@1.13.1:
+ version "1.13.1"
+ resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.13.1.tgz#c5cadd80888a90cf84c2e96e340d7edc85d5f0cb"
+ integrity sha512-dldYtl2WlN0QDkIDtg8+xFwOS2Tbmp12t1cHa5/YClU6ZQjTFm7B66UcVbh9NQB+HvT5BAd2t5+yKsBkw5pcqA==
+
inflight@^1.0.4:
version "1.0.6"
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
@@ -9796,7 +9806,14 @@ modify-values@^1.0.0:
resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022"
integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==
-moment@^2.19.3:
+moment-timezone@^0.5.31:
+ version "0.5.33"
+ resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.33.tgz#b252fd6bb57f341c9b59a5ab61a8e51a73bbd22c"
+ integrity sha512-PTc2vcT8K9J5/9rDEPe5czSIKgLoGsH8UNpA4qZTVw0Vd/Uz19geE9abbIOQKaAQFcnQ3v5YEXrbSc5BpshH+w==
+ dependencies:
+ moment ">= 2.9.0"
+
+"moment@>= 2.9.0", moment@^2.19.3, moment@^2.26.0:
version "2.29.1"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3"
integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==
@@ -12031,6 +12048,13 @@ ret@~0.1.10:
resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==
+retry-as-promised@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/retry-as-promised/-/retry-as-promised-3.2.0.tgz#769f63d536bec4783549db0777cb56dadd9d8543"
+ integrity sha512-CybGs60B7oYU/qSQ6kuaFmRd9sTZ6oXSc0toqePvV74Ac6/IFZSI1ReFQmtCN+uvW1Mtqdwpvt/LGOiCBAY2Mg==
+ dependencies:
+ any-promise "^1.3.0"
+
retry-request@^4.0.0:
version "4.2.2"
resolved "https://registry.yarnpkg.com/retry-request/-/retry-request-4.2.2.tgz#b7d82210b6d2651ed249ba3497f07ea602f1a903"
@@ -12229,6 +12253,30 @@ send@0.17.1:
range-parser "~1.2.1"
statuses "~1.5.0"
+sequelize-pool@^6.0.0:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/sequelize-pool/-/sequelize-pool-6.1.0.tgz#caaa0c1e324d3c2c3a399fed2c7998970925d668"
+ integrity sha512-4YwEw3ZgK/tY/so+GfnSgXkdwIJJ1I32uZJztIEgZeAO6HMgj64OzySbWLgxj+tXhZCJnzRfkY9gINw8Ft8ZMg==
+
+sequelize@^6.6.5:
+ version "6.6.5"
+ resolved "https://registry.yarnpkg.com/sequelize/-/sequelize-6.6.5.tgz#6f618e99f3df1fc81f28709e8a3139cec3ef1f0c"
+ integrity sha512-QyRrJrDRiwuiILqTMHUA1yWOPIL12KlfmgZ3hnzQwbMvp2vJ6fzu9bYJQB+qPMosck4mBUggY4Cjoc6Et8FBIQ==
+ dependencies:
+ debug "^4.1.1"
+ dottie "^2.0.0"
+ inflection "1.13.1"
+ lodash "^4.17.20"
+ moment "^2.26.0"
+ moment-timezone "^0.5.31"
+ retry-as-promised "^3.2.0"
+ semver "^7.3.2"
+ sequelize-pool "^6.0.0"
+ toposort-class "^1.0.1"
+ uuid "^8.1.0"
+ validator "^13.6.0"
+ wkx "^0.5.0"
+
serve-static@1.14.1:
version "1.14.1"
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9"
@@ -13225,6 +13273,11 @@ toidentifier@1.0.0:
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
+toposort-class@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/toposort-class/-/toposort-class-1.0.1.tgz#7ffd1f78c8be28c3ba45cd4e1a3f5ee193bd9988"
+ integrity sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg=
+
"tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4"
@@ -13733,7 +13786,7 @@ uuid@^7.0.3:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-7.0.3.tgz#c5c9f2c8cf25dc0a372c4df1441c41f5bd0c680b"
integrity sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==
-uuid@^8.3.0, uuid@^8.3.2:
+uuid@^8.1.0, uuid@^8.3.0, uuid@^8.3.2:
version "8.3.2"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
@@ -13772,6 +13825,11 @@ validate-npm-package-name@^3.0.0:
dependencies:
builtins "^1.0.3"
+validator@^13.6.0:
+ version "13.6.0"
+ resolved "https://registry.yarnpkg.com/validator/-/validator-13.6.0.tgz#1e71899c14cdc7b2068463cb24c1cc16f6ec7059"
+ integrity sha512-gVgKbdbHgtxpRyR8K0O6oFZPhhB5tT1jeEHZR0Znr9Svg03U0+r9DXWMrnRAB+HtCStDQKlaIZm42tVsVjqtjg==
+
vary@^1, vary@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
@@ -13969,6 +14027,13 @@ winston@^3.0.0:
triple-beam "^1.3.0"
winston-transport "^4.4.0"
+wkx@^0.5.0:
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/wkx/-/wkx-0.5.0.tgz#c6c37019acf40e517cc6b94657a25a3d4aa33e8c"
+ integrity sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==
+ dependencies:
+ "@types/node" "*"
+
word-wrap@^1.2.3, word-wrap@~1.2.3:
version "1.2.3"
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
From bb0e7921bb5186b242376c6fa73fab8280b27276 Mon Sep 17 00:00:00 2001
From: Luke Jones
Date: Mon, 20 Sep 2021 09:16:38 +1000
Subject: [PATCH 02/13] Simplify README
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: Balázs Orbán
---
packages/sequelize/README.md | 13 ++-----------
1 file changed, 2 insertions(+), 11 deletions(-)
diff --git a/packages/sequelize/README.md b/packages/sequelize/README.md
index 21cbb098..9c5b6cb6 100644
--- a/packages/sequelize/README.md
+++ b/packages/sequelize/README.md
@@ -32,23 +32,14 @@ npm install --save-dev sequelize
```js
import NextAuth from "next-auth"
import Providers from "next-auth/providers"
-import SequelizeAdapter, { userSchema } from "@next-auth/sequelize-adapter"
+import SequelizeAdapter from "@next-auth/sequelize-adapter"
const sequelize = new Sequelize("sqlite::memory:")
-// To override the existing models, make your new models available like so:
-sequelize.models.User = sequelize.define("user", { ...userSchema, ...myCustomUserSchema })
-
// For more information on each option (and a full list of options) go to
// https://next-auth.js.org/configuration/options
export default NextAuth({
- // https://next-auth.js.org/configuration/providers
- providers: [
- Providers.Google({
- clientId: process.env.GOOGLE_ID,
- clientSecret: process.env.GOOGLE_SECRET,
- }),
- ],
+ ...
adapter: SequelizeAdapter(sequelize)
...
})
From 6d4f411c4e31aa9f557c88fafa3f2015d80daa79 Mon Sep 17 00:00:00 2001
From: Luke Jones
Date: Mon, 20 Sep 2021 09:17:24 +1000
Subject: [PATCH 03/13] Reference adapters repo in package.json
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: Balázs Orbán
---
packages/sequelize/package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/sequelize/package.json b/packages/sequelize/package.json
index 98a76796..e58f6a94 100644
--- a/packages/sequelize/package.json
+++ b/packages/sequelize/package.json
@@ -5,7 +5,7 @@
"homepage": "https://next-auth.js.org",
"repository": "https://github.com/nextauthjs/adapters",
"bugs": {
- "url": "https://github.com/nextauthjs/next-auth/issues"
+ "url": "https://github.com/nextauthjs/adapters/issues"
},
"author": "github.com/luke-j",
"main": "dist/index.js",
From e0b1dae22ac417ef0888f3f724f917e919e2202b Mon Sep 17 00:00:00 2001
From: Luke Jones
Date: Mon, 20 Sep 2021 09:41:47 +1000
Subject: [PATCH 04/13] Add docs on updating database schema
---
packages/sequelize/README.md | 24 +++++++++++++++++++++++-
1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/packages/sequelize/README.md b/packages/sequelize/README.md
index 9c5b6cb6..6d06f88f 100644
--- a/packages/sequelize/README.md
+++ b/packages/sequelize/README.md
@@ -31,7 +31,6 @@ npm install --save-dev sequelize
```js
import NextAuth from "next-auth"
-import Providers from "next-auth/providers"
import SequelizeAdapter from "@next-auth/sequelize-adapter"
const sequelize = new Sequelize("sqlite::memory:")
@@ -45,6 +44,29 @@ export default NextAuth({
})
```
+## 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://next-auth.js.org/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:
+
+```js
+import NextAuth from "next-auth"
+import SequelizeAdapter from "@next-auth/sequelize-adapter"
+
+const sequelize = new Sequelize("sqlite::memory:")
+const adapter = SequelizeAdapter(sequelize)
+
+// Calling sync() is not recommended in production
+sequelize.sync()
+
+// For more information on each option (and a full list of options) go to
+// https://next-auth.js.org/configuration/options
+export default NextAuth({
+ ...
+ adapter
+ ...
+})
+```
+
## Contributing
We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/adapters/blob/main/CONTRIBUTING.md).
From 30363a193e6439f7aa0e13f76c86ae6463d53ede Mon Sep 17 00:00:00 2001
From: Luke Jones
Date: Mon, 20 Sep 2021 09:52:14 +1000
Subject: [PATCH 05/13] Use uuids over ints for ids
---
packages/sequelize/src/schema.ts | 22 +++++++++++++++++-----
1 file changed, 17 insertions(+), 5 deletions(-)
diff --git a/packages/sequelize/src/schema.ts b/packages/sequelize/src/schema.ts
index 6309cfbb..e80244ae 100644
--- a/packages/sequelize/src/schema.ts
+++ b/packages/sequelize/src/schema.ts
@@ -1,7 +1,11 @@
import { DataTypes } from "sequelize"
export const accountSchema = {
- id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
+ id: {
+ type: DataTypes.UUID,
+ defaultValue: DataTypes.UUIDV4,
+ primaryKey: true,
+ },
type: { type: DataTypes.STRING, allowNull: false },
provider: { type: DataTypes.STRING, allowNull: false },
providerAccountId: { type: DataTypes.STRING, allowNull: false },
@@ -14,11 +18,15 @@ export const accountSchema = {
oauth_token_secret: { type: DataTypes.STRING },
oauth_token: { type: DataTypes.STRING },
session_state: { type: DataTypes.STRING },
- userId: { type: DataTypes.INTEGER },
+ userId: { type: DataTypes.UUID },
}
export const userSchema = {
- id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
+ id: {
+ type: DataTypes.UUID,
+ defaultValue: DataTypes.UUIDV4,
+ primaryKey: true,
+ },
name: { type: DataTypes.STRING },
email: { type: DataTypes.STRING, unique: true },
emailVerified: { type: DataTypes.DATE },
@@ -26,10 +34,14 @@ export const userSchema = {
}
export const sessionSchema = {
- id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true },
+ id: {
+ type: DataTypes.UUID,
+ defaultValue: DataTypes.UUIDV4,
+ primaryKey: true,
+ },
expires: { type: DataTypes.DATE, allowNull: false },
sessionToken: { type: DataTypes.STRING, unique: true, allowNull: false },
- userId: { type: DataTypes.INTEGER },
+ userId: { type: DataTypes.UUID },
}
export const verificationTokenSchema = {
From f6b9518cdc3132f1bc018e8380472733f825d695 Mon Sep 17 00:00:00 2001
From: Luke Jones
Date: Mon, 20 Sep 2021 10:03:52 +1000
Subject: [PATCH 06/13] Refactor schema to models, change user-facing API
---
packages/sequelize/src/index.ts | 75 ++++++++++++-------
.../sequelize/src/{schema.ts => models.ts} | 8 +-
2 files changed, 52 insertions(+), 31 deletions(-)
rename packages/sequelize/src/{schema.ts => models.ts} (91%)
diff --git a/packages/sequelize/src/index.ts b/packages/sequelize/src/index.ts
index 3028dbe4..c1a46e72 100644
--- a/packages/sequelize/src/index.ts
+++ b/packages/sequelize/src/index.ts
@@ -6,12 +6,9 @@ import type {
VerificationToken,
} from "next-auth/adapters"
import { Sequelize, Model, ModelCtor } from "sequelize"
-import {
- accountSchema,
- userSchema,
- sessionSchema,
- verificationTokenSchema,
-} from "./schema"
+import * as defaultModels from "./models"
+
+export { defaultModels as models }
// @see https://sequelize.org/master/manual/typescript.html
interface AccountInstance
@@ -27,27 +24,51 @@ interface VerificationTokenInstance
extends Model>,
VerificationToken {}
-export { accountSchema, userSchema, sessionSchema, verificationTokenSchema }
-
-export default function SequelizeAdapter(client: Sequelize): Adapter {
- const tableOptions = { underscored: true, timestamps: false }
-
- const Account =
- (client.models.Account as ModelCtor) ||
- client.define("account", accountSchema, tableOptions)
- const User =
- (client.models.User as ModelCtor) ||
- client.define("user", userSchema, tableOptions)
- const Session =
- (client.models.Session as ModelCtor) ||
- client.define("session", sessionSchema, tableOptions)
- const VerificationToken =
- (client.models.VerificationToken as ModelCtor) ||
- client.define(
- "verificationToken",
- verificationTokenSchema,
- tableOptions
- )
+interface SequelizeAdapterOptions {
+ models?: Partial<{
+ User: ModelCtor
+ Account: ModelCtor
+ Session: ModelCtor
+ VerificationToken: ModelCtor
+ }>
+}
+
+export default function SequelizeAdapter(
+ client: Sequelize,
+ options?: SequelizeAdapterOptions
+): Adapter {
+ const { models } = options ?? {}
+ const defaultModelOptions = { underscored: true, timestamps: false }
+ const { User, Account, Session, VerificationToken } = {
+ User:
+ models?.User ??
+ client.define(
+ "user",
+ defaultModels.User,
+ defaultModelOptions
+ ),
+ Account:
+ models?.Account ??
+ client.define(
+ "account",
+ defaultModels.Account,
+ defaultModelOptions
+ ),
+ Session:
+ models?.Session ??
+ client.define(
+ "session",
+ defaultModels.Session,
+ defaultModelOptions
+ ),
+ VerificationToken:
+ models?.VerificationToken ??
+ client.define(
+ "verificationToken",
+ defaultModels.VerificationToken,
+ defaultModelOptions
+ ),
+ }
Account.belongsTo(User, { onDelete: "cascade" })
Session.belongsTo(User, { onDelete: "cascade" })
diff --git a/packages/sequelize/src/schema.ts b/packages/sequelize/src/models.ts
similarity index 91%
rename from packages/sequelize/src/schema.ts
rename to packages/sequelize/src/models.ts
index e80244ae..092ad87d 100644
--- a/packages/sequelize/src/schema.ts
+++ b/packages/sequelize/src/models.ts
@@ -1,6 +1,6 @@
import { DataTypes } from "sequelize"
-export const accountSchema = {
+export const Account = {
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
@@ -21,7 +21,7 @@ export const accountSchema = {
userId: { type: DataTypes.UUID },
}
-export const userSchema = {
+export const User = {
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
@@ -33,7 +33,7 @@ export const userSchema = {
image: { type: DataTypes.STRING },
}
-export const sessionSchema = {
+export const Session = {
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
@@ -44,7 +44,7 @@ export const sessionSchema = {
userId: { type: DataTypes.UUID },
}
-export const verificationTokenSchema = {
+export const VerificationToken = {
token: { type: DataTypes.STRING, primaryKey: true },
identifier: { type: DataTypes.STRING, allowNull: false },
expires: { type: DataTypes.DATE, allowNull: false },
From cd444147bb9d0d2b05bc4da8e8518fdd907d2775 Mon Sep 17 00:00:00 2001
From: Luke Jones
Date: Mon, 20 Sep 2021 10:08:55 +1000
Subject: [PATCH 07/13] Add docs on customizing models
---
packages/sequelize/README.md | 27 +++++++++++++++++++++++++--
1 file changed, 25 insertions(+), 2 deletions(-)
diff --git a/packages/sequelize/README.md b/packages/sequelize/README.md
index 6d06f88f..3e96f2c6 100644
--- a/packages/sequelize/README.md
+++ b/packages/sequelize/README.md
@@ -32,6 +32,7 @@ npm install --save-dev sequelize
```js
import NextAuth from "next-auth"
import SequelizeAdapter from "@next-auth/sequelize-adapter"
+import Sequelize from 'sequelize'
const sequelize = new Sequelize("sqlite::memory:")
@@ -51,6 +52,7 @@ By default, the sequelize adapter will not create tables in your database. In pr
```js
import NextAuth from "next-auth"
import SequelizeAdapter from "@next-auth/sequelize-adapter"
+import Sequelize from 'sequelize'
const sequelize = new Sequelize("sqlite::memory:")
const adapter = SequelizeAdapter(sequelize)
@@ -58,8 +60,6 @@ const adapter = SequelizeAdapter(sequelize)
// Calling sync() is not recommended in production
sequelize.sync()
-// For more information on each option (and a full list of options) go to
-// https://next-auth.js.org/configuration/options
export default NextAuth({
...
adapter
@@ -67,6 +67,29 @@ export default NextAuth({
})
```
+## Using custom models
+
+Sequelize models are option to customization like so:
+
+```js
+import NextAuth from "next-auth"
+import SequelizeAdapter, { models } from "@next-auth/sequelize-adapter"
+import Sequelize, { DataTypes } from 'sequelize'
+
+const sequelize = new Sequelize("sqlite::memory:")
+const options = {
+ models: {
+ User: sequelize.define('user', { ...models.User, phoneNumber: DataTypes.STRING })
+ }
+}
+
+export default NextAuth({
+ ...
+ adapter: SequelizeAdapter(sequelize, options)
+ ...
+})
+```
+
## Contributing
We're open to all community contributions! If you'd like to contribute in any way, please read our [Contributing Guide](https://github.com/nextauthjs/adapters/blob/main/CONTRIBUTING.md).
From ddeba750a120d05a267c0dc426fdf994a3c44a04 Mon Sep 17 00:00:00 2001
From: Luke Jones
Date: Mon, 20 Sep 2021 10:13:45 +1000
Subject: [PATCH 08/13] Simplify arguments
---
packages/sequelize/tests/index.test.ts | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/packages/sequelize/tests/index.test.ts b/packages/sequelize/tests/index.test.ts
index ca92afd8..204606db 100644
--- a/packages/sequelize/tests/index.test.ts
+++ b/packages/sequelize/tests/index.test.ts
@@ -14,11 +14,9 @@ runBasicTests({
connect: async () => {
return await sequelize.sync({ force: true })
},
- verificationToken: async ({ identifier, token }) => {
+ verificationToken: async (where) => {
const verificationToken =
- await sequelize.models.verificationToken.findOne({
- where: { identifier, token },
- })
+ await sequelize.models.verificationToken.findOne({ where })
return verificationToken?.get({ plain: true }) || null
},
@@ -27,10 +25,8 @@ runBasicTests({
return user?.get({ plain: true }) || null
},
- account: async ({ provider, providerAccountId }) => {
- const account = await sequelize.models.account.findOne({
- where: { provider, providerAccountId },
- })
+ account: async (where) => {
+ const account = await sequelize.models.account.findOne({ where })
return account?.get({ plain: true }) || null
},
From 3b2da67238589e3b92e35616c81c40381c4e7ecf Mon Sep 17 00:00:00 2001
From: Luke Jones
Date: Mon, 20 Sep 2021 10:16:19 +1000
Subject: [PATCH 09/13] Assume user always exists in
---
packages/sequelize/src/index.ts | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/packages/sequelize/src/index.ts b/packages/sequelize/src/index.ts
index c1a46e72..a5b96b82 100644
--- a/packages/sequelize/src/index.ts
+++ b/packages/sequelize/src/index.ts
@@ -106,11 +106,8 @@ export default function SequelizeAdapter(
await User.update(user, { where: { id: user.id } })
const userInstance = await User.findByPk(user.id)
- if (!userInstance) {
- throw new Error("User does not exist")
- }
-
- return userInstance
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ return userInstance!
},
async deleteUser(userId) {
const userInstance = await User.findByPk(userId)
From 48961d1517a999e421bfa74058dbaa56a7d0bb5e Mon Sep 17 00:00:00 2001
From: Luke Jones
Date: Thu, 23 Sep 2021 14:07:43 +1000
Subject: [PATCH 10/13] Enable automatic sync
---
packages/sequelize/README.md | 8 +-
packages/sequelize/src/index.ts | 47 ++++++++-
packages/sequelize/tests/index.test.ts | 128 ++++++++++++++++++++++++-
3 files changed, 174 insertions(+), 9 deletions(-)
diff --git a/packages/sequelize/README.md b/packages/sequelize/README.md
index 3e96f2c6..ba8fdbb8 100644
--- a/packages/sequelize/README.md
+++ b/packages/sequelize/README.md
@@ -47,7 +47,7 @@ export default NextAuth({
## 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://next-auth.js.org/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:
+By default, the sequelize adapter will not create tables in your database. In production, best practice is to create the [required tables](https://next-auth.js.org/adapters/models) in your database via [migrations](https://sequelize.org/master/manual/migrations.html). In development, you are able to pass `{ synchronize: true }` as the second option to `SequelizeAdapter` to have sequelize create the necessary tables, foreign keys and indexes:
```js
import NextAuth from "next-auth"
@@ -55,14 +55,10 @@ import SequelizeAdapter from "@next-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
+ adapter: SequelizeAdapter(sequelize, { synchronize: true })
...
})
```
diff --git a/packages/sequelize/src/index.ts b/packages/sequelize/src/index.ts
index a5b96b82..800df96e 100644
--- a/packages/sequelize/src/index.ts
+++ b/packages/sequelize/src/index.ts
@@ -25,6 +25,7 @@ interface VerificationTokenInstance
VerificationToken {}
interface SequelizeAdapterOptions {
+ synchronize?: boolean
models?: Partial<{
User: ModelCtor
Account: ModelCtor
@@ -37,7 +38,7 @@ export default function SequelizeAdapter(
client: Sequelize,
options?: SequelizeAdapterOptions
): Adapter {
- const { models } = options ?? {}
+ const { models, synchronize } = options ?? {}
const defaultModelOptions = { underscored: true, timestamps: false }
const { User, Account, Session, VerificationToken } = {
User:
@@ -69,20 +70,42 @@ export default function SequelizeAdapter(
defaultModelOptions
),
}
+ let _synced = false
+ const sync = async () => {
+ if (process.env.NODE_ENV !== "production" && synchronize && !_synced) {
+ const syncOptions =
+ typeof synchronize === "object" ? synchronize : undefined
+
+ await Promise.all([
+ User.sync(syncOptions),
+ Account.sync(syncOptions),
+ Session.sync(syncOptions),
+ VerificationToken.sync(syncOptions),
+ ])
+
+ _synced = true
+ }
+ }
Account.belongsTo(User, { onDelete: "cascade" })
Session.belongsTo(User, { onDelete: "cascade" })
return {
async createUser(user) {
+ await sync()
+
return await User.create(user)
},
async getUser(id) {
+ await sync()
+
const userInstance = await User.findByPk(id)
return userInstance?.get({ plain: true }) ?? null
},
async getUserByEmail(email) {
+ await sync()
+
const userInstance = await User.findOne({
where: { email },
})
@@ -90,6 +113,8 @@ export default function SequelizeAdapter(
return userInstance?.get({ plain: true }) ?? null
},
async getUserByAccount({ provider, providerAccountId }) {
+ await sync()
+
const accountInstance = await Account.findOne({
where: { provider, providerAccountId },
})
@@ -103,6 +128,8 @@ export default function SequelizeAdapter(
return userInstance?.get({ plain: true }) ?? null
},
async updateUser(user) {
+ await sync()
+
await User.update(user, { where: { id: user.id } })
const userInstance = await User.findByPk(user.id)
@@ -110,6 +137,8 @@ export default function SequelizeAdapter(
return userInstance!
},
async deleteUser(userId) {
+ await sync()
+
const userInstance = await User.findByPk(userId)
await User.destroy({ where: { id: userId } })
@@ -117,17 +146,25 @@ export default function SequelizeAdapter(
return userInstance
},
async linkAccount(account) {
+ await sync()
+
await Account.create(account)
},
async unlinkAccount({ provider, providerAccountId }) {
+ await sync()
+
await Account.destroy({
where: { provider, providerAccountId },
})
},
async createSession(session) {
+ await sync()
+
return await Session.create(session)
},
async getSessionAndUser(sessionToken) {
+ await sync()
+
const sessionInstance = await Session.findOne({
where: { sessionToken },
})
@@ -148,6 +185,8 @@ export default function SequelizeAdapter(
}
},
async updateSession({ sessionToken, expires }) {
+ await sync()
+
await Session.update(
{ expires, sessionToken },
{ where: { sessionToken } }
@@ -156,12 +195,18 @@ export default function SequelizeAdapter(
return await Session.findOne({ where: { sessionToken } })
},
async deleteSession(sessionToken) {
+ await sync()
+
await Session.destroy({ where: { sessionToken } })
},
async createVerificationToken(token) {
+ await sync()
+
return await VerificationToken.create(token)
},
async useVerificationToken({ identifier, token }) {
+ await sync()
+
const tokenInstance = await VerificationToken.findOne({
where: { identifier, token },
})
diff --git a/packages/sequelize/tests/index.test.ts b/packages/sequelize/tests/index.test.ts
index 204606db..808067c4 100644
--- a/packages/sequelize/tests/index.test.ts
+++ b/packages/sequelize/tests/index.test.ts
@@ -1,6 +1,6 @@
-import { Sequelize } from "sequelize"
+import { Sequelize, DataTypes } from "sequelize"
import { runBasicTests } from "../../../basic-tests"
-import SequelizeAdapter from "../src"
+import SequelizeAdapter, { models } from "../src"
const sequelize = new Sequelize({
logging: false,
@@ -39,3 +39,127 @@ runBasicTests({
},
},
})
+
+describe("Additional Sequelize tests", () => {
+ describe("synchronize option", () => {
+ const lowercase = (strs: string[]) =>
+ strs.map((s) => s.replace(/[^a-z]/gi, "").toLowerCase())
+
+ beforeEach(async () => {
+ await sequelize.getQueryInterface().dropAllTables()
+
+ const { getUser } = SequelizeAdapter(sequelize, { synchronize: true })
+
+ await getUser("1")
+ })
+
+ test("Creates DB tables", async () => {
+ const tables = await sequelize.getQueryInterface().showAllSchemas()
+
+ expect(tables).toEqual([
+ { name: "users" },
+ { name: "accounts" },
+ { name: "sessions" },
+ { name: "verification_tokens" },
+ ])
+ })
+
+ test("Correctly creates users table", async () => {
+ const table = await sequelize.getQueryInterface().describeTable("users")
+
+ expect(lowercase(Object.keys(table))).toEqual(
+ lowercase(Object.keys(models.User))
+ )
+ })
+
+ test("Correctly creates accounts table", async () => {
+ const table = await sequelize
+ .getQueryInterface()
+ .describeTable("accounts")
+
+ expect(lowercase(Object.keys(table))).toEqual(
+ lowercase(Object.keys(models.Account))
+ )
+ })
+
+ test("Correctly creates sessions table", async () => {
+ const table = await sequelize
+ .getQueryInterface()
+ .describeTable("sessions")
+
+ expect(lowercase(Object.keys(table))).toEqual(
+ lowercase(Object.keys(models.Session))
+ )
+ })
+
+ test("Correctly creates verification_tokens table", async () => {
+ const table = await sequelize
+ .getQueryInterface()
+ .describeTable("verification_tokens")
+
+ expect(lowercase(Object.keys(table))).toEqual(
+ lowercase(Object.keys(models.VerificationToken))
+ )
+ })
+ })
+
+ describe("overriding models", () => {
+ beforeEach(async () => {
+ await sequelize.getQueryInterface().dropAllTables()
+
+ const { getUser } = SequelizeAdapter(sequelize, {
+ synchronize: true,
+ models: {
+ User: sequelize.define("users", {
+ ...models.User,
+ someUserAttribute: { type: DataTypes.STRING },
+ }),
+ Account: sequelize.define("accounts", {
+ ...models.Account,
+ someAccountAttribute: { type: DataTypes.STRING },
+ }),
+ Session: sequelize.define("sessions", {
+ ...models.Session,
+ someSessionAttribute: { type: DataTypes.STRING },
+ }),
+ VerificationToken: sequelize.define("verification_tokens", {
+ ...models.VerificationToken,
+ someVerificationTokenAttribute: { type: DataTypes.STRING },
+ }),
+ },
+ })
+
+ await getUser("1")
+ })
+
+ test("Custom user model", async () => {
+ const table = await sequelize.getQueryInterface().describeTable("users")
+
+ expect(table.someUserAttribute).toBeDefined()
+ })
+
+ test("Custom account model", async () => {
+ const table = await sequelize
+ .getQueryInterface()
+ .describeTable("accounts")
+
+ expect(table.someAccountAttribute).toBeDefined()
+ })
+
+ test("Custom session model", async () => {
+ const table = await sequelize
+ .getQueryInterface()
+ .describeTable("sessions")
+
+ expect(table.someSessionAttribute).toBeDefined()
+ })
+
+ test("Custom verification_token model", async () => {
+ const table = await sequelize
+ .getQueryInterface()
+ .describeTable("verification_tokens")
+
+ expect(table.someVerificationTokenAttribute).toBeDefined()
+ })
+ })
+})
From a03a37c3fef22e6401d15d009727c19ac2ce84f0 Mon Sep 17 00:00:00 2001
From: Luke Jones
Date: Tue, 5 Oct 2021 11:48:49 +1100
Subject: [PATCH 11/13] Default synchronize to true
---
packages/sequelize/README.md | 15 +++++++--------
packages/sequelize/src/index.ts | 2 +-
packages/sequelize/tests/index.test.ts | 2 +-
3 files changed, 9 insertions(+), 10 deletions(-)
diff --git a/packages/sequelize/README.md b/packages/sequelize/README.md
index ba8fdbb8..d1c0566c 100644
--- a/packages/sequelize/README.md
+++ b/packages/sequelize/README.md
@@ -47,7 +47,7 @@ export default NextAuth({
## 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://next-auth.js.org/adapters/models) in your database via [migrations](https://sequelize.org/master/manual/migrations.html). In development, you are able to pass `{ synchronize: true }` as the second option to `SequelizeAdapter` to have sequelize create the necessary tables, foreign keys and indexes:
+By default, the sequelize adapter will create the necessary tables, foreign keys and indexes in your database. In production, best practice is to create the [required tables](https://next-auth.js.org/adapters/models) in your database via [migrations](https://sequelize.org/master/manual/migrations.html). In development, if you do not want the adapter to automatically create tables, you are able to pass `{ synchronize: false }` as the second option to `SequelizeAdapter` to disable this behavior:
```js
import NextAuth from "next-auth"
@@ -58,7 +58,7 @@ const sequelize = new Sequelize("sqlite::memory:")
export default NextAuth({
...
- adapter: SequelizeAdapter(sequelize, { synchronize: true })
+ adapter: SequelizeAdapter(sequelize, { synchronize: false })
...
})
```
@@ -73,15 +73,14 @@ import SequelizeAdapter, { models } from "@next-auth/sequelize-adapter"
import Sequelize, { DataTypes } from 'sequelize'
const sequelize = new Sequelize("sqlite::memory:")
-const options = {
- models: {
- User: sequelize.define('user', { ...models.User, phoneNumber: DataTypes.STRING })
- }
-}
export default NextAuth({
...
- adapter: SequelizeAdapter(sequelize, options)
+ adapter: SequelizeAdapter(sequelize, {
+ models: {
+ User: sequelize.define('user', { ...models.User, phoneNumber: DataTypes.STRING })
+ }
+ })
...
})
```
diff --git a/packages/sequelize/src/index.ts b/packages/sequelize/src/index.ts
index 800df96e..ad12fd06 100644
--- a/packages/sequelize/src/index.ts
+++ b/packages/sequelize/src/index.ts
@@ -38,7 +38,7 @@ export default function SequelizeAdapter(
client: Sequelize,
options?: SequelizeAdapterOptions
): Adapter {
- const { models, synchronize } = options ?? {}
+ const { models, synchronize = true } = options ?? {}
const defaultModelOptions = { underscored: true, timestamps: false }
const { User, Account, Session, VerificationToken } = {
User:
diff --git a/packages/sequelize/tests/index.test.ts b/packages/sequelize/tests/index.test.ts
index 808067c4..0fd1a538 100644
--- a/packages/sequelize/tests/index.test.ts
+++ b/packages/sequelize/tests/index.test.ts
@@ -48,7 +48,7 @@ describe("Additional Sequelize tests", () => {
beforeEach(async () => {
await sequelize.getQueryInterface().dropAllTables()
- const { getUser } = SequelizeAdapter(sequelize, { synchronize: true })
+ const { getUser } = SequelizeAdapter(sequelize)
await getUser("1")
})
From 564dc8141ee151a6bdff88d0b82d724861c636c5 Mon Sep 17 00:00:00 2001
From: Luke Jones
Date: Tue, 5 Oct 2021 11:53:33 +1100
Subject: [PATCH 12/13] Slightly change wording
---
packages/sequelize/README.md | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/packages/sequelize/README.md b/packages/sequelize/README.md
index d1c0566c..60476ad0 100644
--- a/packages/sequelize/README.md
+++ b/packages/sequelize/README.md
@@ -47,7 +47,9 @@ export default NextAuth({
## Updating the database schema
-By default, the sequelize adapter will create the necessary tables, foreign keys and indexes in your database. In production, best practice is to create the [required tables](https://next-auth.js.org/adapters/models) in your database via [migrations](https://sequelize.org/master/manual/migrations.html). In development, if you do not want the adapter to automatically create tables, you are able to pass `{ synchronize: false }` as the second option to `SequelizeAdapter` to disable this behavior:
+In development, the sequelize adapter will create the necessary tables, foreign keys and indexes in your database. In production, synchronization is disabled. Best practice is to create the [required tables](https://next-auth.js.org/adapters/models) in your database via [migrations](https://sequelize.org/master/manual/migrations.html).
+
+In development, if you do not want the adapter to automatically create tables, you are able to pass `{ synchronize: false }` as the second option to `SequelizeAdapter` to disable this behavior:
```js
import NextAuth from "next-auth"
From 4cd4fe8f125d9d4555792e0791072c8858c4702f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bal=C3=A1zs=20Orb=C3=A1n?=
Date: Wed, 17 Nov 2021 23:21:49 +0100
Subject: [PATCH 13/13] fix: correct peer dep versioning, don't run build on
test
---
packages/sequelize/package.json | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/packages/sequelize/package.json b/packages/sequelize/package.json
index e58f6a94..90572f52 100644
--- a/packages/sequelize/package.json
+++ b/packages/sequelize/package.json
@@ -21,7 +21,7 @@
"access": "public"
},
"scripts": {
- "test": "yarn build && jest",
+ "test": "jest",
"build": "tsc"
},
"files": [
@@ -29,7 +29,7 @@
"dist"
],
"peerDependencies": {
- "next-auth": ">=4",
+ "next-auth": ">4 || 4.0.0-beta.1 - 4.0.0-beta.x",
"sequelize": "^6.6.5"
},
"devDependencies": {