create-authhero 0.32.0 โ†’ 0.34.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,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import { Command as R } from "commander";
3
- import u from "inquirer";
2
+ import { Command as I } from "commander";
3
+ import g from "inquirer";
4
4
  import a from "fs";
5
5
  import l from "path";
6
- import { spawn as I } from "child_process";
7
- const T = new R(), p = {
6
+ import { spawn as E } from "child_process";
7
+ const D = new I(), i = {
8
8
  local: {
9
9
  name: "Local (SQLite)",
10
10
  description: "Local development setup with SQLite database - great for getting started",
@@ -133,27 +133,27 @@ const T = new R(), p = {
133
133
  seedFile: "seed.ts"
134
134
  }
135
135
  };
136
- function E(o, e) {
136
+ function N(o, e) {
137
137
  a.readdirSync(o).forEach((n) => {
138
138
  const t = l.join(o, n), s = l.join(e, n);
139
- a.lstatSync(t).isDirectory() ? (a.mkdirSync(s, { recursive: !0 }), E(t, s)) : a.copyFileSync(t, s);
139
+ a.lstatSync(t).isDirectory() ? (a.mkdirSync(s, { recursive: !0 }), N(t, s)) : a.copyFileSync(t, s);
140
140
  });
141
141
  }
142
- function U(o, e = !1, r = "authhero-local") {
142
+ function P(o, e = !1, r = "authhero-local") {
143
143
  const n = o ? "control_plane" : "main", t = o ? "Control Plane" : "Main", s = [
144
144
  "https://manage.authhero.net/auth-callback",
145
145
  "https://local.authhero.net/auth-callback",
146
146
  "http://localhost:5173/auth-callback",
147
147
  "https://localhost:3000/auth-callback"
148
- ], c = e ? [
148
+ ], d = e ? [
149
149
  `https://localhost.emobix.co.uk:8443/test/a/${r}/callback`,
150
150
  `https://localhost:8443/test/a/${r}/callback`
151
- ] : [], g = [...s, ...c], w = [
151
+ ] : [], m = [...s, ...d], f = [
152
152
  "https://manage.authhero.net",
153
153
  "https://local.authhero.net",
154
154
  "http://localhost:5173",
155
155
  "https://localhost:3000"
156
- ], C = e ? ["https://localhost:8443/", "https://localhost.emobix.co.uk:8443/"] : [], y = [...w, ...C], b = e ? `
156
+ ], v = e ? ["https://localhost:8443/", "https://localhost.emobix.co.uk:8443/"] : [], w = [...f, ...v], b = e ? `
157
157
  // Create OpenID Conformance Suite test clients and user
158
158
  console.log("Creating conformance test clients and user...");
159
159
 
@@ -278,9 +278,9 @@ async function main() {
278
278
  adminPassword,
279
279
  tenantId: "${n}",
280
280
  tenantName: "${t}",
281
- isControlPlane: ${o},
282
- callbacks: ${JSON.stringify(g)},
283
- allowedLogoutUrls: ${JSON.stringify(y)},
281
+ isControlPlane: ${!!o},
282
+ callbacks: ${JSON.stringify(m)},
283
+ allowedLogoutUrls: ${JSON.stringify(w)},
284
284
  });
285
285
  ${b}
286
286
  await db.destroy();
@@ -289,12 +289,21 @@ ${b}
289
289
  main().catch(console.error);
290
290
  `;
291
291
  }
292
- function O(o) {
292
+ function R(o) {
293
293
  return o ? `import { Context } from "hono";
294
294
  import { swaggerUI } from "@hono/swagger-ui";
295
295
  import { AuthHeroConfig, DataAdapters } from "authhero";
296
296
  import { serveStatic } from "@hono/node-server/serve-static";
297
297
  import { initMultiTenant } from "@authhero/multi-tenancy";
298
+ import path from "path";
299
+ import { fileURLToPath } from "url";
300
+
301
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
302
+
303
+ const widgetPath = path.resolve(
304
+ __dirname,
305
+ "../node_modules/@authhero/widget/dist/authhero-widget",
306
+ );
298
307
 
299
308
  // Control plane configuration
300
309
  const CONTROL_PLANE_TENANT_ID = "control_plane";
@@ -304,6 +313,10 @@ export default function createApp(config: AuthHeroConfig & { dataAdapter: DataAd
304
313
  // Initialize multi-tenant AuthHero - syncs resource servers, roles, and connections by default
305
314
  const { app } = initMultiTenant({
306
315
  ...config,
316
+ widgetHandler: serveStatic({
317
+ root: widgetPath,
318
+ rewriteRequestPath: (p) => p.replace("/u/widget", ""),
319
+ }),
307
320
  controlPlane: {
308
321
  tenantId: CONTROL_PLANE_TENANT_ID,
309
322
  clientId: CONTROL_PLANE_CLIENT_ID,
@@ -328,23 +341,7 @@ export default function createApp(config: AuthHeroConfig & { dataAdapter: DataAd
328
341
  controlPlaneTenant: CONTROL_PLANE_TENANT_ID,
329
342
  });
330
343
  })
331
- .get("/docs", swaggerUI({ url: "/api/v2/spec" }))
332
- // Serve widget assets from @authhero/widget package
333
- .get(
334
- "/u/widget/*",
335
- serveStatic({
336
- root: "./node_modules/@authhero/widget/dist/authhero-widget",
337
- rewriteRequestPath: (path) => path.replace("/u/widget", ""),
338
- }),
339
- )
340
- // Serve static assets (CSS, JS) from authhero package
341
- .get(
342
- "/u/*",
343
- serveStatic({
344
- root: "./node_modules/authhero/dist/assets/u",
345
- rewriteRequestPath: (path) => path.replace("/u", ""),
346
- }),
347
- );
344
+ .get("/docs", swaggerUI({ url: "/api/v2/spec" }));
348
345
 
349
346
  return app;
350
347
  }
@@ -352,9 +349,24 @@ export default function createApp(config: AuthHeroConfig & { dataAdapter: DataAd
352
349
  import { AuthHeroConfig, init } from "authhero";
353
350
  import { swaggerUI } from "@hono/swagger-ui";
354
351
  import { serveStatic } from "@hono/node-server/serve-static";
352
+ import path from "path";
353
+ import { fileURLToPath } from "url";
354
+
355
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
356
+
357
+ const widgetPath = path.resolve(
358
+ __dirname,
359
+ "../node_modules/@authhero/widget/dist/authhero-widget",
360
+ );
355
361
 
356
362
  export default function createApp(config: AuthHeroConfig) {
357
- const { app } = init(config);
363
+ const { app } = init({
364
+ ...config,
365
+ widgetHandler: serveStatic({
366
+ root: widgetPath,
367
+ rewriteRequestPath: (p) => p.replace("/u/widget", ""),
368
+ }),
369
+ });
358
370
 
359
371
  app
360
372
  .onError((err, ctx) => {
@@ -371,29 +383,13 @@ export default function createApp(config: AuthHeroConfig) {
371
383
  status: "running",
372
384
  });
373
385
  })
374
- .get("/docs", swaggerUI({ url: "/api/v2/spec" }))
375
- // Serve widget assets from @authhero/widget package
376
- .get(
377
- "/u/widget/*",
378
- serveStatic({
379
- root: "./node_modules/@authhero/widget/dist/authhero-widget",
380
- rewriteRequestPath: (path) => path.replace("/u/widget", ""),
381
- }),
382
- )
383
- // Serve static assets (CSS, JS) from authhero package
384
- .get(
385
- "/u/*",
386
- serveStatic({
387
- root: "./node_modules/authhero/dist/assets/u",
388
- rewriteRequestPath: (path) => path.replace("/u", ""),
389
- }),
390
- );
386
+ .get("/docs", swaggerUI({ url: "/api/v2/spec" }));
391
387
 
392
388
  return app;
393
389
  }
394
390
  `;
395
391
  }
396
- function j(o) {
392
+ function O(o) {
397
393
  return `import { D1Dialect } from "kysely-d1";
398
394
  import { Kysely } from "kysely";
399
395
  import createAdapters from "@authhero/kysely-adapter";
@@ -422,7 +418,7 @@ export default {
422
418
  issuer,
423
419
  tenantId: "${o ? "control_plane" : "main"}",
424
420
  tenantName: "${o ? "Control Plane" : "Main"}",
425
- isControlPlane: ${o},
421
+ isControlPlane: ${!!o},
426
422
  });
427
423
 
428
424
  return new Response(
@@ -453,7 +449,7 @@ export default {
453
449
  };
454
450
  `;
455
451
  }
456
- function L(o) {
452
+ function U(o) {
457
453
  return o ? `import { Context } from "hono";
458
454
  import { swaggerUI } from "@hono/swagger-ui";
459
455
  import { AuthHeroConfig, DataAdapters } from "authhero";
@@ -533,7 +529,7 @@ export default function createApp(config: AuthHeroConfig) {
533
529
  }
534
530
  `;
535
531
  }
536
- function $(o) {
532
+ function L(o) {
537
533
  return o ? `import { Context } from "hono";
538
534
  import { swaggerUI } from "@hono/swagger-ui";
539
535
  import { AuthHeroConfig, DataAdapters } from "authhero";
@@ -639,7 +635,7 @@ export default function createApp(config: AppConfig) {
639
635
  }
640
636
  `;
641
637
  }
642
- function M(o) {
638
+ function j(o) {
643
639
  return `import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
644
640
  import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";
645
641
  import createAdapters from "@authhero/aws";
@@ -670,7 +666,7 @@ async function main() {
670
666
  adminPassword,
671
667
  tenantId: "${o ? "control_plane" : "main"}",
672
668
  tenantName: "${o ? "Control Plane" : "Main"}",
673
- isControlPlane: ${o},
669
+ isControlPlane: ${!!o},
674
670
  });
675
671
 
676
672
  console.log("โœ… Database seeded successfully!");
@@ -679,20 +675,22 @@ async function main() {
679
675
  main().catch(console.error);
680
676
  `;
681
677
  }
682
- function H(o, e) {
678
+ function $(o, e) {
683
679
  const r = l.join(o, "src");
684
680
  a.writeFileSync(
685
681
  l.join(r, "app.ts"),
686
- $(e)
682
+ L(e)
687
683
  ), a.writeFileSync(
688
684
  l.join(r, "seed.ts"),
689
- M(e)
685
+ j(e)
690
686
  );
691
687
  }
692
- function D(o) {
693
- 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");
688
+ function k() {
689
+ console.log("\\n" + "โ”€".repeat(50)), console.log("๐Ÿ” AuthHero deployed to AWS!"), console.log("๐Ÿ“š Check SST output for your API URL"), console.log(
690
+ "๐Ÿš€ Open your server URL /setup to complete initial setup"
691
+ ), console.log("๐ŸŒ Portal available at https://local.authhero.net"), console.log("โ”€".repeat(50) + "\\n");
694
692
  }
695
- function F(o) {
693
+ function H(o) {
696
694
  const e = l.join(o, ".github", "workflows");
697
695
  a.mkdirSync(e, { recursive: !0 });
698
696
  const r = `name: Unit tests
@@ -783,7 +781,7 @@ jobs:
783
781
  `;
784
782
  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!");
785
783
  }
786
- function W(o) {
784
+ function M(o) {
787
785
  const e = {
788
786
  branches: ["main"],
789
787
  plugins: [
@@ -808,7 +806,7 @@ function W(o) {
808
806
  }
809
807
  function A(o, e) {
810
808
  return new Promise((r, n) => {
811
- const t = I(o, [], {
809
+ const t = E(o, [], {
812
810
  cwd: e,
813
811
  shell: !0,
814
812
  stdio: "inherit"
@@ -818,43 +816,34 @@ function A(o, e) {
818
816
  }), t.on("error", n);
819
817
  });
820
818
  }
821
- function _(o, e, r) {
822
- return new Promise((n, t) => {
823
- const s = I(o, [], {
824
- cwd: e,
825
- shell: !0,
826
- stdio: "inherit",
827
- env: { ...process.env, ...r }
828
- });
829
- s.on("close", (c) => {
830
- c === 0 ? n() : t(new Error(`Command failed with exit code ${c}`));
831
- }), s.on("error", t);
832
- });
833
- }
834
- function q(o, e) {
819
+ function F(o, e) {
835
820
  const r = l.join(o, "src");
836
821
  a.writeFileSync(
837
822
  l.join(r, "app.ts"),
838
- L(e)
823
+ U(e)
839
824
  ), a.writeFileSync(
840
825
  l.join(r, "seed.ts"),
841
- j(e)
826
+ O(e)
842
827
  );
843
828
  }
844
- function x(o) {
829
+ function x() {
845
830
  console.log(`
846
- ` + "โ”€".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) + `
831
+ ` + "โ”€".repeat(50)), console.log("๐Ÿ” AuthHero server running at https://localhost:3000"), console.log("๐Ÿ“š API documentation available at https://localhost:3000/docs"), console.log(
832
+ "๐Ÿš€ Open https://localhost:3000/setup to complete initial setup"
833
+ ), console.log("๐ŸŒ Portal available at https://local.authhero.net"), console.log("โ”€".repeat(50) + `
847
834
  `);
848
835
  }
849
- function N(o) {
836
+ function _() {
850
837
  console.log(`
851
- ` + "โ”€".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) + `
838
+ ` + "โ”€".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(
839
+ "๐Ÿš€ Open https://localhost:3000/setup to complete initial setup"
840
+ ), console.log("๐ŸŒ Portal available at https://local.authhero.net"), console.log("โ”€".repeat(50) + `
852
841
  `);
853
842
  }
854
- 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(
843
+ 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(
855
844
  "--package-manager <pm>",
856
845
  "package manager to use: npm, yarn, pnpm, or bun"
857
- ).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(
846
+ ).option("--multi-tenant", "enable multi-tenant mode").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(
858
847
  "--conformance-alias <alias>",
859
848
  "alias for conformance suite (default: authhero-local)"
860
849
  ).option(
@@ -866,103 +855,93 @@ T.version("1.0.0").description("Create a new AuthHero project").argument("[proje
866
855
  ๐Ÿ” Welcome to AuthHero!
867
856
  `);
868
857
  let n = o;
869
- n || (r ? (n = "auth-server", console.log(`Using default project name: ${n}`)) : n = (await u.prompt([
858
+ n || (r ? (n = "auth-server", console.log(`Using default project name: ${n}`)) : n = (await g.prompt([
870
859
  {
871
860
  type: "input",
872
861
  name: "projectName",
873
862
  message: "Project name:",
874
863
  default: "auth-server",
875
- validate: (d) => d !== "" || "Project name cannot be empty"
864
+ validate: (p) => p !== "" || "Project name cannot be empty"
876
865
  }
877
866
  ])).projectName);
878
867
  const t = l.join(process.cwd(), n);
879
868
  a.existsSync(t) && (console.error(`โŒ Project "${n}" already exists.`), process.exit(1));
880
869
  let s;
881
- 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([
870
+ 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: ${i[s].name}`)) : s = (await g.prompt([
882
871
  {
883
872
  type: "list",
884
873
  name: "setupType",
885
874
  message: "Select your setup type:",
886
875
  choices: [
887
876
  {
888
- name: `${p.local.name}
889
- ${p.local.description}`,
877
+ name: `${i.local.name}
878
+ ${i.local.description}`,
890
879
  value: "local",
891
- short: p.local.name
880
+ short: i.local.name
892
881
  },
893
882
  {
894
- name: `${p.cloudflare.name}
895
- ${p.cloudflare.description}`,
883
+ name: `${i.cloudflare.name}
884
+ ${i.cloudflare.description}`,
896
885
  value: "cloudflare",
897
- short: p.cloudflare.name
886
+ short: i.cloudflare.name
898
887
  },
899
888
  {
900
- name: `${p["aws-sst"].name}
901
- ${p["aws-sst"].description}`,
889
+ name: `${i["aws-sst"].name}
890
+ ${i["aws-sst"].description}`,
902
891
  value: "aws-sst",
903
- short: p["aws-sst"].name
892
+ short: i["aws-sst"].name
904
893
  }
905
894
  ]
906
895
  }
907
896
  ])).setupType;
908
- let c;
909
- e.multiTenant !== void 0 ? (c = e.multiTenant, console.log(`Multi-tenant mode: ${c ? "enabled" : "disabled"}`)) : r ? c = !1 : c = (await u.prompt([
910
- {
911
- type: "confirm",
912
- name: "multiTenant",
913
- message: `Would you like to enable multi-tenant mode?
914
- (Allows managing multiple tenants from a control plane)`,
915
- default: !1
916
- }
917
- ])).multiTenant;
918
- const g = e.conformance || !1, w = e.conformanceAlias || "authhero-local";
919
- g && console.log(
920
- `OpenID Conformance Suite: enabled (alias: ${w})`
897
+ const d = e.multiTenant, m = e.conformance || !1, f = e.conformanceAlias || "authhero-local";
898
+ m && console.log(
899
+ `OpenID Conformance Suite: enabled (alias: ${f})`
921
900
  );
922
- const C = e.workspace || !1;
923
- C && console.log("Workspace mode: enabled (using workspace:* dependencies)");
924
- const y = p[s];
901
+ const v = e.workspace || !1;
902
+ v && console.log("Workspace mode: enabled (using workspace:* dependencies)");
903
+ const w = i[s];
925
904
  a.mkdirSync(t, { recursive: !0 }), a.writeFileSync(
926
905
  l.join(t, "package.json"),
927
906
  JSON.stringify(
928
- y.packageJson(n, c, g, C),
907
+ w.packageJson(n, d, m, v),
929
908
  null,
930
909
  2
931
910
  )
932
911
  );
933
- const b = y.templateDir, k = l.join(
912
+ const b = w.templateDir, S = l.join(
934
913
  import.meta.url.replace("file://", "").replace("/create-authhero.js", ""),
935
914
  b
936
915
  );
937
- if (a.existsSync(k) ? E(k, t) : (console.error(`โŒ Template directory not found: ${k}`), process.exit(1)), s === "cloudflare" && q(t, c), s === "cloudflare") {
938
- const i = l.join(t, "wrangler.toml"), d = l.join(t, "wrangler.local.toml");
939
- a.existsSync(i) && a.copyFileSync(i, d);
940
- const m = l.join(t, ".dev.vars.example"), f = l.join(t, ".dev.vars");
941
- a.existsSync(m) && a.copyFileSync(m, f), console.log(
916
+ if (a.existsSync(S) ? N(S, t) : (console.error(`โŒ Template directory not found: ${S}`), process.exit(1)), s === "cloudflare" && F(t, d), s === "cloudflare") {
917
+ const c = l.join(t, "wrangler.toml"), p = l.join(t, "wrangler.local.toml");
918
+ a.existsSync(c) && a.copyFileSync(c, p);
919
+ const u = l.join(t, ".dev.vars.example"), h = l.join(t, ".dev.vars");
920
+ a.existsSync(u) && a.copyFileSync(u, h), console.log(
942
921
  "๐Ÿ“ Created wrangler.local.toml and .dev.vars for local development"
943
922
  );
944
923
  }
945
- let S = !1;
946
- if (s === "cloudflare" && (e.githubCi !== void 0 ? (S = e.githubCi, S && console.log("Including GitHub CI workflows with semantic versioning")) : r || (S = (await u.prompt([
924
+ let C = !1;
925
+ if (s === "cloudflare" && (e.githubCi !== void 0 ? (C = e.githubCi, C && console.log("Including GitHub CI workflows with semantic versioning")) : r || (C = (await g.prompt([
947
926
  {
948
927
  type: "confirm",
949
928
  name: "includeGithubCi",
950
929
  message: "Would you like to include GitHub CI with semantic versioning?",
951
930
  default: !1
952
931
  }
953
- ])).includeGithubCi), S && (F(t), W(t))), s === "local") {
954
- const i = U(
955
- c,
956
- g,
957
- w
932
+ ])).includeGithubCi), C && (H(t), M(t))), s === "local") {
933
+ const c = P(
934
+ d,
935
+ m,
936
+ f
958
937
  );
959
- a.writeFileSync(l.join(t, "src/seed.ts"), i);
960
- const d = O(c);
961
- a.writeFileSync(l.join(t, "src/app.ts"), d);
938
+ a.writeFileSync(l.join(t, "src/seed.ts"), c);
939
+ const p = R(d);
940
+ a.writeFileSync(l.join(t, "src/app.ts"), p);
962
941
  }
963
- if (s === "aws-sst" && H(t, c), g) {
964
- const i = {
965
- alias: w,
942
+ if (s === "aws-sst" && $(t, d), m) {
943
+ const c = {
944
+ alias: f,
966
945
  description: "AuthHero Conformance Test",
967
946
  server: {
968
947
  discoveryUrl: "http://host.docker.internal:3000/.well-known/openid-configuration"
@@ -981,30 +960,30 @@ T.version("1.0.0").description("Create a new AuthHero project").argument("[proje
981
960
  };
982
961
  a.writeFileSync(
983
962
  l.join(t, "conformance-config.json"),
984
- JSON.stringify(i, null, 2)
963
+ JSON.stringify(c, null, 2)
985
964
  ), console.log(
986
965
  "๐Ÿ“ Created conformance-config.json for OpenID Conformance Suite"
987
966
  );
988
967
  }
989
- const P = c ? "multi-tenant" : "single-tenant";
968
+ const T = d ? "multi-tenant" : "single-tenant";
990
969
  console.log(
991
970
  `
992
- โœ… Project "${n}" has been created with ${y.name} (${P}) setup!
971
+ โœ… Project "${n}" has been created with ${w.name} (${T}) setup!
993
972
  `
994
973
  );
995
- let v;
996
- if (e.skipInstall ? v = !1 : r ? v = !0 : v = (await u.prompt([
974
+ let y;
975
+ if (e.skipInstall ? y = !1 : r ? y = !0 : y = (await g.prompt([
997
976
  {
998
977
  type: "confirm",
999
978
  name: "shouldInstall",
1000
979
  message: "Would you like to install dependencies now?",
1001
980
  default: !0
1002
981
  }
1003
- ])).shouldInstall, v) {
1004
- let i;
982
+ ])).shouldInstall, y) {
983
+ let c;
1005
984
  e.packageManager ? (["npm", "yarn", "pnpm", "bun"].includes(e.packageManager) || (console.error(
1006
985
  `โŒ Invalid package manager: ${e.packageManager}`
1007
- ), console.error("Valid options: npm, yarn, pnpm, bun"), process.exit(1)), i = e.packageManager) : r ? i = "pnpm" : i = (await u.prompt([
986
+ ), console.error("Valid options: npm, yarn, pnpm, bun"), process.exit(1)), c = e.packageManager) : r ? c = "pnpm" : c = (await g.prompt([
1008
987
  {
1009
988
  type: "list",
1010
989
  name: "packageManager",
@@ -1018,94 +997,65 @@ T.version("1.0.0").description("Create a new AuthHero project").argument("[proje
1018
997
  default: "pnpm"
1019
998
  }
1020
999
  ])).packageManager, console.log(`
1021
- ๐Ÿ“ฆ Installing dependencies with ${i}...
1000
+ ๐Ÿ“ฆ Installing dependencies with ${c}...
1022
1001
  `);
1023
1002
  try {
1024
- const d = i === "pnpm" ? "pnpm install --ignore-workspace" : `${i} install`;
1025
- if (await A(d, t), s === "local" && (console.log(`
1003
+ const p = c === "pnpm" ? "pnpm install --ignore-workspace" : `${c} install`;
1004
+ if (await A(p, t), s === "local" && (console.log(`
1026
1005
  ๐Ÿ”ง Building native modules...
1027
1006
  `), await A("npm rebuild better-sqlite3", t)), console.log(`
1028
1007
  โœ… Dependencies installed successfully!
1029
- `), s === "local" || s === "cloudflare") {
1030
- let f;
1031
- if (e.skipMigrate && e.skipSeed ? f = !1 : r ? f = !e.skipMigrate || !e.skipSeed : f = (await u.prompt([
1008
+ `), (s === "local" || s === "cloudflare") && !e.skipMigrate) {
1009
+ let h;
1010
+ r ? h = !0 : h = (await g.prompt([
1032
1011
  {
1033
1012
  type: "confirm",
1034
- name: "shouldSetup",
1035
- message: "Would you like to run migrations and seed the database?",
1013
+ name: "shouldMigrate",
1014
+ message: "Would you like to run database migrations?",
1036
1015
  default: !0
1037
1016
  }
1038
- ])).shouldSetup, f) {
1039
- let h;
1040
- e.email && e.password ? (h = {
1041
- username: e.email,
1042
- password: e.password
1043
- }, console.log(`Using admin username: ${e.email}`)) : h = await u.prompt([
1044
- {
1045
- type: "input",
1046
- name: "username",
1047
- message: "Admin username:",
1048
- default: "admin"
1049
- },
1050
- {
1051
- type: "password",
1052
- name: "password",
1053
- message: "Admin password:",
1054
- mask: "*",
1055
- default: "admin"
1056
- }
1057
- ]), e.skipMigrate || (console.log(`
1017
+ ])).shouldMigrate, h && (console.log(`
1058
1018
  ๐Ÿ”„ Running migrations...
1059
- `), await A(`${i} run migrate`, t)), e.skipSeed || (console.log(`
1060
- ๐ŸŒฑ Seeding database...
1061
- `), s === "local" ? await _(
1062
- `${i} run seed`,
1063
- t,
1064
- {
1065
- ADMIN_USERNAME: h.username,
1066
- ADMIN_PASSWORD: h.password
1067
- }
1068
- ) : await _(
1069
- `${i} run seed:local`,
1070
- t,
1071
- {
1072
- ADMIN_USERNAME: h.username,
1073
- ADMIN_PASSWORD: h.password
1074
- }
1075
- ));
1076
- }
1019
+ `), await A(`${c} run migrate`, t));
1077
1020
  }
1078
- let m;
1079
- e.skipStart || r ? m = !1 : m = (await u.prompt([
1021
+ let u;
1022
+ e.skipStart || r ? u = !1 : u = (await g.prompt([
1080
1023
  {
1081
1024
  type: "confirm",
1082
1025
  name: "shouldStart",
1083
1026
  message: "Would you like to start the development server?",
1084
1027
  default: !0
1085
1028
  }
1086
- ])).shouldStart, m && (s === "cloudflare" ? x(c) : s === "aws-sst" ? D(c) : N(c), console.log(`๐Ÿš€ Starting development server...
1087
- `), await A(`${i} run dev`, t)), r && !m && (console.log(`
1029
+ ])).shouldStart, u && (s === "cloudflare" ? x() : s === "aws-sst" ? k() : _(), console.log(`๐Ÿš€ Starting development server...
1030
+ `), await A(`${c} run dev`, t)), r && !u && (console.log(`
1088
1031
  โœ… Setup complete!`), console.log(`
1089
- To start the development server:`), console.log(` cd ${n}`), console.log(" npm run dev"), s === "cloudflare" ? x(c) : s === "aws-sst" ? D(c) : N(c));
1090
- } catch (d) {
1032
+ To start the development server:`), console.log(` cd ${n}`), console.log(" npm run dev"), s === "cloudflare" ? x() : s === "aws-sst" ? k() : _());
1033
+ } catch (p) {
1091
1034
  console.error(`
1092
- โŒ An error occurred:`, d), process.exit(1);
1035
+ โŒ An error occurred:`, p), process.exit(1);
1093
1036
  }
1094
1037
  }
1095
- v || (console.log("Next steps:"), console.log(` cd ${n}`), s === "local" ? (console.log(" npm install"), console.log(" npm run migrate"), console.log(" npm run seed # defaults to admin/admin"), console.log(" npm run dev")) : s === "cloudflare" ? (console.log(" npm install"), console.log(
1038
+ y || (console.log("Next steps:"), console.log(` cd ${n}`), s === "local" ? (console.log(" npm install"), console.log(" npm run migrate"), console.log(" npm run dev"), console.log(
1039
+ `
1040
+ Open https://localhost:3000/setup to complete initial setup`
1041
+ )) : s === "cloudflare" ? (console.log(" npm install"), console.log(
1096
1042
  " npm run migrate # or npm run db:migrate:remote for production"
1097
- ), console.log(" npm run seed # defaults to admin/admin"), 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(
1098
- " TABLE_NAME=<your-table> npm run seed # defaults to admin/admin"
1043
+ ), console.log(" npm run dev # or npm run dev:remote for production"), console.log(
1044
+ `
1045
+ Open https://localhost:3000/setup to complete initial setup`
1046
+ )) : s === "aws-sst" && (console.log(" npm install"), console.log(" npm run dev # Deploys to AWS in development mode"), console.log(
1047
+ `
1048
+ Open your server URL /setup to complete initial setup`
1099
1049
  )), console.log(`
1100
- Server will be available at: https://localhost:3000`), console.log("Portal available at: https://local.authhero.net"), g && (console.log(`
1050
+ Server will be available at: https://localhost:3000`), console.log("Portal available at: https://local.authhero.net"), m && (console.log(`
1101
1051
  ๐Ÿงช OpenID Conformance Suite Testing:`), console.log(
1102
1052
  " 1. Clone and start the conformance suite (if not already running):"
1103
1053
  ), console.log(
1104
1054
  " git clone https://gitlab.com/openid/conformance-suite.git"
1105
1055
  ), 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(
1106
1056
  " 3. Create a test plan and use conformance-config.json for settings"
1107
- ), console.log(` 4. Use alias: ${w}`)), console.log(`
1057
+ ), console.log(` 4. Use alias: ${f}`)), console.log(`
1108
1058
  For more information, visit: https://authhero.net/docs
1109
1059
  `));
1110
1060
  });
1111
- T.parse(process.argv);
1061
+ D.parse(process.argv);
@@ -3,6 +3,7 @@ import { AuthHeroConfig, init } from "authhero";
3
3
  import { swaggerUI } from "@hono/swagger-ui";
4
4
  import { serveStatic } from "@hono/node-server/serve-static";
5
5
  import path from "path";
6
+ import fs from "fs";
6
7
  import { fileURLToPath } from "url";
7
8
 
8
9
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
@@ -13,9 +14,15 @@ const widgetPath = path.resolve(
13
14
  "../node_modules/@authhero/widget/dist/authhero-widget",
14
15
  );
15
16
 
17
+ const adminDistPath = path.resolve(
18
+ __dirname,
19
+ "../node_modules/@authhero/react-admin/dist",
20
+ );
21
+ const adminIndexPath = path.join(adminDistPath, "index.html");
22
+
16
23
  export default function createApp(config: AuthHeroConfig) {
17
- // Configure widget handler before init() to serve widget files at /u/widget/*
18
- const configWithWidget: AuthHeroConfig = {
24
+ // Configure widget and admin handlers before init()
25
+ const configWithHandlers: AuthHeroConfig = {
19
26
  ...config,
20
27
  widgetHandler: serveStatic({
21
28
  root: widgetPath,
@@ -23,7 +30,26 @@ export default function createApp(config: AuthHeroConfig) {
23
30
  }),
24
31
  };
25
32
 
26
- const { app } = init(configWithWidget);
33
+ // Add admin UI handler if the package is installed
34
+ if (fs.existsSync(adminIndexPath)) {
35
+ const issuer =
36
+ process.env.ISSUER || `https://localhost:${process.env.PORT || 3000}/`;
37
+ const rawHtml = fs.readFileSync(adminIndexPath, "utf-8");
38
+ const configJson = JSON.stringify({
39
+ domain: issuer.replace(/\/$/, ""),
40
+ basePath: "/admin",
41
+ }).replace(/</g, "\\u003c");
42
+ configWithHandlers.adminIndexHtml = rawHtml.replace(
43
+ "</head>",
44
+ `<script>window.__AUTHHERO_ADMIN_CONFIG__=${configJson};</script>\n</head>`,
45
+ );
46
+ configWithHandlers.adminHandler = serveStatic({
47
+ root: adminDistPath,
48
+ rewriteRequestPath: (p: string) => p.replace("/admin", ""),
49
+ });
50
+ }
51
+
52
+ const { app } = init(configWithHandlers);
27
53
 
28
54
  app
29
55
  .get("/", async (ctx: Context) => {
@@ -90,6 +90,7 @@ const app = createApp({
90
90
  "https://manage.authhero.net",
91
91
  "https://local.authhero.net",
92
92
  "http://localhost:5173",
93
+ "https://localhost:5173",
93
94
  ],
94
95
  });
95
96
 
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.32.0",
8
+ "version": "0.34.0",
9
9
  "type": "module",
10
10
  "main": "dist/create-authhero.js",
11
11
  "bin": {
@@ -29,6 +29,7 @@
29
29
  },
30
30
  "scripts": {
31
31
  "build": "tsc && vite build",
32
+ "dev": "pnpm build && rm -rf auth-server && node dist/create-authhero.js auth-server --workspace --skip-install --skip-start && pnpm -w install --force --filter auth-server... && pnpm --filter auth-server migrate && pnpm --filter auth-server dev",
32
33
  "start": "pnpm build && node dist/create-authhero.js"
33
34
  }
34
35
  }