create-authhero 0.25.0 → 0.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/create-authhero.js +299 -134
- package/package.json +1 -1
package/dist/create-authhero.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { Command as
|
|
2
|
+
import { Command as L } from "commander";
|
|
3
3
|
import u from "inquirer";
|
|
4
|
-
import
|
|
5
|
-
import
|
|
4
|
+
import s from "fs";
|
|
5
|
+
import l from "path";
|
|
6
6
|
import { spawn as N } from "child_process";
|
|
7
|
-
const
|
|
7
|
+
const T = new L(), 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) => ({
|
|
12
|
+
packageJson: (t, e, o) => ({
|
|
13
13
|
name: t,
|
|
14
14
|
version: "1.0.0",
|
|
15
15
|
type: "module",
|
|
@@ -29,7 +29,8 @@ const b = new k(), p = {
|
|
|
29
29
|
"better-sqlite3": "latest",
|
|
30
30
|
hono: "^4.6.0",
|
|
31
31
|
kysely: "latest",
|
|
32
|
-
...e && { "@authhero/multi-tenancy": "latest" }
|
|
32
|
+
...e && { "@authhero/multi-tenancy": "latest" },
|
|
33
|
+
...o && { bcryptjs: "latest" }
|
|
33
34
|
},
|
|
34
35
|
devDependencies: {
|
|
35
36
|
"@types/better-sqlite3": "^7.6.0",
|
|
@@ -44,7 +45,7 @@ const b = new k(), p = {
|
|
|
44
45
|
name: "Cloudflare Workers (D1)",
|
|
45
46
|
description: "Cloudflare Workers setup with D1 database",
|
|
46
47
|
templateDir: "cloudflare",
|
|
47
|
-
packageJson: (t, e) => ({
|
|
48
|
+
packageJson: (t, e, o) => ({
|
|
48
49
|
name: t,
|
|
49
50
|
version: "1.0.0",
|
|
50
51
|
type: "module",
|
|
@@ -72,7 +73,8 @@ const b = new k(), p = {
|
|
|
72
73
|
hono: "^4.6.0",
|
|
73
74
|
kysely: "latest",
|
|
74
75
|
"kysely-d1": "latest",
|
|
75
|
-
...e && { "@authhero/multi-tenancy": "latest" }
|
|
76
|
+
...e && { "@authhero/multi-tenancy": "latest" },
|
|
77
|
+
...o && { bcryptjs: "latest" }
|
|
76
78
|
},
|
|
77
79
|
devDependencies: {
|
|
78
80
|
"@cloudflare/workers-types": "^4.0.0",
|
|
@@ -88,7 +90,7 @@ const b = new k(), p = {
|
|
|
88
90
|
name: "AWS SST (Lambda + DynamoDB)",
|
|
89
91
|
description: "Serverless AWS deployment with Lambda, DynamoDB, and SST",
|
|
90
92
|
templateDir: "aws-sst",
|
|
91
|
-
packageJson: (t, e) => ({
|
|
93
|
+
packageJson: (t, e, o) => ({
|
|
92
94
|
name: t,
|
|
93
95
|
version: "1.0.0",
|
|
94
96
|
type: "module",
|
|
@@ -108,7 +110,8 @@ const b = new k(), p = {
|
|
|
108
110
|
"@hono/zod-openapi": "^0.19.0",
|
|
109
111
|
authhero: "latest",
|
|
110
112
|
hono: "^4.6.0",
|
|
111
|
-
...e && { "@authhero/multi-tenancy": "latest" }
|
|
113
|
+
...e && { "@authhero/multi-tenancy": "latest" },
|
|
114
|
+
...o && { bcryptjs: "latest" }
|
|
112
115
|
},
|
|
113
116
|
devDependencies: {
|
|
114
117
|
"@types/aws-lambda": "^8.10.0",
|
|
@@ -122,12 +125,129 @@ const b = new k(), p = {
|
|
|
122
125
|
}
|
|
123
126
|
};
|
|
124
127
|
function E(t, e) {
|
|
125
|
-
|
|
126
|
-
const n =
|
|
127
|
-
|
|
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);
|
|
128
131
|
});
|
|
129
132
|
}
|
|
130
|
-
function
|
|
133
|
+
function R(t, e = !1, o = "authhero-local") {
|
|
134
|
+
const r = t ? "control_plane" : "main", n = t ? "Control Plane" : "Main", a = [
|
|
135
|
+
"https://manage.authhero.net/auth-callback",
|
|
136
|
+
"https://local.authhero.net/auth-callback",
|
|
137
|
+
"http://localhost:5173/auth-callback",
|
|
138
|
+
"https://localhost:3000/auth-callback"
|
|
139
|
+
], 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 = [
|
|
143
|
+
"https://manage.authhero.net",
|
|
144
|
+
"https://local.authhero.net",
|
|
145
|
+
"http://localhost:5173",
|
|
146
|
+
"https://localhost:3000"
|
|
147
|
+
], y = e ? ["https://localhost:8443/", "https://localhost.emobix.co.uk:8443/"] : [], x = [...w, ...y], v = e ? `
|
|
148
|
+
// Create OpenID Conformance Suite test clients and user
|
|
149
|
+
console.log("Creating conformance test clients and user...");
|
|
150
|
+
|
|
151
|
+
const conformanceCallbacks = [
|
|
152
|
+
"https://localhost.emobix.co.uk:8443/test/a/${o}/callback",
|
|
153
|
+
"https://localhost:8443/test/a/${o}/callback",
|
|
154
|
+
];
|
|
155
|
+
const conformanceLogoutUrls = [
|
|
156
|
+
"https://localhost:8443/",
|
|
157
|
+
"https://localhost.emobix.co.uk:8443/",
|
|
158
|
+
];
|
|
159
|
+
const conformanceWebOrigins = [
|
|
160
|
+
"https://localhost:8443",
|
|
161
|
+
"https://localhost.emobix.co.uk:8443",
|
|
162
|
+
];
|
|
163
|
+
|
|
164
|
+
try {
|
|
165
|
+
await adapters.clients.create("${r}", {
|
|
166
|
+
client_id: "conformance-test",
|
|
167
|
+
client_secret: "conformanceTestSecret123",
|
|
168
|
+
name: "Conformance Test Client",
|
|
169
|
+
callbacks: conformanceCallbacks,
|
|
170
|
+
allowed_logout_urls: conformanceLogoutUrls,
|
|
171
|
+
web_origins: conformanceWebOrigins,
|
|
172
|
+
});
|
|
173
|
+
console.log("✅ Created conformance-test client");
|
|
174
|
+
} catch (e: any) {
|
|
175
|
+
if (e.message?.includes("UNIQUE constraint")) {
|
|
176
|
+
console.log("ℹ️ conformance-test client already exists");
|
|
177
|
+
} else {
|
|
178
|
+
throw e;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
try {
|
|
183
|
+
await adapters.clients.create("${r}", {
|
|
184
|
+
client_id: "conformance-test2",
|
|
185
|
+
client_secret: "conformanceTestSecret456",
|
|
186
|
+
name: "Conformance Test Client 2",
|
|
187
|
+
callbacks: conformanceCallbacks,
|
|
188
|
+
allowed_logout_urls: conformanceLogoutUrls,
|
|
189
|
+
web_origins: conformanceWebOrigins,
|
|
190
|
+
});
|
|
191
|
+
console.log("✅ Created conformance-test2 client");
|
|
192
|
+
} catch (e: any) {
|
|
193
|
+
if (e.message?.includes("UNIQUE constraint")) {
|
|
194
|
+
console.log("ℹ️ conformance-test2 client already exists");
|
|
195
|
+
} else {
|
|
196
|
+
throw e;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Create a conformance test user with ALL OIDC profile claims populated
|
|
201
|
+
// This is required for OIDCC-5.4 (VerifyScopesReturnedInUserInfoClaims) test
|
|
202
|
+
try {
|
|
203
|
+
await adapters.users.create("${r}", {
|
|
204
|
+
user_id: "auth2|conformance-user",
|
|
205
|
+
email: "conformance@example.com",
|
|
206
|
+
email_verified: true,
|
|
207
|
+
name: "Conformance Test User",
|
|
208
|
+
given_name: "Conformance",
|
|
209
|
+
family_name: "User",
|
|
210
|
+
middle_name: "Test",
|
|
211
|
+
nickname: "conformance",
|
|
212
|
+
username: "conformance_user",
|
|
213
|
+
picture: "https://example.com/conformance.png",
|
|
214
|
+
profile: "https://example.com/conformance",
|
|
215
|
+
website: "https://example.com",
|
|
216
|
+
gender: "other",
|
|
217
|
+
birthdate: "2000-01-01",
|
|
218
|
+
zoneinfo: "Europe/London",
|
|
219
|
+
locale: "en-US",
|
|
220
|
+
connection: "Username-Password-Authentication",
|
|
221
|
+
provider: "auth2",
|
|
222
|
+
is_social: false,
|
|
223
|
+
});
|
|
224
|
+
console.log("✅ Created conformance test user (conformance@example.com)");
|
|
225
|
+
} catch (e: any) {
|
|
226
|
+
if (e.message?.includes("UNIQUE constraint")) {
|
|
227
|
+
console.log("ℹ️ conformance test user already exists");
|
|
228
|
+
} else {
|
|
229
|
+
throw e;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Create password for conformance test user
|
|
234
|
+
// Password: ConformanceTest123!
|
|
235
|
+
try {
|
|
236
|
+
const bcrypt = await import("bcryptjs");
|
|
237
|
+
const hashedPassword = await bcrypt.hash("ConformanceTest123!", 10);
|
|
238
|
+
await adapters.passwords.create("${r}", {
|
|
239
|
+
user_id: "auth2|conformance-user",
|
|
240
|
+
password: hashedPassword,
|
|
241
|
+
});
|
|
242
|
+
console.log("✅ Created password for conformance test user");
|
|
243
|
+
} catch (e: any) {
|
|
244
|
+
if (e.message?.includes("UNIQUE constraint")) {
|
|
245
|
+
console.log("ℹ️ conformance test user password already exists");
|
|
246
|
+
} else {
|
|
247
|
+
throw e;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
` : "";
|
|
131
251
|
return `import { SqliteDialect, Kysely } from "kysely";
|
|
132
252
|
import Database from "better-sqlite3";
|
|
133
253
|
import createAdapters from "@authhero/kysely-adapter";
|
|
@@ -153,18 +273,20 @@ async function main() {
|
|
|
153
273
|
await seed(adapters, {
|
|
154
274
|
adminEmail,
|
|
155
275
|
adminPassword,
|
|
156
|
-
tenantId: "${
|
|
157
|
-
tenantName: "${
|
|
276
|
+
tenantId: "${r}",
|
|
277
|
+
tenantName: "${n}",
|
|
158
278
|
isControlPlane: ${t},
|
|
279
|
+
callbacks: ${JSON.stringify(g)},
|
|
280
|
+
allowedLogoutUrls: ${JSON.stringify(x)},
|
|
159
281
|
});
|
|
160
|
-
|
|
282
|
+
${v}
|
|
161
283
|
await db.destroy();
|
|
162
284
|
}
|
|
163
285
|
|
|
164
286
|
main().catch(console.error);
|
|
165
287
|
`;
|
|
166
288
|
}
|
|
167
|
-
function
|
|
289
|
+
function O(t) {
|
|
168
290
|
return t ? `import { Context } from "hono";
|
|
169
291
|
import { swaggerUI } from "@hono/swagger-ui";
|
|
170
292
|
import { AuthHeroConfig, DataAdapters } from "authhero";
|
|
@@ -268,7 +390,7 @@ export default function createApp(config: AuthHeroConfig) {
|
|
|
268
390
|
}
|
|
269
391
|
`;
|
|
270
392
|
}
|
|
271
|
-
function
|
|
393
|
+
function j(t) {
|
|
272
394
|
return `import { D1Dialect } from "kysely-d1";
|
|
273
395
|
import { Kysely } from "kysely";
|
|
274
396
|
import createAdapters from "@authhero/kysely-adapter";
|
|
@@ -341,7 +463,7 @@ export default {
|
|
|
341
463
|
};
|
|
342
464
|
`;
|
|
343
465
|
}
|
|
344
|
-
function
|
|
466
|
+
function U(t) {
|
|
345
467
|
return t ? `import { Context } from "hono";
|
|
346
468
|
import { swaggerUI } from "@hono/swagger-ui";
|
|
347
469
|
import { AuthHeroConfig, DataAdapters } from "authhero";
|
|
@@ -421,7 +543,7 @@ export default function createApp(config: AuthHeroConfig) {
|
|
|
421
543
|
}
|
|
422
544
|
`;
|
|
423
545
|
}
|
|
424
|
-
function
|
|
546
|
+
function M(t) {
|
|
425
547
|
return t ? `import { Context } from "hono";
|
|
426
548
|
import { swaggerUI } from "@hono/swagger-ui";
|
|
427
549
|
import { AuthHeroConfig, DataAdapters } from "authhero";
|
|
@@ -527,7 +649,7 @@ export default function createApp(config: AppConfig) {
|
|
|
527
649
|
}
|
|
528
650
|
`;
|
|
529
651
|
}
|
|
530
|
-
function
|
|
652
|
+
function $(t) {
|
|
531
653
|
return `import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
|
|
532
654
|
import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";
|
|
533
655
|
import createAdapters from "@authhero/aws";
|
|
@@ -573,23 +695,23 @@ async function main() {
|
|
|
573
695
|
main().catch(console.error);
|
|
574
696
|
`;
|
|
575
697
|
}
|
|
576
|
-
function
|
|
577
|
-
const
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
),
|
|
582
|
-
|
|
583
|
-
|
|
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"),
|
|
705
|
+
$(e)
|
|
584
706
|
);
|
|
585
707
|
}
|
|
586
|
-
function
|
|
708
|
+
function I(t) {
|
|
587
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");
|
|
588
710
|
}
|
|
589
|
-
function
|
|
590
|
-
const e =
|
|
591
|
-
|
|
592
|
-
const
|
|
711
|
+
function F(t) {
|
|
712
|
+
const e = l.join(t, ".github", "workflows");
|
|
713
|
+
s.mkdirSync(e, { recursive: !0 });
|
|
714
|
+
const o = `name: Unit tests
|
|
593
715
|
|
|
594
716
|
on: push
|
|
595
717
|
|
|
@@ -610,7 +732,7 @@ jobs:
|
|
|
610
732
|
|
|
611
733
|
- run: npm run type-check
|
|
612
734
|
- run: npm test
|
|
613
|
-
`,
|
|
735
|
+
`, r = `name: Deploy to Dev
|
|
614
736
|
|
|
615
737
|
on:
|
|
616
738
|
push:
|
|
@@ -675,9 +797,9 @@ jobs:
|
|
|
675
797
|
apiToken: \${{ secrets.PROD_CLOUDFLARE_API_TOKEN }}
|
|
676
798
|
command: deploy --env production
|
|
677
799
|
`;
|
|
678
|
-
|
|
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!");
|
|
679
801
|
}
|
|
680
|
-
function
|
|
802
|
+
function W(t) {
|
|
681
803
|
const e = {
|
|
682
804
|
branches: ["main"],
|
|
683
805
|
plugins: [
|
|
@@ -686,75 +808,78 @@ function U(t) {
|
|
|
686
808
|
"@semantic-release/github"
|
|
687
809
|
]
|
|
688
810
|
};
|
|
689
|
-
|
|
690
|
-
|
|
811
|
+
s.writeFileSync(
|
|
812
|
+
l.join(t, ".releaserc.json"),
|
|
691
813
|
JSON.stringify(e, null, 2)
|
|
692
814
|
);
|
|
693
|
-
const
|
|
694
|
-
|
|
695
|
-
...
|
|
815
|
+
const o = l.join(t, "package.json"), r = JSON.parse(s.readFileSync(o, "utf-8"));
|
|
816
|
+
r.devDependencies = {
|
|
817
|
+
...r.devDependencies,
|
|
696
818
|
"semantic-release": "^24.0.0"
|
|
697
|
-
},
|
|
698
|
-
...
|
|
819
|
+
}, r.scripts = {
|
|
820
|
+
...r.scripts,
|
|
699
821
|
test: 'echo "No tests yet"',
|
|
700
822
|
"type-check": "tsc --noEmit"
|
|
701
|
-
},
|
|
823
|
+
}, s.writeFileSync(o, JSON.stringify(r, null, 2));
|
|
702
824
|
}
|
|
703
|
-
function
|
|
704
|
-
return new Promise((
|
|
825
|
+
function b(t, e) {
|
|
826
|
+
return new Promise((o, r) => {
|
|
705
827
|
const n = N(t, [], {
|
|
706
828
|
cwd: e,
|
|
707
829
|
shell: !0,
|
|
708
830
|
stdio: "inherit"
|
|
709
831
|
});
|
|
710
|
-
n.on("close", (
|
|
711
|
-
|
|
712
|
-
}), n.on("error",
|
|
832
|
+
n.on("close", (a) => {
|
|
833
|
+
a === 0 ? o() : r(new Error(`Command failed with exit code ${a}`));
|
|
834
|
+
}), n.on("error", r);
|
|
713
835
|
});
|
|
714
836
|
}
|
|
715
|
-
function D(t, e,
|
|
716
|
-
return new Promise((
|
|
717
|
-
const
|
|
837
|
+
function D(t, e, o) {
|
|
838
|
+
return new Promise((r, n) => {
|
|
839
|
+
const a = N(t, [], {
|
|
718
840
|
cwd: e,
|
|
719
841
|
shell: !0,
|
|
720
842
|
stdio: "inherit",
|
|
721
|
-
env: { ...process.env, ...
|
|
843
|
+
env: { ...process.env, ...o }
|
|
722
844
|
});
|
|
723
|
-
|
|
724
|
-
c === 0 ?
|
|
725
|
-
}),
|
|
845
|
+
a.on("close", (c) => {
|
|
846
|
+
c === 0 ? r() : n(new Error(`Command failed with exit code ${c}`));
|
|
847
|
+
}), a.on("error", n);
|
|
726
848
|
});
|
|
727
849
|
}
|
|
728
|
-
function
|
|
729
|
-
const
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
),
|
|
734
|
-
|
|
735
|
-
|
|
850
|
+
function q(t, e) {
|
|
851
|
+
const o = l.join(t, "src");
|
|
852
|
+
s.writeFileSync(
|
|
853
|
+
l.join(o, "app.ts"),
|
|
854
|
+
U(e)
|
|
855
|
+
), s.writeFileSync(
|
|
856
|
+
l.join(o, "seed.ts"),
|
|
857
|
+
j(e)
|
|
736
858
|
);
|
|
737
859
|
}
|
|
738
|
-
function
|
|
860
|
+
function k(t) {
|
|
739
861
|
console.log(`
|
|
740
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) + `
|
|
741
863
|
`);
|
|
742
864
|
}
|
|
743
|
-
function
|
|
865
|
+
function _(t) {
|
|
744
866
|
console.log(`
|
|
745
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) + `
|
|
746
868
|
`);
|
|
747
869
|
}
|
|
748
|
-
|
|
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(
|
|
749
871
|
"--package-manager <pm>",
|
|
750
872
|
"package manager to use: npm, yarn, pnpm, or bun"
|
|
751
|
-
).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("
|
|
752
|
-
|
|
873
|
+
).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
|
+
"--conformance-alias <alias>",
|
|
875
|
+
"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;
|
|
753
878
|
console.log(`
|
|
754
879
|
🔐 Welcome to AuthHero!
|
|
755
880
|
`);
|
|
756
|
-
let
|
|
757
|
-
|
|
881
|
+
let r = t;
|
|
882
|
+
r || (o ? (r = "auth-server", console.log(`Using default project name: ${r}`)) : r = (await u.prompt([
|
|
758
883
|
{
|
|
759
884
|
type: "input",
|
|
760
885
|
name: "projectName",
|
|
@@ -763,10 +888,10 @@ b.version("1.0.0").description("Create a new AuthHero project").argument("[proje
|
|
|
763
888
|
validate: (d) => d !== "" || "Project name cannot be empty"
|
|
764
889
|
}
|
|
765
890
|
])).projectName);
|
|
766
|
-
const n =
|
|
767
|
-
|
|
768
|
-
let
|
|
769
|
-
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)),
|
|
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([
|
|
770
895
|
{
|
|
771
896
|
type: "list",
|
|
772
897
|
name: "setupType",
|
|
@@ -794,7 +919,7 @@ b.version("1.0.0").description("Create a new AuthHero project").argument("[proje
|
|
|
794
919
|
}
|
|
795
920
|
])).setupType;
|
|
796
921
|
let c;
|
|
797
|
-
e.multiTenant !== void 0 ? (c = e.multiTenant, console.log(`Multi-tenant mode: ${c ? "enabled" : "disabled"}`)) :
|
|
922
|
+
e.multiTenant !== void 0 ? (c = e.multiTenant, console.log(`Multi-tenant mode: ${c ? "enabled" : "disabled"}`)) : o ? c = !1 : c = (await u.prompt([
|
|
798
923
|
{
|
|
799
924
|
type: "confirm",
|
|
800
925
|
name: "multiTenant",
|
|
@@ -803,57 +928,90 @@ b.version("1.0.0").description("Create a new AuthHero project").argument("[proje
|
|
|
803
928
|
default: !1
|
|
804
929
|
}
|
|
805
930
|
])).multiTenant;
|
|
806
|
-
const
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
931
|
+
const g = e.conformance || !1, w = e.conformanceAlias || "authhero-local";
|
|
932
|
+
g && console.log(
|
|
933
|
+
`OpenID Conformance Suite: enabled (alias: ${w})`
|
|
934
|
+
);
|
|
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)
|
|
810
939
|
);
|
|
811
|
-
const
|
|
940
|
+
const x = y.templateDir, v = l.join(
|
|
812
941
|
import.meta.url.replace("file://", "").replace("/create-authhero.js", ""),
|
|
813
|
-
|
|
942
|
+
x
|
|
814
943
|
);
|
|
815
|
-
if (
|
|
816
|
-
const
|
|
817
|
-
|
|
818
|
-
const m =
|
|
819
|
-
|
|
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(
|
|
820
949
|
"📁 Created wrangler.local.toml and .dev.vars for local development"
|
|
821
950
|
);
|
|
822
951
|
}
|
|
823
|
-
let
|
|
824
|
-
if (
|
|
952
|
+
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([
|
|
825
954
|
{
|
|
826
955
|
type: "confirm",
|
|
827
956
|
name: "includeGithubCi",
|
|
828
957
|
message: "Would you like to include GitHub CI with semantic versioning?",
|
|
829
958
|
default: !1
|
|
830
959
|
}
|
|
831
|
-
])).includeGithubCi),
|
|
832
|
-
const
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
960
|
+
])).includeGithubCi), C && (F(n), W(n))), a === "local") {
|
|
961
|
+
const i = R(
|
|
962
|
+
c,
|
|
963
|
+
g,
|
|
964
|
+
w
|
|
965
|
+
);
|
|
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);
|
|
969
|
+
}
|
|
970
|
+
if (a === "aws-sst" && H(n, c), g) {
|
|
971
|
+
const i = {
|
|
972
|
+
alias: w,
|
|
973
|
+
description: "AuthHero Conformance Test",
|
|
974
|
+
server: {
|
|
975
|
+
discoveryUrl: "http://host.docker.internal:3000/.well-known/openid-configuration"
|
|
976
|
+
},
|
|
977
|
+
client: {
|
|
978
|
+
client_id: "conformance-test",
|
|
979
|
+
client_secret: "conformanceTestSecret123"
|
|
980
|
+
},
|
|
981
|
+
client2: {
|
|
982
|
+
client_id: "conformance-test2",
|
|
983
|
+
client_secret: "conformanceTestSecret456"
|
|
984
|
+
},
|
|
985
|
+
resource: {
|
|
986
|
+
resourceUrl: "http://host.docker.internal:3000/userinfo"
|
|
987
|
+
}
|
|
988
|
+
};
|
|
989
|
+
s.writeFileSync(
|
|
990
|
+
l.join(n, "conformance-config.json"),
|
|
991
|
+
JSON.stringify(i, null, 2)
|
|
992
|
+
), console.log(
|
|
993
|
+
"📝 Created conformance-config.json for OpenID Conformance Suite"
|
|
994
|
+
);
|
|
836
995
|
}
|
|
837
|
-
|
|
838
|
-
const T = c ? "multi-tenant" : "single-tenant";
|
|
996
|
+
const P = c ? "multi-tenant" : "single-tenant";
|
|
839
997
|
console.log(
|
|
840
998
|
`
|
|
841
|
-
✅ Project "${
|
|
999
|
+
✅ Project "${r}" has been created with ${y.name} (${P}) setup!
|
|
842
1000
|
`
|
|
843
1001
|
);
|
|
844
|
-
let
|
|
845
|
-
if (e.skipInstall ?
|
|
1002
|
+
let A;
|
|
1003
|
+
if (e.skipInstall ? A = !1 : o ? A = !0 : A = (await u.prompt([
|
|
846
1004
|
{
|
|
847
1005
|
type: "confirm",
|
|
848
1006
|
name: "shouldInstall",
|
|
849
1007
|
message: "Would you like to install dependencies now?",
|
|
850
1008
|
default: !0
|
|
851
1009
|
}
|
|
852
|
-
])).shouldInstall,
|
|
853
|
-
let
|
|
1010
|
+
])).shouldInstall, A) {
|
|
1011
|
+
let i;
|
|
854
1012
|
e.packageManager ? (["npm", "yarn", "pnpm", "bun"].includes(e.packageManager) || (console.error(
|
|
855
1013
|
`❌ Invalid package manager: ${e.packageManager}`
|
|
856
|
-
), console.error("Valid options: npm, yarn, pnpm, bun"), process.exit(1)),
|
|
1014
|
+
), console.error("Valid options: npm, yarn, pnpm, bun"), process.exit(1)), i = e.packageManager) : o ? i = "pnpm" : i = (await u.prompt([
|
|
857
1015
|
{
|
|
858
1016
|
type: "list",
|
|
859
1017
|
name: "packageManager",
|
|
@@ -867,92 +1025,99 @@ b.version("1.0.0").description("Create a new AuthHero project").argument("[proje
|
|
|
867
1025
|
default: "pnpm"
|
|
868
1026
|
}
|
|
869
1027
|
])).packageManager, console.log(`
|
|
870
|
-
📦 Installing dependencies with ${
|
|
1028
|
+
📦 Installing dependencies with ${i}...
|
|
871
1029
|
`);
|
|
872
1030
|
try {
|
|
873
|
-
const d =
|
|
874
|
-
if (await
|
|
1031
|
+
const d = i === "pnpm" ? "pnpm install --ignore-workspace" : `${i} install`;
|
|
1032
|
+
if (await b(d, n), a === "local" && (console.log(`
|
|
875
1033
|
🔧 Building native modules...
|
|
876
|
-
`), await
|
|
1034
|
+
`), await b("npm rebuild better-sqlite3", n)), console.log(`
|
|
877
1035
|
✅ Dependencies installed successfully!
|
|
878
|
-
`),
|
|
879
|
-
let
|
|
880
|
-
if (e.skipMigrate && e.skipSeed ?
|
|
1036
|
+
`), a === "local" || a === "cloudflare") {
|
|
1037
|
+
let f;
|
|
1038
|
+
if (e.skipMigrate && e.skipSeed ? f = !1 : o ? f = !e.skipMigrate || !e.skipSeed : f = (await u.prompt([
|
|
881
1039
|
{
|
|
882
1040
|
type: "confirm",
|
|
883
1041
|
name: "shouldSetup",
|
|
884
1042
|
message: "Would you like to run migrations and seed the database?",
|
|
885
1043
|
default: !0
|
|
886
1044
|
}
|
|
887
|
-
])).shouldSetup,
|
|
888
|
-
let
|
|
889
|
-
e.email && e.password ? (/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e.email) || (console.error("❌ Invalid email address provided"), process.exit(1)), e.password.length < 8 && (console.error("❌ Password must be at least 8 characters"), process.exit(1)),
|
|
1045
|
+
])).shouldSetup, f) {
|
|
1046
|
+
let h;
|
|
1047
|
+
e.email && e.password ? (/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e.email) || (console.error("❌ Invalid email address provided"), process.exit(1)), e.password.length < 8 && (console.error("❌ Password must be at least 8 characters"), process.exit(1)), h = {
|
|
890
1048
|
username: e.email,
|
|
891
1049
|
password: e.password
|
|
892
|
-
}, console.log(`Using admin email: ${e.email}`)) :
|
|
1050
|
+
}, console.log(`Using admin email: ${e.email}`)) : h = await u.prompt([
|
|
893
1051
|
{
|
|
894
1052
|
type: "input",
|
|
895
1053
|
name: "username",
|
|
896
1054
|
message: "Admin email:",
|
|
897
1055
|
default: "admin@example.com",
|
|
898
|
-
validate: (
|
|
1056
|
+
validate: (S) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(S) || "Please enter a valid email address"
|
|
899
1057
|
},
|
|
900
1058
|
{
|
|
901
1059
|
type: "password",
|
|
902
1060
|
name: "password",
|
|
903
1061
|
message: "Admin password:",
|
|
904
1062
|
mask: "*",
|
|
905
|
-
validate: (
|
|
1063
|
+
validate: (S) => S.length < 8 ? "Password must be at least 8 characters" : !0
|
|
906
1064
|
}
|
|
907
1065
|
]), e.skipMigrate || (console.log(`
|
|
908
1066
|
🔄 Running migrations...
|
|
909
|
-
`), await
|
|
1067
|
+
`), await b(`${i} run migrate`, n)), e.skipSeed || (console.log(`
|
|
910
1068
|
🌱 Seeding database...
|
|
911
|
-
`),
|
|
912
|
-
`${
|
|
1069
|
+
`), a === "local" ? await D(
|
|
1070
|
+
`${i} run seed`,
|
|
913
1071
|
n,
|
|
914
1072
|
{
|
|
915
|
-
ADMIN_EMAIL:
|
|
916
|
-
ADMIN_PASSWORD:
|
|
1073
|
+
ADMIN_EMAIL: h.username,
|
|
1074
|
+
ADMIN_PASSWORD: h.password
|
|
917
1075
|
}
|
|
918
1076
|
) : await D(
|
|
919
|
-
`${
|
|
1077
|
+
`${i} run seed:local`,
|
|
920
1078
|
n,
|
|
921
1079
|
{
|
|
922
|
-
ADMIN_EMAIL:
|
|
923
|
-
ADMIN_PASSWORD:
|
|
1080
|
+
ADMIN_EMAIL: h.username,
|
|
1081
|
+
ADMIN_PASSWORD: h.password
|
|
924
1082
|
}
|
|
925
1083
|
));
|
|
926
1084
|
}
|
|
927
1085
|
}
|
|
928
1086
|
let m;
|
|
929
|
-
e.skipStart ||
|
|
1087
|
+
e.skipStart || o ? m = !1 : m = (await u.prompt([
|
|
930
1088
|
{
|
|
931
1089
|
type: "confirm",
|
|
932
1090
|
name: "shouldStart",
|
|
933
1091
|
message: "Would you like to start the development server?",
|
|
934
1092
|
default: !0
|
|
935
1093
|
}
|
|
936
|
-
])).shouldStart, m && (
|
|
937
|
-
`), await
|
|
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(`
|
|
938
1096
|
✅ Setup complete!`), console.log(`
|
|
939
|
-
To start the development server:`), console.log(` cd ${
|
|
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));
|
|
940
1098
|
} catch (d) {
|
|
941
1099
|
console.error(`
|
|
942
1100
|
❌ An error occurred:`, d), process.exit(1);
|
|
943
1101
|
}
|
|
944
1102
|
}
|
|
945
|
-
|
|
1103
|
+
A || (console.log("Next steps:"), console.log(` cd ${r}`), a === "local" ? (console.log(" npm install"), console.log(" npm run migrate"), console.log(
|
|
946
1104
|
" ADMIN_EMAIL=admin@example.com ADMIN_PASSWORD=yourpassword npm run seed"
|
|
947
|
-
), console.log(" npm run dev")) :
|
|
1105
|
+
), console.log(" npm run dev")) : a === "cloudflare" ? (console.log(" npm install"), console.log(
|
|
948
1106
|
" npm run migrate # or npm run db:migrate:remote for production"
|
|
949
1107
|
), console.log(
|
|
950
1108
|
" ADMIN_EMAIL=admin@example.com ADMIN_PASSWORD=yourpassword npm run seed"
|
|
951
|
-
), console.log(" npm run dev # or npm run dev:remote for production")) :
|
|
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(
|
|
952
1110
|
" TABLE_NAME=<your-table> ADMIN_EMAIL=admin@example.com ADMIN_PASSWORD=yourpassword npm run seed"
|
|
953
1111
|
)), console.log(`
|
|
954
|
-
Server will be available at: https://localhost:3000`), console.log("Portal available at: https://local.authhero.net"), console.log(`
|
|
1112
|
+
Server will be available at: https://localhost:3000`), console.log("Portal available at: https://local.authhero.net"), g && (console.log(`
|
|
1113
|
+
🧪 OpenID Conformance Suite Testing:`), console.log(
|
|
1114
|
+
" 1. Clone and start the conformance suite (if not already running):"
|
|
1115
|
+
), console.log(
|
|
1116
|
+
" git clone https://gitlab.com/openid/conformance-suite.git"
|
|
1117
|
+
), 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(
|
|
1118
|
+
" 3. Create a test plan and use conformance-config.json for settings"
|
|
1119
|
+
), console.log(` 4. Use alias: ${w}`)), console.log(`
|
|
955
1120
|
For more information, visit: https://authhero.net/docs
|
|
956
1121
|
`));
|
|
957
1122
|
});
|
|
958
|
-
|
|
1123
|
+
T.parse(process.argv);
|