stackkit 0.2.7 → 0.2.9

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 (61) hide show
  1. package/README.md +91 -12
  2. package/dist/lib/fs/files.js +1 -1
  3. package/dist/lib/generation/code-generator.d.ts +2 -7
  4. package/dist/lib/generation/code-generator.js +120 -56
  5. package/dist/lib/utils/fs-helpers.d.ts +1 -1
  6. package/modules/auth/authjs/generator.json +16 -16
  7. package/modules/auth/better-auth/files/express/middlewares/authorize.ts +121 -41
  8. package/modules/auth/better-auth/files/express/modules/auth/auth.controller.ts +257 -0
  9. package/modules/auth/better-auth/files/express/modules/auth/auth.interface.ts +23 -0
  10. package/modules/auth/better-auth/files/express/modules/auth/auth.route.ts +22 -0
  11. package/modules/auth/better-auth/files/express/modules/auth/auth.service.ts +403 -0
  12. package/modules/auth/better-auth/files/express/templates/google-redirect.ejs +91 -0
  13. package/modules/auth/better-auth/files/express/templates/otp.ejs +87 -0
  14. package/modules/auth/better-auth/files/express/types/express.d.ts +6 -8
  15. package/modules/auth/better-auth/files/express/utils/cookie.ts +19 -0
  16. package/modules/auth/better-auth/files/express/utils/jwt.ts +34 -0
  17. package/modules/auth/better-auth/files/express/utils/token.ts +66 -0
  18. package/modules/auth/better-auth/files/nextjs/api/auth/[...all]/route.ts +1 -1
  19. package/modules/auth/better-auth/files/nextjs/lib/auth/auth-guards.ts +11 -1
  20. package/modules/auth/better-auth/files/nextjs/templates/email-otp.tsx +74 -0
  21. package/modules/auth/better-auth/files/shared/config/env.ts +113 -0
  22. package/modules/auth/better-auth/files/shared/lib/auth-client.ts +1 -1
  23. package/modules/auth/better-auth/files/shared/lib/auth.ts +151 -62
  24. package/modules/auth/better-auth/files/shared/prisma/schema.prisma +22 -11
  25. package/modules/auth/better-auth/files/shared/utils/email.ts +71 -0
  26. package/modules/auth/better-auth/generator.json +159 -81
  27. package/modules/database/mongoose/generator.json +18 -18
  28. package/modules/database/prisma/generator.json +44 -44
  29. package/package.json +1 -1
  30. package/templates/express/env.example +2 -2
  31. package/templates/express/eslint.config.mjs +7 -0
  32. package/templates/express/node_modules/.bin/acorn +17 -0
  33. package/templates/express/node_modules/.bin/eslint +17 -0
  34. package/templates/express/node_modules/.bin/tsc +17 -0
  35. package/templates/express/node_modules/.bin/tsserver +17 -0
  36. package/templates/express/node_modules/.bin/tsx +17 -0
  37. package/templates/express/package.json +12 -6
  38. package/templates/express/src/app.ts +15 -7
  39. package/templates/express/src/config/cors.ts +8 -7
  40. package/templates/express/src/config/env.ts +26 -5
  41. package/templates/express/src/config/logger.ts +2 -2
  42. package/templates/express/src/config/rate-limit.ts +2 -2
  43. package/templates/express/src/modules/health/health.controller.ts +13 -11
  44. package/templates/express/src/routes/index.ts +1 -6
  45. package/templates/express/src/server.ts +12 -12
  46. package/templates/express/src/shared/errors/app-error.ts +16 -0
  47. package/templates/express/src/shared/middlewares/error.middleware.ts +154 -12
  48. package/templates/express/src/shared/middlewares/not-found.middleware.ts +2 -1
  49. package/templates/express/src/shared/utils/catch-async.ts +11 -0
  50. package/templates/express/src/shared/utils/pagination.ts +6 -1
  51. package/templates/express/src/shared/utils/send-response.ts +25 -0
  52. package/templates/nextjs/lib/env.ts +19 -8
  53. package/modules/auth/better-auth/files/shared/lib/email/email-service.ts +0 -33
  54. package/modules/auth/better-auth/files/shared/lib/email/email-templates.ts +0 -89
  55. package/templates/express/eslint.config.cjs +0 -42
  56. package/templates/express/src/config/helmet.ts +0 -5
  57. package/templates/express/src/modules/health/health.service.ts +0 -6
  58. package/templates/express/src/shared/errors/error-codes.ts +0 -9
  59. package/templates/express/src/shared/logger/logger.ts +0 -20
  60. package/templates/express/src/shared/utils/async-handler.ts +0 -9
  61. package/templates/express/src/shared/utils/response.ts +0 -9
package/README.md CHANGED
@@ -1,34 +1,113 @@
1
1
  # StackKit CLI
2
2
 
3
- CLI for scaffolding and composing modular JavaScript applications.
3
+ Production-ready full-stack project generator.
4
4
 
5
- ## Quick Start
5
+ ## Installation
6
6
 
7
- Create a new project without installing globally:
7
+ No installation required. Use npx to get the latest version:
8
8
 
9
9
  ```bash
10
+ npx stackkit@latest <command>
11
+ ```
12
+
13
+ ## Commands
14
+
15
+ ### create
16
+
17
+ Generate a new project:
18
+
19
+ ```bash
20
+ # Interactive mode
10
21
  npx stackkit@latest create my-app
22
+
23
+ # With options
24
+ npx stackkit@latest create my-app \
25
+ --framework nextjs \
26
+ --database prisma-postgresql \
27
+ --auth better-auth \
28
+ --language typescript
11
29
  ```
12
30
 
13
- Add features to an existing project:
31
+ **Options:**
32
+
33
+ - `--framework, -f` - nextjs, express, react
34
+ - `--database, -d` - prisma-postgresql, prisma-mysql, prisma-sqlite, prisma-mongodb, mongoose, none
35
+ - `--auth, -a` - better-auth, authjs, none
36
+ - `--language, -l` - typescript, javascript
37
+ - `--package-manager, -p` - pnpm, npm, yarn, bun
38
+ - `--yes, -y` - Use defaults
39
+ - `--skip-install` - Don't install dependencies
40
+ - `--no-git` - Don't initialize git
41
+
42
+ ### add
43
+
44
+ Add features to existing project:
14
45
 
15
46
  ```bash
16
- npx stackkit@latest add <module>
47
+ npx stackkit@latest add
17
48
  ```
18
49
 
19
- Check project health:
50
+ Interactively select and install modules.
51
+
52
+ ### doctor
53
+
54
+ Diagnose project health:
20
55
 
21
56
  ```bash
22
57
  npx stackkit@latest doctor
58
+
59
+ # Verbose output
60
+ npx stackkit@latest doctor --verbose
61
+
62
+ # JSON output (for CI/CD)
63
+ npx stackkit@latest doctor --json
64
+ ```
65
+
66
+ ### list
67
+
68
+ Show available options:
69
+
70
+ ```bash
71
+ npx stackkit@latest list
23
72
  ```
24
73
 
25
- ## Supported technologies
74
+ ## Supported Technologies
75
+
76
+ **Frameworks:**
77
+
78
+ - Next.js (App Router)
79
+ - Express (TypeScript API)
80
+ - React (Vite SPA)
81
+
82
+ **Databases:**
83
+
84
+ - Prisma (PostgreSQL, MySQL, SQLite, MongoDB)
85
+ - Mongoose (MongoDB)
86
+
87
+ **Authentication:**
26
88
 
27
- - Frameworks: Next.js, React, Express
28
- - Databases: Prisma, Mongoose
29
- - Auth: Auth.js / Better Auth
89
+ - Better Auth (All frameworks)
90
+ - Auth.js (Next.js only)
91
+
92
+ ## Examples
93
+
94
+ ```bash
95
+ # Full-stack Next.js
96
+ npx stackkit@latest create my-app --framework nextjs --database prisma-postgresql --auth better-auth
97
+
98
+ # Express API
99
+ npx stackkit@latest create my-api --framework express --database mongoose
100
+
101
+ # React frontend
102
+ npx stackkit@latest create my-spa --framework react --auth better-auth
103
+ ```
30
104
 
31
105
  ## Links
32
106
 
33
- - Website: https://stackkit.tariqul.dev
34
- - Repo: https://github.com/tariqul420/stackkit
107
+ - **Documentation**: https://stackkit.tariqul.dev
108
+ - **GitHub**: https://github.com/tariqul420/stackkit
109
+ - **Issues**: https://github.com/tariqul420/stackkit/issues
110
+
111
+ ## License
112
+
113
+ MIT © [Tariqul Islam](https://github.com/tariqul420)
@@ -19,7 +19,7 @@ async function copyBaseFramework(templatesDir, targetDir, framework) {
19
19
  throw new Error(`Base template not found for framework: ${framework}\n` + `Expected at: ${baseDir}`);
20
20
  }
21
21
  await fs_extra_1.default.copy(baseDir, targetDir, {
22
- filter: (src) => !constants_1.EXCLUDE_FROM_COPY.includes(path_1.default.basename(src)),
22
+ filter: (src) => !constants_1.EXCLUDE_FROM_COPY.some((entry) => entry === path_1.default.basename(src)),
23
23
  });
24
24
  }
25
25
  async function mergePackageJson(targetDir, config) {
@@ -74,16 +74,14 @@ export declare class AdvancedCodeGenerator {
74
74
  private copyTemplate;
75
75
  private processOperationTemplates;
76
76
  private executeCreateFile;
77
+ private parsePathPattern;
78
+ private collectFilesRecursively;
77
79
  private executePatchFile;
78
80
  private executeAddDependency;
79
81
  private executeAddScript;
80
82
  private executeAddEnv;
81
83
  private executeRunCommand;
82
84
  private generatePackageJson;
83
- /**
84
- * Apply generators to an existing project directory instead of creating a new template.
85
- * This executes applicable operations and updates package.json in-place.
86
- */
87
85
  applyToProject(selectedModules: {
88
86
  framework: string;
89
87
  database?: string;
@@ -95,8 +93,5 @@ export declare class AdvancedCodeGenerator {
95
93
  databases: string[];
96
94
  auths: string[];
97
95
  };
98
- /**
99
- * Register a generator config dynamically (used for modules that only provide module.json patches).
100
- */
101
96
  registerGenerator(type: "framework" | "database" | "auth", name: string, config: GeneratorConfig): void;
102
97
  }
@@ -128,8 +128,7 @@ class AdvancedCodeGenerator {
128
128
  const varNameMatch = result.substring(varStart + 7, equalsIndex).trim();
129
129
  if (!varNameMatch)
130
130
  break;
131
- // Find the end of the variable value by counting braces
132
- // Start with braceCount = 1 because {{#var is already open
131
+ // Find the closing }} for the variable definition, accounting for nested {{#var}}...{{/var}}
133
132
  let braceCount = 1;
134
133
  const valueStart = equalsIndex + 1;
135
134
  let valueEnd = valueStart;
@@ -400,20 +399,6 @@ class AdvancedCodeGenerator {
400
399
  !relativePath.startsWith("node_modules/"));
401
400
  },
402
401
  });
403
- // If template provides a .env.example, create a .env from it when
404
- // the target project does not already have a .env file.
405
- try {
406
- const envExampleSrc = path.join(templatePath, ".env.example");
407
- const envDest = path.join(outputPath, ".env");
408
- if ((await fs.pathExists(envExampleSrc)) && !(await fs.pathExists(envDest))) {
409
- await fs.copy(envExampleSrc, envDest);
410
- }
411
- }
412
- catch {
413
- // ignore (not critical)
414
- }
415
- // Ensure gitignore is present in target even if template authors
416
- // renamed it to avoid npm/package issues (e.g. 'gitignore' or '_gitignore')
417
402
  try {
418
403
  const gitCandidates = [".gitignore", "gitignore", "_gitignore"];
419
404
  for (const g of gitCandidates) {
@@ -430,7 +415,6 @@ class AdvancedCodeGenerator {
430
415
  catch {
431
416
  // ignore
432
417
  }
433
- // Ensure any top-level dotfiles declared in template.json are created
434
418
  try {
435
419
  const templateJsonPath = path.join(templatePath, "template.json");
436
420
  if (await fs.pathExists(templateJsonPath)) {
@@ -454,9 +438,7 @@ class AdvancedCodeGenerator {
454
438
  }
455
439
  continue;
456
440
  }
457
- // For other dotfiles (e.g. .env.example), only create if the template
458
- // actually contains a dotfile source. Don't synthesize from non-dot fallbacks
459
- // to avoid creating files unintentionally.
441
+ // For other dotfiles, only copy if the exact dotfile exists in the template to avoid unintended fallbacks
460
442
  const srcDot = path.join(templatePath, f);
461
443
  if (await fs.pathExists(srcDot)) {
462
444
  await fs.copy(srcDot, targetDest);
@@ -505,6 +487,17 @@ class AdvancedCodeGenerator {
505
487
  catch {
506
488
  // ignore
507
489
  }
490
+ // Handle .env.example -> .env copying if .env doesn't already exist
491
+ try {
492
+ const envExampleDest = path.join(outputPath, ".env.example");
493
+ const envDest = path.join(outputPath, ".env");
494
+ if ((await fs.pathExists(envExampleDest)) && !(await fs.pathExists(envDest))) {
495
+ await fs.copy(envExampleDest, envDest);
496
+ }
497
+ }
498
+ catch {
499
+ // ignore (not critical)
500
+ }
508
501
  }
509
502
  }
510
503
  processOperationTemplates(operation, context) {
@@ -559,28 +552,88 @@ class AdvancedCodeGenerator {
559
552
  async executeCreateFile(operation, context, outputPath) {
560
553
  if (!operation.destination)
561
554
  return;
562
- const destinationPath = path.join(outputPath, this.processTemplate(operation.destination, context));
563
- // Ensure directory exists
564
- await fs.ensureDir(path.dirname(destinationPath));
565
- let content;
555
+ const processedDestination = this.processTemplate(operation.destination, context);
556
+ const { basePath: destinationBasePath, mode: destinationMode } = this.parsePathPattern(processedDestination);
566
557
  if (operation.content) {
567
- // Use content directly
568
- content = this.processTemplate(operation.content, context);
569
- }
570
- else if (operation.source) {
571
- const sourcePath = (0, generator_utils_1.locateOperationSource)(operation.generatorType, operation.generator, operation.source || "");
572
- if (sourcePath && (await fs.pathExists(sourcePath))) {
573
- content = await fs.readFile(sourcePath, "utf-8");
574
- content = this.processTemplate(content, context);
558
+ const destinationPath = path.join(outputPath, processedDestination);
559
+ await fs.ensureDir(path.dirname(destinationPath));
560
+ const content = this.processTemplate(operation.content, context);
561
+ await fs.writeFile(destinationPath, content, "utf-8");
562
+ try {
563
+ const rel = path.relative(outputPath, destinationPath);
564
+ if (rel && !this.createdFiles.includes(rel))
565
+ this.createdFiles.push(rel);
575
566
  }
576
- else {
577
- throw new Error(`Source file not found: ${sourcePath}`);
567
+ catch {
568
+ // ignore logging failures
578
569
  }
570
+ return;
579
571
  }
580
- else {
572
+ if (!operation.source) {
581
573
  throw new Error(`Create file operation must have either 'content' or 'source' field`);
582
574
  }
583
- // Write destination file
575
+ const processedSource = this.processTemplate(operation.source, context);
576
+ const { basePath: sourceBasePathRel, mode: sourceMode } = this.parsePathPattern(processedSource);
577
+ const sourcePath = (0, generator_utils_1.locateOperationSource)(operation.generatorType, operation.generator, sourceBasePathRel);
578
+ if (!sourcePath || !(await fs.pathExists(sourcePath))) {
579
+ throw new Error(`Source file not found: ${sourcePath}`);
580
+ }
581
+ const sourceStat = await fs.stat(sourcePath);
582
+ const shouldCreateMultipleFiles = sourceStat.isDirectory() || sourceMode !== "single";
583
+ if (shouldCreateMultipleFiles) {
584
+ if (!sourceStat.isDirectory()) {
585
+ throw new Error(`Source path must be a directory for wildcard copy: ${processedSource}`);
586
+ }
587
+ let sourceFiles = [];
588
+ if (sourceMode === "flat") {
589
+ const entries = await fs.readdir(sourcePath);
590
+ for (const entry of entries) {
591
+ const candidatePath = path.join(sourcePath, entry);
592
+ const candidateStat = await fs.stat(candidatePath);
593
+ if (candidateStat.isFile()) {
594
+ sourceFiles.push(candidatePath);
595
+ }
596
+ }
597
+ }
598
+ else {
599
+ sourceFiles = await this.collectFilesRecursively(sourcePath);
600
+ }
601
+ for (const sourceFilePath of sourceFiles) {
602
+ let relativeDestinationPath;
603
+ if (destinationMode === "recursive") {
604
+ relativeDestinationPath = path.relative(sourcePath, sourceFilePath);
605
+ }
606
+ else if (destinationMode === "flat") {
607
+ relativeDestinationPath = path.basename(sourceFilePath);
608
+ }
609
+ else {
610
+ relativeDestinationPath =
611
+ sourceMode === "flat"
612
+ ? path.basename(sourceFilePath)
613
+ : path.relative(sourcePath, sourceFilePath);
614
+ }
615
+ const destinationPath = path.join(outputPath, destinationBasePath, relativeDestinationPath);
616
+ await fs.ensureDir(path.dirname(destinationPath));
617
+ let content = await fs.readFile(sourceFilePath, "utf-8");
618
+ content = this.processTemplate(content, context);
619
+ await fs.writeFile(destinationPath, content, "utf-8");
620
+ try {
621
+ const rel = path.relative(outputPath, destinationPath);
622
+ if (rel && !this.createdFiles.includes(rel))
623
+ this.createdFiles.push(rel);
624
+ }
625
+ catch {
626
+ // ignore logging failures
627
+ }
628
+ }
629
+ return;
630
+ }
631
+ const destinationPath = destinationMode === "single"
632
+ ? path.join(outputPath, processedDestination)
633
+ : path.join(outputPath, destinationBasePath, path.basename(sourcePath));
634
+ await fs.ensureDir(path.dirname(destinationPath));
635
+ let content = await fs.readFile(sourcePath, "utf-8");
636
+ content = this.processTemplate(content, context);
584
637
  await fs.writeFile(destinationPath, content, "utf-8");
585
638
  try {
586
639
  const rel = path.relative(outputPath, destinationPath);
@@ -591,6 +644,31 @@ class AdvancedCodeGenerator {
591
644
  // ignore logging failures
592
645
  }
593
646
  }
647
+ parsePathPattern(inputPath) {
648
+ const normalizedPath = inputPath.replace(/\\/g, "/");
649
+ if (normalizedPath.endsWith("/**")) {
650
+ return { basePath: normalizedPath.slice(0, -3), mode: "recursive" };
651
+ }
652
+ if (normalizedPath.endsWith("/*")) {
653
+ return { basePath: normalizedPath.slice(0, -2), mode: "flat" };
654
+ }
655
+ return { basePath: normalizedPath, mode: "single" };
656
+ }
657
+ async collectFilesRecursively(rootDirPath) {
658
+ const files = [];
659
+ const entries = await fs.readdir(rootDirPath);
660
+ for (const entry of entries) {
661
+ const fullPath = path.join(rootDirPath, entry);
662
+ const stat = await fs.stat(fullPath);
663
+ if (stat.isDirectory()) {
664
+ files.push(...(await this.collectFilesRecursively(fullPath)));
665
+ }
666
+ else if (stat.isFile()) {
667
+ files.push(fullPath);
668
+ }
669
+ }
670
+ return files;
671
+ }
594
672
  async executePatchFile(operation, context, outputPath) {
595
673
  if (!operation.destination)
596
674
  return;
@@ -608,14 +686,12 @@ class AdvancedCodeGenerator {
608
686
  switch (patchOp.type) {
609
687
  case "add-import":
610
688
  if (patchOp.imports) {
611
- // Process imports and trim any accidental surrounding blank lines
612
689
  const imports = patchOp.imports
613
690
  .map((imp) => this.processTemplate(imp, context))
614
691
  .join("\n")
615
692
  .replace(/^\n+/, "")
616
693
  .replace(/\n+$/, "");
617
- // Add imports at the top, after existing imports without introducing
618
- // extra blank lines.
694
+ // Split content into lines for easier manipulation
619
695
  const lines = content.split("\n");
620
696
  // Find the last import line index
621
697
  let lastImportIndex = -1;
@@ -623,9 +699,7 @@ class AdvancedCodeGenerator {
623
699
  if (lines[i].trim().startsWith("import"))
624
700
  lastImportIndex = i;
625
701
  }
626
- // Insert right after the last import. If there's a blank line
627
- // immediately after the imports, overwrite that blank line to
628
- // avoid introducing an extra empty line above the inserted imports.
702
+ // Determine where to insert new imports: after the last existing import, or at the top if no imports exist
629
703
  const insertIndex = lastImportIndex === -1 ? 0 : lastImportIndex + 1;
630
704
  // Only add imports that don't already exist in the file
631
705
  const importLines = imports
@@ -641,8 +715,7 @@ class AdvancedCodeGenerator {
641
715
  else {
642
716
  lines.splice(insertIndex, 0, ...newImportLines);
643
717
  }
644
- // After insertion, ensure exactly one blank line after the import block
645
- // Find last import line index again
718
+ // After adding imports, ensure there is exactly one blank line after the last import statement (if there are any imports)
646
719
  let lastIdx = -1;
647
720
  for (let i = 0; i < lines.length; i++) {
648
721
  if (lines[i].trim().startsWith("import"))
@@ -650,7 +723,6 @@ class AdvancedCodeGenerator {
650
723
  }
651
724
  const nextIdx = lastIdx + 1;
652
725
  if (lastIdx !== -1) {
653
- // Remove multiple blank lines after imports
654
726
  let j = nextIdx;
655
727
  while (j < lines.length && lines[j].trim() === "") {
656
728
  j++;
@@ -685,7 +757,6 @@ class AdvancedCodeGenerator {
685
757
  // Normalize code: trim surrounding newlines and ensure single trailing newline
686
758
  let codeNormalized = processedCode.replace(/^\n+|\n+$/g, "") + "\n";
687
759
  // If right already starts with a newline, avoid double-blank by
688
- // removing trailing newline from codeNormalized so only one newline remains
689
760
  const rightStartsWithNewline = right.startsWith("\n");
690
761
  if (rightStartsWithNewline && codeNormalized.endsWith("\n")) {
691
762
  codeNormalized = codeNormalized.replace(/\n+$/, "");
@@ -704,7 +775,6 @@ class AdvancedCodeGenerator {
704
775
  // Normalize code: trim surrounding newlines and ensure single trailing newline
705
776
  let codeNormalized = processedCode.replace(/^\n+|\n+$/g, "") + "\n";
706
777
  // If right already starts with a newline, avoid double-blank by
707
- // removing trailing newline from codeNormalized so only one newline remains
708
778
  const rightStartsWithNewline = right.startsWith("\n");
709
779
  if (rightStartsWithNewline && codeNormalized.endsWith("\n")) {
710
780
  codeNormalized = codeNormalized.replace(/\n+$/, "");
@@ -840,8 +910,7 @@ class AdvancedCodeGenerator {
840
910
  if ((type === "framework" && name === selectedModules.framework) ||
841
911
  (type === "database" && name === selectedModules.database) ||
842
912
  (type === "auth" && name === selectedModules.auth)) {
843
- // Dependencies and devDependencies are now provided via `add-dependency`
844
- // operations. Keep merging scripts from generator configs for now.
913
+ // Merge dependencies, devDependencies, and scripts from the generator into the cumulative objects
845
914
  Object.assign(allScripts, generator.scripts);
846
915
  }
847
916
  }
@@ -860,10 +929,7 @@ class AdvancedCodeGenerator {
860
929
  };
861
930
  await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
862
931
  }
863
- /**
864
- * Apply generators to an existing project directory instead of creating a new template.
865
- * This executes applicable operations and updates package.json in-place.
866
- */
932
+ // Public method to apply generators to an existing project (used for "Add to existing project" flow)
867
933
  async applyToProject(selectedModules, features, projectPath) {
868
934
  const context = {
869
935
  ...selectedModules,
@@ -934,9 +1000,7 @@ class AdvancedCodeGenerator {
934
1000
  }
935
1001
  return { frameworks, databases, auths };
936
1002
  }
937
- /**
938
- * Register a generator config dynamically (used for modules that only provide module.json patches).
939
- */
1003
+ // Method to register a generator configuration
940
1004
  registerGenerator(type, name, config) {
941
1005
  this.generators.set(`${type}:${name}`, config);
942
1006
  }
@@ -7,6 +7,6 @@ export declare function writeFile(filePath: string, content: string): Promise<vo
7
7
  export declare function copyDir(source: string, destination: string, options?: CopyFilterFunction): Promise<void>;
8
8
  export declare function readDir(dirPath: string): Promise<string[]>;
9
9
  export declare function isDirectory(dirPath: string): Promise<boolean>;
10
- export declare function findFilesInDir(dirPath: string, predicate: (file: string) => boolean): Promise<string[]>;
10
+ export declare function findFilesInDir(dirPath: string, predicate: (fileName: string) => boolean): Promise<string[]>;
11
11
  export declare function getEnvFilePath(projectRoot: string): Promise<string | null>;
12
12
  export {};
@@ -3,11 +3,6 @@
3
3
  "type": "auth",
4
4
  "priority": 10,
5
5
  "operations": [
6
- {
7
- "type": "create-file",
8
- "source": "shared/lib/auth.ts",
9
- "destination": "server/auth/auth.ts"
10
- },
11
6
  {
12
7
  "type": "create-file",
13
8
  "source": "nextjs/api/auth/[...nextauth]/route.ts",
@@ -18,6 +13,11 @@
18
13
  "source": "nextjs/proxy.ts",
19
14
  "destination": "proxy.ts"
20
15
  },
16
+ {
17
+ "type": "create-file",
18
+ "source": "shared/lib/auth.ts",
19
+ "destination": "server/auth/auth.ts"
20
+ },
21
21
  {
22
22
  "type": "patch-file",
23
23
  "destination": "prisma/schema.prisma",
@@ -36,6 +36,17 @@
36
36
  "@auth/prisma-adapter": "^2.11.1"
37
37
  }
38
38
  },
39
+ {
40
+ "type": "add-dependency",
41
+ "dependencies": {
42
+ "bcryptjs": "^3.0.3",
43
+ "next-auth": "^5.0.0-beta.30",
44
+ "nodemailer": "^7.0.12"
45
+ },
46
+ "devDependencies": {
47
+ "@types/nodemailer": "^7.0.5"
48
+ }
49
+ },
39
50
  {
40
51
  "type": "add-env",
41
52
  "envVars": {
@@ -48,17 +59,6 @@
48
59
  "EMAIL_PASS": "",
49
60
  "EMAIL_FROM": "noreply@yourapp.com"
50
61
  }
51
- },
52
- {
53
- "type": "add-dependency",
54
- "dependencies": {
55
- "next-auth": "^5.0.0-beta.30",
56
- "bcryptjs": "^3.0.3",
57
- "nodemailer": "^7.0.12"
58
- },
59
- "devDependencies": {
60
- "@types/nodemailer": "^7.0.5"
61
- }
62
62
  }
63
63
  ]
64
64
  }