stackkit 0.1.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 (121) hide show
  1. package/README.md +41 -0
  2. package/bin/stackkit.js +4 -0
  3. package/dist/cli/add.d.ts +8 -0
  4. package/dist/cli/add.js +313 -0
  5. package/dist/cli/create.d.ts +22 -0
  6. package/dist/cli/create.js +336 -0
  7. package/dist/cli/doctor.d.ts +7 -0
  8. package/dist/cli/doctor.js +569 -0
  9. package/dist/cli/list.d.ts +6 -0
  10. package/dist/cli/list.js +123 -0
  11. package/dist/index.d.ts +2 -0
  12. package/dist/index.js +91 -0
  13. package/dist/lib/conversion/js-conversion.d.ts +1 -0
  14. package/dist/lib/conversion/js-conversion.js +244 -0
  15. package/dist/lib/database/database-config.d.ts +6 -0
  16. package/dist/lib/database/database-config.js +9 -0
  17. package/dist/lib/discovery/module-discovery.d.ts +62 -0
  18. package/dist/lib/discovery/module-discovery.js +188 -0
  19. package/dist/lib/env/env-editor.d.ts +9 -0
  20. package/dist/lib/env/env-editor.js +116 -0
  21. package/dist/lib/framework/framework-utils.d.ts +22 -0
  22. package/dist/lib/framework/framework-utils.js +74 -0
  23. package/dist/lib/fs/files.d.ts +14 -0
  24. package/dist/lib/fs/files.js +101 -0
  25. package/dist/lib/generation/code-generator.d.ts +83 -0
  26. package/dist/lib/generation/code-generator.js +681 -0
  27. package/dist/lib/git-utils.d.ts +1 -0
  28. package/dist/lib/git-utils.js +9 -0
  29. package/dist/lib/pm/package-manager.d.ts +5 -0
  30. package/dist/lib/pm/package-manager.js +69 -0
  31. package/dist/lib/project/detect.d.ts +4 -0
  32. package/dist/lib/project/detect.js +121 -0
  33. package/dist/lib/ui/logger.d.ts +16 -0
  34. package/dist/lib/ui/logger.js +59 -0
  35. package/dist/types/index.d.ts +92 -0
  36. package/dist/types/index.js +2 -0
  37. package/modules/auth/authjs/files/api/auth/[...nextauth]/route.ts +6 -0
  38. package/modules/auth/authjs/files/lib/auth-client.ts +11 -0
  39. package/modules/auth/authjs/files/lib/auth.ts +36 -0
  40. package/modules/auth/authjs/files/schemas/prisma-schema.prisma +45 -0
  41. package/modules/auth/authjs/module.json +22 -0
  42. package/modules/auth/better-auth/files/api/auth/[...all]/route.ts +4 -0
  43. package/modules/auth/better-auth/files/lib/auth-client.ts +7 -0
  44. package/modules/auth/better-auth/files/lib/auth.ts +83 -0
  45. package/modules/auth/better-auth/files/lib/email-service.ts +34 -0
  46. package/modules/auth/better-auth/files/lib/email-templates.ts +89 -0
  47. package/modules/auth/better-auth/files/prisma/schema.prisma +63 -0
  48. package/modules/auth/better-auth/generator.json +78 -0
  49. package/modules/auth/better-auth/module.json +37 -0
  50. package/modules/database/mongoose/files/lib/db.ts +63 -0
  51. package/modules/database/mongoose/files/models/User.ts +34 -0
  52. package/modules/database/mongoose/generator.json +24 -0
  53. package/modules/database/mongoose/module.json +15 -0
  54. package/modules/database/prisma/files/lib/prisma.ts +45 -0
  55. package/modules/database/prisma/files/prisma/schema.prisma +8 -0
  56. package/modules/database/prisma/files/prisma.config.ts +12 -0
  57. package/modules/database/prisma/generator.json +43 -0
  58. package/modules/database/prisma/module.json +17 -0
  59. package/package.json +83 -0
  60. package/templates/express/.env.example +2 -0
  61. package/templates/express/eslint.config.cjs +42 -0
  62. package/templates/express/package.json +33 -0
  63. package/templates/express/src/app.ts +51 -0
  64. package/templates/express/src/config/env.ts +12 -0
  65. package/templates/express/src/features/health/health.controller.ts +18 -0
  66. package/templates/express/src/features/health/health.route.ts +9 -0
  67. package/templates/express/src/features/health/health.service.ts +6 -0
  68. package/templates/express/src/middlewares/error.middleware.ts +18 -0
  69. package/templates/express/src/server.ts +8 -0
  70. package/templates/express/template.json +27 -0
  71. package/templates/express/tsconfig.json +30 -0
  72. package/templates/nextjs/README.md +52 -0
  73. package/templates/nextjs/app/favicon.ico +0 -0
  74. package/templates/nextjs/app/globals.css +26 -0
  75. package/templates/nextjs/app/layout.tsx +30 -0
  76. package/templates/nextjs/app/page.tsx +57 -0
  77. package/templates/nextjs/eslint.config.mjs +18 -0
  78. package/templates/nextjs/lib/env.ts +8 -0
  79. package/templates/nextjs/next.config.ts +7 -0
  80. package/templates/nextjs/package.json +27 -0
  81. package/templates/nextjs/postcss.config.mjs +7 -0
  82. package/templates/nextjs/public/file.svg +1 -0
  83. package/templates/nextjs/public/globe.svg +1 -0
  84. package/templates/nextjs/public/next.svg +1 -0
  85. package/templates/nextjs/public/vercel.svg +1 -0
  86. package/templates/nextjs/public/window.svg +1 -0
  87. package/templates/nextjs/template.json +34 -0
  88. package/templates/nextjs/tsconfig.json +34 -0
  89. package/templates/react/.env.example +1 -0
  90. package/templates/react/.prettierignore +4 -0
  91. package/templates/react/.prettierrc +9 -0
  92. package/templates/react/README.md +56 -0
  93. package/templates/react/eslint.config.js +23 -0
  94. package/templates/react/index.html +14 -0
  95. package/templates/react/package.json +44 -0
  96. package/templates/react/public/vite.svg +1 -0
  97. package/templates/react/src/api/client.ts +47 -0
  98. package/templates/react/src/assets/react.svg +1 -0
  99. package/templates/react/src/components/ErrorBoundary.tsx +51 -0
  100. package/templates/react/src/components/Layout.tsx +13 -0
  101. package/templates/react/src/components/Loading.tsx +8 -0
  102. package/templates/react/src/components/SEO.tsx +49 -0
  103. package/templates/react/src/config/constants.ts +5 -0
  104. package/templates/react/src/hooks/index.ts +64 -0
  105. package/templates/react/src/index.css +1 -0
  106. package/templates/react/src/lib/queryClient.ts +12 -0
  107. package/templates/react/src/main.tsx +22 -0
  108. package/templates/react/src/pages/About.tsx +78 -0
  109. package/templates/react/src/pages/Home.tsx +49 -0
  110. package/templates/react/src/pages/NotFound.tsx +24 -0
  111. package/templates/react/src/router.tsx +21 -0
  112. package/templates/react/src/types/api.d.ts +20 -0
  113. package/templates/react/src/utils/helpers.ts +51 -0
  114. package/templates/react/src/utils/storage.ts +35 -0
  115. package/templates/react/src/vite-env.d.ts +11 -0
  116. package/templates/react/template.json +38 -0
  117. package/templates/react/tsconfig.app.json +28 -0
  118. package/templates/react/tsconfig.json +4 -0
  119. package/templates/react/tsconfig.node.json +26 -0
  120. package/templates/react/vite.config.ts +7 -0
  121. package/templates/react-vite/README.md +56 -0
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.listCommand = listCommand;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const fs_extra_1 = __importDefault(require("fs-extra"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const logger_1 = require("../lib/ui/logger");
11
+ async function listCommand(options) {
12
+ const showFrameworks = !options.modules || options.frameworks;
13
+ const showModules = !options.frameworks || options.modules;
14
+ try {
15
+ logger_1.logger.header("StackKit Resources");
16
+ logger_1.logger.newLine();
17
+ let hasFrameworks = false;
18
+ let hasModules = false;
19
+ if (showFrameworks) {
20
+ const templatesDir = path_1.default.join(__dirname, "..", "..", "..", "..", "templates");
21
+ const frameworks = await getAvailableFrameworks(templatesDir);
22
+ if (frameworks.length > 0) {
23
+ hasFrameworks = true;
24
+ logger_1.logger.log(chalk_1.default.bold.blue("FRAMEWORKS"));
25
+ frameworks.forEach((framework, index) => {
26
+ const isLast = index === frameworks.length - 1;
27
+ const prefix = isLast ? "└──" : "├──";
28
+ logger_1.logger.log(` ${chalk_1.default.gray(prefix)} ${chalk_1.default.cyan(framework.displayName)}`);
29
+ });
30
+ logger_1.logger.newLine();
31
+ }
32
+ }
33
+ // List modules
34
+ if (showModules) {
35
+ const modulesDir = path_1.default.join(__dirname, "..", "..", "..", "modules");
36
+ const modules = await getAvailableModules(modulesDir);
37
+ if (modules.length > 0) {
38
+ hasModules = true;
39
+ logger_1.logger.log(chalk_1.default.bold.magenta("MODULES"));
40
+ // Group by category
41
+ const grouped = modules.reduce((acc, mod) => {
42
+ if (!acc[mod.category]) {
43
+ acc[mod.category] = [];
44
+ }
45
+ acc[mod.category].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 ? (isLastMod ? " └──" : " ├──") : (isLastMod ? "│ └──" : "│ ├──");
57
+ logger_1.logger.log(` ${chalk_1.default.gray(modPrefix)} ${chalk_1.default.green(mod.displayName)}`);
58
+ // Show additional details for database modules
59
+ if (mod.category === "database" && mod.name === "prisma") {
60
+ const providerPrefix = isLastCategory ? (isLastMod ? " └──" : " ├──") : (isLastMod ? "│ └──" : "│ ├──");
61
+ logger_1.logger.log(` ${chalk_1.default.gray(providerPrefix)} ${chalk_1.default.dim("Providers: PostgreSQL, MongoDB, MySQL, SQLite")}`);
62
+ }
63
+ });
64
+ });
65
+ logger_1.logger.newLine();
66
+ }
67
+ }
68
+ if (!hasFrameworks && !hasModules) {
69
+ logger_1.logger.log(chalk_1.default.dim("No resources available"));
70
+ logger_1.logger.newLine();
71
+ }
72
+ logger_1.logger.log(chalk_1.default.dim("Use 'stackkit add <module>' to add modules to your project"));
73
+ logger_1.logger.newLine();
74
+ }
75
+ catch (error) {
76
+ logger_1.logger.error(`Failed to list resources: ${error.message}`);
77
+ process.exit(1);
78
+ }
79
+ }
80
+ async function getAvailableFrameworks(templatesDir) {
81
+ if (!(await fs_extra_1.default.pathExists(templatesDir))) {
82
+ return [];
83
+ }
84
+ const frameworkDirs = await fs_extra_1.default.readdir(templatesDir);
85
+ const frameworks = frameworkDirs
86
+ .filter((dir) => dir !== "node_modules" && dir !== ".git")
87
+ .map((dir) => ({
88
+ name: dir,
89
+ displayName: formatFrameworkName(dir),
90
+ }));
91
+ return frameworks;
92
+ }
93
+ function formatFrameworkName(name) {
94
+ return name
95
+ .split("-")
96
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
97
+ .join(" ");
98
+ }
99
+ function formatCategoryName(name) {
100
+ return name.charAt(0).toUpperCase() + name.slice(1);
101
+ }
102
+ async function getAvailableModules(modulesDir) {
103
+ if (!(await fs_extra_1.default.pathExists(modulesDir))) {
104
+ return [];
105
+ }
106
+ const modules = [];
107
+ const categories = await fs_extra_1.default.readdir(modulesDir);
108
+ for (const category of categories) {
109
+ const categoryPath = path_1.default.join(modulesDir, category);
110
+ const stat = await fs_extra_1.default.stat(categoryPath);
111
+ if (!stat.isDirectory())
112
+ continue;
113
+ const moduleDirs = await fs_extra_1.default.readdir(categoryPath);
114
+ for (const moduleDir of moduleDirs) {
115
+ const metadataPath = path_1.default.join(categoryPath, moduleDir, "module.json");
116
+ if (await fs_extra_1.default.pathExists(metadataPath)) {
117
+ const metadata = await fs_extra_1.default.readJSON(metadataPath);
118
+ modules.push(metadata);
119
+ }
120
+ }
121
+ }
122
+ return modules;
123
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const commander_1 = require("commander");
5
+ const create_1 = require("./cli/create");
6
+ const add_1 = require("./cli/add");
7
+ const doctor_1 = require("./cli/doctor");
8
+ const list_1 = require("./cli/list");
9
+ const logger_1 = require("./lib/ui/logger");
10
+ const program = new commander_1.Command();
11
+ program
12
+ .name("stackkit")
13
+ .description("CLI for creating and managing StackKit projects")
14
+ .version("0.1.0");
15
+ // Create command
16
+ program
17
+ .command("create [project-name]")
18
+ .description("Create a new StackKit project")
19
+ .option("-f, --framework <framework>", "Framework: nextjs, express, react")
20
+ .option("-d, --database <database>", "Database: prisma, mongoose, none")
21
+ .option("--prisma-provider <provider>", "Prisma provider: postgresql, mongodb, mysql, sqlite")
22
+ .option("-a, --auth <auth>", "Auth: better-auth, authjs, none")
23
+ .option("-l, --language <language>", "Language: typescript, javascript")
24
+ .option("-p, --package-manager <pm>", "Package manager: pnpm, npm, yarn, bun")
25
+ .option("--skip-install", "Skip dependency installation")
26
+ .option("--no-git", "Skip git initialization")
27
+ .option("-y, --yes", "Use default options")
28
+ .action(async (projectName, options) => {
29
+ try {
30
+ await (0, create_1.createProject)(projectName, options);
31
+ }
32
+ catch (error) {
33
+ logger_1.logger.error(`Error: ${error.message}`);
34
+ process.exit(1);
35
+ }
36
+ });
37
+ // Add command
38
+ program
39
+ .command("add <module>")
40
+ .description("Add a module to your existing project")
41
+ .option("--provider <provider>", "Specific provider/variant to use")
42
+ .option("--force", "Overwrite existing files")
43
+ .option("--dry-run", "Show what would be changed without making changes")
44
+ .option("--no-install", "Skip installing dependencies")
45
+ .action(async (module, options) => {
46
+ try {
47
+ await (0, add_1.addCommand)(module, options);
48
+ }
49
+ catch (error) {
50
+ logger_1.logger.error(`Error: ${error.message}`);
51
+ process.exit(1);
52
+ }
53
+ });
54
+ // Doctor command
55
+ program
56
+ .command("doctor")
57
+ .description("Check project health and compatibility with StackKit modules")
58
+ .option("--json", "Output results in JSON format")
59
+ .option("--verbose", "Show detailed information")
60
+ .option("--strict", "Treat warnings as errors")
61
+ .action(async (options) => {
62
+ try {
63
+ await (0, doctor_1.doctorCommand)(options);
64
+ }
65
+ catch (error) {
66
+ logger_1.logger.error(`Error: ${error.message}`);
67
+ process.exit(1);
68
+ }
69
+ });
70
+ // List command
71
+ program
72
+ .command("list")
73
+ .description("List available frameworks and modules")
74
+ .option("-f, --frameworks", "List only frameworks")
75
+ .option("-m, --modules", "List only modules")
76
+ .action(async (options) => {
77
+ try {
78
+ await (0, list_1.listCommand)(options);
79
+ }
80
+ catch (error) {
81
+ logger_1.logger.error(`Error: ${error.message}`);
82
+ process.exit(1);
83
+ }
84
+ });
85
+ // Error handling
86
+ program.on("command:*", () => {
87
+ logger_1.logger.error(`Invalid command: ${program.args.join(" ")}`);
88
+ logger_1.logger.log("Run stackkit --help for a list of available commands.");
89
+ process.exit(1);
90
+ });
91
+ program.parse();
@@ -0,0 +1 @@
1
+ export declare function convertToJavaScript(targetDir: string, framework: string): Promise<void>;
@@ -0,0 +1,244 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.convertToJavaScript = convertToJavaScript;
7
+ /* eslint-disable @typescript-eslint/no-require-imports */
8
+ const fs_extra_1 = __importDefault(require("fs-extra"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const baseDirs = {
11
+ express: "./src",
12
+ "react": "./src",
13
+ nextjs: ".",
14
+ };
15
+ async function convertToJavaScript(targetDir, framework) {
16
+ const tsFiles = [
17
+ "tsconfig.json",
18
+ "tsconfig.app.json",
19
+ "tsconfig.node.json",
20
+ "next-env.d.ts",
21
+ "vite-env.d.ts",
22
+ ];
23
+ for (const file of tsFiles) {
24
+ const filePath = path_1.default.join(targetDir, file);
25
+ if (await fs_extra_1.default.pathExists(filePath)) {
26
+ await fs_extra_1.default.remove(filePath);
27
+ }
28
+ }
29
+ const removeDtsFiles = async (dir) => {
30
+ const entries = await fs_extra_1.default.readdir(dir, { withFileTypes: true });
31
+ for (const entry of entries) {
32
+ const fullPath = path_1.default.join(dir, entry.name);
33
+ if (entry.isDirectory() && entry.name !== "node_modules") {
34
+ await removeDtsFiles(fullPath);
35
+ }
36
+ else if (entry.isFile() && entry.name.endsWith(".d.ts")) {
37
+ await fs_extra_1.default.remove(fullPath);
38
+ }
39
+ }
40
+ };
41
+ await removeDtsFiles(targetDir);
42
+ const babel = require("@babel/core");
43
+ const transpileAllTsFiles = async (dir) => {
44
+ const entries = await fs_extra_1.default.readdir(dir, { withFileTypes: true });
45
+ for (const entry of entries) {
46
+ const fullPath = path_1.default.join(dir, entry.name);
47
+ if (entry.isDirectory() && entry.name !== "node_modules") {
48
+ await transpileAllTsFiles(fullPath);
49
+ }
50
+ else if (entry.isFile()) {
51
+ if (entry.name.endsWith(".ts") || entry.name.endsWith(".tsx")) {
52
+ const code = await fs_extra_1.default.readFile(fullPath, "utf8");
53
+ const isTsx = entry.name.endsWith(".tsx");
54
+ const outFile = fullPath.replace(/\.tsx$/, ".jsx").replace(/\.ts$/, ".js");
55
+ const presets = [
56
+ [
57
+ require.resolve("@babel/preset-typescript"),
58
+ {
59
+ onlyRemoveTypeImports: true,
60
+ allowDeclareFields: true,
61
+ allowNamespaces: true,
62
+ optimizeForSpeed: true,
63
+ allExtensions: true,
64
+ isTSX: isTsx,
65
+ },
66
+ ],
67
+ [
68
+ require.resolve("@babel/preset-env"),
69
+ {
70
+ targets: { node: "18" },
71
+ modules: false,
72
+ },
73
+ ],
74
+ ];
75
+ if (isTsx) {
76
+ presets.push([
77
+ require.resolve("@babel/preset-react"),
78
+ {
79
+ runtime: "classic",
80
+ },
81
+ ]);
82
+ }
83
+ // Use recast + Babel AST transform (same approach as transform.tools)
84
+ try {
85
+ const recast = require("recast");
86
+ const { transformFromAstSync } = require("@babel/core");
87
+ const transformTypescript = require("@babel/plugin-transform-typescript");
88
+ // getBabelOptions may be exported as default or directly
89
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
90
+ let getBabelOptions = require("recast/parsers/_babel_options");
91
+ if (getBabelOptions && getBabelOptions.default)
92
+ getBabelOptions = getBabelOptions.default;
93
+ const babelParser = require("recast/parsers/babel").parser;
94
+ const ast = recast.parse(code, {
95
+ parser: {
96
+ parse: (source, options) => {
97
+ const babelOptions = getBabelOptions(options || {});
98
+ // ensure typescript and jsx handling
99
+ if (isTsx) {
100
+ babelOptions.plugins.push("typescript", "jsx");
101
+ }
102
+ else {
103
+ babelOptions.plugins.push("typescript");
104
+ }
105
+ return babelParser.parse(source, babelOptions);
106
+ },
107
+ },
108
+ });
109
+ const opts = {
110
+ cloneInputAst: false,
111
+ code: false,
112
+ ast: true,
113
+ plugins: [transformTypescript],
114
+ configFile: false,
115
+ };
116
+ const { ast: transformedAST } = transformFromAstSync(ast, code, opts);
117
+ const resultCode = recast.print(transformedAST).code;
118
+ await fs_extra_1.default.writeFile(outFile, resultCode, "utf8");
119
+ await fs_extra_1.default.remove(fullPath);
120
+ continue;
121
+ }
122
+ catch {
123
+ // ignore recast errors, fall back to babel
124
+ }
125
+ const result = await babel.transformAsync(code, {
126
+ filename: entry.name,
127
+ presets,
128
+ comments: true,
129
+ retainLines: true,
130
+ compact: false,
131
+ babelrc: false,
132
+ configFile: false,
133
+ });
134
+ await fs_extra_1.default.writeFile(outFile, result.code, "utf8");
135
+ await fs_extra_1.default.remove(fullPath);
136
+ }
137
+ }
138
+ }
139
+ };
140
+ await transpileAllTsFiles(targetDir);
141
+ const baseDir = baseDirs[framework];
142
+ if (baseDir) {
143
+ const replaceAliases = async (dir) => {
144
+ const entries = await fs_extra_1.default.readdir(dir, { withFileTypes: true });
145
+ for (const entry of entries) {
146
+ const full = path_1.default.join(dir, entry.name);
147
+ if (entry.isDirectory() && entry.name !== "node_modules") {
148
+ await replaceAliases(full);
149
+ }
150
+ else if (entry.isFile() && (entry.name.endsWith(".js") || entry.name.endsWith(".jsx"))) {
151
+ const content = await fs_extra_1.default.readFile(full, "utf-8");
152
+ if (content.includes("@/")) {
153
+ const fileDir = path_1.default.dirname(full);
154
+ const newContent = content.replace(/from ['"]@\/([^'"]*)['"]/g, (match, p1) => {
155
+ const resolved = path_1.default.resolve(baseDir, p1);
156
+ let relPath = path_1.default.relative(fileDir, resolved);
157
+ if (!relPath.startsWith("."))
158
+ relPath = "./" + relPath;
159
+ return `from '${relPath}'`;
160
+ });
161
+ await fs_extra_1.default.writeFile(full, newContent, "utf-8");
162
+ }
163
+ }
164
+ }
165
+ };
166
+ await replaceAliases(targetDir);
167
+ }
168
+ const templatesRoot = path_1.default.join(__dirname, "..", "..", "..", "templates");
169
+ const templateName = framework;
170
+ let fileReplacements = [];
171
+ let jsScripts = null;
172
+ if (templateName) {
173
+ const templateJsonPath = path_1.default.join(templatesRoot, templateName, "template.json");
174
+ if (await fs_extra_1.default.pathExists(templateJsonPath)) {
175
+ try {
176
+ const templateJson = await fs_extra_1.default.readJson(templateJsonPath);
177
+ if (Array.isArray(templateJson.fileReplacements)) {
178
+ fileReplacements = templateJson.fileReplacements;
179
+ }
180
+ if (templateJson.jsScripts) {
181
+ jsScripts = templateJson.jsScripts;
182
+ }
183
+ }
184
+ catch {
185
+ // ignore errors reading template.json
186
+ }
187
+ }
188
+ }
189
+ for (const rep of fileReplacements) {
190
+ const filePath = path_1.default.join(targetDir, rep.file);
191
+ if (await fs_extra_1.default.pathExists(filePath)) {
192
+ let content = await fs_extra_1.default.readFile(filePath, "utf8");
193
+ if (rep.from && rep.to) {
194
+ content = content.replace(rep.from, rep.to);
195
+ await fs_extra_1.default.writeFile(filePath, content, "utf8");
196
+ }
197
+ }
198
+ }
199
+ if (jsScripts) {
200
+ const packageJsonPath = path_1.default.join(targetDir, "package.json");
201
+ if (await fs_extra_1.default.pathExists(packageJsonPath)) {
202
+ const packageJson = await fs_extra_1.default.readJson(packageJsonPath);
203
+ packageJson.scripts = { ...packageJson.scripts, ...jsScripts };
204
+ await fs_extra_1.default.writeJson(packageJsonPath, packageJson, { spaces: 2 });
205
+ }
206
+ }
207
+ const jsconfig = path_1.default.join(targetDir, "jsconfig.json");
208
+ if (!(await fs_extra_1.default.pathExists(jsconfig))) {
209
+ for (const tmpl of await fs_extra_1.default.readdir(templatesRoot, { withFileTypes: true })) {
210
+ if (tmpl.isDirectory()) {
211
+ const templateJsconfig = path_1.default.join(templatesRoot, tmpl.name, "jsconfig.json");
212
+ if (await fs_extra_1.default.pathExists(templateJsconfig)) {
213
+ await fs_extra_1.default.copy(templateJsconfig, jsconfig);
214
+ break;
215
+ }
216
+ }
217
+ }
218
+ }
219
+ const srcDir = path_1.default.join(targetDir, "src");
220
+ if (await fs_extra_1.default.pathExists(srcDir)) {
221
+ const srcFiles = await fs_extra_1.default.readdir(srcDir);
222
+ for (const file of srcFiles) {
223
+ if ((file.endsWith(".js") || file.endsWith(".jsx")) &&
224
+ file.replace(/\.(js|jsx)$/, ".ts") &&
225
+ srcFiles.includes(file.replace(/\.(js|jsx)$/, ".ts"))) {
226
+ await fs_extra_1.default.remove(path_1.default.join(srcDir, file.replace(/\.(js|jsx)$/, ".ts")));
227
+ }
228
+ if (file.endsWith(".jsx") && srcFiles.includes(file.replace(/\.jsx$/, ".tsx"))) {
229
+ await fs_extra_1.default.remove(path_1.default.join(srcDir, file.replace(/\.jsx$/, ".tsx")));
230
+ }
231
+ }
232
+ }
233
+ const packageJsonPath = path_1.default.join(targetDir, "package.json");
234
+ if (await fs_extra_1.default.pathExists(packageJsonPath)) {
235
+ const packageJson = await fs_extra_1.default.readJson(packageJsonPath);
236
+ if (packageJson.devDependencies) {
237
+ delete packageJson.devDependencies["typescript"];
238
+ delete packageJson.devDependencies["@types/node"];
239
+ delete packageJson.devDependencies["@types/react"];
240
+ delete packageJson.devDependencies["@types/react-dom"];
241
+ }
242
+ await fs_extra_1.default.writeJson(packageJsonPath, packageJson, { spaces: 2 });
243
+ }
244
+ }
@@ -0,0 +1,6 @@
1
+ export declare const DATABASE_CONNECTION_STRINGS: {
2
+ readonly postgresql: "postgresql://user:password@localhost:5432/mydb?schema=public";
3
+ readonly mongodb: "mongodb://localhost:27017/mydb";
4
+ readonly mysql: "mysql://user:password@localhost:3306/mydb";
5
+ readonly sqlite: "file:./dev.db";
6
+ };
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DATABASE_CONNECTION_STRINGS = void 0;
4
+ exports.DATABASE_CONNECTION_STRINGS = {
5
+ postgresql: "postgresql://user:password@localhost:5432/mydb?schema=public",
6
+ mongodb: "mongodb://localhost:27017/mydb",
7
+ mysql: "mysql://user:password@localhost:3306/mydb",
8
+ sqlite: "file:./dev.db",
9
+ };
@@ -0,0 +1,62 @@
1
+ export interface ModuleMetadata {
2
+ name: string;
3
+ displayName: string;
4
+ description: string;
5
+ category: string;
6
+ provider?: string;
7
+ supportedFrameworks?: string[];
8
+ databaseAdapters?: Record<string, unknown>;
9
+ frameworkConfigs?: Record<string, unknown>;
10
+ dependencies?: Record<string, unknown>;
11
+ devDependencies?: Record<string, unknown>;
12
+ envVars?: Record<string, unknown>;
13
+ patches?: unknown[];
14
+ postInstall?: string[];
15
+ compatibility?: {
16
+ databases?: string[];
17
+ auth?: string[];
18
+ languages?: string[];
19
+ };
20
+ framework?: string;
21
+ files?: string[];
22
+ scripts?: Record<string, string>;
23
+ jsScripts?: Record<string, string>;
24
+ }
25
+ export interface DiscoveredModules {
26
+ frameworks: ModuleMetadata[];
27
+ databases: ModuleMetadata[];
28
+ auth: ModuleMetadata[];
29
+ }
30
+ /**
31
+ * Discover all available modules from the modules directory
32
+ */
33
+ export declare function discoverModules(modulesDir: string): Promise<DiscoveredModules>;
34
+ /**
35
+ * Get valid database options for CLI
36
+ */
37
+ export declare function getValidDatabaseOptions(databases: ModuleMetadata[]): string[];
38
+ /**
39
+ * Get valid auth options for CLI
40
+ */
41
+ export declare function getValidAuthOptions(authModules: ModuleMetadata[]): string[];
42
+ /**
43
+ * Parse database option into database name and provider
44
+ */
45
+ export declare function parseDatabaseOption(dbOption: string): {
46
+ database: string;
47
+ provider?: string;
48
+ };
49
+ /**
50
+ * Get compatible auth options for given framework and database
51
+ */
52
+ export declare function getCompatibleAuthOptions(authModules: ModuleMetadata[], framework: string, database: string): Array<{
53
+ name: string;
54
+ value: string;
55
+ }>;
56
+ /**
57
+ * Get database choices for inquirer prompts
58
+ */
59
+ export declare function getDatabaseChoices(databases: ModuleMetadata[], framework: string): Array<{
60
+ name: string;
61
+ value: string;
62
+ }>;