Skip to content

Commit 11cfb0a

Browse files
employee451ndom91
andauthored
fix(fauna): support custom collection names (#10321)
Co-authored-by: Nico Domino <[email protected]>
1 parent 5a500cb commit 11cfb0a

File tree

7 files changed

+135
-27
lines changed

7 files changed

+135
-27
lines changed

packages/adapter-fauna/fauna/account.fsl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,13 @@ collection Account {
66
terms [.provider, .providerAccountId]
77
}
88
}
9+
10+
collection CustomAccount {
11+
index byUserId {
12+
terms [.userId]
13+
}
14+
index byProviderAndProviderAccountId {
15+
terms [.provider, .providerAccountId]
16+
}
17+
}
18+

packages/adapter-fauna/fauna/session.fsl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,14 @@ collection Session {
77
terms [.userId]
88
}
99
}
10+
11+
collection CustomSession {
12+
unique [.sessionToken]
13+
index bySessionToken {
14+
terms [.sessionToken]
15+
}
16+
index byUserId {
17+
terms [.userId]
18+
}
19+
}
20+

packages/adapter-fauna/fauna/user.fsl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,10 @@ collection User {
44
terms [.email]
55
}
66
}
7+
8+
collection CustomUser {
9+
unique [.email]
10+
index byEmail {
11+
terms [.email]
12+
}
13+
}

packages/adapter-fauna/fauna/verificationToken.fsl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,10 @@ collection VerificationToken {
33
terms [.identifier, .token]
44
}
55
}
6+
7+
collection CustomVerificationToken {
8+
index byIdentifierAndToken {
9+
terms [.identifier, .token]
10+
}
11+
}
12+

packages/adapter-fauna/src/index.ts

Lines changed: 55 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
*
1515
* @module @auth/fauna-adapter
1616
*/
17-
import { Client, TimeStub, fql, NullDocument, QueryValue, QueryValueObject } from "fauna"
17+
import { Client, TimeStub, fql, NullDocument, QueryValue, QueryValueObject, Module } from "fauna"
1818

1919
import type {
2020
Adapter,
@@ -33,6 +33,22 @@ export type FaunaSession = ToFauna<AdapterSession>
3333
export type FaunaVerificationToken = ToFauna<VerificationToken> & { id: string }
3434
export type FaunaAccount = ToFauna<AdapterAccount>
3535

36+
type AdapterConfig = {
37+
collectionNames: {
38+
user: string
39+
session: string
40+
account: string
41+
verificationToken: string
42+
}
43+
}
44+
45+
const defaultCollectionNames = {
46+
user: "User",
47+
session: "Session",
48+
account: "Account",
49+
verificationToken: "VerificationToken",
50+
}
51+
3652
/**
3753
*
3854
* ## Setup
@@ -136,6 +152,22 @@ export type FaunaAccount = ToFauna<AdapterAccount>
136152
*
137153
* > This schema is adapted for use in Fauna and based upon our main [schema](https://authjs.dev/reference/core/adapters#models)
138154
*
155+
* #### Custom collection names
156+
* If you want to use custom collection names, you can pass them as an option to the adapter, like this:
157+
*
158+
* ```javascript
159+
* FaunaAdapter(client, {
160+
* collectionNames: {
161+
* user: "CustomUser",
162+
* account: "CustomAccount",
163+
* session: "CustomSession",
164+
* verificationToken: "CustomVerificationToken",
165+
* }
166+
* })
167+
* ```
168+
*
169+
* Make sure the collection names you pass to the provider match the collection names of your Fauna database.
170+
*
139171
* ### Migrating from v1
140172
* 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.
141173
* Additionally, we've renamed the indexes to match the new method-like index names.
@@ -191,33 +223,35 @@ export type FaunaAccount = ToFauna<AdapterAccount>
191223
* ```
192224
*
193225
**/
194-
export function FaunaAdapter(client: Client): Adapter {
226+
export function FaunaAdapter(client: Client, config?: AdapterConfig): Adapter {
227+
const { collectionNames = defaultCollectionNames } = config || {}
228+
195229
return {
196230
async createUser(user) {
197231
const response = await client.query<FaunaUser>(
198-
fql`User.create(${format.to(user)})`,
232+
fql`Collection(${collectionNames.user}).create(${format.to(user)})`,
199233
)
200234
return format.from(response.data)
201235
},
202236
async getUser(id) {
203237
const response = await client.query<FaunaUser | NullDocument>(
204-
fql`User.byId(${id})`,
238+
fql`Collection(${collectionNames.user}).byId(${id})`,
205239
)
206240
if (response.data instanceof NullDocument) return null
207241
return format.from(response.data)
208242
},
209243
async getUserByEmail(email) {
210244
const response = await client.query<FaunaUser>(
211-
fql`User.byEmail(${email}).first()`,
245+
fql`Collection(${collectionNames.user}).byEmail(${email}).first()`,
212246
)
213247
if (response.data === null) return null
214248
return format.from(response.data)
215249
},
216250
async getUserByAccount({ provider, providerAccountId }) {
217251
const response = await client.query<FaunaUser>(fql`
218-
let account = Account.byProviderAndProviderAccountId(${provider}, ${providerAccountId}).first()
252+
let account = Collection(${collectionNames.account}).byProviderAndProviderAccountId(${provider}, ${providerAccountId}).first()
219253
if (account != null) {
220-
User.byId(account.userId)
254+
Collection(${collectionNames.user}).byId(account.userId)
221255
} else {
222256
null
223257
}
@@ -228,39 +262,39 @@ export function FaunaAdapter(client: Client): Adapter {
228262
const _user: Partial<AdapterUser> = { ...user }
229263
delete _user.id
230264
const response = await client.query<FaunaUser>(
231-
fql`User.byId(${user.id}).update(${format.to(_user)})`,
265+
fql`Collection(${collectionNames.user}).byId(${user.id}).update(${format.to(_user)})`,
232266
)
233267
return format.from(response.data)
234268
},
235269
async deleteUser(userId) {
236270
await client.query(fql`
237271
// Delete the user's sessions
238-
Session.byUserId(${userId}).forEach(session => session.delete())
272+
Collection(${collectionNames.session}).byUserId(${userId}).forEach(session => session.delete())
239273
240274
// Delete the user's accounts
241-
Account.byUserId(${userId}).forEach(account => account.delete())
275+
Collection(${collectionNames.account}).byUserId(${userId}).forEach(account => account.delete())
242276
243277
// Delete the user
244-
User.byId(${userId}).delete()
278+
Collection(${collectionNames.user}).byId(${userId}).delete()
245279
`)
246280
},
247281
async linkAccount(account) {
248282
await client.query<FaunaAccount>(
249-
fql`Account.create(${format.to(account)})`,
283+
fql`Collection(${collectionNames.account}).create(${format.to(account)})`,
250284
)
251285
return account
252286
},
253287
async unlinkAccount({ provider, providerAccountId }) {
254288
const response = await client.query<FaunaAccount>(
255-
fql`Account.byProviderAndProviderAccountId(${provider}, ${providerAccountId}).first().delete()`,
289+
fql`Collection(${collectionNames.account}).byProviderAndProviderAccountId(${provider}, ${providerAccountId}).first().delete()`,
256290
)
257291
return format.from<AdapterAccount>(response.data)
258292
},
259293
async getSessionAndUser(sessionToken) {
260294
const response = await client.query<[FaunaUser, FaunaSession]>(fql`
261-
let session = Session.bySessionToken(${sessionToken}).first()
295+
let session = Collection(${collectionNames.session}).bySessionToken(${sessionToken}).first()
262296
if (session != null) {
263-
let user = User.byId(session.userId)
297+
let user = Collection(${collectionNames.user}).byId(session.userId)
264298
if (user != null) {
265299
[user, session]
266300
} else {
@@ -276,39 +310,39 @@ export function FaunaAdapter(client: Client): Adapter {
276310
},
277311
async createSession(session) {
278312
await client.query<FaunaSession>(
279-
fql`Session.create(${format.to(session)})`,
313+
fql`Collection(${collectionNames.session}).create(${format.to(session)})`,
280314
)
281315
return session
282316
},
283317
async updateSession(session) {
284318
const response = await client.query<FaunaSession>(
285-
fql`Session.bySessionToken(${
319+
fql`Collection(${collectionNames.session}).bySessionToken(${
286320
session.sessionToken
287321
}).first().update(${format.to(session)})`,
288322
)
289323
return format.from(response.data)
290324
},
291325
async deleteSession(sessionToken) {
292326
await client.query(
293-
fql`Session.bySessionToken(${sessionToken}).first().delete()`,
327+
fql`Collection(${collectionNames.session}).bySessionToken(${sessionToken}).first().delete()`,
294328
)
295329
},
296330
async createVerificationToken(verificationToken) {
297331
await client.query<FaunaVerificationToken>(
298-
fql`VerificationToken.create(${format.to(
332+
fql`Collection(${collectionNames.verificationToken}).create(${format.to(
299333
verificationToken,
300334
)})`,
301335
)
302336
return verificationToken
303337
},
304338
async useVerificationToken({ identifier, token }) {
305339
const response = await client.query<FaunaVerificationToken>(
306-
fql`VerificationToken.byIdentifierAndToken(${identifier}, ${token}).first()`,
340+
fql`Collection(${collectionNames.verificationToken}).byIdentifierAndToken(${identifier}, ${token}).first()`,
307341
)
308342
if (response.data === null) return null
309343
// Delete the verification token so it can only be used once
310344
await client.query(
311-
fql`VerificationToken.byId(${response.data.id}).delete()`,
345+
fql`Collection(${collectionNames.verificationToken}).byId(${response.data.id}).delete()`,
312346
)
313347
const _verificationToken: Partial<FaunaVerificationToken> = { ...response.data }
314348
delete _verificationToken.id

packages/adapter-fauna/test/index.test.ts

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,11 @@ const client = new Client({
1717
endpoint: new URL("http://localhost:8443"),
1818
})
1919

20-
const adapter = FaunaAdapter(client)
21-
2220
runBasicTests({
23-
adapter,
21+
adapter: FaunaAdapter(client),
2422
db: {
2523
// UUID is not a valid ID in Fauna (see https://docs.fauna.com/fauna/current/reference/fql_reference/types#id)
2624
id: () => String(Math.floor(Math.random() * 10 ** 18)),
27-
disconnect: async () => client.close(),
2825
user: async (id) => {
2926
const response = await client.query<FaunaUser>(
3027
fql`User.byId(${id})`,
@@ -54,3 +51,45 @@ runBasicTests({
5451
},
5552
},
5653
})
54+
55+
runBasicTests({
56+
adapter: FaunaAdapter(client, {
57+
collectionNames: {
58+
user: "CustomUser",
59+
account: "CustomAccount",
60+
session: "CustomSession",
61+
verificationToken: "CustomVerificationToken",
62+
}
63+
}),
64+
db: {
65+
// UUID is not a valid ID in Fauna (see https://docs.fauna.com/fauna/current/reference/fql_reference/types#id)
66+
id: () => String(Math.floor(Math.random() * 10 ** 18)),
67+
user: async (id) => {
68+
const response = await client.query<FaunaUser>(
69+
fql`CustomUser.byId(${id})`,
70+
)
71+
if (response.data instanceof NullDocument) return null
72+
return format.from(response.data)
73+
},
74+
async session(sessionToken) {
75+
const response = await client.query<FaunaSession>(
76+
fql`CustomSession.bySessionToken(${sessionToken}).first()`,
77+
)
78+
return format.from(response.data)
79+
},
80+
async account({ provider, providerAccountId }) {
81+
const response = await client.query<FaunaAccount>(
82+
fql`CustomAccount.byProviderAndProviderAccountId(${provider}, ${providerAccountId}).first()`,
83+
)
84+
return format.from(response.data)
85+
},
86+
async verificationToken({ identifier, token }) {
87+
const response = await client.query<FaunaVerificationToken>(
88+
fql`CustomVerificationToken.byIdentifierAndToken(${identifier}, ${token}).first()`,
89+
)
90+
const _verificationToken: Partial<FaunaVerificationToken> = { ...response.data }
91+
delete _verificationToken.id
92+
return format.from(_verificationToken)
93+
},
94+
},
95+
})

packages/adapter-fauna/test/test.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ docker run -d --rm \
1010
-p ${FAUNADB_PORT}:${FAUNADB_PORT} \
1111
fauna/faunadb
1212

13-
echo "Waiting 10s for db to start..."
14-
sleep 10
13+
echo "Waiting 15s for db to start..."
14+
sleep 15
1515

1616
# Create collections and indexes
1717
fauna schema push --url=http://localhost:8443 --force --secret=${FAUNA_ADMIN_KEY}

0 commit comments

Comments
 (0)