@batijs/cli 0.0.644 → 0.0.647
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/dist/{asset-package.json-Oy4M8AmU.js → asset-package.json-45oDzgS0.js} +1 -0
- package/dist/{asset-package.json-D6e6vjLM.js → asset-package.json-C4csvBBQ.js} +1 -0
- package/dist/{asset-package.json-DsPzKJwr.js → asset-package.json-CDq-96lS.js} +1 -0
- package/dist/{asset-package.json-BBHKZA3A.js → asset-package.json-C_aGwesI.js} +1 -0
- package/dist/asset-package.json-D0EjbpfM.js +50 -0
- package/dist/{asset-package.json-DUzfK1ah.js → asset-package.json-DRdzE2Je.js} +1 -0
- package/dist/{asset-package.json-c4TM2QxI.js → asset-package.json-IZ_nF8HA.js} +1 -0
- package/dist/boilerplates/@batijs/better-auth/bati.config.mjs +48 -0
- package/dist/boilerplates/@batijs/better-auth/files/$TODO.md.js +26 -0
- package/dist/boilerplates/@batijs/better-auth/files/$package.json.js +23 -0
- package/dist/boilerplates/@batijs/better-auth/files/asset-package.json.mjs +48 -0
- package/dist/boilerplates/@batijs/better-auth/files/database/better-auth/migrate.ts +20 -0
- package/dist/boilerplates/@batijs/better-auth/files/database/drizzle/schema/auth.ts +99 -0
- package/dist/boilerplates/@batijs/better-auth/files/database/migrations/$better-auth.sql.js +54 -0
- package/dist/boilerplates/@batijs/better-auth/files/server/better-auth-handler.ts +67 -0
- package/dist/boilerplates/@batijs/better-auth/files/server/better-auth.ts +89 -0
- package/dist/boilerplates/@batijs/better-auth/types/database/better-auth/migrate.d.mts +1 -0
- package/dist/boilerplates/@batijs/better-auth/types/database/drizzle/schema/auth.d.mts +1253 -0
- package/dist/boilerplates/@batijs/better-auth/types/server/better-auth-handler.d.mts +20 -0
- package/dist/boilerplates/@batijs/better-auth/types/server/better-auth.d.mts +7 -0
- package/dist/boilerplates/@batijs/cloudflare/files/$wrangler.jsonc.js +5 -0
- package/dist/boilerplates/@batijs/elysia/files/$package.json.js +1 -1
- package/dist/boilerplates/@batijs/elysia/files/asset-package.json.mjs +1 -0
- package/dist/boilerplates/@batijs/elysia/files/server/elysia.ts +7 -0
- package/dist/boilerplates/@batijs/express/files/$package.json.js +1 -1
- package/dist/boilerplates/@batijs/express/files/+server.ts +7 -0
- package/dist/boilerplates/@batijs/express/files/asset-package.json.mjs +1 -0
- package/dist/boilerplates/@batijs/fastify/files/$package.json.js +1 -1
- package/dist/boilerplates/@batijs/fastify/files/+server.ts +7 -0
- package/dist/boilerplates/@batijs/fastify/files/asset-package.json.mjs +1 -0
- package/dist/boilerplates/@batijs/hono/files/$package.json.js +1 -1
- package/dist/boilerplates/@batijs/hono/files/asset-package.json.mjs +1 -0
- package/dist/boilerplates/@batijs/hono/files/entry_aws_lambda.ts +2 -4
- package/dist/boilerplates/@batijs/hono/files/server/hono.ts +7 -0
- package/dist/boilerplates/@batijs/hono/types/entry_aws_lambda.d.mts +1 -4
- package/dist/boilerplates/@batijs/hono/types/node_modules/.bun/@types+aws-lambda@8.10.162/node_modules/@types/aws-lambda/index.d.mts +1 -2
- package/dist/boilerplates/@batijs/hono/types/node_modules/.bun/@types+aws-lambda@8.10.162/node_modules/@types/aws-lambda/trigger/api-gateway-proxy.d.mts +1 -18
- package/dist/boilerplates/@batijs/react/files/$package.json.js +1 -1
- package/dist/boilerplates/@batijs/react/files/asset-package.json.mjs +1 -0
- package/dist/boilerplates/@batijs/react/files/pages/+Layout.tsx +2 -0
- package/dist/boilerplates/@batijs/react/files/pages/+config.ts +1 -1
- package/dist/boilerplates/@batijs/react-better-auth/bati.config.mjs +14 -0
- package/dist/boilerplates/@batijs/react-better-auth/files/components/AuthNav.tsx +34 -0
- package/dist/boilerplates/@batijs/react-better-auth/files/global.d.ts +10 -0
- package/dist/boilerplates/@batijs/react-better-auth/files/pages/account/+Page.tsx +32 -0
- package/dist/boilerplates/@batijs/react-better-auth/files/pages/account/+guard.ts +10 -0
- package/dist/boilerplates/@batijs/react-better-auth/files/pages/login/+Page.tsx +84 -0
- package/dist/boilerplates/@batijs/react-better-auth/files/pages/signup/+Page.tsx +87 -0
- package/dist/boilerplates/@batijs/react-better-auth/types/components/AuthNav.d.mts +4 -0
- package/dist/boilerplates/@batijs/react-better-auth/types/pages/account/+Page.d.mts +4 -0
- package/dist/boilerplates/@batijs/react-better-auth/types/pages/account/+guard.d.mts +6 -0
- package/dist/boilerplates/@batijs/react-better-auth/types/pages/login/+Page.d.mts +4 -0
- package/dist/boilerplates/@batijs/react-better-auth/types/pages/signup/+Page.d.mts +4 -0
- package/dist/boilerplates/@batijs/solid/files/$package.json.js +1 -1
- package/dist/boilerplates/@batijs/solid/files/asset-package.json.mjs +1 -0
- package/dist/boilerplates/@batijs/solid/files/pages/+Layout.tsx +2 -0
- package/dist/boilerplates/@batijs/solid/files/pages/+config.ts +1 -1
- package/dist/boilerplates/@batijs/solid-better-auth/bati.config.mjs +14 -0
- package/dist/boilerplates/@batijs/solid-better-auth/files/components/AuthNav.tsx +38 -0
- package/dist/boilerplates/@batijs/solid-better-auth/files/global.d.ts +10 -0
- package/dist/boilerplates/@batijs/solid-better-auth/files/pages/account/+Page.tsx +31 -0
- package/dist/boilerplates/@batijs/solid-better-auth/files/pages/account/+guard.ts +10 -0
- package/dist/boilerplates/@batijs/solid-better-auth/files/pages/login/+Page.tsx +86 -0
- package/dist/boilerplates/@batijs/solid-better-auth/files/pages/signup/+Page.tsx +89 -0
- package/dist/boilerplates/@batijs/solid-better-auth/types/components/AuthNav.d.mts +4 -0
- package/dist/boilerplates/@batijs/solid-better-auth/types/pages/account/+Page.d.mts +4 -0
- package/dist/boilerplates/@batijs/solid-better-auth/types/pages/account/+guard.d.mts +6 -0
- package/dist/boilerplates/@batijs/solid-better-auth/types/pages/login/+Page.d.mts +4 -0
- package/dist/boilerplates/@batijs/solid-better-auth/types/pages/signup/+Page.d.mts +4 -0
- package/dist/boilerplates/@batijs/trpc/files/$package.json.js +1 -1
- package/dist/boilerplates/@batijs/vue/files/pages/+Layout.vue +4 -0
- package/dist/boilerplates/@batijs/vue/files/pages/+config.ts +1 -1
- package/dist/boilerplates/@batijs/vue-better-auth/bati.config.mjs +14 -0
- package/dist/boilerplates/@batijs/vue-better-auth/files/components/AuthNav.vue +24 -0
- package/dist/boilerplates/@batijs/vue-better-auth/files/global.d.ts +10 -0
- package/dist/boilerplates/@batijs/vue-better-auth/files/pages/account/+Page.vue +26 -0
- package/dist/boilerplates/@batijs/vue-better-auth/files/pages/account/+guard.ts +10 -0
- package/dist/boilerplates/@batijs/vue-better-auth/files/pages/login/+Page.vue +65 -0
- package/dist/boilerplates/@batijs/vue-better-auth/files/pages/signup/+Page.vue +54 -0
- package/dist/boilerplates/@batijs/vue-better-auth/types/pages/account/+guard.d.mts +6 -0
- package/dist/boilerplates/boilerplates.json +24 -0
- package/dist/index.js +3 -1
- package/package.json +5 -5
- /package/dist/{asset-package.json-DPPOFRzH.js → asset-package2.json-DPPOFRzH.js} +0 -0
|
@@ -18,6 +18,7 @@ var package_default = {
|
|
|
18
18
|
"@batijs/compile": "workspace:*",
|
|
19
19
|
"@batijs/core": "workspace:*",
|
|
20
20
|
"@batijs/shared-todo": "workspace:*",
|
|
21
|
+
"@batijs/solid-better-auth": "workspace:*",
|
|
21
22
|
"@batijs/telefunc": "workspace:*",
|
|
22
23
|
"@batijs/trpc": "workspace:*",
|
|
23
24
|
"@batijs/ts-rest": "workspace:*",
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
//#region ../../boilerplates/better-auth/dist/files/asset-package.json.mjs
|
|
4
|
+
var package_default = {
|
|
5
|
+
name: "@batijs/better-auth",
|
|
6
|
+
"private": true,
|
|
7
|
+
version: "0.0.1",
|
|
8
|
+
description: "",
|
|
9
|
+
type: "module",
|
|
10
|
+
scripts: {
|
|
11
|
+
"check-types": "tsc --noEmit",
|
|
12
|
+
"build": "bati-compile-boilerplate"
|
|
13
|
+
},
|
|
14
|
+
keywords: [],
|
|
15
|
+
author: "",
|
|
16
|
+
license: "MIT",
|
|
17
|
+
devDependencies: {
|
|
18
|
+
"@batijs/compile": "workspace:*",
|
|
19
|
+
"@batijs/core": "workspace:*",
|
|
20
|
+
"@batijs/drizzle": "workspace:*",
|
|
21
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
22
|
+
"@types/node": "^20.19.37",
|
|
23
|
+
"@universal-middleware/core": "^0.4.17",
|
|
24
|
+
"better-sqlite3": "^12.10.0",
|
|
25
|
+
"drizzle-orm": "^0.45.2",
|
|
26
|
+
"dotenv": "^17.4.2",
|
|
27
|
+
"kysely": "^0.29.2",
|
|
28
|
+
"kysely-d1": "^0.4.0",
|
|
29
|
+
"kysely-postgres-js": "^3.0.0",
|
|
30
|
+
"postgres": "^3.4.9",
|
|
31
|
+
"tsx": "^4.22.4"
|
|
32
|
+
},
|
|
33
|
+
dependencies: { "better-auth": "^1.6.15" },
|
|
34
|
+
files: ["dist/"],
|
|
35
|
+
exports: {
|
|
36
|
+
"./database/better-auth/migrate": { "types": "./dist/types/database/better-auth/migrate.d.mts" },
|
|
37
|
+
"./database/drizzle/schema/auth": { "types": "./dist/types/database/drizzle/schema/auth.d.mts" },
|
|
38
|
+
"./server/better-auth": { "types": "./dist/types/server/better-auth.d.mts" },
|
|
39
|
+
"./server/better-auth-handler": { "types": "./dist/types/server/better-auth-handler.d.mts" }
|
|
40
|
+
},
|
|
41
|
+
typesVersions: { "*": {
|
|
42
|
+
"database/better-auth/migrate": ["./dist/types/database/better-auth/migrate.d.mts"],
|
|
43
|
+
"database/drizzle/schema/auth": ["./dist/types/database/drizzle/schema/auth.d.mts"],
|
|
44
|
+
"server/better-auth": ["./dist/types/server/better-auth.d.mts"],
|
|
45
|
+
"server/better-auth-handler": ["./dist/types/server/better-auth-handler.d.mts"]
|
|
46
|
+
} },
|
|
47
|
+
nx: { "tags": ["type:boilerplate"] }
|
|
48
|
+
};
|
|
49
|
+
//#endregion
|
|
50
|
+
export { package_default as default };
|
|
@@ -20,6 +20,7 @@ var package_default = {
|
|
|
20
20
|
"@babel/plugin-transform-react-jsx": "^7.29.7",
|
|
21
21
|
"@batijs/compile": "workspace:*",
|
|
22
22
|
"@batijs/core": "workspace:*",
|
|
23
|
+
"@batijs/react-better-auth": "workspace:*",
|
|
23
24
|
"@batijs/shared-todo": "workspace:*",
|
|
24
25
|
"@batijs/telefunc": "workspace:*",
|
|
25
26
|
"@batijs/trpc": "workspace:*",
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
//#region ../../packages/core/dist/config.js
|
|
2
|
+
function e(e, t) {
|
|
3
|
+
if (!e) throw Error(t);
|
|
4
|
+
}
|
|
5
|
+
function t(t) {
|
|
6
|
+
return `enforce` in t && e(t.enforce === `pre` || t.enforce === `post`, `'enforce' must be 'pre' or 'post', was ${t.enforce}`), `if` in t && e(typeof t.if == `function`, `'if' must be a function`), `nextSteps` in t && e(typeof t.nextSteps == `function`, `'nextSteps' must be a function`), `knip` in t && (e(typeof t.knip == `object` && t.knip !== null, `'knip' must be an object`), `entry` in t.knip && e(Array.isArray(t.knip.entry), `'knip.entry' must be an array`), `ignoreDependencies` in t.knip && e(Array.isArray(t.knip.ignoreDependencies), `'knip.ignoreDependencies' must be an array`), `ignore` in t.knip && e(Array.isArray(t.knip.ignore), `'knip.ignore' must be an array`), `vite` in t.knip && e(typeof t.knip.vite == `boolean`, `'knip.vite' must be a boolean`)), `env` in t && e(typeof t.env == `function`, `'env' must be a function of meta`), t;
|
|
7
|
+
}
|
|
8
|
+
//#endregion
|
|
9
|
+
//#region bati.config.ts
|
|
10
|
+
var bati_config_default = t({
|
|
11
|
+
if(meta) {
|
|
12
|
+
return meta.BATI.has("better-auth");
|
|
13
|
+
},
|
|
14
|
+
env: () => [
|
|
15
|
+
{
|
|
16
|
+
key: "BETTER_AUTH_SECRET",
|
|
17
|
+
scope: "server-default",
|
|
18
|
+
default: "dev-secret-please-change-me-in-production",
|
|
19
|
+
comment: "Better Auth secret used to sign cookies and tokens — replace in production. See https://better-auth.com/docs/reference/options#secret"
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
key: "GITHUB_CLIENT_ID",
|
|
23
|
+
scope: "secret",
|
|
24
|
+
comment: "GitHub OAuth Client ID",
|
|
25
|
+
devValueFrom: "TEST_GITHUB_CLIENT_ID",
|
|
26
|
+
group: "github"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
key: "GITHUB_CLIENT_SECRET",
|
|
30
|
+
scope: "secret",
|
|
31
|
+
comment: "GitHub OAuth Client Secret",
|
|
32
|
+
devValueFrom: "TEST_GITHUB_CLIENT_SECRET",
|
|
33
|
+
group: "github"
|
|
34
|
+
}
|
|
35
|
+
],
|
|
36
|
+
nextSteps(meta, packageManager, { bold }) {
|
|
37
|
+
return [...meta.BATI.hasD1 || meta.BATI.has("drizzle") ? [] : [{
|
|
38
|
+
type: "command",
|
|
39
|
+
step: `${packageManager} better-auth:migrate`
|
|
40
|
+
}], {
|
|
41
|
+
type: "text",
|
|
42
|
+
step: `Configure Better Auth (secret, GitHub OAuth, migrations). Check ${bold("TODO.md")} for details`
|
|
43
|
+
}];
|
|
44
|
+
},
|
|
45
|
+
knip: { entry: ["server/better-auth-handler.ts", "database/better-auth/migrate.ts"] }
|
|
46
|
+
});
|
|
47
|
+
//#endregion
|
|
48
|
+
export { bati_config_default as default };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { loadMarkdown, packageManager } from "@batijs/core";
|
|
4
|
+
//#region ../../boilerplates/better-auth/dist/files/$TODO.md.mjs
|
|
5
|
+
async function getTodo(props) {
|
|
6
|
+
const content = await loadMarkdown(props);
|
|
7
|
+
const pmRun = packageManager().run;
|
|
8
|
+
const { BATI } = props.meta;
|
|
9
|
+
const todo = `
|
|
10
|
+
## Better Auth
|
|
11
|
+
|
|
12
|
+
Pages are scaffolded at \`/login\`, \`/signup\` and \`/account\` (the latter is protected and redirects to \`/login\`).
|
|
13
|
+
|
|
14
|
+
1. Replace \`BETTER_AUTH_SECRET\` in your \`.env\` with a strong, unique value before going to production — see <https://better-auth.com/docs/reference/options#secret>.
|
|
15
|
+
2. ${BATI.has("drizzle") ? `Create Better Auth's tables — they live in your Drizzle schema (\`database/drizzle/schema/auth.ts\`), so the Drizzle migrate steps create them.` : BATI.hasD1 ? `Create Better Auth's tables in your D1 database. Generate the SQL with \`npx @better-auth/cli generate\` and apply it as a [wrangler D1 migration](https://developers.cloudflare.com/d1/reference/migrations/).` : `Create Better Auth's tables (run again whenever the schema changes):
|
|
16
|
+
\`\`\`sh
|
|
17
|
+
${pmRun} better-auth:migrate
|
|
18
|
+
\`\`\``}
|
|
19
|
+
3. (Optional) Enable GitHub sign-in: create a GitHub OAuth app (<https://github.com/settings/developers>), set the callback URL to \`<your-app-url>/api/auth/callback/github\`, and fill \`GITHUB_CLIENT_ID\` / \`GITHUB_CLIENT_SECRET\` in your \`.env\`. The button is hidden until both are set.
|
|
20
|
+
|
|
21
|
+
See <https://better-auth.com/docs> for adding more providers and plugins.`;
|
|
22
|
+
content.addMarkdownFeature(todo, "better-auth");
|
|
23
|
+
return content;
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
export { getTodo as default };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { loadPackageJson, packageManager } from "@batijs/core";
|
|
4
|
+
//#region ../../boilerplates/better-auth/dist/files/$package.json.mjs
|
|
5
|
+
async function getPackageJson(props) {
|
|
6
|
+
const packageJson = await loadPackageJson(props, await import("../../../../asset-package.json-D0EjbpfM.js").then((x) => x.default));
|
|
7
|
+
const { BATI } = props.meta;
|
|
8
|
+
packageJson.addDependencies(["better-auth", "@universal-middleware/core"]);
|
|
9
|
+
if (BATI.has("drizzle")) return packageJson;
|
|
10
|
+
if (BATI.hasD1) return packageJson.addDependencies(["kysely", "kysely-d1"]);
|
|
11
|
+
const hasPostgres = BATI.has("postgres");
|
|
12
|
+
const bunDirect = packageManager().name === "bun" && hasPostgres;
|
|
13
|
+
return packageJson.setScript("better-auth:migrate", {
|
|
14
|
+
value: `${bunDirect ? "bun" : "tsx"} ./database/better-auth/migrate.ts`,
|
|
15
|
+
precedence: 20
|
|
16
|
+
}).addDevDependencies(["tsx"], ["better-auth:migrate"], !bunDirect).addDependencies(["dotenv"]).addDependencies([
|
|
17
|
+
"postgres",
|
|
18
|
+
"kysely",
|
|
19
|
+
"kysely-postgres-js"
|
|
20
|
+
], hasPostgres).addDependencies(["better-sqlite3"], !hasPostgres).addDevDependencies(["@types/better-sqlite3"], !hasPostgres);
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
export { getPackageJson as default };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
//#region package.json
|
|
2
|
+
var package_default = {
|
|
3
|
+
name: "@batijs/better-auth",
|
|
4
|
+
"private": true,
|
|
5
|
+
version: "0.0.1",
|
|
6
|
+
description: "",
|
|
7
|
+
type: "module",
|
|
8
|
+
scripts: {
|
|
9
|
+
"check-types": "tsc --noEmit",
|
|
10
|
+
"build": "bati-compile-boilerplate"
|
|
11
|
+
},
|
|
12
|
+
keywords: [],
|
|
13
|
+
author: "",
|
|
14
|
+
license: "MIT",
|
|
15
|
+
devDependencies: {
|
|
16
|
+
"@batijs/compile": "workspace:*",
|
|
17
|
+
"@batijs/core": "workspace:*",
|
|
18
|
+
"@batijs/drizzle": "workspace:*",
|
|
19
|
+
"@types/better-sqlite3": "^7.6.13",
|
|
20
|
+
"@types/node": "^20.19.37",
|
|
21
|
+
"@universal-middleware/core": "^0.4.17",
|
|
22
|
+
"better-sqlite3": "^12.10.0",
|
|
23
|
+
"drizzle-orm": "^0.45.2",
|
|
24
|
+
"dotenv": "^17.4.2",
|
|
25
|
+
"kysely": "^0.29.2",
|
|
26
|
+
"kysely-d1": "^0.4.0",
|
|
27
|
+
"kysely-postgres-js": "^3.0.0",
|
|
28
|
+
"postgres": "^3.4.9",
|
|
29
|
+
"tsx": "^4.22.4"
|
|
30
|
+
},
|
|
31
|
+
dependencies: { "better-auth": "^1.6.15" },
|
|
32
|
+
files: ["dist/"],
|
|
33
|
+
exports: {
|
|
34
|
+
"./database/better-auth/migrate": { "types": "./dist/types/database/better-auth/migrate.d.mts" },
|
|
35
|
+
"./database/drizzle/schema/auth": { "types": "./dist/types/database/drizzle/schema/auth.d.mts" },
|
|
36
|
+
"./server/better-auth": { "types": "./dist/types/server/better-auth.d.mts" },
|
|
37
|
+
"./server/better-auth-handler": { "types": "./dist/types/server/better-auth-handler.d.mts" }
|
|
38
|
+
},
|
|
39
|
+
typesVersions: { "*": {
|
|
40
|
+
"database/better-auth/migrate": ["./dist/types/database/better-auth/migrate.d.mts"],
|
|
41
|
+
"database/drizzle/schema/auth": ["./dist/types/database/drizzle/schema/auth.d.mts"],
|
|
42
|
+
"server/better-auth": ["./dist/types/server/better-auth.d.mts"],
|
|
43
|
+
"server/better-auth-handler": ["./dist/types/server/better-auth-handler.d.mts"]
|
|
44
|
+
} },
|
|
45
|
+
nx: { "tags": ["type:boilerplate"] }
|
|
46
|
+
};
|
|
47
|
+
//#endregion
|
|
48
|
+
export { package_default as default };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/*{ @if (!it.BATI.hasD1 && !it.BATI.has("drizzle")) }*/
|
|
2
|
+
|
|
3
|
+
import "dotenv/config";
|
|
4
|
+
import { getMigrations } from "better-auth/db/migration";
|
|
5
|
+
import { getAuthConfig } from "../../server/better-auth";
|
|
6
|
+
|
|
7
|
+
// Creates / updates Better Auth's tables (`user`, `session`, `account`, `verification`) using its
|
|
8
|
+
// built-in Kysely adapter. Run with `better-auth:migrate`.
|
|
9
|
+
// Note: with Drizzle or on Cloudflare D1 this script is not generated — Drizzle's schema or a wrangler
|
|
10
|
+
// D1 migration creates the tables instead.
|
|
11
|
+
const { runMigrations } = await getMigrations(getAuthConfig());
|
|
12
|
+
|
|
13
|
+
await runMigrations();
|
|
14
|
+
|
|
15
|
+
console.log("Better Auth tables are up to date");
|
|
16
|
+
|
|
17
|
+
// The database driver keeps the event loop alive (e.g. Postgres connection pool); exit explicitly
|
|
18
|
+
// so this one-shot script terminates instead of hanging.
|
|
19
|
+
process.exit(0);
|
|
20
|
+
/*{ /if }*/
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/*# BATI include-if-imported #*/
|
|
2
|
+
import { boolean, pgTable, text as pgText, timestamp } from "drizzle-orm/pg-core";
|
|
3
|
+
import { integer, sqliteTable, text as sqliteText } from "drizzle-orm/sqlite-core";
|
|
4
|
+
|
|
5
|
+
// Better Auth's tables, owned by Drizzle so its migrations create them.
|
|
6
|
+
// Regenerate with `npx @better-auth/cli generate` if you customize the Better Auth config.
|
|
7
|
+
// Column names are snake_case to match Better Auth's Drizzle adapter defaults.
|
|
8
|
+
|
|
9
|
+
export const user = BATI.has("postgres")
|
|
10
|
+
? pgTable("user", {
|
|
11
|
+
id: pgText("id").primaryKey(),
|
|
12
|
+
name: pgText("name").notNull(),
|
|
13
|
+
email: pgText("email").notNull().unique(),
|
|
14
|
+
emailVerified: boolean("email_verified").notNull(),
|
|
15
|
+
image: pgText("image"),
|
|
16
|
+
createdAt: timestamp("created_at").notNull(),
|
|
17
|
+
updatedAt: timestamp("updated_at").notNull(),
|
|
18
|
+
})
|
|
19
|
+
: sqliteTable("user", {
|
|
20
|
+
id: sqliteText("id").primaryKey(),
|
|
21
|
+
name: sqliteText("name").notNull(),
|
|
22
|
+
email: sqliteText("email").notNull().unique(),
|
|
23
|
+
emailVerified: integer("email_verified", { mode: "boolean" }).notNull(),
|
|
24
|
+
image: sqliteText("image"),
|
|
25
|
+
createdAt: integer("created_at", { mode: "timestamp_ms" }).notNull(),
|
|
26
|
+
updatedAt: integer("updated_at", { mode: "timestamp_ms" }).notNull(),
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
export const session = BATI.has("postgres")
|
|
30
|
+
? pgTable("session", {
|
|
31
|
+
id: pgText("id").primaryKey(),
|
|
32
|
+
expiresAt: timestamp("expires_at").notNull(),
|
|
33
|
+
token: pgText("token").notNull().unique(),
|
|
34
|
+
createdAt: timestamp("created_at").notNull(),
|
|
35
|
+
updatedAt: timestamp("updated_at").notNull(),
|
|
36
|
+
ipAddress: pgText("ip_address"),
|
|
37
|
+
userAgent: pgText("user_agent"),
|
|
38
|
+
userId: pgText("user_id").notNull(),
|
|
39
|
+
})
|
|
40
|
+
: sqliteTable("session", {
|
|
41
|
+
id: sqliteText("id").primaryKey(),
|
|
42
|
+
expiresAt: integer("expires_at", { mode: "timestamp_ms" }).notNull(),
|
|
43
|
+
token: sqliteText("token").notNull().unique(),
|
|
44
|
+
createdAt: integer("created_at", { mode: "timestamp_ms" }).notNull(),
|
|
45
|
+
updatedAt: integer("updated_at", { mode: "timestamp_ms" }).notNull(),
|
|
46
|
+
ipAddress: sqliteText("ip_address"),
|
|
47
|
+
userAgent: sqliteText("user_agent"),
|
|
48
|
+
userId: sqliteText("user_id").notNull(),
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
export const account = BATI.has("postgres")
|
|
52
|
+
? pgTable("account", {
|
|
53
|
+
id: pgText("id").primaryKey(),
|
|
54
|
+
accountId: pgText("account_id").notNull(),
|
|
55
|
+
providerId: pgText("provider_id").notNull(),
|
|
56
|
+
userId: pgText("user_id").notNull(),
|
|
57
|
+
accessToken: pgText("access_token"),
|
|
58
|
+
refreshToken: pgText("refresh_token"),
|
|
59
|
+
idToken: pgText("id_token"),
|
|
60
|
+
accessTokenExpiresAt: timestamp("access_token_expires_at"),
|
|
61
|
+
refreshTokenExpiresAt: timestamp("refresh_token_expires_at"),
|
|
62
|
+
scope: pgText("scope"),
|
|
63
|
+
password: pgText("password"),
|
|
64
|
+
createdAt: timestamp("created_at").notNull(),
|
|
65
|
+
updatedAt: timestamp("updated_at").notNull(),
|
|
66
|
+
})
|
|
67
|
+
: sqliteTable("account", {
|
|
68
|
+
id: sqliteText("id").primaryKey(),
|
|
69
|
+
accountId: sqliteText("account_id").notNull(),
|
|
70
|
+
providerId: sqliteText("provider_id").notNull(),
|
|
71
|
+
userId: sqliteText("user_id").notNull(),
|
|
72
|
+
accessToken: sqliteText("access_token"),
|
|
73
|
+
refreshToken: sqliteText("refresh_token"),
|
|
74
|
+
idToken: sqliteText("id_token"),
|
|
75
|
+
accessTokenExpiresAt: integer("access_token_expires_at", { mode: "timestamp_ms" }),
|
|
76
|
+
refreshTokenExpiresAt: integer("refresh_token_expires_at", { mode: "timestamp_ms" }),
|
|
77
|
+
scope: sqliteText("scope"),
|
|
78
|
+
password: sqliteText("password"),
|
|
79
|
+
createdAt: integer("created_at", { mode: "timestamp_ms" }).notNull(),
|
|
80
|
+
updatedAt: integer("updated_at", { mode: "timestamp_ms" }).notNull(),
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
export const verification = BATI.has("postgres")
|
|
84
|
+
? pgTable("verification", {
|
|
85
|
+
id: pgText("id").primaryKey(),
|
|
86
|
+
identifier: pgText("identifier").notNull(),
|
|
87
|
+
value: pgText("value").notNull(),
|
|
88
|
+
expiresAt: timestamp("expires_at").notNull(),
|
|
89
|
+
createdAt: timestamp("created_at").notNull(),
|
|
90
|
+
updatedAt: timestamp("updated_at").notNull(),
|
|
91
|
+
})
|
|
92
|
+
: sqliteTable("verification", {
|
|
93
|
+
id: sqliteText("id").primaryKey(),
|
|
94
|
+
identifier: sqliteText("identifier").notNull(),
|
|
95
|
+
value: sqliteText("value").notNull(),
|
|
96
|
+
expiresAt: integer("expires_at", { mode: "timestamp_ms" }).notNull(),
|
|
97
|
+
createdAt: integer("created_at", { mode: "timestamp_ms" }).notNull(),
|
|
98
|
+
updatedAt: integer("updated_at", { mode: "timestamp_ms" }).notNull(),
|
|
99
|
+
});
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
//#region ../../boilerplates/better-auth/dist/files/database/migrations/$better-auth.sql.mjs
|
|
4
|
+
function getMigration(props) {
|
|
5
|
+
if (!props.meta.BATI.hasD1 || props.meta.BATI.has("drizzle")) return void 0;
|
|
6
|
+
return `CREATE TABLE IF NOT EXISTS "user" (
|
|
7
|
+
"id" text NOT NULL PRIMARY KEY,
|
|
8
|
+
"name" text NOT NULL,
|
|
9
|
+
"email" text NOT NULL UNIQUE,
|
|
10
|
+
"emailVerified" integer NOT NULL DEFAULT 0,
|
|
11
|
+
"image" text,
|
|
12
|
+
"createdAt" date NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
13
|
+
"updatedAt" date NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
CREATE TABLE IF NOT EXISTS "session" (
|
|
17
|
+
"id" text NOT NULL PRIMARY KEY,
|
|
18
|
+
"expiresAt" date NOT NULL,
|
|
19
|
+
"token" text NOT NULL UNIQUE,
|
|
20
|
+
"createdAt" date NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
21
|
+
"updatedAt" date NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
22
|
+
"ipAddress" text,
|
|
23
|
+
"userAgent" text,
|
|
24
|
+
"userId" text NOT NULL REFERENCES "user" ("id")
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
CREATE TABLE IF NOT EXISTS "account" (
|
|
28
|
+
"id" text NOT NULL PRIMARY KEY,
|
|
29
|
+
"accountId" text NOT NULL,
|
|
30
|
+
"providerId" text NOT NULL,
|
|
31
|
+
"userId" text NOT NULL REFERENCES "user" ("id"),
|
|
32
|
+
"accessToken" text,
|
|
33
|
+
"refreshToken" text,
|
|
34
|
+
"idToken" text,
|
|
35
|
+
"accessTokenExpiresAt" date,
|
|
36
|
+
"refreshTokenExpiresAt" date,
|
|
37
|
+
"scope" text,
|
|
38
|
+
"password" text,
|
|
39
|
+
"createdAt" date NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
40
|
+
"updatedAt" date NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
CREATE TABLE IF NOT EXISTS "verification" (
|
|
44
|
+
"id" text NOT NULL PRIMARY KEY,
|
|
45
|
+
"identifier" text NOT NULL,
|
|
46
|
+
"value" text NOT NULL,
|
|
47
|
+
"expiresAt" date NOT NULL,
|
|
48
|
+
"createdAt" date DEFAULT CURRENT_TIMESTAMP,
|
|
49
|
+
"updatedAt" date DEFAULT CURRENT_TIMESTAMP
|
|
50
|
+
);
|
|
51
|
+
`;
|
|
52
|
+
}
|
|
53
|
+
//#endregion
|
|
54
|
+
export { getMigration as default };
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import {
|
|
2
|
+
enhance,
|
|
3
|
+
type RuntimeAdapter,
|
|
4
|
+
type UniversalHandler,
|
|
5
|
+
type UniversalMiddleware,
|
|
6
|
+
} from "@universal-middleware/core";
|
|
7
|
+
import { betterAuth } from "better-auth";
|
|
8
|
+
import { getAuthConfig } from "./better-auth";
|
|
9
|
+
|
|
10
|
+
//# !BATI.hasD1
|
|
11
|
+
let authSingleton: ReturnType<typeof betterAuth> | undefined;
|
|
12
|
+
|
|
13
|
+
// On Cloudflare the D1 binding is request-scoped (fresh instance per request); elsewhere it's memoized.
|
|
14
|
+
function getAuth(runtime: RuntimeAdapter) {
|
|
15
|
+
if (BATI.hasD1) {
|
|
16
|
+
return betterAuth(getAuthConfig(runtime));
|
|
17
|
+
} else {
|
|
18
|
+
authSingleton ??= betterAuth(getAuthConfig(runtime));
|
|
19
|
+
return authSingleton;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Note: You can directly define a server middleware instead of defining a Universal Middleware. (You can remove @universal-middleware/* — Vike's scaffolder uses it only to simplify its internal logic, see https://github.com/vikejs/vike/discussions/3116)
|
|
24
|
+
/**
|
|
25
|
+
* Add the Better Auth user to the context.
|
|
26
|
+
* @link {@see https://better-auth.com/docs/concepts/session-management}
|
|
27
|
+
*/
|
|
28
|
+
export const betterAuthSessionMiddleware: UniversalMiddleware = enhance(
|
|
29
|
+
// The context we add here is automatically merged into pageContext
|
|
30
|
+
async (request, context, runtime) => {
|
|
31
|
+
try {
|
|
32
|
+
const data = await getAuth(runtime).api.getSession({ headers: request.headers });
|
|
33
|
+
return {
|
|
34
|
+
...context,
|
|
35
|
+
// Sets pageContext.user
|
|
36
|
+
user: data?.user ?? null,
|
|
37
|
+
};
|
|
38
|
+
} catch (error) {
|
|
39
|
+
console.debug("betterAuthSessionMiddleware:", error);
|
|
40
|
+
return {
|
|
41
|
+
...context,
|
|
42
|
+
user: null,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: "my-app:better-auth-middleware",
|
|
48
|
+
immutable: false,
|
|
49
|
+
},
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
// Note: You can directly define a server middleware instead of defining a Universal Middleware. (You can remove @universal-middleware/* — Vike's scaffolder uses it only to simplify its internal logic, see https://github.com/vikejs/vike/discussions/3116)
|
|
53
|
+
/**
|
|
54
|
+
* Better Auth route
|
|
55
|
+
* @link {@see https://better-auth.com/docs/installation}
|
|
56
|
+
**/
|
|
57
|
+
export const betterAuthHandler = enhance(
|
|
58
|
+
async (request, _context, runtime) => {
|
|
59
|
+
return getAuth(runtime).handler(request);
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: "my-app:better-auth-handler",
|
|
63
|
+
path: "/api/auth/**",
|
|
64
|
+
method: ["GET", "POST"],
|
|
65
|
+
immutable: false,
|
|
66
|
+
},
|
|
67
|
+
) satisfies UniversalHandler;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { env as cloudflareEnv } from "cloudflare:workers";
|
|
2
|
+
import { dbD1, dbPostgres, dbSqlite } from "@batijs/drizzle/database/drizzle/db";
|
|
3
|
+
import type { RuntimeAdapter } from "@universal-middleware/core";
|
|
4
|
+
import type { BetterAuthOptions } from "better-auth";
|
|
5
|
+
import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
|
6
|
+
import Database from "better-sqlite3";
|
|
7
|
+
import { Kysely } from "kysely";
|
|
8
|
+
import { D1Dialect } from "kysely-d1";
|
|
9
|
+
import { PostgresJSDialect } from "kysely-postgres-js";
|
|
10
|
+
import postgres from "postgres";
|
|
11
|
+
import * as authSchema from "../database/drizzle/schema/auth";
|
|
12
|
+
|
|
13
|
+
const env: BATI.If<{ '!BATI.has("cloudflare")': Record<string, string | undefined> }> = BATI.has("cloudflare")
|
|
14
|
+
? (cloudflareEnv as BATI.Any)
|
|
15
|
+
: typeof process?.env !== "undefined"
|
|
16
|
+
? process.env
|
|
17
|
+
: {};
|
|
18
|
+
|
|
19
|
+
//# BATI.hasD1
|
|
20
|
+
function getD1(runtime?: RuntimeAdapter): D1Database {
|
|
21
|
+
if (runtime?.runtime === "workerd" && runtime.env) {
|
|
22
|
+
return runtime.env.DB as D1Database;
|
|
23
|
+
}
|
|
24
|
+
throw new Error("Cloudflare D1 binding (DB) is not available");
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
//# BATI.has("drizzle")
|
|
28
|
+
function getDrizzleDb(_runtime?: RuntimeAdapter) {
|
|
29
|
+
if (BATI.hasD1) {
|
|
30
|
+
return dbD1(getD1(_runtime));
|
|
31
|
+
} else if (BATI.has("postgres")) {
|
|
32
|
+
return dbPostgres();
|
|
33
|
+
} else {
|
|
34
|
+
return dbSqlite();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Better Auth keeps its own tables (user/session/account/verification) so it only needs the engine.
|
|
39
|
+
// With Drizzle it reuses the app's instance (Drizzle owns the schema + migrations); otherwise it
|
|
40
|
+
// opens its own connection and creates the tables via `better-auth:migrate` (or a D1 SQL migration).
|
|
41
|
+
function getDatabase(_runtime?: RuntimeAdapter): BetterAuthOptions["database"] {
|
|
42
|
+
if (BATI.has("drizzle")) {
|
|
43
|
+
return drizzleAdapter(getDrizzleDb(_runtime), {
|
|
44
|
+
provider: BATI.has("postgres") ? "pg" : "sqlite",
|
|
45
|
+
schema: authSchema,
|
|
46
|
+
});
|
|
47
|
+
} else if (BATI.hasD1) {
|
|
48
|
+
// Cloudflare D1 is the SQLite engine on Workers, reached through Kysely's D1 dialect.
|
|
49
|
+
return {
|
|
50
|
+
db: new Kysely({ dialect: new D1Dialect({ database: getD1(_runtime) }) }),
|
|
51
|
+
type: "sqlite" as const,
|
|
52
|
+
};
|
|
53
|
+
} else if (BATI.has("postgres")) {
|
|
54
|
+
// postgres.js via Kysely's dialect — the same driver the rest of the app uses (and Bun-friendly).
|
|
55
|
+
if (!env.DATABASE_URL) {
|
|
56
|
+
throw new Error("Missing DATABASE_URL in .env file");
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
db: new Kysely({ dialect: new PostgresJSDialect({ postgres: postgres(env.DATABASE_URL) }) }),
|
|
60
|
+
type: "postgres" as const,
|
|
61
|
+
};
|
|
62
|
+
} else {
|
|
63
|
+
// SQLite via better-sqlite3. Prisma-style `file:` URLs are normalized to a plain path.
|
|
64
|
+
if (!env.DATABASE_URL) {
|
|
65
|
+
throw new Error("Missing DATABASE_URL in .env file");
|
|
66
|
+
}
|
|
67
|
+
return new Database(env.DATABASE_URL.replace(/^file:/, ""));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function getAuthConfig(runtime?: RuntimeAdapter): BetterAuthOptions {
|
|
72
|
+
return {
|
|
73
|
+
secret: env.BETTER_AUTH_SECRET,
|
|
74
|
+
database: getDatabase(runtime),
|
|
75
|
+
emailAndPassword: {
|
|
76
|
+
enabled: true,
|
|
77
|
+
},
|
|
78
|
+
// GitHub is only enabled once its credentials are set, so the app runs out of the box without them.
|
|
79
|
+
socialProviders:
|
|
80
|
+
env.GITHUB_CLIENT_ID && env.GITHUB_CLIENT_SECRET
|
|
81
|
+
? {
|
|
82
|
+
github: {
|
|
83
|
+
clientId: env.GITHUB_CLIENT_ID,
|
|
84
|
+
clientSecret: env.GITHUB_CLIENT_SECRET,
|
|
85
|
+
},
|
|
86
|
+
}
|
|
87
|
+
: {},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|