This commit is contained in:
Skye 2023-02-22 00:32:55 +09:00
parent d1ca256f5a
commit 4b4b26a09a
Signed by: me
GPG key ID: 0104BC05F41B77B8
5 changed files with 32 additions and 178 deletions

View file

@ -1,13 +1,13 @@
{
"name": "@next-auth/mongodb-adapter",
"version": "1.1.1",
"description": "mongoDB adapter for next-auth.",
"homepage": "https://authjs.dev",
"repository": "https://github.com/nextauthjs/next-auth",
"name": "nextauth-mongodb-realm",
"version": "1.0.0",
"description": "mongoDB Realm adapter for next-auth.",
"homepage": "https://git.skye.vg/me/nextauth-mongodb-realm",
"repository": "https://git.skye.vg/me/nextauth-mongodb-realm",
"bugs": {
"url": "https://github.com/nextauthjs/next-auth/issues"
"url": "https://git.skye.vg/me/nextauth-mongodb-realm/issues"
},
"author": "Balázs Orbán <info@balazsorban.com>",
"author": "Skye Green <support@skyevg.systems>",
"main": "dist/index.js",
"license": "ISC",
"keywords": [
@ -22,8 +22,6 @@
"access": "public"
},
"scripts": {
"test": "./tests/test.sh",
"test:watch": "./tests/test.sh -w",
"build": "tsc"
},
"files": [
@ -31,17 +29,12 @@
"dist"
],
"peerDependencies": {
"mongodb": "^4.1.1",
"realm-web": "^2.0.0",
"next-auth": "^4"
},
"devDependencies": {
"@next-auth/adapter-test": "https://gitpkg.now.sh/nextauthjs/next-auth/packages/adapter-test?main",
"@next-auth/tsconfig": "https://gitpkg.now.sh/nextauthjs/next-auth/packages/tsconfig?main",
"jest": "^27.4.3",
"mongodb": "^4.4.0",
"next-auth": "^4.19.2"
},
"jest": {
"preset": "@next-auth/adapter-test/jest"
"realm-web": "^2.0.0",
"next-auth": "^4"
}
}

View file

@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import { ObjectId } from "mongodb"
import * as Realm from "realm-web";
import type {
Adapter,
@ -8,7 +8,6 @@ import type {
AdapterSession,
VerificationToken,
} from "next-auth/adapters"
import type { MongoClient } from "mongodb"
export interface MongoDBAdapterOptions {
collections?: {
@ -17,7 +16,8 @@ export interface MongoDBAdapterOptions {
Sessions?: string
VerificationTokens?: string
}
databaseName?: string
databaseName: string
serviceName: string
}
export const defaultCollections: Required<
@ -56,31 +56,31 @@ export const format = {
else if (key === "id") continue
else newObject[key] = value
}
return newObject as T & { _id: ObjectId }
return newObject as T & { _id: Realm.BSON.ObjectId }
},
}
/** Converts from string to ObjectId */
export function _id(hex?: string) {
if (hex?.length !== 24) return new ObjectId()
return new ObjectId(hex)
if (hex?.length !== 24) return new Realm.BSON.ObjectId()
return new Realm.BSON.ObjectId(hex)
}
export function MongoDBAdapter(
client: Promise<MongoClient>,
options: MongoDBAdapterOptions = {}
client: Promise<Realm.User>,
options: MongoDBAdapterOptions
): Adapter {
const { collections } = options
const { from, to } = format
const db = (async () => {
const _db = (await client).db(options.databaseName)
const _db = (await client).mongoClient(options.serviceName).db(options.databaseName)
const c = { ...defaultCollections, ...collections }
return {
U: _db.collection<AdapterUser>(c.Users),
A: _db.collection<AdapterAccount>(c.Accounts),
S: _db.collection<AdapterSession>(c.Sessions),
V: _db.collection<VerificationToken>(c?.VerificationTokens),
U: _db.collection<AdapterUser & { _id: Realm.BSON.ObjectId }>(c.Users),
A: _db.collection<AdapterAccount & { _id: Realm.BSON.ObjectId }>(c.Accounts),
S: _db.collection<AdapterSession & { _id: Realm.BSON.ObjectId }>(c.Sessions),
V: _db.collection<VerificationToken & { _id: Realm.BSON.ObjectId }>(c?.VerificationTokens),
}
})()
@ -105,7 +105,7 @@ export function MongoDBAdapter(
if (!account) return null
const user = await (
await db
).U.findOne({ _id: new ObjectId(account.userId) })
).U.findOne({ _id: new Realm.BSON.ObjectId(account.userId) })
if (!user) return null
return from<AdapterUser>(user)
},
@ -114,9 +114,9 @@ export function MongoDBAdapter(
const result = await (
await db
).U.findOneAndUpdate({ _id }, { $set: user }, { returnDocument: "after" })
).U.findOneAndUpdate({ _id }, { $set: user }, { returnNewDocument: true })
return from<AdapterUser>(result.value!)
return from<AdapterUser>(result!)
},
async deleteUser(id) {
const userId = _id(id)
@ -133,7 +133,7 @@ export function MongoDBAdapter(
return account
},
async unlinkAccount(provider_providerAccountId) {
const { value: account } = await (
const account = await (
await db
).A.findOneAndDelete(provider_providerAccountId)
return from<AdapterAccount>(account!)
@ -143,7 +143,7 @@ export function MongoDBAdapter(
if (!session) return null
const user = await (
await db
).U.findOne({ _id: new ObjectId(session.userId) })
).U.findOne({ _id: new Realm.BSON.ObjectId(session.userId) })
if (!user) return null
return {
user: from<AdapterUser>(user),
@ -163,12 +163,12 @@ export function MongoDBAdapter(
).S.findOneAndUpdate(
{ sessionToken: session.sessionToken },
{ $set: session },
{ returnDocument: "after" }
{ returnNewDocument: true }
)
return from<AdapterSession>(result.value!)
return from<AdapterSession>(result!)
},
async deleteSession(sessionToken) {
const { value: session } = await (
const session = await (
await db
).S.findOneAndDelete({
sessionToken,
@ -180,7 +180,7 @@ export function MongoDBAdapter(
return data
},
async useVerificationToken(identifier_token) {
const { value: verificationToken } = await (
const verificationToken = await (
await db
).V.findOneAndDelete(identifier_token)

View file

@ -1,54 +0,0 @@
import { runBasicTests } from "@next-auth/adapter-test"
import { defaultCollections, format, MongoDBAdapter, _id } from "../src"
import { MongoClient } from "mongodb"
const name = "custom-test"
const client = new MongoClient(`mongodb://localhost:27017/${name}`)
const clientPromise = client.connect()
const collections = { ...defaultCollections, Users: "some_userz" }
runBasicTests({
adapter: MongoDBAdapter(clientPromise, {
collections,
}),
db: {
async disconnect() {
await client.db().dropDatabase()
await client.close()
},
async user(id) {
const user = await client
.db()
.collection(collections.Users)
.findOne({ _id: _id(id) })
if (!user) return null
return format.from(user)
},
async account(provider_providerAccountId) {
const account = await client
.db()
.collection(collections.Accounts)
.findOne(provider_providerAccountId)
if (!account) return null
return format.from(account)
},
async session(sessionToken) {
const session = await client
.db()
.collection(collections.Sessions)
.findOne({ sessionToken })
if (!session) return null
return format.from(session)
},
async verificationToken(identifier_token) {
const token = await client
.db()
.collection(collections.VerificationTokens)
.findOne(identifier_token)
if (!token) return null
const { _id, ...rest } = token
return rest
},
},
})

View file

@ -1,51 +0,0 @@
import { runBasicTests } from "@next-auth/adapter-test"
import { defaultCollections, format, MongoDBAdapter, _id } from "../src"
import { MongoClient } from "mongodb"
const name = "test"
const client = new MongoClient(`mongodb://localhost:27017/${name}`)
const clientPromise = client.connect()
runBasicTests({
adapter: MongoDBAdapter(clientPromise),
db: {
async disconnect() {
await client.db().dropDatabase()
await client.close()
},
async user(id) {
const user = await client
.db()
.collection(defaultCollections.Users)
.findOne({ _id: _id(id) })
if (!user) return null
return format.from(user)
},
async account(provider_providerAccountId) {
const account = await client
.db()
.collection(defaultCollections.Accounts)
.findOne(provider_providerAccountId)
if (!account) return null
return format.from(account)
},
async session(sessionToken) {
const session = await client
.db()
.collection(defaultCollections.Sessions)
.findOne({ sessionToken })
if (!session) return null
return format.from(session)
},
async verificationToken(identifier_token) {
const token = await client
.db()
.collection(defaultCollections.VerificationTokens)
.findOne(identifier_token)
if (!token) return null
const { _id, ...rest } = token
return rest
},
},
})

View file

@ -1,34 +0,0 @@
#!/usr/bin/env bash
CONTAINER_NAME=next-auth-mongodb-test
JEST_WATCH=false
# Is the watch flag passed to the script?
while getopts w flag
do
case "${flag}" in
w) JEST_WATCH=true;;
*) continue;;
esac
done
# Start db
docker run -d --rm -p 27017:27017 --name ${CONTAINER_NAME} mongo
echo "Waiting 3 sec for db to start..."
sleep 3
if $JEST_WATCH; then
# Run jest in watch mode
npx jest tests --watch
# Only stop the container after jest has been quit
docker stop "${CONTAINER_NAME}"
else
# Always stop container, but exit with 1 when tests are failing
if npx jest;then
docker stop ${CONTAINER_NAME}
else
docker stop ${CONTAINER_NAME} && exit 1
fi
fi