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