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,188 @@
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.discoverModules = discoverModules;
7
+ exports.getValidDatabaseOptions = getValidDatabaseOptions;
8
+ exports.getValidAuthOptions = getValidAuthOptions;
9
+ exports.parseDatabaseOption = parseDatabaseOption;
10
+ exports.getCompatibleAuthOptions = getCompatibleAuthOptions;
11
+ exports.getDatabaseChoices = getDatabaseChoices;
12
+ const fs_extra_1 = __importDefault(require("fs-extra"));
13
+ const path_1 = __importDefault(require("path"));
14
+ /**
15
+ * Discover all available modules from the modules directory
16
+ */
17
+ async function discoverModules(modulesDir) {
18
+ const discovered = {
19
+ frameworks: [],
20
+ databases: [],
21
+ auth: [],
22
+ };
23
+ if (!(await fs_extra_1.default.pathExists(modulesDir))) {
24
+ return discovered;
25
+ }
26
+ // Discover frameworks from templates directory
27
+ const templatesDir = path_1.default.join(modulesDir, '..', 'templates');
28
+ if (await fs_extra_1.default.pathExists(templatesDir)) {
29
+ const frameworkDirs = await fs_extra_1.default.readdir(templatesDir);
30
+ for (const frameworkName of frameworkDirs) {
31
+ const templateJsonPath = path_1.default.join(templatesDir, frameworkName, 'template.json');
32
+ if (await fs_extra_1.default.pathExists(templateJsonPath)) {
33
+ try {
34
+ const templateConfig = await fs_extra_1.default.readJson(templateJsonPath);
35
+ discovered.frameworks.push({
36
+ ...templateConfig,
37
+ name: frameworkName,
38
+ category: 'framework',
39
+ });
40
+ }
41
+ catch {
42
+ // Silently skip invalid templates
43
+ }
44
+ }
45
+ }
46
+ }
47
+ // Discover database modules
48
+ const databaseDir = path_1.default.join(modulesDir, 'database');
49
+ if (await fs_extra_1.default.pathExists(databaseDir)) {
50
+ const dbModules = await fs_extra_1.default.readdir(databaseDir);
51
+ // Sort to ensure consistent order: prisma first, then others
52
+ dbModules.sort((a, b) => {
53
+ if (a === 'prisma')
54
+ return -1;
55
+ if (b === 'prisma')
56
+ return 1;
57
+ return a.localeCompare(b);
58
+ });
59
+ for (const moduleName of dbModules) {
60
+ const modulePath = path_1.default.join(databaseDir, moduleName);
61
+ const moduleJsonPath = path_1.default.join(modulePath, 'module.json');
62
+ if (await fs_extra_1.default.pathExists(moduleJsonPath)) {
63
+ try {
64
+ const metadata = await fs_extra_1.default.readJson(moduleJsonPath);
65
+ discovered.databases.push(metadata);
66
+ }
67
+ catch {
68
+ // Silently skip invalid modules
69
+ }
70
+ }
71
+ }
72
+ }
73
+ // Discover auth modules
74
+ const authDir = path_1.default.join(modulesDir, 'auth');
75
+ if (await fs_extra_1.default.pathExists(authDir)) {
76
+ const authModules = await fs_extra_1.default.readdir(authDir);
77
+ for (const moduleName of authModules) {
78
+ const modulePath = path_1.default.join(authDir, moduleName);
79
+ const moduleJsonPath = path_1.default.join(modulePath, 'module.json');
80
+ if (await fs_extra_1.default.pathExists(moduleJsonPath)) {
81
+ try {
82
+ const metadata = await fs_extra_1.default.readJson(moduleJsonPath);
83
+ discovered.auth.push(metadata);
84
+ }
85
+ catch {
86
+ // Silently skip invalid modules
87
+ }
88
+ }
89
+ }
90
+ }
91
+ return discovered;
92
+ }
93
+ /**
94
+ * Get valid database options for CLI
95
+ */
96
+ function getValidDatabaseOptions(databases) {
97
+ const options = ['none'];
98
+ for (const db of databases) {
99
+ if (db.name === 'prisma') {
100
+ // For Prisma, add provider-specific options
101
+ options.push('prisma-postgresql', 'prisma-mongodb', 'prisma-mysql', 'prisma-sqlite');
102
+ }
103
+ else if (db.name === 'mongoose') {
104
+ options.push('mongoose-mongodb', 'mongoose');
105
+ }
106
+ else {
107
+ // For other databases, add the name directly
108
+ options.push(db.name);
109
+ }
110
+ }
111
+ return options;
112
+ }
113
+ /**
114
+ * Get valid auth options for CLI
115
+ */
116
+ function getValidAuthOptions(authModules) {
117
+ const options = ['none'];
118
+ for (const auth of authModules) {
119
+ options.push(auth.name);
120
+ }
121
+ return options;
122
+ }
123
+ /**
124
+ * Parse database option into database name and provider
125
+ */
126
+ function parseDatabaseOption(dbOption) {
127
+ if (dbOption === 'none') {
128
+ return { database: 'none' };
129
+ }
130
+ if (dbOption.startsWith('prisma-')) {
131
+ const provider = dbOption.split('-')[1];
132
+ return { database: 'prisma', provider };
133
+ }
134
+ if (dbOption === 'mongoose-mongodb' || dbOption === 'mongoose') {
135
+ return { database: 'mongoose' };
136
+ }
137
+ return { database: dbOption };
138
+ }
139
+ /**
140
+ * Get compatible auth options for given framework and database
141
+ */
142
+ function getCompatibleAuthOptions(authModules, framework, database) {
143
+ const compatible = [];
144
+ for (const auth of authModules) {
145
+ // Check if auth supports the framework
146
+ if (auth.supportedFrameworks && !auth.supportedFrameworks.includes(framework)) {
147
+ continue;
148
+ }
149
+ // Special compatibility rules
150
+ if (auth.name === 'authjs' && (database !== 'prisma' || framework !== 'nextjs')) {
151
+ continue;
152
+ }
153
+ if (auth.name === 'better-auth' && database === 'none' && framework !== 'react') {
154
+ continue;
155
+ }
156
+ compatible.push({
157
+ name: auth.displayName,
158
+ value: auth.name
159
+ });
160
+ }
161
+ // Add "None" at the end
162
+ compatible.push({ name: 'None', value: 'none' });
163
+ return compatible;
164
+ }
165
+ /**
166
+ * Get database choices for inquirer prompts
167
+ */
168
+ function getDatabaseChoices(databases, framework) {
169
+ const choices = [];
170
+ for (const db of databases) {
171
+ // Check framework compatibility
172
+ if (db.supportedFrameworks && !db.supportedFrameworks.includes(framework)) {
173
+ continue;
174
+ }
175
+ if (db.name === 'prisma') {
176
+ choices.push({ name: 'Prisma (PostgreSQL)', value: 'prisma-postgresql' }, { name: 'Prisma (MongoDB)', value: 'prisma-mongodb' }, { name: 'Prisma (MySQL)', value: 'prisma-mysql' }, { name: 'Prisma (SQLite)', value: 'prisma-sqlite' });
177
+ }
178
+ else if (db.name === 'mongoose') {
179
+ choices.push({ name: 'Mongoose (MongoDB)', value: 'mongoose-mongodb' });
180
+ }
181
+ else {
182
+ choices.push({ name: db.displayName, value: db.name });
183
+ }
184
+ }
185
+ // Add "None" at the end
186
+ choices.push({ name: 'None', value: 'none' });
187
+ return choices;
188
+ }
@@ -0,0 +1,9 @@
1
+ export interface EnvVariable {
2
+ key: string;
3
+ value?: string;
4
+ required: boolean;
5
+ }
6
+ export declare function addEnvVariables(projectRoot: string, variables: EnvVariable[], options?: {
7
+ force?: boolean;
8
+ }): Promise<void>;
9
+ export declare function removeEnvVariables(projectRoot: string, keys: string[]): Promise<void>;
@@ -0,0 +1,116 @@
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.addEnvVariables = addEnvVariables;
7
+ exports.removeEnvVariables = removeEnvVariables;
8
+ const fs_extra_1 = __importDefault(require("fs-extra"));
9
+ const path_1 = __importDefault(require("path"));
10
+ const logger_1 = require("../ui/logger");
11
+ const ENV_MARKER_START = "# StackKit:";
12
+ const ENV_MARKER_END = "# End StackKit";
13
+ async function addEnvVariables(projectRoot, variables, options = {}) {
14
+ const envExamplePath = path_1.default.join(projectRoot, ".env.example");
15
+ const envPath = path_1.default.join(projectRoot, ".env");
16
+ await appendToEnvFile(envExamplePath, variables, "example", options);
17
+ const envExists = await fs_extra_1.default.pathExists(envPath);
18
+ if (envExists || options.force) {
19
+ await appendToEnvFile(envPath, variables, "local", options);
20
+ }
21
+ logger_1.logger.success("Environment variables added");
22
+ }
23
+ async function appendToEnvFile(filePath, variables, fileType, options = {}) {
24
+ // Validate environment variable keys
25
+ for (const variable of variables) {
26
+ if (!/^[A-Z_][A-Z0-9_]*$/.test(variable.key)) {
27
+ throw new Error(`Invalid environment variable key: ${variable.key}`);
28
+ }
29
+ }
30
+ let content = "";
31
+ if (await fs_extra_1.default.pathExists(filePath)) {
32
+ content = await fs_extra_1.default.readFile(filePath, "utf-8");
33
+ }
34
+ // If force, remove existing keys first to avoid duplicates
35
+ if (options.force) {
36
+ const keysToRemove = variables.map((v) => v.key);
37
+ await removeFromEnvFile(filePath, keysToRemove);
38
+ if (await fs_extra_1.default.pathExists(filePath)) {
39
+ content = await fs_extra_1.default.readFile(filePath, "utf-8");
40
+ }
41
+ else {
42
+ content = "";
43
+ }
44
+ }
45
+ // Check if variables already exist (after potential removal)
46
+ const existingKeys = new Set();
47
+ const lines = content.split("\n");
48
+ for (const line of lines) {
49
+ const match = line.match(/^([A-Z_][A-Z0-9_]*)=/);
50
+ if (match) {
51
+ existingKeys.add(match[1]);
52
+ }
53
+ }
54
+ const newVariables = variables.filter((v) => !existingKeys.has(v.key));
55
+ if (newVariables.length === 0) {
56
+ return;
57
+ }
58
+ // Ensure file ends with newline
59
+ if (content && !content.endsWith("\n")) {
60
+ content += "\n";
61
+ }
62
+ // Add marker and variables
63
+ content += "\n";
64
+ content += `${ENV_MARKER_START} Added by StackKit\n`;
65
+ for (const variable of newVariables) {
66
+ const value = fileType === "example" ? (variable.value || "") : (variable.value || "");
67
+ content += `${variable.key}=${value}\n`;
68
+ }
69
+ content += `${ENV_MARKER_END}\n`;
70
+ await fs_extra_1.default.ensureDir(path_1.default.dirname(filePath));
71
+ await fs_extra_1.default.writeFile(filePath, content, "utf-8");
72
+ }
73
+ async function removeEnvVariables(projectRoot, keys) {
74
+ const envExamplePath = path_1.default.join(projectRoot, ".env.example");
75
+ const envPath = path_1.default.join(projectRoot, ".env");
76
+ await removeFromEnvFile(envExamplePath, keys);
77
+ if (await fs_extra_1.default.pathExists(envPath)) {
78
+ await removeFromEnvFile(envPath, keys);
79
+ }
80
+ }
81
+ async function removeFromEnvFile(filePath, keys) {
82
+ if (!(await fs_extra_1.default.pathExists(filePath))) {
83
+ return;
84
+ }
85
+ try {
86
+ const content = await fs_extra_1.default.readFile(filePath, "utf-8");
87
+ const lines = content.split("\n");
88
+ const newLines = [];
89
+ let inStackKitBlock = false;
90
+ for (const line of lines) {
91
+ if (line.includes(ENV_MARKER_START)) {
92
+ inStackKitBlock = true;
93
+ continue;
94
+ }
95
+ if (line.includes(ENV_MARKER_END)) {
96
+ inStackKitBlock = false;
97
+ continue;
98
+ }
99
+ const match = line.match(/^([A-Z_][A-Z0-9_]*)=/);
100
+ if (match && keys.includes(match[1])) {
101
+ continue;
102
+ }
103
+ if (!inStackKitBlock || !line.startsWith("#")) {
104
+ newLines.push(line);
105
+ }
106
+ }
107
+ while (newLines.length > 0 && newLines[newLines.length - 1].trim() === "") {
108
+ newLines.pop();
109
+ }
110
+ await fs_extra_1.default.writeFile(filePath, newLines.join("\n"), "utf-8");
111
+ }
112
+ catch (error) {
113
+ logger_1.logger.error(`Failed to remove env variables from ${filePath}: ${error}`);
114
+ throw error;
115
+ }
116
+ }
@@ -0,0 +1,22 @@
1
+ export interface FrameworkConfig {
2
+ name: string;
3
+ displayName: string;
4
+ compatibility: {
5
+ databases: string[];
6
+ auth: string[];
7
+ };
8
+ }
9
+ export interface ModuleConfig {
10
+ name: string;
11
+ displayName: string;
12
+ type: 'database' | 'auth';
13
+ compatibility?: {
14
+ frameworks?: string[];
15
+ databases?: string[];
16
+ };
17
+ }
18
+ export declare class FrameworkUtils {
19
+ private static frameworkConfigs;
20
+ static loadFrameworkConfig(frameworkName: string, templatesDir: string): Promise<FrameworkConfig>;
21
+ static isCompatible(framework: string, database?: string, auth?: string): boolean;
22
+ }
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.FrameworkUtils = void 0;
37
+ const fs = __importStar(require("fs-extra"));
38
+ const path = __importStar(require("path"));
39
+ // eslint-disable-next-line @typescript-eslint/no-extraneous-class
40
+ class FrameworkUtils {
41
+ static async loadFrameworkConfig(frameworkName, templatesDir) {
42
+ const configPath = path.join(templatesDir, frameworkName, 'template.json');
43
+ if (await fs.pathExists(configPath)) {
44
+ const config = await fs.readJson(configPath);
45
+ this.frameworkConfigs.set(frameworkName, config);
46
+ return config;
47
+ }
48
+ // Default config if no template.json exists
49
+ const defaultConfig = {
50
+ name: frameworkName,
51
+ displayName: frameworkName.charAt(0).toUpperCase() + frameworkName.slice(1),
52
+ compatibility: {
53
+ databases: ['prisma', 'mongoose'],
54
+ auth: ['better-auth', 'authjs'],
55
+ },
56
+ };
57
+ this.frameworkConfigs.set(frameworkName, defaultConfig);
58
+ return defaultConfig;
59
+ }
60
+ static isCompatible(framework, database, auth) {
61
+ const config = this.frameworkConfigs.get(framework);
62
+ if (!config)
63
+ return true; // Assume compatible if no config
64
+ if (database && !config.compatibility.databases.includes(database)) {
65
+ return false;
66
+ }
67
+ if (auth && !config.compatibility.auth.includes(auth)) {
68
+ return false;
69
+ }
70
+ return true;
71
+ }
72
+ }
73
+ exports.FrameworkUtils = FrameworkUtils;
74
+ FrameworkUtils.frameworkConfigs = new Map();
@@ -0,0 +1,14 @@
1
+ export interface PackageJsonConfig {
2
+ dependencies?: Record<string, string>;
3
+ devDependencies?: Record<string, string>;
4
+ scripts?: Record<string, string>;
5
+ }
6
+ export declare function copyBaseFramework(templatesDir: string, targetDir: string, framework: string): Promise<void>;
7
+ export declare function mergePackageJson(targetDir: string, config: PackageJsonConfig): Promise<void>;
8
+ export declare function mergeEnvFile(targetDir: string, envVars: Record<string, string>): Promise<void>;
9
+ export declare function copyTemplate(templatePath: string, targetPath: string, projectName: string): Promise<void>;
10
+ export declare function createFile(targetPath: string, content: string, options?: {
11
+ force?: boolean;
12
+ }): Promise<void>;
13
+ export declare function readFile(filePath: string): Promise<string>;
14
+ export declare function fileExists(filePath: string): Promise<boolean>;
@@ -0,0 +1,101 @@
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.copyBaseFramework = copyBaseFramework;
7
+ exports.mergePackageJson = mergePackageJson;
8
+ exports.mergeEnvFile = mergeEnvFile;
9
+ exports.copyTemplate = copyTemplate;
10
+ exports.createFile = createFile;
11
+ exports.readFile = readFile;
12
+ exports.fileExists = fileExists;
13
+ const fs_extra_1 = __importDefault(require("fs-extra"));
14
+ const path_1 = __importDefault(require("path"));
15
+ const logger_1 = require("../ui/logger");
16
+ async function copyBaseFramework(templatesDir, targetDir, framework) {
17
+ const baseDir = path_1.default.join(templatesDir, framework);
18
+ if (!(await fs_extra_1.default.pathExists(baseDir))) {
19
+ throw new Error(`Base template not found for framework: ${framework}\n` + `Expected at: ${baseDir}`);
20
+ }
21
+ await fs_extra_1.default.copy(baseDir, targetDir, {
22
+ filter: (src) => {
23
+ const basename = path_1.default.basename(src);
24
+ return !["template.json", "config.json", "node_modules", ".git"].includes(basename);
25
+ },
26
+ });
27
+ }
28
+ async function mergePackageJson(targetDir, config) {
29
+ const pkgPath = path_1.default.join(targetDir, "package.json");
30
+ if (!(await fs_extra_1.default.pathExists(pkgPath))) {
31
+ return;
32
+ }
33
+ const pkg = await fs_extra_1.default.readJson(pkgPath);
34
+ if (config.dependencies) {
35
+ pkg.dependencies = { ...pkg.dependencies, ...config.dependencies };
36
+ }
37
+ if (config.devDependencies) {
38
+ pkg.devDependencies = { ...pkg.devDependencies, ...config.devDependencies };
39
+ }
40
+ if (config.scripts) {
41
+ pkg.scripts = { ...pkg.scripts, ...config.scripts };
42
+ }
43
+ await fs_extra_1.default.writeJson(pkgPath, pkg, { spaces: 2 });
44
+ }
45
+ async function mergeEnvFile(targetDir, envVars) {
46
+ const envPath = path_1.default.join(targetDir, ".env");
47
+ let existingEnv = "";
48
+ if (await fs_extra_1.default.pathExists(envPath)) {
49
+ existingEnv = await fs_extra_1.default.readFile(envPath, "utf-8");
50
+ }
51
+ const envLines = existingEnv.split("\n").filter((line) => line.trim() !== "");
52
+ // Add new variables
53
+ for (const [key, value] of Object.entries(envVars)) {
54
+ const existingIndex = envLines.findIndex((line) => line.startsWith(`${key}=`));
55
+ if (existingIndex !== -1) {
56
+ envLines[existingIndex] = `${key}=${value}`;
57
+ }
58
+ else {
59
+ envLines.push(`${key}=${value}`);
60
+ }
61
+ }
62
+ await fs_extra_1.default.writeFile(envPath, envLines.join("\n") + "\n", "utf-8");
63
+ }
64
+ async function copyTemplate(templatePath, targetPath, projectName) {
65
+ if (!(await fs_extra_1.default.pathExists(templatePath))) {
66
+ throw new Error(`Template not found: ${templatePath}`);
67
+ }
68
+ // Create target directory
69
+ await fs_extra_1.default.ensureDir(targetPath);
70
+ // Copy all files
71
+ await fs_extra_1.default.copy(templatePath, targetPath, {
72
+ filter: (src) => {
73
+ const basename = path_1.default.basename(src);
74
+ // Skip template.json metadata file and node_modules
75
+ return basename !== "template.json" && basename !== "node_modules";
76
+ },
77
+ });
78
+ // Update package.json with project name
79
+ const packageJsonPath = path_1.default.join(targetPath, "package.json");
80
+ if (await fs_extra_1.default.pathExists(packageJsonPath)) {
81
+ const packageJson = await fs_extra_1.default.readJSON(packageJsonPath);
82
+ packageJson.name = projectName;
83
+ await fs_extra_1.default.writeJSON(packageJsonPath, packageJson, { spaces: 2 });
84
+ }
85
+ logger_1.logger.success(`Template copied to ${targetPath}`);
86
+ }
87
+ async function createFile(targetPath, content, options = {}) {
88
+ const exists = await fs_extra_1.default.pathExists(targetPath);
89
+ if (exists && !options.force) {
90
+ logger_1.logger.warn(`File already exists: ${targetPath} (use --force to overwrite)`);
91
+ return;
92
+ }
93
+ await fs_extra_1.default.ensureDir(path_1.default.dirname(targetPath));
94
+ await fs_extra_1.default.writeFile(targetPath, content, "utf-8");
95
+ }
96
+ async function readFile(filePath) {
97
+ return fs_extra_1.default.readFile(filePath, "utf-8");
98
+ }
99
+ async function fileExists(filePath) {
100
+ return fs_extra_1.default.pathExists(filePath);
101
+ }
@@ -0,0 +1,83 @@
1
+ import { FrameworkConfig } from '../framework/framework-utils';
2
+ export interface GenerationContext {
3
+ framework: string;
4
+ database?: string;
5
+ auth?: string;
6
+ features?: string[];
7
+ [key: string]: unknown;
8
+ }
9
+ export interface TemplateCondition {
10
+ framework?: string | string[];
11
+ database?: string | string[];
12
+ auth?: string | string[];
13
+ features?: string[];
14
+ }
15
+ export interface Operation {
16
+ type: 'create-file' | 'patch-file' | 'add-dependency' | 'add-script' | 'add-env' | 'run-command';
17
+ description?: string;
18
+ condition?: TemplateCondition;
19
+ priority?: number;
20
+ source?: string;
21
+ destination?: string;
22
+ content?: string;
23
+ operations?: PatchOperation[];
24
+ dependencies?: Record<string, string>;
25
+ devDependencies?: Record<string, string>;
26
+ scripts?: Record<string, string>;
27
+ envVars?: Record<string, string>;
28
+ command?: string;
29
+ }
30
+ export interface PatchOperation {
31
+ type: 'add-import' | 'add-code' | 'replace-code' | 'add-to-top' | 'add-to-bottom';
32
+ condition?: TemplateCondition;
33
+ imports?: string[];
34
+ code?: string;
35
+ after?: string;
36
+ before?: string;
37
+ replace?: string;
38
+ content?: string;
39
+ source?: string;
40
+ }
41
+ export interface GeneratorConfig {
42
+ name: string;
43
+ type: 'framework' | 'database' | 'auth';
44
+ priority: number;
45
+ operations?: Operation[];
46
+ dependencies?: Record<string, string>;
47
+ devDependencies?: Record<string, string>;
48
+ scripts?: Record<string, string>;
49
+ envVars?: Record<string, string>;
50
+ postInstall?: string[];
51
+ }
52
+ export declare class AdvancedCodeGenerator {
53
+ private generators;
54
+ private frameworkConfig;
55
+ private postInstallCommands;
56
+ constructor(frameworkConfig: FrameworkConfig);
57
+ loadGenerators(modulesPath: string): Promise<void>;
58
+ private evaluateCondition;
59
+ private processTemplate;
60
+ private processVariableDefinitions;
61
+ private processTemplateRecursive;
62
+ generate(selectedModules: {
63
+ framework: string;
64
+ database?: string;
65
+ auth?: string;
66
+ prismaProvider?: string;
67
+ }, features: string[], outputPath: string): Promise<string[]>;
68
+ private executeOperation;
69
+ private copyTemplate;
70
+ private processOperationTemplates;
71
+ private executeCreateFile;
72
+ private executePatchFile;
73
+ private executeAddDependency;
74
+ private executeAddScript;
75
+ private executeAddEnv;
76
+ private executeRunCommand;
77
+ private generatePackageJson;
78
+ getAvailableGenerators(): {
79
+ frameworks: string[];
80
+ databases: string[];
81
+ auths: string[];
82
+ };
83
+ }