@diagramers/cli 1.0.6
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.
- package/README.md +91 -0
- package/dist/commands/extend.d.ts +3 -0
- package/dist/commands/extend.d.ts.map +1 -0
- package/dist/commands/extend.js +37 -0
- package/dist/commands/extend.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +31 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/update.d.ts +3 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +29 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/config/template-config.d.ts +21 -0
- package/dist/config/template-config.d.ts.map +1 -0
- package/dist/config/template-config.js +93 -0
- package/dist/config/template-config.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/services/project-extender.d.ts +15 -0
- package/dist/services/project-extender.d.ts.map +1 -0
- package/dist/services/project-extender.js +207 -0
- package/dist/services/project-extender.js.map +1 -0
- package/dist/services/project-initializer.d.ts +15 -0
- package/dist/services/project-initializer.d.ts.map +1 -0
- package/dist/services/project-initializer.js +240 -0
- package/dist/services/project-initializer.js.map +1 -0
- package/dist/services/project-updater.d.ts +16 -0
- package/dist/services/project-updater.d.ts.map +1 -0
- package/dist/services/project-updater.js +134 -0
- package/dist/services/project-updater.js.map +1 -0
- package/package.json +51 -0
- package/scripts/publish.sh +58 -0
- package/scripts/setup.sh +38 -0
- package/scripts/version.sh +80 -0
- package/src/commands/extend.ts +35 -0
- package/src/commands/init.ts +27 -0
- package/src/commands/update.ts +25 -0
- package/src/config/template-config.ts +111 -0
- package/src/index.ts +35 -0
- package/src/services/project-extender.ts +196 -0
- package/src/services/project-initializer.ts +224 -0
- package/src/services/project-updater.ts +125 -0
- package/tsconfig.json +19 -0
@@ -0,0 +1,27 @@
|
|
1
|
+
import { Command } from 'commander';
|
2
|
+
import { ProjectInitializer } from '../services/project-initializer';
|
3
|
+
import chalk from 'chalk';
|
4
|
+
|
5
|
+
export function initCommand(program: Command) {
|
6
|
+
program
|
7
|
+
.command('init <project-name>')
|
8
|
+
.description('Initialize a new project from the template')
|
9
|
+
.option('-t, --template <template>', 'Template version to use', 'latest')
|
10
|
+
.option('-y, --yes', 'Skip prompts and use defaults')
|
11
|
+
.action(async (projectName: string, options: any) => {
|
12
|
+
try {
|
13
|
+
console.log(chalk.blue(`🚀 Initializing new project: ${projectName}`));
|
14
|
+
|
15
|
+
const initializer = new ProjectInitializer();
|
16
|
+
await initializer.initialize(projectName, options);
|
17
|
+
|
18
|
+
console.log(chalk.green(`✅ Project ${projectName} initialized successfully!`));
|
19
|
+
console.log(chalk.yellow(`📁 Navigate to the project: cd ${projectName}`));
|
20
|
+
console.log(chalk.yellow(`🔧 Install dependencies: npm install`));
|
21
|
+
console.log(chalk.yellow(`🚀 Start development: npm run serve`));
|
22
|
+
} catch (error: any) {
|
23
|
+
console.error(chalk.red(`❌ Failed to initialize project: ${error.message}`));
|
24
|
+
process.exit(1);
|
25
|
+
}
|
26
|
+
});
|
27
|
+
}
|
@@ -0,0 +1,25 @@
|
|
1
|
+
import { Command } from 'commander';
|
2
|
+
import { ProjectUpdater } from '../services/project-updater';
|
3
|
+
import chalk from 'chalk';
|
4
|
+
|
5
|
+
export function updateCommand(program: Command) {
|
6
|
+
program
|
7
|
+
.command('update')
|
8
|
+
.description('Update existing project with latest template features')
|
9
|
+
.option('-f, --force', 'Force update even if conflicts detected')
|
10
|
+
.option('-b, --backup', 'Create backup before updating')
|
11
|
+
.action(async (options: any) => {
|
12
|
+
try {
|
13
|
+
console.log(chalk.blue('🔄 Checking for template updates...'));
|
14
|
+
|
15
|
+
const updater = new ProjectUpdater();
|
16
|
+
await updater.update(options);
|
17
|
+
|
18
|
+
console.log(chalk.green('✅ Project updated successfully!'));
|
19
|
+
console.log(chalk.yellow('📝 Review the changes and test your application'));
|
20
|
+
} catch (error: any) {
|
21
|
+
console.error(chalk.red(`❌ Failed to update project: ${error.message}`));
|
22
|
+
process.exit(1);
|
23
|
+
}
|
24
|
+
});
|
25
|
+
}
|
@@ -0,0 +1,111 @@
|
|
1
|
+
export interface TemplateConfig {
|
2
|
+
name: string;
|
3
|
+
version: string;
|
4
|
+
description: string;
|
5
|
+
files: {
|
6
|
+
include: string[];
|
7
|
+
exclude: string[];
|
8
|
+
updateable: string[];
|
9
|
+
customizable: string[];
|
10
|
+
};
|
11
|
+
features: {
|
12
|
+
[key: string]: {
|
13
|
+
name: string;
|
14
|
+
description: string;
|
15
|
+
dependencies: string[];
|
16
|
+
files: string[];
|
17
|
+
};
|
18
|
+
};
|
19
|
+
}
|
20
|
+
|
21
|
+
export const templateConfig: TemplateConfig = {
|
22
|
+
name: 'diagrammers-api-template',
|
23
|
+
version: '1.0.0',
|
24
|
+
description: 'Node.js API template with TypeScript, Firebase Functions, and Socket.io',
|
25
|
+
|
26
|
+
files: {
|
27
|
+
include: [
|
28
|
+
'src/**/*',
|
29
|
+
'package.json',
|
30
|
+
'tsconfig.json',
|
31
|
+
'webpack.config.js',
|
32
|
+
'main.ts',
|
33
|
+
'certs/**/*'
|
34
|
+
],
|
35
|
+
exclude: [
|
36
|
+
'node_modules/**',
|
37
|
+
'dist/**',
|
38
|
+
'cli/**',
|
39
|
+
'.git/**',
|
40
|
+
'backup-*/**',
|
41
|
+
'*.log',
|
42
|
+
'.env*'
|
43
|
+
],
|
44
|
+
updateable: [
|
45
|
+
'src/helpers/**/*',
|
46
|
+
'src/config/**/*',
|
47
|
+
'src/server/**/*',
|
48
|
+
'webpack.config.js',
|
49
|
+
'tsconfig.json'
|
50
|
+
],
|
51
|
+
customizable: [
|
52
|
+
'src/controllers/**/*',
|
53
|
+
'src/entities/**/*',
|
54
|
+
'src/routes/**/*',
|
55
|
+
'src/services/**/*',
|
56
|
+
'src/schemas/**/*',
|
57
|
+
'main.ts'
|
58
|
+
]
|
59
|
+
},
|
60
|
+
|
61
|
+
features: {
|
62
|
+
auth: {
|
63
|
+
name: 'Authentication',
|
64
|
+
description: 'JWT-based authentication system',
|
65
|
+
dependencies: ['jsonwebtoken', 'bcryptjs', '@types/jsonwebtoken', '@types/bcryptjs'],
|
66
|
+
files: [
|
67
|
+
'src/features/auth/**/*',
|
68
|
+
'src/helpers/auth.ts'
|
69
|
+
]
|
70
|
+
},
|
71
|
+
email: {
|
72
|
+
name: 'Email System',
|
73
|
+
description: 'Email notification system with templates',
|
74
|
+
dependencies: ['nodemailer', 'handlebars', '@types/nodemailer'],
|
75
|
+
files: [
|
76
|
+
'src/features/email/**/*',
|
77
|
+
'src/helpers/mailer.ts',
|
78
|
+
'src/assets/css/email-template.css'
|
79
|
+
]
|
80
|
+
},
|
81
|
+
socket: {
|
82
|
+
name: 'WebSocket',
|
83
|
+
description: 'Real-time communication with Socket.io',
|
84
|
+
dependencies: ['socket.io', '@types/socket.io'],
|
85
|
+
files: [
|
86
|
+
'src/features/socket/**/*',
|
87
|
+
'src/server/socket-server-provider.ts'
|
88
|
+
]
|
89
|
+
},
|
90
|
+
cron: {
|
91
|
+
name: 'Scheduled Tasks',
|
92
|
+
description: 'Cron job system for scheduled tasks',
|
93
|
+
dependencies: ['node-cron', '@types/node-cron'],
|
94
|
+
files: [
|
95
|
+
'src/features/cron/**/*',
|
96
|
+
'src/helpers/cronHelper.ts'
|
97
|
+
]
|
98
|
+
},
|
99
|
+
audit: {
|
100
|
+
name: 'Audit Logging',
|
101
|
+
description: 'Comprehensive audit logging system',
|
102
|
+
dependencies: [],
|
103
|
+
files: [
|
104
|
+
'src/features/audit/**/*',
|
105
|
+
'src/entities/audit.ts',
|
106
|
+
'src/schemas/audit.ts',
|
107
|
+
'src/services/audit-service.ts'
|
108
|
+
]
|
109
|
+
}
|
110
|
+
}
|
111
|
+
};
|
package/src/index.ts
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
#!/usr/bin/env node
|
2
|
+
|
3
|
+
import { Command } from 'commander';
|
4
|
+
import { initCommand } from './commands/init';
|
5
|
+
import { updateCommand } from './commands/update';
|
6
|
+
import { extendCommand } from './commands/extend';
|
7
|
+
import chalk from 'chalk';
|
8
|
+
|
9
|
+
const program = new Command();
|
10
|
+
|
11
|
+
program
|
12
|
+
.name('diagrammers')
|
13
|
+
.description('CLI tool for managing Diagrammers projects')
|
14
|
+
.version('1.0.0');
|
15
|
+
|
16
|
+
// Add commands
|
17
|
+
initCommand(program);
|
18
|
+
updateCommand(program);
|
19
|
+
extendCommand(program);
|
20
|
+
|
21
|
+
// Add help text
|
22
|
+
program.addHelpText('after', `
|
23
|
+
Examples:
|
24
|
+
$ diagrammers init api my-new-project
|
25
|
+
$ diagrammers init admin my-admin-dashboard
|
26
|
+
$ diagrammers update
|
27
|
+
$ diagrammers extend --feature auth
|
28
|
+
`);
|
29
|
+
|
30
|
+
program.parse();
|
31
|
+
|
32
|
+
// If no command is provided, show help
|
33
|
+
if (!process.argv.slice(2).length) {
|
34
|
+
program.outputHelp();
|
35
|
+
}
|
@@ -0,0 +1,196 @@
|
|
1
|
+
import * as fs from 'fs-extra';
|
2
|
+
import * as path from 'path';
|
3
|
+
import chalk from 'chalk';
|
4
|
+
|
5
|
+
export interface Feature {
|
6
|
+
name: string;
|
7
|
+
description: string;
|
8
|
+
files: string[];
|
9
|
+
dependencies?: string[];
|
10
|
+
}
|
11
|
+
|
12
|
+
export class ProjectExtender {
|
13
|
+
private features: Feature[] = [
|
14
|
+
{
|
15
|
+
name: 'auth',
|
16
|
+
description: 'Authentication system with JWT',
|
17
|
+
files: ['src/features/auth/**/*'],
|
18
|
+
dependencies: ['jsonwebtoken', 'bcryptjs']
|
19
|
+
},
|
20
|
+
{
|
21
|
+
name: 'email',
|
22
|
+
description: 'Email notification system',
|
23
|
+
files: ['src/features/email/**/*'],
|
24
|
+
dependencies: ['nodemailer', 'handlebars']
|
25
|
+
},
|
26
|
+
{
|
27
|
+
name: 'socket',
|
28
|
+
description: 'Real-time WebSocket communication',
|
29
|
+
files: ['src/features/socket/**/*'],
|
30
|
+
dependencies: ['socket.io']
|
31
|
+
},
|
32
|
+
{
|
33
|
+
name: 'cron',
|
34
|
+
description: 'Scheduled task system',
|
35
|
+
files: ['src/features/cron/**/*'],
|
36
|
+
dependencies: ['node-cron']
|
37
|
+
},
|
38
|
+
{
|
39
|
+
name: 'audit',
|
40
|
+
description: 'Audit logging system',
|
41
|
+
files: ['src/features/audit/**/*']
|
42
|
+
}
|
43
|
+
];
|
44
|
+
|
45
|
+
async listFeatures(): Promise<void> {
|
46
|
+
console.log(chalk.blue('📋 Available features:'));
|
47
|
+
console.log('');
|
48
|
+
|
49
|
+
this.features.forEach(feature => {
|
50
|
+
console.log(chalk.green(` ${feature.name}`));
|
51
|
+
console.log(chalk.gray(` ${feature.description}`));
|
52
|
+
if (feature.dependencies && feature.dependencies.length > 0) {
|
53
|
+
console.log(chalk.yellow(` Dependencies: ${feature.dependencies.join(', ')}`));
|
54
|
+
}
|
55
|
+
console.log('');
|
56
|
+
});
|
57
|
+
}
|
58
|
+
|
59
|
+
async addFeature(featureName: string): Promise<void> {
|
60
|
+
const feature = this.features.find(f => f.name === featureName);
|
61
|
+
|
62
|
+
if (!feature) {
|
63
|
+
throw new Error(`Feature '${featureName}' not found. Use --list to see available features.`);
|
64
|
+
}
|
65
|
+
|
66
|
+
const projectPath = process.cwd();
|
67
|
+
|
68
|
+
// Check if feature already exists
|
69
|
+
const featurePath = path.join(projectPath, 'src', 'features', featureName);
|
70
|
+
if (await fs.pathExists(featurePath)) {
|
71
|
+
throw new Error(`Feature '${featureName}' already exists in this project.`);
|
72
|
+
}
|
73
|
+
|
74
|
+
// Create feature directory structure
|
75
|
+
await this.createFeatureStructure(projectPath, feature);
|
76
|
+
|
77
|
+
// Add dependencies if any
|
78
|
+
if (feature.dependencies && feature.dependencies.length > 0) {
|
79
|
+
await this.addDependencies(feature.dependencies);
|
80
|
+
}
|
81
|
+
|
82
|
+
console.log(chalk.green(`✅ Feature '${featureName}' added successfully!`));
|
83
|
+
}
|
84
|
+
|
85
|
+
private async createFeatureStructure(projectPath: string, feature: Feature): Promise<void> {
|
86
|
+
const featurePath = path.join(projectPath, 'src', 'features', feature.name);
|
87
|
+
|
88
|
+
// Create basic feature structure
|
89
|
+
const structure = {
|
90
|
+
'controllers': 'Feature controllers',
|
91
|
+
'services': 'Feature business logic',
|
92
|
+
'schemas': 'Feature validation schemas',
|
93
|
+
'routes': 'Feature API routes',
|
94
|
+
'types': 'Feature TypeScript types'
|
95
|
+
};
|
96
|
+
|
97
|
+
for (const [dir, description] of Object.entries(structure)) {
|
98
|
+
const dirPath = path.join(featurePath, dir);
|
99
|
+
await fs.ensureDir(dirPath);
|
100
|
+
|
101
|
+
// Create index file
|
102
|
+
const indexContent = `// ${description} for ${feature.name} feature
|
103
|
+
export * from './${feature.name}-${dir.slice(0, -1)}';
|
104
|
+
`;
|
105
|
+
await fs.writeFile(path.join(dirPath, 'index.ts'), indexContent);
|
106
|
+
}
|
107
|
+
|
108
|
+
// Create main feature file
|
109
|
+
const mainFeatureContent = `import { Router } from 'express';
|
110
|
+
import { ${feature.name}Controller } from './controllers';
|
111
|
+
import { ${feature.name}Service } from './services';
|
112
|
+
|
113
|
+
export class ${this.capitalizeFirst(feature.name)}Feature {
|
114
|
+
private router: Router;
|
115
|
+
private controller: ${feature.name}Controller;
|
116
|
+
private service: ${feature.name}Service;
|
117
|
+
|
118
|
+
constructor() {
|
119
|
+
this.router = Router();
|
120
|
+
this.service = new ${feature.name}Service();
|
121
|
+
this.controller = new ${feature.name}Controller(this.service);
|
122
|
+
this.setupRoutes();
|
123
|
+
}
|
124
|
+
|
125
|
+
private setupRoutes(): void {
|
126
|
+
// Define your routes here
|
127
|
+
// this.router.get('/', this.controller.index.bind(this.controller));
|
128
|
+
}
|
129
|
+
|
130
|
+
public getRouter(): Router {
|
131
|
+
return this.router;
|
132
|
+
}
|
133
|
+
}
|
134
|
+
`;
|
135
|
+
|
136
|
+
await fs.writeFile(path.join(featurePath, `${feature.name}.ts`), mainFeatureContent);
|
137
|
+
|
138
|
+
// Create controller
|
139
|
+
const controllerContent = `import { Request, Response } from 'express';
|
140
|
+
import { ${feature.name}Service } from '../services';
|
141
|
+
|
142
|
+
export class ${feature.name}Controller {
|
143
|
+
constructor(private service: ${feature.name}Service) {}
|
144
|
+
|
145
|
+
// Add your controller methods here
|
146
|
+
// async index(req: Request, res: Response): Promise<void> {
|
147
|
+
// try {
|
148
|
+
// const result = await this.service.someMethod();
|
149
|
+
// res.json(result);
|
150
|
+
// } catch (error) {
|
151
|
+
// res.status(500).json({ error: error.message });
|
152
|
+
// }
|
153
|
+
// }
|
154
|
+
}
|
155
|
+
`;
|
156
|
+
|
157
|
+
await fs.writeFile(path.join(featurePath, 'controllers', `${feature.name}-controller.ts`), controllerContent);
|
158
|
+
|
159
|
+
// Create service
|
160
|
+
const serviceContent = `export class ${feature.name}Service {
|
161
|
+
// Add your service methods here
|
162
|
+
// async someMethod(): Promise<any> {
|
163
|
+
// // Implementation
|
164
|
+
// }
|
165
|
+
}
|
166
|
+
`;
|
167
|
+
|
168
|
+
await fs.writeFile(path.join(featurePath, 'services', `${feature.name}-service.ts`), serviceContent);
|
169
|
+
|
170
|
+
// Create types
|
171
|
+
const typesContent = `// TypeScript types for ${feature.name} feature
|
172
|
+
export interface ${this.capitalizeFirst(feature.name)}Config {
|
173
|
+
// Add configuration interface
|
174
|
+
}
|
175
|
+
|
176
|
+
export interface ${this.capitalizeFirst(feature.name)}Data {
|
177
|
+
// Add data interface
|
178
|
+
}
|
179
|
+
`;
|
180
|
+
|
181
|
+
await fs.writeFile(path.join(featurePath, 'types', `${feature.name}-types.ts`), typesContent);
|
182
|
+
}
|
183
|
+
|
184
|
+
private async addDependencies(dependencies: string[]): Promise<void> {
|
185
|
+
console.log(chalk.blue('📦 Installing dependencies...'));
|
186
|
+
|
187
|
+
// This would typically run npm install with the dependencies
|
188
|
+
// For now, we'll just log what would be installed
|
189
|
+
console.log(chalk.yellow(`Would install: ${dependencies.join(', ')}`));
|
190
|
+
console.log(chalk.gray('Run: npm install ' + dependencies.join(' ') + ' to install dependencies'));
|
191
|
+
}
|
192
|
+
|
193
|
+
private capitalizeFirst(str: string): string {
|
194
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
195
|
+
}
|
196
|
+
}
|
@@ -0,0 +1,224 @@
|
|
1
|
+
import * as fs from 'fs-extra';
|
2
|
+
import * as path from 'path';
|
3
|
+
import * as glob from 'glob';
|
4
|
+
import chalk from 'chalk';
|
5
|
+
|
6
|
+
export interface InitOptions {
|
7
|
+
template?: string;
|
8
|
+
yes?: boolean;
|
9
|
+
}
|
10
|
+
|
11
|
+
export class ProjectInitializer {
|
12
|
+
private templatePath: string;
|
13
|
+
private templateFiles: string[] = [
|
14
|
+
'src/**/*',
|
15
|
+
'package.json',
|
16
|
+
'tsconfig.json',
|
17
|
+
'webpack.config.js',
|
18
|
+
'main.ts',
|
19
|
+
'certs/**/*'
|
20
|
+
];
|
21
|
+
|
22
|
+
constructor() {
|
23
|
+
// Get the path to the template (parent directory of CLI)
|
24
|
+
this.templatePath = path.resolve(__dirname, '../../..');
|
25
|
+
}
|
26
|
+
|
27
|
+
async initialize(projectName: string, options: InitOptions): Promise<void> {
|
28
|
+
const projectPath = path.resolve(process.cwd(), projectName);
|
29
|
+
|
30
|
+
// Check if project directory already exists
|
31
|
+
if (await fs.pathExists(projectPath)) {
|
32
|
+
throw new Error(`Project directory ${projectName} already exists`);
|
33
|
+
}
|
34
|
+
|
35
|
+
// Create project directory
|
36
|
+
await fs.ensureDir(projectPath);
|
37
|
+
|
38
|
+
// Copy template files
|
39
|
+
await this.copyTemplateFiles(projectPath);
|
40
|
+
|
41
|
+
// Update package.json with project name
|
42
|
+
await this.updatePackageJson(projectPath, projectName);
|
43
|
+
|
44
|
+
// Create .gitignore
|
45
|
+
await this.createGitignore(projectPath);
|
46
|
+
|
47
|
+
// Create README
|
48
|
+
await this.createReadme(projectPath, projectName);
|
49
|
+
|
50
|
+
console.log(chalk.green(`✅ Project structure created successfully`));
|
51
|
+
}
|
52
|
+
|
53
|
+
private async copyTemplateFiles(projectPath: string): Promise<void> {
|
54
|
+
for (const pattern of this.templateFiles) {
|
55
|
+
try {
|
56
|
+
const files = glob.sync(pattern, {
|
57
|
+
cwd: this.templatePath,
|
58
|
+
ignore: ['node_modules/**', 'dist/**', 'cli/**', '.git/**'],
|
59
|
+
nodir: false
|
60
|
+
});
|
61
|
+
|
62
|
+
for (const file of files) {
|
63
|
+
const sourcePath = path.join(this.templatePath, file);
|
64
|
+
const destPath = path.join(projectPath, file);
|
65
|
+
|
66
|
+
if (await fs.pathExists(sourcePath)) {
|
67
|
+
const stat = await fs.stat(sourcePath);
|
68
|
+
|
69
|
+
if (stat.isDirectory()) {
|
70
|
+
// Copy directory
|
71
|
+
await fs.ensureDir(destPath);
|
72
|
+
await fs.copy(sourcePath, destPath);
|
73
|
+
} else {
|
74
|
+
// Copy file
|
75
|
+
await fs.ensureDir(path.dirname(destPath));
|
76
|
+
await fs.copy(sourcePath, destPath);
|
77
|
+
}
|
78
|
+
}
|
79
|
+
}
|
80
|
+
} catch (error: any) {
|
81
|
+
// Log warning but continue with other files
|
82
|
+
console.log(chalk.yellow(`⚠️ Warning: Could not copy pattern '${pattern}': ${error.message}`));
|
83
|
+
}
|
84
|
+
}
|
85
|
+
}
|
86
|
+
|
87
|
+
private async updatePackageJson(projectPath: string, projectName: string): Promise<void> {
|
88
|
+
const packageJsonPath = path.join(projectPath, 'package.json');
|
89
|
+
|
90
|
+
if (await fs.pathExists(packageJsonPath)) {
|
91
|
+
const packageJson = await fs.readJson(packageJsonPath);
|
92
|
+
packageJson.name = projectName;
|
93
|
+
packageJson.description = `API project: ${projectName}`;
|
94
|
+
|
95
|
+
await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
|
96
|
+
}
|
97
|
+
}
|
98
|
+
|
99
|
+
private async createGitignore(projectPath: string): Promise<void> {
|
100
|
+
const gitignoreContent = `
|
101
|
+
# Dependencies
|
102
|
+
node_modules/
|
103
|
+
npm-debug.log*
|
104
|
+
yarn-debug.log*
|
105
|
+
yarn-error.log*
|
106
|
+
|
107
|
+
# Build outputs
|
108
|
+
dist/
|
109
|
+
build/
|
110
|
+
*.tsbuildinfo
|
111
|
+
|
112
|
+
# Environment variables
|
113
|
+
.env
|
114
|
+
.env.local
|
115
|
+
.env.development.local
|
116
|
+
.env.test.local
|
117
|
+
.env.production.local
|
118
|
+
|
119
|
+
# IDE
|
120
|
+
.vscode/
|
121
|
+
.idea/
|
122
|
+
*.swp
|
123
|
+
*.swo
|
124
|
+
|
125
|
+
# OS
|
126
|
+
.DS_Store
|
127
|
+
Thumbs.db
|
128
|
+
|
129
|
+
# Logs
|
130
|
+
logs
|
131
|
+
*.log
|
132
|
+
|
133
|
+
# Runtime data
|
134
|
+
pids
|
135
|
+
*.pid
|
136
|
+
*.seed
|
137
|
+
*.pid.lock
|
138
|
+
|
139
|
+
# Coverage directory used by tools like istanbul
|
140
|
+
coverage/
|
141
|
+
|
142
|
+
# Firebase
|
143
|
+
.firebase/
|
144
|
+
firebase-debug.log
|
145
|
+
firestore-debug.log
|
146
|
+
ui-debug.log
|
147
|
+
|
148
|
+
# Temporary folders
|
149
|
+
tmp/
|
150
|
+
temp/
|
151
|
+
`.trim();
|
152
|
+
|
153
|
+
await fs.writeFile(path.join(projectPath, '.gitignore'), gitignoreContent);
|
154
|
+
}
|
155
|
+
|
156
|
+
private async createReadme(projectPath: string, projectName: string): Promise<void> {
|
157
|
+
const readmeContent = `# ${projectName}
|
158
|
+
|
159
|
+
A Node.js API project built with TypeScript and Firebase Functions.
|
160
|
+
|
161
|
+
## Features
|
162
|
+
|
163
|
+
- Express.js server with TypeScript
|
164
|
+
- Firebase Functions integration
|
165
|
+
- Socket.io for real-time communication
|
166
|
+
- MongoDB with Mongoose
|
167
|
+
- Authentication system
|
168
|
+
- Email notifications
|
169
|
+
- Cron jobs
|
170
|
+
- Audit logging
|
171
|
+
|
172
|
+
## Getting Started
|
173
|
+
|
174
|
+
1. Install dependencies:
|
175
|
+
\`\`\`bash
|
176
|
+
npm install
|
177
|
+
\`\`\`
|
178
|
+
|
179
|
+
2. Set up environment variables:
|
180
|
+
- Copy \`.env.example\` to \`.env\`
|
181
|
+
- Update the values according to your configuration
|
182
|
+
|
183
|
+
3. Start development server:
|
184
|
+
\`\`\`bash
|
185
|
+
npm run serve
|
186
|
+
\`\`\`
|
187
|
+
|
188
|
+
## Available Scripts
|
189
|
+
|
190
|
+
- \`npm run serve\` - Start development server
|
191
|
+
- \`npm run build:dev\` - Build for development
|
192
|
+
- \`npm run build:prod\` - Build for production
|
193
|
+
- \`npm run deploy\` - Deploy to Firebase
|
194
|
+
|
195
|
+
## Project Structure
|
196
|
+
|
197
|
+
\`\`\`
|
198
|
+
src/
|
199
|
+
├── config/ # Configuration files
|
200
|
+
├── controllers/ # Route controllers
|
201
|
+
├── entities/ # Database entities
|
202
|
+
├── helpers/ # Utility functions
|
203
|
+
├── routes/ # API routes
|
204
|
+
├── schemas/ # Validation schemas
|
205
|
+
├── server/ # Server setup
|
206
|
+
└── services/ # Business logic
|
207
|
+
\`\`\`
|
208
|
+
|
209
|
+
## Contributing
|
210
|
+
|
211
|
+
1. Fork the repository
|
212
|
+
2. Create a feature branch
|
213
|
+
3. Make your changes
|
214
|
+
4. Test thoroughly
|
215
|
+
5. Submit a pull request
|
216
|
+
|
217
|
+
## License
|
218
|
+
|
219
|
+
MIT
|
220
|
+
`;
|
221
|
+
|
222
|
+
await fs.writeFile(path.join(projectPath, 'README.md'), readmeContent);
|
223
|
+
}
|
224
|
+
}
|