create-authhero 0.42.0 → 0.44.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.
@@ -1,164 +1,187 @@
1
1
  #!/usr/bin/env node
2
- import { Command as R } from "commander";
3
- import m from "inquirer";
4
- import i from "fs";
5
- import a from "path";
6
- import { fileURLToPath as O } from "url";
7
- import { spawn as U } from "child_process";
8
- const N = new R(), p = {
9
- local: {
10
- name: "Local (SQLite)",
11
- description: "Local development setup with SQLite database - great for getting started",
12
- templateDir: "local",
13
- packageJson: (s, e, o, r, n) => {
14
- const t = r ? "workspace:*" : "latest";
15
- return {
16
- name: s,
17
- version: "1.0.0",
18
- type: "module",
19
- scripts: {
20
- dev: "npx tsx watch src/index.ts",
21
- start: "npx tsx src/index.ts",
22
- migrate: "npx tsx src/migrate.ts",
23
- seed: "npx tsx src/seed.ts"
24
- },
25
- dependencies: {
26
- "@authhero/kysely-adapter": t,
27
- ...n && { "@authhero/admin": t },
28
- "@authhero/widget": t,
29
- "@hono/swagger-ui": "^0.5.0",
30
- "@hono/zod-openapi": "^0.19.0",
31
- "@hono/node-server": "latest",
32
- authhero: t,
33
- "better-sqlite3": "latest",
34
- hono: "^4.6.0",
35
- kysely: "latest",
36
- ...e && { "@authhero/multi-tenancy": t },
37
- ...o && { bcryptjs: "latest" }
38
- },
39
- devDependencies: {
40
- "@types/better-sqlite3": "^7.6.0",
41
- "@types/node": "^20.0.0",
42
- tsx: "^4.0.0",
43
- typescript: "^5.5.0"
44
- }
45
- };
46
- },
47
- seedFile: "seed.ts"
48
- },
49
- cloudflare: {
50
- name: "Cloudflare Workers (D1)",
51
- description: "Cloudflare Workers setup with D1 database",
52
- templateDir: "cloudflare",
53
- packageJson: (s, e, o, r, n) => {
54
- const t = r ? "workspace:*" : "latest";
55
- return {
56
- name: s,
57
- version: "1.0.0",
58
- type: "module",
59
- scripts: {
60
- postinstall: "node copy-assets.js",
61
- "copy-assets": "node copy-assets.js",
62
- dev: "node copy-assets.js && wrangler dev --port 3000 --local-protocol https",
63
- "dev:remote": "node copy-assets.js && wrangler dev --port 3000 --local-protocol https --remote --config wrangler.local.toml",
64
- deploy: "node copy-assets.js && wrangler deploy --config wrangler.local.toml",
65
- "db:migrate:local": "wrangler d1 migrations apply AUTH_DB --local",
66
- "db:migrate:remote": "wrangler d1 migrations apply AUTH_DB --remote --config wrangler.local.toml",
67
- migrate: "wrangler d1 migrations apply AUTH_DB --local",
68
- "seed:local": "node seed-helper.js",
69
- "seed:remote": "node seed-helper.js '' '' remote",
70
- seed: "node seed-helper.js",
71
- setup: "cp wrangler.toml wrangler.local.toml && cp .dev.vars.example .dev.vars && echo '✅ Created wrangler.local.toml and .dev.vars - update with your IDs'"
72
- },
73
- dependencies: {
74
- "@authhero/drizzle": t,
75
- "@authhero/kysely-adapter": t,
76
- ...n && { "@authhero/admin": t },
77
- "@authhero/widget": t,
78
- "@hono/swagger-ui": "^0.5.0",
79
- "@hono/zod-openapi": "^0.19.0",
80
- authhero: t,
81
- hono: "^4.6.0",
82
- kysely: "latest",
83
- "kysely-d1": "latest",
84
- ...e && { "@authhero/multi-tenancy": t },
85
- ...o && { bcryptjs: "latest" }
86
- },
87
- devDependencies: {
88
- "@cloudflare/workers-types": "^4.0.0",
89
- "drizzle-kit": "^0.31.0",
90
- "drizzle-orm": "^0.44.0",
91
- typescript: "^5.5.0",
92
- wrangler: "^3.0.0"
93
- }
94
- };
95
- },
96
- seedFile: "seed.ts"
97
- },
98
- "aws-sst": {
99
- name: "AWS SST (Lambda + DynamoDB)",
100
- description: "Serverless AWS deployment with Lambda, DynamoDB, and SST",
101
- templateDir: "aws-sst",
102
- packageJson: (s, e, o, r, n) => {
103
- const t = r ? "workspace:*" : "latest";
104
- return {
105
- name: s,
106
- version: "1.0.0",
107
- type: "module",
108
- scripts: {
109
- dev: "sst dev",
110
- deploy: "sst deploy --stage production",
111
- remove: "sst remove",
112
- seed: "npx tsx src/seed.ts",
113
- "copy-assets": "node copy-assets.js"
114
- },
115
- dependencies: {
116
- "@authhero/aws": t,
117
- ...n && { "@authhero/admin": t },
118
- "@authhero/widget": t,
119
- "@aws-sdk/client-dynamodb": "^3.0.0",
120
- "@aws-sdk/lib-dynamodb": "^3.0.0",
121
- "@hono/swagger-ui": "^0.5.0",
122
- "@hono/zod-openapi": "^0.19.0",
123
- authhero: t,
124
- hono: "^4.6.0",
125
- ...e && { "@authhero/multi-tenancy": t },
126
- ...o && { bcryptjs: "latest" }
127
- },
128
- devDependencies: {
129
- "@types/aws-lambda": "^8.10.0",
130
- "@types/node": "^20.0.0",
131
- sst: "^3.0.0",
132
- tsx: "^4.0.0",
133
- typescript: "^5.5.0"
134
- }
135
- };
136
- },
137
- seedFile: "seed.ts"
138
- }
2
+ import { Command as e } from "commander";
3
+ import t from "inquirer";
4
+ import n from "fs";
5
+ import r from "path";
6
+ import { fileURLToPath as i } from "url";
7
+ import { spawn as a } from "child_process";
8
+ //#region src/index.ts
9
+ var o = new e(), s = {
10
+ local: {
11
+ name: "Local (SQLite)",
12
+ description: "Local development setup with SQLite database - great for getting started",
13
+ templateDir: "local",
14
+ packageJson: (e, t, n, r, i) => {
15
+ let a = r ? "workspace:*" : "latest";
16
+ return {
17
+ name: e,
18
+ version: "1.0.0",
19
+ type: "module",
20
+ scripts: {
21
+ dev: "npx tsx watch src/index.ts",
22
+ start: "npx tsx src/index.ts",
23
+ migrate: "npx tsx src/migrate.ts",
24
+ seed: "npx tsx src/seed.ts"
25
+ },
26
+ dependencies: {
27
+ "@authhero/kysely-adapter": a,
28
+ ...i && { "@authhero/admin": a },
29
+ "@authhero/widget": a,
30
+ "@hono/swagger-ui": "^0.5.0",
31
+ "@hono/zod-openapi": "^0.19.0",
32
+ "@hono/node-server": "latest",
33
+ authhero: a,
34
+ "better-sqlite3": "latest",
35
+ hono: "^4.6.0",
36
+ kysely: "latest",
37
+ ...t && { "@authhero/multi-tenancy": a },
38
+ ...n && { bcryptjs: "latest" }
39
+ },
40
+ devDependencies: {
41
+ "@types/better-sqlite3": "^7.6.0",
42
+ "@types/node": "^20.0.0",
43
+ tsx: "^4.0.0",
44
+ typescript: "^5.5.0"
45
+ }
46
+ };
47
+ },
48
+ seedFile: "seed.ts"
49
+ },
50
+ cloudflare: {
51
+ name: "Cloudflare Workers (D1)",
52
+ description: "Cloudflare Workers setup with D1 database",
53
+ templateDir: "cloudflare",
54
+ packageJson: (e, t, n, r, i) => {
55
+ let a = r ? "workspace:*" : "latest";
56
+ return {
57
+ name: e,
58
+ version: "1.0.0",
59
+ type: "module",
60
+ scripts: {
61
+ postinstall: "node copy-assets.js",
62
+ "copy-assets": "node copy-assets.js",
63
+ dev: "node copy-assets.js && wrangler dev --port 3000 --local-protocol https",
64
+ "dev:remote": "node copy-assets.js && wrangler dev --port 3000 --local-protocol https --remote --config wrangler.local.toml",
65
+ deploy: "node copy-assets.js && wrangler deploy --config wrangler.local.toml",
66
+ "db:migrate:local": "wrangler d1 migrations apply AUTH_DB --local",
67
+ "db:migrate:remote": "wrangler d1 migrations apply AUTH_DB --remote --config wrangler.local.toml",
68
+ migrate: "wrangler d1 migrations apply AUTH_DB --local",
69
+ "seed:local": "node seed-helper.js",
70
+ "seed:remote": "node seed-helper.js '' '' remote",
71
+ seed: "node seed-helper.js",
72
+ setup: "cp wrangler.toml wrangler.local.toml && cp .dev.vars.example .dev.vars && echo '✅ Created wrangler.local.toml and .dev.vars - update with your IDs'"
73
+ },
74
+ dependencies: {
75
+ "@authhero/drizzle": a,
76
+ "@authhero/kysely-adapter": a,
77
+ ...i && { "@authhero/admin": a },
78
+ "@authhero/widget": a,
79
+ "@hono/swagger-ui": "^0.5.0",
80
+ "@hono/zod-openapi": "^0.19.0",
81
+ authhero: a,
82
+ hono: "^4.6.0",
83
+ kysely: "latest",
84
+ "kysely-d1": "latest",
85
+ ...t && { "@authhero/multi-tenancy": a },
86
+ ...n && { bcryptjs: "latest" }
87
+ },
88
+ devDependencies: {
89
+ "@cloudflare/workers-types": "^4.0.0",
90
+ "drizzle-kit": "^0.31.0",
91
+ "drizzle-orm": "^0.44.0",
92
+ typescript: "^5.5.0",
93
+ wrangler: "^3.0.0"
94
+ }
95
+ };
96
+ },
97
+ seedFile: "seed.ts"
98
+ },
99
+ proxy: {
100
+ name: "Proxy (Cloudflare Workers)",
101
+ description: "Host-based reverse proxy on Cloudflare Workers — static config, no DB",
102
+ templateDir: "proxy",
103
+ packageJson: (e, t, n, r) => ({
104
+ name: e,
105
+ version: "1.0.0",
106
+ type: "module",
107
+ scripts: {
108
+ dev: "wrangler dev --port 8787",
109
+ deploy: "wrangler deploy",
110
+ logs: "wrangler tail"
111
+ },
112
+ dependencies: {
113
+ "@authhero/proxy": r ? "workspace:*" : "latest",
114
+ hono: "^4.6.0"
115
+ },
116
+ devDependencies: {
117
+ "@cloudflare/workers-types": "^4.0.0",
118
+ "@types/node": "^20.0.0",
119
+ typescript: "^5.5.0",
120
+ wrangler: "^3.0.0"
121
+ }
122
+ })
123
+ },
124
+ "aws-sst": {
125
+ name: "AWS SST (Lambda + DynamoDB)",
126
+ description: "Serverless AWS deployment with Lambda, DynamoDB, and SST",
127
+ templateDir: "aws-sst",
128
+ packageJson: (e, t, n, r, i) => {
129
+ let a = r ? "workspace:*" : "latest";
130
+ return {
131
+ name: e,
132
+ version: "1.0.0",
133
+ type: "module",
134
+ scripts: {
135
+ dev: "sst dev",
136
+ deploy: "sst deploy --stage production",
137
+ remove: "sst remove",
138
+ seed: "npx tsx src/seed.ts",
139
+ "copy-assets": "node copy-assets.js"
140
+ },
141
+ dependencies: {
142
+ "@authhero/aws": a,
143
+ ...i && { "@authhero/admin": a },
144
+ "@authhero/widget": a,
145
+ "@aws-sdk/client-dynamodb": "^3.0.0",
146
+ "@aws-sdk/lib-dynamodb": "^3.0.0",
147
+ "@hono/swagger-ui": "^0.5.0",
148
+ "@hono/zod-openapi": "^0.19.0",
149
+ authhero: a,
150
+ hono: "^4.6.0",
151
+ ...t && { "@authhero/multi-tenancy": a },
152
+ ...n && { bcryptjs: "latest" }
153
+ },
154
+ devDependencies: {
155
+ "@types/aws-lambda": "^8.10.0",
156
+ "@types/node": "^20.0.0",
157
+ sst: "^3.0.0",
158
+ tsx: "^4.0.0",
159
+ typescript: "^5.5.0"
160
+ }
161
+ };
162
+ },
163
+ seedFile: "seed.ts"
164
+ }
139
165
  };
140
- function P(s, e) {
141
- i.readdirSync(s).forEach((r) => {
142
- const n = a.join(s, r), t = a.join(e, r);
143
- i.lstatSync(n).isDirectory() ? (i.mkdirSync(t, { recursive: !0 }), P(n, t)) : i.copyFileSync(n, t);
144
- });
166
+ function c(e, t) {
167
+ n.readdirSync(e).forEach((i) => {
168
+ let a = r.join(e, i), o = r.join(t, i);
169
+ n.lstatSync(a).isDirectory() ? (n.mkdirSync(o, { recursive: !0 }), c(a, o)) : n.copyFileSync(a, o);
170
+ });
145
171
  }
146
- function $(s, e = !1, o = "authhero-local", r) {
147
- const n = s ? "control_plane" : "main", t = s ? "Control Plane" : "Main", c = [
148
- "https://manage.authhero.net/auth-callback",
149
- "https://local.authhero.net/auth-callback",
150
- "http://localhost:5173/auth-callback",
151
- "http://localhost:3000/auth-callback",
152
- ...r ? ["http://localhost:3000/admin/auth-callback"] : []
153
- ], d = e ? [
154
- `https://localhost.emobix.co.uk:8443/test/a/${o}/callback`,
155
- `https://localhost:8443/test/a/${o}/callback`
156
- ] : [], f = [...c, ...d], h = [
157
- "https://manage.authhero.net",
158
- "https://local.authhero.net",
159
- "http://localhost:5173",
160
- "http://localhost:3000"
161
- ], C = e ? ["https://localhost:8443/", "https://localhost.emobix.co.uk:8443/"] : [], y = [...h, ...C], _ = e ? `
172
+ function l(e, t = !1, n = "authhero-local", r) {
173
+ let i = e ? "control_plane" : "main", a = e ? "Control Plane" : "Main", o = [
174
+ "https://manage.authhero.net/auth-callback",
175
+ "https://local.authhero.net/auth-callback",
176
+ "http://localhost:5173/auth-callback",
177
+ "http://localhost:3000/auth-callback",
178
+ ...r ? ["http://localhost:3000/admin/auth-callback"] : []
179
+ ], s = t ? [`https://localhost.emobix.co.uk:8443/test/a/${n}/callback`, `https://localhost:8443/test/a/${n}/callback`] : [], c = [...o, ...s], l = [
180
+ "https://manage.authhero.net",
181
+ "https://local.authhero.net",
182
+ "http://localhost:5173",
183
+ "http://localhost:3000"
184
+ ], u = t ? ["https://localhost:8443/", "https://localhost.emobix.co.uk:8443/"] : [], d = [...l, ...u], f = t ? `
162
185
  // Create OpenID Conformance Suite test clients and user
163
186
  console.log("Creating conformance test clients and user...");
164
187
 
@@ -172,8 +195,8 @@ function $(s, e = !1, o = "authhero-local", r) {
172
195
  // default is to require an IAT. Existing flags (e.g.
173
196
  // inherit_global_permissions_in_organizations set by seed for the
174
197
  // control-plane tenant) are merged in so the update doesn't clobber.
175
- const existingTenant = await adapters.tenants.get("${n}");
176
- await adapters.tenants.update("${n}", {
198
+ const existingTenant = await adapters.tenants.get("${i}");
199
+ await adapters.tenants.update("${i}", {
177
200
  default_audience: "urn:authhero:management",
178
201
  flags: {
179
202
  ...(existingTenant?.flags ?? {}),
@@ -184,8 +207,8 @@ function $(s, e = !1, o = "authhero-local", r) {
184
207
  console.log("✅ Set tenant default_audience and enabled DCR for conformance");
185
208
 
186
209
  const conformanceCallbacks = [
187
- "https://localhost.emobix.co.uk:8443/test/a/${o}/callback",
188
- "https://localhost:8443/test/a/${o}/callback",
210
+ "https://localhost.emobix.co.uk:8443/test/a/${n}/callback",
211
+ "https://localhost:8443/test/a/${n}/callback",
189
212
  ];
190
213
  const conformanceLogoutUrls = [
191
214
  "https://localhost:8443/",
@@ -224,12 +247,12 @@ function $(s, e = !1, o = "authhero-local", r) {
224
247
  // Idempotent reconcile: prior runs may have created the client with stale
225
248
  // callbacks/web_origins after this seed file was changed. Update existing
226
249
  // records in place rather than just logging "already exists".
227
- const existing = await adapters.clients.get("${n}", spec.client_id);
250
+ const existing = await adapters.clients.get("${i}", spec.client_id);
228
251
  if (existing) {
229
- await adapters.clients.update("${n}", spec.client_id, desired);
252
+ await adapters.clients.update("${i}", spec.client_id, desired);
230
253
  console.log(\`🔄 Updated \${spec.client_id} client\`);
231
254
  } else {
232
- await adapters.clients.create("${n}", {
255
+ await adapters.clients.create("${i}", {
233
256
  client_id: spec.client_id,
234
257
  ...desired,
235
258
  });
@@ -240,7 +263,7 @@ function $(s, e = !1, o = "authhero-local", r) {
240
263
  // Create a conformance test user with ALL OIDC profile claims populated
241
264
  // This is required for OIDCC-5.4 (VerifyScopesReturnedInUserInfoClaims) test
242
265
  try {
243
- await adapters.users.create("${n}", {
266
+ await adapters.users.create("${i}", {
244
267
  user_id: \`\${USERNAME_PASSWORD_PROVIDER}|conformance-user\`,
245
268
  email: "conformance@example.com",
246
269
  email_verified: true,
@@ -275,7 +298,7 @@ function $(s, e = !1, o = "authhero-local", r) {
275
298
  try {
276
299
  const bcrypt = await import("bcryptjs");
277
300
  const hashedPassword = await bcrypt.hash("ConformanceTest123!", 10);
278
- await adapters.passwords.create("${n}", {
301
+ await adapters.passwords.create("${i}", {
279
302
  user_id: \`\${USERNAME_PASSWORD_PROVIDER}|conformance-user\`,
280
303
  password: hashedPassword,
281
304
  });
@@ -288,10 +311,10 @@ function $(s, e = !1, o = "authhero-local", r) {
288
311
  }
289
312
  }
290
313
  ` : "";
291
- return `import { SqliteDialect, Kysely } from "kysely";
314
+ return `import { SqliteDialect, Kysely } from "kysely";
292
315
  import Database from "better-sqlite3";
293
316
  import createAdapters from "@authhero/kysely-adapter";
294
- import { seed${e ? ", USERNAME_PASSWORD_PROVIDER" : ""} } from "authhero";
317
+ import { seed${t ? ", USERNAME_PASSWORD_PROVIDER" : ""} } from "authhero";
295
318
 
296
319
  interface ExtraClient {
297
320
  client_id: string;
@@ -350,12 +373,12 @@ async function main() {
350
373
  const seedResult = await seed(adapters, {
351
374
  adminUsername,
352
375
  adminPassword,
353
- tenantId: "${n}",
354
- tenantName: "${t}",
355
- isControlPlane: ${!!s},
376
+ tenantId: "${i}",
377
+ tenantName: "${a}",
378
+ isControlPlane: ${!!e},
356
379
  clientId: "default",
357
- callbacks: ${JSON.stringify(f)},
358
- allowedLogoutUrls: ${JSON.stringify(y)},
380
+ callbacks: ${JSON.stringify(c)},
381
+ allowedLogoutUrls: ${JSON.stringify(d)},
359
382
  });
360
383
 
361
384
  for (const c of extraClients) {
@@ -384,7 +407,7 @@ async function main() {
384
407
  await adapters.users.update(seedResult.tenantId, seedResult.userId, userProfile);
385
408
  console.log(\`✅ Updated profile of user "\${seedResult.username}"\`);
386
409
  }
387
- ${_}
410
+ ${f}
388
411
  await db.destroy();
389
412
  }
390
413
 
@@ -394,15 +417,8 @@ main().catch((err) => {
394
417
  });
395
418
  `;
396
419
  }
397
- function L(s, e) {
398
- const o = e ? `import fs from "fs";
399
- ` : "", r = e ? `
400
- const adminDistPath = path.resolve(
401
- __dirname,
402
- "../node_modules/@authhero/admin/dist",
403
- );
404
- const adminIndexPath = path.join(adminDistPath, "index.html");
405
- ` : "", n = e ? `
420
+ function u(e, t) {
421
+ let n = t ? "import fs from \"fs\";\n" : "", r = t ? "\nconst adminDistPath = path.resolve(\n __dirname,\n \"../node_modules/@authhero/admin/dist\",\n);\nconst adminIndexPath = path.join(adminDistPath, \"index.html\");\n" : "", i = t ? `
406
422
  // Add admin UI handler if the package is installed
407
423
  if (fs.existsSync(adminIndexPath)) {
408
424
  const issuer =
@@ -412,7 +428,7 @@ const adminIndexPath = path.join(adminDistPath, "index.html");
412
428
  .replace(/href="\\.\\//g, 'href="/admin/');
413
429
  const configJson = JSON.stringify({
414
430
  domain: issuer.replace(/\\/$/, ""),
415
- clientId: ${s ? "CONTROL_PLANE_CLIENT_ID," : '"default",'}
431
+ clientId: ${e ? "CONTROL_PLANE_CLIENT_ID," : "\"default\","}
416
432
  basePath: "/admin",
417
433
  }).replace(/</g, "\\\\u003c");
418
434
  configWithHandlers.adminIndexHtml = rawHtml.replace(
@@ -425,13 +441,13 @@ const adminIndexPath = path.join(adminDistPath, "index.html");
425
441
  });
426
442
  }
427
443
  ` : "";
428
- return s ? `import { Context } from "hono";
444
+ return e ? `import { Context } from "hono";
429
445
  import { swaggerUI } from "@hono/swagger-ui";
430
446
  import { AuthHeroConfig, DataAdapters } from "authhero";
431
447
  import { serveStatic } from "@hono/node-server/serve-static";
432
448
  import { initMultiTenant } from "@authhero/multi-tenancy";
433
449
  import path from "path";
434
- ${o}import { fileURLToPath } from "url";
450
+ ${n}import { fileURLToPath } from "url";
435
451
 
436
452
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
437
453
 
@@ -452,7 +468,7 @@ export default function createApp(config: AuthHeroConfig & { dataAdapter: DataAd
452
468
  rewriteRequestPath: (p) => p.replace("/u/widget", ""),
453
469
  }),
454
470
  };
455
- ${n}
471
+ ${i}
456
472
  // Initialize multi-tenant AuthHero - syncs resource servers, roles, and connections by default
457
473
  const { app } = initMultiTenant({
458
474
  ...configWithHandlers,
@@ -489,7 +505,7 @@ import { AuthHeroConfig, init } from "authhero";
489
505
  import { swaggerUI } from "@hono/swagger-ui";
490
506
  import { serveStatic } from "@hono/node-server/serve-static";
491
507
  import path from "path";
492
- ${o}import { fileURLToPath } from "url";
508
+ ${n}import { fileURLToPath } from "url";
493
509
 
494
510
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
495
511
 
@@ -506,7 +522,7 @@ export default function createApp(config: AuthHeroConfig) {
506
522
  rewriteRequestPath: (p) => p.replace("/u/widget", ""),
507
523
  }),
508
524
  };
509
- ${n}
525
+ ${i}
510
526
  const { app } = init(configWithHandlers);
511
527
 
512
528
  app
@@ -530,8 +546,8 @@ ${n}
530
546
  }
531
547
  `;
532
548
  }
533
- function j(s) {
534
- return `import { D1Dialect } from "kysely-d1";
549
+ function d(e) {
550
+ return `import { D1Dialect } from "kysely-d1";
535
551
  import { Kysely } from "kysely";
536
552
  import createAdapters from "@authhero/kysely-adapter";
537
553
  import { seed } from "authhero";
@@ -557,9 +573,9 @@ export default {
557
573
  adminUsername,
558
574
  adminPassword,
559
575
  issuer,
560
- tenantId: "${s ? "control_plane" : "main"}",
561
- tenantName: "${s ? "Control Plane" : "Main"}",
562
- isControlPlane: ${!!s},
576
+ tenantId: "${e ? "control_plane" : "main"}",
577
+ tenantName: "${e ? "Control Plane" : "Main"}",
578
+ isControlPlane: ${!!e},
563
579
  clientId: "default",
564
580
  });
565
581
 
@@ -591,15 +607,13 @@ export default {
591
607
  };
592
608
  `;
593
609
  }
594
- function H(s, e) {
595
- const o = e ? `import adminIndexHtml from "./admin-index-html";
596
- ` : "", r = e ? ` adminIndexHtml,
597
- ` : "";
598
- return s ? `import { Context } from "hono";
610
+ function f(e, t) {
611
+ let n = t ? "import adminIndexHtml from \"./admin-index-html\";\n" : "", r = t ? " adminIndexHtml,\n" : "";
612
+ return e ? `import { Context } from "hono";
599
613
  import { swaggerUI } from "@hono/swagger-ui";
600
614
  import { AuthHeroConfig, DataAdapters } from "authhero";
601
615
  import { initMultiTenant } from "@authhero/multi-tenancy";
602
- ${o}
616
+ ${n}
603
617
  // Control plane configuration
604
618
  const CONTROL_PLANE_TENANT_ID = "control_plane";
605
619
  const CONTROL_PLANE_CLIENT_ID = "default";
@@ -640,7 +654,7 @@ ${r} controlPlane: {
640
654
  import { cors } from "hono/cors";
641
655
  import { AuthHeroConfig, init } from "authhero";
642
656
  import { swaggerUI } from "@hono/swagger-ui";
643
- ${o}
657
+ ${n}
644
658
  export default function createApp(config: AuthHeroConfig) {
645
659
  const { app } = init({
646
660
  ...config,
@@ -676,114 +690,11 @@ ${r} });
676
690
  }
677
691
  `;
678
692
  }
679
- function F(s) {
680
- return s ? `import { Context } from "hono";
681
- import { swaggerUI } from "@hono/swagger-ui";
682
- import { AuthHeroConfig, DataAdapters } from "authhero";
683
- import { initMultiTenant } from "@authhero/multi-tenancy";
684
-
685
- // Control plane configuration
686
- const CONTROL_PLANE_TENANT_ID = "control_plane";
687
- const CONTROL_PLANE_CLIENT_ID = "default";
688
-
689
- interface AppConfig extends AuthHeroConfig {
690
- dataAdapter: DataAdapters;
691
- widgetUrl: string;
692
- }
693
-
694
- export default function createApp(config: AppConfig) {
695
- // Initialize multi-tenant AuthHero
696
- const { app } = initMultiTenant({
697
- ...config,
698
- controlPlane: {
699
- tenantId: CONTROL_PLANE_TENANT_ID,
700
- clientId: CONTROL_PLANE_CLIENT_ID,
701
- },
702
- });
703
-
704
- app
705
- .onError((err, ctx) => {
706
- if (err && typeof err === "object" && "getResponse" in err) {
707
- return (err as { getResponse: () => Response }).getResponse();
708
- }
709
- console.error(err);
710
- return ctx.text(err instanceof Error ? err.message : "Internal Server Error", 500);
711
- })
712
- .get("/", async (ctx: Context) => {
713
- return ctx.json({
714
- name: "AuthHero Multi-Tenant Server (AWS)",
715
- version: "1.0.0",
716
- status: "running",
717
- docs: "/docs",
718
- controlPlaneTenant: CONTROL_PLANE_TENANT_ID,
719
- });
720
- })
721
- .get("/docs", swaggerUI({ url: "/api/v2/spec" }))
722
- // Redirect widget requests to S3/CloudFront
723
- .get("/u/widget/*", async (ctx) => {
724
- const file = ctx.req.path.replace("/u/widget/", "");
725
- return ctx.redirect(\`\${config.widgetUrl}/u/widget/\${file}\`);
726
- })
727
- .get("/u/*", async (ctx) => {
728
- const file = ctx.req.path.replace("/u/", "");
729
- return ctx.redirect(\`\${config.widgetUrl}/u/\${file}\`);
730
- });
731
-
732
- return app;
733
- }
734
- ` : `import { Context } from "hono";
735
- import { cors } from "hono/cors";
736
- import { AuthHeroConfig, init, DataAdapters } from "authhero";
737
- import { swaggerUI } from "@hono/swagger-ui";
738
-
739
- interface AppConfig extends AuthHeroConfig {
740
- dataAdapter: DataAdapters;
741
- widgetUrl: string;
742
- }
743
-
744
- export default function createApp(config: AppConfig) {
745
- const { app } = init(config);
746
-
747
- // Enable CORS for all origins in development
748
- app.use("*", cors({
749
- origin: (origin) => origin || "*",
750
- allowMethods: ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"],
751
- allowHeaders: ["Content-Type", "Authorization", "Auth0-Client"],
752
- exposeHeaders: ["Content-Length"],
753
- credentials: true,
754
- }));
755
-
756
- app
757
- .onError((err, ctx) => {
758
- if (err && typeof err === "object" && "getResponse" in err) {
759
- return (err as { getResponse: () => Response }).getResponse();
760
- }
761
- console.error(err);
762
- return ctx.text(err instanceof Error ? err.message : "Internal Server Error", 500);
763
- })
764
- .get("/", async (ctx: Context) => {
765
- return ctx.json({
766
- name: "AuthHero Server (AWS)",
767
- status: "running",
768
- });
769
- })
770
- .get("/docs", swaggerUI({ url: "/api/v2/spec" }))
771
- // Redirect widget requests to S3/CloudFront
772
- .get("/u/widget/*", async (ctx) => {
773
- const file = ctx.req.path.replace("/u/widget/", "");
774
- return ctx.redirect(\`\${config.widgetUrl}/u/widget/\${file}\`);
775
- })
776
- .get("/u/*", async (ctx) => {
777
- const file = ctx.req.path.replace("/u/", "");
778
- return ctx.redirect(\`\${config.widgetUrl}/u/\${file}\`);
779
- });
780
-
781
- return app;
782
- }
783
- `;
693
+ function p(e) {
694
+ return e ? "import { Context } from \"hono\";\nimport { swaggerUI } from \"@hono/swagger-ui\";\nimport { AuthHeroConfig, DataAdapters } from \"authhero\";\nimport { initMultiTenant } from \"@authhero/multi-tenancy\";\n\n// Control plane configuration\nconst CONTROL_PLANE_TENANT_ID = \"control_plane\";\nconst CONTROL_PLANE_CLIENT_ID = \"default\";\n\ninterface AppConfig extends AuthHeroConfig {\n dataAdapter: DataAdapters;\n widgetUrl: string;\n}\n\nexport default function createApp(config: AppConfig) {\n // Initialize multi-tenant AuthHero\n const { app } = initMultiTenant({\n ...config,\n controlPlane: {\n tenantId: CONTROL_PLANE_TENANT_ID,\n clientId: CONTROL_PLANE_CLIENT_ID,\n },\n });\n\n app\n .onError((err, ctx) => {\n if (err && typeof err === \"object\" && \"getResponse\" in err) {\n return (err as { getResponse: () => Response }).getResponse();\n }\n console.error(err);\n return ctx.text(err instanceof Error ? err.message : \"Internal Server Error\", 500);\n })\n .get(\"/\", async (ctx: Context) => {\n return ctx.json({\n name: \"AuthHero Multi-Tenant Server (AWS)\",\n version: \"1.0.0\",\n status: \"running\",\n docs: \"/docs\",\n controlPlaneTenant: CONTROL_PLANE_TENANT_ID,\n });\n })\n .get(\"/docs\", swaggerUI({ url: \"/api/v2/spec\" }))\n // Redirect widget requests to S3/CloudFront\n .get(\"/u/widget/*\", async (ctx) => {\n const file = ctx.req.path.replace(\"/u/widget/\", \"\");\n return ctx.redirect(`${config.widgetUrl}/u/widget/${file}`);\n })\n .get(\"/u/*\", async (ctx) => {\n const file = ctx.req.path.replace(\"/u/\", \"\");\n return ctx.redirect(`${config.widgetUrl}/u/${file}`);\n });\n\n return app;\n}\n" : "import { Context } from \"hono\";\nimport { cors } from \"hono/cors\";\nimport { AuthHeroConfig, init, DataAdapters } from \"authhero\";\nimport { swaggerUI } from \"@hono/swagger-ui\";\n\ninterface AppConfig extends AuthHeroConfig {\n dataAdapter: DataAdapters;\n widgetUrl: string;\n}\n\nexport default function createApp(config: AppConfig) {\n const { app } = init(config);\n\n // Enable CORS for all origins in development\n app.use(\"*\", cors({\n origin: (origin) => origin || \"*\",\n allowMethods: [\"GET\", \"POST\", \"PUT\", \"DELETE\", \"PATCH\", \"OPTIONS\"],\n allowHeaders: [\"Content-Type\", \"Authorization\", \"Auth0-Client\"],\n exposeHeaders: [\"Content-Length\"],\n credentials: true,\n }));\n\n app\n .onError((err, ctx) => {\n if (err && typeof err === \"object\" && \"getResponse\" in err) {\n return (err as { getResponse: () => Response }).getResponse();\n }\n console.error(err);\n return ctx.text(err instanceof Error ? err.message : \"Internal Server Error\", 500);\n })\n .get(\"/\", async (ctx: Context) => {\n return ctx.json({\n name: \"AuthHero Server (AWS)\",\n status: \"running\",\n });\n })\n .get(\"/docs\", swaggerUI({ url: \"/api/v2/spec\" }))\n // Redirect widget requests to S3/CloudFront\n .get(\"/u/widget/*\", async (ctx) => {\n const file = ctx.req.path.replace(\"/u/widget/\", \"\");\n return ctx.redirect(`${config.widgetUrl}/u/widget/${file}`);\n })\n .get(\"/u/*\", async (ctx) => {\n const file = ctx.req.path.replace(\"/u/\", \"\");\n return ctx.redirect(`${config.widgetUrl}/u/${file}`);\n });\n\n return app;\n}\n";
784
695
  }
785
- function M(s) {
786
- return `import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
696
+ function m(e) {
697
+ return `import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
787
698
  import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";
788
699
  import createAdapters from "@authhero/aws";
789
700
  import { seed } from "authhero";
@@ -811,9 +722,9 @@ async function main() {
811
722
  await seed(adapters, {
812
723
  adminUsername,
813
724
  adminPassword,
814
- tenantId: "${s ? "control_plane" : "main"}",
815
- tenantName: "${s ? "Control Plane" : "Main"}",
816
- isControlPlane: ${!!s},
725
+ tenantId: "${e ? "control_plane" : "main"}",
726
+ tenantName: "${e ? "Control Plane" : "Main"}",
727
+ isControlPlane: ${!!e},
817
728
  });
818
729
 
819
730
  console.log("✅ Database seeded successfully!");
@@ -822,408 +733,223 @@ async function main() {
822
733
  main().catch(console.error);
823
734
  `;
824
735
  }
825
- function W(s, e) {
826
- const o = a.join(s, "src");
827
- i.writeFileSync(
828
- a.join(o, "app.ts"),
829
- F(e)
830
- ), i.writeFileSync(
831
- a.join(o, "seed.ts"),
832
- M(e)
833
- );
736
+ function h(e, t) {
737
+ let i = r.join(e, "src");
738
+ n.writeFileSync(r.join(i, "app.ts"), p(t)), n.writeFileSync(r.join(i, "seed.ts"), m(t));
834
739
  }
835
- function k() {
836
- console.log("\\n" + "─".repeat(50)), console.log("🔐 AuthHero deployed to AWS!"), console.log("📚 Check SST output for your API URL"), console.log("🚀 Open your server URL /setup to complete initial setup"), console.log("🌐 Portal available at https://local.authhero.net"), console.log("─".repeat(50) + "\\n");
740
+ function g() {
741
+ console.log("\\n" + "─".repeat(50)), console.log("🔐 AuthHero deployed to AWS!"), console.log("📚 Check SST output for your API URL"), console.log("🚀 Open your server URL /setup to complete initial setup"), console.log("🌐 Portal available at https://local.authhero.net"), console.log("─".repeat(50) + "\\n");
837
742
  }
838
- function q(s) {
839
- const e = a.join(s, ".github", "workflows");
840
- i.mkdirSync(e, { recursive: !0 });
841
- const o = `name: Unit tests
842
-
843
- on: push
844
-
845
- jobs:
846
- test:
847
- runs-on: ubuntu-latest
848
- steps:
849
- - uses: actions/checkout@v4
850
-
851
- - name: Setup Node.js
852
- uses: actions/setup-node@v4
853
- with:
854
- node-version: "22"
855
- cache: "npm"
856
-
857
- - name: Install dependencies
858
- run: npm ci
859
-
860
- - run: npm run type-check
861
- - run: npm test
862
- `, r = `name: Deploy to Dev
863
-
864
- on:
865
- push:
866
- branches:
867
- - main
868
-
869
- jobs:
870
- release:
871
- name: Release and Deploy
872
- runs-on: ubuntu-latest
873
- steps:
874
- - name: Checkout
875
- uses: actions/checkout@v4
876
- with:
877
- fetch-depth: 0
878
-
879
- - name: Setup Node.js
880
- uses: actions/setup-node@v4
881
- with:
882
- node-version: "22"
883
- cache: "npm"
884
-
885
- - name: Install dependencies
886
- run: npm ci
887
-
888
- - name: Release
889
- env:
890
- GITHUB_TOKEN: \${{ secrets.GITHUB_TOKEN }}
891
- run: npx semantic-release
892
-
893
- - name: Deploy to Cloudflare (Dev)
894
- uses: cloudflare/wrangler-action@v3
895
- with:
896
- apiToken: \${{ secrets.CLOUDFLARE_API_TOKEN }}
897
- command: deploy
898
- `, n = `name: Deploy to Production
899
-
900
- on:
901
- release:
902
- types: ["released"]
903
-
904
- jobs:
905
- deploy:
906
- name: Deploy to Production
907
- runs-on: ubuntu-latest
908
- steps:
909
- - name: Checkout
910
- uses: actions/checkout@v4
911
-
912
- - name: Setup Node.js
913
- uses: actions/setup-node@v4
914
- with:
915
- node-version: "22"
916
- cache: "npm"
917
-
918
- - name: Install dependencies
919
- run: npm ci
920
-
921
- - name: Deploy to Cloudflare (Production)
922
- uses: cloudflare/wrangler-action@v3
923
- with:
924
- apiToken: \${{ secrets.PROD_CLOUDFLARE_API_TOKEN }}
925
- command: deploy --env production
926
- `;
927
- i.writeFileSync(a.join(e, "unit-tests.yml"), o), i.writeFileSync(a.join(e, "deploy-dev.yml"), r), i.writeFileSync(a.join(e, "release.yml"), n), console.log("\\n📦 GitHub CI workflows created!");
743
+ function _(e) {
744
+ let t = r.join(e, ".github", "workflows");
745
+ n.mkdirSync(t, { recursive: !0 }), n.writeFileSync(r.join(t, "unit-tests.yml"), "name: Unit tests\n\non: push\n\njobs:\n test:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n\n - name: Setup Node.js\n uses: actions/setup-node@v4\n with:\n node-version: \"22\"\n cache: \"npm\"\n\n - name: Install dependencies\n run: npm ci\n\n - run: npm run type-check\n - run: npm test\n"), n.writeFileSync(r.join(t, "deploy-dev.yml"), "name: Deploy to Dev\n\non:\n push:\n branches:\n - main\n\njobs:\n release:\n name: Release and Deploy\n runs-on: ubuntu-latest\n steps:\n - name: Checkout\n uses: actions/checkout@v4\n with:\n fetch-depth: 0\n\n - name: Setup Node.js\n uses: actions/setup-node@v4\n with:\n node-version: \"22\"\n cache: \"npm\"\n\n - name: Install dependencies\n run: npm ci\n\n - name: Release\n env:\n GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n run: npx semantic-release\n\n - name: Deploy to Cloudflare (Dev)\n uses: cloudflare/wrangler-action@v3\n with:\n apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}\n command: deploy\n"), n.writeFileSync(r.join(t, "release.yml"), "name: Deploy to Production\n\non:\n release:\n types: [\"released\"]\n\njobs:\n deploy:\n name: Deploy to Production\n runs-on: ubuntu-latest\n steps:\n - name: Checkout\n uses: actions/checkout@v4\n\n - name: Setup Node.js\n uses: actions/setup-node@v4\n with:\n node-version: \"22\"\n cache: \"npm\"\n\n - name: Install dependencies\n run: npm ci\n\n - name: Deploy to Cloudflare (Production)\n uses: cloudflare/wrangler-action@v3\n with:\n apiToken: ${{ secrets.PROD_CLOUDFLARE_API_TOKEN }}\n command: deploy --env production\n"), console.log("\\n📦 GitHub CI workflows created!");
928
746
  }
929
- function J(s) {
930
- const e = {
931
- branches: ["main"],
932
- plugins: [
933
- "@semantic-release/commit-analyzer",
934
- "@semantic-release/release-notes-generator",
935
- "@semantic-release/github"
936
- ]
937
- };
938
- i.writeFileSync(
939
- a.join(s, ".releaserc.json"),
940
- JSON.stringify(e, null, 2)
941
- );
942
- const o = a.join(s, "package.json"), r = JSON.parse(i.readFileSync(o, "utf-8"));
943
- r.devDependencies = {
944
- ...r.devDependencies,
945
- "semantic-release": "^24.0.0"
946
- }, r.scripts = {
947
- ...r.scripts,
948
- test: 'echo "No tests yet"',
949
- "type-check": "tsc --noEmit"
950
- }, i.writeFileSync(o, JSON.stringify(r, null, 2));
747
+ function v(e) {
748
+ n.writeFileSync(r.join(e, ".releaserc.json"), JSON.stringify({
749
+ branches: ["main"],
750
+ plugins: [
751
+ "@semantic-release/commit-analyzer",
752
+ "@semantic-release/release-notes-generator",
753
+ "@semantic-release/github"
754
+ ]
755
+ }, null, 2));
756
+ let t = r.join(e, "package.json"), i = JSON.parse(n.readFileSync(t, "utf-8"));
757
+ i.devDependencies = {
758
+ ...i.devDependencies,
759
+ "semantic-release": "^24.0.0"
760
+ }, i.scripts = {
761
+ ...i.scripts,
762
+ test: "echo \"No tests yet\"",
763
+ "type-check": "tsc --noEmit"
764
+ }, n.writeFileSync(t, JSON.stringify(i, null, 2));
951
765
  }
952
- function A(s, e) {
953
- return new Promise((o, r) => {
954
- const n = U(s, [], {
955
- cwd: e,
956
- shell: !0,
957
- stdio: "inherit"
958
- });
959
- n.on("close", (t) => {
960
- t === 0 ? o() : r(new Error(`Command failed with exit code ${t}`));
961
- }), n.on("error", r);
962
- });
766
+ function y(e, t) {
767
+ return new Promise((n, r) => {
768
+ let i = a(e, [], {
769
+ cwd: t,
770
+ shell: !0,
771
+ stdio: "inherit"
772
+ });
773
+ i.on("close", (e) => {
774
+ e === 0 ? n() : r(/* @__PURE__ */ Error(`Command failed with exit code ${e}`));
775
+ }), i.on("error", r);
776
+ });
963
777
  }
964
- function z(s, e, o) {
965
- const r = a.join(s, "src");
966
- i.writeFileSync(
967
- a.join(r, "app.ts"),
968
- H(e, o)
969
- ), i.writeFileSync(
970
- a.join(r, "seed.ts"),
971
- j(e)
972
- );
778
+ function b(e, t, i) {
779
+ let a = r.join(e, "src");
780
+ n.writeFileSync(r.join(a, "app.ts"), f(t, i)), n.writeFileSync(r.join(a, "seed.ts"), d(t));
973
781
  }
974
- function D() {
975
- console.log(`
976
- ` + "─".repeat(50)), console.log("🔐 AuthHero server running at https://localhost:3000"), console.log("🚀 Open https://localhost:3000/setup to complete initial setup"), console.log("─".repeat(50) + `
977
- `);
782
+ function x() {
783
+ console.log("\n" + "─".repeat(50)), console.log("🔐 AuthHero server running at https://localhost:3000"), console.log("🚀 Open https://localhost:3000/setup to complete initial setup"), console.log("─".repeat(50) + "\n");
978
784
  }
979
- function T() {
980
- console.log(`
981
- ` + "─".repeat(50)), console.log("✅ Self-signed certificates generated with openssl"), console.log("⚠️ You may need to trust the certificate in your browser"), console.log("🔐 AuthHero server running at http://localhost:3000"), console.log("📚 API documentation available at http://localhost:3000/docs"), console.log("🚀 Open http://localhost:3000/setup to complete initial setup"), console.log("─".repeat(50) + `
982
- `);
785
+ function S() {
786
+ console.log("\n" + "─".repeat(50)), console.log("🛰️ AuthHero proxy running at http://localhost:8787"), console.log("✏️ Edit src/proxy.config.ts to add hosts and routes"), console.log("📖 See README.md for deployment instructions"), console.log("─".repeat(50) + "\n");
983
787
  }
984
- N.version("1.0.0").description("Create a new AuthHero project").argument("[project-name]", "name of the project").option("-t, --template <type>", "template type: local or cloudflare").option(
985
- "--package-manager <pm>",
986
- "package manager to use: npm, yarn, pnpm, or bun"
987
- ).option("--multi-tenant", "enable multi-tenant mode").option("--admin-ui", "include admin UI at /admin").option("--skip-install", "skip installing dependencies").option("--skip-migrate", "skip running database migrations").option("--skip-start", "skip starting the development server").option("--github-ci", "include GitHub CI workflows with semantic versioning").option("--conformance", "add OpenID conformance suite test clients").option(
988
- "--conformance-alias <alias>",
989
- "alias for conformance suite (default: authhero-local)"
990
- ).option(
991
- "--workspace",
992
- "use workspace:* dependencies for local monorepo development"
993
- ).option("-y, --yes", "skip all prompts and use defaults/provided options").action(async (s, e) => {
994
- const o = e.yes === !0;
995
- console.log(`
996
- 🔐 Welcome to AuthHero!
997
- `);
998
- let r = s;
999
- r || (o ? (r = "auth-server", console.log(`Using default project name: ${r}`)) : r = (await m.prompt([
1000
- {
1001
- type: "input",
1002
- name: "projectName",
1003
- message: "Project name:",
1004
- default: "auth-server",
1005
- validate: (u) => u !== "" || "Project name cannot be empty"
1006
- }
1007
- ])).projectName);
1008
- const n = a.join(process.cwd(), r);
1009
- i.existsSync(n) && (console.error(`❌ Project "${r}" already exists.`), process.exit(1));
1010
- let t;
1011
- e.template ? (["local", "cloudflare", "aws-sst"].includes(e.template) || (console.error(`❌ Invalid template: ${e.template}`), console.error("Valid options: local, cloudflare, aws-sst"), process.exit(1)), t = e.template, console.log(`Using template: ${p[t].name}`)) : t = (await m.prompt([
1012
- {
1013
- type: "list",
1014
- name: "setupType",
1015
- message: "Select your setup type:",
1016
- choices: [
1017
- {
1018
- name: `${p.local.name}
1019
- ${p.local.description}`,
1020
- value: "local",
1021
- short: p.local.name
1022
- },
1023
- {
1024
- name: `${p.cloudflare.name}
1025
- ${p.cloudflare.description}`,
1026
- value: "cloudflare",
1027
- short: p.cloudflare.name
1028
- },
1029
- {
1030
- name: `${p["aws-sst"].name}
1031
- ${p["aws-sst"].description}`,
1032
- value: "aws-sst",
1033
- short: p["aws-sst"].name
1034
- }
1035
- ]
1036
- }
1037
- ])).setupType;
1038
- let c;
1039
- e.multiTenant !== void 0 ? c = e.multiTenant : o ? c = !1 : c = (await m.prompt([
1040
- {
1041
- type: "confirm",
1042
- name: "multiTenant",
1043
- message: "Would you like to enable multi-tenant mode?",
1044
- default: !1
1045
- }
1046
- ])).multiTenant, c && console.log("Multi-tenant mode: enabled");
1047
- let d = !1;
1048
- (t === "local" || t === "cloudflare") && (e.adminUi !== void 0 ? d = e.adminUi : o ? d = !0 : d = (await m.prompt([
1049
- {
1050
- type: "confirm",
1051
- name: "adminUi",
1052
- message: "Would you like to include the admin UI at /admin?",
1053
- default: !0
1054
- }
1055
- ])).adminUi, d && console.log("Admin UI: enabled (available at /admin)"));
1056
- const f = e.conformance || !1, h = e.conformanceAlias || "authhero-local";
1057
- f && console.log(
1058
- `OpenID Conformance Suite: enabled (alias: ${h})`
1059
- );
1060
- const C = e.workspace || !1;
1061
- C && console.log("Workspace mode: enabled (using workspace:* dependencies)");
1062
- const y = p[t];
1063
- i.mkdirSync(n, { recursive: !0 }), i.writeFileSync(
1064
- a.join(n, "package.json"),
1065
- JSON.stringify(
1066
- y.packageJson(
1067
- r,
1068
- c,
1069
- f,
1070
- C,
1071
- d
1072
- ),
1073
- null,
1074
- 2
1075
- )
1076
- );
1077
- const _ = y.templateDir, S = a.dirname(O(import.meta.url)), x = [
1078
- a.join(S, _),
1079
- a.join(S, "..", "templates", _)
1080
- ], I = x.find((l) => i.existsSync(l));
1081
- if (I ? P(I, n) : (console.error(
1082
- `❌ Template directory not found. Looked in:
1083
- ${x.join(`
1084
- `)}`
1085
- ), process.exit(1)), t === "cloudflare" && z(n, c, d), t === "cloudflare") {
1086
- const l = a.join(n, "wrangler.toml"), u = a.join(n, "wrangler.local.toml");
1087
- i.existsSync(l) && i.copyFileSync(l, u);
1088
- const g = a.join(n, ".dev.vars.example"), w = a.join(n, ".dev.vars");
1089
- i.existsSync(g) && i.copyFileSync(g, w), console.log(
1090
- "📁 Created wrangler.local.toml and .dev.vars for local development"
1091
- );
1092
- }
1093
- let b = !1;
1094
- if (t === "cloudflare" && (e.githubCi !== void 0 ? (b = e.githubCi, b && console.log("Including GitHub CI workflows with semantic versioning")) : o || (b = (await m.prompt([
1095
- {
1096
- type: "confirm",
1097
- name: "includeGithubCi",
1098
- message: "Would you like to include GitHub CI with semantic versioning?",
1099
- default: !1
1100
- }
1101
- ])).includeGithubCi), b && (q(n), J(n))), t === "local") {
1102
- const l = $(
1103
- c,
1104
- f,
1105
- h,
1106
- d
1107
- );
1108
- i.writeFileSync(a.join(n, "src/seed.ts"), l);
1109
- const u = L(c, d);
1110
- i.writeFileSync(a.join(n, "src/app.ts"), u);
1111
- }
1112
- if (t === "aws-sst" && W(n, c), f) {
1113
- const l = {
1114
- alias: h,
1115
- description: "AuthHero Conformance Test",
1116
- server: {
1117
- discoveryUrl: "http://host.docker.internal:3000/.well-known/openid-configuration"
1118
- },
1119
- client: {
1120
- client_id: "conformance-test",
1121
- client_secret: "conformanceTestSecret123"
1122
- },
1123
- client2: {
1124
- client_id: "conformance-test2",
1125
- client_secret: "conformanceTestSecret456"
1126
- },
1127
- resource: {
1128
- resourceUrl: "http://host.docker.internal:3000/userinfo"
1129
- }
1130
- };
1131
- i.writeFileSync(
1132
- a.join(n, "conformance-config.json"),
1133
- JSON.stringify(l, null, 2)
1134
- ), console.log(
1135
- "📝 Created conformance-config.json for OpenID Conformance Suite"
1136
- );
1137
- }
1138
- const E = c ? "multi-tenant" : "single-tenant";
1139
- console.log(
1140
- `
1141
- Project "${r}" has been created with ${y.name} (${E}) setup!
1142
- `
1143
- );
1144
- let v;
1145
- if (e.skipInstall ? v = !1 : o ? v = !0 : v = (await m.prompt([
1146
- {
1147
- type: "confirm",
1148
- name: "shouldInstall",
1149
- message: "Would you like to install dependencies now?",
1150
- default: !0
1151
- }
1152
- ])).shouldInstall, v) {
1153
- let l;
1154
- e.packageManager ? (["npm", "yarn", "pnpm", "bun"].includes(e.packageManager) || (console.error(
1155
- `❌ Invalid package manager: ${e.packageManager}`
1156
- ), console.error("Valid options: npm, yarn, pnpm, bun"), process.exit(1)), l = e.packageManager) : o ? l = "pnpm" : l = (await m.prompt([
1157
- {
1158
- type: "list",
1159
- name: "packageManager",
1160
- message: "Which package manager would you like to use?",
1161
- choices: [
1162
- { name: "pnpm", value: "pnpm" },
1163
- { name: "npm", value: "npm" },
1164
- { name: "yarn", value: "yarn" },
1165
- { name: "bun", value: "bun" }
1166
- ],
1167
- default: "pnpm"
1168
- }
1169
- ])).packageManager, console.log(`
1170
- 📦 Installing dependencies with ${l}...
1171
- `);
1172
- try {
1173
- const u = l === "pnpm" ? "pnpm install --ignore-workspace" : `${l} install`;
1174
- if (await A(u, n), t === "local" && (console.log(`
1175
- 🔧 Building native modules...
1176
- `), await A("npm rebuild better-sqlite3", n)), console.log(`
1177
- ✅ Dependencies installed successfully!
1178
- `), (t === "local" || t === "cloudflare") && !e.skipMigrate) {
1179
- let w;
1180
- o ? w = !0 : w = (await m.prompt([
1181
- {
1182
- type: "confirm",
1183
- name: "shouldMigrate",
1184
- message: "Would you like to run database migrations?",
1185
- default: !0
1186
- }
1187
- ])).shouldMigrate, w && (console.log(`
1188
- 🔄 Running migrations...
1189
- `), await A(`${l} run migrate`, n));
1190
- }
1191
- let g;
1192
- e.skipStart || o ? g = !1 : g = (await m.prompt([
1193
- {
1194
- type: "confirm",
1195
- name: "shouldStart",
1196
- message: "Would you like to start the development server?",
1197
- default: !0
1198
- }
1199
- ])).shouldStart, g && (t === "cloudflare" ? D() : t === "aws-sst" ? k() : T(), console.log(`🚀 Starting development server...
1200
- `), await A(`${l} run dev`, n)), o && !g && (console.log(`
1201
- ✅ Setup complete!`), console.log(`
1202
- To start the development server:`), console.log(` cd ${r}`), console.log(" npm run dev"), t === "cloudflare" ? D() : t === "aws-sst" ? k() : T());
1203
- } catch (u) {
1204
- console.error(`
1205
- ❌ An error occurred:`, u), process.exit(1);
1206
- }
1207
- }
1208
- v || (console.log("Next steps:"), console.log(` cd ${r}`), t === "local" ? (console.log(" npm install"), console.log(" npm run migrate"), console.log(" npm run dev"), console.log(
1209
- `
1210
- Open http://localhost:3000/setup to complete initial setup`
1211
- )) : t === "cloudflare" ? (console.log(" npm install"), console.log(
1212
- " npm run migrate # or npm run db:migrate:remote for production"
1213
- ), console.log(" npm run dev # or npm run dev:remote for production"), console.log(
1214
- `
1215
- Open https://localhost:3000/setup to complete initial setup`
1216
- )) : t === "aws-sst" && (console.log(" npm install"), console.log(" npm run dev # Deploys to AWS in development mode"), console.log(`
1217
- Open your server URL /setup to complete initial setup`)), console.log(`
1218
- Server will be available at: http://localhost:3000`), f && (console.log(`
1219
- 🧪 OpenID Conformance Suite Testing:`), console.log(
1220
- " 1. Clone and start the conformance suite (if not already running):"
1221
- ), console.log(
1222
- " git clone https://gitlab.com/openid/conformance-suite.git"
1223
- ), console.log(" cd conformance-suite && mvn clean package"), console.log(" docker-compose up -d"), console.log(" 2. Open https://localhost.emobix.co.uk:8443"), console.log(
1224
- " 3. Create a test plan and use conformance-config.json for settings"
1225
- ), console.log(` 4. Use alias: ${h}`)), console.log(`
1226
- For more information, visit: https://authhero.net/docs
1227
- `));
1228
- });
1229
- N.parse(process.argv);
788
+ function C() {
789
+ console.log("\n" + "─".repeat(50)), console.log("✅ Self-signed certificates generated with openssl"), console.log("⚠️ You may need to trust the certificate in your browser"), console.log("🔐 AuthHero server running at http://localhost:3000"), console.log("📚 API documentation available at http://localhost:3000/docs"), console.log("🚀 Open http://localhost:3000/setup to complete initial setup"), console.log("─".repeat(50) + "\n");
790
+ }
791
+ o.version("1.0.0").description("Create a new AuthHero project").argument("[project-name]", "name of the project").option("-t, --template <type>", "template type: local, cloudflare, aws-sst, or proxy").option("--package-manager <pm>", "package manager to use: npm, yarn, pnpm, or bun").option("--multi-tenant", "enable multi-tenant mode").option("--admin-ui", "include admin UI at /admin").option("--skip-install", "skip installing dependencies").option("--skip-migrate", "skip running database migrations").option("--skip-start", "skip starting the development server").option("--github-ci", "include GitHub CI workflows with semantic versioning").option("--conformance", "add OpenID conformance suite test clients").option("--conformance-alias <alias>", "alias for conformance suite (default: authhero-local)").option("--workspace", "use workspace:* dependencies for local monorepo development").option("-y, --yes", "skip all prompts and use defaults/provided options").action(async (e, a) => {
792
+ let o = a.yes === !0;
793
+ console.log("\n🔐 Welcome to AuthHero!\n");
794
+ let d = e;
795
+ d || (o ? (d = "auth-server", console.log(`Using default project name: ${d}`)) : d = (await t.prompt([{
796
+ type: "input",
797
+ name: "projectName",
798
+ message: "Project name:",
799
+ default: "auth-server",
800
+ validate: (e) => e !== "" || "Project name cannot be empty"
801
+ }])).projectName);
802
+ let f = r.join(process.cwd(), d);
803
+ n.existsSync(f) && (console.error(`❌ Project "${d}" already exists.`), process.exit(1));
804
+ let p;
805
+ a.template ? ([
806
+ "local",
807
+ "cloudflare",
808
+ "aws-sst",
809
+ "proxy"
810
+ ].includes(a.template) || (console.error(`❌ Invalid template: ${a.template}`), console.error("Valid options: local, cloudflare, aws-sst, proxy"), process.exit(1)), p = a.template, console.log(`Using template: ${s[p].name}`)) : p = (await t.prompt([{
811
+ type: "list",
812
+ name: "setupType",
813
+ message: "Select your setup type:",
814
+ choices: [
815
+ {
816
+ name: `${s.local.name}\n ${s.local.description}`,
817
+ value: "local",
818
+ short: s.local.name
819
+ },
820
+ {
821
+ name: `${s.cloudflare.name}\n ${s.cloudflare.description}`,
822
+ value: "cloudflare",
823
+ short: s.cloudflare.name
824
+ },
825
+ {
826
+ name: `${s["aws-sst"].name}\n ${s["aws-sst"].description}`,
827
+ value: "aws-sst",
828
+ short: s["aws-sst"].name
829
+ },
830
+ {
831
+ name: `${s.proxy.name}\n ${s.proxy.description}`,
832
+ value: "proxy",
833
+ short: s.proxy.name
834
+ }
835
+ ]
836
+ }])).setupType;
837
+ let m;
838
+ m = p === "proxy" ? !1 : a.multiTenant === void 0 ? o ? !1 : (await t.prompt([{
839
+ type: "confirm",
840
+ name: "multiTenant",
841
+ message: "Would you like to enable multi-tenant mode?",
842
+ default: !1
843
+ }])).multiTenant : a.multiTenant, m && console.log("Multi-tenant mode: enabled");
844
+ let w = !1;
845
+ (p === "local" || p === "cloudflare") && (w = a.adminUi === void 0 ? o ? !0 : (await t.prompt([{
846
+ type: "confirm",
847
+ name: "adminUi",
848
+ message: "Would you like to include the admin UI at /admin?",
849
+ default: !0
850
+ }])).adminUi : a.adminUi, w && console.log("Admin UI: enabled (available at /admin)"));
851
+ let T = a.conformance || !1, E = a.conformanceAlias || "authhero-local";
852
+ T && console.log(`OpenID Conformance Suite: enabled (alias: ${E})`);
853
+ let D = a.workspace || !1;
854
+ D && console.log("Workspace mode: enabled (using workspace:* dependencies)");
855
+ let O = s[p];
856
+ n.mkdirSync(f, { recursive: !0 }), n.writeFileSync(r.join(f, "package.json"), JSON.stringify(O.packageJson(d, m, T, D, w), null, 2));
857
+ let k = O.templateDir, A = r.dirname(i(import.meta.url)), j = [r.join(A, k), r.join(A, "..", "templates", k)], M = j.find((e) => n.existsSync(e));
858
+ if (M ? c(M, f) : (console.error(`❌ Template directory not found. Looked in:\n ${j.join("\n ")}`), process.exit(1)), p === "cloudflare" && b(f, m, w), p === "cloudflare") {
859
+ let e = r.join(f, "wrangler.toml"), t = r.join(f, "wrangler.local.toml");
860
+ n.existsSync(e) && n.copyFileSync(e, t);
861
+ let i = r.join(f, ".dev.vars.example"), a = r.join(f, ".dev.vars");
862
+ n.existsSync(i) && n.copyFileSync(i, a), console.log("📁 Created wrangler.local.toml and .dev.vars for local development");
863
+ }
864
+ let N = !1;
865
+ if (p === "cloudflare" && (a.githubCi === void 0 ? o || (N = (await t.prompt([{
866
+ type: "confirm",
867
+ name: "includeGithubCi",
868
+ message: "Would you like to include GitHub CI with semantic versioning?",
869
+ default: !1
870
+ }])).includeGithubCi) : (N = a.githubCi, N && console.log("Including GitHub CI workflows with semantic versioning")), N && (_(f), v(f))), p === "local") {
871
+ let e = l(m, T, E, w);
872
+ n.writeFileSync(r.join(f, "src/seed.ts"), e);
873
+ let t = u(m, w);
874
+ n.writeFileSync(r.join(f, "src/app.ts"), t);
875
+ }
876
+ if (p === "aws-sst" && h(f, m), T) {
877
+ let e = {
878
+ alias: E,
879
+ description: "AuthHero Conformance Test",
880
+ server: { discoveryUrl: "http://host.docker.internal:3000/.well-known/openid-configuration" },
881
+ client: {
882
+ client_id: "conformance-test",
883
+ client_secret: "conformanceTestSecret123"
884
+ },
885
+ client2: {
886
+ client_id: "conformance-test2",
887
+ client_secret: "conformanceTestSecret456"
888
+ },
889
+ resource: { resourceUrl: "http://host.docker.internal:3000/userinfo" }
890
+ };
891
+ n.writeFileSync(r.join(f, "conformance-config.json"), JSON.stringify(e, null, 2)), console.log("📝 Created conformance-config.json for OpenID Conformance Suite");
892
+ }
893
+ let P = m ? "multi-tenant" : "single-tenant";
894
+ console.log(`\n✅ Project "${d}" has been created with ${O.name} (${P}) setup!\n`);
895
+ let F;
896
+ if (F = a.skipInstall ? !1 : o ? !0 : (await t.prompt([{
897
+ type: "confirm",
898
+ name: "shouldInstall",
899
+ message: "Would you like to install dependencies now?",
900
+ default: !0
901
+ }])).shouldInstall, F) {
902
+ let e;
903
+ a.packageManager ? ([
904
+ "npm",
905
+ "yarn",
906
+ "pnpm",
907
+ "bun"
908
+ ].includes(a.packageManager) || (console.error(`❌ Invalid package manager: ${a.packageManager}`), console.error("Valid options: npm, yarn, pnpm, bun"), process.exit(1)), e = a.packageManager) : e = o ? "pnpm" : (await t.prompt([{
909
+ type: "list",
910
+ name: "packageManager",
911
+ message: "Which package manager would you like to use?",
912
+ choices: [
913
+ {
914
+ name: "pnpm",
915
+ value: "pnpm"
916
+ },
917
+ {
918
+ name: "npm",
919
+ value: "npm"
920
+ },
921
+ {
922
+ name: "yarn",
923
+ value: "yarn"
924
+ },
925
+ {
926
+ name: "bun",
927
+ value: "bun"
928
+ }
929
+ ],
930
+ default: "pnpm"
931
+ }])).packageManager, console.log(`\n📦 Installing dependencies with ${e}...\n`);
932
+ try {
933
+ if (await y(e === "pnpm" ? "pnpm install --ignore-workspace" : `${e} install`, f), p === "local" && (console.log("\n🔧 Building native modules...\n"), await y("npm rebuild better-sqlite3", f)), console.log("\n✅ Dependencies installed successfully!\n"), (p === "local" || p === "cloudflare") && !a.skipMigrate) {
934
+ let n;
935
+ n = o ? !0 : (await t.prompt([{
936
+ type: "confirm",
937
+ name: "shouldMigrate",
938
+ message: "Would you like to run database migrations?",
939
+ default: !0
940
+ }])).shouldMigrate, n && (console.log("\n🔄 Running migrations...\n"), await y(`${e} run migrate`, f));
941
+ }
942
+ let n;
943
+ n = a.skipStart || o ? !1 : (await t.prompt([{
944
+ type: "confirm",
945
+ name: "shouldStart",
946
+ message: "Would you like to start the development server?",
947
+ default: !0
948
+ }])).shouldStart, n && (p === "cloudflare" ? x() : p === "aws-sst" ? g() : p === "proxy" ? S() : C(), console.log("🚀 Starting development server...\n"), await y(`${e} run dev`, f)), o && !n && (console.log("\n✅ Setup complete!"), console.log("\nTo start the development server:"), console.log(` cd ${d}`), console.log(" npm run dev"), p === "cloudflare" ? x() : p === "aws-sst" ? g() : p === "proxy" ? S() : C());
949
+ } catch (e) {
950
+ console.error("\n❌ An error occurred:", e), process.exit(1);
951
+ }
952
+ }
953
+ F || (console.log("Next steps:"), console.log(` cd ${d}`), p === "local" ? (console.log(" npm install"), console.log(" npm run migrate"), console.log(" npm run dev"), console.log("\nOpen http://localhost:3000/setup to complete initial setup")) : p === "cloudflare" ? (console.log(" npm install"), console.log(" npm run migrate # or npm run db:migrate:remote for production"), console.log(" npm run dev # or npm run dev:remote for production"), console.log("\nOpen https://localhost:3000/setup to complete initial setup")) : p === "aws-sst" ? (console.log(" npm install"), console.log(" npm run dev # Deploys to AWS in development mode"), console.log("\nOpen your server URL /setup to complete initial setup")) : p === "proxy" && (console.log(" npm install"), console.log(" npm run dev"), console.log("\nEdit src/proxy.config.ts to add hosts and routes")), console.log(`\nServer will be available at: http://localhost:${p === "proxy" ? 8787 : 3e3}`), T && (console.log("\n🧪 OpenID Conformance Suite Testing:"), console.log(" 1. Clone and start the conformance suite (if not already running):"), console.log(" git clone https://gitlab.com/openid/conformance-suite.git"), console.log(" cd conformance-suite && mvn clean package"), console.log(" docker-compose up -d"), console.log(" 2. Open https://localhost.emobix.co.uk:8443"), console.log(" 3. Create a test plan and use conformance-config.json for settings"), console.log(` 4. Use alias: ${E}`)), console.log("\nFor more information, visit: https://authhero.net/docs\n"));
954
+ }), o.parse(process.argv);
955
+ //#endregion