From 6bcd2684e53c0ea525d3bc616d88801a02ca2649 Mon Sep 17 00:00:00 2001 From: Bereket Engida Date: Fri, 30 Aug 2024 12:28:23 +0300 Subject: [PATCH] test: init --- dev/next-app/prisma/db.sqlite | Bin 188416 -> 196608 bytes dev/next-app/src/lib/auth-client.ts | 7 ++ .../src/__snapshots__/init.test.ts.snap | 100 ++++++++++++++++++ packages/better-auth/src/api/index.ts | 2 + packages/better-auth/src/api/routes/ok.ts | 13 +++ .../better-auth/src/api/routes/signin.test.ts | 64 +++-------- packages/better-auth/src/auth.ts | 1 - packages/better-auth/src/client/base.ts | 10 +- .../better-auth/src/client/fetch-plugins.ts | 2 + packages/better-auth/src/client/preact.ts | 2 +- packages/better-auth/src/client/proxy.ts | 4 - packages/better-auth/src/client/react.ts | 2 +- packages/better-auth/src/client/type.ts | 7 +- packages/better-auth/src/client/vue.ts | 2 +- packages/better-auth/src/init.test.ts | 22 ++++ packages/better-auth/src/init.ts | 1 + 16 files changed, 180 insertions(+), 59 deletions(-) create mode 100644 packages/better-auth/src/__snapshots__/init.test.ts.snap create mode 100644 packages/better-auth/src/api/routes/ok.ts create mode 100644 packages/better-auth/src/init.test.ts diff --git a/dev/next-app/prisma/db.sqlite b/dev/next-app/prisma/db.sqlite index 37368446ed2356c0e8cd3f374f385f9232bbce5c..ee1751769f9d95d03a36ab639a118d71e41287f0 100644 GIT binary patch delta 4033 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 bM>P}qfglPy1yH*=Wi1fB(mB`ad7A$Mdv>9s delta 1061 zcmXAne@xVM7{|ZQ^Zj|>`~HBYhChbiJGeUzkgkAMVBnm%j3`*E<{)7)mot_(U6QrM z9a_u4ICi+lEEAIBOj#bB@NMX(WwoZUSW`-6-P&wansZQ1gI1q|&tK2y{XBoX->>Hh zg|yIlXJn;lavWFGZB>Ff)YQL2S!V8K0#_8(f`#4PJ;`r_Ck?873bg3nwtc`Ql~B7$ zw~wJ)U{kATtslJ#t5$mW8YE3a3%N7xkPC6YU3Z{vT@4TZ#47EjS3@6pV7zlINzbS>kU|{KP;TlGsLg7-=S6eQah@>u05*- zG}U9kQdlp_@>1!JbV>MG z8j!+Ly;O?hQigaljc4K6zCH*+^rtSju#kSD2`&2LW5^TOke4QE84Td<@?$UqRAGag z28SV^_QYT;4KEnI)oRfPBTz_&hS`i8^_+%kY8wR)HQBJsu86}0WvS4^DBj@2&&3bL zRa zba7e~g_JNR^w^ULSPv8&O53cWvSHXwfpcg{P`(hSa3fmw-^1_`q}>wTx(XKE_2Vuo z7=iPo-DBUk{a8qyQ^2bztS!j{tdf4d`_UjF7@xTt_ zem#>fmPFB|-PFF8j%a;yJ$&Y<8AqU6kRJwXB7oVh- z0p>HAi?7g3KYF9{VGp%<@O{dPG5rBA)5A<(wApl+?R46UuhEizmMQFGBif^B>r*uD z!$S-WY@)tF)(ahHy@}&2Xl19L)_sC4(YXVDa-F~x_NRV)9_YUq`sl$Fu145QH3hhn zTm#J1F9mp3$mMH*LUmw40mb{V+Rj{qvpa=yxt60qFJ|4R7{)UFj($;(=^?#dFO_%G zmR@vgN{M<^{#8w?2h^ABNH3P~$w0J$@6S4Kp%6IZZS{U5>`Jc9rL diff --git a/dev/next-app/src/lib/auth-client.ts b/dev/next-app/src/lib/auth-client.ts index e111bb5ea3..7d38b0c887 100644 --- a/dev/next-app/src/lib/auth-client.ts +++ b/dev/next-app/src/lib/auth-client.ts @@ -4,3 +4,10 @@ import { auth } from "./auth"; export const authClient = createAuthClient({ baseURL: "http://localhost:3000/api/auth", }); + +export const { + useSession, + useActiveOrganization, + useInvitation, + useListOrganization, +} = authClient; diff --git a/packages/better-auth/src/__snapshots__/init.test.ts.snap b/packages/better-auth/src/__snapshots__/init.test.ts.snap new file mode 100644 index 0000000000..24a11825f5 --- /dev/null +++ b/packages/better-auth/src/__snapshots__/init.test.ts.snap @@ -0,0 +1,100 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`init > should match config 1`] = ` +{ + "adapter": { + "create": [Function], + "delete": [Function], + "findMany": [Function], + "findOne": [Function], + "update": [Function], + }, + "authCookies": { + "csrfToken": { + "name": "better-auth.csrf_token", + "options": { + "httpOnly": true, + "maxAge": 604800, + "path": "/", + "sameSite": "lax", + "secure": false, + }, + }, + "nonce": { + "name": "better-auth.nonce", + "options": { + "httpOnly": true, + "maxAge": 900, + "path": "/", + "sameSite": "lax", + "secure": false, + }, + }, + "pkCodeVerifier": { + "name": "better-auth.pk_code_verifier", + "options": { + "httpOnly": true, + "maxAge": 900, + "path": "/", + "sameSite": "lax", + "secure": false, + }, + }, + "sessionToken": { + "name": "better-auth.session_token", + "options": { + "httpOnly": true, + "maxAge": 604800, + "path": "/", + "sameSite": "lax", + "secure": false, + }, + }, + "state": { + "name": "better-auth.state", + "options": { + "httpOnly": true, + "maxAge": 900, + "path": "/", + "sameSite": "lax", + "secure": false, + }, + }, + }, + "baseURL": "http://localhost:3000/api/auth", + "createAuthCookie": [Function], + "db": Kysely {}, + "internalAdapter": { + "createOAuthUser": [Function], + "createSession": [Function], + "createUser": [Function], + "deleteSession": [Function], + "findSession": [Function], + "findUserByEmail": [Function], + "findUserById": [Function], + "linkAccount": [Function], + "updatePassword": [Function], + "updateSession": [Function], + "updateUserByEmail": [Function], + }, + "logger": { + "box": [Function], + "break": [Function], + "debug": [Function], + "error": [Function], + "info": [Function], + "log": [Function], + "success": [Function], + "warn": [Function], + }, + "options": { + "basePath": "/api/auth", + "baseURL": "http://localhost:3000", + "database": { + "provider": "sqlite", + "url": ":memory:", + }, + }, + "secret": "better-auth-secret-123456789", +} +`; diff --git a/packages/better-auth/src/api/index.ts b/packages/better-auth/src/api/index.ts index 95b8e7565e..d4bff25ef0 100644 --- a/packages/better-auth/src/api/index.ts +++ b/packages/better-auth/src/api/index.ts @@ -17,6 +17,7 @@ import { signUpCredential } from "./routes/sign-up"; import { parseAccount, parseSession, parseUser } from "../adapters/schema"; import { BetterAuthOptions, InferSession, InferUser } from "../types"; import { Prettify } from "../types/helper"; +import { ok } from "./routes/ok"; export const router = ( ctx: C, @@ -92,6 +93,7 @@ export const router = ( const endpoints = { ...baseEndpoints, ...pluginEndpoints, + ok, }; let api: Record = {}; for (const [key, value] of Object.entries(endpoints)) { diff --git a/packages/better-auth/src/api/routes/ok.ts b/packages/better-auth/src/api/routes/ok.ts new file mode 100644 index 0000000000..1031431256 --- /dev/null +++ b/packages/better-auth/src/api/routes/ok.ts @@ -0,0 +1,13 @@ +import { createAuthEndpoint } from "../call"; + +export const ok = createAuthEndpoint( + "/ok", + { + method: "GET", + }, + async (ctx) => { + return ctx.json({ + ok: true, + }); + }, +); diff --git a/packages/better-auth/src/api/routes/signin.test.ts b/packages/better-auth/src/api/routes/signin.test.ts index fba8c007a5..5956e094a7 100644 --- a/packages/better-auth/src/api/routes/signin.test.ts +++ b/packages/better-auth/src/api/routes/signin.test.ts @@ -1,56 +1,24 @@ import { describe, expect, it } from "vitest"; import { getTestInstance } from "../../test-utils/test-instance"; +import { createAuthClient } from "../../client"; describe("signIn", async () => { - const app = await getTestInstance(); - it("should sign up with credential", async () => { - const res = await app.api.signUpCredential({ - body: { - email: "test@test.com", - password: "test1234", - name: "test", - }, - }); - expect(res).toMatchObject({ - user: { - id: expect.any(String), - email: "test@test.com", - name: "test", - image: undefined, - emailVerified: false, - createdAt: expect.any(Date), - updatedAt: expect.any(Date), - }, - session: { - id: expect.any(String), - userId: expect.any(String), - expiresAt: expect.any(Date), - }, - }); + const auth = await getTestInstance(); + const client = createAuthClient({ + customFetchImpl: async (url, init) => { + const req = new Request(url.toString(), init); + const res = await auth.handler(req); + return res; + }, + csrfPlugin: false, }); - it("should sign in with credential", async () => { - const res = await app.api.signInCredential({ - body: { - email: "test@test.com", - password: "test1234", - }, - }); - expect(res).toMatchObject({ - user: { - id: expect.any(String), - email: "test@test.com", - name: "test", - image: null, - emailVerified: false, - createdAt: expect.any(Date), - updatedAt: expect.any(Date), - }, - session: { - id: expect.any(String), - userId: expect.any(String), - expiresAt: expect.any(Date), - }, - }); + it("should sign up with email and password", async () => { + // const res = await client.signUp.credential({ + // email: "test@test.com", + // password: "test", + // name: "test", + // }); + // console.log(res); }); }); diff --git a/packages/better-auth/src/auth.ts b/packages/better-auth/src/auth.ts index 936d9f33dc..c677b70365 100644 --- a/packages/better-auth/src/auth.ts +++ b/packages/better-auth/src/auth.ts @@ -13,7 +13,6 @@ export const betterAuth = (options: O) => { : {} : {} >; - const { handler, endpoints } = router(authContext, options); type Endpoint = typeof endpoints; return { diff --git a/packages/better-auth/src/client/base.ts b/packages/better-auth/src/client/base.ts index 5ff386d907..6ab9fc06bf 100644 --- a/packages/better-auth/src/client/base.ts +++ b/packages/better-auth/src/client/base.ts @@ -10,7 +10,7 @@ import { ClientOptions, HasPlugin } from "./type"; import { getBaseURL } from "../utils/base-url"; import type { router } from "../api"; -export const createVanillaClient = ( +export const createAuthClient = ( options?: ClientOptions, ) => { type BAuth = Auth extends never ? BetterAuth : Auth; @@ -18,9 +18,15 @@ export const createVanillaClient = ( ? ReturnType["endpoints"] : BAuth["api"]; const $fetch = createFetch({ + method: "GET", ...options, baseURL: getBaseURL(options?.baseURL).withPath, - plugins: [redirectPlugin, addCurrentURL, csrfPlugin], + plugins: [ + redirectPlugin, + addCurrentURL, + ...(options?.csrfPlugin !== false ? [csrfPlugin] : []), + ...(options?.plugins || []), + ], }); const { $session, $sessionSignal } = getSessionAtom($fetch); const { signInPasskey, register } = getPasskeyActions($fetch); diff --git a/packages/better-auth/src/client/fetch-plugins.ts b/packages/better-auth/src/client/fetch-plugins.ts index 11f7d98f0e..a842389a2d 100644 --- a/packages/better-auth/src/client/fetch-plugins.ts +++ b/packages/better-auth/src/client/fetch-plugins.ts @@ -39,6 +39,8 @@ export const csrfPlugin = { csrfToken: string; }>("/csrf", { baseURL: options.baseURL, + ...options, + plugins: [], }); if (error?.status === 404) { throw new BetterAuthError( diff --git a/packages/better-auth/src/client/preact.ts b/packages/better-auth/src/client/preact.ts index 9081fe2de6..74524ab84c 100644 --- a/packages/better-auth/src/client/preact.ts +++ b/packages/better-auth/src/client/preact.ts @@ -1,7 +1,7 @@ import { useStore } from "@nanostores/react"; export const useAuthStore = useStore; -import { createVanillaClient } from "./base"; +import { createAuthClient as createVanillaClient } from "./base"; import { BetterFetchOption } from "@better-fetch/fetch"; export const createAuthClient = (options?: BetterFetchOption) => { diff --git a/packages/better-auth/src/client/proxy.ts b/packages/better-auth/src/client/proxy.ts index 05d2e693c4..535a418a80 100644 --- a/packages/better-auth/src/client/proxy.ts +++ b/packages/better-auth/src/client/proxy.ts @@ -65,10 +65,6 @@ export function createDynamicPathProxy>( method, onSuccess() { const signal = $signal?.find((s) => s.matcher(routePath)); - console.log({ - signal, - routePath, - }); if (signal) { signal.atom.set(!signal.atom.get()); } diff --git a/packages/better-auth/src/client/react.ts b/packages/better-auth/src/client/react.ts index 77d0c94d8a..aeee9a1555 100644 --- a/packages/better-auth/src/client/react.ts +++ b/packages/better-auth/src/client/react.ts @@ -1,5 +1,5 @@ import { useStore } from "@nanostores/react"; -import { createVanillaClient } from "./base"; +import { createAuthClient as createVanillaClient } from "./base"; import { BetterFetchOption } from "@better-fetch/fetch"; import { BetterAuth } from "../auth"; import { InferSession, InferUser } from "../types"; diff --git a/packages/better-auth/src/client/type.ts b/packages/better-auth/src/client/type.ts index ae994997e6..14c7609bb1 100644 --- a/packages/better-auth/src/client/type.ts +++ b/packages/better-auth/src/client/type.ts @@ -5,7 +5,12 @@ import type { useAuthStore as reactStore } from "./react"; import type { useAuthStore as vueStore } from "./vue"; export type AuthStore = typeof reactStore | typeof vueStore; -export interface ClientOptions extends BetterFetchOption {} +export interface ClientOptions extends BetterFetchOption { + /** + * csrf plugin is enabled by default + */ + csrfPlugin?: boolean; +} export type HasPlugin< PluginId extends string, diff --git a/packages/better-auth/src/client/vue.ts b/packages/better-auth/src/client/vue.ts index 290f43fbfb..3af80fa2ba 100644 --- a/packages/better-auth/src/client/vue.ts +++ b/packages/better-auth/src/client/vue.ts @@ -1,6 +1,6 @@ import { useStore } from "@nanostores/vue"; import { BetterFetchOption } from "@better-fetch/fetch"; -import { createVanillaClient } from "./base"; +import { createAuthClient as createVanillaClient } from "./base"; export const createAuthClient = (options?: BetterFetchOption) => { const client = createVanillaClient(options); diff --git a/packages/better-auth/src/init.test.ts b/packages/better-auth/src/init.test.ts new file mode 100644 index 0000000000..9e6a7c4dd9 --- /dev/null +++ b/packages/better-auth/src/init.test.ts @@ -0,0 +1,22 @@ +import { describe, expect, it } from "vitest"; +import { init } from "./init"; +import { createAuthClient } from "./client"; + +describe("init", async () => { + const client = createAuthClient(); + + it("should match config", () => { + const res = init({ + database: { + provider: "sqlite", + url: ":memory:", + }, + }); + expect(res).toMatchSnapshot(); + }); + + it("should respond ok endpoint", async () => { + const res = await client.$fetch<{ ok: boolean }>("/ok"); + expect(res.data?.ok).toBe(true); + }); +}); diff --git a/packages/better-auth/src/init.ts b/packages/better-auth/src/init.ts index d3d9eb1ff7..077d73aa7a 100644 --- a/packages/better-auth/src/init.ts +++ b/packages/better-auth/src/init.ts @@ -19,6 +19,7 @@ export const init = (options: BetterAuthOptions) => { options: { ...options, baseURL: baseURL, + basePath: options.basePath || "/api/auth", }, baseURL: withPath, secret: