@amerged/ohmyhost-auth 0.1.10
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 +202 -0
- package/NOTICE +4 -0
- package/README.md +11 -0
- package/THIRD_PARTY_NOTICES.md +3 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/installation-contract.d.ts +18 -0
- package/dist/installation-contract.d.ts.map +1 -0
- package/dist/installation-contract.js +17 -0
- package/dist/installation-contract.js.map +1 -0
- package/dist/mail-gateway.d.ts +13 -0
- package/dist/mail-gateway.d.ts.map +1 -0
- package/dist/mail-gateway.js +125 -0
- package/dist/mail-gateway.js.map +1 -0
- package/dist/next.d.ts +9 -0
- package/dist/next.d.ts.map +1 -0
- package/dist/next.js +5 -0
- package/dist/next.js.map +1 -0
- package/dist/runtime.d.ts +26 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +151 -0
- package/dist/runtime.js.map +1 -0
- package/dist/schema.d.ts +2 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +26 -0
- package/dist/schema.js.map +1 -0
- package/dist/tanstack.d.ts +2 -0
- package/dist/tanstack.d.ts.map +1 -0
- package/dist/tanstack.js +2 -0
- package/dist/tanstack.js.map +1 -0
- package/dist/vite-companion.d.ts +5 -0
- package/dist/vite-companion.d.ts.map +1 -0
- package/dist/vite-companion.js +5 -0
- package/dist/vite-companion.js.map +1 -0
- package/dist/web-handler.d.ts +3 -0
- package/dist/web-handler.d.ts.map +1 -0
- package/dist/web-handler.js +19 -0
- package/dist/web-handler.js.map +1 -0
- package/package.json +49 -0
- package/src/packages/customer-auth-better-auth/index.ts +5 -0
- package/src/packages/customer-auth-better-auth/installation-contract.ts +17 -0
- package/src/packages/customer-auth-better-auth/mail-gateway.ts +149 -0
- package/src/packages/customer-auth-better-auth/next.ts +7 -0
- package/src/packages/customer-auth-better-auth/runtime.ts +193 -0
- package/src/packages/customer-auth-better-auth/schema.ts +29 -0
- package/src/packages/customer-auth-better-auth/tanstack.ts +1 -0
- package/src/packages/customer-auth-better-auth/vite-companion.ts +6 -0
- package/src/packages/customer-auth-better-auth/web-handler.ts +18 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"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"}
|
package/dist/schema.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAIA,wBAAgB,2BAA2B,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CAwB3E"}
|
package/dist/schema.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { CUSTOMER_AUTH_INSTALLATION_CONTRACT } from "./installation-contract.js";
|
|
2
|
+
const EXPECTED_TABLES = CUSTOMER_AUTH_INSTALLATION_CONTRACT.database.tables;
|
|
3
|
+
export function renderCustomerAuthMigration(generatedSchema) {
|
|
4
|
+
if (typeof generatedSchema !== "string" ||
|
|
5
|
+
generatedSchema.length < 1 ||
|
|
6
|
+
generatedSchema.length > 256 * 1024 ||
|
|
7
|
+
generatedSchema.includes("\r") ||
|
|
8
|
+
/^(?:drop|alter|truncate|delete|update|insert)\b/imu.test(generatedSchema)) {
|
|
9
|
+
throw new TypeError("Generated Better Auth schema is invalid");
|
|
10
|
+
}
|
|
11
|
+
const tables = [...generatedSchema.matchAll(/^create table "([^"]+)"/gmu)]
|
|
12
|
+
.map((match) => match[1])
|
|
13
|
+
.sort();
|
|
14
|
+
if (JSON.stringify(tables) !== JSON.stringify(EXPECTED_TABLES)) {
|
|
15
|
+
throw new TypeError("Generated Better Auth schema is invalid");
|
|
16
|
+
}
|
|
17
|
+
const qualified = generatedSchema
|
|
18
|
+
.replace(/^create table "([^"]+)"/gmu, 'create table auth."$1"')
|
|
19
|
+
.replace(/ references "([^"]+)"/gu, ' references auth."$1"')
|
|
20
|
+
.replace(/^(create (?:unique )?index "[^"]+" on) "([^"]+)"/gmu, '$1 auth."$2"');
|
|
21
|
+
if (/^create table "| references "| on "/mu.test(qualified)) {
|
|
22
|
+
throw new TypeError("Generated Better Auth schema is invalid");
|
|
23
|
+
}
|
|
24
|
+
return `create schema if not exists auth;\n\n${qualified.trimEnd()}\n`;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mCAAmC,EAAE,MAAM,4BAA4B,CAAC;AAEjF,MAAM,eAAe,GAAG,mCAAmC,CAAC,QAAQ,CAAC,MAAM,CAAC;AAE5E,MAAM,UAAU,2BAA2B,CAAC,eAAuB;IACjE,IACE,OAAO,eAAe,KAAK,QAAQ;QACnC,eAAe,CAAC,MAAM,GAAG,CAAC;QAC1B,eAAe,CAAC,MAAM,GAAG,GAAG,GAAG,IAAI;QACnC,eAAe,CAAC,QAAQ,CAAC,IAAI,CAAC;QAC9B,oDAAoD,CAAC,IAAI,CAAC,eAAe,CAAC,EAC1E,CAAC;QACD,MAAM,IAAI,SAAS,CAAC,yCAAyC,CAAC,CAAC;IACjE,CAAC;IACD,MAAM,MAAM,GAAG,CAAC,GAAG,eAAe,CAAC,QAAQ,CAAC,4BAA4B,CAAC,CAAC;SACvE,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SACxB,IAAI,EAAE,CAAC;IACV,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,EAAE,CAAC;QAC/D,MAAM,IAAI,SAAS,CAAC,yCAAyC,CAAC,CAAC;IACjE,CAAC;IACD,MAAM,SAAS,GAAG,eAAe;SAC9B,OAAO,CAAC,4BAA4B,EAAE,wBAAwB,CAAC;SAC/D,OAAO,CAAC,yBAAyB,EAAE,uBAAuB,CAAC;SAC3D,OAAO,CAAC,qDAAqD,EAAE,cAAc,CAAC,CAAC;IAClF,IAAI,uCAAuC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QAC5D,MAAM,IAAI,SAAS,CAAC,yCAAyC,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,wCAAwC,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC;AACzE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tanstack.d.ts","sourceRoot":"","sources":["../src/tanstack.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,8BAA8B,IAAI,iCAAiC,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/tanstack.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tanstack.js","sourceRoot":"","sources":["../src/tanstack.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,8BAA8B,IAAI,iCAAiC,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vite-companion.d.ts","sourceRoot":"","sources":["../src/vite-companion.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAGjD,wBAAgB,+BAA+B,CAAC,IAAI,EAAE,YAAY;;GAEjE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vite-companion.js","sourceRoot":"","sources":["../src/vite-companion.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,8BAA8B,EAAE,MAAM,kBAAkB,CAAC;AAElE,MAAM,UAAU,+BAA+B,CAAC,IAAkB;IAChE,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,8BAA8B,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACxE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-handler.d.ts","sourceRoot":"","sources":["../src/web-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAGjD,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,YAAY,IAEjD,SAAS,OAAO,KAAG,OAAO,CAAC,QAAQ,CAAC,CAYnD"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { CUSTOMER_AUTH_INSTALLATION_CONTRACT } from "./installation-contract.js";
|
|
2
|
+
export function createCustomerAuthFetchHandler(auth) {
|
|
3
|
+
if (typeof auth?.handler !== "function")
|
|
4
|
+
throw new TypeError("Customer auth handler is invalid");
|
|
5
|
+
return async (request) => {
|
|
6
|
+
if (!(request instanceof Request))
|
|
7
|
+
throw new TypeError("Customer auth request is invalid");
|
|
8
|
+
const pathname = new URL(request.url).pathname;
|
|
9
|
+
const routePath = CUSTOMER_AUTH_INSTALLATION_CONTRACT.http.routePath;
|
|
10
|
+
if (pathname !== routePath && !pathname.startsWith(`${routePath}/`)) {
|
|
11
|
+
return new Response("Not Found", {
|
|
12
|
+
status: 404,
|
|
13
|
+
headers: { "cache-control": "no-store" },
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
return auth.handler(request);
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=web-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-handler.js","sourceRoot":"","sources":["../src/web-handler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mCAAmC,EAAE,MAAM,4BAA4B,CAAC;AAEjF,MAAM,UAAU,8BAA8B,CAAC,IAAkB;IAC/D,IAAI,OAAO,IAAI,EAAE,OAAO,KAAK,UAAU;QAAE,MAAM,IAAI,SAAS,CAAC,kCAAkC,CAAC,CAAC;IACjG,OAAO,KAAK,EAAE,OAAgB,EAAqB,EAAE;QACnD,IAAI,CAAC,CAAC,OAAO,YAAY,OAAO,CAAC;YAAE,MAAM,IAAI,SAAS,CAAC,kCAAkC,CAAC,CAAC;QAC3F,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;QAC/C,MAAM,SAAS,GAAG,mCAAmC,CAAC,IAAI,CAAC,SAAS,CAAC;QACrE,IAAI,QAAQ,KAAK,SAAS,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,SAAS,GAAG,CAAC,EAAE,CAAC;YACpE,OAAO,IAAI,QAAQ,CAAC,WAAW,EAAE;gBAC/B,MAAM,EAAE,GAAG;gBACX,OAAO,EAAE,EAAE,eAAe,EAAE,UAAU,EAAE;aACzC,CAAC,CAAC;QACL,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC,CAAC;AACJ,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@amerged/ohmyhost-auth",
|
|
3
|
+
"version": "0.1.10",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"engines": {
|
|
6
|
+
"node": ">=22"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"src",
|
|
11
|
+
"LICENSE",
|
|
12
|
+
"NOTICE",
|
|
13
|
+
"README.md",
|
|
14
|
+
"THIRD_PARTY_NOTICES.md"
|
|
15
|
+
],
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"import": "./dist/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./next": {
|
|
22
|
+
"types": "./dist/next.d.ts",
|
|
23
|
+
"import": "./dist/next.js"
|
|
24
|
+
},
|
|
25
|
+
"./tanstack": {
|
|
26
|
+
"types": "./dist/tanstack.d.ts",
|
|
27
|
+
"import": "./dist/tanstack.js"
|
|
28
|
+
},
|
|
29
|
+
"./vite-companion": {
|
|
30
|
+
"types": "./dist/vite-companion.d.ts",
|
|
31
|
+
"import": "./dist/vite-companion.js"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@better-fetch/fetch": "1.3.1",
|
|
36
|
+
"@cloudflare/workers-types": "5.20260906.1",
|
|
37
|
+
"@types/pg": "8.15.5",
|
|
38
|
+
"better-auth": "1.7.1",
|
|
39
|
+
"bun-types": "1.4.1",
|
|
40
|
+
"pg": "8.22.0"
|
|
41
|
+
},
|
|
42
|
+
"license": "Apache-2.0",
|
|
43
|
+
"homepage": "https://docs.ohmyho.st/",
|
|
44
|
+
"description": "ohmyho.st auth client",
|
|
45
|
+
"publishConfig": {
|
|
46
|
+
"access": "public",
|
|
47
|
+
"registry": "https://registry.npmjs.org/"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const TABLES = Object.freeze(["account", "rateLimit", "session", "user", "verification"]);
|
|
2
|
+
const SECRETS = Object.freeze(["BETTER_AUTH_SECRET"]);
|
|
3
|
+
|
|
4
|
+
export const CUSTOMER_AUTH_INSTALLATION_CONTRACT = Object.freeze({
|
|
5
|
+
package: Object.freeze({
|
|
6
|
+
name: "better-auth" as const,
|
|
7
|
+
version: "1.7.1" as const,
|
|
8
|
+
}),
|
|
9
|
+
database: Object.freeze({
|
|
10
|
+
schema: "auth" as const,
|
|
11
|
+
idGeneration: "uuid" as const,
|
|
12
|
+
tables: TABLES,
|
|
13
|
+
binding: "OHMYHOST_DATABASE" as const,
|
|
14
|
+
}),
|
|
15
|
+
http: Object.freeze({ routePath: "/api/auth" as const, handlerExport: "fetch" as const }),
|
|
16
|
+
secrets: SECRETS,
|
|
17
|
+
});
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import type { CustomerAuthEmailSender } from "./runtime.js";
|
|
2
|
+
|
|
3
|
+
const ULID_PATTERN = /^[0-7][0-9A-HJKMNP-TV-Z]{25}$/u;
|
|
4
|
+
|
|
5
|
+
export class CustomerAuthEmailDeliveryError extends Error {
|
|
6
|
+
public readonly code = "customer_auth_email_delivery_failed";
|
|
7
|
+
public constructor() {
|
|
8
|
+
super("Customer authentication email delivery failed");
|
|
9
|
+
this.name = "CustomerAuthEmailDeliveryError";
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function createMailGatewayEmailSender(input: {
|
|
14
|
+
readonly projectId: string;
|
|
15
|
+
readonly gatewayOrigin: string;
|
|
16
|
+
readonly key: string;
|
|
17
|
+
readonly fetch: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
|
|
18
|
+
readonly crypto: Crypto;
|
|
19
|
+
}): CustomerAuthEmailSender {
|
|
20
|
+
const projectId = input.projectId;
|
|
21
|
+
if (typeof projectId !== "string" || !ULID_PATTERN.test(projectId))
|
|
22
|
+
throw new TypeError("Invalid canonical ULID");
|
|
23
|
+
const gatewayOrigin = canonicalOrigin(input.gatewayOrigin);
|
|
24
|
+
if (
|
|
25
|
+
!/^[A-Za-z0-9_-]{43}$/u.test(input.key) ||
|
|
26
|
+
typeof input.fetch !== "function" ||
|
|
27
|
+
typeof input.crypto?.subtle?.digest !== "function"
|
|
28
|
+
) {
|
|
29
|
+
throw new TypeError("Mail gateway email sender input is invalid");
|
|
30
|
+
}
|
|
31
|
+
return Object.freeze({
|
|
32
|
+
async send(message: Parameters<CustomerAuthEmailSender["send"]>[0]) {
|
|
33
|
+
validateMessage(message);
|
|
34
|
+
const subject =
|
|
35
|
+
message.kind === "verification"
|
|
36
|
+
? "Verify your account"
|
|
37
|
+
: message.kind === "password-reset"
|
|
38
|
+
? "Reset your password"
|
|
39
|
+
: "Your password was changed";
|
|
40
|
+
const action = message.kind === "password-changed" ? "Review your account" : subject;
|
|
41
|
+
const body = {
|
|
42
|
+
project_id: projectId,
|
|
43
|
+
to: message.to,
|
|
44
|
+
subject,
|
|
45
|
+
text: `${subject}: ${message.url}`,
|
|
46
|
+
html: `<p><a href="${escapeHtml(message.url)}">${action}</a></p>`,
|
|
47
|
+
};
|
|
48
|
+
const idempotencyKey = await sha256Hex(
|
|
49
|
+
input.crypto,
|
|
50
|
+
`${message.kind}\n${message.to}\n${message.url}`,
|
|
51
|
+
);
|
|
52
|
+
let response: Response;
|
|
53
|
+
try {
|
|
54
|
+
response = await input.fetch(`${gatewayOrigin}/v1/send`, {
|
|
55
|
+
method: "POST",
|
|
56
|
+
headers: {
|
|
57
|
+
Authorization: `Bearer ${input.key}`,
|
|
58
|
+
"Content-Type": "application/json",
|
|
59
|
+
"Idempotency-Key": idempotencyKey,
|
|
60
|
+
},
|
|
61
|
+
body: JSON.stringify(body),
|
|
62
|
+
redirect: "manual",
|
|
63
|
+
signal: AbortSignal.timeout(8_000),
|
|
64
|
+
});
|
|
65
|
+
} catch {
|
|
66
|
+
throw new CustomerAuthEmailDeliveryError();
|
|
67
|
+
}
|
|
68
|
+
const value = await readJson(response);
|
|
69
|
+
if (
|
|
70
|
+
response.status !== 202 ||
|
|
71
|
+
!isRecord(value) ||
|
|
72
|
+
value["state"] !== "accepted" ||
|
|
73
|
+
typeof value["request_id"] !== "string" ||
|
|
74
|
+
typeof value["message_id"] !== "string"
|
|
75
|
+
) {
|
|
76
|
+
throw new CustomerAuthEmailDeliveryError();
|
|
77
|
+
}
|
|
78
|
+
if (!ULID_PATTERN.test(value["request_id"])) throw new TypeError("Invalid canonical ULID");
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function validateMessage(message: Parameters<CustomerAuthEmailSender["send"]>[0]): void {
|
|
84
|
+
if (
|
|
85
|
+
(message.kind !== "verification" &&
|
|
86
|
+
message.kind !== "password-reset" &&
|
|
87
|
+
message.kind !== "password-changed") ||
|
|
88
|
+
!/^[a-z0-9](?:[a-z0-9._%+-]{0,62}[a-z0-9])?@(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$/u.test(
|
|
89
|
+
message.to,
|
|
90
|
+
) ||
|
|
91
|
+
!/^https:\/\//u.test(message.url) ||
|
|
92
|
+
message.url.length > 4_096
|
|
93
|
+
) {
|
|
94
|
+
throw new CustomerAuthEmailDeliveryError();
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function canonicalOrigin(value: string): string {
|
|
99
|
+
let url: URL;
|
|
100
|
+
try {
|
|
101
|
+
url = new URL(value);
|
|
102
|
+
} catch {
|
|
103
|
+
throw new TypeError("Mail gateway origin is invalid");
|
|
104
|
+
}
|
|
105
|
+
if (
|
|
106
|
+
url.protocol !== "https:" ||
|
|
107
|
+
url.username !== "" ||
|
|
108
|
+
url.password !== "" ||
|
|
109
|
+
url.pathname !== "/" ||
|
|
110
|
+
url.search !== "" ||
|
|
111
|
+
url.hash !== ""
|
|
112
|
+
) {
|
|
113
|
+
throw new TypeError("Mail gateway origin is invalid");
|
|
114
|
+
}
|
|
115
|
+
return url.origin;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async function sha256Hex(crypto: Crypto, value: string): Promise<string> {
|
|
119
|
+
const bytes = Uint8Array.from(new TextEncoder().encode(value));
|
|
120
|
+
const digest = new Uint8Array(await crypto.subtle.digest("SHA-256", bytes.buffer));
|
|
121
|
+
return Array.from(digest, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async function readJson(response: Response): Promise<unknown> {
|
|
125
|
+
const declared = response.headers.get("content-length");
|
|
126
|
+
if (declared !== null && (!/^[0-9]+$/u.test(declared) || Number(declared) > 4_096)) {
|
|
127
|
+
await response.body?.cancel().catch(() => undefined);
|
|
128
|
+
throw new CustomerAuthEmailDeliveryError();
|
|
129
|
+
}
|
|
130
|
+
const bytes = new Uint8Array(await response.arrayBuffer());
|
|
131
|
+
if (bytes.byteLength > 4_096) throw new CustomerAuthEmailDeliveryError();
|
|
132
|
+
try {
|
|
133
|
+
return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
|
|
134
|
+
} catch {
|
|
135
|
+
throw new CustomerAuthEmailDeliveryError();
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function escapeHtml(value: string): string {
|
|
140
|
+
return value
|
|
141
|
+
.replaceAll("&", "&")
|
|
142
|
+
.replaceAll('"', """)
|
|
143
|
+
.replaceAll("<", "<")
|
|
144
|
+
.replaceAll(">", ">");
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
148
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
149
|
+
}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/// <reference types="bun-types/sqlite.d.ts" preserve="true" />
|
|
2
|
+
import { betterAuth, type BetterAuthOptions } from "better-auth";
|
|
3
|
+
import { Pool } from "pg";
|
|
4
|
+
|
|
5
|
+
import { CUSTOMER_AUTH_INSTALLATION_CONTRACT } from "./installation-contract.js";
|
|
6
|
+
|
|
7
|
+
// Better Fetch 1.3.1 exposes an unbound Timer name; keep its type local to that module.
|
|
8
|
+
// Referencing only Bun's SQLite declarations above avoids changing Node's global APIs.
|
|
9
|
+
declare module "@better-fetch/fetch" {
|
|
10
|
+
type Timer = ReturnType<typeof globalThis.setTimeout>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface CustomerAuthEmail {
|
|
14
|
+
readonly kind: "password-changed" | "password-reset" | "verification";
|
|
15
|
+
readonly to: string;
|
|
16
|
+
readonly url: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface CustomerAuthEmailSender {
|
|
20
|
+
send(message: CustomerAuthEmail): Promise<void>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface CustomerAuthRuntimeInput {
|
|
24
|
+
readonly appName: string;
|
|
25
|
+
readonly publicOrigin: string;
|
|
26
|
+
readonly database: Pool;
|
|
27
|
+
readonly secret: string;
|
|
28
|
+
readonly email: CustomerAuthEmailSender;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function createCustomerAuthOptions(input: CustomerAuthRuntimeInput): BetterAuthOptions {
|
|
32
|
+
const publicOrigin = parsePublicOrigin(input.publicOrigin);
|
|
33
|
+
const authBasePath = CUSTOMER_AUTH_INSTALLATION_CONTRACT.http.routePath;
|
|
34
|
+
if (
|
|
35
|
+
typeof input.appName !== "string" ||
|
|
36
|
+
input.appName.trim() !== input.appName ||
|
|
37
|
+
input.appName.length < 1 ||
|
|
38
|
+
input.appName.length > 80 ||
|
|
39
|
+
typeof input.database?.query !== "function" ||
|
|
40
|
+
typeof input.secret !== "string" ||
|
|
41
|
+
input.secret.length < 32 ||
|
|
42
|
+
input.secret.length > 512 ||
|
|
43
|
+
typeof input.email?.send !== "function"
|
|
44
|
+
) {
|
|
45
|
+
throw new TypeError("Customer auth runtime input is invalid");
|
|
46
|
+
}
|
|
47
|
+
const send = async (kind: CustomerAuthEmail["kind"], email: string, url: string) => {
|
|
48
|
+
await input.email.send({
|
|
49
|
+
kind,
|
|
50
|
+
to: email,
|
|
51
|
+
url:
|
|
52
|
+
kind === "password-changed"
|
|
53
|
+
? sameOriginExactUrl(url, publicOrigin, "/login")
|
|
54
|
+
: sameOriginAuthUrl(url, publicOrigin, authBasePath),
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
const options: BetterAuthOptions = {
|
|
58
|
+
appName: input.appName,
|
|
59
|
+
baseURL: publicOrigin,
|
|
60
|
+
basePath: authBasePath,
|
|
61
|
+
trustedOrigins: [publicOrigin],
|
|
62
|
+
secret: input.secret,
|
|
63
|
+
database: input.database,
|
|
64
|
+
emailAndPassword: {
|
|
65
|
+
enabled: true,
|
|
66
|
+
requireEmailVerification: true,
|
|
67
|
+
autoSignIn: false,
|
|
68
|
+
minPasswordLength: 12,
|
|
69
|
+
maxPasswordLength: 128,
|
|
70
|
+
revokeSessionsOnPasswordReset: true,
|
|
71
|
+
resetPasswordTokenExpiresIn: 3_600,
|
|
72
|
+
sendResetPassword: ({ user, url }) => send("password-reset", user.email, url),
|
|
73
|
+
onPasswordReset: ({ user }) => send("password-changed", user.email, `${publicOrigin}/login`),
|
|
74
|
+
},
|
|
75
|
+
emailVerification: {
|
|
76
|
+
sendOnSignUp: true,
|
|
77
|
+
sendOnSignIn: true,
|
|
78
|
+
autoSignInAfterVerification: false,
|
|
79
|
+
expiresIn: 3_600,
|
|
80
|
+
sendVerificationEmail: ({ user, url }) => send("verification", user.email, url),
|
|
81
|
+
},
|
|
82
|
+
session: { expiresIn: 7 * 24 * 60 * 60, updateAge: 24 * 60 * 60 },
|
|
83
|
+
rateLimit: {
|
|
84
|
+
enabled: true,
|
|
85
|
+
window: 60,
|
|
86
|
+
max: 100,
|
|
87
|
+
storage: "database",
|
|
88
|
+
customRules: {
|
|
89
|
+
"/sign-in/email": { window: 60, max: 5 },
|
|
90
|
+
"/sign-up/email": { window: 60, max: 3 },
|
|
91
|
+
"/request-password-reset": { window: 60, max: 3 },
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
advanced: {
|
|
95
|
+
useSecureCookies: true,
|
|
96
|
+
database: {
|
|
97
|
+
generateId: CUSTOMER_AUTH_INSTALLATION_CONTRACT.database.idGeneration,
|
|
98
|
+
joins: true,
|
|
99
|
+
},
|
|
100
|
+
ipAddress: { ipAddressHeaders: ["cf-connecting-ip"] },
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
return Object.freeze(options);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function createCustomerAuth(input: CustomerAuthRuntimeInput) {
|
|
107
|
+
return betterAuth(createCustomerAuthOptions(input));
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function createCustomerAuthPostgresPool(connectionString: string): Pool {
|
|
111
|
+
validateConnectionString(connectionString);
|
|
112
|
+
return new Pool(poolConfiguration(connectionString));
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function validateConnectionString(connectionString: string): void {
|
|
116
|
+
if (
|
|
117
|
+
typeof connectionString !== "string" ||
|
|
118
|
+
connectionString.length < 1 ||
|
|
119
|
+
connectionString.length > 8_192 ||
|
|
120
|
+
!/^postgres(?:ql)?:\/\//u.test(connectionString)
|
|
121
|
+
) {
|
|
122
|
+
throw new TypeError("Customer auth database URL is invalid");
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function poolConfiguration(connectionString: string) {
|
|
127
|
+
return {
|
|
128
|
+
connectionString,
|
|
129
|
+
options: `-c search_path=${CUSTOMER_AUTH_INSTALLATION_CONTRACT.database.schema}`,
|
|
130
|
+
max: 1,
|
|
131
|
+
connectionTimeoutMillis: 5_000,
|
|
132
|
+
idleTimeoutMillis: 30_000,
|
|
133
|
+
query_timeout: 10_000,
|
|
134
|
+
statement_timeout: 10_000,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export type CustomerAuth = ReturnType<typeof createCustomerAuth>;
|
|
139
|
+
|
|
140
|
+
function parsePublicOrigin(value: string): string {
|
|
141
|
+
let url: URL;
|
|
142
|
+
try {
|
|
143
|
+
url = new URL(value);
|
|
144
|
+
} catch {
|
|
145
|
+
throw new TypeError("Customer auth public origin is invalid");
|
|
146
|
+
}
|
|
147
|
+
if (
|
|
148
|
+
url.protocol !== "https:" ||
|
|
149
|
+
url.origin !== value ||
|
|
150
|
+
url.pathname !== "/" ||
|
|
151
|
+
url.username !== "" ||
|
|
152
|
+
url.password !== "" ||
|
|
153
|
+
url.search !== "" ||
|
|
154
|
+
url.hash !== ""
|
|
155
|
+
) {
|
|
156
|
+
throw new TypeError("Customer auth public origin is invalid");
|
|
157
|
+
}
|
|
158
|
+
return url.origin;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function sameOriginAuthUrl(value: string, publicOrigin: string, authBasePath: string): string {
|
|
162
|
+
let url: URL;
|
|
163
|
+
try {
|
|
164
|
+
url = new URL(value);
|
|
165
|
+
} catch {
|
|
166
|
+
throw new TypeError("Customer auth e-mail URL is invalid");
|
|
167
|
+
}
|
|
168
|
+
if (
|
|
169
|
+
url.origin !== publicOrigin ||
|
|
170
|
+
(url.pathname !== authBasePath && !url.pathname.startsWith(`${authBasePath}/`))
|
|
171
|
+
) {
|
|
172
|
+
throw new TypeError("Customer auth e-mail URL is invalid");
|
|
173
|
+
}
|
|
174
|
+
return url.href;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function sameOriginExactUrl(value: string, publicOrigin: string, pathname: string): string {
|
|
178
|
+
let url: URL;
|
|
179
|
+
try {
|
|
180
|
+
url = new URL(value);
|
|
181
|
+
} catch {
|
|
182
|
+
throw new TypeError("Customer auth e-mail URL is invalid");
|
|
183
|
+
}
|
|
184
|
+
if (
|
|
185
|
+
url.origin !== publicOrigin ||
|
|
186
|
+
url.pathname !== pathname ||
|
|
187
|
+
url.search !== "" ||
|
|
188
|
+
url.hash !== ""
|
|
189
|
+
) {
|
|
190
|
+
throw new TypeError("Customer auth e-mail URL is invalid");
|
|
191
|
+
}
|
|
192
|
+
return url.href;
|
|
193
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { CUSTOMER_AUTH_INSTALLATION_CONTRACT } from "./installation-contract.js";
|
|
2
|
+
|
|
3
|
+
const EXPECTED_TABLES = CUSTOMER_AUTH_INSTALLATION_CONTRACT.database.tables;
|
|
4
|
+
|
|
5
|
+
export function renderCustomerAuthMigration(generatedSchema: string): string {
|
|
6
|
+
if (
|
|
7
|
+
typeof generatedSchema !== "string" ||
|
|
8
|
+
generatedSchema.length < 1 ||
|
|
9
|
+
generatedSchema.length > 256 * 1024 ||
|
|
10
|
+
generatedSchema.includes("\r") ||
|
|
11
|
+
/^(?:drop|alter|truncate|delete|update|insert)\b/imu.test(generatedSchema)
|
|
12
|
+
) {
|
|
13
|
+
throw new TypeError("Generated Better Auth schema is invalid");
|
|
14
|
+
}
|
|
15
|
+
const tables = [...generatedSchema.matchAll(/^create table "([^"]+)"/gmu)]
|
|
16
|
+
.map((match) => match[1])
|
|
17
|
+
.sort();
|
|
18
|
+
if (JSON.stringify(tables) !== JSON.stringify(EXPECTED_TABLES)) {
|
|
19
|
+
throw new TypeError("Generated Better Auth schema is invalid");
|
|
20
|
+
}
|
|
21
|
+
const qualified = generatedSchema
|
|
22
|
+
.replace(/^create table "([^"]+)"/gmu, 'create table auth."$1"')
|
|
23
|
+
.replace(/ references "([^"]+)"/gu, ' references auth."$1"')
|
|
24
|
+
.replace(/^(create (?:unique )?index "[^"]+" on) "([^"]+)"/gmu, '$1 auth."$2"');
|
|
25
|
+
if (/^create table "| references "| on "/mu.test(qualified)) {
|
|
26
|
+
throw new TypeError("Generated Better Auth schema is invalid");
|
|
27
|
+
}
|
|
28
|
+
return `create schema if not exists auth;\n\n${qualified.trimEnd()}\n`;
|
|
29
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { createCustomerAuthFetchHandler as createTanStackCustomerAuthHandler } from "./web-handler.js";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { CustomerAuth } from "./runtime.js";
|
|
2
|
+
import { CUSTOMER_AUTH_INSTALLATION_CONTRACT } from "./installation-contract.js";
|
|
3
|
+
|
|
4
|
+
export function createCustomerAuthFetchHandler(auth: CustomerAuth) {
|
|
5
|
+
if (typeof auth?.handler !== "function") throw new TypeError("Customer auth handler is invalid");
|
|
6
|
+
return async (request: Request): Promise<Response> => {
|
|
7
|
+
if (!(request instanceof Request)) throw new TypeError("Customer auth request is invalid");
|
|
8
|
+
const pathname = new URL(request.url).pathname;
|
|
9
|
+
const routePath = CUSTOMER_AUTH_INSTALLATION_CONTRACT.http.routePath;
|
|
10
|
+
if (pathname !== routePath && !pathname.startsWith(`${routePath}/`)) {
|
|
11
|
+
return new Response("Not Found", {
|
|
12
|
+
status: 404,
|
|
13
|
+
headers: { "cache-control": "no-store" },
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
return auth.handler(request);
|
|
17
|
+
};
|
|
18
|
+
}
|