create-authhero 0.26.0 → 0.28.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.
@@ -14,6 +14,7 @@
14
14
  name = "authhero-server"
15
15
  main = "src/index.ts"
16
16
  compatibility_date = "2024-11-20"
17
+ compatibility_flags = ["nodejs_compat"]
17
18
 
18
19
  # ════════════════════════════════════════════════════════════════════════════
19
20
  # Static Assets (CSS, JS, Widget)
@@ -1,156 +1,165 @@
1
1
  #!/usr/bin/env node
2
- import { Command as L } from "commander";
2
+ import { Command as R } from "commander";
3
3
  import u from "inquirer";
4
- import s from "fs";
4
+ import a from "fs";
5
5
  import l from "path";
6
- import { spawn as N } from "child_process";
7
- const T = new L(), p = {
6
+ import { spawn as T } from "child_process";
7
+ const E = new R(), p = {
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: (t, e, o) => ({
13
- name: t,
14
- version: "1.0.0",
15
- type: "module",
16
- scripts: {
17
- dev: "npx tsx watch src/index.ts",
18
- start: "npx tsx src/index.ts",
19
- migrate: "npx tsx src/migrate.ts",
20
- seed: "npx tsx src/seed.ts"
21
- },
22
- dependencies: {
23
- "@authhero/kysely-adapter": "latest",
24
- "@authhero/widget": "latest",
25
- "@hono/swagger-ui": "^0.5.0",
26
- "@hono/zod-openapi": "^0.19.0",
27
- "@hono/node-server": "latest",
28
- authhero: "latest",
29
- "better-sqlite3": "latest",
30
- hono: "^4.6.0",
31
- kysely: "latest",
32
- ...e && { "@authhero/multi-tenancy": "latest" },
33
- ...o && { bcryptjs: "latest" }
34
- },
35
- devDependencies: {
36
- "@types/better-sqlite3": "^7.6.0",
37
- "@types/node": "^20.0.0",
38
- tsx: "^4.0.0",
39
- typescript: "^5.5.0"
40
- }
41
- }),
12
+ packageJson: (o, e, r, n) => {
13
+ const t = n ? "workspace:*" : "latest";
14
+ return {
15
+ name: o,
16
+ version: "1.0.0",
17
+ type: "module",
18
+ scripts: {
19
+ dev: "npx tsx watch src/index.ts",
20
+ start: "npx tsx src/index.ts",
21
+ migrate: "npx tsx src/migrate.ts",
22
+ seed: "npx tsx src/seed.ts"
23
+ },
24
+ dependencies: {
25
+ "@authhero/kysely-adapter": t,
26
+ "@authhero/widget": t,
27
+ "@hono/swagger-ui": "^0.5.0",
28
+ "@hono/zod-openapi": "^0.19.0",
29
+ "@hono/node-server": "latest",
30
+ authhero: t,
31
+ "better-sqlite3": "latest",
32
+ hono: "^4.6.0",
33
+ kysely: "latest",
34
+ ...e && { "@authhero/multi-tenancy": t },
35
+ ...r && { bcryptjs: "latest" }
36
+ },
37
+ devDependencies: {
38
+ "@types/better-sqlite3": "^7.6.0",
39
+ "@types/node": "^20.0.0",
40
+ tsx: "^4.0.0",
41
+ typescript: "^5.5.0"
42
+ }
43
+ };
44
+ },
42
45
  seedFile: "seed.ts"
43
46
  },
44
47
  cloudflare: {
45
48
  name: "Cloudflare Workers (D1)",
46
49
  description: "Cloudflare Workers setup with D1 database",
47
50
  templateDir: "cloudflare",
48
- packageJson: (t, e, o) => ({
49
- name: t,
50
- version: "1.0.0",
51
- type: "module",
52
- scripts: {
53
- postinstall: "node copy-assets.js",
54
- "copy-assets": "node copy-assets.js",
55
- dev: "wrangler dev --port 3000 --local-protocol https",
56
- "dev:remote": "wrangler dev --port 3000 --local-protocol https --remote --config wrangler.local.toml",
57
- deploy: "wrangler deploy --config wrangler.local.toml",
58
- "db:migrate:local": "wrangler d1 migrations apply AUTH_DB --local",
59
- "db:migrate:remote": "wrangler d1 migrations apply AUTH_DB --remote --config wrangler.local.toml",
60
- migrate: "wrangler d1 migrations apply AUTH_DB --local",
61
- "seed:local": "node seed-helper.js",
62
- "seed:remote": "node seed-helper.js '' '' remote",
63
- seed: "node seed-helper.js",
64
- 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'"
65
- },
66
- dependencies: {
67
- "@authhero/drizzle": "latest",
68
- "@authhero/kysely-adapter": "latest",
69
- "@authhero/widget": "latest",
70
- "@hono/swagger-ui": "^0.5.0",
71
- "@hono/zod-openapi": "^0.19.0",
72
- authhero: "latest",
73
- hono: "^4.6.0",
74
- kysely: "latest",
75
- "kysely-d1": "latest",
76
- ...e && { "@authhero/multi-tenancy": "latest" },
77
- ...o && { bcryptjs: "latest" }
78
- },
79
- devDependencies: {
80
- "@cloudflare/workers-types": "^4.0.0",
81
- "drizzle-kit": "^0.31.0",
82
- "drizzle-orm": "^0.44.0",
83
- typescript: "^5.5.0",
84
- wrangler: "^3.0.0"
85
- }
86
- }),
51
+ packageJson: (o, e, r, n) => {
52
+ const t = n ? "workspace:*" : "latest";
53
+ return {
54
+ name: o,
55
+ version: "1.0.0",
56
+ type: "module",
57
+ scripts: {
58
+ postinstall: "node copy-assets.js",
59
+ "copy-assets": "node copy-assets.js",
60
+ dev: "wrangler dev --port 3000 --local-protocol https",
61
+ "dev:remote": "wrangler dev --port 3000 --local-protocol https --remote --config wrangler.local.toml",
62
+ deploy: "wrangler deploy --config wrangler.local.toml",
63
+ "db:migrate:local": "wrangler d1 migrations apply AUTH_DB --local",
64
+ "db:migrate:remote": "wrangler d1 migrations apply AUTH_DB --remote --config wrangler.local.toml",
65
+ migrate: "wrangler d1 migrations apply AUTH_DB --local",
66
+ "seed:local": "node seed-helper.js",
67
+ "seed:remote": "node seed-helper.js '' '' remote",
68
+ seed: "node seed-helper.js",
69
+ 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'"
70
+ },
71
+ dependencies: {
72
+ "@authhero/drizzle": t,
73
+ "@authhero/kysely-adapter": t,
74
+ "@authhero/widget": t,
75
+ "@hono/swagger-ui": "^0.5.0",
76
+ "@hono/zod-openapi": "^0.19.0",
77
+ authhero: t,
78
+ hono: "^4.6.0",
79
+ kysely: "latest",
80
+ "kysely-d1": "latest",
81
+ ...e && { "@authhero/multi-tenancy": t },
82
+ ...r && { bcryptjs: "latest" }
83
+ },
84
+ devDependencies: {
85
+ "@cloudflare/workers-types": "^4.0.0",
86
+ "drizzle-kit": "^0.31.0",
87
+ "drizzle-orm": "^0.44.0",
88
+ typescript: "^5.5.0",
89
+ wrangler: "^3.0.0"
90
+ }
91
+ };
92
+ },
87
93
  seedFile: "seed.ts"
88
94
  },
89
95
  "aws-sst": {
90
96
  name: "AWS SST (Lambda + DynamoDB)",
91
97
  description: "Serverless AWS deployment with Lambda, DynamoDB, and SST",
92
98
  templateDir: "aws-sst",
93
- packageJson: (t, e, o) => ({
94
- name: t,
95
- version: "1.0.0",
96
- type: "module",
97
- scripts: {
98
- dev: "sst dev",
99
- deploy: "sst deploy --stage production",
100
- remove: "sst remove",
101
- seed: "npx tsx src/seed.ts",
102
- "copy-assets": "node copy-assets.js"
103
- },
104
- dependencies: {
105
- "@authhero/aws": "latest",
106
- "@authhero/widget": "latest",
107
- "@aws-sdk/client-dynamodb": "^3.0.0",
108
- "@aws-sdk/lib-dynamodb": "^3.0.0",
109
- "@hono/swagger-ui": "^0.5.0",
110
- "@hono/zod-openapi": "^0.19.0",
111
- authhero: "latest",
112
- hono: "^4.6.0",
113
- ...e && { "@authhero/multi-tenancy": "latest" },
114
- ...o && { bcryptjs: "latest" }
115
- },
116
- devDependencies: {
117
- "@types/aws-lambda": "^8.10.0",
118
- "@types/node": "^20.0.0",
119
- sst: "^3.0.0",
120
- tsx: "^4.0.0",
121
- typescript: "^5.5.0"
122
- }
123
- }),
99
+ packageJson: (o, e, r, n) => {
100
+ const t = n ? "workspace:*" : "latest";
101
+ return {
102
+ name: o,
103
+ version: "1.0.0",
104
+ type: "module",
105
+ scripts: {
106
+ dev: "sst dev",
107
+ deploy: "sst deploy --stage production",
108
+ remove: "sst remove",
109
+ seed: "npx tsx src/seed.ts",
110
+ "copy-assets": "node copy-assets.js"
111
+ },
112
+ dependencies: {
113
+ "@authhero/aws": t,
114
+ "@authhero/widget": t,
115
+ "@aws-sdk/client-dynamodb": "^3.0.0",
116
+ "@aws-sdk/lib-dynamodb": "^3.0.0",
117
+ "@hono/swagger-ui": "^0.5.0",
118
+ "@hono/zod-openapi": "^0.19.0",
119
+ authhero: t,
120
+ hono: "^4.6.0",
121
+ ...e && { "@authhero/multi-tenancy": t },
122
+ ...r && { bcryptjs: "latest" }
123
+ },
124
+ devDependencies: {
125
+ "@types/aws-lambda": "^8.10.0",
126
+ "@types/node": "^20.0.0",
127
+ sst: "^3.0.0",
128
+ tsx: "^4.0.0",
129
+ typescript: "^5.5.0"
130
+ }
131
+ };
132
+ },
124
133
  seedFile: "seed.ts"
125
134
  }
126
135
  };
127
- function E(t, e) {
128
- s.readdirSync(t).forEach((r) => {
129
- const n = l.join(t, r), a = l.join(e, r);
130
- s.lstatSync(n).isDirectory() ? (s.mkdirSync(a, { recursive: !0 }), E(n, a)) : s.copyFileSync(n, a);
136
+ function P(o, e) {
137
+ a.readdirSync(o).forEach((n) => {
138
+ const t = l.join(o, n), s = l.join(e, n);
139
+ a.lstatSync(t).isDirectory() ? (a.mkdirSync(s, { recursive: !0 }), P(t, s)) : a.copyFileSync(t, s);
131
140
  });
132
141
  }
133
- function R(t, e = !1, o = "authhero-local") {
134
- const r = t ? "control_plane" : "main", n = t ? "Control Plane" : "Main", a = [
142
+ function O(o, e = !1, r = "authhero-local") {
143
+ const n = o ? "control_plane" : "main", t = o ? "Control Plane" : "Main", s = [
135
144
  "https://manage.authhero.net/auth-callback",
136
145
  "https://local.authhero.net/auth-callback",
137
146
  "http://localhost:5173/auth-callback",
138
147
  "https://localhost:3000/auth-callback"
139
148
  ], c = e ? [
140
- `https://localhost.emobix.co.uk:8443/test/a/${o}/callback`,
141
- `https://localhost:8443/test/a/${o}/callback`
142
- ] : [], g = [...a, ...c], w = [
149
+ `https://localhost.emobix.co.uk:8443/test/a/${r}/callback`,
150
+ `https://localhost:8443/test/a/${r}/callback`
151
+ ] : [], g = [...s, ...c], w = [
143
152
  "https://manage.authhero.net",
144
153
  "https://local.authhero.net",
145
154
  "http://localhost:5173",
146
155
  "https://localhost:3000"
147
- ], y = e ? ["https://localhost:8443/", "https://localhost.emobix.co.uk:8443/"] : [], x = [...w, ...y], v = e ? `
156
+ ], A = e ? ["https://localhost:8443/", "https://localhost.emobix.co.uk:8443/"] : [], y = [...w, ...A], k = e ? `
148
157
  // Create OpenID Conformance Suite test clients and user
149
158
  console.log("Creating conformance test clients and user...");
150
159
 
151
160
  const conformanceCallbacks = [
152
- "https://localhost.emobix.co.uk:8443/test/a/${o}/callback",
153
- "https://localhost:8443/test/a/${o}/callback",
161
+ "https://localhost.emobix.co.uk:8443/test/a/${r}/callback",
162
+ "https://localhost:8443/test/a/${r}/callback",
154
163
  ];
155
164
  const conformanceLogoutUrls = [
156
165
  "https://localhost:8443/",
@@ -162,7 +171,7 @@ function R(t, e = !1, o = "authhero-local") {
162
171
  ];
163
172
 
164
173
  try {
165
- await adapters.clients.create("${r}", {
174
+ await adapters.clients.create("${n}", {
166
175
  client_id: "conformance-test",
167
176
  client_secret: "conformanceTestSecret123",
168
177
  name: "Conformance Test Client",
@@ -180,7 +189,7 @@ function R(t, e = !1, o = "authhero-local") {
180
189
  }
181
190
 
182
191
  try {
183
- await adapters.clients.create("${r}", {
192
+ await adapters.clients.create("${n}", {
184
193
  client_id: "conformance-test2",
185
194
  client_secret: "conformanceTestSecret456",
186
195
  name: "Conformance Test Client 2",
@@ -200,7 +209,7 @@ function R(t, e = !1, o = "authhero-local") {
200
209
  // Create a conformance test user with ALL OIDC profile claims populated
201
210
  // This is required for OIDCC-5.4 (VerifyScopesReturnedInUserInfoClaims) test
202
211
  try {
203
- await adapters.users.create("${r}", {
212
+ await adapters.users.create("${n}", {
204
213
  user_id: "auth2|conformance-user",
205
214
  email: "conformance@example.com",
206
215
  email_verified: true,
@@ -235,7 +244,7 @@ function R(t, e = !1, o = "authhero-local") {
235
244
  try {
236
245
  const bcrypt = await import("bcryptjs");
237
246
  const hashedPassword = await bcrypt.hash("ConformanceTest123!", 10);
238
- await adapters.passwords.create("${r}", {
247
+ await adapters.passwords.create("${n}", {
239
248
  user_id: "auth2|conformance-user",
240
249
  password: hashedPassword,
241
250
  });
@@ -273,21 +282,21 @@ async function main() {
273
282
  await seed(adapters, {
274
283
  adminEmail,
275
284
  adminPassword,
276
- tenantId: "${r}",
277
- tenantName: "${n}",
278
- isControlPlane: ${t},
285
+ tenantId: "${n}",
286
+ tenantName: "${t}",
287
+ isControlPlane: ${o},
279
288
  callbacks: ${JSON.stringify(g)},
280
- allowedLogoutUrls: ${JSON.stringify(x)},
289
+ allowedLogoutUrls: ${JSON.stringify(y)},
281
290
  });
282
- ${v}
291
+ ${k}
283
292
  await db.destroy();
284
293
  }
285
294
 
286
295
  main().catch(console.error);
287
296
  `;
288
297
  }
289
- function O(t) {
290
- return t ? `import { Context } from "hono";
298
+ function j(o) {
299
+ return o ? `import { Context } from "hono";
291
300
  import { swaggerUI } from "@hono/swagger-ui";
292
301
  import { AuthHeroConfig, DataAdapters } from "authhero";
293
302
  import { serveStatic } from "@hono/node-server/serve-static";
@@ -390,7 +399,7 @@ export default function createApp(config: AuthHeroConfig) {
390
399
  }
391
400
  `;
392
401
  }
393
- function j(t) {
402
+ function U(o) {
394
403
  return `import { D1Dialect } from "kysely-d1";
395
404
  import { Kysely } from "kysely";
396
405
  import createAdapters from "@authhero/kysely-adapter";
@@ -430,9 +439,9 @@ export default {
430
439
  adminEmail,
431
440
  adminPassword,
432
441
  issuer,
433
- tenantId: "${t ? "control_plane" : "main"}",
434
- tenantName: "${t ? "Control Plane" : "Main"}",
435
- isControlPlane: ${t},
442
+ tenantId: "${o ? "control_plane" : "main"}",
443
+ tenantName: "${o ? "Control Plane" : "Main"}",
444
+ isControlPlane: ${o},
436
445
  });
437
446
 
438
447
  return new Response(
@@ -463,8 +472,8 @@ export default {
463
472
  };
464
473
  `;
465
474
  }
466
- function U(t) {
467
- return t ? `import { Context } from "hono";
475
+ function M(o) {
476
+ return o ? `import { Context } from "hono";
468
477
  import { swaggerUI } from "@hono/swagger-ui";
469
478
  import { AuthHeroConfig, DataAdapters } from "authhero";
470
479
  import { initMultiTenant } from "@authhero/multi-tenancy";
@@ -543,8 +552,8 @@ export default function createApp(config: AuthHeroConfig) {
543
552
  }
544
553
  `;
545
554
  }
546
- function M(t) {
547
- return t ? `import { Context } from "hono";
555
+ function $(o) {
556
+ return o ? `import { Context } from "hono";
548
557
  import { swaggerUI } from "@hono/swagger-ui";
549
558
  import { AuthHeroConfig, DataAdapters } from "authhero";
550
559
  import { initMultiTenant } from "@authhero/multi-tenancy";
@@ -649,7 +658,7 @@ export default function createApp(config: AppConfig) {
649
658
  }
650
659
  `;
651
660
  }
652
- function $(t) {
661
+ function H(o) {
653
662
  return `import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
654
663
  import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";
655
664
  import createAdapters from "@authhero/aws";
@@ -684,9 +693,9 @@ async function main() {
684
693
  await seed(adapters, {
685
694
  adminEmail,
686
695
  adminPassword,
687
- tenantId: "${t ? "control_plane" : "main"}",
688
- tenantName: "${t ? "Control Plane" : "Main"}",
689
- isControlPlane: ${t},
696
+ tenantId: "${o ? "control_plane" : "main"}",
697
+ tenantName: "${o ? "Control Plane" : "Main"}",
698
+ isControlPlane: ${o},
690
699
  });
691
700
 
692
701
  console.log("✅ Database seeded successfully!");
@@ -695,23 +704,23 @@ async function main() {
695
704
  main().catch(console.error);
696
705
  `;
697
706
  }
698
- function H(t, e) {
699
- const o = l.join(t, "src");
700
- s.writeFileSync(
701
- l.join(o, "app.ts"),
702
- M(e)
703
- ), s.writeFileSync(
704
- l.join(o, "seed.ts"),
707
+ function F(o, e) {
708
+ const r = l.join(o, "src");
709
+ a.writeFileSync(
710
+ l.join(r, "app.ts"),
705
711
  $(e)
712
+ ), a.writeFileSync(
713
+ l.join(r, "seed.ts"),
714
+ H(e)
706
715
  );
707
716
  }
708
- function I(t) {
709
- console.log("\\n" + "─".repeat(50)), console.log("🔐 AuthHero deployed to AWS!"), console.log("📚 Check SST output for your API URL"), console.log("🌐 Portal available at https://local.authhero.net"), console.log(t ? "🏢 Multi-tenant mode enabled with control_plane tenant" : "🏠 Single-tenant mode with 'main' tenant"), console.log("─".repeat(50) + "\\n");
717
+ function I(o) {
718
+ console.log("\\n" + "─".repeat(50)), console.log("🔐 AuthHero deployed to AWS!"), console.log("📚 Check SST output for your API URL"), console.log("🌐 Portal available at https://local.authhero.net"), console.log(o ? "🏢 Multi-tenant mode enabled with control_plane tenant" : "🏠 Single-tenant mode with 'main' tenant"), console.log("─".repeat(50) + "\\n");
710
719
  }
711
- function F(t) {
712
- const e = l.join(t, ".github", "workflows");
713
- s.mkdirSync(e, { recursive: !0 });
714
- const o = `name: Unit tests
720
+ function W(o) {
721
+ const e = l.join(o, ".github", "workflows");
722
+ a.mkdirSync(e, { recursive: !0 });
723
+ const r = `name: Unit tests
715
724
 
716
725
  on: push
717
726
 
@@ -732,7 +741,7 @@ jobs:
732
741
 
733
742
  - run: npm run type-check
734
743
  - run: npm test
735
- `, r = `name: Deploy to Dev
744
+ `, n = `name: Deploy to Dev
736
745
 
737
746
  on:
738
747
  push:
@@ -768,7 +777,7 @@ jobs:
768
777
  with:
769
778
  apiToken: \${{ secrets.CLOUDFLARE_API_TOKEN }}
770
779
  command: deploy
771
- `, n = `name: Deploy to Production
780
+ `, t = `name: Deploy to Production
772
781
 
773
782
  on:
774
783
  release:
@@ -797,9 +806,9 @@ jobs:
797
806
  apiToken: \${{ secrets.PROD_CLOUDFLARE_API_TOKEN }}
798
807
  command: deploy --env production
799
808
  `;
800
- s.writeFileSync(l.join(e, "unit-tests.yml"), o), s.writeFileSync(l.join(e, "deploy-dev.yml"), r), s.writeFileSync(l.join(e, "release.yml"), n), console.log("\\n📦 GitHub CI workflows created!");
809
+ a.writeFileSync(l.join(e, "unit-tests.yml"), r), a.writeFileSync(l.join(e, "deploy-dev.yml"), n), a.writeFileSync(l.join(e, "release.yml"), t), console.log("\\n📦 GitHub CI workflows created!");
801
810
  }
802
- function W(t) {
811
+ function q(o) {
803
812
  const e = {
804
813
  branches: ["main"],
805
814
  plugins: [
@@ -808,78 +817,78 @@ function W(t) {
808
817
  "@semantic-release/github"
809
818
  ]
810
819
  };
811
- s.writeFileSync(
812
- l.join(t, ".releaserc.json"),
820
+ a.writeFileSync(
821
+ l.join(o, ".releaserc.json"),
813
822
  JSON.stringify(e, null, 2)
814
823
  );
815
- const o = l.join(t, "package.json"), r = JSON.parse(s.readFileSync(o, "utf-8"));
816
- r.devDependencies = {
817
- ...r.devDependencies,
824
+ const r = l.join(o, "package.json"), n = JSON.parse(a.readFileSync(r, "utf-8"));
825
+ n.devDependencies = {
826
+ ...n.devDependencies,
818
827
  "semantic-release": "^24.0.0"
819
- }, r.scripts = {
820
- ...r.scripts,
828
+ }, n.scripts = {
829
+ ...n.scripts,
821
830
  test: 'echo "No tests yet"',
822
831
  "type-check": "tsc --noEmit"
823
- }, s.writeFileSync(o, JSON.stringify(r, null, 2));
832
+ }, a.writeFileSync(r, JSON.stringify(n, null, 2));
824
833
  }
825
- function b(t, e) {
826
- return new Promise((o, r) => {
827
- const n = N(t, [], {
834
+ function b(o, e) {
835
+ return new Promise((r, n) => {
836
+ const t = T(o, [], {
828
837
  cwd: e,
829
838
  shell: !0,
830
839
  stdio: "inherit"
831
840
  });
832
- n.on("close", (a) => {
833
- a === 0 ? o() : r(new Error(`Command failed with exit code ${a}`));
834
- }), n.on("error", r);
841
+ t.on("close", (s) => {
842
+ s === 0 ? r() : n(new Error(`Command failed with exit code ${s}`));
843
+ }), t.on("error", n);
835
844
  });
836
845
  }
837
- function D(t, e, o) {
838
- return new Promise((r, n) => {
839
- const a = N(t, [], {
846
+ function D(o, e, r) {
847
+ return new Promise((n, t) => {
848
+ const s = T(o, [], {
840
849
  cwd: e,
841
850
  shell: !0,
842
851
  stdio: "inherit",
843
- env: { ...process.env, ...o }
852
+ env: { ...process.env, ...r }
844
853
  });
845
- a.on("close", (c) => {
846
- c === 0 ? r() : n(new Error(`Command failed with exit code ${c}`));
847
- }), a.on("error", n);
854
+ s.on("close", (c) => {
855
+ c === 0 ? n() : t(new Error(`Command failed with exit code ${c}`));
856
+ }), s.on("error", t);
848
857
  });
849
858
  }
850
- function q(t, e) {
851
- const o = l.join(t, "src");
852
- s.writeFileSync(
853
- l.join(o, "app.ts"),
859
+ function B(o, e) {
860
+ const r = l.join(o, "src");
861
+ a.writeFileSync(
862
+ l.join(r, "app.ts"),
863
+ M(e)
864
+ ), a.writeFileSync(
865
+ l.join(r, "seed.ts"),
854
866
  U(e)
855
- ), s.writeFileSync(
856
- l.join(o, "seed.ts"),
857
- j(e)
858
867
  );
859
868
  }
860
- function k(t) {
869
+ function _(o) {
861
870
  console.log(`
862
- ` + "─".repeat(50)), console.log("🔐 AuthHero server running at https://localhost:3000"), console.log("📚 API documentation available at https://localhost:3000/docs"), console.log("🌐 Portal available at https://local.authhero.net"), console.log(t ? "🏢 Multi-tenant mode enabled with control_plane tenant" : "🏠 Single-tenant mode with 'main' tenant"), console.log("─".repeat(50) + `
871
+ ` + "─".repeat(50)), console.log("🔐 AuthHero server running at https://localhost:3000"), console.log("📚 API documentation available at https://localhost:3000/docs"), console.log("🌐 Portal available at https://local.authhero.net"), console.log(o ? "🏢 Multi-tenant mode enabled with control_plane tenant" : "🏠 Single-tenant mode with 'main' tenant"), console.log("─".repeat(50) + `
863
872
  `);
864
873
  }
865
- function _(t) {
874
+ function N(o) {
866
875
  console.log(`
867
- ` + "─".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 https://localhost:3000"), console.log("📚 API documentation available at https://localhost:3000/docs"), console.log("🌐 Portal available at https://local.authhero.net"), console.log(t ? "🏢 Multi-tenant mode enabled with control_plane tenant" : "🏠 Single-tenant mode with 'main' tenant"), console.log("─".repeat(50) + `
876
+ ` + "─".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 https://localhost:3000"), console.log("📚 API documentation available at https://localhost:3000/docs"), console.log("🌐 Portal available at https://local.authhero.net"), console.log(o ? "🏢 Multi-tenant mode enabled with control_plane tenant" : "🏠 Single-tenant mode with 'main' tenant"), console.log("─".repeat(50) + `
868
877
  `);
869
878
  }
870
- T.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("-e, --email <email>", "admin email address").option("-p, --password <password>", "admin password (min 8 characters)").option(
879
+ E.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("-e, --email <email>", "admin email address").option("-p, --password <password>", "admin password (min 8 characters)").option(
871
880
  "--package-manager <pm>",
872
881
  "package manager to use: npm, yarn, pnpm, or bun"
873
882
  ).option("--multi-tenant", "enable multi-tenant mode").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("--github-ci", "include GitHub CI workflows with semantic versioning").option("--conformance", "add OpenID conformance suite test clients").option(
874
883
  "--conformance-alias <alias>",
875
884
  "alias for conformance suite (default: authhero-local)"
876
- ).option("-y, --yes", "skip all prompts and use defaults/provided options").action(async (t, e) => {
877
- const o = e.yes === !0;
885
+ ).option("--workspace", "use workspace:* dependencies for local monorepo development").option("-y, --yes", "skip all prompts and use defaults/provided options").action(async (o, e) => {
886
+ const r = e.yes === !0;
878
887
  console.log(`
879
888
  🔐 Welcome to AuthHero!
880
889
  `);
881
- let r = t;
882
- r || (o ? (r = "auth-server", console.log(`Using default project name: ${r}`)) : r = (await u.prompt([
890
+ let n = o;
891
+ n || (r ? (n = "auth-server", console.log(`Using default project name: ${n}`)) : n = (await u.prompt([
883
892
  {
884
893
  type: "input",
885
894
  name: "projectName",
@@ -888,10 +897,10 @@ T.version("1.0.0").description("Create a new AuthHero project").argument("[proje
888
897
  validate: (d) => d !== "" || "Project name cannot be empty"
889
898
  }
890
899
  ])).projectName);
891
- const n = l.join(process.cwd(), r);
892
- s.existsSync(n) && (console.error(`❌ Project "${r}" already exists.`), process.exit(1));
893
- let a;
894
- 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)), a = e.template, console.log(`Using template: ${p[a].name}`)) : a = (await u.prompt([
900
+ const t = l.join(process.cwd(), n);
901
+ a.existsSync(t) && (console.error(`❌ Project "${n}" already exists.`), process.exit(1));
902
+ let s;
903
+ 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)), s = e.template, console.log(`Using template: ${p[s].name}`)) : s = (await u.prompt([
895
904
  {
896
905
  type: "list",
897
906
  name: "setupType",
@@ -919,7 +928,7 @@ T.version("1.0.0").description("Create a new AuthHero project").argument("[proje
919
928
  }
920
929
  ])).setupType;
921
930
  let c;
922
- e.multiTenant !== void 0 ? (c = e.multiTenant, console.log(`Multi-tenant mode: ${c ? "enabled" : "disabled"}`)) : o ? c = !1 : c = (await u.prompt([
931
+ e.multiTenant !== void 0 ? (c = e.multiTenant, console.log(`Multi-tenant mode: ${c ? "enabled" : "disabled"}`)) : r ? c = !1 : c = (await u.prompt([
923
932
  {
924
933
  type: "confirm",
925
934
  name: "multiTenant",
@@ -932,42 +941,44 @@ T.version("1.0.0").description("Create a new AuthHero project").argument("[proje
932
941
  g && console.log(
933
942
  `OpenID Conformance Suite: enabled (alias: ${w})`
934
943
  );
935
- const y = p[a];
936
- s.mkdirSync(n, { recursive: !0 }), s.writeFileSync(
937
- l.join(n, "package.json"),
938
- JSON.stringify(y.packageJson(r, c, g), null, 2)
944
+ const A = e.workspace || !1;
945
+ A && console.log("Workspace mode: enabled (using workspace:* dependencies)");
946
+ const y = p[s];
947
+ a.mkdirSync(t, { recursive: !0 }), a.writeFileSync(
948
+ l.join(t, "package.json"),
949
+ JSON.stringify(y.packageJson(n, c, g, A), null, 2)
939
950
  );
940
- const x = y.templateDir, v = l.join(
951
+ const k = y.templateDir, x = l.join(
941
952
  import.meta.url.replace("file://", "").replace("/create-authhero.js", ""),
942
- x
953
+ k
943
954
  );
944
- if (s.existsSync(v) ? E(v, n) : (console.error(`❌ Template directory not found: ${v}`), process.exit(1)), a === "cloudflare" && q(n, c), a === "cloudflare") {
945
- const i = l.join(n, "wrangler.toml"), d = l.join(n, "wrangler.local.toml");
946
- s.existsSync(i) && s.copyFileSync(i, d);
947
- const m = l.join(n, ".dev.vars.example"), f = l.join(n, ".dev.vars");
948
- s.existsSync(m) && s.copyFileSync(m, f), console.log(
955
+ if (a.existsSync(x) ? P(x, t) : (console.error(`❌ Template directory not found: ${x}`), process.exit(1)), s === "cloudflare" && B(t, c), s === "cloudflare") {
956
+ const i = l.join(t, "wrangler.toml"), d = l.join(t, "wrangler.local.toml");
957
+ a.existsSync(i) && a.copyFileSync(i, d);
958
+ const m = l.join(t, ".dev.vars.example"), f = l.join(t, ".dev.vars");
959
+ a.existsSync(m) && a.copyFileSync(m, f), console.log(
949
960
  "📁 Created wrangler.local.toml and .dev.vars for local development"
950
961
  );
951
962
  }
952
963
  let C = !1;
953
- if (a === "cloudflare" && (e.githubCi !== void 0 ? (C = e.githubCi, C && console.log("Including GitHub CI workflows with semantic versioning")) : o || (C = (await u.prompt([
964
+ if (s === "cloudflare" && (e.githubCi !== void 0 ? (C = e.githubCi, C && console.log("Including GitHub CI workflows with semantic versioning")) : r || (C = (await u.prompt([
954
965
  {
955
966
  type: "confirm",
956
967
  name: "includeGithubCi",
957
968
  message: "Would you like to include GitHub CI with semantic versioning?",
958
969
  default: !1
959
970
  }
960
- ])).includeGithubCi), C && (F(n), W(n))), a === "local") {
961
- const i = R(
971
+ ])).includeGithubCi), C && (W(t), q(t))), s === "local") {
972
+ const i = O(
962
973
  c,
963
974
  g,
964
975
  w
965
976
  );
966
- s.writeFileSync(l.join(n, "src/seed.ts"), i);
967
- const d = O(c);
968
- s.writeFileSync(l.join(n, "src/app.ts"), d);
977
+ a.writeFileSync(l.join(t, "src/seed.ts"), i);
978
+ const d = j(c);
979
+ a.writeFileSync(l.join(t, "src/app.ts"), d);
969
980
  }
970
- if (a === "aws-sst" && H(n, c), g) {
981
+ if (s === "aws-sst" && F(t, c), g) {
971
982
  const i = {
972
983
  alias: w,
973
984
  description: "AuthHero Conformance Test",
@@ -986,32 +997,32 @@ T.version("1.0.0").description("Create a new AuthHero project").argument("[proje
986
997
  resourceUrl: "http://host.docker.internal:3000/userinfo"
987
998
  }
988
999
  };
989
- s.writeFileSync(
990
- l.join(n, "conformance-config.json"),
1000
+ a.writeFileSync(
1001
+ l.join(t, "conformance-config.json"),
991
1002
  JSON.stringify(i, null, 2)
992
1003
  ), console.log(
993
1004
  "📝 Created conformance-config.json for OpenID Conformance Suite"
994
1005
  );
995
1006
  }
996
- const P = c ? "multi-tenant" : "single-tenant";
1007
+ const L = c ? "multi-tenant" : "single-tenant";
997
1008
  console.log(
998
1009
  `
999
- ✅ Project "${r}" has been created with ${y.name} (${P}) setup!
1010
+ ✅ Project "${n}" has been created with ${y.name} (${L}) setup!
1000
1011
  `
1001
1012
  );
1002
- let A;
1003
- if (e.skipInstall ? A = !1 : o ? A = !0 : A = (await u.prompt([
1013
+ let v;
1014
+ if (e.skipInstall ? v = !1 : r ? v = !0 : v = (await u.prompt([
1004
1015
  {
1005
1016
  type: "confirm",
1006
1017
  name: "shouldInstall",
1007
1018
  message: "Would you like to install dependencies now?",
1008
1019
  default: !0
1009
1020
  }
1010
- ])).shouldInstall, A) {
1021
+ ])).shouldInstall, v) {
1011
1022
  let i;
1012
1023
  e.packageManager ? (["npm", "yarn", "pnpm", "bun"].includes(e.packageManager) || (console.error(
1013
1024
  `❌ Invalid package manager: ${e.packageManager}`
1014
- ), console.error("Valid options: npm, yarn, pnpm, bun"), process.exit(1)), i = e.packageManager) : o ? i = "pnpm" : i = (await u.prompt([
1025
+ ), console.error("Valid options: npm, yarn, pnpm, bun"), process.exit(1)), i = e.packageManager) : r ? i = "pnpm" : i = (await u.prompt([
1015
1026
  {
1016
1027
  type: "list",
1017
1028
  name: "packageManager",
@@ -1029,13 +1040,13 @@ T.version("1.0.0").description("Create a new AuthHero project").argument("[proje
1029
1040
  `);
1030
1041
  try {
1031
1042
  const d = i === "pnpm" ? "pnpm install --ignore-workspace" : `${i} install`;
1032
- if (await b(d, n), a === "local" && (console.log(`
1043
+ if (await b(d, t), s === "local" && (console.log(`
1033
1044
  🔧 Building native modules...
1034
- `), await b("npm rebuild better-sqlite3", n)), console.log(`
1045
+ `), await b("npm rebuild better-sqlite3", t)), console.log(`
1035
1046
  ✅ Dependencies installed successfully!
1036
- `), a === "local" || a === "cloudflare") {
1047
+ `), s === "local" || s === "cloudflare") {
1037
1048
  let f;
1038
- if (e.skipMigrate && e.skipSeed ? f = !1 : o ? f = !e.skipMigrate || !e.skipSeed : f = (await u.prompt([
1049
+ if (e.skipMigrate && e.skipSeed ? f = !1 : r ? f = !e.skipMigrate || !e.skipSeed : f = (await u.prompt([
1039
1050
  {
1040
1051
  type: "confirm",
1041
1052
  name: "shouldSetup",
@@ -1064,18 +1075,18 @@ T.version("1.0.0").description("Create a new AuthHero project").argument("[proje
1064
1075
  }
1065
1076
  ]), e.skipMigrate || (console.log(`
1066
1077
  🔄 Running migrations...
1067
- `), await b(`${i} run migrate`, n)), e.skipSeed || (console.log(`
1078
+ `), await b(`${i} run migrate`, t)), e.skipSeed || (console.log(`
1068
1079
  🌱 Seeding database...
1069
- `), a === "local" ? await D(
1080
+ `), s === "local" ? await D(
1070
1081
  `${i} run seed`,
1071
- n,
1082
+ t,
1072
1083
  {
1073
1084
  ADMIN_EMAIL: h.username,
1074
1085
  ADMIN_PASSWORD: h.password
1075
1086
  }
1076
1087
  ) : await D(
1077
1088
  `${i} run seed:local`,
1078
- n,
1089
+ t,
1079
1090
  {
1080
1091
  ADMIN_EMAIL: h.username,
1081
1092
  ADMIN_PASSWORD: h.password
@@ -1084,29 +1095,29 @@ T.version("1.0.0").description("Create a new AuthHero project").argument("[proje
1084
1095
  }
1085
1096
  }
1086
1097
  let m;
1087
- e.skipStart || o ? m = !1 : m = (await u.prompt([
1098
+ e.skipStart || r ? m = !1 : m = (await u.prompt([
1088
1099
  {
1089
1100
  type: "confirm",
1090
1101
  name: "shouldStart",
1091
1102
  message: "Would you like to start the development server?",
1092
1103
  default: !0
1093
1104
  }
1094
- ])).shouldStart, m && (a === "cloudflare" ? k(c) : a === "aws-sst" ? I(c) : _(c), console.log(`🚀 Starting development server...
1095
- `), await b(`${i} run dev`, n)), o && !m && (console.log(`
1105
+ ])).shouldStart, m && (s === "cloudflare" ? _(c) : s === "aws-sst" ? I(c) : N(c), console.log(`🚀 Starting development server...
1106
+ `), await b(`${i} run dev`, t)), r && !m && (console.log(`
1096
1107
  ✅ Setup complete!`), console.log(`
1097
- To start the development server:`), console.log(` cd ${r}`), console.log(" npm run dev"), a === "cloudflare" ? k(c) : a === "aws-sst" ? I(c) : _(c));
1108
+ To start the development server:`), console.log(` cd ${n}`), console.log(" npm run dev"), s === "cloudflare" ? _(c) : s === "aws-sst" ? I(c) : N(c));
1098
1109
  } catch (d) {
1099
1110
  console.error(`
1100
1111
  ❌ An error occurred:`, d), process.exit(1);
1101
1112
  }
1102
1113
  }
1103
- A || (console.log("Next steps:"), console.log(` cd ${r}`), a === "local" ? (console.log(" npm install"), console.log(" npm run migrate"), console.log(
1114
+ v || (console.log("Next steps:"), console.log(` cd ${n}`), s === "local" ? (console.log(" npm install"), console.log(" npm run migrate"), console.log(
1104
1115
  " ADMIN_EMAIL=admin@example.com ADMIN_PASSWORD=yourpassword npm run seed"
1105
- ), console.log(" npm run dev")) : a === "cloudflare" ? (console.log(" npm install"), console.log(
1116
+ ), console.log(" npm run dev")) : s === "cloudflare" ? (console.log(" npm install"), console.log(
1106
1117
  " npm run migrate # or npm run db:migrate:remote for production"
1107
1118
  ), console.log(
1108
1119
  " ADMIN_EMAIL=admin@example.com ADMIN_PASSWORD=yourpassword npm run seed"
1109
- ), console.log(" npm run dev # or npm run dev:remote for production")) : a === "aws-sst" && (console.log(" npm install"), console.log(" npm run dev # Deploys to AWS in development mode"), console.log(" # After deploy, get TABLE_NAME from output, then:"), console.log(
1120
+ ), console.log(" npm run dev # or npm run dev:remote for production")) : s === "aws-sst" && (console.log(" npm install"), console.log(" npm run dev # Deploys to AWS in development mode"), console.log(" # After deploy, get TABLE_NAME from output, then:"), console.log(
1110
1121
  " TABLE_NAME=<your-table> ADMIN_EMAIL=admin@example.com ADMIN_PASSWORD=yourpassword npm run seed"
1111
1122
  )), console.log(`
1112
1123
  Server will be available at: https://localhost:3000`), console.log("Portal available at: https://local.authhero.net"), g && (console.log(`
@@ -1120,4 +1131,4 @@ Server will be available at: https://localhost:3000`), console.log("Portal avail
1120
1131
  For more information, visit: https://authhero.net/docs
1121
1132
  `));
1122
1133
  });
1123
- T.parse(process.argv);
1134
+ E.parse(process.argv);
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "type": "git",
6
6
  "url": "https://github.com/markusahlstrand/authhero"
7
7
  },
8
- "version": "0.26.0",
8
+ "version": "0.28.0",
9
9
  "type": "module",
10
10
  "main": "dist/create-authhero.js",
11
11
  "bin": {