create-authhero 0.39.0 → 0.41.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,18 +1,19 @@
1
1
  #!/usr/bin/env node
2
- import { Command as E } from "commander";
2
+ import { Command as R } from "commander";
3
3
  import m from "inquirer";
4
- import s from "fs";
5
- import i from "path";
6
- import { spawn as P } from "child_process";
7
- const D = new E(), p = {
4
+ import i from "fs";
5
+ import a from "path";
6
+ import { fileURLToPath as U } from "url";
7
+ import { spawn as O } from "child_process";
8
+ const T = new R(), p = {
8
9
  local: {
9
10
  name: "Local (SQLite)",
10
11
  description: "Local development setup with SQLite database - great for getting started",
11
12
  templateDir: "local",
12
- packageJson: (a, e, n, r, o) => {
13
+ packageJson: (s, e, o, r, n) => {
13
14
  const t = r ? "workspace:*" : "latest";
14
15
  return {
15
- name: a,
16
+ name: s,
16
17
  version: "1.0.0",
17
18
  type: "module",
18
19
  scripts: {
@@ -23,7 +24,7 @@ const D = new E(), p = {
23
24
  },
24
25
  dependencies: {
25
26
  "@authhero/kysely-adapter": t,
26
- ...o && { "@authhero/react-admin": t },
27
+ ...n && { "@authhero/react-admin": t },
27
28
  "@authhero/widget": t,
28
29
  "@hono/swagger-ui": "^0.5.0",
29
30
  "@hono/zod-openapi": "^0.19.0",
@@ -33,7 +34,7 @@ const D = new E(), p = {
33
34
  hono: "^4.6.0",
34
35
  kysely: "latest",
35
36
  ...e && { "@authhero/multi-tenancy": t },
36
- ...n && { bcryptjs: "latest" }
37
+ ...o && { bcryptjs: "latest" }
37
38
  },
38
39
  devDependencies: {
39
40
  "@types/better-sqlite3": "^7.6.0",
@@ -49,10 +50,10 @@ const D = new E(), p = {
49
50
  name: "Cloudflare Workers (D1)",
50
51
  description: "Cloudflare Workers setup with D1 database",
51
52
  templateDir: "cloudflare",
52
- packageJson: (a, e, n, r, o) => {
53
+ packageJson: (s, e, o, r, n) => {
53
54
  const t = r ? "workspace:*" : "latest";
54
55
  return {
55
- name: a,
56
+ name: s,
56
57
  version: "1.0.0",
57
58
  type: "module",
58
59
  scripts: {
@@ -72,7 +73,7 @@ const D = new E(), p = {
72
73
  dependencies: {
73
74
  "@authhero/drizzle": t,
74
75
  "@authhero/kysely-adapter": t,
75
- ...o && { "@authhero/react-admin": t },
76
+ ...n && { "@authhero/react-admin": t },
76
77
  "@authhero/widget": t,
77
78
  "@hono/swagger-ui": "^0.5.0",
78
79
  "@hono/zod-openapi": "^0.19.0",
@@ -81,7 +82,7 @@ const D = new E(), p = {
81
82
  kysely: "latest",
82
83
  "kysely-d1": "latest",
83
84
  ...e && { "@authhero/multi-tenancy": t },
84
- ...n && { bcryptjs: "latest" }
85
+ ...o && { bcryptjs: "latest" }
85
86
  },
86
87
  devDependencies: {
87
88
  "@cloudflare/workers-types": "^4.0.0",
@@ -98,10 +99,10 @@ const D = new E(), p = {
98
99
  name: "AWS SST (Lambda + DynamoDB)",
99
100
  description: "Serverless AWS deployment with Lambda, DynamoDB, and SST",
100
101
  templateDir: "aws-sst",
101
- packageJson: (a, e, n, r, o) => {
102
+ packageJson: (s, e, o, r, n) => {
102
103
  const t = r ? "workspace:*" : "latest";
103
104
  return {
104
- name: a,
105
+ name: s,
105
106
  version: "1.0.0",
106
107
  type: "module",
107
108
  scripts: {
@@ -113,7 +114,7 @@ const D = new E(), p = {
113
114
  },
114
115
  dependencies: {
115
116
  "@authhero/aws": t,
116
- ...o && { "@authhero/react-admin": t },
117
+ ...n && { "@authhero/react-admin": t },
117
118
  "@authhero/widget": t,
118
119
  "@aws-sdk/client-dynamodb": "^3.0.0",
119
120
  "@aws-sdk/lib-dynamodb": "^3.0.0",
@@ -122,7 +123,7 @@ const D = new E(), p = {
122
123
  authhero: t,
123
124
  hono: "^4.6.0",
124
125
  ...e && { "@authhero/multi-tenancy": t },
125
- ...n && { bcryptjs: "latest" }
126
+ ...o && { bcryptjs: "latest" }
126
127
  },
127
128
  devDependencies: {
128
129
  "@types/aws-lambda": "^8.10.0",
@@ -136,34 +137,42 @@ const D = new E(), p = {
136
137
  seedFile: "seed.ts"
137
138
  }
138
139
  };
139
- function N(a, e) {
140
- s.readdirSync(a).forEach((r) => {
141
- const o = i.join(a, r), t = i.join(e, r);
142
- s.lstatSync(o).isDirectory() ? (s.mkdirSync(t, { recursive: !0 }), N(o, t)) : s.copyFileSync(o, t);
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);
143
144
  });
144
145
  }
145
- function R(a, e = !1, n = "authhero-local", r) {
146
- const o = a ? "control_plane" : "main", t = a ? "Control Plane" : "Main", c = [
146
+ function L(s, e = !1, o = "authhero-local", r) {
147
+ const n = s ? "control_plane" : "main", t = s ? "Control Plane" : "Main", c = [
147
148
  "https://manage.authhero.net/auth-callback",
148
149
  "https://local.authhero.net/auth-callback",
149
150
  "http://localhost:5173/auth-callback",
150
151
  "http://localhost:3000/auth-callback",
151
152
  ...r ? ["http://localhost:3000/admin/auth-callback"] : []
152
153
  ], d = e ? [
153
- `https://localhost.emobix.co.uk:8443/test/a/${n}/callback`,
154
- `https://localhost:8443/test/a/${n}/callback`
154
+ `https://localhost.emobix.co.uk:8443/test/a/${o}/callback`,
155
+ `https://localhost:8443/test/a/${o}/callback`
155
156
  ] : [], f = [...c, ...d], h = [
156
157
  "https://manage.authhero.net",
157
158
  "https://local.authhero.net",
158
159
  "http://localhost:5173",
159
160
  "http://localhost:3000"
160
- ], C = e ? ["https://localhost:8443/", "https://localhost.emobix.co.uk:8443/"] : [], y = [...h, ...C], S = e ? `
161
+ ], C = e ? ["https://localhost:8443/", "https://localhost.emobix.co.uk:8443/"] : [], y = [...h, ...C], A = e ? `
161
162
  // Create OpenID Conformance Suite test clients and user
162
163
  console.log("Creating conformance test clients and user...");
163
-
164
+
165
+ // The OIDCC basic test plan calls /token without an audience param. AuthHero
166
+ // requires either an explicit audience or a tenant default_audience to mint
167
+ // an access token, so set one here for the conformance setup.
168
+ await adapters.tenants.update("${n}", {
169
+ default_audience: "urn:authhero:management",
170
+ });
171
+ console.log("✅ Set tenant default_audience for conformance");
172
+
164
173
  const conformanceCallbacks = [
165
- "https://localhost.emobix.co.uk:8443/test/a/${n}/callback",
166
- "https://localhost:8443/test/a/${n}/callback",
174
+ "https://localhost.emobix.co.uk:8443/test/a/${o}/callback",
175
+ "https://localhost:8443/test/a/${o}/callback",
167
176
  ];
168
177
  const conformanceLogoutUrls = [
169
178
  "https://localhost:8443/",
@@ -175,7 +184,7 @@ function R(a, e = !1, n = "authhero-local", r) {
175
184
  ];
176
185
 
177
186
  try {
178
- await adapters.clients.create("${o}", {
187
+ await adapters.clients.create("${n}", {
179
188
  client_id: "conformance-test",
180
189
  client_secret: "conformanceTestSecret123",
181
190
  name: "Conformance Test Client",
@@ -193,7 +202,7 @@ function R(a, e = !1, n = "authhero-local", r) {
193
202
  }
194
203
 
195
204
  try {
196
- await adapters.clients.create("${o}", {
205
+ await adapters.clients.create("${n}", {
197
206
  client_id: "conformance-test2",
198
207
  client_secret: "conformanceTestSecret456",
199
208
  name: "Conformance Test Client 2",
@@ -213,7 +222,7 @@ function R(a, e = !1, n = "authhero-local", r) {
213
222
  // Create a conformance test user with ALL OIDC profile claims populated
214
223
  // This is required for OIDCC-5.4 (VerifyScopesReturnedInUserInfoClaims) test
215
224
  try {
216
- await adapters.users.create("${o}", {
225
+ await adapters.users.create("${n}", {
217
226
  user_id: \`\${USERNAME_PASSWORD_PROVIDER}|conformance-user\`,
218
227
  email: "conformance@example.com",
219
228
  email_verified: true,
@@ -248,7 +257,7 @@ function R(a, e = !1, n = "authhero-local", r) {
248
257
  try {
249
258
  const bcrypt = await import("bcryptjs");
250
259
  const hashedPassword = await bcrypt.hash("ConformanceTest123!", 10);
251
- await adapters.passwords.create("${o}", {
260
+ await adapters.passwords.create("${n}", {
252
261
  user_id: \`\${USERNAME_PASSWORD_PROVIDER}|conformance-user\`,
253
262
  password: hashedPassword,
254
263
  });
@@ -266,9 +275,51 @@ import Database from "better-sqlite3";
266
275
  import createAdapters from "@authhero/kysely-adapter";
267
276
  import { seed } from "authhero";
268
277
 
278
+ interface ExtraClient {
279
+ client_id: string;
280
+ client_secret: string;
281
+ name?: string;
282
+ callbacks?: string[];
283
+ allowed_logout_urls?: string[];
284
+ web_origins?: string[];
285
+ }
286
+
287
+ function parseFlag(name: string): string | undefined {
288
+ const argv = process.argv.slice(2);
289
+ const eqPrefix = \`--\${name}=\`;
290
+ for (let i = 0; i < argv.length; i++) {
291
+ const arg = argv[i]!;
292
+ if (arg === \`--\${name}\`) return argv[i + 1];
293
+ if (arg.startsWith(eqPrefix)) return arg.slice(eqPrefix.length);
294
+ }
295
+ return undefined;
296
+ }
297
+
298
+ function positionalArgs(): string[] {
299
+ const out: string[] = [];
300
+ const argv = process.argv.slice(2);
301
+ for (let i = 0; i < argv.length; i++) {
302
+ const arg = argv[i]!;
303
+ if (arg.startsWith("--")) {
304
+ if (!arg.includes("=")) i++;
305
+ continue;
306
+ }
307
+ out.push(arg);
308
+ }
309
+ return out;
310
+ }
311
+
269
312
  async function main() {
270
- const adminUsername = process.argv[2] || process.env.ADMIN_USERNAME || "admin";
271
- const adminPassword = process.argv[3] || process.env.ADMIN_PASSWORD || "admin";
313
+ const positional = positionalArgs();
314
+ const adminUsername = positional[0] || process.env.ADMIN_USERNAME || "admin";
315
+ const adminPassword = positional[1] || process.env.ADMIN_PASSWORD || "admin";
316
+
317
+ const clientsJson = parseFlag("clients");
318
+ const userProfileJson = parseFlag("user-profile");
319
+ const extraClients: ExtraClient[] = clientsJson ? JSON.parse(clientsJson) : [];
320
+ const userProfile: Record<string, unknown> = userProfileJson
321
+ ? JSON.parse(userProfileJson)
322
+ : {};
272
323
 
273
324
  const dialect = new SqliteDialect({
274
325
  database: new Database("db.sqlite"),
@@ -277,32 +328,59 @@ async function main() {
277
328
  const db = new Kysely<any>({ dialect });
278
329
  const adapters = createAdapters(db);
279
330
 
280
- await seed(adapters, {
331
+ const seedResult = await seed(adapters, {
281
332
  adminUsername,
282
333
  adminPassword,
283
- tenantId: "${o}",
334
+ tenantId: "${n}",
284
335
  tenantName: "${t}",
285
- isControlPlane: ${!!a},
336
+ isControlPlane: ${!!s},
286
337
  clientId: "default",
287
338
  callbacks: ${JSON.stringify(f)},
288
339
  allowedLogoutUrls: ${JSON.stringify(y)},
289
340
  });
290
- ${S}
341
+
342
+ for (const c of extraClients) {
343
+ const existing = await adapters.clients.get(seedResult.tenantId, c.client_id);
344
+ if (existing) {
345
+ console.log(\`Client "\${c.client_id}" already exists, skipping...\`);
346
+ continue;
347
+ }
348
+ await adapters.clients.create(seedResult.tenantId, {
349
+ client_id: c.client_id,
350
+ client_secret: c.client_secret,
351
+ name: c.name ?? c.client_id,
352
+ callbacks: c.callbacks ?? [],
353
+ allowed_logout_urls: c.allowed_logout_urls ?? [],
354
+ web_origins: c.web_origins ?? [],
355
+ connections: ["Username-Password-Authentication"],
356
+ client_metadata: { universal_login_version: "2" },
357
+ });
358
+ console.log(\`✅ Created client "\${c.client_id}"\`);
359
+ }
360
+
361
+ if (Object.keys(userProfile).length > 0) {
362
+ await adapters.users.update(seedResult.tenantId, seedResult.userId, userProfile);
363
+ console.log(\`✅ Updated profile of user "\${seedResult.username}"\`);
364
+ }
365
+ ${A}
291
366
  await db.destroy();
292
367
  }
293
368
 
294
- main().catch(console.error);
369
+ main().catch((err) => {
370
+ console.error(err);
371
+ process.exit(1);
372
+ });
295
373
  `;
296
374
  }
297
- function U(a, e) {
298
- const n = e ? `import fs from "fs";
375
+ function $(s, e) {
376
+ const o = e ? `import fs from "fs";
299
377
  ` : "", r = e ? `
300
378
  const adminDistPath = path.resolve(
301
379
  __dirname,
302
380
  "../node_modules/@authhero/react-admin/dist",
303
381
  );
304
382
  const adminIndexPath = path.join(adminDistPath, "index.html");
305
- ` : "", o = e ? `
383
+ ` : "", n = e ? `
306
384
  // Add admin UI handler if the package is installed
307
385
  if (fs.existsSync(adminIndexPath)) {
308
386
  const issuer =
@@ -312,7 +390,7 @@ const adminIndexPath = path.join(adminDistPath, "index.html");
312
390
  .replace(/href="\\.\\//g, 'href="/admin/');
313
391
  const configJson = JSON.stringify({
314
392
  domain: issuer.replace(/\\/$/, ""),
315
- clientId: ${a ? "CONTROL_PLANE_CLIENT_ID," : '"default",'}
393
+ clientId: ${s ? "CONTROL_PLANE_CLIENT_ID," : '"default",'}
316
394
  basePath: "/admin",
317
395
  }).replace(/</g, "\\\\u003c");
318
396
  configWithHandlers.adminIndexHtml = rawHtml.replace(
@@ -325,13 +403,13 @@ const adminIndexPath = path.join(adminDistPath, "index.html");
325
403
  });
326
404
  }
327
405
  ` : "";
328
- return a ? `import { Context } from "hono";
406
+ return s ? `import { Context } from "hono";
329
407
  import { swaggerUI } from "@hono/swagger-ui";
330
408
  import { AuthHeroConfig, DataAdapters } from "authhero";
331
409
  import { serveStatic } from "@hono/node-server/serve-static";
332
410
  import { initMultiTenant } from "@authhero/multi-tenancy";
333
411
  import path from "path";
334
- ${n}import { fileURLToPath } from "url";
412
+ ${o}import { fileURLToPath } from "url";
335
413
 
336
414
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
337
415
 
@@ -352,7 +430,7 @@ export default function createApp(config: AuthHeroConfig & { dataAdapter: DataAd
352
430
  rewriteRequestPath: (p) => p.replace("/u/widget", ""),
353
431
  }),
354
432
  };
355
- ${o}
433
+ ${n}
356
434
  // Initialize multi-tenant AuthHero - syncs resource servers, roles, and connections by default
357
435
  const { app } = initMultiTenant({
358
436
  ...configWithHandlers,
@@ -389,7 +467,7 @@ import { AuthHeroConfig, init } from "authhero";
389
467
  import { swaggerUI } from "@hono/swagger-ui";
390
468
  import { serveStatic } from "@hono/node-server/serve-static";
391
469
  import path from "path";
392
- ${n}import { fileURLToPath } from "url";
470
+ ${o}import { fileURLToPath } from "url";
393
471
 
394
472
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
395
473
 
@@ -406,7 +484,7 @@ export default function createApp(config: AuthHeroConfig) {
406
484
  rewriteRequestPath: (p) => p.replace("/u/widget", ""),
407
485
  }),
408
486
  };
409
- ${o}
487
+ ${n}
410
488
  const { app } = init(configWithHandlers);
411
489
 
412
490
  app
@@ -430,7 +508,7 @@ ${o}
430
508
  }
431
509
  `;
432
510
  }
433
- function O(a) {
511
+ function j(s) {
434
512
  return `import { D1Dialect } from "kysely-d1";
435
513
  import { Kysely } from "kysely";
436
514
  import createAdapters from "@authhero/kysely-adapter";
@@ -457,9 +535,9 @@ export default {
457
535
  adminUsername,
458
536
  adminPassword,
459
537
  issuer,
460
- tenantId: "${a ? "control_plane" : "main"}",
461
- tenantName: "${a ? "Control Plane" : "Main"}",
462
- isControlPlane: ${!!a},
538
+ tenantId: "${s ? "control_plane" : "main"}",
539
+ tenantName: "${s ? "Control Plane" : "Main"}",
540
+ isControlPlane: ${!!s},
463
541
  clientId: "default",
464
542
  });
465
543
 
@@ -491,15 +569,15 @@ export default {
491
569
  };
492
570
  `;
493
571
  }
494
- function L(a, e) {
495
- const n = e ? `import adminIndexHtml from "./admin-index-html";
572
+ function H(s, e) {
573
+ const o = e ? `import adminIndexHtml from "./admin-index-html";
496
574
  ` : "", r = e ? ` adminIndexHtml,
497
575
  ` : "";
498
- return a ? `import { Context } from "hono";
576
+ return s ? `import { Context } from "hono";
499
577
  import { swaggerUI } from "@hono/swagger-ui";
500
578
  import { AuthHeroConfig, DataAdapters } from "authhero";
501
579
  import { initMultiTenant } from "@authhero/multi-tenancy";
502
- ${n}
580
+ ${o}
503
581
  // Control plane configuration
504
582
  const CONTROL_PLANE_TENANT_ID = "control_plane";
505
583
  const CONTROL_PLANE_CLIENT_ID = "default";
@@ -540,7 +618,7 @@ ${r} controlPlane: {
540
618
  import { cors } from "hono/cors";
541
619
  import { AuthHeroConfig, init } from "authhero";
542
620
  import { swaggerUI } from "@hono/swagger-ui";
543
- ${n}
621
+ ${o}
544
622
  export default function createApp(config: AuthHeroConfig) {
545
623
  const { app } = init({
546
624
  ...config,
@@ -576,8 +654,8 @@ ${r} });
576
654
  }
577
655
  `;
578
656
  }
579
- function j(a) {
580
- return a ? `import { Context } from "hono";
657
+ function F(s) {
658
+ return s ? `import { Context } from "hono";
581
659
  import { swaggerUI } from "@hono/swagger-ui";
582
660
  import { AuthHeroConfig, DataAdapters } from "authhero";
583
661
  import { initMultiTenant } from "@authhero/multi-tenancy";
@@ -682,7 +760,7 @@ export default function createApp(config: AppConfig) {
682
760
  }
683
761
  `;
684
762
  }
685
- function $(a) {
763
+ function M(s) {
686
764
  return `import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
687
765
  import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";
688
766
  import createAdapters from "@authhero/aws";
@@ -711,9 +789,9 @@ async function main() {
711
789
  await seed(adapters, {
712
790
  adminUsername,
713
791
  adminPassword,
714
- tenantId: "${a ? "control_plane" : "main"}",
715
- tenantName: "${a ? "Control Plane" : "Main"}",
716
- isControlPlane: ${!!a},
792
+ tenantId: "${s ? "control_plane" : "main"}",
793
+ tenantName: "${s ? "Control Plane" : "Main"}",
794
+ isControlPlane: ${!!s},
717
795
  });
718
796
 
719
797
  console.log("✅ Database seeded successfully!");
@@ -722,23 +800,23 @@ async function main() {
722
800
  main().catch(console.error);
723
801
  `;
724
802
  }
725
- function H(a, e) {
726
- const n = i.join(a, "src");
727
- s.writeFileSync(
728
- i.join(n, "app.ts"),
729
- j(e)
730
- ), s.writeFileSync(
731
- i.join(n, "seed.ts"),
732
- $(e)
803
+ function W(s, e) {
804
+ const o = a.join(s, "src");
805
+ i.writeFileSync(
806
+ a.join(o, "app.ts"),
807
+ F(e)
808
+ ), i.writeFileSync(
809
+ a.join(o, "seed.ts"),
810
+ M(e)
733
811
  );
734
812
  }
735
- function x() {
813
+ function I() {
736
814
  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");
737
815
  }
738
- function M(a) {
739
- const e = i.join(a, ".github", "workflows");
740
- s.mkdirSync(e, { recursive: !0 });
741
- const n = `name: Unit tests
816
+ function q(s) {
817
+ const e = a.join(s, ".github", "workflows");
818
+ i.mkdirSync(e, { recursive: !0 });
819
+ const o = `name: Unit tests
742
820
 
743
821
  on: push
744
822
 
@@ -795,7 +873,7 @@ jobs:
795
873
  with:
796
874
  apiToken: \${{ secrets.CLOUDFLARE_API_TOKEN }}
797
875
  command: deploy
798
- `, o = `name: Deploy to Production
876
+ `, n = `name: Deploy to Production
799
877
 
800
878
  on:
801
879
  release:
@@ -824,9 +902,9 @@ jobs:
824
902
  apiToken: \${{ secrets.PROD_CLOUDFLARE_API_TOKEN }}
825
903
  command: deploy --env production
826
904
  `;
827
- s.writeFileSync(i.join(e, "unit-tests.yml"), n), s.writeFileSync(i.join(e, "deploy-dev.yml"), r), s.writeFileSync(i.join(e, "release.yml"), o), console.log("\\n📦 GitHub CI workflows created!");
905
+ 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!");
828
906
  }
829
- function F(a) {
907
+ function J(s) {
830
908
  const e = {
831
909
  branches: ["main"],
832
910
  plugins: [
@@ -835,11 +913,11 @@ function F(a) {
835
913
  "@semantic-release/github"
836
914
  ]
837
915
  };
838
- s.writeFileSync(
839
- i.join(a, ".releaserc.json"),
916
+ i.writeFileSync(
917
+ a.join(s, ".releaserc.json"),
840
918
  JSON.stringify(e, null, 2)
841
919
  );
842
- const n = i.join(a, "package.json"), r = JSON.parse(s.readFileSync(n, "utf-8"));
920
+ const o = a.join(s, "package.json"), r = JSON.parse(i.readFileSync(o, "utf-8"));
843
921
  r.devDependencies = {
844
922
  ...r.devDependencies,
845
923
  "semantic-release": "^24.0.0"
@@ -847,41 +925,41 @@ function F(a) {
847
925
  ...r.scripts,
848
926
  test: 'echo "No tests yet"',
849
927
  "type-check": "tsc --noEmit"
850
- }, s.writeFileSync(n, JSON.stringify(r, null, 2));
928
+ }, i.writeFileSync(o, JSON.stringify(r, null, 2));
851
929
  }
852
- function b(a, e) {
853
- return new Promise((n, r) => {
854
- const o = P(a, [], {
930
+ function b(s, e) {
931
+ return new Promise((o, r) => {
932
+ const n = O(s, [], {
855
933
  cwd: e,
856
934
  shell: !0,
857
935
  stdio: "inherit"
858
936
  });
859
- o.on("close", (t) => {
860
- t === 0 ? n() : r(new Error(`Command failed with exit code ${t}`));
861
- }), o.on("error", r);
937
+ n.on("close", (t) => {
938
+ t === 0 ? o() : r(new Error(`Command failed with exit code ${t}`));
939
+ }), n.on("error", r);
862
940
  });
863
941
  }
864
- function W(a, e, n) {
865
- const r = i.join(a, "src");
866
- s.writeFileSync(
867
- i.join(r, "app.ts"),
868
- L(e, n)
869
- ), s.writeFileSync(
870
- i.join(r, "seed.ts"),
871
- O(e)
942
+ function z(s, e, o) {
943
+ const r = a.join(s, "src");
944
+ i.writeFileSync(
945
+ a.join(r, "app.ts"),
946
+ H(e, o)
947
+ ), i.writeFileSync(
948
+ a.join(r, "seed.ts"),
949
+ j(e)
872
950
  );
873
951
  }
874
- function _() {
952
+ function D() {
875
953
  console.log(`
876
954
  ` + "─".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) + `
877
955
  `);
878
956
  }
879
- function k() {
957
+ function N() {
880
958
  console.log(`
881
959
  ` + "─".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) + `
882
960
  `);
883
961
  }
884
- D.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(
962
+ 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(
885
963
  "--package-manager <pm>",
886
964
  "package manager to use: npm, yarn, pnpm, or bun"
887
965
  ).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(
@@ -890,13 +968,13 @@ D.version("1.0.0").description("Create a new AuthHero project").argument("[proje
890
968
  ).option(
891
969
  "--workspace",
892
970
  "use workspace:* dependencies for local monorepo development"
893
- ).option("-y, --yes", "skip all prompts and use defaults/provided options").action(async (a, e) => {
894
- const n = e.yes === !0;
971
+ ).option("-y, --yes", "skip all prompts and use defaults/provided options").action(async (s, e) => {
972
+ const o = e.yes === !0;
895
973
  console.log(`
896
974
  🔐 Welcome to AuthHero!
897
975
  `);
898
- let r = a;
899
- r || (n ? (r = "auth-server", console.log(`Using default project name: ${r}`)) : r = (await m.prompt([
976
+ let r = s;
977
+ r || (o ? (r = "auth-server", console.log(`Using default project name: ${r}`)) : r = (await m.prompt([
900
978
  {
901
979
  type: "input",
902
980
  name: "projectName",
@@ -905,8 +983,8 @@ D.version("1.0.0").description("Create a new AuthHero project").argument("[proje
905
983
  validate: (u) => u !== "" || "Project name cannot be empty"
906
984
  }
907
985
  ])).projectName);
908
- const o = i.join(process.cwd(), r);
909
- s.existsSync(o) && (console.error(`❌ Project "${r}" already exists.`), process.exit(1));
986
+ const n = a.join(process.cwd(), r);
987
+ i.existsSync(n) && (console.error(`❌ Project "${r}" already exists.`), process.exit(1));
910
988
  let t;
911
989
  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([
912
990
  {
@@ -936,7 +1014,7 @@ D.version("1.0.0").description("Create a new AuthHero project").argument("[proje
936
1014
  }
937
1015
  ])).setupType;
938
1016
  let c;
939
- e.multiTenant !== void 0 ? c = e.multiTenant : n ? c = !1 : c = (await m.prompt([
1017
+ e.multiTenant !== void 0 ? c = e.multiTenant : o ? c = !1 : c = (await m.prompt([
940
1018
  {
941
1019
  type: "confirm",
942
1020
  name: "multiTenant",
@@ -945,7 +1023,7 @@ D.version("1.0.0").description("Create a new AuthHero project").argument("[proje
945
1023
  }
946
1024
  ])).multiTenant, c && console.log("Multi-tenant mode: enabled");
947
1025
  let d = !1;
948
- (t === "local" || t === "cloudflare") && (e.adminUi !== void 0 ? d = e.adminUi : n ? d = !0 : d = (await m.prompt([
1026
+ (t === "local" || t === "cloudflare") && (e.adminUi !== void 0 ? d = e.adminUi : o ? d = !0 : d = (await m.prompt([
949
1027
  {
950
1028
  type: "confirm",
951
1029
  name: "adminUi",
@@ -960,8 +1038,8 @@ D.version("1.0.0").description("Create a new AuthHero project").argument("[proje
960
1038
  const C = e.workspace || !1;
961
1039
  C && console.log("Workspace mode: enabled (using workspace:* dependencies)");
962
1040
  const y = p[t];
963
- s.mkdirSync(o, { recursive: !0 }), s.writeFileSync(
964
- i.join(o, "package.json"),
1041
+ i.mkdirSync(n, { recursive: !0 }), i.writeFileSync(
1042
+ a.join(n, "package.json"),
965
1043
  JSON.stringify(
966
1044
  y.packageJson(
967
1045
  r,
@@ -974,38 +1052,42 @@ D.version("1.0.0").description("Create a new AuthHero project").argument("[proje
974
1052
  2
975
1053
  )
976
1054
  );
977
- const S = y.templateDir, I = i.join(
978
- import.meta.url.replace("file://", "").replace("/create-authhero.js", ""),
979
- S
980
- );
981
- if (s.existsSync(I) ? N(I, o) : (console.error(`❌ Template directory not found: ${I}`), process.exit(1)), t === "cloudflare" && W(o, c, d), t === "cloudflare") {
982
- const l = i.join(o, "wrangler.toml"), u = i.join(o, "wrangler.local.toml");
983
- s.existsSync(l) && s.copyFileSync(l, u);
984
- const g = i.join(o, ".dev.vars.example"), w = i.join(o, ".dev.vars");
985
- s.existsSync(g) && s.copyFileSync(g, w), console.log(
1055
+ const A = y.templateDir, S = a.dirname(U(import.meta.url)), x = [
1056
+ a.join(S, A),
1057
+ a.join(S, "..", "templates", A)
1058
+ ], k = x.find((l) => i.existsSync(l));
1059
+ if (k ? P(k, n) : (console.error(
1060
+ `❌ Template directory not found. Looked in:
1061
+ ${x.join(`
1062
+ `)}`
1063
+ ), process.exit(1)), t === "cloudflare" && z(n, c, d), t === "cloudflare") {
1064
+ const l = a.join(n, "wrangler.toml"), u = a.join(n, "wrangler.local.toml");
1065
+ i.existsSync(l) && i.copyFileSync(l, u);
1066
+ const g = a.join(n, ".dev.vars.example"), w = a.join(n, ".dev.vars");
1067
+ i.existsSync(g) && i.copyFileSync(g, w), console.log(
986
1068
  "📁 Created wrangler.local.toml and .dev.vars for local development"
987
1069
  );
988
1070
  }
989
- let A = !1;
990
- if (t === "cloudflare" && (e.githubCi !== void 0 ? (A = e.githubCi, A && console.log("Including GitHub CI workflows with semantic versioning")) : n || (A = (await m.prompt([
1071
+ let _ = !1;
1072
+ if (t === "cloudflare" && (e.githubCi !== void 0 ? (_ = e.githubCi, _ && console.log("Including GitHub CI workflows with semantic versioning")) : o || (_ = (await m.prompt([
991
1073
  {
992
1074
  type: "confirm",
993
1075
  name: "includeGithubCi",
994
1076
  message: "Would you like to include GitHub CI with semantic versioning?",
995
1077
  default: !1
996
1078
  }
997
- ])).includeGithubCi), A && (M(o), F(o))), t === "local") {
998
- const l = R(
1079
+ ])).includeGithubCi), _ && (q(n), J(n))), t === "local") {
1080
+ const l = L(
999
1081
  c,
1000
1082
  f,
1001
1083
  h,
1002
1084
  d
1003
1085
  );
1004
- s.writeFileSync(i.join(o, "src/seed.ts"), l);
1005
- const u = U(c, d);
1006
- s.writeFileSync(i.join(o, "src/app.ts"), u);
1086
+ i.writeFileSync(a.join(n, "src/seed.ts"), l);
1087
+ const u = $(c, d);
1088
+ i.writeFileSync(a.join(n, "src/app.ts"), u);
1007
1089
  }
1008
- if (t === "aws-sst" && H(o, c), f) {
1090
+ if (t === "aws-sst" && W(n, c), f) {
1009
1091
  const l = {
1010
1092
  alias: h,
1011
1093
  description: "AuthHero Conformance Test",
@@ -1024,21 +1106,21 @@ D.version("1.0.0").description("Create a new AuthHero project").argument("[proje
1024
1106
  resourceUrl: "http://host.docker.internal:3000/userinfo"
1025
1107
  }
1026
1108
  };
1027
- s.writeFileSync(
1028
- i.join(o, "conformance-config.json"),
1109
+ i.writeFileSync(
1110
+ a.join(n, "conformance-config.json"),
1029
1111
  JSON.stringify(l, null, 2)
1030
1112
  ), console.log(
1031
1113
  "📝 Created conformance-config.json for OpenID Conformance Suite"
1032
1114
  );
1033
1115
  }
1034
- const T = c ? "multi-tenant" : "single-tenant";
1116
+ const E = c ? "multi-tenant" : "single-tenant";
1035
1117
  console.log(
1036
1118
  `
1037
- ✅ Project "${r}" has been created with ${y.name} (${T}) setup!
1119
+ ✅ Project "${r}" has been created with ${y.name} (${E}) setup!
1038
1120
  `
1039
1121
  );
1040
1122
  let v;
1041
- if (e.skipInstall ? v = !1 : n ? v = !0 : v = (await m.prompt([
1123
+ if (e.skipInstall ? v = !1 : o ? v = !0 : v = (await m.prompt([
1042
1124
  {
1043
1125
  type: "confirm",
1044
1126
  name: "shouldInstall",
@@ -1049,7 +1131,7 @@ D.version("1.0.0").description("Create a new AuthHero project").argument("[proje
1049
1131
  let l;
1050
1132
  e.packageManager ? (["npm", "yarn", "pnpm", "bun"].includes(e.packageManager) || (console.error(
1051
1133
  `❌ Invalid package manager: ${e.packageManager}`
1052
- ), console.error("Valid options: npm, yarn, pnpm, bun"), process.exit(1)), l = e.packageManager) : n ? l = "pnpm" : l = (await m.prompt([
1134
+ ), console.error("Valid options: npm, yarn, pnpm, bun"), process.exit(1)), l = e.packageManager) : o ? l = "pnpm" : l = (await m.prompt([
1053
1135
  {
1054
1136
  type: "list",
1055
1137
  name: "packageManager",
@@ -1067,13 +1149,13 @@ D.version("1.0.0").description("Create a new AuthHero project").argument("[proje
1067
1149
  `);
1068
1150
  try {
1069
1151
  const u = l === "pnpm" ? "pnpm install --ignore-workspace" : `${l} install`;
1070
- if (await b(u, o), t === "local" && (console.log(`
1152
+ if (await b(u, n), t === "local" && (console.log(`
1071
1153
  🔧 Building native modules...
1072
- `), await b("npm rebuild better-sqlite3", o)), console.log(`
1154
+ `), await b("npm rebuild better-sqlite3", n)), console.log(`
1073
1155
  ✅ Dependencies installed successfully!
1074
1156
  `), (t === "local" || t === "cloudflare") && !e.skipMigrate) {
1075
1157
  let w;
1076
- n ? w = !0 : w = (await m.prompt([
1158
+ o ? w = !0 : w = (await m.prompt([
1077
1159
  {
1078
1160
  type: "confirm",
1079
1161
  name: "shouldMigrate",
@@ -1082,20 +1164,20 @@ D.version("1.0.0").description("Create a new AuthHero project").argument("[proje
1082
1164
  }
1083
1165
  ])).shouldMigrate, w && (console.log(`
1084
1166
  🔄 Running migrations...
1085
- `), await b(`${l} run migrate`, o));
1167
+ `), await b(`${l} run migrate`, n));
1086
1168
  }
1087
1169
  let g;
1088
- e.skipStart || n ? g = !1 : g = (await m.prompt([
1170
+ e.skipStart || o ? g = !1 : g = (await m.prompt([
1089
1171
  {
1090
1172
  type: "confirm",
1091
1173
  name: "shouldStart",
1092
1174
  message: "Would you like to start the development server?",
1093
1175
  default: !0
1094
1176
  }
1095
- ])).shouldStart, g && (t === "cloudflare" ? _() : t === "aws-sst" ? x() : k(), console.log(`🚀 Starting development server...
1096
- `), await b(`${l} run dev`, o)), n && !g && (console.log(`
1177
+ ])).shouldStart, g && (t === "cloudflare" ? D() : t === "aws-sst" ? I() : N(), console.log(`🚀 Starting development server...
1178
+ `), await b(`${l} run dev`, n)), o && !g && (console.log(`
1097
1179
  ✅ Setup complete!`), console.log(`
1098
- To start the development server:`), console.log(` cd ${r}`), console.log(" npm run dev"), t === "cloudflare" ? _() : t === "aws-sst" ? x() : k());
1180
+ To start the development server:`), console.log(` cd ${r}`), console.log(" npm run dev"), t === "cloudflare" ? D() : t === "aws-sst" ? I() : N());
1099
1181
  } catch (u) {
1100
1182
  console.error(`
1101
1183
  ❌ An error occurred:`, u), process.exit(1);
@@ -1122,4 +1204,4 @@ Server will be available at: http://localhost:3000`), f && (console.log(`
1122
1204
  For more information, visit: https://authhero.net/docs
1123
1205
  `));
1124
1206
  });
1125
- D.parse(process.argv);
1207
+ T.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.39.0",
8
+ "version": "0.41.0",
9
9
  "type": "module",
10
10
  "main": "dist/create-authhero.js",
11
11
  "bin": {
@@ -20,6 +20,7 @@
20
20
  "@rollup/plugin-node-resolve": "^15.2.3",
21
21
  "@types/inquirer": "^9.0.7",
22
22
  "@types/node": "^20.14.9",
23
+ "tsx": "^4.19.4",
23
24
  "typescript": "^5.5.2",
24
25
  "vite": "^5.3.2"
25
26
  },