create-souro-api 1.0.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.
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,154 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const commander_1 = require("commander");
8
+ const inquirer_1 = __importDefault(require("inquirer"));
9
+ const chalk_1 = __importDefault(require("chalk"));
10
+ const ora_1 = __importDefault(require("ora"));
11
+ const execa_1 = require("execa");
12
+ const fs_extra_1 = __importDefault(require("fs-extra"));
13
+ const path_1 = __importDefault(require("path"));
14
+ const REPO_URL = 'https://github.com/CoulibalySourouga/node-api-boilerplate.git';
15
+ const program = new commander_1.Command();
16
+ program
17
+ .name('create-souro-api')
18
+ .description('CLI to Generate a production-ready Node.js REST API boilerplate')
19
+ .argument('[project-name]', 'Name of the project')
20
+ .action(async (projectName) => {
21
+ await run(projectName);
22
+ });
23
+ program.parse();
24
+ async function run(projectName) {
25
+ console.log(chalk_1.default.bold.cyan('\n🚀 Create Souro API\n'));
26
+ // 1. Demander le nom du projet si non fourni
27
+ if (!projectName) {
28
+ const answer = await inquirer_1.default.prompt([
29
+ {
30
+ type: 'input',
31
+ name: 'projectName',
32
+ message: 'Project name:',
33
+ default: 'my-api',
34
+ },
35
+ ]);
36
+ projectName = answer.projectName;
37
+ }
38
+ const targetDir = path_1.default.join(process.cwd(), projectName);
39
+ // 2. Vérifier si le dossier existe déjà
40
+ if (fs_extra_1.default.existsSync(targetDir)) {
41
+ console.log(chalk_1.default.red(`\n❌ Folder "${projectName}" already exists.\n`));
42
+ process.exit(1);
43
+ }
44
+ // 3. Poser les questions de configuration
45
+ const config = await inquirer_1.default.prompt([
46
+ {
47
+ type: 'confirm',
48
+ name: 'includeAI',
49
+ message: 'Include AI integration (OpenAI/Anthropic)?',
50
+ default: true,
51
+ },
52
+ {
53
+ type: 'confirm',
54
+ name: 'includeDocker',
55
+ message: 'Include Docker setup?',
56
+ default: true,
57
+ },
58
+ {
59
+ type: 'confirm',
60
+ name: 'initGit',
61
+ message: 'Initialize a new git repository?',
62
+ default: true,
63
+ },
64
+ {
65
+ type: 'confirm',
66
+ name: 'installDeps',
67
+ message: 'Install dependencies now?',
68
+ default: true,
69
+ },
70
+ ]);
71
+ await scaffold(projectName, targetDir, config);
72
+ async function scaffold(projectName, targetDir, config) {
73
+ // 1. Cloner le repo
74
+ const spinner = (0, ora_1.default)('Cloning boilerplate...').start();
75
+ try {
76
+ await (0, execa_1.execa)('git', ['clone', '--depth=1', REPO_URL, targetDir]);
77
+ spinner.succeed('Boilerplate cloned');
78
+ }
79
+ catch (error) {
80
+ spinner.fail('Failed to clone repository');
81
+ console.error(error);
82
+ process.exit(1);
83
+ }
84
+ // 2. Supprimer le .git cloné (on repart propre)
85
+ await fs_extra_1.default.remove(path_1.default.join(targetDir, '.git'));
86
+ // 3. Supprimer Docker si non désiré
87
+ if (!config.includeDocker) {
88
+ await fs_extra_1.default.remove(path_1.default.join(targetDir, 'Dockerfile'));
89
+ await fs_extra_1.default.remove(path_1.default.join(targetDir, 'docker-compose.yml'));
90
+ }
91
+ // 4. Générer le fichier .env
92
+ await generateEnvFile(targetDir, config);
93
+ // 5. Initialiser git
94
+ if (config.initGit) {
95
+ const gitSpinner = (0, ora_1.default)('Initializing git repository...').start();
96
+ await (0, execa_1.execa)('git', ['init'], { cwd: targetDir });
97
+ gitSpinner.succeed('Git repository initialized');
98
+ }
99
+ // 6. Installer les dépendances
100
+ if (config.installDeps) {
101
+ const installSpinner = (0, ora_1.default)('Installing dependencies (this may take a minute)...').start();
102
+ try {
103
+ await (0, execa_1.execa)('npm', ['install'], { cwd: targetDir });
104
+ installSpinner.succeed('Dependencies installed');
105
+ }
106
+ catch (error) {
107
+ installSpinner.fail('Failed to install dependencies');
108
+ console.log(chalk_1.default.yellow('You can install them manually with: npm install'));
109
+ }
110
+ }
111
+ // 7. Message final
112
+ printSuccessMessage(projectName, config);
113
+ }
114
+ async function generateEnvFile(targetDir, config) {
115
+ const envContent = `# Server
116
+ PORT=3000
117
+ NODE_ENV=development
118
+
119
+ # Database
120
+ DATABASE_URL="postgresql://admin:password@localhost:5432/${path_1.default.basename(targetDir)}"
121
+ POSTGRES_PASSWORD=password
122
+
123
+ # JWT
124
+ JWT_SECRET=change_this_secret_key
125
+ JWT_REFRESH_SECRET=change_this_refresh_secret
126
+ JWT_EXPIRES_IN=15m
127
+ JWT_REFRESH_EXPIRES_IN=7d
128
+
129
+ # AI Provider (mock | openai | anthropic)
130
+ AI_PROVIDER=${config.includeAI ? 'mock' : 'mock'}
131
+ OPENAI_API_KEY=your_openai_key_here
132
+ ANTHROPIC_API_KEY=your_anthropic_key_here
133
+ `;
134
+ await fs_extra_1.default.writeFile(path_1.default.join(targetDir, '.env'), envContent);
135
+ await fs_extra_1.default.writeFile(path_1.default.join(targetDir, '.env.example'), envContent);
136
+ }
137
+ function printSuccessMessage(projectName, config) {
138
+ console.log(chalk_1.default.bold.green('\nâś… Project created successfully!\n'));
139
+ console.log(chalk_1.default.bold('Next steps:\n'));
140
+ console.log(chalk_1.default.cyan(` cd ${projectName}`));
141
+ if (!config.installDeps) {
142
+ console.log(chalk_1.default.cyan(' npm install'));
143
+ }
144
+ if (config.includeDocker) {
145
+ console.log(chalk_1.default.cyan(' docker-compose up --build'));
146
+ }
147
+ else {
148
+ console.log(chalk_1.default.cyan(' npx prisma migrate dev'));
149
+ console.log(chalk_1.default.cyan(' npx ts-node src/index.ts'));
150
+ }
151
+ console.log(chalk_1.default.gray('\nđź“„ Docs: http://localhost:3000/api/docs'));
152
+ console.log(chalk_1.default.gray('🤖 AI Provider is set to "mock" by default — update AI_PROVIDER in .env\n'));
153
+ }
154
+ }
package/package.json ADDED
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "create-souro-api",
3
+ "version": "1.0.0",
4
+ "description": "CLI to scaffold a production-ready Node.js REST API boilerplate",
5
+ "bin": {
6
+ "create-souro-api": "./dist/index.js"
7
+ },
8
+ "main": "dist/index.js",
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "dev": "ts-node src/index.ts"
12
+ },
13
+ "files": [
14
+ "dist"
15
+ ],
16
+ "keywords": ["nodejs", "boilerplate", "cli", "typescript", "prisma", "jwt"],
17
+ "license": "MIT"
18
+ }