stackkit 0.2.3 → 0.2.7

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 (99) hide show
  1. package/dist/cli/add.js +2 -16
  2. package/dist/cli/create.js +2 -5
  3. package/dist/cli/doctor.js +0 -4
  4. package/dist/cli/list.js +73 -83
  5. package/dist/index.js +25 -44
  6. package/dist/lib/constants.d.ts +110 -0
  7. package/dist/lib/constants.js +112 -0
  8. package/dist/lib/conversion/js-conversion.js +27 -11
  9. package/dist/lib/discovery/installed-detection.js +3 -3
  10. package/dist/lib/discovery/module-discovery.d.ts +1 -1
  11. package/dist/lib/discovery/module-discovery.js +22 -6
  12. package/dist/lib/env/env-editor.js +41 -47
  13. package/dist/lib/fs/files.d.ts +0 -1
  14. package/dist/lib/fs/files.js +12 -40
  15. package/dist/lib/generation/code-generator.d.ts +4 -1
  16. package/dist/lib/generation/code-generator.js +39 -13
  17. package/dist/lib/pm/package-manager.d.ts +1 -1
  18. package/dist/lib/pm/package-manager.js +130 -14
  19. package/dist/lib/ui/logger.d.ts +8 -1
  20. package/dist/lib/ui/logger.js +60 -3
  21. package/dist/lib/utils/fs-helpers.d.ts +12 -0
  22. package/dist/lib/utils/fs-helpers.js +61 -0
  23. package/dist/lib/utils/json-loader.d.ts +6 -0
  24. package/dist/lib/utils/json-loader.js +34 -0
  25. package/dist/lib/utils/module-loader.d.ts +9 -0
  26. package/dist/lib/utils/module-loader.js +98 -0
  27. package/dist/lib/utils/package-root.d.ts +1 -0
  28. package/dist/lib/utils/package-root.js +75 -2
  29. package/dist/lib/utils/path-resolver.d.ts +9 -0
  30. package/dist/lib/utils/path-resolver.js +44 -0
  31. package/modules/auth/authjs/files/nextjs/api/auth/[...nextauth]/route.ts +3 -0
  32. package/modules/auth/authjs/files/nextjs/proxy.ts +1 -0
  33. package/modules/auth/authjs/files/shared/lib/auth.ts +119 -0
  34. package/modules/auth/authjs/files/{prisma → shared/prisma}/schema.prisma +11 -1
  35. package/modules/auth/authjs/generator.json +18 -8
  36. package/modules/auth/better-auth/files/express/middlewares/authorize.ts +54 -0
  37. package/modules/auth/better-auth/files/express/types/express.d.ts +16 -0
  38. package/modules/auth/better-auth/files/nextjs/lib/auth/auth-guards.ts +31 -0
  39. package/modules/auth/better-auth/files/nextjs/proxy.ts +34 -0
  40. package/modules/auth/better-auth/files/{lib → shared/lib}/auth-client.ts +1 -1
  41. package/modules/auth/better-auth/files/{lib → shared/lib}/auth.ts +46 -20
  42. package/modules/auth/better-auth/files/{prisma → shared/prisma}/schema.prisma +11 -2
  43. package/modules/auth/better-auth/generator.json +74 -19
  44. package/modules/database/mongoose/generator.json +16 -2
  45. package/modules/database/prisma/files/lib/prisma.ts +1 -1
  46. package/modules/database/prisma/files/prisma/schema.prisma +1 -2
  47. package/modules/database/prisma/generator.json +8 -1
  48. package/package.json +7 -7
  49. package/templates/express/env.example +2 -1
  50. package/templates/express/package.json +3 -4
  51. package/templates/express/src/app.ts +18 -25
  52. package/templates/express/src/config/cors.ts +12 -0
  53. package/templates/express/src/config/helmet.ts +5 -0
  54. package/templates/express/src/config/logger.ts +6 -0
  55. package/templates/express/src/config/rate-limit.ts +11 -0
  56. package/templates/express/src/{features → modules}/health/health.route.ts +1 -1
  57. package/templates/express/src/routes/index.ts +12 -0
  58. package/templates/express/src/shared/errors/api-error.ts +14 -0
  59. package/templates/express/src/shared/errors/error-codes.ts +9 -0
  60. package/templates/express/src/shared/logger/logger.ts +20 -0
  61. package/templates/express/src/{middlewares → shared/middlewares}/error.middleware.ts +1 -1
  62. package/templates/express/src/shared/middlewares/not-found.middleware.ts +9 -0
  63. package/templates/express/src/shared/utils/async-handler.ts +9 -0
  64. package/templates/express/src/shared/utils/pagination.ts +6 -0
  65. package/templates/express/src/shared/utils/response.ts +9 -0
  66. package/templates/express/tsconfig.json +9 -3
  67. package/templates/nextjs/next-env.d.ts +6 -0
  68. package/templates/react/dist/assets/index-D4AHT4dU.js +193 -0
  69. package/templates/react/dist/assets/index-rpwj5ZOX.css +1 -0
  70. package/templates/react/dist/index.html +14 -0
  71. package/templates/react/dist/vite.svg +1 -0
  72. package/templates/react/src/app/layouts/dashboard-layout.tsx +8 -0
  73. package/templates/react/src/app/layouts/public-layout.tsx +5 -0
  74. package/templates/react/src/app/providers.tsx +20 -0
  75. package/templates/react/src/app/router.tsx +21 -0
  76. package/templates/react/src/{pages/About.tsx → features/about/pages/about.tsx} +1 -1
  77. package/templates/react/src/{pages/Home.tsx → features/home/pages/home.tsx} +1 -1
  78. package/templates/react/src/main.tsx +2 -2
  79. package/templates/react/src/{api/client.ts → shared/api/http.ts} +1 -1
  80. package/templates/react/src/{pages/NotFound.tsx → shared/pages/not-found.tsx} +1 -1
  81. package/dist/lib/git-utils.d.ts +0 -1
  82. package/dist/lib/git-utils.js +0 -29
  83. package/modules/auth/authjs/files/api/auth/[...nextauth]/route.ts +0 -2
  84. package/modules/auth/authjs/files/lib/auth.ts +0 -22
  85. package/templates/express/.env.example +0 -2
  86. package/templates/nextjs/.env.example +0 -1
  87. package/templates/react/.env.example +0 -1
  88. package/templates/react/.prettierignore +0 -4
  89. package/templates/react/.prettierrc +0 -9
  90. /package/modules/auth/better-auth/files/{api → nextjs/api}/auth/[...all]/route.ts +0 -0
  91. /package/modules/auth/better-auth/files/{lib → shared/lib/email}/email-service.ts +0 -0
  92. /package/modules/auth/better-auth/files/{lib → shared/lib/email}/email-templates.ts +0 -0
  93. /package/templates/express/src/{features → modules}/health/health.controller.ts +0 -0
  94. /package/templates/express/src/{features → modules}/health/health.service.ts +0 -0
  95. /package/templates/react/src/{components/ErrorBoundary.tsx → shared/components/error-boundary.tsx} +0 -0
  96. /package/templates/react/src/{components/Layout.tsx → shared/components/layout.tsx} +0 -0
  97. /package/templates/react/src/{components/Loading.tsx → shared/components/loading.tsx} +0 -0
  98. /package/templates/react/src/{components/SEO.tsx → shared/components/seo.tsx} +0 -0
  99. /package/templates/react/src/{lib/queryClient.ts → shared/lib/query-client.ts} +0 -0
package/dist/cli/add.js CHANGED
@@ -31,10 +31,7 @@ async function addCommand(module, options) {
31
31
  await addModuleToProject(projectRoot, refreshedProjectInfo, config, options);
32
32
  logger_1.logger.newLine();
33
33
  if (config.preAdded && config.preAdded.length > 0) {
34
- const addedNames = [
35
- ...config.preAdded.map((p) => p.displayName),
36
- config.displayName,
37
- ].map((s) => chalk_1.default.bold(s));
34
+ const addedNames = [...config.preAdded.map((p) => p.displayName), config.displayName].map((s) => chalk_1.default.bold(s));
38
35
  logger_1.logger.success(`Added ${addedNames.join(" and ")}`);
39
36
  }
40
37
  else {
@@ -121,7 +118,7 @@ async function getInteractiveConfig(modulesDir, projectInfo, options) {
121
118
  const discovered = await (0, module_discovery_1.discoverModules)(modulesDir);
122
119
  // Prefer discovered framework, then projectInfo.framework; leave empty if unknown
123
120
  const defaultFramework = (discovered.frameworks && discovered.frameworks[0]?.name) || projectInfo?.framework || "";
124
- const compatibleAuths = (0, module_discovery_1.getCompatibleAuthOptions)(discovered.auth || [], projectInfo?.framework || defaultFramework, projectInfo?.hasPrisma ? "prisma" : "none");
121
+ const compatibleAuths = (0, module_discovery_1.getCompatibleAuthOptions)(discovered.auth || [], projectInfo?.framework || defaultFramework, projectInfo?.hasPrisma ? "prisma" : "none", discovered.frameworks);
125
122
  const categories = [
126
123
  { name: "Database", value: "database" },
127
124
  ];
@@ -171,7 +168,6 @@ async function getInteractiveConfig(modulesDir, projectInfo, options) {
171
168
  }
172
169
  else if (category === "auth") {
173
170
  let preAddedForReturn;
174
- // If no database detected, require the user to select/add a database first
175
171
  if (!projectInfo?.hasDatabase) {
176
172
  logger_1.logger.warn("No database detected in the project. Authentication requires a database.");
177
173
  const dbChoices = (0, module_discovery_1.getDatabaseChoices)(discovered.databases || [], projectInfo?.framework || defaultFramework);
@@ -188,7 +184,6 @@ async function getInteractiveConfig(modulesDir, projectInfo, options) {
188
184
  logger_1.logger.info("Cancelled — authentication requires a database");
189
185
  process.exit(0);
190
186
  }
191
- // Build a database AddConfig and add it immediately, then refresh projectInfo
192
187
  let dbConfig;
193
188
  if (selectedDb.startsWith("prisma-")) {
194
189
  const provider = selectedDb.split("-")[1];
@@ -210,13 +205,9 @@ async function getInteractiveConfig(modulesDir, projectInfo, options) {
210
205
  metadata: meta,
211
206
  };
212
207
  }
213
- // Add the database first (suppress its top-level success message)
214
208
  await addModuleToProject(projectRoot, projectInfo || (await (0, detect_1.detectProjectInfo)(projectRoot)), dbConfig, options);
215
- // Refresh project info after database install and record pre-added
216
209
  projectInfo = await (0, detect_1.detectProjectInfo)(projectRoot);
217
- // attach preAdded so caller can summarize chained additions
218
210
  dbConfig.preAdded = dbConfig.preAdded || [];
219
- // store for returning later
220
211
  preAddedForReturn = dbConfig;
221
212
  }
222
213
  const dbString = projectInfo?.hasPrisma ? "prisma" : "none";
@@ -249,7 +240,6 @@ async function getInteractiveConfig(modulesDir, projectInfo, options) {
249
240
  displayName: metadata.displayName || selectedAuth,
250
241
  metadata,
251
242
  };
252
- // If we added a DB earlier in this flow, include it for grouped messaging
253
243
  if (typeof preAddedForReturn !== "undefined" && preAddedForReturn) {
254
244
  result.preAdded = [preAddedForReturn];
255
245
  }
@@ -257,7 +247,6 @@ async function getInteractiveConfig(modulesDir, projectInfo, options) {
257
247
  }
258
248
  throw new Error("Invalid selection");
259
249
  }
260
- /* removed unused getProviderConfig — discovery-based flows handle providers */
261
250
  async function addModuleToProject(projectRoot, projectInfo, config, options) {
262
251
  const moduleMetadata = config.metadata;
263
252
  const selectedProvider = config.provider;
@@ -329,14 +318,11 @@ async function addModuleToProject(projectRoot, projectInfo, config, options) {
329
318
  }
330
319
  }
331
320
  const selectedModules = { framework: projectInfo.framework };
332
- // Populate database context from detected project state so generator conditions work
333
321
  try {
334
322
  const pkg = await fs_extra_1.default.readJson(path_1.default.join(projectRoot, "package.json"));
335
323
  const deps = { ...(pkg.dependencies || {}), ...(pkg.devDependencies || {}) };
336
324
  if (projectInfo.hasPrisma) {
337
325
  selectedModules.database = "prisma";
338
- // Parse provider specifically from the `datasource` block to avoid
339
- // capturing the generator block (which uses provider = "prisma-client-js").
340
326
  const prismaSchema = path_1.default.join(projectRoot, "prisma", "schema.prisma");
341
327
  if (await fs_extra_1.default.pathExists(prismaSchema)) {
342
328
  const content = await fs_extra_1.default.readFile(prismaSchema, "utf-8");
@@ -16,7 +16,6 @@ const shared_1 = require("../lib/discovery/shared");
16
16
  const env_editor_1 = require("../lib/env/env-editor");
17
17
  const framework_utils_1 = require("../lib/framework/framework-utils");
18
18
  const code_generator_1 = require("../lib/generation/code-generator");
19
- const git_utils_1 = require("../lib/git-utils");
20
19
  const package_manager_1 = require("../lib/pm/package-manager");
21
20
  const logger_1 = require("../lib/ui/logger");
22
21
  const package_root_1 = require("../lib/utils/package-root");
@@ -205,8 +204,6 @@ async function getProjectConfig(projectName, options) {
205
204
  return [{ name: "None", value: "none" }];
206
205
  },
207
206
  },
208
- // If a prisma-* choice is selected above, `prismaProvider` will be derived from it,
209
- // otherwise prompt for provider when `prisma` is selected directly.
210
207
  {
211
208
  type: "list",
212
209
  name: "prismaProvider",
@@ -222,7 +219,7 @@ async function getProjectConfig(projectName, options) {
222
219
  name: "auth",
223
220
  message: "Select authentication:",
224
221
  when: (answers) => answers.database !== "none" || answers.framework === "react",
225
- choices: (answers) => (0, module_discovery_1.getCompatibleAuthOptions)(discoveredModules.auth, answers.framework, answers.database || "none"),
222
+ choices: (answers) => (0, module_discovery_1.getCompatibleAuthOptions)(discoveredModules.auth, answers.framework, answers.database || "none", discoveredModules.frameworks),
226
223
  },
227
224
  {
228
225
  type: "list",
@@ -306,7 +303,7 @@ async function generateProject(config, targetDir, options) {
306
303
  if (options?.git !== false && !(options?.["no-git"] || options?.noGit)) {
307
304
  const gitSpinner = logger_1.logger.startSpinner("Initializing git repository...");
308
305
  try {
309
- await (0, git_utils_1.initGit)(targetDir);
306
+ await (0, package_manager_1.initGit)(targetDir);
310
307
  gitSpinner.succeed("Git repository initialized");
311
308
  }
312
309
  catch (error) {
@@ -296,9 +296,6 @@ async function checkAuthRoutesExist(projectRoot) {
296
296
  catch {
297
297
  // ignore discovery errors
298
298
  }
299
- // Fallback to known common paths if generators don't provide any
300
- // If generators provided candidate routes, check them. Otherwise
301
- // do not assume any hard-coded route locations.
302
299
  if (candidates.size === 0)
303
300
  return false;
304
301
  for (const routePath of candidates) {
@@ -442,7 +439,6 @@ async function checkDependencies(packageJson) {
442
439
  // Assume up to date if using flexible versioning
443
440
  }
444
441
  else {
445
- // Assume outdated if using exact versions (simplified check)
446
442
  outdated.push(name);
447
443
  }
448
444
  }
package/dist/cli/list.js CHANGED
@@ -9,6 +9,7 @@ const fs_extra_1 = __importDefault(require("fs-extra"));
9
9
  const path_1 = __importDefault(require("path"));
10
10
  const shared_1 = require("../lib/discovery/shared");
11
11
  const logger_1 = require("../lib/ui/logger");
12
+ const module_loader_1 = require("../lib/utils/module-loader");
12
13
  const package_root_1 = require("../lib/utils/package-root");
13
14
  async function listCommand(options) {
14
15
  const showFrameworks = !options.modules || options.frameworks;
@@ -16,72 +17,22 @@ async function listCommand(options) {
16
17
  try {
17
18
  logger_1.logger.header("StackKit Resources");
18
19
  logger_1.logger.newLine();
19
- let hasFrameworks = false;
20
- let hasModules = false;
20
+ let hasContent = false;
21
21
  if (showFrameworks) {
22
- const templatesDir = path_1.default.join((0, package_root_1.getPackageRoot)(), "templates");
23
- const frameworks = await getAvailableFrameworks(templatesDir);
22
+ const frameworks = await getAvailableFrameworks();
24
23
  if (frameworks.length > 0) {
25
- hasFrameworks = true;
26
- logger_1.logger.log(chalk_1.default.bold.blue("FRAMEWORKS"));
27
- frameworks.forEach((framework, index) => {
28
- const isLast = index === frameworks.length - 1;
29
- const prefix = isLast ? "└──" : "├──";
30
- logger_1.logger.log(` ${chalk_1.default.gray(prefix)} ${chalk_1.default.cyan(framework.displayName || framework.name)}`);
31
- });
32
- logger_1.logger.newLine();
24
+ hasContent = true;
25
+ printFrameworks(frameworks);
33
26
  }
34
27
  }
35
28
  if (showModules) {
36
- const modulesDir = path_1.default.join((0, package_root_1.getPackageRoot)(), "modules");
37
- const modules = await getAvailableModules(modulesDir);
29
+ const modules = await getAvailableModules();
38
30
  if (modules.length > 0) {
39
- hasModules = true;
40
- logger_1.logger.log(chalk_1.default.bold.magenta("MODULES"));
41
- const grouped = modules.reduce((acc, mod) => {
42
- const cat = mod.category || "other";
43
- if (!acc[cat])
44
- acc[cat] = [];
45
- acc[cat].push(mod);
46
- return acc;
47
- }, {});
48
- const categories = Object.keys(grouped);
49
- categories.forEach((category, categoryIndex) => {
50
- const mods = grouped[category];
51
- const isLastCategory = categoryIndex === categories.length - 1;
52
- const categoryPrefix = isLastCategory ? "└──" : "├──";
53
- logger_1.logger.log(` ${chalk_1.default.gray(categoryPrefix)} ${chalk_1.default.yellow(formatCategoryName(category))} ${chalk_1.default.dim(`(${mods.length})`)}`);
54
- mods.forEach((mod, modIndex) => {
55
- const isLastMod = modIndex === mods.length - 1;
56
- const modPrefix = isLastCategory
57
- ? isLastMod
58
- ? " └──"
59
- : " ├──"
60
- : isLastMod
61
- ? "│ └──"
62
- : "│ ├──";
63
- logger_1.logger.log(` ${chalk_1.default.gray(modPrefix)} ${chalk_1.default.green(mod.displayName)}`);
64
- if (mod.category === "database" && mod.name === "prisma") {
65
- const providerPrefix = isLastCategory
66
- ? isLastMod
67
- ? " └──"
68
- : " ├──"
69
- : isLastMod
70
- ? "│ └──"
71
- : "│ ├──";
72
- // Derive provider list directly from the Prisma generator metadata
73
- const providers = (0, shared_1.getPrismaProvidersFromGenerator)((0, package_root_1.getPackageRoot)());
74
- const providersText = providers.length
75
- ? providers.map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join(", ")
76
- : "None";
77
- logger_1.logger.log(` ${chalk_1.default.gray(providerPrefix)} ${chalk_1.default.dim(`Providers: ${providersText}`)}`);
78
- }
79
- });
80
- });
81
- logger_1.logger.newLine();
31
+ hasContent = true;
32
+ printModules(modules);
82
33
  }
83
34
  }
84
- if (!hasFrameworks && !hasModules) {
35
+ if (!hasContent) {
85
36
  logger_1.logger.log(chalk_1.default.dim("No resources available"));
86
37
  logger_1.logger.newLine();
87
38
  }
@@ -93,18 +44,79 @@ async function listCommand(options) {
93
44
  process.exit(1);
94
45
  }
95
46
  }
96
- async function getAvailableFrameworks(templatesDir) {
47
+ function printFrameworks(frameworks) {
48
+ logger_1.logger.log(chalk_1.default.bold.blue("FRAMEWORKS"));
49
+ frameworks.forEach((framework, index) => {
50
+ const isLast = index === frameworks.length - 1;
51
+ const prefix = isLast ? "└──" : "├──";
52
+ logger_1.logger.log(` ${chalk_1.default.gray(prefix)} ${chalk_1.default.cyan(framework.displayName)}`);
53
+ });
54
+ logger_1.logger.newLine();
55
+ }
56
+ function printModules(modules) {
57
+ logger_1.logger.log(chalk_1.default.bold.magenta("MODULES"));
58
+ const grouped = groupModulesByCategory(modules);
59
+ const categories = Object.keys(grouped);
60
+ categories.forEach((category, categoryIndex) => {
61
+ const mods = grouped[category];
62
+ const isLastCategory = categoryIndex === categories.length - 1;
63
+ const categoryPrefix = isLastCategory ? "└──" : "├──";
64
+ logger_1.logger.log(` ${chalk_1.default.gray(categoryPrefix)} ${chalk_1.default.yellow(formatCategoryName(category))} ${chalk_1.default.dim(`(${mods.length})`)}`);
65
+ mods.forEach((mod, modIndex) => {
66
+ const isLastMod = modIndex === mods.length - 1;
67
+ const modPrefix = getModulePrefix(isLastCategory, isLastMod);
68
+ logger_1.logger.log(` ${chalk_1.default.gray(modPrefix)} ${chalk_1.default.green(mod.displayName)}`);
69
+ if (mod.category === "database" && mod.name === "prisma") {
70
+ printPrismaProviders(isLastCategory, isLastMod);
71
+ }
72
+ });
73
+ });
74
+ logger_1.logger.newLine();
75
+ }
76
+ function printPrismaProviders(isLastCategory, isLastMod) {
77
+ const providerPrefix = getProviderPrefix(isLastCategory, isLastMod);
78
+ const providers = (0, shared_1.getPrismaProvidersFromGenerator)((0, package_root_1.getPackageRoot)());
79
+ const providersText = providers.length
80
+ ? providers.map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join(", ")
81
+ : "None";
82
+ logger_1.logger.log(` ${chalk_1.default.gray(providerPrefix)} ${chalk_1.default.dim(`Providers: ${providersText}`)}`);
83
+ }
84
+ function getModulePrefix(isLastCategory, isLastMod) {
85
+ if (isLastCategory) {
86
+ return isLastMod ? " └──" : " ├──";
87
+ }
88
+ return isLastMod ? "│ └──" : "│ ├──";
89
+ }
90
+ function getProviderPrefix(isLastCategory, isLastMod) {
91
+ if (isLastCategory) {
92
+ return isLastMod ? " └──" : " ├──";
93
+ }
94
+ return isLastMod ? "│ └──" : "│ ├──";
95
+ }
96
+ function groupModulesByCategory(modules) {
97
+ return modules.reduce((acc, mod) => {
98
+ const cat = mod.category || "other";
99
+ if (!acc[cat])
100
+ acc[cat] = [];
101
+ acc[cat].push(mod);
102
+ return acc;
103
+ }, {});
104
+ }
105
+ async function getAvailableFrameworks() {
106
+ const templatesDir = path_1.default.join((0, package_root_1.getPackageRoot)(), "templates");
97
107
  if (!(await fs_extra_1.default.pathExists(templatesDir))) {
98
108
  return [];
99
109
  }
100
110
  const frameworkDirs = await fs_extra_1.default.readdir(templatesDir);
101
- const frameworks = frameworkDirs
111
+ return frameworkDirs
102
112
  .filter((dir) => dir !== "node_modules" && dir !== ".git")
103
113
  .map((dir) => ({
104
114
  name: dir,
105
115
  displayName: formatFrameworkName(dir),
106
116
  }));
107
- return frameworks;
117
+ }
118
+ async function getAvailableModules() {
119
+ return (0, module_loader_1.getAllModules)();
108
120
  }
109
121
  function formatFrameworkName(name) {
110
122
  return name
@@ -115,25 +127,3 @@ function formatFrameworkName(name) {
115
127
  function formatCategoryName(name) {
116
128
  return name.charAt(0).toUpperCase() + name.slice(1);
117
129
  }
118
- async function getAvailableModules(modulesDir) {
119
- if (!(await fs_extra_1.default.pathExists(modulesDir))) {
120
- return [];
121
- }
122
- const modules = [];
123
- const categories = await fs_extra_1.default.readdir(modulesDir);
124
- for (const category of categories) {
125
- const categoryPath = path_1.default.join(modulesDir, category);
126
- const stat = await fs_extra_1.default.stat(categoryPath);
127
- if (!stat.isDirectory())
128
- continue;
129
- const moduleDirs = await fs_extra_1.default.readdir(categoryPath);
130
- for (const moduleDir of moduleDirs) {
131
- const metadataPath = path_1.default.join(categoryPath, moduleDir, "module.json");
132
- if (await fs_extra_1.default.pathExists(metadataPath)) {
133
- const metadata = await fs_extra_1.default.readJSON(metadataPath);
134
- modules.push(metadata);
135
- }
136
- }
137
- }
138
- return modules;
139
- }
package/dist/index.js CHANGED
@@ -36,65 +36,51 @@ var __importStar = (this && this.__importStar) || (function () {
36
36
  Object.defineProperty(exports, "__esModule", { value: true });
37
37
  const commander_1 = require("commander");
38
38
  const fs = __importStar(require("fs"));
39
- const fs_1 = require("fs");
40
39
  const path_1 = require("path");
41
40
  const add_1 = require("./cli/add");
42
41
  const create_1 = require("./cli/create");
43
42
  const doctor_1 = require("./cli/doctor");
44
43
  const list_1 = require("./cli/list");
44
+ const constants_1 = require("./lib/constants");
45
45
  const shared_1 = require("./lib/discovery/shared");
46
46
  const logger_1 = require("./lib/ui/logger");
47
+ const json_loader_1 = require("./lib/utils/json-loader");
47
48
  const package_root_1 = require("./lib/utils/package-root");
48
- const packageJson = JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(__dirname, "../package.json"), "utf-8"));
49
+ const path_resolver_1 = require("./lib/utils/path-resolver");
50
+ const packageJson = (0, json_loader_1.loadJsonSync)((0, path_1.join)(__dirname, "../package.json"));
49
51
  function buildOptionHints() {
50
52
  try {
51
- const pkgRoot = (0, package_root_1.getPackageRoot)();
52
- const modulesDir = (0, path_1.join)(pkgRoot, "modules");
53
+ const databaseModulesPath = (0, path_resolver_1.getDatabaseModulesPath)();
54
+ const authModulesPath = (0, path_resolver_1.getAuthModulesPath)();
53
55
  const dbs = [];
54
56
  const auths = [];
55
- if (fs.existsSync((0, path_1.join)(modulesDir, "database"))) {
56
- for (const d of fs.readdirSync((0, path_1.join)(modulesDir, "database"))) {
57
- const moduleJson = (0, path_1.join)(modulesDir, "database", d, "module.json");
57
+ if (fs.existsSync(databaseModulesPath)) {
58
+ for (const d of fs.readdirSync(databaseModulesPath)) {
59
+ const moduleJson = (0, path_resolver_1.getModuleJsonPath)(constants_1.MODULE_CATEGORIES.DATABASE, d);
58
60
  if (fs.existsSync(moduleJson)) {
59
- try {
60
- const m = JSON.parse((0, fs_1.readFileSync)(moduleJson, "utf-8"));
61
- if (m && m.name === "prisma") {
62
- try {
63
- const providers = (0, shared_1.getPrismaProvidersFromGenerator)((0, package_root_1.getPackageRoot)());
64
- if (providers.length > 0) {
65
- for (const p of providers)
66
- dbs.push(`prisma-${p}`);
67
- }
68
- else {
69
- dbs.push("prisma");
70
- }
71
- }
72
- catch {
73
- dbs.push("prisma");
74
- }
61
+ const m = (0, json_loader_1.loadJsonSync)(moduleJson);
62
+ if (m && m.name === "prisma") {
63
+ const providers = (0, shared_1.getPrismaProvidersFromGenerator)((0, package_root_1.getPackageRoot)());
64
+ if (providers.length > 0) {
65
+ providers.forEach((p) => dbs.push(`prisma-${p}`));
75
66
  }
76
- else if (m && m.name) {
77
- dbs.push(m.name);
67
+ else {
68
+ dbs.push("prisma");
78
69
  }
79
70
  }
80
- catch {
81
- /* ignore */
71
+ else if (m && m.name) {
72
+ dbs.push(m.name);
82
73
  }
83
74
  }
84
75
  }
85
76
  }
86
- if (fs.existsSync((0, path_1.join)(modulesDir, "auth"))) {
87
- for (const a of fs.readdirSync((0, path_1.join)(modulesDir, "auth"))) {
88
- const moduleJson = (0, path_1.join)(modulesDir, "auth", a, "module.json");
77
+ if (fs.existsSync(authModulesPath)) {
78
+ for (const a of fs.readdirSync(authModulesPath)) {
79
+ const moduleJson = (0, path_resolver_1.getModuleJsonPath)(constants_1.MODULE_CATEGORIES.AUTH, a);
89
80
  if (fs.existsSync(moduleJson)) {
90
- try {
91
- const m = JSON.parse((0, fs_1.readFileSync)(moduleJson, "utf-8"));
92
- if (m && m.name)
93
- auths.push(m.name);
94
- }
95
- catch {
96
- /* ignore */
97
- }
81
+ const m = (0, json_loader_1.loadJsonSync)(moduleJson);
82
+ if (m && m.name)
83
+ auths.push(m.name);
98
84
  }
99
85
  }
100
86
  }
@@ -112,7 +98,7 @@ const program = new commander_1.Command();
112
98
  program
113
99
  .name("stackkit")
114
100
  .description("CLI for creating and managing StackKit projects")
115
- .version(packageJson.version)
101
+ .version(packageJson?.version || "0.0.0")
116
102
  .configureHelp({
117
103
  subcommandTerm: (cmd) => {
118
104
  const name = cmd.name();
@@ -129,7 +115,6 @@ program
129
115
  return name + " [options]";
130
116
  },
131
117
  });
132
- // Create command
133
118
  program
134
119
  .command("create [project-name]")
135
120
  .description("Create a new StackKit project")
@@ -152,7 +137,6 @@ program
152
137
  process.exit(1);
153
138
  }
154
139
  });
155
- // Add command
156
140
  program
157
141
  .command("add [module]")
158
142
  .description("Add a module or category to your existing project")
@@ -171,7 +155,6 @@ program
171
155
  process.exit(1);
172
156
  }
173
157
  });
174
- // Doctor command
175
158
  program
176
159
  .command("doctor")
177
160
  .description("Check project health and compatibility with StackKit modules")
@@ -187,7 +170,6 @@ program
187
170
  process.exit(1);
188
171
  }
189
172
  });
190
- // List command
191
173
  program
192
174
  .command("list")
193
175
  .description("List available frameworks and modules")
@@ -202,7 +184,6 @@ program
202
184
  process.exit(1);
203
185
  }
204
186
  });
205
- // Error handling
206
187
  program.on("command:*", () => {
207
188
  logger_1.logger.error(`Invalid command: ${program.args.join(" ")}`);
208
189
  logger_1.logger.log("Run stackkit --help for a list of available commands.");
@@ -0,0 +1,110 @@
1
+ export declare const PACKAGE_MANAGERS: {
2
+ PNPM: "pnpm";
3
+ NPM: "npm";
4
+ YARN: "yarn";
5
+ BUN: "bun";
6
+ };
7
+ export declare const LOCK_FILES: {
8
+ readonly pnpm: "pnpm-lock.yaml";
9
+ readonly yarn: "yarn.lock";
10
+ readonly bun: "bun.lockb";
11
+ readonly npm: "package-lock.json";
12
+ };
13
+ export declare const LOCK_FILES_ARRAY: readonly [{
14
+ readonly file: "pnpm-lock.yaml";
15
+ readonly pm: "pnpm";
16
+ }, {
17
+ readonly file: "yarn.lock";
18
+ readonly pm: "yarn";
19
+ }, {
20
+ readonly file: "bun.lockb";
21
+ readonly pm: "bun";
22
+ }, {
23
+ readonly file: "package-lock.json";
24
+ readonly pm: "npm";
25
+ }];
26
+ export declare const LANGUAGES: {
27
+ TYPESCRIPT: "typescript";
28
+ JAVASCRIPT: "javascript";
29
+ };
30
+ export declare const MODULE_CATEGORIES: {
31
+ DATABASE: "database";
32
+ AUTH: "auth";
33
+ FRAMEWORK: "framework";
34
+ };
35
+ export declare const DIRECTORY_NAMES: {
36
+ readonly MODULES: "modules";
37
+ readonly TEMPLATES: "templates";
38
+ readonly NODE_MODULES: "node_modules";
39
+ readonly GIT: ".git";
40
+ readonly PRISMA: "prisma";
41
+ readonly FILES: "files";
42
+ readonly SRC: "src";
43
+ readonly DIST: "dist";
44
+ readonly BIN: "bin";
45
+ };
46
+ export declare const FILE_NAMES: {
47
+ readonly PACKAGE_JSON: "package.json";
48
+ readonly TSCONFIG_JSON: "tsconfig.json";
49
+ readonly MODULE_JSON: "module.json";
50
+ readonly GENERATOR_JSON: "generator.json";
51
+ readonly TEMPLATE_JSON: "template.json";
52
+ readonly CONFIG_JSON: "config.json";
53
+ readonly ENV: ".env";
54
+ readonly ENV_LOCAL: ".env.local";
55
+ readonly ENV_EXAMPLE: ".env.example";
56
+ readonly GITIGNORE: ".gitignore";
57
+ readonly README: "README.md";
58
+ readonly SCHEMA_PRISMA: "schema.prisma";
59
+ };
60
+ export declare const ENV_FILES: readonly [".env", ".env.local"];
61
+ export declare const EXCLUDE_FROM_COPY: readonly ["template.json", "config.json", "node_modules", ".git"];
62
+ export declare const TIMEOUTS: {
63
+ readonly PACKAGE_INSTALL: 300000;
64
+ readonly GIT_INIT: 30000;
65
+ readonly RETRY_DELAY_BASE: 1000;
66
+ };
67
+ export declare const RETRY_CONFIG: {
68
+ readonly MAX_ATTEMPTS: 2;
69
+ readonly PACKAGE_ROOT_MAX_ATTEMPTS: 10;
70
+ };
71
+ export declare const ENV_PATTERNS: {
72
+ readonly KEY: RegExp;
73
+ readonly COMMENT: RegExp;
74
+ };
75
+ export declare const ROUTER_TYPES: {
76
+ readonly APP: "app";
77
+ readonly PAGES: "pages";
78
+ };
79
+ export declare const DISPLAY_NAMES: {
80
+ readonly database: "Database";
81
+ readonly auth: "Auth";
82
+ readonly framework: "Framework";
83
+ };
84
+ export declare const ERROR_MESSAGES: {
85
+ readonly NO_PACKAGE_JSON: "No package.json found in current directory or any parent directory.";
86
+ readonly INVALID_DIRECTORY: "Target directory already exists and is not empty.";
87
+ readonly INVALID_PROJECT_NAME: "Invalid project name. Please use a valid npm package name.";
88
+ readonly UNKNOWN_MODULE_TYPE: (module: string) => string;
89
+ readonly MODULE_NOT_FOUND: (moduleName: string) => string;
90
+ readonly TEMPLATE_NOT_FOUND: (framework: string) => string;
91
+ readonly GIT_INIT_FAILED: "Failed to initialize git repository";
92
+ readonly PACKAGE_INSTALL_FAILED: "Failed to install dependencies";
93
+ };
94
+ export declare const SUCCESS_MESSAGES: {
95
+ readonly PROJECT_CREATED: "✨ Project created successfully!";
96
+ readonly MODULE_ADDED: "✨ Module added successfully!";
97
+ readonly DEPENDENCIES_INSTALLED: "✓ Dependencies installed";
98
+ readonly GIT_INITIALIZED: "✓ Git repository initialized";
99
+ };
100
+ export declare const CLI_COLORS: {
101
+ readonly PRIMARY: "cyan";
102
+ readonly SUCCESS: "green";
103
+ readonly WARNING: "yellow";
104
+ readonly ERROR: "red";
105
+ readonly INFO: "blue";
106
+ readonly HEADER: "magenta";
107
+ };
108
+ export declare const PACKAGE_NAME: "stackkit";
109
+ export declare const DEFAULT_PACKAGE_MANAGER: "npm";
110
+ export declare const DEFAULT_LANGUAGE: "typescript";