create-authhero 0.8.0 → 0.10.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/dist/cloudflare-multitenant/.dev.vars.example +20 -4
- package/dist/cloudflare-multitenant/README.md +238 -89
- package/dist/cloudflare-multitenant/drizzle.config.ts +8 -0
- package/dist/cloudflare-multitenant/migrations/0000_init.sql +782 -0
- package/dist/cloudflare-multitenant/migrations/meta/_journal.json +13 -0
- package/dist/cloudflare-multitenant/seed-helper.js +75 -0
- package/dist/cloudflare-multitenant/src/app.ts +3 -22
- package/dist/cloudflare-multitenant/src/db/schema.ts +845 -0
- package/dist/cloudflare-multitenant/src/index.ts +61 -55
- package/dist/cloudflare-multitenant/src/seed.ts +64 -0
- package/dist/cloudflare-multitenant/src/types.ts +17 -17
- package/dist/cloudflare-multitenant/wrangler.toml +40 -28
- package/dist/cloudflare-simple/.dev.vars.example +20 -0
- package/dist/cloudflare-simple/README.md +137 -0
- package/dist/cloudflare-simple/src/db/schema.ts +5 -839
- package/dist/cloudflare-simple/src/index.ts +37 -4
- package/dist/cloudflare-simple/src/types.ts +18 -0
- package/dist/cloudflare-simple/wrangler.toml +27 -0
- package/dist/create-authhero.js +117 -128
- package/package.json +1 -1
- package/dist/cloudflare-multitenant/src/database-factory.ts +0 -220
|
@@ -5,6 +5,11 @@ import createApp from "./app";
|
|
|
5
5
|
import { Env } from "./types";
|
|
6
6
|
import { AuthHeroConfig } from "authhero";
|
|
7
7
|
|
|
8
|
+
// ──────────────────────────────────────────────────────────────────────────────
|
|
9
|
+
// OPTIONAL: Uncomment to enable Cloudflare adapters (Analytics Engine, etc.)
|
|
10
|
+
// ──────────────────────────────────────────────────────────────────────────────
|
|
11
|
+
// import createCloudflareAdapters from "@authhero/cloudflare-adapter";
|
|
12
|
+
|
|
8
13
|
export default {
|
|
9
14
|
async fetch(request: Request, env: Env): Promise<Response> {
|
|
10
15
|
const url = new URL(request.url);
|
|
@@ -17,17 +22,45 @@ export default {
|
|
|
17
22
|
const db = new Kysely<any>({ dialect });
|
|
18
23
|
const dataAdapter = createAdapters(db);
|
|
19
24
|
|
|
25
|
+
// ────────────────────────────────────────────────────────────────────────
|
|
26
|
+
// OPTIONAL: Cloudflare Analytics Engine for centralized logging
|
|
27
|
+
// Uncomment to enable:
|
|
28
|
+
// ────────────────────────────────────────────────────────────────────────
|
|
29
|
+
// const cloudflareAdapters = createCloudflareAdapters({
|
|
30
|
+
// accountId: env.CLOUDFLARE_ACCOUNT_ID,
|
|
31
|
+
// apiToken: env.CLOUDFLARE_API_TOKEN,
|
|
32
|
+
// analyticsEngineLogs: {
|
|
33
|
+
// analyticsEngineBinding: env.AUTH_LOGS,
|
|
34
|
+
// accountId: env.CLOUDFLARE_ACCOUNT_ID,
|
|
35
|
+
// apiToken: env.ANALYTICS_ENGINE_API_TOKEN || env.CLOUDFLARE_API_TOKEN,
|
|
36
|
+
// dataset: "authhero_logs",
|
|
37
|
+
// },
|
|
38
|
+
// });
|
|
39
|
+
|
|
40
|
+
// ────────────────────────────────────────────────────────────────────────
|
|
41
|
+
// OPTIONAL: Rate Limiting
|
|
42
|
+
// Uncomment to enable rate limiting on authentication endpoints:
|
|
43
|
+
// ────────────────────────────────────────────────────────────────────────
|
|
44
|
+
// const clientIp = request.headers.get("CF-Connecting-IP") || "unknown";
|
|
45
|
+
// const { success } = await env.RATE_LIMITER.limit({ key: clientIp });
|
|
46
|
+
// if (!success) {
|
|
47
|
+
// return new Response("Rate limit exceeded", { status: 429 });
|
|
48
|
+
// }
|
|
49
|
+
|
|
20
50
|
const config: AuthHeroConfig = {
|
|
21
51
|
dataAdapter,
|
|
22
|
-
//
|
|
52
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
53
|
+
// OPTIONAL: Spread Cloudflare adapters to enable Analytics Engine logging
|
|
54
|
+
// Uncomment when using createCloudflareAdapters above:
|
|
55
|
+
// ──────────────────────────────────────────────────────────────────────
|
|
56
|
+
// ...cloudflareAdapters,
|
|
57
|
+
|
|
58
|
+
// Allow CORS for the Management API from admin UIs
|
|
23
59
|
allowedOrigins: [
|
|
24
60
|
"http://localhost:5173",
|
|
25
|
-
"http://localhost:3000",
|
|
26
|
-
"https://localhost:5173",
|
|
27
61
|
"https://localhost:3000",
|
|
28
62
|
"https://manage.authhero.net",
|
|
29
63
|
"https://local.authhero.net",
|
|
30
|
-
// Also allow the requesting origin in development
|
|
31
64
|
origin,
|
|
32
65
|
].filter(Boolean),
|
|
33
66
|
};
|
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
/// <reference types="@cloudflare/workers-types" />
|
|
2
2
|
|
|
3
|
+
// Uncomment to enable Analytics Engine logging:
|
|
4
|
+
// import { AnalyticsEngineDataset } from "@authhero/cloudflare-adapter";
|
|
5
|
+
|
|
3
6
|
export interface Env {
|
|
4
7
|
AUTH_DB: D1Database;
|
|
8
|
+
|
|
9
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
10
|
+
// OPTIONAL: Analytics Engine for centralized logging
|
|
11
|
+
// Uncomment to enable:
|
|
12
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
13
|
+
// AUTH_LOGS: AnalyticsEngineDataset;
|
|
14
|
+
// CLOUDFLARE_ACCOUNT_ID: string;
|
|
15
|
+
// CLOUDFLARE_API_TOKEN: string;
|
|
16
|
+
// ANALYTICS_ENGINE_API_TOKEN?: string; // Optional: separate token for Analytics Engine
|
|
17
|
+
|
|
18
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
19
|
+
// OPTIONAL: Rate Limiting
|
|
20
|
+
// Uncomment to enable:
|
|
21
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
22
|
+
// RATE_LIMITER: RateLimiter;
|
|
5
23
|
}
|
|
@@ -18,6 +18,33 @@ database_name = "authhero-db"
|
|
|
18
18
|
database_id = "local"
|
|
19
19
|
migrations_dir = "migrations"
|
|
20
20
|
|
|
21
|
+
# ════════════════════════════════════════════════════════════════════════════
|
|
22
|
+
# OPTIONAL: Analytics Engine for centralized logging
|
|
23
|
+
# ════════════════════════════════════════════════════════════════════════════
|
|
24
|
+
# To enable Analytics Engine:
|
|
25
|
+
# 1. Create dataset in Cloudflare Dashboard: Workers & Pages > Analytics Engine
|
|
26
|
+
# 2. Uncomment the binding below
|
|
27
|
+
# 3. Add CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_API_TOKEN to .dev.vars
|
|
28
|
+
# 4. Uncomment the Analytics Engine code in src/index.ts
|
|
29
|
+
#
|
|
30
|
+
# [[analytics_engine_datasets]]
|
|
31
|
+
# binding = "AUTH_LOGS"
|
|
32
|
+
# dataset = "authhero_logs"
|
|
33
|
+
|
|
34
|
+
# ════════════════════════════════════════════════════════════════════════════
|
|
35
|
+
# OPTIONAL: Rate Limiting
|
|
36
|
+
# ════════════════════════════════════════════════════════════════════════════
|
|
37
|
+
# To enable Rate Limiting:
|
|
38
|
+
# 1. Rate limiting is available on Workers Paid plan ($5/month)
|
|
39
|
+
# 2. Uncomment the binding below
|
|
40
|
+
# 3. Implement rate limiting logic in src/index.ts
|
|
41
|
+
#
|
|
42
|
+
# [[unsafe.bindings]]
|
|
43
|
+
# name = "RATE_LIMITER"
|
|
44
|
+
# type = "ratelimit"
|
|
45
|
+
# namespace_id = "1001" # Unique namespace ID for this limiter
|
|
46
|
+
# simple = { limit = 100, period = 60 } # 100 requests per 60 seconds
|
|
47
|
+
|
|
21
48
|
# Optional: Enable observability
|
|
22
49
|
# [observability]
|
|
23
50
|
# enabled = true
|
package/dist/create-authhero.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { Command as
|
|
3
|
-
import
|
|
2
|
+
import { Command as x } from "commander";
|
|
3
|
+
import c from "inquirer";
|
|
4
4
|
import i from "fs";
|
|
5
5
|
import f from "path";
|
|
6
|
-
import { spawn as
|
|
7
|
-
const
|
|
6
|
+
import { spawn as b } from "child_process";
|
|
7
|
+
const D = new x(), n = {
|
|
8
8
|
local: {
|
|
9
9
|
name: "Local (SQLite)",
|
|
10
10
|
description: "Local development setup with SQLite database - great for getting started",
|
|
11
11
|
templateDir: "local",
|
|
12
|
-
packageJson: (
|
|
13
|
-
name:
|
|
12
|
+
packageJson: (r) => ({
|
|
13
|
+
name: r,
|
|
14
14
|
version: "1.0.0",
|
|
15
15
|
type: "module",
|
|
16
16
|
scripts: {
|
|
@@ -42,8 +42,8 @@ const b = new I(), l = {
|
|
|
42
42
|
name: "Cloudflare Simple (Single Tenant)",
|
|
43
43
|
description: "Single-tenant Cloudflare Workers setup with D1 database",
|
|
44
44
|
templateDir: "cloudflare-simple",
|
|
45
|
-
packageJson: (
|
|
46
|
-
name:
|
|
45
|
+
packageJson: (r) => ({
|
|
46
|
+
name: r,
|
|
47
47
|
version: "1.0.0",
|
|
48
48
|
type: "module",
|
|
49
49
|
scripts: {
|
|
@@ -80,49 +80,53 @@ const b = new I(), l = {
|
|
|
80
80
|
},
|
|
81
81
|
"cloudflare-multitenant": {
|
|
82
82
|
name: "Cloudflare Multi-Tenant (Production)",
|
|
83
|
-
description: "Production-grade multi-tenant setup with
|
|
83
|
+
description: "Production-grade multi-tenant setup with D1 database and tenant management",
|
|
84
84
|
templateDir: "cloudflare-multitenant",
|
|
85
|
-
packageJson: (
|
|
86
|
-
name:
|
|
85
|
+
packageJson: (r) => ({
|
|
86
|
+
name: r,
|
|
87
87
|
version: "1.0.0",
|
|
88
88
|
type: "module",
|
|
89
89
|
scripts: {
|
|
90
|
-
dev: "wrangler dev",
|
|
90
|
+
"dev:local": "wrangler dev --port 3000 --local-protocol https",
|
|
91
|
+
"dev:remote": "wrangler dev --port 3000 --local-protocol https --remote",
|
|
92
|
+
dev: "wrangler dev --port 3000 --local-protocol https",
|
|
91
93
|
deploy: "wrangler deploy",
|
|
92
|
-
"db:migrate": "wrangler d1 migrations apply
|
|
93
|
-
"db:migrate:
|
|
94
|
-
|
|
94
|
+
"db:migrate:local": "wrangler d1 migrations apply AUTH_DB --local",
|
|
95
|
+
"db:migrate:remote": "wrangler d1 migrations apply AUTH_DB --remote",
|
|
96
|
+
migrate: "wrangler d1 migrations apply AUTH_DB --local",
|
|
97
|
+
"db:generate": "drizzle-kit generate",
|
|
98
|
+
"seed:local": "node seed-helper.js",
|
|
99
|
+
"seed:remote": "node seed-helper.js '' '' remote",
|
|
100
|
+
seed: "node seed-helper.js"
|
|
95
101
|
},
|
|
96
102
|
dependencies: {
|
|
97
|
-
"@authhero/cloudflare-adapter": "latest",
|
|
98
103
|
"@authhero/kysely-adapter": "latest",
|
|
99
|
-
"@authhero/multi-tenancy": "latest",
|
|
100
104
|
"@hono/swagger-ui": "^0.5.0",
|
|
101
|
-
"@hono/zod-openapi": "^0.19.
|
|
105
|
+
"@hono/zod-openapi": "^0.19.0",
|
|
102
106
|
authhero: "latest",
|
|
103
107
|
hono: "^4.6.0",
|
|
104
108
|
kysely: "latest",
|
|
105
|
-
"kysely-d1": "latest"
|
|
106
|
-
wretch: "^3.0.0"
|
|
109
|
+
"kysely-d1": "latest"
|
|
107
110
|
},
|
|
108
111
|
devDependencies: {
|
|
109
112
|
"@cloudflare/workers-types": "^4.0.0",
|
|
113
|
+
"drizzle-kit": "^0.31.0",
|
|
114
|
+
"drizzle-orm": "^0.44.0",
|
|
110
115
|
typescript: "^5.5.0",
|
|
111
116
|
wrangler: "^3.0.0"
|
|
112
117
|
}
|
|
113
118
|
}),
|
|
114
|
-
seedFile: "seed.
|
|
119
|
+
seedFile: "seed.ts"
|
|
115
120
|
}
|
|
116
121
|
};
|
|
117
|
-
function
|
|
118
|
-
i.readdirSync(
|
|
119
|
-
const t = f.join(
|
|
120
|
-
i.lstatSync(t).isDirectory() ? (i.mkdirSync(
|
|
122
|
+
function A(r, a) {
|
|
123
|
+
i.readdirSync(r).forEach((o) => {
|
|
124
|
+
const t = f.join(r, o), e = f.join(a, o);
|
|
125
|
+
i.lstatSync(t).isDirectory() ? (i.mkdirSync(e, { recursive: !0 }), A(t, e)) : i.copyFileSync(t, e);
|
|
121
126
|
});
|
|
122
127
|
}
|
|
123
|
-
function $(
|
|
124
|
-
|
|
125
|
-
return `import { SqliteDialect, Kysely } from "kysely";
|
|
128
|
+
function $() {
|
|
129
|
+
return `import { SqliteDialect, Kysely } from "kysely";
|
|
126
130
|
import Database from "better-sqlite3";
|
|
127
131
|
import createAdapters from "@authhero/kysely-adapter";
|
|
128
132
|
import { seed } from "authhero";
|
|
@@ -154,109 +158,88 @@ async function main() {
|
|
|
154
158
|
|
|
155
159
|
main().catch(console.error);
|
|
156
160
|
`;
|
|
157
|
-
{
|
|
158
|
-
const e = (/* @__PURE__ */ new Date()).toISOString(), r = "default";
|
|
159
|
-
return `-- Seed file for AuthHero
|
|
160
|
-
--
|
|
161
|
-
-- IMPORTANT: This SQL file creates the basic structure but the password
|
|
162
|
-
-- cannot be properly hashed in SQL. After running this seed, you should
|
|
163
|
-
-- use the management API or run a script to set the admin password.
|
|
164
|
-
|
|
165
|
-
-- Create default tenant
|
|
166
|
-
INSERT OR IGNORE INTO tenants (id, friendly_name, audience, sender_email, sender_name, created_at, updated_at)
|
|
167
|
-
VALUES ('${r}', 'Default Tenant', 'https://api.example.com', 'noreply@example.com', 'AuthHero', '${e}', '${e}');
|
|
168
|
-
|
|
169
|
-
-- Create password connection
|
|
170
|
-
INSERT OR IGNORE INTO connections (id, tenant_id, name, strategy, options, created_at, updated_at)
|
|
171
|
-
VALUES ('conn_default', '${r}', 'Username-Password-Authentication', 'Username-Password-Authentication', '{}', '${e}', '${e}');
|
|
172
|
-
|
|
173
|
-
-- Create default client
|
|
174
|
-
INSERT OR IGNORE INTO clients (client_id, tenant_id, name, callbacks, allowed_origins, web_origins, connections, created_at, updated_at)
|
|
175
|
-
VALUES ('default', '${r}', 'Default Application', '["https://manage.authhero.net/auth-callback","https://local.authhero.net/auth-callback"]', '[]', '[]', '["Username-Password-Authentication"]', '${e}', '${e}');
|
|
176
|
-
|
|
177
|
-
-- Note: Admin user and password should be created via the management API
|
|
178
|
-
-- or using a TypeScript seed script with proper bcrypt hashing.
|
|
179
|
-
-- Example command: curl -X POST http://localhost:3000/api/v2/users ...
|
|
180
|
-
`;
|
|
181
|
-
}
|
|
182
161
|
}
|
|
183
|
-
function v(
|
|
184
|
-
return new Promise((
|
|
185
|
-
const t =
|
|
186
|
-
cwd:
|
|
162
|
+
function v(r, a) {
|
|
163
|
+
return new Promise((s, o) => {
|
|
164
|
+
const t = b(r, [], {
|
|
165
|
+
cwd: a,
|
|
187
166
|
shell: !0,
|
|
188
167
|
stdio: "inherit"
|
|
189
168
|
});
|
|
190
|
-
t.on("close", (
|
|
191
|
-
|
|
169
|
+
t.on("close", (e) => {
|
|
170
|
+
e === 0 ? s() : o(new Error(`Command failed with exit code ${e}`));
|
|
192
171
|
}), t.on("error", o);
|
|
193
172
|
});
|
|
194
173
|
}
|
|
195
|
-
function S(
|
|
174
|
+
function S(r, a, s) {
|
|
196
175
|
return new Promise((o, t) => {
|
|
197
|
-
const
|
|
198
|
-
cwd:
|
|
176
|
+
const e = b(r, [], {
|
|
177
|
+
cwd: a,
|
|
199
178
|
shell: !0,
|
|
200
179
|
stdio: "inherit",
|
|
201
|
-
env: { ...process.env, ...
|
|
180
|
+
env: { ...process.env, ...s }
|
|
202
181
|
});
|
|
203
|
-
|
|
182
|
+
e.on("close", (g) => {
|
|
204
183
|
g === 0 ? o() : t(new Error(`Command failed with exit code ${g}`));
|
|
205
|
-
}),
|
|
184
|
+
}), e.on("error", t);
|
|
206
185
|
});
|
|
207
186
|
}
|
|
208
|
-
|
|
187
|
+
D.version("1.0.0").description("Create a new AuthHero project").argument("[project-name]", "name of the project").option(
|
|
209
188
|
"-t, --template <type>",
|
|
210
189
|
"template type: local, cloudflare-simple, or cloudflare-multitenant"
|
|
211
190
|
).option("-e, --email <email>", "admin email address").option("-p, --password <password>", "admin password (min 8 characters)").option(
|
|
212
191
|
"--package-manager <pm>",
|
|
213
192
|
"package manager to use: npm, yarn, pnpm, or bun"
|
|
214
|
-
).option("--skip-install", "skip installing dependencies").option("--skip-migrate", "skip running database migrations").option("--skip-seed", "skip seeding the database").option("--skip-start", "skip starting the development server").option("--remote", "use remote mode for cloudflare-simple (production D1)").option("-y, --yes", "skip all prompts and use defaults/provided options").action(async (
|
|
215
|
-
const
|
|
193
|
+
).option("--skip-install", "skip installing dependencies").option("--skip-migrate", "skip running database migrations").option("--skip-seed", "skip seeding the database").option("--skip-start", "skip starting the development server").option("--remote", "use remote mode for cloudflare-simple (production D1)").option("-y, --yes", "skip all prompts and use defaults/provided options").action(async (r, a) => {
|
|
194
|
+
const s = a.yes === !0;
|
|
216
195
|
console.log(`
|
|
217
196
|
🔐 Welcome to AuthHero!
|
|
218
197
|
`);
|
|
219
|
-
let o =
|
|
220
|
-
o || (
|
|
198
|
+
let o = r;
|
|
199
|
+
o || (s ? (o = "auth-server", console.log(`Using default project name: ${o}`)) : o = (await c.prompt([
|
|
221
200
|
{
|
|
222
201
|
type: "input",
|
|
223
202
|
name: "projectName",
|
|
224
203
|
message: "Project name:",
|
|
225
204
|
default: "auth-server",
|
|
226
|
-
validate: (
|
|
205
|
+
validate: (p) => p !== "" || "Project name cannot be empty"
|
|
227
206
|
}
|
|
228
207
|
])).projectName);
|
|
229
208
|
const t = f.join(process.cwd(), o);
|
|
230
209
|
i.existsSync(t) && (console.error(`❌ Project "${o}" already exists.`), process.exit(1));
|
|
231
|
-
let
|
|
232
|
-
|
|
210
|
+
let e;
|
|
211
|
+
a.template ? (["local", "cloudflare-simple", "cloudflare-multitenant"].includes(
|
|
212
|
+
a.template
|
|
213
|
+
) || (console.error(`❌ Invalid template: ${a.template}`), console.error(
|
|
214
|
+
"Valid options: local, cloudflare-simple, cloudflare-multitenant"
|
|
215
|
+
), process.exit(1)), e = a.template, console.log(`Using template: ${n[e].name}`)) : e = (await c.prompt([
|
|
233
216
|
{
|
|
234
217
|
type: "list",
|
|
235
218
|
name: "setupType",
|
|
236
219
|
message: "Select your setup type:",
|
|
237
220
|
choices: [
|
|
238
221
|
{
|
|
239
|
-
name: `${
|
|
240
|
-
${
|
|
222
|
+
name: `${n.local.name}
|
|
223
|
+
${n.local.description}`,
|
|
241
224
|
value: "local",
|
|
242
|
-
short:
|
|
225
|
+
short: n.local.name
|
|
243
226
|
},
|
|
244
227
|
{
|
|
245
|
-
name: `${
|
|
246
|
-
${
|
|
228
|
+
name: `${n["cloudflare-simple"].name}
|
|
229
|
+
${n["cloudflare-simple"].description}`,
|
|
247
230
|
value: "cloudflare-simple",
|
|
248
|
-
short:
|
|
231
|
+
short: n["cloudflare-simple"].name
|
|
249
232
|
},
|
|
250
233
|
{
|
|
251
|
-
name: `${
|
|
252
|
-
${
|
|
234
|
+
name: `${n["cloudflare-multitenant"].name}
|
|
235
|
+
${n["cloudflare-multitenant"].description}`,
|
|
253
236
|
value: "cloudflare-multitenant",
|
|
254
|
-
short:
|
|
237
|
+
short: n["cloudflare-multitenant"].name
|
|
255
238
|
}
|
|
256
239
|
]
|
|
257
240
|
}
|
|
258
241
|
])).setupType;
|
|
259
|
-
const g =
|
|
242
|
+
const g = n[e];
|
|
260
243
|
i.mkdirSync(t, { recursive: !0 }), i.writeFileSync(
|
|
261
244
|
f.join(t, "package.json"),
|
|
262
245
|
JSON.stringify(g.packageJson(o), null, 2)
|
|
@@ -265,9 +248,9 @@ b.version("1.0.0").description("Create a new AuthHero project").argument("[proje
|
|
|
265
248
|
import.meta.url.replace("file://", "").replace("/create-authhero.js", ""),
|
|
266
249
|
g.templateDir
|
|
267
250
|
);
|
|
268
|
-
if (i.existsSync(k) ?
|
|
269
|
-
const
|
|
270
|
-
i.writeFileSync(f.join(t,
|
|
251
|
+
if (i.existsSync(k) ? A(k, t) : (console.error(`❌ Template directory not found: ${k}`), process.exit(1)), e === "local") {
|
|
252
|
+
const l = $();
|
|
253
|
+
i.writeFileSync(f.join(t, "src/seed.ts"), l);
|
|
271
254
|
}
|
|
272
255
|
console.log(
|
|
273
256
|
`
|
|
@@ -275,7 +258,7 @@ b.version("1.0.0").description("Create a new AuthHero project").argument("[proje
|
|
|
275
258
|
`
|
|
276
259
|
);
|
|
277
260
|
let h;
|
|
278
|
-
if (
|
|
261
|
+
if (a.skipInstall ? h = !1 : s ? h = !0 : h = (await c.prompt([
|
|
279
262
|
{
|
|
280
263
|
type: "confirm",
|
|
281
264
|
name: "shouldInstall",
|
|
@@ -283,8 +266,10 @@ b.version("1.0.0").description("Create a new AuthHero project").argument("[proje
|
|
|
283
266
|
default: !0
|
|
284
267
|
}
|
|
285
268
|
])).shouldInstall, h) {
|
|
286
|
-
let
|
|
287
|
-
|
|
269
|
+
let l;
|
|
270
|
+
a.packageManager ? (["npm", "yarn", "pnpm", "bun"].includes(a.packageManager) || (console.error(
|
|
271
|
+
`❌ Invalid package manager: ${a.packageManager}`
|
|
272
|
+
), console.error("Valid options: npm, yarn, pnpm, bun"), process.exit(1)), l = a.packageManager) : s ? l = "npm" : l = (await c.prompt([
|
|
288
273
|
{
|
|
289
274
|
type: "list",
|
|
290
275
|
name: "packageManager",
|
|
@@ -298,18 +283,18 @@ b.version("1.0.0").description("Create a new AuthHero project").argument("[proje
|
|
|
298
283
|
default: "npm"
|
|
299
284
|
}
|
|
300
285
|
])).packageManager, console.log(`
|
|
301
|
-
📦 Installing dependencies with ${
|
|
286
|
+
📦 Installing dependencies with ${l}...
|
|
302
287
|
`);
|
|
303
288
|
try {
|
|
304
|
-
const
|
|
305
|
-
await v(
|
|
289
|
+
const p = l === "pnpm" ? "pnpm install --ignore-workspace" : `${l} install`;
|
|
290
|
+
await v(p, t), e === "local" && (console.log(`
|
|
306
291
|
🔧 Building native modules...
|
|
307
292
|
`), await v("npm rebuild better-sqlite3", t)), console.log(`
|
|
308
293
|
✅ Dependencies installed successfully!
|
|
309
294
|
`);
|
|
310
|
-
let w =
|
|
311
|
-
if (
|
|
312
|
-
|
|
295
|
+
let w = a.remote ? "remote" : "local";
|
|
296
|
+
if (e === "local" || e === "cloudflare-simple" || e === "cloudflare-multitenant") {
|
|
297
|
+
(e === "cloudflare-simple" || e === "cloudflare-multitenant") && !s && !a.remote && (w = (await c.prompt([
|
|
313
298
|
{
|
|
314
299
|
type: "list",
|
|
315
300
|
name: "mode",
|
|
@@ -330,7 +315,7 @@ b.version("1.0.0").description("Create a new AuthHero project").argument("[proje
|
|
|
330
315
|
}
|
|
331
316
|
])).mode);
|
|
332
317
|
let u;
|
|
333
|
-
if (
|
|
318
|
+
if (a.skipMigrate && a.skipSeed ? u = !1 : s ? u = !a.skipMigrate || !a.skipSeed : u = (await c.prompt([
|
|
334
319
|
{
|
|
335
320
|
type: "confirm",
|
|
336
321
|
name: "shouldSetup",
|
|
@@ -338,55 +323,55 @@ b.version("1.0.0").description("Create a new AuthHero project").argument("[proje
|
|
|
338
323
|
default: !0
|
|
339
324
|
}
|
|
340
325
|
])).shouldSetup, u) {
|
|
341
|
-
let
|
|
342
|
-
if (
|
|
343
|
-
username:
|
|
344
|
-
password:
|
|
345
|
-
}, console.log(`Using admin email: ${
|
|
326
|
+
let d;
|
|
327
|
+
if (a.email && a.password ? (/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(a.email) || (console.error("❌ Invalid email address provided"), process.exit(1)), a.password.length < 8 && (console.error("❌ Password must be at least 8 characters"), process.exit(1)), d = {
|
|
328
|
+
username: a.email,
|
|
329
|
+
password: a.password
|
|
330
|
+
}, console.log(`Using admin email: ${a.email}`)) : d = await c.prompt([
|
|
346
331
|
{
|
|
347
332
|
type: "input",
|
|
348
333
|
name: "username",
|
|
349
334
|
message: "Admin email:",
|
|
350
335
|
default: "admin@example.com",
|
|
351
|
-
validate: (
|
|
336
|
+
validate: (m) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(m) || "Please enter a valid email address"
|
|
352
337
|
},
|
|
353
338
|
{
|
|
354
339
|
type: "password",
|
|
355
340
|
name: "password",
|
|
356
341
|
message: "Admin password:",
|
|
357
342
|
mask: "*",
|
|
358
|
-
validate: (
|
|
343
|
+
validate: (m) => m.length < 8 ? "Password must be at least 8 characters" : !0
|
|
359
344
|
}
|
|
360
|
-
]), !
|
|
345
|
+
]), !a.skipMigrate) {
|
|
361
346
|
console.log(`
|
|
362
347
|
🔄 Running migrations...
|
|
363
348
|
`);
|
|
364
|
-
const
|
|
365
|
-
await v(
|
|
349
|
+
const m = (e === "cloudflare-simple" || e === "cloudflare-multitenant") && w === "remote" ? `${l} run db:migrate:remote` : `${l} run migrate`;
|
|
350
|
+
await v(m, t);
|
|
366
351
|
}
|
|
367
|
-
if (!
|
|
352
|
+
if (!a.skipSeed)
|
|
368
353
|
if (console.log(`
|
|
369
354
|
🌱 Seeding database...
|
|
370
|
-
`),
|
|
355
|
+
`), e === "local")
|
|
371
356
|
await S(
|
|
372
|
-
`${
|
|
357
|
+
`${l} run seed`,
|
|
373
358
|
t,
|
|
374
359
|
{
|
|
375
|
-
ADMIN_EMAIL:
|
|
376
|
-
ADMIN_PASSWORD:
|
|
360
|
+
ADMIN_EMAIL: d.username,
|
|
361
|
+
ADMIN_PASSWORD: d.password
|
|
377
362
|
}
|
|
378
363
|
);
|
|
379
364
|
else {
|
|
380
|
-
const
|
|
381
|
-
await S(
|
|
382
|
-
ADMIN_EMAIL:
|
|
383
|
-
ADMIN_PASSWORD:
|
|
365
|
+
const m = w === "remote" ? `${l} run seed:remote` : `${l} run seed:local`;
|
|
366
|
+
await S(m, t, {
|
|
367
|
+
ADMIN_EMAIL: d.username,
|
|
368
|
+
ADMIN_PASSWORD: d.password
|
|
384
369
|
});
|
|
385
370
|
}
|
|
386
371
|
}
|
|
387
372
|
}
|
|
388
373
|
let y;
|
|
389
|
-
if (
|
|
374
|
+
if (a.skipStart || s ? y = !1 : y = (await c.prompt([
|
|
390
375
|
{
|
|
391
376
|
type: "confirm",
|
|
392
377
|
name: "shouldStart",
|
|
@@ -394,30 +379,34 @@ b.version("1.0.0").description("Create a new AuthHero project").argument("[proje
|
|
|
394
379
|
default: !0
|
|
395
380
|
}
|
|
396
381
|
])).shouldStart, y) {
|
|
397
|
-
console.log(
|
|
382
|
+
console.log(
|
|
383
|
+
`
|
|
398
384
|
🚀 Starting development server on https://localhost:3000 ...
|
|
399
|
-
`
|
|
400
|
-
|
|
385
|
+
`
|
|
386
|
+
);
|
|
387
|
+
const u = (e === "cloudflare-simple" || e === "cloudflare-multitenant") && w === "remote" ? `${l} run dev:remote` : `${l} run dev`;
|
|
401
388
|
await v(u, t);
|
|
402
389
|
}
|
|
403
|
-
|
|
390
|
+
s && !y && (console.log(`
|
|
404
391
|
✅ Setup complete!`), console.log(`
|
|
405
|
-
To start the development server:`), console.log(` cd ${o}`), console.log(
|
|
406
|
-
|
|
407
|
-
|
|
392
|
+
To start the development server:`), console.log(` cd ${o}`), console.log((e === "cloudflare-simple" || e === "cloudflare-multitenant") && w === "remote" ? " npm run dev:remote" : " npm run dev"), (e === "cloudflare-simple" || e === "cloudflare-multitenant") && console.log(
|
|
393
|
+
`
|
|
394
|
+
Server will be available at: https://localhost:3000`
|
|
395
|
+
));
|
|
396
|
+
} catch (p) {
|
|
408
397
|
console.error(`
|
|
409
|
-
❌ An error occurred:`,
|
|
398
|
+
❌ An error occurred:`, p), process.exit(1);
|
|
410
399
|
}
|
|
411
400
|
}
|
|
412
|
-
h || (console.log("Next steps:"), console.log(` cd ${o}`),
|
|
401
|
+
h || (console.log("Next steps:"), console.log(` cd ${o}`), e === "local" ? (console.log(" npm install"), console.log(" npm run migrate"), console.log(
|
|
413
402
|
" ADMIN_EMAIL=admin@example.com ADMIN_PASSWORD=yourpassword npm run seed"
|
|
414
|
-
), console.log(" npm run dev")) :
|
|
403
|
+
), console.log(" npm run dev")) : (e === "cloudflare-simple" || e === "cloudflare-multitenant") && (console.log(" npm install"), console.log(
|
|
415
404
|
" npm run migrate # or npm run db:migrate:remote for production"
|
|
416
405
|
), console.log(
|
|
417
406
|
" ADMIN_EMAIL=admin@example.com ADMIN_PASSWORD=yourpassword npm run seed"
|
|
418
407
|
), console.log(" npm run dev # or npm run dev:remote for production"), console.log(`
|
|
419
|
-
Server will be available at: https://localhost:3000`))
|
|
408
|
+
Server will be available at: https://localhost:3000`)), console.log(`
|
|
420
409
|
For more information, visit: https://authhero.net/docs
|
|
421
410
|
`));
|
|
422
411
|
});
|
|
423
|
-
|
|
412
|
+
D.parse(process.argv);
|