create-authhero 0.6.0 → 0.8.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-simple/README.md +109 -10
- package/dist/cloudflare-simple/drizzle.config.ts +8 -0
- package/dist/cloudflare-simple/migrations/0000_init.sql +782 -0
- package/dist/cloudflare-simple/migrations/meta/0000_snapshot.json +5325 -0
- package/dist/cloudflare-simple/migrations/meta/_journal.json +13 -0
- package/dist/cloudflare-simple/seed-helper.js +75 -0
- package/dist/cloudflare-simple/src/app.ts +10 -0
- package/dist/cloudflare-simple/src/db/schema.ts +845 -0
- package/dist/cloudflare-simple/src/index.ts +32 -14
- package/dist/cloudflare-simple/src/seed.ts +64 -0
- package/dist/cloudflare-simple/wrangler.toml +2 -0
- package/dist/create-authhero.js +177 -98
- package/index.js +3 -0
- package/package.json +4 -3
|
@@ -1,27 +1,45 @@
|
|
|
1
|
-
import { OpenAPIHono } from "@hono/zod-openapi";
|
|
2
1
|
import { D1Dialect } from "kysely-d1";
|
|
3
2
|
import { Kysely } from "kysely";
|
|
4
3
|
import createAdapters from "@authhero/kysely-adapter";
|
|
5
4
|
import createApp from "./app";
|
|
6
5
|
import { Env } from "./types";
|
|
7
|
-
import { AuthHeroConfig
|
|
8
|
-
|
|
9
|
-
let app: OpenAPIHono<{ Bindings: Bindings; Variables: Variables }> | undefined;
|
|
6
|
+
import { AuthHeroConfig } from "authhero";
|
|
10
7
|
|
|
11
8
|
export default {
|
|
12
9
|
async fetch(request: Request, env: Env): Promise<Response> {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
10
|
+
const url = new URL(request.url);
|
|
11
|
+
const issuer = `${url.protocol}//${url.host}/`;
|
|
12
|
+
|
|
13
|
+
// Get the origin from the request for dynamic CORS
|
|
14
|
+
const origin = request.headers.get("Origin") || "";
|
|
15
|
+
|
|
16
|
+
const dialect = new D1Dialect({ database: env.AUTH_DB });
|
|
17
|
+
const db = new Kysely<any>({ dialect });
|
|
18
|
+
const dataAdapter = createAdapters(db);
|
|
19
|
+
|
|
20
|
+
const config: AuthHeroConfig = {
|
|
21
|
+
dataAdapter,
|
|
22
|
+
// Allow CORS from common development origins
|
|
23
|
+
allowedOrigins: [
|
|
24
|
+
"http://localhost:5173",
|
|
25
|
+
"http://localhost:3000",
|
|
26
|
+
"https://localhost:5173",
|
|
27
|
+
"https://localhost:3000",
|
|
28
|
+
"https://manage.authhero.net",
|
|
29
|
+
"https://local.authhero.net",
|
|
30
|
+
// Also allow the requesting origin in development
|
|
31
|
+
origin,
|
|
32
|
+
].filter(Boolean),
|
|
33
|
+
};
|
|
17
34
|
|
|
18
|
-
|
|
19
|
-
dataAdapter,
|
|
20
|
-
};
|
|
35
|
+
const app = createApp(config);
|
|
21
36
|
|
|
22
|
-
|
|
23
|
-
|
|
37
|
+
// Pass the issuer via env bindings
|
|
38
|
+
const envWithIssuer = {
|
|
39
|
+
...env,
|
|
40
|
+
ISSUER: issuer,
|
|
41
|
+
};
|
|
24
42
|
|
|
25
|
-
return app.fetch(request,
|
|
43
|
+
return app.fetch(request, envWithIssuer);
|
|
26
44
|
},
|
|
27
45
|
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { D1Dialect } from "kysely-d1";
|
|
2
|
+
import { Kysely } from "kysely";
|
|
3
|
+
import createAdapters from "@authhero/kysely-adapter";
|
|
4
|
+
import { seed } from "authhero";
|
|
5
|
+
|
|
6
|
+
interface Env {
|
|
7
|
+
AUTH_DB: D1Database;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export default {
|
|
11
|
+
async fetch(request: Request, env: Env): Promise<Response> {
|
|
12
|
+
const url = new URL(request.url);
|
|
13
|
+
const adminEmail = url.searchParams.get("email");
|
|
14
|
+
const adminPassword = url.searchParams.get("password");
|
|
15
|
+
|
|
16
|
+
if (!adminEmail || !adminPassword) {
|
|
17
|
+
return new Response(
|
|
18
|
+
JSON.stringify({
|
|
19
|
+
error: "Missing email or password query parameters",
|
|
20
|
+
usage: "/?email=admin@example.com&password=yourpassword",
|
|
21
|
+
}),
|
|
22
|
+
{
|
|
23
|
+
status: 400,
|
|
24
|
+
headers: { "Content-Type": "application/json" },
|
|
25
|
+
},
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
const dialect = new D1Dialect({ database: env.AUTH_DB });
|
|
31
|
+
const db = new Kysely<any>({ dialect });
|
|
32
|
+
const adapters = createAdapters(db);
|
|
33
|
+
|
|
34
|
+
const result = await seed(adapters, {
|
|
35
|
+
adminEmail,
|
|
36
|
+
adminPassword,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
return new Response(
|
|
40
|
+
JSON.stringify({
|
|
41
|
+
success: true,
|
|
42
|
+
message: "Database seeded successfully",
|
|
43
|
+
result,
|
|
44
|
+
}),
|
|
45
|
+
{
|
|
46
|
+
status: 200,
|
|
47
|
+
headers: { "Content-Type": "application/json" },
|
|
48
|
+
},
|
|
49
|
+
);
|
|
50
|
+
} catch (error) {
|
|
51
|
+
console.error("Seed error:", error);
|
|
52
|
+
return new Response(
|
|
53
|
+
JSON.stringify({
|
|
54
|
+
error: "Failed to seed database",
|
|
55
|
+
message: error instanceof Error ? error.message : String(error),
|
|
56
|
+
}),
|
|
57
|
+
{
|
|
58
|
+
status: 500,
|
|
59
|
+
headers: { "Content-Type": "application/json" },
|
|
60
|
+
},
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
};
|
|
@@ -9,12 +9,14 @@ compatibility_date = "2024-11-20"
|
|
|
9
9
|
# binding = "AUTH_DB"
|
|
10
10
|
# database_name = "authhero-db"
|
|
11
11
|
# database_id = "<YOUR_DATABASE_ID>"
|
|
12
|
+
# migrations_dir = "migrations"
|
|
12
13
|
|
|
13
14
|
# For local development, you can use a local D1 database:
|
|
14
15
|
[[d1_databases]]
|
|
15
16
|
binding = "AUTH_DB"
|
|
16
17
|
database_name = "authhero-db"
|
|
17
18
|
database_id = "local"
|
|
19
|
+
migrations_dir = "migrations"
|
|
18
20
|
|
|
19
21
|
# Optional: Enable observability
|
|
20
22
|
# [observability]
|
package/dist/create-authhero.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { Command as
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import { spawn as
|
|
7
|
-
const
|
|
2
|
+
import { Command as I } from "commander";
|
|
3
|
+
import m from "inquirer";
|
|
4
|
+
import i from "fs";
|
|
5
|
+
import f from "path";
|
|
6
|
+
import { spawn as A } from "child_process";
|
|
7
|
+
const b = new I(), l = {
|
|
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: (n) => ({
|
|
13
|
+
name: n,
|
|
14
14
|
version: "1.0.0",
|
|
15
15
|
type: "module",
|
|
16
16
|
scripts: {
|
|
@@ -42,16 +42,22 @@ const w = new b(), r = {
|
|
|
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: (n) => ({
|
|
46
|
+
name: n,
|
|
47
47
|
version: "1.0.0",
|
|
48
48
|
type: "module",
|
|
49
49
|
scripts: {
|
|
50
|
-
dev: "wrangler dev",
|
|
50
|
+
"dev:local": "wrangler dev --port 3000 --local-protocol https",
|
|
51
|
+
"dev:remote": "wrangler dev --port 3000 --local-protocol https --remote",
|
|
52
|
+
dev: "wrangler dev --port 3000 --local-protocol https",
|
|
51
53
|
deploy: "wrangler deploy",
|
|
52
|
-
"db:migrate": "wrangler d1 migrations apply AUTH_DB --local",
|
|
53
|
-
"db:migrate:
|
|
54
|
-
|
|
54
|
+
"db:migrate:local": "wrangler d1 migrations apply AUTH_DB --local",
|
|
55
|
+
"db:migrate:remote": "wrangler d1 migrations apply AUTH_DB --remote",
|
|
56
|
+
migrate: "wrangler d1 migrations apply AUTH_DB --local",
|
|
57
|
+
"db:generate": "drizzle-kit generate",
|
|
58
|
+
"seed:local": "node seed-helper.js",
|
|
59
|
+
"seed:remote": "node seed-helper.js '' '' remote",
|
|
60
|
+
seed: "node seed-helper.js"
|
|
55
61
|
},
|
|
56
62
|
dependencies: {
|
|
57
63
|
"@authhero/kysely-adapter": "latest",
|
|
@@ -64,18 +70,20 @@ const w = new b(), r = {
|
|
|
64
70
|
},
|
|
65
71
|
devDependencies: {
|
|
66
72
|
"@cloudflare/workers-types": "^4.0.0",
|
|
73
|
+
"drizzle-kit": "^0.31.0",
|
|
74
|
+
"drizzle-orm": "^0.44.0",
|
|
67
75
|
typescript: "^5.5.0",
|
|
68
76
|
wrangler: "^3.0.0"
|
|
69
77
|
}
|
|
70
78
|
}),
|
|
71
|
-
seedFile: "seed.
|
|
79
|
+
seedFile: "seed.ts"
|
|
72
80
|
},
|
|
73
81
|
"cloudflare-multitenant": {
|
|
74
82
|
name: "Cloudflare Multi-Tenant (Production)",
|
|
75
83
|
description: "Production-grade multi-tenant setup with per-tenant D1 databases and Analytics Engine",
|
|
76
84
|
templateDir: "cloudflare-multitenant",
|
|
77
|
-
packageJson: (
|
|
78
|
-
name:
|
|
85
|
+
packageJson: (n) => ({
|
|
86
|
+
name: n,
|
|
79
87
|
version: "1.0.0",
|
|
80
88
|
type: "module",
|
|
81
89
|
scripts: {
|
|
@@ -106,14 +114,14 @@ const w = new b(), r = {
|
|
|
106
114
|
seedFile: "seed.sql"
|
|
107
115
|
}
|
|
108
116
|
};
|
|
109
|
-
function
|
|
110
|
-
|
|
111
|
-
const
|
|
112
|
-
|
|
117
|
+
function D(n, e) {
|
|
118
|
+
i.readdirSync(n).forEach((o) => {
|
|
119
|
+
const t = f.join(n, o), a = f.join(e, o);
|
|
120
|
+
i.lstatSync(t).isDirectory() ? (i.mkdirSync(a, { recursive: !0 }), D(t, a)) : i.copyFileSync(t, a);
|
|
113
121
|
});
|
|
114
122
|
}
|
|
115
|
-
function
|
|
116
|
-
if (
|
|
123
|
+
function $(n) {
|
|
124
|
+
if (n === "local")
|
|
117
125
|
return `import { SqliteDialect, Kysely } from "kysely";
|
|
118
126
|
import Database from "better-sqlite3";
|
|
119
127
|
import createAdapters from "@authhero/kysely-adapter";
|
|
@@ -147,7 +155,7 @@ async function main() {
|
|
|
147
155
|
main().catch(console.error);
|
|
148
156
|
`;
|
|
149
157
|
{
|
|
150
|
-
const e = (/* @__PURE__ */ new Date()).toISOString(),
|
|
158
|
+
const e = (/* @__PURE__ */ new Date()).toISOString(), r = "default";
|
|
151
159
|
return `-- Seed file for AuthHero
|
|
152
160
|
--
|
|
153
161
|
-- IMPORTANT: This SQL file creates the basic structure but the password
|
|
@@ -156,15 +164,15 @@ main().catch(console.error);
|
|
|
156
164
|
|
|
157
165
|
-- Create default tenant
|
|
158
166
|
INSERT OR IGNORE INTO tenants (id, friendly_name, audience, sender_email, sender_name, created_at, updated_at)
|
|
159
|
-
VALUES ('${
|
|
167
|
+
VALUES ('${r}', 'Default Tenant', 'https://api.example.com', 'noreply@example.com', 'AuthHero', '${e}', '${e}');
|
|
160
168
|
|
|
161
169
|
-- Create password connection
|
|
162
170
|
INSERT OR IGNORE INTO connections (id, tenant_id, name, strategy, options, created_at, updated_at)
|
|
163
|
-
VALUES ('conn_default', '${
|
|
171
|
+
VALUES ('conn_default', '${r}', 'Username-Password-Authentication', 'Username-Password-Authentication', '{}', '${e}', '${e}');
|
|
164
172
|
|
|
165
173
|
-- Create default client
|
|
166
174
|
INSERT OR IGNORE INTO clients (client_id, tenant_id, name, callbacks, allowed_origins, web_origins, connections, created_at, updated_at)
|
|
167
|
-
VALUES ('default', '${
|
|
175
|
+
VALUES ('default', '${r}', 'Default Application', '["https://manage.authhero.net/auth-callback","https://local.authhero.net/auth-callback"]', '[]', '[]', '["Username-Password-Authentication"]', '${e}', '${e}');
|
|
168
176
|
|
|
169
177
|
-- Note: Admin user and password should be created via the management API
|
|
170
178
|
-- or using a TypeScript seed script with proper bcrypt hashing.
|
|
@@ -172,97 +180,111 @@ VALUES ('default', '${a}', 'Default Application', '["https://manage.authhero.net
|
|
|
172
180
|
`;
|
|
173
181
|
}
|
|
174
182
|
}
|
|
175
|
-
function
|
|
176
|
-
return new Promise((
|
|
177
|
-
const
|
|
183
|
+
function v(n, e) {
|
|
184
|
+
return new Promise((r, o) => {
|
|
185
|
+
const t = A(n, [], {
|
|
178
186
|
cwd: e,
|
|
179
187
|
shell: !0,
|
|
180
188
|
stdio: "inherit"
|
|
181
189
|
});
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
}),
|
|
190
|
+
t.on("close", (a) => {
|
|
191
|
+
a === 0 ? r() : o(new Error(`Command failed with exit code ${a}`));
|
|
192
|
+
}), t.on("error", o);
|
|
185
193
|
});
|
|
186
194
|
}
|
|
187
|
-
function
|
|
188
|
-
return new Promise((
|
|
189
|
-
const
|
|
195
|
+
function S(n, e, r) {
|
|
196
|
+
return new Promise((o, t) => {
|
|
197
|
+
const a = A(n, [], {
|
|
190
198
|
cwd: e,
|
|
191
199
|
shell: !0,
|
|
192
200
|
stdio: "inherit",
|
|
193
|
-
env: { ...process.env, ...
|
|
201
|
+
env: { ...process.env, ...r }
|
|
194
202
|
});
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
}),
|
|
203
|
+
a.on("close", (g) => {
|
|
204
|
+
g === 0 ? o() : t(new Error(`Command failed with exit code ${g}`));
|
|
205
|
+
}), a.on("error", t);
|
|
198
206
|
});
|
|
199
207
|
}
|
|
200
|
-
|
|
208
|
+
b.version("1.0.0").description("Create a new AuthHero project").argument("[project-name]", "name of the project").option(
|
|
209
|
+
"-t, --template <type>",
|
|
210
|
+
"template type: local, cloudflare-simple, or cloudflare-multitenant"
|
|
211
|
+
).option("-e, --email <email>", "admin email address").option("-p, --password <password>", "admin password (min 8 characters)").option(
|
|
212
|
+
"--package-manager <pm>",
|
|
213
|
+
"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 (n, e) => {
|
|
215
|
+
const r = e.yes === !0;
|
|
201
216
|
console.log(`
|
|
202
217
|
🔐 Welcome to AuthHero!
|
|
203
|
-
`)
|
|
218
|
+
`);
|
|
219
|
+
let o = n;
|
|
220
|
+
o || (r ? (o = "auth-server", console.log(`Using default project name: ${o}`)) : o = (await m.prompt([
|
|
204
221
|
{
|
|
205
222
|
type: "input",
|
|
206
223
|
name: "projectName",
|
|
207
224
|
message: "Project name:",
|
|
208
225
|
default: "auth-server",
|
|
209
|
-
validate: (
|
|
226
|
+
validate: (d) => d !== "" || "Project name cannot be empty"
|
|
210
227
|
}
|
|
211
228
|
])).projectName);
|
|
212
|
-
const
|
|
213
|
-
|
|
214
|
-
|
|
229
|
+
const t = f.join(process.cwd(), o);
|
|
230
|
+
i.existsSync(t) && (console.error(`❌ Project "${o}" already exists.`), process.exit(1));
|
|
231
|
+
let a;
|
|
232
|
+
e.template ? (["local", "cloudflare-simple", "cloudflare-multitenant"].includes(e.template) || (console.error(`❌ Invalid template: ${e.template}`), console.error("Valid options: local, cloudflare-simple, cloudflare-multitenant"), process.exit(1)), a = e.template, console.log(`Using template: ${l[a].name}`)) : a = (await m.prompt([
|
|
215
233
|
{
|
|
216
234
|
type: "list",
|
|
217
235
|
name: "setupType",
|
|
218
236
|
message: "Select your setup type:",
|
|
219
237
|
choices: [
|
|
220
238
|
{
|
|
221
|
-
name: `${
|
|
222
|
-
${
|
|
239
|
+
name: `${l.local.name}
|
|
240
|
+
${l.local.description}`,
|
|
223
241
|
value: "local",
|
|
224
|
-
short:
|
|
242
|
+
short: l.local.name
|
|
225
243
|
},
|
|
226
244
|
{
|
|
227
|
-
name: `${
|
|
228
|
-
${
|
|
245
|
+
name: `${l["cloudflare-simple"].name}
|
|
246
|
+
${l["cloudflare-simple"].description}`,
|
|
229
247
|
value: "cloudflare-simple",
|
|
230
|
-
short:
|
|
248
|
+
short: l["cloudflare-simple"].name
|
|
231
249
|
},
|
|
232
250
|
{
|
|
233
|
-
name: `${
|
|
234
|
-
${
|
|
251
|
+
name: `${l["cloudflare-multitenant"].name}
|
|
252
|
+
${l["cloudflare-multitenant"].description}`,
|
|
235
253
|
value: "cloudflare-multitenant",
|
|
236
|
-
short:
|
|
254
|
+
short: l["cloudflare-multitenant"].name
|
|
237
255
|
}
|
|
238
256
|
]
|
|
239
257
|
}
|
|
240
|
-
])
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
258
|
+
])).setupType;
|
|
259
|
+
const g = l[a];
|
|
260
|
+
i.mkdirSync(t, { recursive: !0 }), i.writeFileSync(
|
|
261
|
+
f.join(t, "package.json"),
|
|
262
|
+
JSON.stringify(g.packageJson(o), null, 2)
|
|
244
263
|
);
|
|
245
|
-
const
|
|
264
|
+
const k = f.join(
|
|
246
265
|
import.meta.url.replace("file://", "").replace("/create-authhero.js", ""),
|
|
247
|
-
|
|
266
|
+
g.templateDir
|
|
248
267
|
);
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
268
|
+
if (i.existsSync(k) ? D(k, t) : (console.error(`❌ Template directory not found: ${k}`), process.exit(1)), a === "local" || a === "cloudflare-multitenant") {
|
|
269
|
+
const s = $(a), d = a === "local" ? "src/seed.ts" : "seed.sql";
|
|
270
|
+
i.writeFileSync(f.join(t, d), s);
|
|
271
|
+
}
|
|
272
|
+
console.log(
|
|
252
273
|
`
|
|
253
|
-
✅ Project "${
|
|
274
|
+
✅ Project "${o}" has been created with ${g.name} setup!
|
|
254
275
|
`
|
|
255
276
|
);
|
|
256
|
-
|
|
277
|
+
let h;
|
|
278
|
+
if (e.skipInstall ? h = !1 : r ? h = !0 : h = (await m.prompt([
|
|
257
279
|
{
|
|
258
280
|
type: "confirm",
|
|
259
281
|
name: "shouldInstall",
|
|
260
282
|
message: "Would you like to install dependencies now?",
|
|
261
283
|
default: !0
|
|
262
284
|
}
|
|
263
|
-
])
|
|
264
|
-
|
|
265
|
-
|
|
285
|
+
])).shouldInstall, h) {
|
|
286
|
+
let s;
|
|
287
|
+
e.packageManager ? (["npm", "yarn", "pnpm", "bun"].includes(e.packageManager) || (console.error(`❌ Invalid package manager: ${e.packageManager}`), console.error("Valid options: npm, yarn, pnpm, bun"), process.exit(1)), s = e.packageManager) : r ? s = "npm" : s = (await m.prompt([
|
|
266
288
|
{
|
|
267
289
|
type: "list",
|
|
268
290
|
name: "packageManager",
|
|
@@ -275,70 +297,127 @@ w.version("1.0.0").description("Create a new AuthHero project").argument("[proje
|
|
|
275
297
|
],
|
|
276
298
|
default: "npm"
|
|
277
299
|
}
|
|
278
|
-
])
|
|
279
|
-
|
|
280
|
-
📦 Installing dependencies with ${i}...
|
|
300
|
+
])).packageManager, console.log(`
|
|
301
|
+
📦 Installing dependencies with ${s}...
|
|
281
302
|
`);
|
|
282
303
|
try {
|
|
283
|
-
const
|
|
284
|
-
|
|
304
|
+
const d = s === "pnpm" ? "pnpm install --ignore-workspace" : `${s} install`;
|
|
305
|
+
await v(d, t), a === "local" && (console.log(`
|
|
285
306
|
🔧 Building native modules...
|
|
286
|
-
`), await
|
|
307
|
+
`), await v("npm rebuild better-sqlite3", t)), console.log(`
|
|
287
308
|
✅ Dependencies installed successfully!
|
|
288
|
-
`)
|
|
289
|
-
|
|
309
|
+
`);
|
|
310
|
+
let w = e.remote ? "remote" : "local";
|
|
311
|
+
if (a === "local" || a === "cloudflare-simple") {
|
|
312
|
+
a === "cloudflare-simple" && !r && !e.remote && (w = (await m.prompt([
|
|
313
|
+
{
|
|
314
|
+
type: "list",
|
|
315
|
+
name: "mode",
|
|
316
|
+
message: "Would you like to run in local mode or remote mode?",
|
|
317
|
+
choices: [
|
|
318
|
+
{
|
|
319
|
+
name: "Local (using local D1 database)",
|
|
320
|
+
value: "local",
|
|
321
|
+
short: "Local"
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
name: "Remote (using production D1 database)",
|
|
325
|
+
value: "remote",
|
|
326
|
+
short: "Remote"
|
|
327
|
+
}
|
|
328
|
+
],
|
|
329
|
+
default: "local"
|
|
330
|
+
}
|
|
331
|
+
])).mode);
|
|
332
|
+
let u;
|
|
333
|
+
if (e.skipMigrate && e.skipSeed ? u = !1 : r ? u = !e.skipMigrate || !e.skipSeed : u = (await m.prompt([
|
|
290
334
|
{
|
|
291
335
|
type: "confirm",
|
|
292
336
|
name: "shouldSetup",
|
|
293
337
|
message: "Would you like to run migrations and seed the database?",
|
|
294
338
|
default: !0
|
|
295
339
|
}
|
|
296
|
-
])
|
|
297
|
-
|
|
298
|
-
|
|
340
|
+
])).shouldSetup, u) {
|
|
341
|
+
let c;
|
|
342
|
+
if (e.email && e.password ? (/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e.email) || (console.error("❌ Invalid email address provided"), process.exit(1)), e.password.length < 8 && (console.error("❌ Password must be at least 8 characters"), process.exit(1)), c = {
|
|
343
|
+
username: e.email,
|
|
344
|
+
password: e.password
|
|
345
|
+
}, console.log(`Using admin email: ${e.email}`)) : c = await m.prompt([
|
|
299
346
|
{
|
|
300
347
|
type: "input",
|
|
301
348
|
name: "username",
|
|
302
349
|
message: "Admin email:",
|
|
303
350
|
default: "admin@example.com",
|
|
304
|
-
validate: (
|
|
351
|
+
validate: (p) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(p) || "Please enter a valid email address"
|
|
305
352
|
},
|
|
306
353
|
{
|
|
307
354
|
type: "password",
|
|
308
355
|
name: "password",
|
|
309
356
|
message: "Admin password:",
|
|
310
357
|
mask: "*",
|
|
311
|
-
validate: (
|
|
358
|
+
validate: (p) => p.length < 8 ? "Password must be at least 8 characters" : !0
|
|
312
359
|
}
|
|
313
|
-
])
|
|
314
|
-
|
|
360
|
+
]), !e.skipMigrate) {
|
|
361
|
+
console.log(`
|
|
315
362
|
🔄 Running migrations...
|
|
316
|
-
`)
|
|
363
|
+
`);
|
|
364
|
+
const p = a === "cloudflare-simple" && w === "remote" ? `${s} run db:migrate:remote` : `${s} run migrate`;
|
|
365
|
+
await v(p, t);
|
|
366
|
+
}
|
|
367
|
+
if (!e.skipSeed)
|
|
368
|
+
if (console.log(`
|
|
317
369
|
🌱 Seeding database...
|
|
318
|
-
`),
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
370
|
+
`), a === "local")
|
|
371
|
+
await S(
|
|
372
|
+
`${s} run seed`,
|
|
373
|
+
t,
|
|
374
|
+
{
|
|
375
|
+
ADMIN_EMAIL: c.username,
|
|
376
|
+
ADMIN_PASSWORD: c.password
|
|
377
|
+
}
|
|
378
|
+
);
|
|
379
|
+
else {
|
|
380
|
+
const p = w === "remote" ? `${s} run seed:remote` : `${s} run seed:local`;
|
|
381
|
+
await S(p, t, {
|
|
382
|
+
ADMIN_EMAIL: c.username,
|
|
383
|
+
ADMIN_PASSWORD: c.password
|
|
384
|
+
});
|
|
385
|
+
}
|
|
322
386
|
}
|
|
323
387
|
}
|
|
324
|
-
|
|
388
|
+
let y;
|
|
389
|
+
if (e.skipStart || r ? y = !1 : y = (await m.prompt([
|
|
325
390
|
{
|
|
326
391
|
type: "confirm",
|
|
327
392
|
name: "shouldStart",
|
|
328
393
|
message: "Would you like to start the development server?",
|
|
329
394
|
default: !0
|
|
330
395
|
}
|
|
331
|
-
])
|
|
332
|
-
|
|
333
|
-
🚀 Starting development server...
|
|
334
|
-
`)
|
|
335
|
-
|
|
396
|
+
])).shouldStart, y) {
|
|
397
|
+
console.log(`
|
|
398
|
+
🚀 Starting development server on https://localhost:3000 ...
|
|
399
|
+
`);
|
|
400
|
+
const u = a === "cloudflare-simple" && w === "remote" ? `${s} run dev:remote` : `${s} run dev`;
|
|
401
|
+
await v(u, t);
|
|
402
|
+
}
|
|
403
|
+
r && !y && (console.log(`
|
|
404
|
+
✅ Setup complete!`), console.log(`
|
|
405
|
+
To start the development server:`), console.log(` cd ${o}`), console.log(a === "cloudflare-simple" && w === "remote" ? " npm run dev:remote" : " npm run dev"), a === "cloudflare-simple" && console.log(`
|
|
406
|
+
Server will be available at: https://localhost:3000`));
|
|
407
|
+
} catch (d) {
|
|
336
408
|
console.error(`
|
|
337
|
-
❌ An error occurred:`,
|
|
409
|
+
❌ An error occurred:`, d), process.exit(1);
|
|
338
410
|
}
|
|
339
411
|
}
|
|
340
|
-
h || (console.log("Next steps:"), console.log(` cd ${
|
|
412
|
+
h || (console.log("Next steps:"), console.log(` cd ${o}`), a === "local" ? (console.log(" npm install"), console.log(" npm run migrate"), console.log(
|
|
413
|
+
" ADMIN_EMAIL=admin@example.com ADMIN_PASSWORD=yourpassword npm run seed"
|
|
414
|
+
), console.log(" npm run dev")) : a === "cloudflare-simple" ? (console.log(" npm install"), console.log(
|
|
415
|
+
" npm run migrate # or npm run db:migrate:remote for production"
|
|
416
|
+
), console.log(
|
|
417
|
+
" ADMIN_EMAIL=admin@example.com ADMIN_PASSWORD=yourpassword npm run seed"
|
|
418
|
+
), console.log(" npm run dev # or npm run dev:remote for production"), console.log(`
|
|
419
|
+
Server will be available at: https://localhost:3000`)) : (console.log(" npm install"), console.log(" npm run db:migrate"), console.log(" npm run seed"), console.log(" npm run dev")), console.log(`
|
|
341
420
|
For more information, visit: https://authhero.net/docs
|
|
342
421
|
`));
|
|
343
422
|
});
|
|
344
|
-
|
|
423
|
+
b.parse(process.argv);
|
package/index.js
ADDED
package/package.json
CHANGED
|
@@ -5,14 +5,15 @@
|
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/markusahlstrand/authhero"
|
|
7
7
|
},
|
|
8
|
-
"version": "0.
|
|
8
|
+
"version": "0.8.0",
|
|
9
9
|
"type": "module",
|
|
10
10
|
"main": "dist/create-authhero.js",
|
|
11
11
|
"bin": {
|
|
12
|
-
"create-authhero": "
|
|
12
|
+
"create-authhero": "index.js"
|
|
13
13
|
},
|
|
14
14
|
"files": [
|
|
15
|
-
"dist"
|
|
15
|
+
"dist",
|
|
16
|
+
"index.js"
|
|
16
17
|
],
|
|
17
18
|
"devDependencies": {
|
|
18
19
|
"@rollup/plugin-commonjs": "^26.0.1",
|