@ingram-tech/nk-auth 0.2.0 → 0.3.0

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/README.md CHANGED
@@ -73,6 +73,7 @@ per the prime directive. The presets carry the RLS-preserving bits.
73
73
  import { passkey } from "@better-auth/passkey";
74
74
  import { fromAddress, sendEmail } from "@ingram-tech/email";
75
75
  import {
76
+ authBasePath,
76
77
  authEnv,
77
78
  bcryptPassword,
78
79
  makeEmailSenders,
@@ -93,7 +94,8 @@ export const auth = betterAuth({
93
94
  database: new Pool({ connectionString: env.databaseUrl }),
94
95
  secret: env.secret,
95
96
  baseURL: env.baseURL,
96
- advanced: { database: { generateId: uuidGenerateId } }, // UUID-shaped ids
97
+ basePath: authBasePath, // mount at /auth, not the framework default /api/auth
98
+ advanced: { database: { generateId: uuidGenerateId } }, // UUIDv7 ids
97
99
  emailAndPassword: {
98
100
  enabled: true,
99
101
  password: bcryptPassword, // verifies migrated Supabase bcrypt hashes
@@ -114,7 +116,9 @@ export const auth = betterAuth({
114
116
  ```
115
117
 
116
118
  ```ts
117
- // app/api/auth/[...all]/route.ts — a standard Next.js route handler
119
+ // app/auth/[...all]/route.ts — a standard Next.js route handler.
120
+ // Lives at /auth (set via `basePath: authBasePath`), NOT /api/auth: auth is a
121
+ // user-facing surface (sign-in, OAuth callbacks), not an internal machine API.
118
122
  import { auth } from "@/lib/auth";
119
123
  export const { GET, POST } = auth.handler;
120
124
  ```
@@ -153,6 +157,7 @@ preserved here too):
153
157
  ```tsx
154
158
  "use client";
155
159
  import {
160
+ authBasePath,
156
161
  createAuthClient,
157
162
  jwtClient,
158
163
  passkeyClient,
@@ -160,6 +165,7 @@ import {
160
165
 
161
166
  export const authClient = createAuthClient({
162
167
  baseURL: process.env.NEXT_PUBLIC_SITE_URL ?? "",
168
+ basePath: authBasePath, // matches the server: /auth
163
169
  plugins: [jwtClient(), passkeyClient()],
164
170
  });
165
171
  // authClient.signIn.email(...), signIn.social(...), useSession(), passkey.*
@@ -169,7 +175,7 @@ export const authClient = createAuthClient({
169
175
 
170
176
  `auth.uid()` reads the `sub` claim of the JWT PostgREST receives. The `jwt`
171
177
  plugin (configured here) mints an asymmetric token with `sub` = the user's UUID
172
- and `role: "authenticated"`, exposed at `/api/auth/jwks`. Register that JWKS URL
178
+ and `role: "authenticated"`, exposed at `/auth/jwks`. Register that JWKS URL
173
179
  as a Supabase **third-party auth** issuer, and every existing policy works
174
180
  unchanged. Full rationale and the HS256 fallback:
175
181
  [`docs/better-auth-migration.md`](../../docs/better-auth-migration.md).
package/dist/client.d.ts CHANGED
@@ -20,4 +20,5 @@
20
20
  export { passkeyClient } from "@better-auth/passkey/client";
21
21
  export { jwtClient } from "better-auth/client/plugins";
22
22
  export { createAuthClient } from "better-auth/react";
23
+ export { authBasePath } from "./paths";
23
24
  //# sourceMappingURL=client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC"}
package/dist/client.js CHANGED
@@ -20,4 +20,6 @@
20
20
  export { passkeyClient } from "@better-auth/passkey/client";
21
21
  export { jwtClient } from "better-auth/client/plugins";
22
22
  export { createAuthClient } from "better-auth/react";
23
+ // Re-exported here too so the client can set `basePath` without a server import.
24
+ export { authBasePath } from "./paths";
23
25
  //# sourceMappingURL=client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,iFAAiF;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC"}
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ export { type BackendJwtConfig, backendJwtOptions, rlsJwtOptions, verifyBackendJ
2
2
  export { type AuthEnv, authEnv, isConfigured } from "./keys";
3
3
  export { bcryptPassword, makeEmailSenders, makePasskeyOptions, type PasskeyConfig, type SendEmail, uuidGenerateId, } from "./options";
4
4
  export { lastActiveOrganizationHooks, lastActiveOrganizationUserField, nkOrganizationDefaults, } from "./organization";
5
+ export { authBasePath } from "./paths";
5
6
  export { createAuthPool } from "./pool";
6
7
  export { createServerSupabase, type ServerSupabaseConfig, } from "./supabase";
7
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EACN,KAAK,gBAAgB,EACrB,iBAAiB,EACjB,aAAa,EACb,gBAAgB,GAChB,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,KAAK,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAC7D,OAAO,EACN,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,cAAc,GACd,MAAM,WAAW,CAAC;AACnB,OAAO,EACN,2BAA2B,EAC3B,+BAA+B,EAC/B,sBAAsB,GACtB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,EACN,oBAAoB,EACpB,KAAK,oBAAoB,GACzB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,EACN,KAAK,gBAAgB,EACrB,iBAAiB,EACjB,aAAa,EACb,gBAAgB,GAChB,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,KAAK,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAC7D,OAAO,EACN,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,cAAc,GACd,MAAM,WAAW,CAAC;AACnB,OAAO,EACN,2BAA2B,EAC3B,+BAA+B,EAC/B,sBAAsB,GACtB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,EACN,oBAAoB,EACpB,KAAK,oBAAoB,GACzB,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -6,6 +6,7 @@ export { backendJwtOptions, rlsJwtOptions, verifyBackendJwt, } from "./jwt";
6
6
  export { authEnv, isConfigured } from "./keys";
7
7
  export { bcryptPassword, makeEmailSenders, makePasskeyOptions, uuidGenerateId, } from "./options";
8
8
  export { lastActiveOrganizationHooks, lastActiveOrganizationUserField, nkOrganizationDefaults, } from "./organization";
9
+ export { authBasePath } from "./paths";
9
10
  export { createAuthPool } from "./pool";
10
11
  export { createServerSupabase, } from "./supabase";
11
12
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,+EAA+E;AAC/E,4EAA4E;AAC5E,wEAAwE;AAExE,OAAO,EAEN,iBAAiB,EACjB,aAAa,EACb,gBAAgB,GAChB,MAAM,OAAO,CAAC;AACf,OAAO,EAAgB,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAC7D,OAAO,EACN,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAGlB,cAAc,GACd,MAAM,WAAW,CAAC;AACnB,OAAO,EACN,2BAA2B,EAC3B,+BAA+B,EAC/B,sBAAsB,GACtB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,EACN,oBAAoB,GAEpB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,+EAA+E;AAC/E,4EAA4E;AAC5E,wEAAwE;AAExE,OAAO,EAEN,iBAAiB,EACjB,aAAa,EACb,gBAAgB,GAChB,MAAM,OAAO,CAAC;AACf,OAAO,EAAgB,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAC7D,OAAO,EACN,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAGlB,cAAc,GACd,MAAM,WAAW,CAAC;AACnB,OAAO,EACN,2BAA2B,EAC3B,+BAA+B,EAC/B,sBAAsB,GACtB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,EACN,oBAAoB,GAEpB,MAAM,YAAY,CAAC"}
package/dist/options.d.ts CHANGED
@@ -8,8 +8,9 @@ import type { PasskeyOptions } from "@better-auth/passkey";
8
8
  * site stays plain Better Auth, we just ship the shared config. JWT + org
9
9
  * presets live in `./jwt` and `./organization`. See docs/better-auth-migration.md.
10
10
  *
11
- * `uuidGenerateId` keeps new-user ids UUID-shaped (needed for Supabase
12
- * `auth.uid()::uuid` on RLS sites).
11
+ * `uuidGenerateId` keeps new-user ids UUID-shaped (so Supabase `auth.uid()::uuid`
12
+ * keeps working on RLS sites) — and specifically **UUIDv7**: time-ordered, so ids
13
+ * cluster by creation time for index locality instead of scattering like v4.
13
14
  */
14
15
  /**
15
16
  * `emailAndPassword.password` config. Verifies with bcrypt so passwords
@@ -22,7 +23,12 @@ export declare const bcryptPassword: {
22
23
  password: string;
23
24
  }) => Promise<boolean>;
24
25
  };
25
- /** `advanced.database.generateId` — keeps new-user ids UUID-shaped. */
26
+ /**
27
+ * `advanced.database.generateId` — mints a **UUIDv7** (RFC 9562): a 48-bit
28
+ * Unix-ms timestamp prefix + random tail, version `7`, variant `10`. Keeps ids
29
+ * UUID-shaped (Supabase `auth.uid()::uuid`) while staying time-ordered.
30
+ * Node/Bun's `randomUUID` is v4-only, so we lay the bytes out by hand.
31
+ */
26
32
  export declare const uuidGenerateId: () => string;
27
33
  export interface PasskeyConfig {
28
34
  /** Relying-party id: the registrable domain, e.g. "example.com". */
@@ -1 +1 @@
1
- {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG3D;;;;;;;;;;;GAWG;AAEH;;;GAGG;AACH,eAAO,MAAM,cAAc;qBACT,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;kCAItC;QACF,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;KACjB,KAAG,OAAO,CAAC,OAAO,CAAC;CACpB,CAAC;AAEF,uEAAuE;AACvE,eAAO,MAAM,cAAc,QAAO,MAAsB,CAAC;AAEzD,MAAM,WAAW,aAAa;IAC7B,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC1B;AAED,iFAAiF;AACjF,eAAO,MAAM,kBAAkB,GAAI,KAAK,aAAa,KAAG,cAItD,CAAC;AAEH,iFAAiF;AACjF,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,EAAE;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;CACZ,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAEvB;;;GAGG;AACH,eAAO,MAAM,gBAAgB,GAAI,MAAM,SAAS;wCAI5C;QACF,IAAI,EAAE;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;QACxB,GAAG,EAAE,MAAM,CAAC;KACZ,KAAG,OAAO,CAAC,IAAI,CAAC;4CAMd;QACF,IAAI,EAAE;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;QACxB,GAAG,EAAE,MAAM,CAAC;KACZ,KAAG,OAAO,CAAC,IAAI,CAAC;CAGhB,CAAC"}
1
+ {"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG3D;;;;;;;;;;;;GAYG;AAEH;;;GAGG;AACH,eAAO,MAAM,cAAc;qBACT,MAAM,KAAG,OAAO,CAAC,MAAM,CAAC;kCAItC;QACF,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;KACjB,KAAG,OAAO,CAAC,OAAO,CAAC;CACpB,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,cAAc,QAAO,MAajC,CAAC;AAEF,MAAM,WAAW,aAAa;IAC7B,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC1B;AAED,iFAAiF;AACjF,eAAO,MAAM,kBAAkB,GAAI,KAAK,aAAa,KAAG,cAItD,CAAC;AAEH,iFAAiF;AACjF,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,EAAE;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;CACZ,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAEvB;;;GAGG;AACH,eAAO,MAAM,gBAAgB,GAAI,MAAM,SAAS;wCAI5C;QACF,IAAI,EAAE;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;QACxB,GAAG,EAAE,MAAM,CAAC;KACZ,KAAG,OAAO,CAAC,IAAI,CAAC;4CAMd;QACF,IAAI,EAAE;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;QACxB,GAAG,EAAE,MAAM,CAAC;KACZ,KAAG,OAAO,CAAC,IAAI,CAAC;CAGhB,CAAC"}
package/dist/options.js CHANGED
@@ -1,4 +1,4 @@
1
- import { randomUUID } from "node:crypto";
1
+ import { randomBytes } from "node:crypto";
2
2
  import bcrypt from "bcrypt";
3
3
  /**
4
4
  * Portable Better Auth building blocks for Ingram sites.
@@ -9,8 +9,9 @@ import bcrypt from "bcrypt";
9
9
  * site stays plain Better Auth, we just ship the shared config. JWT + org
10
10
  * presets live in `./jwt` and `./organization`. See docs/better-auth-migration.md.
11
11
  *
12
- * `uuidGenerateId` keeps new-user ids UUID-shaped (needed for Supabase
13
- * `auth.uid()::uuid` on RLS sites).
12
+ * `uuidGenerateId` keeps new-user ids UUID-shaped (so Supabase `auth.uid()::uuid`
13
+ * keeps working on RLS sites) — and specifically **UUIDv7**: time-ordered, so ids
14
+ * cluster by creation time for index locality instead of scattering like v4.
14
15
  */
15
16
  /**
16
17
  * `emailAndPassword.password` config. Verifies with bcrypt so passwords
@@ -20,8 +21,26 @@ export const bcryptPassword = {
20
21
  hash: (password) => bcrypt.hash(password, 10),
21
22
  verify: ({ hash, password, }) => bcrypt.compare(password, hash),
22
23
  };
23
- /** `advanced.database.generateId` — keeps new-user ids UUID-shaped. */
24
- export const uuidGenerateId = () => randomUUID();
24
+ /**
25
+ * `advanced.database.generateId` mints a **UUIDv7** (RFC 9562): a 48-bit
26
+ * Unix-ms timestamp prefix + random tail, version `7`, variant `10`. Keeps ids
27
+ * UUID-shaped (Supabase `auth.uid()::uuid`) while staying time-ordered.
28
+ * Node/Bun's `randomUUID` is v4-only, so we lay the bytes out by hand.
29
+ */
30
+ export const uuidGenerateId = () => {
31
+ const bytes = randomBytes(16);
32
+ const ts = Date.now();
33
+ bytes[0] = Math.floor(ts / 2 ** 40) & 0xff;
34
+ bytes[1] = Math.floor(ts / 2 ** 32) & 0xff;
35
+ bytes[2] = Math.floor(ts / 2 ** 24) & 0xff;
36
+ bytes[3] = Math.floor(ts / 2 ** 16) & 0xff;
37
+ bytes[4] = Math.floor(ts / 2 ** 8) & 0xff;
38
+ bytes[5] = ts & 0xff;
39
+ bytes[6] = ((bytes[6] ?? 0) & 0x0f) | 0x70; // version 7
40
+ bytes[8] = ((bytes[8] ?? 0) & 0x3f) | 0x80; // variant 10
41
+ const hex = bytes.toString("hex");
42
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
43
+ };
25
44
  /** Build `passkey` plugin options. Use as `passkey(makePasskeyOptions(cfg))`. */
26
45
  export const makePasskeyOptions = (cfg) => ({
27
46
  rpID: cfg.rpId,
@@ -1 +1 @@
1
- {"version":3,"file":"options.js","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B;;;;;;;;;;;GAWG;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC7B,IAAI,EAAE,CAAC,QAAgB,EAAmB,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC;IACtE,MAAM,EAAE,CAAC,EACR,IAAI,EACJ,QAAQ,GAIR,EAAoB,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC;CACtD,CAAC;AAEF,uEAAuE;AACvE,MAAM,CAAC,MAAM,cAAc,GAAG,GAAW,EAAE,CAAC,UAAU,EAAE,CAAC;AAWzD,iFAAiF;AACjF,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,GAAkB,EAAkB,EAAE,CAAC,CAAC;IAC1E,IAAI,EAAE,GAAG,CAAC,IAAI;IACd,MAAM,EAAE,GAAG,CAAC,MAAM;IAClB,MAAM,EAAE,GAAG,CAAC,MAAM;CAClB,CAAC,CAAC;AASH;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,IAAe,EAAE,EAAE,CAAC,CAAC;IACrD,iBAAiB,EAAE,KAAK,EAAE,EACzB,IAAI,EACJ,GAAG,GAIH,EAAiB,EAAE;QACnB,MAAM,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,qBAAqB,EAAE,GAAG,EAAE,CAAC,CAAC;IACrE,CAAC;IACD,qBAAqB,EAAE,KAAK,EAAE,EAC7B,IAAI,EACJ,GAAG,GAIH,EAAiB,EAAE;QACnB,MAAM,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,mBAAmB,EAAE,GAAG,EAAE,CAAC,CAAC;IACnE,CAAC;CACD,CAAC,CAAC"}
1
+ {"version":3,"file":"options.js","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Where Better Auth mounts in an Ingram site: **`/auth`**, not the framework
3
+ * default `/api/auth`. Auth is a first-class user-facing surface — sign-in,
4
+ * OAuth callbacks, the JWKS — not an internal machine API, so it lives at the
5
+ * site root alongside the other pages.
6
+ *
7
+ * Use it on both ends so server and client agree:
8
+ *
9
+ * betterAuth({ basePath: authBasePath, ... })
10
+ * createAuthClient({ baseURL, basePath: authBasePath, ... })
11
+ *
12
+ * and mount the catch-all at `app/auth/[...all]/route.ts`. OAuth redirect URIs
13
+ * then become `<site>/auth/callback/<provider>` and the JWKS `<site>/auth/jwks`.
14
+ */
15
+ export declare const authBasePath = "/auth";
16
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,YAAY,UAAU,CAAC"}
package/dist/paths.js ADDED
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Where Better Auth mounts in an Ingram site: **`/auth`**, not the framework
3
+ * default `/api/auth`. Auth is a first-class user-facing surface — sign-in,
4
+ * OAuth callbacks, the JWKS — not an internal machine API, so it lives at the
5
+ * site root alongside the other pages.
6
+ *
7
+ * Use it on both ends so server and client agree:
8
+ *
9
+ * betterAuth({ basePath: authBasePath, ... })
10
+ * createAuthClient({ baseURL, basePath: authBasePath, ... })
11
+ *
12
+ * and mount the catch-all at `app/auth/[...all]/route.ts`. OAuth redirect URIs
13
+ * then become `<site>/auth/callback/<provider>` and the JWKS `<site>/auth/jwks`.
14
+ */
15
+ export const authBasePath = "/auth";
16
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,OAAO,CAAC"}
package/dist/pool.d.ts CHANGED
@@ -1,9 +1,16 @@
1
1
  import { Pool } from "pg";
2
2
  /**
3
- * A `pg` Pool for Better Auth's direct database connection, with optional
4
- * SSL CA verification (equivalent to `sslmode=verify-full`). Keep `sslmode` out
5
- * of the connection string — `pg` discards the `ssl` object when the URL
6
- * carries SSL settings.
3
+ * A `pg` Pool for Better Auth's direct database connection, with the right TLS
4
+ * for each kind of host:
5
+ *
6
+ * - `caCert` set → verify the server cert + hostname against it
7
+ * (equivalent to `sslmode=verify-full`).
8
+ * - local (`127.0.0.1`/`localhost`) → no TLS.
9
+ * - otherwise (managed Postgres like Supabase) → TLS **without** chain
10
+ * verification. Supabase's cert chain isn't in Node's trust store, so plain
11
+ * verification fails with "self-signed certificate in certificate chain";
12
+ * the connection is still encrypted. `sslmode` is stripped from the URL
13
+ * because `pg` ignores the `ssl` object when the URL carries SSL settings.
7
14
  */
8
15
  export declare const createAuthPool: (config: {
9
16
  connectionString: string;
@@ -1 +1 @@
1
- {"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAE1B;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAAI,QAAQ;IACtC,gBAAgB,EAAE,MAAM,CAAC;IACzB,sEAAsE;IACtE,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB,KAAG,IAMD,CAAC"}
1
+ {"version":3,"file":"pool.d.ts","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAK1B;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,cAAc,GAAI,QAAQ;IACtC,gBAAgB,EAAE,MAAM,CAAC;IACzB,sEAAsE;IACtE,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB,KAAG,IAgBH,CAAC"}
package/dist/pool.js CHANGED
@@ -1,14 +1,33 @@
1
1
  import { Pool } from "pg";
2
+ const isLocal = (connectionString) => connectionString.includes("127.0.0.1") || connectionString.includes("localhost");
2
3
  /**
3
- * A `pg` Pool for Better Auth's direct database connection, with optional
4
- * SSL CA verification (equivalent to `sslmode=verify-full`). Keep `sslmode` out
5
- * of the connection string — `pg` discards the `ssl` object when the URL
6
- * carries SSL settings.
4
+ * A `pg` Pool for Better Auth's direct database connection, with the right TLS
5
+ * for each kind of host:
6
+ *
7
+ * - `caCert` set → verify the server cert + hostname against it
8
+ * (equivalent to `sslmode=verify-full`).
9
+ * - local (`127.0.0.1`/`localhost`) → no TLS.
10
+ * - otherwise (managed Postgres like Supabase) → TLS **without** chain
11
+ * verification. Supabase's cert chain isn't in Node's trust store, so plain
12
+ * verification fails with "self-signed certificate in certificate chain";
13
+ * the connection is still encrypted. `sslmode` is stripped from the URL
14
+ * because `pg` ignores the `ssl` object when the URL carries SSL settings.
7
15
  */
8
- export const createAuthPool = (config) => new Pool({
9
- connectionString: config.connectionString,
10
- ssl: config.caCert
11
- ? { ca: config.caCert, rejectUnauthorized: true }
12
- : undefined,
13
- });
16
+ export const createAuthPool = (config) => {
17
+ if (config.caCert) {
18
+ return new Pool({
19
+ connectionString: config.connectionString,
20
+ ssl: { ca: config.caCert, rejectUnauthorized: true },
21
+ });
22
+ }
23
+ if (isLocal(config.connectionString)) {
24
+ return new Pool({ connectionString: config.connectionString });
25
+ }
26
+ const url = new URL(config.connectionString);
27
+ url.searchParams.delete("sslmode");
28
+ return new Pool({
29
+ connectionString: url.toString(),
30
+ ssl: { rejectUnauthorized: false },
31
+ });
32
+ };
14
33
  //# sourceMappingURL=pool.js.map
package/dist/pool.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"pool.js","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAE1B;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,MAI9B,EAAQ,EAAE,CACV,IAAI,IAAI,CAAC;IACR,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;IACzC,GAAG,EAAE,MAAM,CAAC,MAAM;QACjB,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,EAAE,IAAI,EAAE;QACjD,CAAC,CAAC,SAAS;CACZ,CAAC,CAAC"}
1
+ {"version":3,"file":"pool.js","sourceRoot":"","sources":["../src/pool.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAE1B,MAAM,OAAO,GAAG,CAAC,gBAAwB,EAAW,EAAE,CACrD,gBAAgB,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,gBAAgB,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AAElF;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,MAI9B,EAAQ,EAAE;IACV,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QACnB,OAAO,IAAI,IAAI,CAAC;YACf,gBAAgB,EAAE,MAAM,CAAC,gBAAgB;YACzC,GAAG,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,EAAE,IAAI,EAAE;SACpD,CAAC,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACtC,OAAO,IAAI,IAAI,CAAC,EAAE,gBAAgB,EAAE,MAAM,CAAC,gBAAgB,EAAE,CAAC,CAAC;IAChE,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;IAC7C,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACnC,OAAO,IAAI,IAAI,CAAC;QACf,gBAAgB,EAAE,GAAG,CAAC,QAAQ,EAAE;QAChC,GAAG,EAAE,EAAE,kBAAkB,EAAE,KAAK,EAAE;KAClC,CAAC,CAAC;AACJ,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ingram-tech/nk-auth",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "The Ingram Better Auth foundation: composable presets (org, dual-shape JWT, Supabase RLS bridge, active-org hooks, pg pool) for Next.js sites.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -33,6 +33,10 @@
33
33
  "types": "./dist/pool.d.ts",
34
34
  "import": "./dist/pool.js"
35
35
  },
36
+ "./paths": {
37
+ "types": "./dist/paths.d.ts",
38
+ "import": "./dist/paths.js"
39
+ },
36
40
  "./client": {
37
41
  "types": "./dist/client.d.ts",
38
42
  "import": "./dist/client.js"
@@ -72,7 +76,7 @@
72
76
  },
73
77
  "devDependencies": {
74
78
  "@better-auth/passkey": "^1.6.0",
75
- "@ingram-tech/typescript-config": "0.1.0",
79
+ "@ingram-tech/typescript-config": "workspace:*",
76
80
  "@supabase/supabase-js": "^2.45.0",
77
81
  "@types/bcrypt": "^5.0.2",
78
82
  "@types/node": "^20.0.0",