create-authenik8-app 2.1.7 → 2.2.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.
Files changed (88) hide show
  1. package/README.md +5 -4
  2. package/package.json +1 -1
  3. package/dist/bin/index.d.ts +0 -8
  4. package/dist/bin/index.d.ts.map +0 -1
  5. package/dist/bin/index.js +0 -796
  6. package/dist/bin/index.js.map +0 -1
  7. package/dist/index.d.ts +0 -3
  8. package/dist/index.d.ts.map +0 -1
  9. package/dist/index.js +0 -292
  10. package/dist/index.js.map +0 -1
  11. package/dist/lib/constants.d.ts +0 -4
  12. package/dist/lib/constants.d.ts.map +0 -1
  13. package/dist/lib/constants.js +0 -25
  14. package/dist/lib/constants.js.map +0 -1
  15. package/dist/lib/process.d.ts +0 -7
  16. package/dist/lib/process.d.ts.map +0 -1
  17. package/dist/lib/process.js +0 -60
  18. package/dist/lib/process.js.map +0 -1
  19. package/dist/lib/state.d.ts +0 -8
  20. package/dist/lib/state.d.ts.map +0 -1
  21. package/dist/lib/state.js +0 -31
  22. package/dist/lib/state.js.map +0 -1
  23. package/dist/lib/types.d.ts +0 -17
  24. package/dist/lib/types.d.ts.map +0 -1
  25. package/dist/lib/types.js +0 -2
  26. package/dist/lib/types.js.map +0 -1
  27. package/dist/lib/ui.d.ts +0 -7
  28. package/dist/lib/ui.d.ts.map +0 -1
  29. package/dist/lib/ui.js +0 -124
  30. package/dist/lib/ui.js.map +0 -1
  31. package/dist/steps/configurePrisma.d.ts +0 -3
  32. package/dist/steps/configurePrisma.d.ts.map +0 -1
  33. package/dist/steps/configurePrisma.js +0 -41
  34. package/dist/steps/configurePrisma.js.map +0 -1
  35. package/dist/steps/createProject.d.ts +0 -5
  36. package/dist/steps/createProject.d.ts.map +0 -1
  37. package/dist/steps/createProject.js +0 -35
  38. package/dist/steps/createProject.js.map +0 -1
  39. package/dist/steps/finalSetup.d.ts +0 -7
  40. package/dist/steps/finalSetup.d.ts.map +0 -1
  41. package/dist/steps/finalSetup.js +0 -110
  42. package/dist/steps/finalSetup.js.map +0 -1
  43. package/dist/steps/installAuth.d.ts +0 -3
  44. package/dist/steps/installAuth.d.ts.map +0 -1
  45. package/dist/steps/installAuth.js +0 -18
  46. package/dist/steps/installAuth.js.map +0 -1
  47. package/dist/steps/installDeps.d.ts +0 -4
  48. package/dist/steps/installDeps.d.ts.map +0 -1
  49. package/dist/steps/installDeps.js +0 -50
  50. package/dist/steps/installDeps.js.map +0 -1
  51. package/dist/steps/prompts.d.ts +0 -3
  52. package/dist/steps/prompts.d.ts.map +0 -1
  53. package/dist/steps/prompts.js +0 -76
  54. package/dist/steps/prompts.js.map +0 -1
  55. package/dist/tests/helpers/generator.d.ts +0 -27
  56. package/dist/tests/helpers/generator.d.ts.map +0 -1
  57. package/dist/tests/helpers/generator.js +0 -282
  58. package/dist/tests/helpers/generator.js.map +0 -1
  59. package/dist/tests/integration/generator.test.d.ts +0 -2
  60. package/dist/tests/integration/generator.test.d.ts.map +0 -1
  61. package/dist/tests/integration/generator.test.js +0 -116
  62. package/dist/tests/integration/generator.test.js.map +0 -1
  63. package/dist/tests/integration/snapshot.test.d.ts +0 -2
  64. package/dist/tests/integration/snapshot.test.d.ts.map +0 -1
  65. package/dist/tests/integration/snapshot.test.js +0 -68
  66. package/dist/tests/integration/snapshot.test.js.map +0 -1
  67. package/dist/tests/setup.d.ts +0 -2
  68. package/dist/tests/setup.d.ts.map +0 -1
  69. package/dist/tests/setup.js +0 -10
  70. package/dist/tests/setup.js.map +0 -1
  71. package/dist/tests/unit/cli.test.d.ts +0 -2
  72. package/dist/tests/unit/cli.test.d.ts.map +0 -1
  73. package/dist/tests/unit/cli.test.js +0 -242
  74. package/dist/tests/unit/cli.test.js.map +0 -1
  75. package/dist/utils/hash.d.ts +0 -4
  76. package/dist/utils/hash.d.ts.map +0 -1
  77. package/dist/utils/hash.js +0 -51
  78. package/dist/utils/hash.js.map +0 -1
  79. package/dist/utils/output.d.ts +0 -3
  80. package/dist/utils/output.d.ts.map +0 -1
  81. package/dist/utils/output.js +0 -65
  82. package/dist/utils/output.js.map +0 -1
  83. package/dist/vitest.config.d.ts +0 -3
  84. package/dist/vitest.config.d.ts.map +0 -1
  85. package/dist/vitest.config.js +0 -21
  86. package/dist/vitest.config.js.map +0 -1
  87. package/templates/prisma/postgresql/.env +0 -3
  88. package/templates/prisma/sqlite/.env +0 -1
package/dist/bin/index.js DELETED
@@ -1,796 +0,0 @@
1
- #!/usr/bin/env node
2
- import fs from "fs-extra";
3
- import path from "path";
4
- import chalk from "chalk";
5
- import inquirer from "inquirer";
6
- import { ExitPromptError } from "@inquirer/core";
7
- import ora from "ora";
8
- import { execSync, ChildProcess } from "child_process";
9
- import { fileURLToPath } from "url";
10
- import { spawnSync, spawn } from "child_process";
11
- import os from "os";
12
- const spinner = ora().start();
13
- const activeProcesses = new Set();
14
- export function run(cmd, args, options) {
15
- return new Promise((resolve, reject) => {
16
- const child = spawn(cmd, args, {
17
- cwd: options.cwd,
18
- stdio: "ignore",
19
- });
20
- activeProcesses.add(child);
21
- child.on("exit", (code) => {
22
- activeProcesses.delete(child);
23
- if (code === 0) {
24
- resolve();
25
- }
26
- else {
27
- reject(new Error(`${cmd} exited with code ${code}`));
28
- }
29
- });
30
- child.on("error", (err) => {
31
- activeProcesses.delete(child);
32
- reject(err);
33
- });
34
- });
35
- }
36
- function killAllProcesses() {
37
- for (const proc of activeProcesses) {
38
- try {
39
- proc.kill("SIGINT");
40
- }
41
- catch { }
42
- }
43
- activeProcesses.clear();
44
- }
45
- function getCommand(cmd) {
46
- const isWin = process.platform === "win32";
47
- if (cmd === "npm")
48
- return isWin ? "npm.cmd" : "npm";
49
- if (cmd === "npx")
50
- return isWin ? "npx.cmd" : "npx";
51
- if (cmd === "git")
52
- return isWin ? "git.exe" : "git";
53
- return cmd;
54
- }
55
- //make sure steps are completed
56
- function stepActuallyCompleted(step) {
57
- switch (step) {
58
- case "deps-installed":
59
- return fs.existsSync(path.join(targetDir, "node_modules"));
60
- case "prisma-generated":
61
- return fs.existsSync(path.join(targetDir, "node_modules/.prisma/client"));
62
- case "git-initialized":
63
- return fs.existsSync(path.join(targetDir, ".git"));
64
- default:
65
- return true;
66
- }
67
- }
68
- const args = process.argv.slice(2);
69
- const projectNameArg = args.find(arg => !arg.startsWith("--"));
70
- //const projectNameArg = process.argv[2];
71
- if (!projectNameArg) {
72
- console.log(chalk.red("❌ Please provide a project name"));
73
- process.exit(1);
74
- }
75
- const projectName = projectNameArg;
76
- //let answers:any = {};
77
- let state = {
78
- step: "start",
79
- projectName,
80
- };
81
- const platform = os.platform();
82
- // 'linux' | 'darwin' | 'win32'
83
- const isTermux = process.env.PREFIX?.includes("com.termux") ||
84
- process.env.TERMUX === "true";
85
- function getBestHashLib() {
86
- if (isTermux)
87
- return "bcryptjs";
88
- if (platform === "win32")
89
- return "bcryptjs";
90
- // avoids build tools issues for most users
91
- if (platform === "darwin")
92
- return "argon2";
93
- // mac usually fine
94
- if (platform === "linux")
95
- return "argon2";
96
- // but still fallback later if needed
97
- return "bcryptjs";
98
- }
99
- function generateHashModule(hashLib) {
100
- if (hashLib === "argon2") {
101
- return `
102
- import argon2 from "argon2";
103
-
104
- export const hashPassword = (password: string) => {
105
- return argon2.hash(password);
106
- };
107
-
108
- export const comparePassword = (password: string, hash: string) => {
109
- return argon2.verify(hash, password);
110
- };
111
- `;
112
- }
113
- return `
114
- import bcrypt from "bcryptjs";
115
-
116
- export const hashPassword = (password: string) => {
117
- return bcrypt.hash(password, 10);
118
- };
119
-
120
- export const comparePassword = (password: string, hash: string) => {
121
- return bcrypt.compare(password, hash);
122
- };
123
- `;
124
- }
125
- const __filename = fileURLToPath(import.meta.url);
126
- const __dirname = path.dirname(__filename);
127
- const isProduction = args.includes("--production-ready");
128
- const isResume = args.includes("--resume");
129
- const targetDir = path.resolve(process.cwd(), projectName);
130
- let projectCreated = false;
131
- const stepOrder = [
132
- "start",
133
- "prompts",
134
- "project-created",
135
- "auth-installed",
136
- "prisma-configured",
137
- "deps-installed",
138
- "prisma-generated",
139
- "production-configured",
140
- "git-initialized",
141
- "done",
142
- ];
143
- const stepLabels = {
144
- start: "Starting",
145
- prompts: "Collecting inputs",
146
- "project-created": "Project scaffold",
147
- "auth-installed": "Auth setup",
148
- "prisma-configured": "Prisma setup",
149
- "deps-installed": "Dependencies install",
150
- "prisma-generated": "Prisma generate",
151
- "production-configured": "Production setup",
152
- "git-initialized": "Git init",
153
- done: "Completed",
154
- };
155
- const globalStateDir = path.join(process.cwd(), ".authenik8");
156
- const stateFile = path.join(globalStateDir, `${projectName}.json`);
157
- function hasReachedStep(currentStep, targetStep) {
158
- return stepOrder.indexOf(currentStep) >= stepOrder.indexOf(targetStep);
159
- }
160
- //function saveState(step: StepName, extra: Partial<CliState> = {}) {
161
- function saveState(update) {
162
- state = { ...state, ...update };
163
- fs.ensureDirSync(path.dirname(stateFile));
164
- fs.writeJsonSync(stateFile, state, { spaces: 2 });
165
- }
166
- function loadState() {
167
- if (!fs.existsSync(stateFile))
168
- return null;
169
- return fs.readJsonSync(stateFile);
170
- }
171
- function clearState() {
172
- if (fs.existsSync(stateFile)) {
173
- fs.removeSync(stateFile);
174
- }
175
- }
176
- function renderStep(current) {
177
- console.clear();
178
- renderHeader();
179
- for (const step of stepOrder) {
180
- const label = stepLabels[step];
181
- if (step === "production-configured" && !isProduction) {
182
- continue;
183
- }
184
- if (step === current) {
185
- console.log(chalk.yellow(`⏳ ${label}...`));
186
- break;
187
- }
188
- if (hasReachedStep(current, step)) {
189
- console.log(chalk.green(`✔ ${label}`));
190
- }
191
- else {
192
- console.log(chalk.gray(`○ ${label}`));
193
- }
194
- }
195
- console.log("");
196
- }
197
- function isInterruptedError(err) {
198
- return (typeof err === "object" &&
199
- err !== null &&
200
- "signal" in err &&
201
- (err.signal === "SIGINT" ||
202
- err.signal === "SIGTERM"));
203
- }
204
- async function exitForInterrupt(err) {
205
- if (isInterruptedError(err)) {
206
- throw err;
207
- }
208
- }
209
- async function cleanupIncompleteProject() {
210
- if (projectCreated && fs.existsSync(targetDir)) {
211
- await fs.remove(targetDir);
212
- console.log("🧹 Cleaned up incomplete project.");
213
- }
214
- }
215
- const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
216
- const cleanLogo = `
217
-
218
- █████╗ █████╗
219
- ██╔══██╗ ██╔══██╗
220
- ███████║ ╚█████╔╝
221
- ██╔══██║ ██╔══██╗
222
- ██║ ██║ ╚█████╔╝
223
- ╚═╝ ╚═╝ ╚════╝
224
-
225
- A8
226
-
227
- Authenik8 CLI
228
- Build Faster
229
- More , Secure
230
- `;
231
- const glitchFrames = [
232
- `
233
- █████╗ █████╗
234
- ██╔══██╗ ██▒▒▒▒██
235
- ███████║ ╚█████╔╝
236
- ██╔══██║ ██▒▒▒▒██
237
- ██║ ██║ ╚█████╔╝
238
- ╚═╝ ╚═╝ ╚════╝
239
-
240
- A8
241
- Authenik8 CLI
242
-
243
- More
244
- `,
245
- `
246
- ██▓▓██╗ ██▓▓██╗
247
- ██▒▒██╔╝ ██▒▒██╔╝
248
- ██▒▒▒▒██ ╚█████╔╝
249
- ██▓▓██╔╝ ██▒▒██╗
250
- ██▒▒██║ ╚█████╔╝
251
- ╚═════╝ ╚════╝
252
-
253
- A8
254
- Authenik8 CLI
255
- Faster
256
- `,
257
- `
258
- ██▒▒██╗ ██▒▒██╗
259
- ██▓▓██╔╝ ██▓▓██╔╝
260
- ██▒▒▒▒██ ╚█████╔╝
261
- ██▓▓██╔╝ ██▓▓██╗
262
- ██▒▒██║ ╚█████╔╝
263
- ╚═════╝ ╚════╝
264
-
265
- A8
266
- Authenik8 CLI
267
- Build
268
- `,
269
- `
270
- ██▓▓██╗ ██▓▓██╗
271
- ██▒▒██╔╝ ██▒▒██╔╝
272
- ██▒▒▒▒██ ╚█████╔╝
273
- ██▓▓██╔╝ ██▒▒██╗
274
- ██▒▒██║ ╚█████╔╝
275
- ╚═════╝ ╚════╝
276
-
277
- A8
278
- Authenik8 CLI
279
-
280
- `
281
- ];
282
- function renderHeader() {
283
- console.log(chalk.cyan.bold("Happy building \nAuthenik8 CLI"));
284
- console.log(chalk.gray("────────────────────"));
285
- console.log("");
286
- }
287
- async function showBootLogo() {
288
- console.clear();
289
- spinner.text = "Initializing Authenik8 engine...";
290
- // Phase 1: clean → unstable
291
- console.clear();
292
- console.log(chalk.cyan(cleanLogo));
293
- await sleep(200);
294
- // Phase 2: glitch burst (irregular feel)
295
- for (let i = 0; i < 5; i++) {
296
- console.clear();
297
- const frame = glitchFrames[Math.floor(Math.random() * glitchFrames.length)];
298
- console.log(chalk.cyan(frame));
299
- await sleep(120 + Math.random() * 120);
300
- }
301
- // Phase 3: stabilization flicker
302
- for (let i = 0; i < 2; i++) {
303
- console.clear();
304
- console.log(chalk.cyan(cleanLogo));
305
- await sleep(180);
306
- console.clear();
307
- console.log(chalk.gray(cleanLogo));
308
- await sleep(120);
309
- }
310
- // Final render
311
- console.clear();
312
- console.log(chalk.cyan.bold(cleanLogo));
313
- await sleep(800);
314
- spinner.succeed("Engine ready");
315
- }
316
- async function main() {
317
- process.on("SIGINT", async () => {
318
- console.log("\n");
319
- spinner.stop();
320
- killAllProcesses();
321
- console.log(chalk.yellow("⏸ Setup interrupted."));
322
- console.log(chalk.gray(`↻ Resume with: create-authenik8-app ${projectName} --resume`));
323
- process.exit(0);
324
- });
325
- try {
326
- await showBootLogo();
327
- if (process.argv.includes("--help")) {
328
- console.log(`
329
- Authenik8 CLI
330
-
331
- Usage:
332
- create-authenik8-app <project-name>
333
-
334
- Options:
335
- --resume Resume project setup(in development)
336
- --help Show this help message
337
- --production-ready production mode
338
- Features:
339
-
340
- Express backend (default)
341
-
342
- Optional Prisma ORM
343
-
344
- PostgreSQL (production)
345
-
346
- SQLite (quick start)
347
-
348
- Optional Git initialization
349
-
350
- Optional OAuth
351
-
352
-
353
- Examples:
354
- create-authenik8-app my-app
355
- `);
356
- process.exit(0);
357
- }
358
- console.log(chalk.gray(`
359
- Available options:
360
- Authentication setup:
361
- • base (JWT only)
362
- • auth (JWT + Password/Email auth)
363
- • auth-oauth(JWT+ Password/Email + oauth)
364
-
365
- Frameworks:
366
- • Express
367
- • Fastify(coming soon)
368
-
369
- Database (if Prisma enabled):
370
- • PostgreSQL
371
- • SQLite (quick start)
372
-
373
- Features:
374
- • Prisma ORM (optional)
375
- • Git initialization (optional)
376
- • OAuth + Auth
377
-
378
-
379
- `));
380
- const savedState = loadState();
381
- let currentStep = "start";
382
- if (!isResume && fs.existsSync(targetDir)) {
383
- if (savedState) {
384
- console.log(chalk.red(`❌ "${projectName}" already contains an incomplete Authenik8 setup. Run again with --resume.`));
385
- }
386
- else {
387
- console.log(chalk.red(`❌ Directory "${projectName}" already exists.`));
388
- }
389
- process.exit(1);
390
- }
391
- if (isResume || fs.existsSync(stateFile)) {
392
- console.log(chalk.gray(`
393
- Resumable steps:
394
- ✔ project scaffold
395
- ✔ auth install
396
- ✔ prisma setup
397
- ✔ deps install
398
- ✔ prisma generate
399
- ✔ git init
400
- `));
401
- }
402
- if (isResume) {
403
- if (!savedState) {
404
- console.log(chalk.red(`❌ No saved setup state found for "${projectName}".`));
405
- process.exit(1);
406
- }
407
- state = savedState;
408
- currentStep = state.step;
409
- console.log(chalk.yellow(`\n↻ Resuming setup for ${projectName} from "${currentStep}"...\n`));
410
- }
411
- else {
412
- const promptAnswers = await inquirer.prompt([
413
- {
414
- type: "list",
415
- name: "framework",
416
- message: "Choose framework:",
417
- choices: ["Express", "Fastify (coming soon)"],
418
- default: "Express",
419
- },
420
- {
421
- type: "confirm",
422
- name: "usePrisma",
423
- message: "Use Prisma?",
424
- default: true,
425
- },
426
- {
427
- type: "list",
428
- name: "database",
429
- message: "Choose database:",
430
- choices: [
431
- { name: "PostgreSQL", value: "postgresql" },
432
- { name: "SQLite ", value: "sqlite" }
433
- ],
434
- when: (answers) => answers.usePrisma,
435
- default: "sqlite",
436
- },
437
- {
438
- type: "confirm",
439
- name: "useGit",
440
- message: "Initialize git?",
441
- default: true,
442
- }, {
443
- type: "list",
444
- name: "authMode",
445
- message: "Choose authentication setup:",
446
- choices: [
447
- { name: "JWT only", value: "base" },
448
- { name: "Email + Password Auth", value: "auth" },
449
- { name: "Full Auth (Password + OAuth)", value: "auth-oauth" },
450
- ],
451
- default: "base"
452
- }
453
- ]);
454
- //saveState({
455
- //...promptAnswers,
456
- //step:"prompts"});
457
- state = {
458
- ...state,
459
- ...promptAnswers,
460
- step: "prompts"
461
- };
462
- saveState({
463
- ...state
464
- });
465
- currentStep = "prompts";
466
- }
467
- function assertRequired(value, name) {
468
- if (value === undefined || value === null || value === "") {
469
- console.log(`❌ Missing required input: ${name}`);
470
- process.exit(1);
471
- }
472
- }
473
- assertRequired(state.framework, "framework");
474
- assertRequired(state.authMode, "authMode");
475
- if (state.usePrisma) {
476
- if (!state.database) {
477
- state.database = "sqlite";
478
- }
479
- assertRequired(state.database, "database");
480
- }
481
- console.log(chalk.cyan("\nSetting up your project\n"));
482
- const templateRoot = path.resolve(__dirname, "../../templates");
483
- let templateName = "express-base";
484
- if (state.authMode === "auth") {
485
- templateName = "express-auth";
486
- }
487
- if (state.authMode === "auth-oauth") {
488
- templateName = "express-auth+";
489
- }
490
- const templatePath = path.join(templateRoot, templateName);
491
- // 📁 Create project (SPINNER)
492
- if (!hasReachedStep(currentStep, "project-created")) {
493
- renderStep("project-created");
494
- try {
495
- await fs.copy(templatePath, targetDir);
496
- projectCreated = true;
497
- saveState({ step: "project-created" });
498
- currentStep = "project-created";
499
- renderStep(currentStep);
500
- }
501
- catch (err) {
502
- console.error(err);
503
- process.exit(1);
504
- }
505
- }
506
- else {
507
- console.log(chalk.gray("↷ Skipping project creation (already completed)"));
508
- }
509
- let selectedHash = "bcryptjs"; // default safe fallback
510
- if (!hasReachedStep(currentStep, "auth-installed")) {
511
- if (state.authMode !== "base") {
512
- spinner.start("Installing password auth...");
513
- selectedHash = getBestHashLib();
514
- try {
515
- const installResult = await run(getCommand("npm"), ["install", selectedHash], {
516
- cwd: targetDir,
517
- stdio: "ignore"
518
- });
519
- }
520
- catch {
521
- if (selectedHash !== "bcryptjs") {
522
- spinner.warn(`${selectedHash} failed, falling back to bcryptjs`);
523
- const fallbackResult = await run(getCommand("npm"), ["install", "bcryptjs"], {
524
- cwd: targetDir,
525
- stdio: "ignore",
526
- });
527
- spinner.stop();
528
- selectedHash = "bcryptjs";
529
- renderStep("auth-installed");
530
- }
531
- else {
532
- spinner.fail("Failed to install password auth");
533
- process.exit(1);
534
- spinner.fail("Failed to install password auth");
535
- process.exit(1);
536
- }
537
- }
538
- }
539
- renderStep("auth-installed");
540
- if (state.authMode !== "base") {
541
- spinner.start("Installing password auth...");
542
- const hashLib = selectedHash;
543
- await fs.writeFile(path.join(targetDir, "src/utils/hash.ts"), generateHashModule(hashLib));
544
- }
545
- saveState({ step: "auth-installed", ...(state.authMode !== "base" && { hashLib: selectedHash })
546
- });
547
- currentStep = "auth-installed";
548
- renderStep(currentStep);
549
- }
550
- else {
551
- selectedHash = savedState?.hashLib ?? selectedHash;
552
- console.log(chalk.gray("↷ Skipping auth setup (already completed)"));
553
- }
554
- if (!hasReachedStep(currentStep, "prisma-configured")) {
555
- const pkgPath = path.join(targetDir, "package.json");
556
- const pkg = await fs.readJson(pkgPath);
557
- pkg.dependencies = {
558
- ...pkg.dependencies,
559
- ioredis: "^5.8.1",
560
- };
561
- if (state.usePrisma) {
562
- spinner.start("Adding Prisma setup...");
563
- try {
564
- const dbType = state.database ===
565
- "postgresql" ? "postgresql" :
566
- "sqlite";
567
- const prismaTemplatePath = path.join(templateRoot, `prisma/${dbType}`);
568
- // Copy prisma schema
569
- await fs.copy(path.join(prismaTemplatePath, "schema.prisma"), path.join(targetDir, "prisma/schema.prisma"));
570
- // Copy env
571
- await fs.copy(path.join(prismaTemplatePath, ".env"), path.join(targetDir, ".env"));
572
- // Inject dependencies
573
- pkg.dependencies = {
574
- ...pkg.dependencies,
575
- "@prisma/client": "5.22.0",
576
- };
577
- pkg.devDependencies = {
578
- ...pkg.devDependencies,
579
- prisma: "5.22.0",
580
- };
581
- // Add scripts
582
- pkg.scripts = {
583
- ...pkg.scripts,
584
- "prisma:generate": "prisma generate",
585
- "prisma:migrate": "prisma migrate dev",
586
- };
587
- await fs.writeJson(pkgPath, pkg, { spaces: 2 });
588
- spinner.succeed(`Prisma (${dbType}) configured`);
589
- }
590
- catch (err) {
591
- spinner.fail("Failed to setup Prisma");
592
- exitForInterrupt(err);
593
- }
594
- }
595
- await fs.writeJson(pkgPath, pkg, { spaces: 2 });
596
- saveState({ step: "prisma-configured", ...(state.authMode !== "base" && { hashLib: selectedHash })
597
- });
598
- currentStep = "prisma-configured";
599
- renderStep(currentStep);
600
- }
601
- else {
602
- console.log(chalk.gray(" Skipping Prisma/package setup (already completed)"));
603
- }
604
- if (!hasReachedStep(currentStep, "deps-installed")) {
605
- renderStep("deps-installed");
606
- spinner.start("Installing dependencies...(this may take a few minutes)");
607
- try {
608
- await run(getCommand("npm"), ["install"], {
609
- cwd: targetDir,
610
- stdio: "ignore",
611
- });
612
- spinner.stop();
613
- }
614
- catch (err) {
615
- spinner.fail("Failed to install dependencies");
616
- exitForInterrupt(err);
617
- }
618
- saveState({ step: "deps-installed", ...(state.authMode !== "base" && { hashLib: selectedHash })
619
- });
620
- currentStep = "deps-installed";
621
- renderStep(currentStep);
622
- }
623
- else {
624
- await run(getCommand("npm"), ["install"], {
625
- cwd: targetDir,
626
- stdio: "ignore",
627
- });
628
- }
629
- if (!hasReachedStep(currentStep, "prisma-generated")) {
630
- if (state.usePrisma) {
631
- spinner.start("Generating Prisma client...");
632
- try {
633
- await run(getCommand("npx"), ["prisma@5.22.0", "generate"], {
634
- cwd: targetDir,
635
- stdio: "ignore"
636
- });
637
- spinner.stop();
638
- }
639
- catch (err) {
640
- spinner.fail("Failed to generate Prisma client");
641
- exitForInterrupt(err);
642
- }
643
- }
644
- saveState({ step: "prisma-generated", ...(state.authMode !== "base" && { hashLib: selectedHash })
645
- });
646
- currentStep = "prisma-generated";
647
- renderStep(currentStep);
648
- }
649
- else {
650
- console.log(chalk.gray("↷ Skipping Prisma client generation (already completed)"));
651
- }
652
- if (isProduction && !hasReachedStep(currentStep, "production-configured")) {
653
- spinner.start("Setting up production mode (PM2)...");
654
- try {
655
- await run(getCommand("npm"), ["install pm2"], {
656
- cwd: targetDir,
657
- stdio: "ignore",
658
- });
659
- spinner.stop();
660
- }
661
- catch (err) {
662
- spinner.fail("Failed to install PM2");
663
- exitForInterrupt(err);
664
- }
665
- saveState({ step: "production-configured", ...(state.authMode !== "base" && { hashLib: selectedHash })
666
- });
667
- currentStep = "production-configured";
668
- renderStep(currentStep);
669
- }
670
- if (!hasReachedStep(currentStep, "git-initialized")) {
671
- if (state.useGit) {
672
- renderStep("git-initialized");
673
- try {
674
- await run(getCommand("git"), ["init"], {
675
- cwd: targetDir,
676
- stdio: "ignore",
677
- });
678
- spinner.stop();
679
- }
680
- catch (err) {
681
- spinner.fail("Git init failed");
682
- }
683
- }
684
- saveState({ step: "git-initialized", ...(state.authMode !== "base" && { hashLib: selectedHash }),
685
- });
686
- currentStep = "git-initialized";
687
- renderStep("done");
688
- }
689
- else {
690
- console.log(chalk.gray("↷ Skipping git init (already completed)"));
691
- }
692
- console.log(chalk.green.bold("\n🎉 Authenik8 app created successfully!\n"));
693
- if (isProduction) {
694
- fs.appendFileSync(path.join(targetDir, "README.md"), `
695
-
696
- 🚀 Production Mode
697
-
698
- This project is configured for production using PM2.
699
-
700
- Start app in cluster mode:
701
-
702
- npm run pm2:start
703
-
704
- View logs:
705
-
706
- npm run pm2:logs
707
-
708
- Stop app:
709
-
710
- npm run pm2:stop
711
-
712
- `);
713
- }
714
- console.log(chalk.white(`
715
- Next steps:
716
-
717
- cd ${projectName}
718
- redis-server --daemonize yes
719
- npm run dev
720
-
721
- Auth Features:
722
- ${state.authMode === "base"
723
- ? "✓ JWT only"
724
- : state.authMode === "auth"
725
- ? "✓ Email + Password"
726
- : "✓ Password + OAuth (Google/GitHub)"}
727
-
728
- 🛠 Stack:
729
- ✔ Express
730
- ✔ ${state.usePrisma ? (state.database === "postgresql" ? "PostgreSQL" : "SQLite") : "No database"}
731
- ✔ ${state.usePrisma ? "Prisma ORM" : "No ORM"}
732
-
733
- 📡 API Routes:
734
- ${state.authMode === "base"
735
- ? `
736
- GET /public
737
- GET /guest
738
- GET /protected
739
- POST /refresh
740
- `
741
- : state.authMode === "auth"
742
- ? `
743
- POST /auth/register
744
- POST /auth/login
745
- POST /auth/refresh
746
- GET /protected
747
- `
748
- : `
749
- POST /auth/register
750
- POST /auth/login
751
- POST /auth/refresh
752
- GET /auth/google
753
- GET /auth/github
754
- GET /protected
755
- `}
756
-
757
- 🔥 You're ready to build.
758
- `));
759
- if (isProduction) {
760
- console.log(`
761
- 🚀 Production Ready Enabled:
762
-
763
- ✔ PM2 installed
764
- ✔ Cluster mode enabled
765
- ✔ Memory auto-restart (300MB)
766
-
767
- Run:
768
- npm run pm2:start
769
- `);
770
- }
771
- saveState({ step: "done", ...(state.authMode !== "base" && { hashLib: selectedHash }),
772
- });
773
- clearState();
774
- }
775
- catch (err) {
776
- if (err instanceof ExitPromptError) {
777
- throw err;
778
- console.error("Fatal error", err);
779
- process.exit(1);
780
- }
781
- }
782
- }
783
- main().catch(async (err) => {
784
- if (err instanceof ExitPromptError) {
785
- console.log("\n👋 Authenik8 setup cancelled.You can --resume later");
786
- killAllProcesses();
787
- await new Promise((r) => setTimeout(r, 300));
788
- console.log(chalk.bgYellow.black(" SETUP CANCELLED "));
789
- await cleanupIncompleteProject();
790
- process.exit(0);
791
- }
792
- console.error(chalk.red("\n❌ Unexpected error:"), err);
793
- await cleanupIncompleteProject();
794
- process.exit(1);
795
- });
796
- //# sourceMappingURL=index.js.map