@farm.js/auth 0.1.0-beta.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Farm.js Team
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
@@ -0,0 +1,31 @@
1
+ import type { FarmAuthClientOptions, FarmAuthCredentials, FarmAuthSignUpInput } from "./types.js";
2
+ export declare function createFarmAuthClient(options?: FarmAuthClientOptions): {
3
+ signIn: (input: FarmAuthCredentials) => any;
4
+ signUp: (input: FarmAuthSignUpInput) => any;
5
+ signOut: () => any;
6
+ getSession: () => any;
7
+ useAuth: () => {
8
+ user: any;
9
+ session: any;
10
+ isPending: any;
11
+ isRefetching: any;
12
+ error: any;
13
+ refetch: any;
14
+ signIn: (input: FarmAuthCredentials) => any;
15
+ signUp: (input: FarmAuthSignUpInput) => any;
16
+ signOut: () => any;
17
+ };
18
+ };
19
+ export declare const getSession: () => any, signIn: (input: FarmAuthCredentials) => any, signOut: () => any, signUp: (input: FarmAuthSignUpInput) => any, useAuth: () => {
20
+ user: any;
21
+ session: any;
22
+ isPending: any;
23
+ isRefetching: any;
24
+ error: any;
25
+ refetch: any;
26
+ signIn: (input: FarmAuthCredentials) => any;
27
+ signUp: (input: FarmAuthSignUpInput) => any;
28
+ signOut: () => any;
29
+ };
30
+ export type { FarmAuthClientOptions, FarmAuthCredentials, FarmAuthSignUpInput } from "./types.js";
31
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAElG,wBAAgB,oBAAoB,CAAC,OAAO,GAAE,qBAA0B;oBAG/C,mBAAmB;oBAInB,mBAAmB;;;;;;;;;;wBAJnB,mBAAmB;wBAInB,mBAAmB;;;EAmC3C;AAID,eAAO,MAAQ,UAAU,aAAE,MAAM,UA3CR,mBAAmB,UA2CT,OAAO,aAAE,MAAM,UAvCzB,mBAAmB,UAuCQ,OAAO;;;;;;;oBA3ClC,mBAAmB;oBAInB,mBAAmB;;CAuCiC,CAAC;AAE9E,YAAY,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC"}
package/dist/client.js ADDED
@@ -0,0 +1,40 @@
1
+ "use client";
2
+ import { createAuthClient } from "better-auth/react";
3
+ export function createFarmAuthClient(options = {}) {
4
+ const client = createAuthClient(options);
5
+ function signIn(input) {
6
+ return client.signIn.email(input);
7
+ }
8
+ function signUp(input) {
9
+ return client.signUp.email(input);
10
+ }
11
+ function signOut() {
12
+ return client.signOut();
13
+ }
14
+ function getSession() {
15
+ return client.getSession();
16
+ }
17
+ function useAuth() {
18
+ const state = client.useSession();
19
+ return {
20
+ user: state.data?.user ?? null,
21
+ session: state.data?.session ?? null,
22
+ isPending: state.isPending,
23
+ isRefetching: state.isRefetching,
24
+ error: state.error,
25
+ refetch: state.refetch,
26
+ signIn,
27
+ signUp,
28
+ signOut,
29
+ };
30
+ }
31
+ return {
32
+ signIn,
33
+ signUp,
34
+ signOut,
35
+ getSession,
36
+ useAuth,
37
+ };
38
+ }
39
+ const defaultClient = createFarmAuthClient();
40
+ export const { getSession, signIn, signOut, signUp, useAuth } = defaultClient;
@@ -0,0 +1,3 @@
1
+ import type { FarmAuthUserConfig, ResolvedFarmAuthConfig } from "./types.js";
2
+ export declare function resolveFarmAuthConfig(input: FarmAuthUserConfig | undefined): ResolvedFarmAuthConfig;
3
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAK7E,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,kBAAkB,GAAG,SAAS,GACpC,sBAAsB,CAiDxB"}
package/dist/config.js ADDED
@@ -0,0 +1,70 @@
1
+ const DEFAULT_SESSION_EXPIRES_IN = 60 * 60 * 24 * 7;
2
+ const DEFAULT_SESSION_UPDATE_AGE = 60 * 60 * 24;
3
+ export function resolveFarmAuthConfig(input) {
4
+ if (input === false || input === undefined) {
5
+ return {
6
+ enabled: false,
7
+ basePath: "/api/auth",
8
+ emailAndPassword: {
9
+ enabled: true,
10
+ requireEmailVerification: false,
11
+ minPasswordLength: 8,
12
+ maxPasswordLength: 128,
13
+ },
14
+ session: {
15
+ expiresIn: DEFAULT_SESSION_EXPIRES_IN,
16
+ updateAge: DEFAULT_SESSION_UPDATE_AGE,
17
+ },
18
+ database: {
19
+ path: ".farm/auth.sqlite",
20
+ migrateInDevelopment: true,
21
+ },
22
+ };
23
+ }
24
+ const config = input === true ? {} : input;
25
+ const passwordConfig = typeof config.emailAndPassword === "object" ? config.emailAndPassword : {};
26
+ const basePath = normalizeBasePath(config.basePath);
27
+ const resolved = {
28
+ enabled: config.enabled !== false,
29
+ appName: config.appName,
30
+ basePath,
31
+ emailAndPassword: {
32
+ enabled: config.emailAndPassword !== false,
33
+ requireEmailVerification: passwordConfig.requireEmailVerification ?? false,
34
+ minPasswordLength: passwordConfig.minPasswordLength ?? 8,
35
+ maxPasswordLength: passwordConfig.maxPasswordLength ?? 128,
36
+ },
37
+ session: {
38
+ expiresIn: config.session?.expiresIn ?? DEFAULT_SESSION_EXPIRES_IN,
39
+ updateAge: config.session?.updateAge ?? DEFAULT_SESSION_UPDATE_AGE,
40
+ },
41
+ database: {
42
+ url: config.database?.url,
43
+ path: config.database?.path || ".farm/auth.sqlite",
44
+ migrateInDevelopment: config.database?.migrateInDevelopment ?? true,
45
+ },
46
+ };
47
+ validateFarmAuthConfig(resolved);
48
+ return resolved;
49
+ }
50
+ function normalizeBasePath(value) {
51
+ const path = (value || "/api/auth").trim();
52
+ const withLeadingSlash = path.startsWith("/") ? path : `/${path}`;
53
+ const normalized = withLeadingSlash.replace(/\/+/g, "/").replace(/\/+$/, "");
54
+ return normalized || "/api/auth";
55
+ }
56
+ function validateFarmAuthConfig(config) {
57
+ const { minPasswordLength, maxPasswordLength } = config.emailAndPassword;
58
+ if (!Number.isInteger(minPasswordLength) || minPasswordLength < 1) {
59
+ throw new Error("auth.emailAndPassword.minPasswordLength must be a positive integer.");
60
+ }
61
+ if (!Number.isInteger(maxPasswordLength) || maxPasswordLength < minPasswordLength) {
62
+ throw new Error("auth.emailAndPassword.maxPasswordLength must be an integer greater than or equal to minPasswordLength.");
63
+ }
64
+ if (!Number.isInteger(config.session.expiresIn) || config.session.expiresIn < 1) {
65
+ throw new Error("auth.session.expiresIn must be a positive integer.");
66
+ }
67
+ if (!Number.isInteger(config.session.updateAge) || config.session.updateAge < 0) {
68
+ throw new Error("auth.session.updateAge must be a non-negative integer.");
69
+ }
70
+ }
@@ -0,0 +1,3 @@
1
+ export { resolveFarmAuthConfig } from "./config.js";
2
+ export type { FarmAuthConfig, FarmAuthClientOptions, FarmAuthCredentials, FarmAuthDatabaseConfig, FarmAuthEmailAndPasswordConfig, FarmAuthSession, FarmAuthSessionConfig, FarmAuthSessionData, FarmAuthSignUpInput, FarmAuthUser, FarmAuthUserConfig, ResolvedFarmAuthConfig, } from "./types.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,YAAY,EACV,cAAc,EACd,qBAAqB,EACrB,mBAAmB,EACnB,sBAAsB,EACtB,8BAA8B,EAC9B,eAAe,EACf,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACnB,YAAY,EACZ,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export { resolveFarmAuthConfig } from "./config.js";
@@ -0,0 +1,22 @@
1
+ import type { ResolvedFarmAuthConfig } from "./types.js";
2
+ interface FarmAuthIntegrationOptions {
3
+ root: string;
4
+ mode: "development" | "production";
5
+ }
6
+ interface FarmAuthIntegration {
7
+ readonly kind: "farm-integration";
8
+ category: "auth";
9
+ type: "farm-auth";
10
+ instance: {
11
+ readonly kind: "farm-auth-runtime";
12
+ };
13
+ routes: Array<{
14
+ path: string;
15
+ methods: readonly ["GET", "POST"];
16
+ handler(request: Request): Promise<Response>;
17
+ }>;
18
+ }
19
+ export declare function createFarmAuthIntegration(config: ResolvedFarmAuthConfig, options: FarmAuthIntegrationOptions): FarmAuthIntegration;
20
+ export declare function migrateFarmAuth(): Promise<void>;
21
+ export {};
22
+ //# sourceMappingURL=internal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAOzD,UAAU,0BAA0B;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,aAAa,GAAG,YAAY,CAAC;CACpC;AAED,UAAU,mBAAmB;IAC3B,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,WAAW,CAAC;IAClB,QAAQ,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAA;KAAE,CAAC;IACjD,MAAM,EAAE,KAAK,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAClC,OAAO,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;KAC9C,CAAC,CAAC;CACJ;AAED,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,sBAAsB,EAC9B,OAAO,EAAE,0BAA0B,GAClC,mBAAmB,CAmBrB;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAErD"}
@@ -0,0 +1,23 @@
1
+ import { configureFarmAuth, getFarmAuthRuntime, migrateFarmAuth as runMigration, } from "./runtime.js";
2
+ export function createFarmAuthIntegration(config, options) {
3
+ configureFarmAuth(config, options);
4
+ return {
5
+ kind: "farm-integration",
6
+ category: "auth",
7
+ type: "farm-auth",
8
+ instance: Object.freeze({ kind: "farm-auth-runtime" }),
9
+ routes: [
10
+ {
11
+ path: `${config.basePath}/[...auth]`,
12
+ methods: ["GET", "POST"],
13
+ async handler(request) {
14
+ const runtime = await getFarmAuthRuntime();
15
+ return runtime.handler(request);
16
+ },
17
+ },
18
+ ],
19
+ };
20
+ }
21
+ export async function migrateFarmAuth() {
22
+ await runMigration();
23
+ }
@@ -0,0 +1,19 @@
1
+ import type { ResolvedFarmAuthConfig } from "./types.js";
2
+ interface FarmAuthRuntimeOptions {
3
+ root: string;
4
+ mode: "development" | "production";
5
+ }
6
+ interface BetterAuthRuntime {
7
+ handler(request: Request): Promise<Response>;
8
+ api: {
9
+ getSession(input: {
10
+ headers: Headers;
11
+ }): Promise<unknown>;
12
+ };
13
+ }
14
+ export declare function configureFarmAuth(config: ResolvedFarmAuthConfig, options: FarmAuthRuntimeOptions): void;
15
+ export declare function getFarmAuthRuntime(): Promise<BetterAuthRuntime>;
16
+ export declare function getFarmAuthRequest(request?: Request): Request;
17
+ export declare function migrateFarmAuth(): Promise<void>;
18
+ export {};
19
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAMzD,UAAU,sBAAsB;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,aAAa,GAAG,YAAY,CAAC;CACpC;AAED,UAAU,iBAAiB;IACzB,OAAO,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC7C,GAAG,EAAE;QACH,UAAU,CAAC,KAAK,EAAE;YAAE,OAAO,EAAE,OAAO,CAAA;SAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;KAC3D,CAAC;CACH;AAmBD,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,sBAAsB,EAC9B,OAAO,EAAE,sBAAsB,GAC9B,IAAI,CAYN;AAED,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAUrE;AAED,wBAAgB,kBAAkB,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAU7D;AAED,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAgBrD"}
@@ -0,0 +1,140 @@
1
+ import { mkdir } from "node:fs/promises";
2
+ import { createRequire } from "node:module";
3
+ import path from "node:path";
4
+ const FARM_AUTH_STATE_KEY = Symbol.for("@farm.js/auth/runtime");
5
+ const CURRENT_REQUEST_RESOLVER_KEY = Symbol.for("farm.currentRequestResolver");
6
+ const loadNodeModule = createRequire(import.meta.url);
7
+ function getState() {
8
+ const runtime = globalThis;
9
+ runtime[FARM_AUTH_STATE_KEY] ||= {};
10
+ return runtime[FARM_AUTH_STATE_KEY];
11
+ }
12
+ export function configureFarmAuth(config, options) {
13
+ const state = getState();
14
+ const changed = JSON.stringify(state.config) !== JSON.stringify(config) ||
15
+ state.options?.root !== options.root ||
16
+ state.options?.mode !== options.mode;
17
+ state.config = config;
18
+ state.options = options;
19
+ if (changed) {
20
+ state.runtime = undefined;
21
+ }
22
+ }
23
+ export async function getFarmAuthRuntime() {
24
+ const state = getState();
25
+ if (!state.config?.enabled || !state.options) {
26
+ throw new Error("Farm Auth is not enabled. Add `auth: true` to farm.config.ts before using @farm.js/auth.");
27
+ }
28
+ state.runtime ||= createRuntime(state.config, state.options);
29
+ return state.runtime;
30
+ }
31
+ export function getFarmAuthRequest(request) {
32
+ if (request)
33
+ return request;
34
+ const current = globalThis[CURRENT_REQUEST_RESOLVER_KEY]?.();
35
+ if (!current) {
36
+ throw new Error("No current request is available. Farm Auth server helpers can only be used during a request, or with an explicit `request` option.");
37
+ }
38
+ return current;
39
+ }
40
+ export async function migrateFarmAuth() {
41
+ const state = getState();
42
+ if (!state.config?.enabled || !state.options) {
43
+ throw new Error("Farm Auth is not enabled in farm.config.ts.");
44
+ }
45
+ const options = await createBetterAuthOptions(state.config, state.options, {
46
+ migration: true,
47
+ });
48
+ const { getMigrations } = await import("better-auth/db/migration");
49
+ try {
50
+ const migrations = await getMigrations(options);
51
+ await migrations.runMigrations();
52
+ }
53
+ finally {
54
+ await closeDatabase(options.database);
55
+ }
56
+ }
57
+ async function createRuntime(config, options) {
58
+ const authOptions = await createBetterAuthOptions(config, options);
59
+ if (options.mode === "development" && config.database.migrateInDevelopment) {
60
+ const { getMigrations } = await import("better-auth/db/migration");
61
+ const migrations = await getMigrations(authOptions);
62
+ await migrations.runMigrations();
63
+ }
64
+ const { betterAuth } = await import("better-auth");
65
+ return betterAuth(authOptions);
66
+ }
67
+ async function createBetterAuthOptions(config, options, runtimeOptions = {}) {
68
+ const secret = process.env.FARM_AUTH_SECRET || process.env.AUTH_SECRET || process.env.BETTER_AUTH_SECRET;
69
+ if (options.mode === "production" && !secret && !runtimeOptions.migration) {
70
+ throw new Error("Farm Auth requires FARM_AUTH_SECRET (or AUTH_SECRET) in production. Generate a random 32-byte secret and add it to your deployment environment.");
71
+ }
72
+ return {
73
+ appName: config.appName || "Farm app",
74
+ baseURL: resolveBaseURL(options.mode),
75
+ basePath: config.basePath,
76
+ secret: secret || "farm-auth-development-or-migration-secret",
77
+ database: await createDatabase(config, options),
78
+ emailAndPassword: {
79
+ enabled: config.emailAndPassword.enabled,
80
+ requireEmailVerification: config.emailAndPassword.requireEmailVerification,
81
+ minPasswordLength: config.emailAndPassword.minPasswordLength,
82
+ maxPasswordLength: config.emailAndPassword.maxPasswordLength,
83
+ },
84
+ session: {
85
+ expiresIn: config.session.expiresIn,
86
+ updateAge: config.session.updateAge,
87
+ },
88
+ };
89
+ }
90
+ function resolveBaseURL(mode) {
91
+ const configured = process.env.FARM_AUTH_URL || process.env.BETTER_AUTH_URL;
92
+ if (configured)
93
+ return configured;
94
+ if (process.env.VERCEL_URL) {
95
+ return process.env.VERCEL_URL.startsWith("http")
96
+ ? process.env.VERCEL_URL
97
+ : `https://${process.env.VERCEL_URL}`;
98
+ }
99
+ return mode === "development" ? "http://localhost:3000" : undefined;
100
+ }
101
+ async function closeDatabase(database) {
102
+ if (!database || typeof database !== "object")
103
+ return;
104
+ const connection = database;
105
+ if (typeof connection.end === "function") {
106
+ await connection.end();
107
+ return;
108
+ }
109
+ if (typeof connection.close === "function") {
110
+ await connection.close();
111
+ }
112
+ }
113
+ async function createDatabase(config, options) {
114
+ const databaseUrl = config.database.url || process.env.DATABASE_URL;
115
+ if (databaseUrl) {
116
+ const { Pool } = await import("pg");
117
+ return new Pool({ connectionString: databaseUrl });
118
+ }
119
+ if (options.mode === "production") {
120
+ throw new Error("Farm Auth requires DATABASE_URL in production. Config loading and `farm build` do not connect to the database; the connection is opened only by auth requests or `farm auth migrate`.");
121
+ }
122
+ const databasePath = path.resolve(options.root, config.database.path);
123
+ await mkdir(path.dirname(databasePath), { recursive: true });
124
+ try {
125
+ const { DatabaseSync } = loadNodeModule("node:sqlite");
126
+ return new DatabaseSync(databasePath);
127
+ }
128
+ catch {
129
+ // node:sqlite is available on Node 22+. Keep the native package fallback
130
+ // for supported older Node releases.
131
+ }
132
+ try {
133
+ const imported = await import("better-sqlite3");
134
+ const Database = imported.default;
135
+ return new Database(databasePath);
136
+ }
137
+ catch (error) {
138
+ throw new Error(`Farm Auth could not open its local SQLite database. Install better-sqlite3 or set DATABASE_URL. ${error instanceof Error ? error.message : String(error)}`);
139
+ }
140
+ }
@@ -0,0 +1,19 @@
1
+ import type { FarmAuthLookupOptions, FarmAuthSession, FarmAuthUser } from "./types.js";
2
+ /**
3
+ * Farm Auth server helpers. Use `required: true` when anonymous access should
4
+ * immediately return a 401 response.
5
+ */
6
+ declare function session(options: FarmAuthLookupOptions & {
7
+ required: true;
8
+ }): Promise<FarmAuthSession>;
9
+ declare function session(options?: FarmAuthLookupOptions): Promise<FarmAuthSession | null>;
10
+ declare function user(options: FarmAuthLookupOptions & {
11
+ required: true;
12
+ }): Promise<FarmAuthUser>;
13
+ declare function user(options?: FarmAuthLookupOptions): Promise<FarmAuthUser | null>;
14
+ export declare const auth: {
15
+ session: typeof session;
16
+ user: typeof user;
17
+ };
18
+ export type { FarmAuthLookupOptions, FarmAuthSession, FarmAuthSessionData, FarmAuthUser, } from "./types.js";
19
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAsBvF;;;GAGG;AACH,iBAAS,OAAO,CAAC,OAAO,EAAE,qBAAqB,GAAG;IAAE,QAAQ,EAAE,IAAI,CAAA;CAAE,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;AAChG,iBAAS,OAAO,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;AAKnF,iBAAS,IAAI,CAAC,OAAO,EAAE,qBAAqB,GAAG;IAAE,QAAQ,EAAE,IAAI,CAAA;CAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;AAC1F,iBAAS,IAAI,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;AAK7E,eAAO,MAAM,IAAI;;;CAAoB,CAAC;AAEtC,YAAY,EACV,qBAAqB,EACrB,eAAe,EACf,mBAAmB,EACnB,YAAY,GACb,MAAM,YAAY,CAAC"}
package/dist/server.js ADDED
@@ -0,0 +1,22 @@
1
+ import { getFarmAuthRequest, getFarmAuthRuntime } from "./runtime.js";
2
+ async function readSession(options = {}) {
3
+ const request = getFarmAuthRequest(options.request);
4
+ const runtime = await getFarmAuthRuntime();
5
+ const session = (await runtime.api.getSession({
6
+ headers: request.headers,
7
+ }));
8
+ if (!session && options.required) {
9
+ throw Response.json({
10
+ error: "Authentication required",
11
+ code: "FARM_AUTH_REQUIRED",
12
+ }, { status: 401 });
13
+ }
14
+ return session;
15
+ }
16
+ function session(options) {
17
+ return readSession(options);
18
+ }
19
+ async function user(options) {
20
+ return (await readSession(options))?.user ?? null;
21
+ }
22
+ export const auth = { session, user };
@@ -0,0 +1,105 @@
1
+ export interface FarmAuthEmailAndPasswordConfig {
2
+ /** Require a verified email before creating a session. @default false */
3
+ requireEmailVerification?: boolean;
4
+ /** Smallest accepted password length. @default 8 */
5
+ minPasswordLength?: number;
6
+ /** Largest accepted password length. @default 128 */
7
+ maxPasswordLength?: number;
8
+ }
9
+ export interface FarmAuthSessionConfig {
10
+ /** Session lifetime in seconds. @default 604800 */
11
+ expiresIn?: number;
12
+ /** Session refresh interval in seconds. @default 86400 */
13
+ updateAge?: number;
14
+ }
15
+ export interface FarmAuthDatabaseConfig {
16
+ /**
17
+ * Postgres connection string. Defaults to DATABASE_URL.
18
+ * Local development falls back to SQLite when no URL is present.
19
+ */
20
+ url?: string;
21
+ /** Local SQLite path. @default ".farm/auth.sqlite" */
22
+ path?: string;
23
+ /** Automatically update the schema in development. @default true */
24
+ migrateInDevelopment?: boolean;
25
+ }
26
+ export interface FarmAuthConfig {
27
+ /** Set false to disable auth without removing its configuration. @default true */
28
+ enabled?: boolean;
29
+ /** Display name used by authentication emails and metadata. */
30
+ appName?: string;
31
+ /** Route prefix for the auth endpoints. @default "/api/auth" */
32
+ basePath?: string;
33
+ /**
34
+ * Email/password authentication. It is enabled by default; set false to
35
+ * disable it when adding another sign-in method.
36
+ */
37
+ emailAndPassword?: boolean | FarmAuthEmailAndPasswordConfig;
38
+ session?: FarmAuthSessionConfig;
39
+ database?: FarmAuthDatabaseConfig;
40
+ }
41
+ export type FarmAuthUserConfig = boolean | FarmAuthConfig;
42
+ export interface ResolvedFarmAuthConfig {
43
+ enabled: boolean;
44
+ appName?: string;
45
+ basePath: string;
46
+ emailAndPassword: {
47
+ enabled: boolean;
48
+ requireEmailVerification: boolean;
49
+ minPasswordLength: number;
50
+ maxPasswordLength: number;
51
+ };
52
+ session: {
53
+ expiresIn: number;
54
+ updateAge: number;
55
+ };
56
+ database: {
57
+ url?: string;
58
+ path: string;
59
+ migrateInDevelopment: boolean;
60
+ };
61
+ }
62
+ export interface FarmAuthUser {
63
+ id: string;
64
+ name: string;
65
+ email: string;
66
+ emailVerified: boolean;
67
+ image?: string | null;
68
+ createdAt: Date;
69
+ updatedAt: Date;
70
+ }
71
+ export interface FarmAuthSessionData {
72
+ id: string;
73
+ userId: string;
74
+ expiresAt: Date;
75
+ token: string;
76
+ createdAt: Date;
77
+ updatedAt: Date;
78
+ ipAddress?: string | null;
79
+ userAgent?: string | null;
80
+ }
81
+ export interface FarmAuthSession {
82
+ session: FarmAuthSessionData;
83
+ user: FarmAuthUser;
84
+ }
85
+ export interface FarmAuthLookupOptions {
86
+ /** Return a 401 Response when no session exists. */
87
+ required?: boolean;
88
+ /** Override the current Farm request, primarily for route handlers and tests. */
89
+ request?: Request;
90
+ }
91
+ export interface FarmAuthCredentials {
92
+ email: string;
93
+ password: string;
94
+ rememberMe?: boolean;
95
+ }
96
+ export interface FarmAuthSignUpInput extends FarmAuthCredentials {
97
+ name: string;
98
+ }
99
+ export interface FarmAuthClientOptions {
100
+ /** Must match auth.basePath when that option is customized. */
101
+ basePath?: string;
102
+ /** Optional absolute origin for non-browser clients. */
103
+ baseURL?: string;
104
+ }
105
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@farm.js/auth",
3
+ "version": "0.1.0-beta.6",
4
+ "description": "Farm-native authentication with email/password, server helpers, and React hooks",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "https://github.com/farming-labs/farm.js",
9
+ "directory": "packages/farm-auth"
10
+ },
11
+ "files": [
12
+ "dist"
13
+ ],
14
+ "type": "module",
15
+ "main": "./dist/index.js",
16
+ "module": "./dist/index.js",
17
+ "types": "./dist/index.d.ts",
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/index.d.ts",
21
+ "import": "./dist/index.js",
22
+ "default": "./dist/index.js"
23
+ },
24
+ "./server": {
25
+ "types": "./dist/server.d.ts",
26
+ "import": "./dist/server.js",
27
+ "default": "./dist/server.js"
28
+ },
29
+ "./client": {
30
+ "types": "./dist/client.d.ts",
31
+ "import": "./dist/client.js",
32
+ "default": "./dist/client.js"
33
+ },
34
+ "./internal": {
35
+ "types": "./dist/internal.d.ts",
36
+ "import": "./dist/internal.js",
37
+ "default": "./dist/internal.js"
38
+ }
39
+ },
40
+ "publishConfig": {
41
+ "access": "public"
42
+ },
43
+ "dependencies": {
44
+ "better-auth": "1.5.5",
45
+ "pg": "8.20.0"
46
+ },
47
+ "devDependencies": {
48
+ "@types/better-sqlite3": "^7.6.13",
49
+ "@types/node": "^20.10.5",
50
+ "@types/react": "^18.2.45",
51
+ "react": "19.2.8",
52
+ "typescript": "^5.3.3",
53
+ "vitest": "^1.1.0"
54
+ },
55
+ "peerDependencies": {
56
+ "react": "^18.2.0 || ^19.0.0"
57
+ },
58
+ "optionalDependencies": {
59
+ "better-sqlite3": "12.8.0"
60
+ },
61
+ "scripts": {
62
+ "build": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\" && tsc",
63
+ "dev": "tsc --watch",
64
+ "type-check": "tsc --noEmit",
65
+ "test": "vitest run"
66
+ }
67
+ }