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
package/README.md ADDED
@@ -0,0 +1,41 @@
1
+ # StackKit CLI
2
+
3
+ Production-ready CLI for creating and enhancing JavaScript applications.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install -g stackkit
9
+ # or
10
+ npx stackkit
11
+ ```
12
+
13
+ ## Create New Project
14
+
15
+ ```bash
16
+ npx stackkit create my-app
17
+ ```
18
+
19
+ ## Add Features to Existing Project
20
+
21
+ ```bash
22
+ npx stackkit add auth
23
+ npx stackkit add database
24
+ ```
25
+
26
+ ## Check Project Health
27
+
28
+ ```bash
29
+ npx stackkit doctor
30
+ ```
31
+
32
+ ## Supported Technologies
33
+
34
+ - **Frameworks**: Next.js, React (Vite), Express
35
+ - **Databases**: Prisma (PostgreSQL, MySQL, SQLite), Mongoose (MongoDB)
36
+ - **Auth**: Better Auth, Auth.js
37
+
38
+ ## Documentation
39
+
40
+ - [StackKit Docs](https://stack-kit.dev)
41
+ - [GitHub Repository](https://github.com/tariqul420/stackkit)
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+
3
+ // eslint-disable-next-line
4
+ require("../dist/index.js");
@@ -0,0 +1,8 @@
1
+ interface AddOptions {
2
+ provider?: string;
3
+ force?: boolean;
4
+ dryRun?: boolean;
5
+ install?: boolean;
6
+ }
7
+ export declare function addCommand(module: string, options: AddOptions): Promise<void>;
8
+ export {};
@@ -0,0 +1,313 @@
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.addCommand = addCommand;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const child_process_1 = require("child_process");
9
+ const fs_extra_1 = __importDefault(require("fs-extra"));
10
+ const inquirer_1 = __importDefault(require("inquirer"));
11
+ const path_1 = __importDefault(require("path"));
12
+ const detect_1 = require("../lib/project/detect");
13
+ const env_editor_1 = require("../lib/env/env-editor");
14
+ const files_1 = require("../lib/fs/files");
15
+ const logger_1 = require("../lib/ui/logger");
16
+ const package_manager_1 = require("../lib/pm/package-manager");
17
+ const database_config_1 = require("../lib/database/database-config");
18
+ async function addCommand(module, options) {
19
+ try {
20
+ const projectRoot = process.cwd();
21
+ const spinner = logger_1.logger.startSpinner("Detecting project...");
22
+ const projectInfo = await (0, detect_1.detectProjectInfo)(projectRoot);
23
+ spinner.succeed(`Detected ${projectInfo.framework} (${projectInfo.router} router, ${projectInfo.language})`);
24
+ const moduleMetadata = await loadModuleMetadata(path_1.default.join(__dirname, "..", "..", "..", "modules"), module, options.provider);
25
+ if (!moduleMetadata) {
26
+ logger_1.logger.error(`Module "${module}" not found`);
27
+ process.exit(1);
28
+ }
29
+ let selectedProvider = options.provider;
30
+ if (moduleMetadata.category === "database" && !selectedProvider) {
31
+ if (typeof moduleMetadata.dependencies === "object" && "providers" in moduleMetadata.dependencies) {
32
+ const providers = Object.keys(moduleMetadata.dependencies.providers || {});
33
+ if (providers.length > 0) {
34
+ const { provider } = await inquirer_1.default.prompt([
35
+ {
36
+ type: "list",
37
+ name: "provider",
38
+ message: "Select database provider:",
39
+ choices: providers.map((p) => ({ name: p, value: p })),
40
+ },
41
+ ]);
42
+ selectedProvider = provider;
43
+ }
44
+ }
45
+ }
46
+ const mergedDeps = {};
47
+ const mergedDevDeps = {};
48
+ if (moduleMetadata.frameworkConfigs?.shared?.dependencies) {
49
+ Object.assign(mergedDeps, moduleMetadata.frameworkConfigs.shared.dependencies);
50
+ }
51
+ if (moduleMetadata.frameworkConfigs?.shared?.devDependencies) {
52
+ Object.assign(mergedDevDeps, moduleMetadata.frameworkConfigs.shared.devDependencies);
53
+ }
54
+ if (selectedProvider && moduleMetadata.databaseAdapters?.providers?.[selectedProvider]?.dependencies) {
55
+ Object.assign(mergedDeps, moduleMetadata.databaseAdapters.providers[selectedProvider].dependencies);
56
+ }
57
+ if (selectedProvider && moduleMetadata.databaseAdapters?.providers?.[selectedProvider]?.devDependencies) {
58
+ Object.assign(mergedDevDeps, moduleMetadata.databaseAdapters.providers[selectedProvider].devDependencies);
59
+ }
60
+ moduleMetadata.dependencies = mergedDeps;
61
+ moduleMetadata.devDependencies = mergedDevDeps;
62
+ const variables = {};
63
+ if (selectedProvider) {
64
+ variables.provider = selectedProvider;
65
+ variables.connectionString = database_config_1.DATABASE_CONNECTION_STRINGS[selectedProvider] || "";
66
+ }
67
+ if (!moduleMetadata.supportedFrameworks.includes(projectInfo.framework)) {
68
+ logger_1.logger.error(`Module "${module}" does not support ${projectInfo.framework}. Supported: ${moduleMetadata.supportedFrameworks.join(", ")}`);
69
+ process.exit(1);
70
+ }
71
+ if (module === "auth" && projectInfo.hasAuth && !options.force) {
72
+ logger_1.logger.warn("Auth library already detected in this project");
73
+ const { proceed } = await inquirer_1.default.prompt([
74
+ {
75
+ type: "confirm",
76
+ name: "proceed",
77
+ message: "Continue anyway? (use --force to skip this prompt)",
78
+ default: false,
79
+ },
80
+ ]);
81
+ if (!proceed) {
82
+ logger_1.logger.info("Cancelled");
83
+ process.exit(0);
84
+ }
85
+ }
86
+ if (options.dryRun) {
87
+ logger_1.logger.warn("Dry run mode - no changes will be made");
88
+ logger_1.logger.newLine();
89
+ }
90
+ await applyModulePatches(projectRoot, projectInfo, moduleMetadata, path_1.default.join(__dirname, "..", "..", "modules"), module, options);
91
+ if (moduleMetadata.frameworkPatches && !options.dryRun) {
92
+ await applyFrameworkPatches(projectRoot, moduleMetadata.frameworkPatches, projectInfo.framework);
93
+ }
94
+ if (moduleMetadata.postInstall && moduleMetadata.postInstall.length > 0 && !options.dryRun) {
95
+ const postInstallSpinner = logger_1.logger.startSpinner("Running post-install commands...");
96
+ try {
97
+ for (const command of moduleMetadata.postInstall) {
98
+ (0, child_process_1.execSync)(command, { cwd: projectRoot, stdio: "pipe" });
99
+ }
100
+ postInstallSpinner.succeed("Post-install commands completed");
101
+ }
102
+ catch (error) {
103
+ postInstallSpinner.fail("Failed to run post-install commands");
104
+ throw error;
105
+ }
106
+ }
107
+ if (Object.keys(mergedDeps).length > 0 && options.install !== false) {
108
+ const deps = Object.entries(mergedDeps).map(([name, version]) => `${name}@${version}`);
109
+ if (!options.dryRun) {
110
+ await (0, package_manager_1.addDependencies)(projectRoot, projectInfo.packageManager, deps, false);
111
+ }
112
+ else {
113
+ logger_1.logger.info(`Would add dependencies: ${deps.join(", ")}`);
114
+ }
115
+ }
116
+ if (Object.keys(mergedDevDeps).length > 0 && options.install !== false) {
117
+ const devDeps = Object.entries(mergedDevDeps).map(([name, version]) => `${name}@${version}`);
118
+ if (!options.dryRun) {
119
+ await (0, package_manager_1.addDependencies)(projectRoot, projectInfo.packageManager, devDeps, true);
120
+ }
121
+ else {
122
+ logger_1.logger.info(`Would add dev dependencies: ${devDeps.join(", ")}`);
123
+ }
124
+ }
125
+ if (moduleMetadata.envVars && moduleMetadata.envVars.length > 0) {
126
+ const processedEnvVars = moduleMetadata.envVars.map((envVar) => ({
127
+ ...envVar,
128
+ value: envVar.value?.replace(/\{\{(\w+)\}\}/g, (match, key) => variables[key] || match),
129
+ }));
130
+ if (!options.dryRun) {
131
+ await (0, env_editor_1.addEnvVariables)(projectRoot, processedEnvVars, { force: options.force });
132
+ }
133
+ else {
134
+ logger_1.logger.log(` ${chalk_1.default.dim("~")} .env.example`);
135
+ }
136
+ }
137
+ logger_1.logger.newLine();
138
+ logger_1.logger.success(`Added ${chalk_1.default.bold(moduleMetadata.displayName)}`);
139
+ logger_1.logger.newLine();
140
+ if (moduleMetadata.envVars && moduleMetadata.envVars.some((v) => v.required)) {
141
+ logger_1.logger.log("Next: Fill in environment variables in .env");
142
+ }
143
+ logger_1.logger.newLine();
144
+ }
145
+ catch (error) {
146
+ logger_1.logger.error(`Failed to add module: ${error.message}`);
147
+ if (error instanceof Error && error.stack) {
148
+ logger_1.logger.log(chalk_1.default.gray(error.stack));
149
+ }
150
+ process.exit(1);
151
+ }
152
+ }
153
+ async function loadModuleMetadata(modulesDir, moduleName, provider) {
154
+ if (!(await fs_extra_1.default.pathExists(modulesDir))) {
155
+ return null;
156
+ }
157
+ const categories = await fs_extra_1.default.readdir(modulesDir);
158
+ for (const category of categories) {
159
+ const categoryPath = path_1.default.join(modulesDir, category);
160
+ const stat = await fs_extra_1.default.stat(categoryPath);
161
+ if (!stat.isDirectory())
162
+ continue;
163
+ const moduleDirs = await fs_extra_1.default.readdir(categoryPath);
164
+ for (const moduleDir of moduleDirs) {
165
+ const modulePath = path_1.default.join(categoryPath, moduleDir);
166
+ const moduleStat = await fs_extra_1.default.stat(modulePath);
167
+ if (!moduleStat.isDirectory())
168
+ continue;
169
+ const metadataPath = path_1.default.join(modulePath, "module.json");
170
+ if (await fs_extra_1.default.pathExists(metadataPath)) {
171
+ const metadata = await fs_extra_1.default.readJSON(metadataPath);
172
+ if (provider && moduleDir === provider) {
173
+ return await loadGeneratorAndMerge(metadata, modulePath);
174
+ }
175
+ if (!provider && metadata.category === moduleName) {
176
+ return await loadGeneratorAndMerge(metadata, modulePath);
177
+ }
178
+ }
179
+ }
180
+ }
181
+ return null;
182
+ }
183
+ async function loadGeneratorAndMerge(metadata, modulePath) {
184
+ const generatorPath = path_1.default.join(modulePath, "generator.json");
185
+ if (await fs_extra_1.default.pathExists(generatorPath)) {
186
+ const generator = await fs_extra_1.default.readJSON(generatorPath);
187
+ // Merge envVars, dependencies, etc.
188
+ if (generator.envVars) {
189
+ metadata.envVars = metadata.envVars || [];
190
+ for (const [key, value] of Object.entries(generator.envVars)) {
191
+ metadata.envVars.push({ key, value: value, description: `Environment variable for ${key}`, required: true });
192
+ }
193
+ }
194
+ if (generator.dependencies) {
195
+ metadata.dependencies = { ...metadata.dependencies, ...generator.dependencies };
196
+ }
197
+ if (generator.devDependencies) {
198
+ metadata.devDependencies = { ...metadata.devDependencies, ...generator.devDependencies };
199
+ }
200
+ if (generator.scripts) {
201
+ // Perhaps add to metadata, but currently not used
202
+ }
203
+ // For operations, perhaps add to patches or something, but for now, keep manual
204
+ }
205
+ return metadata;
206
+ }
207
+ async function applyModulePatches(projectRoot, projectInfo, moduleMetadata, modulesDir, moduleName, options) {
208
+ if (!moduleMetadata.patches || !Array.isArray(moduleMetadata.patches)) {
209
+ return;
210
+ }
211
+ const moduleBasePath = await findModulePath(modulesDir, moduleName, options.provider);
212
+ if (!moduleBasePath) {
213
+ throw new Error("Module files not found");
214
+ }
215
+ for (const patch of moduleMetadata.patches) {
216
+ if (patch.type === "create-file") {
217
+ const filePatch = patch;
218
+ if (filePatch.condition) {
219
+ if (filePatch.condition.router && filePatch.condition.router !== projectInfo.router) {
220
+ continue;
221
+ }
222
+ if (filePatch.condition.language && filePatch.condition.language !== projectInfo.language) {
223
+ continue;
224
+ }
225
+ }
226
+ const sourceFile = path_1.default.join(moduleBasePath, "files", filePatch.source);
227
+ let destFile = path_1.default.join(projectRoot, filePatch.destination);
228
+ destFile = destFile
229
+ .replace("{{router}}", (0, detect_1.getRouterBasePath)(projectInfo))
230
+ .replace("{{lib}}", (0, detect_1.getLibPath)(projectInfo));
231
+ if (!options.dryRun) {
232
+ if (await (0, files_1.fileExists)(sourceFile)) {
233
+ const content = await fs_extra_1.default.readFile(sourceFile, "utf-8");
234
+ await (0, files_1.createFile)(destFile, content, { force: options.force });
235
+ const relativePath = path_1.default.relative(projectRoot, destFile);
236
+ logger_1.logger.log(` ${chalk_1.default.green("+")} ${relativePath}`);
237
+ }
238
+ else {
239
+ logger_1.logger.warn(`Source file not found: ${filePatch.source}`);
240
+ }
241
+ }
242
+ else {
243
+ const relativePath = path_1.default.relative(projectRoot, destFile);
244
+ logger_1.logger.log(` ${chalk_1.default.dim("+")} ${relativePath}`);
245
+ }
246
+ }
247
+ }
248
+ }
249
+ async function findModulePath(modulesDir, moduleName, provider) {
250
+ const categories = await fs_extra_1.default.readdir(modulesDir);
251
+ for (const category of categories) {
252
+ const categoryPath = path_1.default.join(modulesDir, category);
253
+ const stat = await fs_extra_1.default.stat(categoryPath);
254
+ if (!stat.isDirectory())
255
+ continue;
256
+ const moduleDirs = await fs_extra_1.default.readdir(categoryPath);
257
+ for (const moduleDir of moduleDirs) {
258
+ const modulePath = path_1.default.join(categoryPath, moduleDir);
259
+ const moduleStat = await fs_extra_1.default.stat(modulePath);
260
+ if (!moduleStat.isDirectory())
261
+ continue;
262
+ const metadataPath = path_1.default.join(modulePath, "module.json");
263
+ if (await fs_extra_1.default.pathExists(metadataPath)) {
264
+ const metadata = await fs_extra_1.default.readJSON(metadataPath);
265
+ if (provider && moduleDir === provider) {
266
+ return modulePath;
267
+ }
268
+ if (!provider && metadata.name === moduleName) {
269
+ return modulePath;
270
+ }
271
+ }
272
+ }
273
+ }
274
+ return null;
275
+ }
276
+ async function applyFrameworkPatches(projectRoot, patches, framework) {
277
+ const frameworkKey = framework;
278
+ const frameworkPatches = patches[frameworkKey];
279
+ if (!frameworkPatches)
280
+ return;
281
+ for (const [filename, patchConfig] of Object.entries(frameworkPatches)) {
282
+ const filePath = path_1.default.join(projectRoot, filename);
283
+ if (await fs_extra_1.default.pathExists(filePath)) {
284
+ const fileContent = await fs_extra_1.default.readJson(filePath);
285
+ if (patchConfig.merge) {
286
+ const merged = deepMerge(fileContent, patchConfig.merge);
287
+ await fs_extra_1.default.writeJson(filePath, merged, { spaces: 2 });
288
+ const relativePath = path_1.default.relative(projectRoot, filePath);
289
+ logger_1.logger.log(` ${chalk_1.default.blue("~")} ${relativePath}`);
290
+ }
291
+ }
292
+ }
293
+ }
294
+ function deepMerge(target, source) {
295
+ const output = { ...target };
296
+ for (const key in source) {
297
+ if (source[key] && typeof source[key] === "object" && !Array.isArray(source[key])) {
298
+ if (target[key]) {
299
+ output[key] = deepMerge(target[key], source[key]);
300
+ }
301
+ else {
302
+ output[key] = source[key];
303
+ }
304
+ }
305
+ else if (Array.isArray(source[key])) {
306
+ output[key] = Array.from(new Set([...(target[key] || []), ...source[key]]));
307
+ }
308
+ else {
309
+ output[key] = source[key];
310
+ }
311
+ }
312
+ return output;
313
+ }
@@ -0,0 +1,22 @@
1
+ interface CliOptions {
2
+ framework?: string;
3
+ f?: string;
4
+ database?: string;
5
+ d?: string;
6
+ auth?: string;
7
+ a?: string;
8
+ language?: string;
9
+ l?: string;
10
+ packageManager?: string;
11
+ p?: string;
12
+ install?: boolean;
13
+ 'skip-install'?: boolean;
14
+ skipInstall?: boolean;
15
+ git?: boolean;
16
+ 'no-git'?: boolean;
17
+ noGit?: boolean;
18
+ yes?: boolean;
19
+ y?: boolean;
20
+ }
21
+ export declare function createProject(projectName?: string, options?: CliOptions): Promise<void>;
22
+ export {};