Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(core): centralize isDate util fn and use in all adapters #10872

Merged
merged 15 commits into from
May 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 8 additions & 26 deletions packages/adapter-d1/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@

import type { D1Database as WorkerDatabase } from "@cloudflare/workers-types"
import type { D1Database as MiniflareD1Database } from "@miniflare/d1"
import type {
Adapter,
AdapterSession,
AdapterUser,
AdapterAccount,
VerificationToken as AdapterVerificationToken,
import {
type Adapter,
type AdapterSession,
type AdapterUser,
type AdapterAccount,
type VerificationToken as AdapterVerificationToken,
isDate,
} from "@auth/core/adapters"

export { up } from "./migrations.js"
Expand All @@ -36,8 +37,6 @@ export { up } from "./migrations.js"
*/
export type D1Database = WorkerDatabase | MiniflareD1Database

// all the sqls
// USER
export const CREATE_USER_SQL = `INSERT INTO users (id, name, email, emailVerified, image) VALUES (?, ?, ?, ?, ?)`
export const GET_USER_BY_ID_SQL = `SELECT * FROM users WHERE id = ?`
export const GET_USER_BY_EMAIL_SQL = `SELECT * FROM users WHERE email = ?`
Expand Down Expand Up @@ -81,17 +80,6 @@ export const GET_VERIFICATION_TOKEN_BY_IDENTIFIER_AND_TOKEN_SQL = `SELECT * FROM
export const CREATE_VERIFICATION_TOKEN_SQL = `INSERT INTO verification_tokens (identifier, expires, token) VALUES (?,?,?)`
export const DELETE_VERIFICATION_TOKEN_SQL = `DELETE FROM verification_tokens WHERE identifier = ? and token = ?`

// helper functions

// isDate is borrowed from the supabase adapter, graciously
// depending on error messages ("Invalid Date") is always precarious, but probably fine for a built in native like Date
function isDate(date: any) {
return (
new Date(date).toString() !== "Invalid Date" && !isNaN(Date.parse(date))
)
}

// format is borrowed from the supabase adapter, graciously
function format<T>(obj: Record<string, any>): T {
for (const [key, value] of Object.entries(obj)) {
if (value === null) {
Expand Down Expand Up @@ -242,7 +230,6 @@ export function D1Adapter(db: D1Database): Adapter {
params.id,
])
if (res.success) {
// we could probably just return
const user = await getRecord<AdapterUser>(db, GET_USER_BY_ID_SQL, [
params.id,
])
Expand All @@ -255,8 +242,7 @@ export function D1Adapter(db: D1Database): Adapter {
throw new Error("Error updating user: Failed to run the update SQL.")
},
async deleteUser(userId) {
// this should probably be in a db.batch but batch has problems right now in miniflare
// no multi line sql statements
// miniflare doesn't support batch operations or multiline sql statements
await deleteRecord(db, DELETE_ACCOUNT_BY_USER_ID_SQL, [userId])
await deleteRecord(db, DELETE_SESSION_BY_USER_ID_SQL, [userId])
await deleteRecord(db, DELETE_USER_SQL, [userId])
Expand Down Expand Up @@ -317,10 +303,8 @@ export function D1Adapter(db: D1Database): Adapter {
GET_SESSION_BY_TOKEN_SQL,
[sessionToken]
)
// no session? no user!
if (session === null) return null

// this shouldnt happen, but just in case
const user = await getRecord<AdapterUser>(db, GET_USER_BY_ID_SQL, [
session.userId,
])
Expand All @@ -329,8 +313,6 @@ export function D1Adapter(db: D1Database): Adapter {
return { session, user }
},
async updateSession({ sessionToken, expires }) {
// kinda strange that we have to deal with an undefined expires,
// we dont have any policy to enforce, lets just expire it now.
if (expires === undefined) {
await deleteRecord(db, DELETE_SESSION_SQL, [sessionToken])
return null
Expand Down
3 changes: 1 addition & 2 deletions packages/adapter-d1/test/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { test, beforeAll, expect } from "vitest"
import { beforeAll } from "vitest"

import {
D1Adapter,
Expand All @@ -22,7 +22,6 @@ const sqliteDB = new Database(":memory:")
let db = new D1Database(new D1DatabaseAPI(sqliteDB as any))
let adapter = D1Adapter(db)

// put stuff here if we need some async init
beforeAll(async () => await up(db))
runBasicTests({
adapter,
Expand Down
22 changes: 18 additions & 4 deletions packages/adapter-dgraph/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
* @module @auth/dgraph-adapter
*/
import { client as dgraphClient } from "./lib/client"
import { format } from "./lib/utils"
import type { Adapter } from "@auth/core/adapters"
import { isDate, type Adapter } from "@auth/core/adapters"
import type { DgraphClientParams } from "./lib/client"
import * as defaultFragments from "./lib/graphql/fragments"

Expand All @@ -39,8 +38,6 @@ export interface DgraphAdapterOptions {
}
}

export { format }

export function DgraphAdapter(
client: DgraphClientParams,
options?: DgraphAdapterOptions
Expand Down Expand Up @@ -336,3 +333,20 @@ export function DgraphAdapter(
},
}
}

export const format = {
from<T>(object?: Record<string, any>): T | null {
const newObject: Record<string, unknown> = {}
if (!object) return null
for (const key in object) {
const value = object[key]
if (isDate(value)) {
newObject[key] = new Date(value)
} else {
newObject[key] = value
}
}

return newObject as T
},
}
24 changes: 0 additions & 24 deletions packages/adapter-dgraph/src/lib/utils.ts

This file was deleted.

20 changes: 7 additions & 13 deletions packages/adapter-dynamodb/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@ import type {
BatchWriteCommandInput,
DynamoDBDocument,
} from "@aws-sdk/lib-dynamodb"
import type {
Adapter,
AdapterSession,
AdapterAccount,
AdapterUser,
VerificationToken,
import {
type Adapter,
type AdapterSession,
type AdapterAccount,
type AdapterUser,
type VerificationToken,
isDate,
} from "@auth/core/adapters"

export interface DynamoDBAdapterOptions {
Expand Down Expand Up @@ -344,13 +345,6 @@ export function DynamoDBAdapter(
}
}

// https://github.com/honeinc/is-iso-date/blob/master/index.js
const isoDateRE =
/(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))/
function isDate(value: any) {
return value && isoDateRE.test(value) && !isNaN(Date.parse(value))
}

const format = {
/** Takes a plain old JavaScript object and turns it into a DynamoDB object */
to(object: Record<string, any>) {
Expand Down
10 changes: 1 addition & 9 deletions packages/adapter-hasura/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* @module @auth/hasura-adapter
*/

import type { Adapter } from "@auth/core/adapters"
import { isDate, type Adapter } from "@auth/core/adapters"

import {
client as hasuraClient,
Expand Down Expand Up @@ -174,14 +174,6 @@ export function HasuraAdapter(client: HasuraAdapterClient): Adapter {
}
}

// https://github.com/honeinc/is-iso-date/blob/master/index.js
const isoDateRE =
/(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))/

function isDate(value: any) {
return value && isoDateRE.test(value) && !isNaN(Date.parse(value))
}

export const format = {
from<T, B extends boolean = false>(
object?: Record<string, any> | null | undefined,
Expand Down
20 changes: 7 additions & 13 deletions packages/adapter-kysely/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@

import { Kysely, SqliteAdapter } from "kysely"

import type {
Adapter,
AdapterUser,
AdapterAccount,
AdapterSession,
VerificationToken,
import {
type Adapter,
type AdapterUser,
type AdapterAccount,
type AdapterSession,
type VerificationToken,
isDate,
} from "@auth/core/adapters"

export interface Database {
Expand All @@ -32,13 +33,6 @@ export interface Database {
VerificationToken: VerificationToken
}

// https://github.com/honeinc/is-iso-date/blob/master/index.js
const isoDateRE =
/(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))/
function isDate(value: any) {
return value && isoDateRE.test(value) && !isNaN(Date.parse(value))
}

export const format = {
from<T>(object?: Record<string, any>): T {
const newObject: Record<string, unknown> = {}
Expand Down
10 changes: 1 addition & 9 deletions packages/adapter-neo4j/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* @module @auth/neo4j-adapter
*/
import { type Session, isInt, integer } from "neo4j-driver"
import type { Adapter } from "@auth/core/adapters"
import { isDate, type Adapter } from "@auth/core/adapters"

/**
* This is the interface of the Neo4j adapter options. The Neo4j adapter takes a {@link https://neo4j.com/docs/bolt/current/driver-api/#driver-session Neo4j session} as its only argument.
Expand Down Expand Up @@ -182,14 +182,6 @@ export function Neo4jAdapter(session: Session): Adapter {
}
}

// https://github.com/honeinc/is-iso-date/blob/master/index.js
const isoDateRE =
/(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))/

function isDate(value: any) {
return value && isoDateRE.test(value) && !isNaN(Date.parse(value))
}

export const format = {
/** Takes a plain old JavaScript object and turns it into a Neo4j compatible object */
to(object: Record<string, any>) {
Expand Down
15 changes: 5 additions & 10 deletions packages/adapter-supabase/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,13 @@
*/
import { createClient } from "@supabase/supabase-js"
import {
Adapter,
AdapterSession,
AdapterUser,
VerificationToken,
type Adapter,
type AdapterSession,
type AdapterUser,
type VerificationToken,
isDate,
} from "@auth/core/adapters"

function isDate(date: any) {
return (
new Date(date).toString() !== "Invalid Date" && !isNaN(Date.parse(date))
)
}

export function format<T>(obj: Record<string, any>): T {
for (const [key, value] of Object.entries(obj)) {
if (value === null) {
Expand Down
7 changes: 1 addition & 6 deletions packages/adapter-unstorage/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import type {
AdapterAuthenticator,
VerificationToken,
} from "@auth/core/adapters"
import { isDate } from "@auth/core/adapters"
import type { Storage, StorageValue } from "unstorage"

/** This is the interface of the Unstorage adapter options. */
Expand Down Expand Up @@ -88,12 +89,6 @@ export const defaultOptions = {
useItemRaw: false,
}

const isoDateRE =
/(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))/
function isDate(value: any) {
return value && isoDateRE.test(value) && !isNaN(Date.parse(value))
}

export function hydrateDates(json: Record<string, any>) {
return Object.entries(json).reduce((acc, [key, val]) => {
acc[key] = isDate(val) ? new Date(val as string) : val
Expand Down
19 changes: 7 additions & 12 deletions packages/adapter-upstash-redis/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@
*
* @module @auth/upstash-redis-adapter
*/
import type {
Adapter,
AdapterUser,
AdapterAccount,
AdapterSession,
VerificationToken,
import {
type Adapter,
type AdapterUser,
type AdapterAccount,
type AdapterSession,
type VerificationToken,
isDate,
} from "@auth/core/adapters"
import type { Redis } from "@upstash/redis"

Expand Down Expand Up @@ -70,12 +71,6 @@ export const defaultOptions = {
verificationTokenKeyPrefix: "user:token:",
}

const isoDateRE =
/(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))/
function isDate(value: any) {
return value && isoDateRE.test(value) && !isNaN(Date.parse(value))
}

export function hydrateDates(json: object) {
return Object.entries(json).reduce((acc, [key, val]) => {
acc[key] = isDate(val) ? new Date(val as string) : val
Expand Down
3 changes: 2 additions & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@
"import": "./index.js"
},
"./adapters": {
"types": "./adapters.d.ts"
"types": "./adapters.d.ts",
"import": "./adapters.js"
},
"./errors": {
"types": "./errors.d.ts",
Expand Down
8 changes: 8 additions & 0 deletions packages/core/src/adapters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,14 @@
): Awaitable<AdapterAuthenticator>
}

// https://github.com/honeinc/is-iso-date/blob/master/index.js
const isoDateRE =
/(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))/

export function isDate(value: any) {
return value && isoDateRE.test(value) && !isNaN(Date.parse(value))
}

Check warning on line 447 in packages/core/src/adapters.ts

View check run for this annotation

Codecov / codecov/patch

packages/core/src/adapters.ts#L440-L447

Added lines #L440 - L447 were not covered by tests
// For compatibility with older versions of NextAuth.js
// @ts-expect-error
declare module "next-auth/adapters" {
Expand Down
Loading