@diagramers/cli 1.0.12 → 1.0.14
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/dist/commands/api.d.ts +3 -0
- package/dist/commands/api.d.ts.map +1 -0
- package/dist/commands/api.js +46 -0
- package/dist/commands/api.js.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/services/api-generator.d.ts +2 -0
- package/dist/services/api-generator.d.ts.map +1 -0
- package/dist/services/api-generator.js +387 -0
- package/dist/services/api-generator.js.map +1 -0
- package/dist/services/project-initializer.d.ts +2 -0
- package/dist/services/project-initializer.d.ts.map +1 -1
- package/dist/services/project-initializer.js +55 -0
- package/dist/services/project-initializer.js.map +1 -1
- package/dist/services/template-processor.d.ts +2 -0
- package/dist/services/template-processor.d.ts.map +1 -0
- package/dist/services/template-processor.js +162 -0
- package/dist/services/template-processor.js.map +1 -0
- package/package.json +1 -1
- package/src/commands/api.ts +42 -0
- package/src/index.ts +4 -0
- package/src/services/api-generator.ts +376 -0
- package/src/services/project-initializer.ts +64 -0
- package/src/services/template-processor.ts +161 -0
@@ -11,7 +11,9 @@ export interface InitOptions {
|
|
11
11
|
|
12
12
|
export class ProjectInitializer {
|
13
13
|
private templateFiles: string[] = [
|
14
|
+
'scripts',
|
14
15
|
'src/**/*',
|
16
|
+
'scripts/**/*',
|
15
17
|
'package.json',
|
16
18
|
'tsconfig.json',
|
17
19
|
'webpack.config.js',
|
@@ -50,6 +52,12 @@ export class ProjectInitializer {
|
|
50
52
|
// Create README
|
51
53
|
await this.createReadme(projectPath, projectName, templateType);
|
52
54
|
|
55
|
+
// Make scripts executable
|
56
|
+
await this.makeScriptsExecutable(projectPath);
|
57
|
+
|
58
|
+
// Process template for project name (update database names, etc.)
|
59
|
+
await this.processTemplate(projectPath, projectName);
|
60
|
+
|
53
61
|
// Clean up the temporary installation
|
54
62
|
await this.cleanup(projectPath);
|
55
63
|
|
@@ -137,6 +145,19 @@ export class ProjectInitializer {
|
|
137
145
|
if (packageJson.bin) {
|
138
146
|
delete packageJson.bin;
|
139
147
|
}
|
148
|
+
|
149
|
+
// Ensure CLI scripts are included
|
150
|
+
if (!packageJson.scripts) {
|
151
|
+
packageJson.scripts = {};
|
152
|
+
}
|
153
|
+
|
154
|
+
// Add CLI scripts if they don't exist
|
155
|
+
if (!packageJson.scripts['generate:module']) {
|
156
|
+
packageJson.scripts['generate:module'] = './scripts/generate-module.sh';
|
157
|
+
}
|
158
|
+
if (!packageJson.scripts['cli']) {
|
159
|
+
packageJson.scripts['cli'] = './scripts/cli-commands.sh';
|
160
|
+
}
|
140
161
|
|
141
162
|
await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
|
142
163
|
}
|
@@ -268,4 +289,47 @@ MIT
|
|
268
289
|
|
269
290
|
await fs.writeFile(path.join(projectPath, 'README.md'), readmeContent);
|
270
291
|
}
|
292
|
+
|
293
|
+
private async makeScriptsExecutable(projectPath: string): Promise<void> {
|
294
|
+
const scriptsDir = path.join(projectPath, 'scripts');
|
295
|
+
|
296
|
+
if (await fs.pathExists(scriptsDir)) {
|
297
|
+
try {
|
298
|
+
const scripts = await fs.readdir(scriptsDir);
|
299
|
+
for (const script of scripts) {
|
300
|
+
if (script.endsWith('.sh')) {
|
301
|
+
const scriptPath = path.join(scriptsDir, script);
|
302
|
+
// Make script executable (chmod 755)
|
303
|
+
await fs.chmod(scriptPath, 0o755);
|
304
|
+
console.log(chalk.blue(`🔧 Made executable: ${script}`));
|
305
|
+
}
|
306
|
+
}
|
307
|
+
} catch (error: any) {
|
308
|
+
console.log(chalk.yellow(`⚠️ Warning: Could not make scripts executable: ${error.message}`));
|
309
|
+
}
|
310
|
+
}
|
311
|
+
}
|
312
|
+
|
313
|
+
private async processTemplate(projectPath: string, projectName: string): Promise<void> {
|
314
|
+
try {
|
315
|
+
console.log(chalk.blue(`🔧 Processing template for project: ${projectName}`));
|
316
|
+
|
317
|
+
// Change to project directory
|
318
|
+
const originalCwd = process.cwd();
|
319
|
+
process.chdir(projectPath);
|
320
|
+
|
321
|
+
// Run the template processor
|
322
|
+
execSync(`npm run cli process:template ${projectName}`, {
|
323
|
+
stdio: 'inherit'
|
324
|
+
});
|
325
|
+
|
326
|
+
// Change back to original directory
|
327
|
+
process.chdir(originalCwd);
|
328
|
+
|
329
|
+
console.log(chalk.green(`✅ Template processed successfully`));
|
330
|
+
} catch (error: any) {
|
331
|
+
console.log(chalk.yellow(`⚠️ Warning: Could not process template: ${error.message}`));
|
332
|
+
console.log(chalk.yellow(` You can manually run: npm run cli process:template ${projectName}`));
|
333
|
+
}
|
334
|
+
}
|
271
335
|
}
|
@@ -0,0 +1,161 @@
|
|
1
|
+
import * as fs from 'fs';
|
2
|
+
import * as path from 'path';
|
3
|
+
|
4
|
+
export async function processTemplate(projectName: string): Promise<void> {
|
5
|
+
if (!projectName) {
|
6
|
+
throw new Error('Project name is required');
|
7
|
+
}
|
8
|
+
|
9
|
+
const currentDir = process.cwd();
|
10
|
+
|
11
|
+
// Check if we're in a diagramers API project
|
12
|
+
const packageJsonPath = path.join(currentDir, 'package.json');
|
13
|
+
if (!fs.existsSync(packageJsonPath)) {
|
14
|
+
throw new Error('package.json not found. Please run this command from a diagramers API project root.');
|
15
|
+
}
|
16
|
+
|
17
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
18
|
+
if (!packageJson.name?.includes('diagramers') && !packageJson.name?.includes('api')) {
|
19
|
+
throw new Error('This command should be run from a diagramers API project.');
|
20
|
+
}
|
21
|
+
|
22
|
+
// Convert project name to database-friendly format
|
23
|
+
const dbName = projectName
|
24
|
+
.toLowerCase()
|
25
|
+
.replace(/[^a-zA-Z0-9]/g, '_')
|
26
|
+
.replace(/_+/g, '_')
|
27
|
+
.replace(/^_|_$/g, '');
|
28
|
+
|
29
|
+
console.log(`🗄️ Database name will be: ${dbName}`);
|
30
|
+
|
31
|
+
// Process configuration files
|
32
|
+
console.log('📝 Updating configuration files...');
|
33
|
+
|
34
|
+
// Update development config
|
35
|
+
const devConfigPath = path.join(currentDir, 'src/config/development.ts');
|
36
|
+
if (fs.existsSync(devConfigPath)) {
|
37
|
+
let devConfig = fs.readFileSync(devConfigPath, 'utf8');
|
38
|
+
devConfig = devConfig.replace(
|
39
|
+
/mongodb:\/\/127\.0\.0\.1:27017\/[^,\s]+/g,
|
40
|
+
`mongodb://127.0.0.1:27017/${dbName}-development`
|
41
|
+
);
|
42
|
+
fs.writeFileSync(devConfigPath, devConfig);
|
43
|
+
console.log(' ✅ Updated development.ts');
|
44
|
+
}
|
45
|
+
|
46
|
+
// Update staging config
|
47
|
+
const stagingConfigPath = path.join(currentDir, 'src/config/staging.ts');
|
48
|
+
if (fs.existsSync(stagingConfigPath)) {
|
49
|
+
let stagingConfig = fs.readFileSync(stagingConfigPath, 'utf8');
|
50
|
+
stagingConfig = stagingConfig.replace(
|
51
|
+
/sendifier-staging/g,
|
52
|
+
`${dbName}-staging`
|
53
|
+
);
|
54
|
+
fs.writeFileSync(stagingConfigPath, stagingConfig);
|
55
|
+
console.log(' ✅ Updated staging.ts');
|
56
|
+
}
|
57
|
+
|
58
|
+
// Update production config
|
59
|
+
const prodConfigPath = path.join(currentDir, 'src/config/production.ts');
|
60
|
+
if (fs.existsSync(prodConfigPath)) {
|
61
|
+
let prodConfig = fs.readFileSync(prodConfigPath, 'utf8');
|
62
|
+
prodConfig = prodConfig.replace(
|
63
|
+
/sendifier-production/g,
|
64
|
+
`${dbName}-production`
|
65
|
+
);
|
66
|
+
fs.writeFileSync(prodConfigPath, prodConfig);
|
67
|
+
console.log(' ✅ Updated production.ts');
|
68
|
+
}
|
69
|
+
|
70
|
+
// Update package.json
|
71
|
+
let packageJsonContent = fs.readFileSync(packageJsonPath, 'utf8');
|
72
|
+
packageJsonContent = packageJsonContent.replace(
|
73
|
+
/"name":\s*"@diagramers\/api"/g,
|
74
|
+
`"name": "${projectName}"`
|
75
|
+
);
|
76
|
+
packageJsonContent = packageJsonContent.replace(
|
77
|
+
/"description":\s*"Diagramers API - A comprehensive Node\.js API template with TypeScript, Firebase Functions, and Socket\.io"/g,
|
78
|
+
`"description": "${projectName} - API project"`
|
79
|
+
);
|
80
|
+
fs.writeFileSync(packageJsonPath, packageJsonContent);
|
81
|
+
console.log(' ✅ Updated package.json');
|
82
|
+
|
83
|
+
// Update README.md
|
84
|
+
const readmePath = path.join(currentDir, 'README.md');
|
85
|
+
if (fs.existsSync(readmePath)) {
|
86
|
+
let readmeContent = fs.readFileSync(readmePath, 'utf8');
|
87
|
+
readmeContent = readmeContent.replace(
|
88
|
+
/# @diagramers\/api/g,
|
89
|
+
`# ${projectName}`
|
90
|
+
);
|
91
|
+
readmeContent = readmeContent.replace(
|
92
|
+
/A comprehensive Node\.js API template with TypeScript, Firebase Functions, and Socket\.io\./g,
|
93
|
+
`${projectName} - API project.`
|
94
|
+
);
|
95
|
+
fs.writeFileSync(readmePath, readmeContent);
|
96
|
+
console.log(' ✅ Updated README.md');
|
97
|
+
}
|
98
|
+
|
99
|
+
// Create .env file template
|
100
|
+
console.log('📄 Creating .env template...');
|
101
|
+
const envTemplate = generateEnvTemplate(dbName);
|
102
|
+
fs.writeFileSync(path.join(currentDir, '.env.example'), envTemplate);
|
103
|
+
|
104
|
+
console.log('✅ Template processing completed!');
|
105
|
+
console.log('');
|
106
|
+
console.log('📋 Summary:');
|
107
|
+
console.log(` Project Name: ${projectName}`);
|
108
|
+
console.log(` Database Name: ${dbName}`);
|
109
|
+
console.log(` Development DB: ${dbName}-development`);
|
110
|
+
console.log(` Staging DB: ${dbName}-staging`);
|
111
|
+
console.log(` Production DB: ${dbName}-production`);
|
112
|
+
console.log('');
|
113
|
+
console.log('🚀 Next steps:');
|
114
|
+
console.log(' 1. Copy .env.example to .env and configure your environment variables');
|
115
|
+
console.log(' 2. Install dependencies: npm install');
|
116
|
+
console.log(' 3. Build the project: npm run build:dev');
|
117
|
+
console.log(' 4. Start the server: npm run serve');
|
118
|
+
}
|
119
|
+
|
120
|
+
function generateEnvTemplate(dbName: string): string {
|
121
|
+
return `# Environment Configuration
|
122
|
+
NODE_ENV=development
|
123
|
+
|
124
|
+
# Server Configuration
|
125
|
+
PORT=4000
|
126
|
+
HOST=localhost
|
127
|
+
|
128
|
+
# Database Configuration
|
129
|
+
MONGODB_URI=mongodb://127.0.0.1:27017/${dbName}-development
|
130
|
+
|
131
|
+
# Firebase Configuration
|
132
|
+
FIREBASE_API_KEY=your-api-key
|
133
|
+
FIREBASE_AUTH_DOMAIN=your-project.firebaseapp.com
|
134
|
+
FIREBASE_PROJECT_ID=your-project-id
|
135
|
+
FIREBASE_STORAGE_BUCKET=your-project.appspot.com
|
136
|
+
FIREBASE_MESSAGING_SENDER_ID=your-sender-id
|
137
|
+
FIREBASE_APP_ID=your-app-id
|
138
|
+
|
139
|
+
# JWT Configuration
|
140
|
+
JWT_SECRET=your-jwt-secret-key
|
141
|
+
|
142
|
+
# Twilio Configuration (for SMS)
|
143
|
+
TWILIO_ACCOUNT_SID=your-account-sid
|
144
|
+
TWILIO_AUTH_TOKEN=your-auth-token
|
145
|
+
|
146
|
+
# Email Configuration
|
147
|
+
SMTP_HOST=smtp.gmail.com
|
148
|
+
SMTP_PORT=587
|
149
|
+
SMTP_USER=your-email@gmail.com
|
150
|
+
SMTP_PASS=your-app-password
|
151
|
+
|
152
|
+
# Internal API Configuration
|
153
|
+
INTERNAL_REQUEST_HEADER_VALUE=your-secret-header-value
|
154
|
+
|
155
|
+
# Optional Configuration
|
156
|
+
BASE_SITE_URL=http://localhost:3000
|
157
|
+
LOCAL_API_TUNNEL_URL=https://your-ngrok-url.ngrok-free.app
|
158
|
+
LOCAL_UI_TUNNEL_URL=https://your-ui-ngrok-url.ngrok-free.app
|
159
|
+
BACKUP_DATABASES_FOLDER_PATH=/path/to/backup/folder
|
160
|
+
EXTERNAL_HTTP_REQUEST_TIMEOUT=5000`;
|
161
|
+
}
|