@bayajidalam/apollo-cli 1.0.3 → 1.0.4

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,10 @@
1
+ {
2
+ "bracketSpacing": true,
3
+ "endOfLine": "lf",
4
+ "plugins": ["prettier-plugin-organize-imports", "prettier-plugin-sort-json"],
5
+ "printWidth": 80,
6
+ "semi": true,
7
+ "singleQuote": true,
8
+ "tabWidth": 2,
9
+ "trailingComma": "es5"
10
+ }
package/README.md CHANGED
@@ -21,17 +21,19 @@ apollo-cli init my-new-project
21
21
  ```
22
22
 
23
23
  During init, the CLI:
24
- - Fetches the latest versions of all dependencies from npm
25
- - Creates a `prisma/schema.prisma` file and `prisma` folder
26
- - Lets you choose npm, yarn, or pnpm for installation
24
+
25
+ - **Latest Dependencies**: Fetches the latest versions of all packages from npm.
26
+ - **Database Setup**: Configures Prisma with PostgreSQL adapter (`@prisma/adapter-pg`) for optimized connection pooling.
27
+ - **Strict TypeScript**: Generates a strict `tsconfig.json` for type safety.
28
+ - **Structure**: Creates a modular `src` folder structure with `modules`, `middlewares`, `routes`, `utils`, `errors`, `config`, and `lib`.
27
29
 
28
30
  ### 2. Generate Modules
29
31
 
30
32
  Scaffold a new module (Controller, Service, Route, Interface, Validation, Constants) instantly.
31
33
 
32
- **Alias**: `g`
34
+ **Alias**:
33
35
 
34
- **Important:** You must run this command *inside* your project directory.
36
+ **Important:** You must run this command _inside_ your project directory.
35
37
 
36
38
  ```bash
37
39
  cd my-new-project
@@ -42,7 +44,8 @@ apollo-cli generate module User
42
44
  apollo-cli g module User
43
45
  ```
44
46
 
45
- This will create `src/app/modules/User` with:
47
+ This will create `src/modules/User` with:
48
+
46
49
  - `user.controller.ts`: Request handlers
47
50
  - `user.service.ts`: Business logic
48
51
  - `user.route.ts`: Express routes
@@ -50,6 +53,8 @@ This will create `src/app/modules/User` with:
50
53
  - `user.validation.ts`: Zod validation schemas
51
54
  - `user.constant.ts`: Module constants
52
55
 
56
+ The module will be automatically placed in `src/modules/User` (capitalized).
57
+
53
58
  ### 3. Build for Production
54
59
 
55
60
  Builds your TypeScript application to the `dist` folder.
package/dist/bin/index.js CHANGED
@@ -5,20 +5,43 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  };
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
7
  const commander_1 = require("commander");
8
- const generate_1 = require("../commands/generate");
9
8
  const build_1 = require("../commands/build");
10
- const prisma_1 = require("../commands/prisma");
9
+ const generate_1 = require("../commands/generate");
11
10
  const init_1 = require("../commands/init");
11
+ const prisma_1 = require("../commands/prisma");
12
+ // Set up the main CLI program
12
13
  const program = new commander_1.Command();
14
+ const chalk_1 = __importDefault(require("chalk"));
15
+ const figlet_1 = __importDefault(require("figlet"));
13
16
  const fs_1 = __importDefault(require("fs"));
14
17
  const path_1 = __importDefault(require("path"));
18
+ // Read package.json to get version and description
15
19
  const packageJsonPath = path_1.default.join(__dirname, '../../package.json');
16
20
  const packageJson = JSON.parse(fs_1.default.readFileSync(packageJsonPath, 'utf-8'));
17
21
  program
18
22
  .version(packageJson.version)
19
- .description('Apollo CLI Tool');
23
+ .description('Apollo CLI Tool')
24
+ .addHelpText('beforeAll', chalk_1.default.cyan(figlet_1.default.textSync('Apollo CLI', { horizontalLayout: 'full' })) +
25
+ '\n')
26
+ .configureHelp({
27
+ subcommandTerm: (cmd) => chalk_1.default.magenta.bold(cmd.name()),
28
+ subcommandDescription: (cmd) => chalk_1.default.white(cmd.description()),
29
+ optionTerm: (option) => chalk_1.default.green(option.flags),
30
+ optionDescription: (option) => chalk_1.default.white(option.description),
31
+ commandUsage: (cmd) => chalk_1.default.yellow(cmd.usage()),
32
+ commandDescription: (cmd) => chalk_1.default.blue(cmd.description()),
33
+ })
34
+ .addHelpText('after', `
35
+ ${chalk_1.default.yellow('Global Examples:')}
36
+ ${chalk_1.default.cyan('$ apollo-cli init my-project')}
37
+ ${chalk_1.default.cyan('$ apollo-cli generate module user')}
38
+ ${chalk_1.default.cyan('$ apollo-cli prisma migrate')}
39
+ ${chalk_1.default.cyan('$ apollo-cli build')}
40
+ `);
41
+ // Register available commands
20
42
  program.addCommand(generate_1.generateCommand);
21
43
  program.addCommand(build_1.buildCommand);
22
44
  program.addCommand(prisma_1.prismaCommand);
23
45
  program.addCommand(init_1.initCommand);
46
+ // Parse command line arguments
24
47
  program.parse(process.argv);
@@ -4,27 +4,31 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.buildCommand = void 0;
7
- const commander_1 = require("commander");
7
+ const chalk_1 = __importDefault(require("chalk"));
8
8
  const child_process_1 = require("child_process");
9
+ const commander_1 = require("commander");
9
10
  const fs_extra_1 = __importDefault(require("fs-extra"));
10
11
  const path_1 = __importDefault(require("path"));
11
- const chalk_1 = __importDefault(require("chalk"));
12
12
  exports.buildCommand = new commander_1.Command('build')
13
13
  .description('Build the application for production')
14
+ .addHelpText('after', `
15
+ ${chalk_1.default.yellow('Examples:')}
16
+ ${chalk_1.default.cyan('$ apollo-cli build')}
17
+ `)
14
18
  .action(async () => {
15
- console.log(chalk_1.default.blue('🚀 Starting build process...'));
19
+ console.log(chalk_1.default.blue('\n🚀 Starting build process...\n'));
16
20
  try {
17
- // 1. Clean dist folder
21
+ // Clean up the dist folder before starting a fresh build
18
22
  const distPath = path_1.default.join(process.cwd(), 'dist');
19
23
  if (fs_extra_1.default.existsSync(distPath)) {
20
- console.log(chalk_1.default.yellow('🧹 Cleaning dist folder...'));
24
+ console.log(chalk_1.default.yellow('🧹 Cleaning dist folder...\n'));
21
25
  await fs_extra_1.default.remove(distPath);
22
26
  }
23
- // 2. Run TypeScript Compiler
24
- console.log(chalk_1.default.blue('🔨 Compiling TypeScript...'));
27
+ // Compile the TypeScript code using the local tsc binary
28
+ console.log(chalk_1.default.blue('🔨 Compiling TypeScript...\n'));
25
29
  (0, child_process_1.execSync)('npx tsc', { stdio: 'inherit' });
26
- // 3. Copy Key Files
27
- console.log(chalk_1.default.blue('📂 Copying static files...'));
30
+ // Copy essential files like package.json and .env to the dist folder
31
+ console.log(chalk_1.default.blue('\n📂 Copying static files...\n'));
28
32
  const filesToCopy = ['package.json', 'package-lock.json', '.env'];
29
33
  for (const file of filesToCopy) {
30
34
  const srcPath = path_1.default.join(process.cwd(), file);
@@ -32,12 +36,12 @@ exports.buildCommand = new commander_1.Command('build')
32
36
  await fs_extra_1.default.copy(srcPath, path_1.default.join(distPath, file));
33
37
  }
34
38
  }
35
- console.log(chalk_1.default.green('\n✅ Build completed successfully!'));
39
+ console.log(chalk_1.default.green('\n✅ Build completed successfully! ✨\n'));
36
40
  console.log(chalk_1.default.white('To deploy, upload the "dist" folder and run:'));
37
- console.log(chalk_1.default.cyan('npm install --production'));
41
+ console.log(chalk_1.default.cyan('npm install --production\n'));
38
42
  }
39
43
  catch (error) {
40
- console.error(chalk_1.default.red('❌ Build failed:'), error);
44
+ console.error(chalk_1.default.red('\n❌ Build failed:'), error);
41
45
  process.exit(1);
42
46
  }
43
47
  });
@@ -4,61 +4,84 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.generateCommand = void 0;
7
+ const chalk_1 = __importDefault(require("chalk"));
7
8
  const commander_1 = require("commander");
8
9
  const inquirer_1 = __importDefault(require("inquirer"));
9
10
  const path_1 = __importDefault(require("path"));
10
- const generator_1 = require("../utils/generator");
11
+ const file_generator_1 = require("../utils/file-generator");
11
12
  exports.generateCommand = new commander_1.Command('generate')
12
13
  .alias('g')
13
14
  .description('Generate a new resource')
14
15
  .argument('[type]', 'Type of resource to generate (e.g., module)')
15
16
  .argument('[name]', 'Name of the resource')
17
+ .addHelpText('after', `
18
+ ${chalk_1.default.yellow('Examples:')}
19
+ ${chalk_1.default.cyan('$ apollo-cli generate module user')}
20
+ ${chalk_1.default.cyan('$ apollo-cli g module product')}
21
+ `)
16
22
  .action(async (type, name) => {
17
- // 1. Validate Input
18
23
  if (!type) {
19
- const answers = await inquirer_1.default.prompt([{
24
+ const answers = await inquirer_1.default.prompt([
25
+ {
20
26
  type: 'list',
21
27
  name: 'type',
22
- message: 'What would you like to generate?',
23
- choices: ['module']
24
- }]);
28
+ message: chalk_1.default.blue('What would you like to generate?'),
29
+ choices: ['module'],
30
+ },
31
+ ]);
25
32
  type = answers.type;
26
33
  }
27
34
  if (type !== 'module') {
28
- console.error('Only "module" generation is currently supported.');
35
+ console.error(chalk_1.default.red('Only "module" generation is currently supported.'));
29
36
  return;
30
37
  }
31
38
  if (!name) {
32
- const answers = await inquirer_1.default.prompt([{
39
+ const answers = await inquirer_1.default.prompt([
40
+ {
33
41
  type: 'input',
34
42
  name: 'name',
35
- message: 'What is the name of the module?',
36
- validate: (input) => input.trim() !== '' ? 'Module name is required' : true
37
- }]);
43
+ message: chalk_1.default.blue('What is the name of the module?'),
44
+ validate: (input) => input.trim() === '' ? 'Module name is required' : true,
45
+ },
46
+ ]);
38
47
  name = answers.name;
39
48
  }
40
49
  const moduleNameRaw = name.trim();
41
- // 2. Format Casing
42
50
  const capitalize = (s) => s.charAt(0).toUpperCase() + s.slice(1);
43
51
  const camelize = (s) => s.charAt(0).toLowerCase() + s.slice(1);
44
52
  const moduleNamePascal = capitalize(moduleNameRaw);
45
53
  const moduleNameCamel = camelize(moduleNameRaw);
46
- console.log(`Generating module: ${moduleNamePascal}...`);
47
- // 3. Define Output Paths
48
- // Assume we are in the project root
49
- const baseDir = path_1.default.join(process.cwd(), 'src/app/modules', moduleNamePascal);
50
- // 4. Generate Files
54
+ console.log(chalk_1.default.cyan(`\n🚀 Generating module: ${chalk_1.default.bold(moduleNamePascal)}...\n`));
55
+ // Assumes the command is run from the project root
56
+ const baseDir = path_1.default.join(process.cwd(), 'src/modules', moduleNamePascal);
51
57
  const files = [
52
- { template: 'module/controller.ejs', output: `${moduleNameCamel}.controller.ts` },
53
- { template: 'module/service.ejs', output: `${moduleNameCamel}.service.ts` },
58
+ {
59
+ template: 'module/controller.ejs',
60
+ output: `${moduleNameCamel}.controller.ts`,
61
+ },
62
+ {
63
+ template: 'module/service.ejs',
64
+ output: `${moduleNameCamel}.service.ts`,
65
+ },
54
66
  { template: 'module/route.ejs', output: `${moduleNameCamel}.route.ts` },
55
- { template: 'module/interface.ejs', output: `${moduleNameCamel}.interface.ts` },
56
- { template: 'module/validation.ejs', output: `${moduleNameCamel}.validation.ts` },
57
- { template: 'module/constant.ejs', output: `${moduleNameCamel}.constant.ts` },
67
+ {
68
+ template: 'module/interface.ejs',
69
+ output: `${moduleNameCamel}.interface.ts`,
70
+ },
71
+ {
72
+ template: 'module/validation.ejs',
73
+ output: `${moduleNameCamel}.validation.ts`,
74
+ },
75
+ {
76
+ template: 'module/constant.ejs',
77
+ output: `${moduleNameCamel}.constant.ts`,
78
+ },
58
79
  ];
59
80
  for (const file of files) {
60
- await (0, generator_1.renderTemplate)(file.template, path_1.default.join(baseDir, file.output), { moduleName: moduleNamePascal, camelModuleName: moduleNameCamel });
81
+ await (0, file_generator_1.renderTemplate)(file.template, path_1.default.join(baseDir, file.output), {
82
+ moduleName: moduleNamePascal,
83
+ camelModuleName: moduleNameCamel,
84
+ });
61
85
  }
62
- // 5. Success Message
63
- console.log('\nModule generated successfully! 🚀');
86
+ console.log(chalk_1.default.green('\n✨ Module generated successfully! 🚀\n'));
64
87
  });
@@ -4,18 +4,19 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.initCommand = void 0;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const child_process_1 = require("child_process");
7
9
  const commander_1 = require("commander");
8
- const inquirer_1 = __importDefault(require("inquirer"));
9
10
  const fs_extra_1 = __importDefault(require("fs-extra"));
11
+ const inquirer_1 = __importDefault(require("inquirer"));
10
12
  const path_1 = __importDefault(require("path"));
11
- const chalk_1 = __importDefault(require("chalk"));
12
- const child_process_1 = require("child_process");
13
+ const file_generator_1 = require("../utils/file-generator");
13
14
  // Helper function to get the latest version of a package from npm
14
15
  async function getLatestVersion(packageName) {
15
16
  try {
16
17
  const version = (0, child_process_1.execSync)(`npm view ${packageName} version`, {
17
18
  encoding: 'utf-8',
18
- stdio: ['pipe', 'pipe', 'pipe']
19
+ stdio: ['pipe', 'pipe', 'pipe'],
19
20
  }).trim();
20
21
  return `^${version}`;
21
22
  }
@@ -27,22 +28,47 @@ async function getLatestVersion(packageName) {
27
28
  // Fetch latest versions for all dependencies
28
29
  async function getLatestDependencies() {
29
30
  console.log(chalk_1.default.blue('📦 Fetching latest package versions...'));
30
- const deps = ['express', 'cors', 'dotenv', 'http-status', '@prisma/client'];
31
- const devDeps = ['typescript', 'ts-node-dev', '@types/node', '@types/express', '@types/cors', 'prisma', 'eslint', 'prettier'];
31
+ const deps = [
32
+ 'express',
33
+ 'cors',
34
+ 'dotenv',
35
+ 'http-status',
36
+ '@prisma/client',
37
+ '@prisma/adapter-pg',
38
+ 'pg',
39
+ 'zod',
40
+ 'bcrypt',
41
+ 'jsonwebtoken',
42
+ 'cookie-parser',
43
+ ];
44
+ const devDeps = [
45
+ 'typescript',
46
+ 'ts-node-dev',
47
+ '@types/node',
48
+ '@types/express',
49
+ '@types/cookie-parser',
50
+ '@types/bcrypt',
51
+ '@types/jsonwebtoken',
52
+ '@types/pg',
53
+ '@types/cors',
54
+ 'prisma',
55
+ 'eslint',
56
+ 'prettier',
57
+ ];
32
58
  const [dependencies, devDependencies] = await Promise.all([
33
59
  Promise.all(deps.map(async (dep) => [dep, await getLatestVersion(dep)])),
34
- Promise.all(devDeps.map(async (dep) => [dep, await getLatestVersion(dep)]))
60
+ Promise.all(devDeps.map(async (dep) => [dep, await getLatestVersion(dep)])),
35
61
  ]);
36
62
  return {
37
63
  dependencies: Object.fromEntries(dependencies),
38
- devDependencies: Object.fromEntries(devDependencies)
64
+ devDependencies: Object.fromEntries(devDependencies),
39
65
  };
40
66
  }
41
67
  // Detect available package managers
42
68
  function detectPackageManagers() {
43
69
  const all = ['npm', 'pnpm', 'yarn'];
44
70
  const available = [];
45
- all.forEach(pm => {
71
+ all.forEach((pm) => {
46
72
  try {
47
73
  (0, child_process_1.execSync)(`${pm} --version`, { stdio: 'ignore' });
48
74
  available.push(pm);
@@ -66,8 +92,13 @@ function isPackageManagerInstalled(pm) {
66
92
  exports.initCommand = new commander_1.Command('init')
67
93
  .description('Initialize a new Apollo Gears project')
68
94
  .argument('[projectName]', 'Name of the project directory')
95
+ .addHelpText('after', `
96
+ ${chalk_1.default.yellow('Examples:')}
97
+ ${chalk_1.default.cyan('$ apollo-cli init my-backend-project')}
98
+ ${chalk_1.default.cyan('$ apollo-cli init')}
99
+ `)
69
100
  .action(async (projectName) => {
70
- // 1. Prompt for Project Name if missing
101
+ // Prompt for Project Name if missing
71
102
  if (!projectName) {
72
103
  const answers = await inquirer_1.default.prompt([
73
104
  {
@@ -75,8 +106,8 @@ exports.initCommand = new commander_1.Command('init')
75
106
  name: 'name',
76
107
  message: 'What is the name of your project?',
77
108
  default: 'my-apollo-app',
78
- validate: (input) => input.trim() !== '' ? true : 'Project name is required'
79
- }
109
+ validate: (input) => input.trim() !== '' ? true : 'Project name is required',
110
+ },
80
111
  ]);
81
112
  projectName = answers.name;
82
113
  }
@@ -85,158 +116,70 @@ exports.initCommand = new commander_1.Command('init')
85
116
  console.error(chalk_1.default.red(`Error: Directory "${projectName}" already exists.`));
86
117
  process.exit(1);
87
118
  }
88
- console.log(chalk_1.default.blue(`\n🚀 Initializing project in ${projectRoot}...\n`));
119
+ console.log(chalk_1.default.blue(`\n🚀 Initializing project: ${chalk_1.default.bold(projectName)}...\n`));
89
120
  try {
90
- // 2. Create Directory
121
+ // Create project directory
91
122
  await fs_extra_1.default.ensureDir(projectRoot);
92
- // 3. Fetch latest versions
123
+ // Fetch latest versions of dependencies
93
124
  const { dependencies, devDependencies } = await getLatestDependencies();
94
- // 4. Create Package.json
95
- const packageJson = {
96
- name: projectName,
97
- version: "1.0.0",
98
- description: "Backend project generated by Apollo Gears CLI",
99
- main: "dist/server.js",
100
- scripts: {
101
- "start": "node dist/server.js",
102
- "dev": "ts-node-dev --respawn --transpile-only src/server.ts",
103
- "build": "tsc",
104
- "lint": "eslint src/**/*.ts",
105
- "lint:fix": "eslint src/**/*.ts --fix",
106
- "format": "prettier --write ."
107
- },
108
- keywords: ["express", "prisma", "typescript", "apollo-gears"],
109
- author: "",
110
- license: "ISC",
111
- dependencies,
112
- devDependencies
113
- };
114
- await fs_extra_1.default.writeJson(path_1.default.join(projectRoot, 'package.json'), packageJson, { spaces: 2 });
115
- // 5. Create tsconfig.json
116
- const tsconfig = {
117
- "compilerOptions": {
118
- "target": "ES2021",
119
- "module": "commonjs",
120
- "moduleResolution": "node",
121
- "outDir": "./dist",
122
- "rootDir": "./src",
123
- "strict": true,
124
- "esModuleInterop": true,
125
- "skipLibCheck": true,
126
- "forceConsistentCasingInFileNames": true
127
- },
128
- "include": ["src/**/*"],
129
- "exclude": ["node_modules"]
130
- };
131
- await fs_extra_1.default.writeJson(path_1.default.join(projectRoot, 'tsconfig.json'), tsconfig, { spaces: 2 });
132
- // 6. Create Scaffolding Folders
125
+ // Create Package.json
126
+ await (0, file_generator_1.writePackageJson)(projectRoot, projectName, dependencies, devDependencies);
127
+ // Create tsconfig.json
128
+ await (0, file_generator_1.writeTsConfig)(projectRoot);
129
+ // Create scaffolding folders
133
130
  const folders = [
134
- 'src/app/modules',
135
- 'src/app/middlewares',
136
- 'src/app/routes',
137
- 'src/app/utils',
138
- 'src/app/errors',
139
- 'src/app/config',
140
- 'prisma'
131
+ 'src/modules',
132
+ 'src/middlewares',
133
+ 'src/routes',
134
+ 'src/utils',
135
+ 'src/errors',
136
+ 'src/config',
137
+ 'src/lib',
141
138
  ];
139
+ console.log(chalk_1.default.blue('📂 Creating project structure...'));
142
140
  for (const folder of folders) {
143
141
  await fs_extra_1.default.ensureDir(path_1.default.join(projectRoot, folder));
144
142
  }
145
- // 7. Create Essential Files
146
- // src/server.ts
147
- const serverContent = `import app from './app';
148
- import config from './app/config';
149
-
150
- async function main() {
151
- try {
152
- app.listen(config.port, () => {
153
- console.log(\`Example app listening on port \${config.port}\`);
154
- });
155
- } catch (err) {
156
- console.log(err);
157
- }
158
- }
159
-
160
- main();`;
161
- await fs_extra_1.default.writeFile(path_1.default.join(projectRoot, 'src/server.ts'), serverContent);
162
- // src/app.ts
163
- const appContent = `import express, { Application, Request, Response } from 'express';
164
- import cors from 'cors';
165
-
166
- const app: Application = express();
167
-
168
- // parsers
169
- app.use(express.json());
170
- app.use(cors());
171
-
172
- // application routes
173
- // app.use('/api/v1', router);
174
-
175
- app.get('/', (req: Request, res: Response) => {
176
- res.send('Hello from Apollo Gears World!');
177
- });
178
-
179
- export default app;`;
180
- await fs_extra_1.default.writeFile(path_1.default.join(projectRoot, 'src/app.ts'), appContent);
181
- // src/app/config/index.ts
182
- const configContent = `import dotenv from 'dotenv';
183
- import path from 'path';
184
-
185
- dotenv.config({ path: path.join(process.cwd(), '.env') });
186
-
187
- export default {
188
- port: process.env.PORT,
189
- database_url: process.env.DATABASE_URL,
190
- };`;
191
- await fs_extra_1.default.writeFile(path_1.default.join(projectRoot, 'src/app/config/index.ts'), configContent);
192
- // .env
193
- const envContent = `PORT=5000
194
- DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public"`;
195
- await fs_extra_1.default.writeFile(path_1.default.join(projectRoot, '.env'), envContent);
196
- // prisma/schema.prisma
197
- const prismaSchemaContent = `generator client {
198
- provider = "prisma-client-js"
199
- }
200
-
201
- datasource db {
202
- provider = "postgresql"
203
- url = env("DATABASE_URL")
204
- }
205
-
206
- model User {
207
- id String @id @default(uuid())
208
- email String @unique
209
- name String?
210
- createdAt DateTime @default(now())
211
- updatedAt DateTime @updatedAt
212
- }`;
213
- await fs_extra_1.default.writeFile(path_1.default.join(projectRoot, 'prisma/schema.prisma'), prismaSchemaContent);
214
- // .gitignore
215
- const gitignoreContent = `node_modules
216
- dist
217
- .env`;
218
- await fs_extra_1.default.writeFile(path_1.default.join(projectRoot, '.gitignore'), gitignoreContent);
219
- console.log(chalk_1.default.green('\n✅ Project structure created successfully!'));
220
- // 8. Package Manager & Install Dependencies Prompt
143
+ // Initialize Prisma
144
+ console.log(chalk_1.default.blue('\n🔄 Initializing Prisma...\n'));
145
+ try {
146
+ (0, child_process_1.execSync)('npx prisma init --datasource-provider postgresql --output ../generated/prisma', {
147
+ cwd: projectRoot,
148
+ stdio: 'inherit',
149
+ });
150
+ }
151
+ catch (error) {
152
+ // Ignore if it fails (e.g., if files already exist)
153
+ }
154
+ // Create essential project files
155
+ await (0, file_generator_1.writeServerFile)(projectRoot);
156
+ await (0, file_generator_1.writeAppFile)(projectRoot);
157
+ await (0, file_generator_1.writeConfigFile)(projectRoot);
158
+ await (0, file_generator_1.writeEnvFile)(projectRoot);
159
+ await (0, file_generator_1.writePrismaSchema)(projectRoot);
160
+ await (0, file_generator_1.writeGitIgnore)(projectRoot);
161
+ await (0, file_generator_1.writePrismaFile)(projectRoot);
162
+ console.log(chalk_1.default.green('\n✅ Project structure created successfully! ✨'));
163
+ // Prompt for package manager selection and installation
221
164
  const { available, all } = detectPackageManagers();
222
- const pmChoices = all.map(pm => ({
165
+ const pmChoices = all.map((pm) => ({
223
166
  name: available.includes(pm) ? `${pm} ✓` : `${pm} (not installed)`,
224
- value: pm
167
+ value: pm,
225
168
  }));
226
169
  const answers = await inquirer_1.default.prompt([
227
170
  {
228
171
  type: 'list',
229
172
  name: 'packageManager',
230
- message: 'Which package manager would you like to use?',
173
+ message: chalk_1.default.blue('Which package manager would you like to use?'),
231
174
  choices: pmChoices,
232
- default: available[0] || 'npm'
175
+ default: available[0] || 'npm',
233
176
  },
234
177
  {
235
178
  type: 'confirm',
236
179
  name: 'install',
237
- message: 'Would you like to install dependencies now?',
238
- default: true
239
- }
180
+ message: chalk_1.default.blue('Would you like to install dependencies now?'),
181
+ default: true,
182
+ },
240
183
  ]);
241
184
  const packageManager = answers.packageManager;
242
185
  const { install } = answers;
@@ -247,28 +190,34 @@ dist
247
190
  console.log(chalk_1.default.cyan(`Falling back to npm...\n`));
248
191
  const installCmd = 'npm install';
249
192
  (0, child_process_1.execSync)(installCmd, { cwd: projectRoot, stdio: 'inherit' });
250
- console.log(chalk_1.default.green('\n✅ Dependencies installed!'));
193
+ console.log(chalk_1.default.green('\n✅ Dependencies installed!'));
251
194
  const devCmd = 'npm run dev';
252
195
  console.log(chalk_1.default.cyan(`\nTo get started:\n cd ${projectName}\n ${devCmd}\n`));
253
196
  }
254
197
  else if (install) {
255
- console.log(chalk_1.default.yellow(`\n📦 Installing dependencies with ${packageManager}...`));
198
+ console.log(chalk_1.default.yellow(`\n📦 Installing dependencies with ${packageManager}...\n`));
256
199
  const installCmd = packageManager === 'yarn' ? 'yarn' : `${packageManager} install`;
257
200
  (0, child_process_1.execSync)(installCmd, { cwd: projectRoot, stdio: 'inherit' });
258
- console.log(chalk_1.default.green('\n✅ Dependencies installed!'));
259
- const devCmd = packageManager === 'npm' ? 'npm run dev' :
260
- packageManager === 'yarn' ? 'yarn dev' : 'pnpm dev';
261
- console.log(chalk_1.default.cyan(`\nTo get started:\n cd ${projectName}\n ${devCmd}\n`));
201
+ console.log(chalk_1.default.green('\n✅ Dependencies installed!'));
202
+ const devCmd = packageManager === 'npm'
203
+ ? 'npm run dev'
204
+ : packageManager === 'yarn'
205
+ ? 'yarn dev'
206
+ : 'pnpm dev';
207
+ console.log(chalk_1.default.cyan(`\nTo get started:\n cd ${projectName}\n ${chalk_1.default.bold(devCmd)}\n`));
262
208
  }
263
209
  else {
264
- const devCmd = packageManager === 'npm' ? 'npm run dev' :
265
- packageManager === 'yarn' ? 'yarn dev' : 'pnpm dev';
210
+ const devCmd = packageManager === 'npm'
211
+ ? 'npm run dev'
212
+ : packageManager === 'yarn'
213
+ ? 'yarn dev'
214
+ : 'pnpm dev';
266
215
  const installCmd = packageManager === 'yarn' ? 'yarn' : `${packageManager} install`;
267
- console.log(chalk_1.default.cyan(`\nTo get started:\n cd ${projectName}\n ${installCmd} && ${devCmd}\n`));
216
+ console.log(chalk_1.default.cyan(`\nTo get started:\n cd ${projectName}\n ${chalk_1.default.bold(`${installCmd} && ${devCmd}`)}\n`));
268
217
  }
269
218
  }
270
219
  catch (error) {
271
- console.error(chalk_1.default.red('❌ Initialization failed:'), error);
220
+ console.error(chalk_1.default.red('\n❌ Initialization failed:'), error);
272
221
  process.exit(1);
273
222
  }
274
223
  });
@@ -4,32 +4,39 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.prismaCommand = void 0;
7
- const commander_1 = require("commander");
8
- const child_process_1 = require("child_process");
9
7
  const chalk_1 = __importDefault(require("chalk"));
8
+ const child_process_1 = require("child_process");
9
+ const commander_1 = require("commander");
10
10
  exports.prismaCommand = new commander_1.Command('prisma')
11
11
  .description('Prisma utility commands')
12
12
  .argument('<action>', 'Action to perform (generate, migrate)')
13
+ .addHelpText('after', `
14
+ ${chalk_1.default.yellow('Examples:')}
15
+ ${chalk_1.default.cyan('$ apollo-cli prisma generate')}
16
+ ${chalk_1.default.cyan('$ apollo-cli prisma migrate')}
17
+ `)
13
18
  .action(async (action) => {
14
19
  try {
15
20
  if (action === 'generate') {
16
- console.log(chalk_1.default.blue('🔄 Generating Prisma Client...'));
21
+ // Run Prisma generate
22
+ console.log(chalk_1.default.blue('\n🔄 Generating Prisma Client...\n'));
17
23
  (0, child_process_1.execSync)('npx prisma generate', { stdio: 'inherit' });
18
- console.log(chalk_1.default.green('✅ Prisma Client generated!'));
24
+ console.log(chalk_1.default.green('\n✅ Prisma Client generated! ✨\n'));
19
25
  }
20
26
  else if (action === 'migrate') {
21
- console.log(chalk_1.default.blue('🔄 Running Migrations...'));
27
+ // Run Prisma migrate dev
28
+ console.log(chalk_1.default.blue('\n🔄 Running Migrations...\n'));
22
29
  (0, child_process_1.execSync)('npx prisma migrate dev', { stdio: 'inherit' });
23
- console.log(chalk_1.default.green('✅ Migrations applied!'));
30
+ console.log(chalk_1.default.green('\n✅ Migrations applied! ✨\n'));
24
31
  }
25
32
  else {
26
- console.error(chalk_1.default.red(`Unknown action: ${action}`));
27
- console.log('Available actions: generate, migrate');
33
+ console.error(chalk_1.default.red(`\n❌ Unknown action: ${chalk_1.default.bold(action)}`));
34
+ console.log('Available actions: generate, migrate\n');
28
35
  }
29
36
  }
30
37
  catch (error) {
31
38
  // Error is already logged by inherit stdio usually, but we catch to prevent crash dump
32
- console.error(chalk_1.default.red('❌ Prisma command failed.'));
39
+ console.error(chalk_1.default.red('\n❌ Prisma command failed.\n'));
33
40
  process.exit(1);
34
41
  }
35
42
  });
@@ -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.renderTemplate = renderTemplate;
7
+ exports.writePackageJson = writePackageJson;
8
+ exports.writeTsConfig = writeTsConfig;
9
+ exports.writeServerFile = writeServerFile;
10
+ exports.writeAppFile = writeAppFile;
11
+ exports.writeConfigFile = writeConfigFile;
12
+ exports.writeEnvFile = writeEnvFile;
13
+ exports.writePrismaFile = writePrismaFile;
14
+ exports.writePrismaSchema = writePrismaSchema;
15
+ exports.writeGitIgnore = writeGitIgnore;
16
+ const chalk_1 = __importDefault(require("chalk"));
17
+ const ejs_1 = __importDefault(require("ejs"));
18
+ const fs_extra_1 = __importDefault(require("fs-extra"));
19
+ const path_1 = __importDefault(require("path"));
20
+ /**
21
+ * Renders an EJS template and writes the output to the target path.
22
+ */
23
+ async function renderTemplate(templateName, targetPath, data = {}) {
24
+ try {
25
+ const templateDir = path_1.default.resolve(__dirname, '../templates');
26
+ let templatePath = path_1.default.join(templateDir, templateName);
27
+ // Fallback for development (src/templates)
28
+ if (!fs_extra_1.default.existsSync(templatePath)) {
29
+ templatePath = path_1.default.resolve(__dirname, '../../src/templates', templateName);
30
+ }
31
+ if (!fs_extra_1.default.existsSync(templatePath)) {
32
+ console.error(chalk_1.default.red(`❌ Template not found at: ${templatePath}`));
33
+ return;
34
+ }
35
+ const templateContent = await fs_extra_1.default.readFile(templatePath, 'utf-8');
36
+ const renderedContent = ejs_1.default.render(templateContent, data);
37
+ await fs_extra_1.default.ensureDir(path_1.default.dirname(targetPath));
38
+ await fs_extra_1.default.writeFile(targetPath, renderedContent);
39
+ console.log(chalk_1.default.green(`✓ Created: ${path_1.default.relative(process.cwd(), targetPath)}`));
40
+ }
41
+ catch (error) {
42
+ console.error(chalk_1.default.red('❌ Error generating file:'), error);
43
+ process.exit(1);
44
+ }
45
+ }
46
+ /**
47
+ * Generates the package.json file for the new project.
48
+ */
49
+ async function writePackageJson(projectRoot, projectName, dependencies, devDependencies) {
50
+ const packageJson = {
51
+ name: projectName,
52
+ version: '1.0.0',
53
+ description: 'Backend project generated by Apollo Gears CLI',
54
+ main: 'dist/server.js',
55
+ scripts: {
56
+ start: 'node dist/server.js',
57
+ dev: 'ts-node-dev --respawn --transpile-only src/server.ts',
58
+ build: 'tsc',
59
+ lint: 'eslint src/**/*.ts',
60
+ 'lint:fix': 'eslint src/**/*.ts --fix',
61
+ format: 'prettier --write .',
62
+ },
63
+ keywords: ['express', 'prisma', 'typescript', 'apollo-gears'],
64
+ author: '',
65
+ license: 'ISC',
66
+ dependencies,
67
+ devDependencies,
68
+ };
69
+ await fs_extra_1.default.writeJson(path_1.default.join(projectRoot, 'package.json'), packageJson, {
70
+ spaces: 2,
71
+ });
72
+ }
73
+ /**
74
+ * Generates the tsconfig.json file with TypeScript configuration.
75
+ */
76
+ async function writeTsConfig(projectRoot) {
77
+ const tsconfig = {
78
+ compilerOptions: {
79
+ target: 'ES2021',
80
+ module: 'commonjs',
81
+ moduleResolution: 'node',
82
+ outDir: './dist',
83
+ rootDir: './src',
84
+ strict: true,
85
+ esModuleInterop: true,
86
+ skipLibCheck: true,
87
+ forceConsistentCasingInFileNames: true,
88
+ },
89
+ include: ['src/**/*'],
90
+ exclude: ['node_modules', 'dist', 'generated/prisma'],
91
+ };
92
+ await fs_extra_1.default.writeJson(path_1.default.join(projectRoot, 'tsconfig.json'), tsconfig, {
93
+ spaces: 2,
94
+ });
95
+ }
96
+ async function writeServerFile(projectRoot) {
97
+ await renderTemplate('init/server.ejs', path_1.default.join(projectRoot, 'src/server.ts'), { port: 5000 });
98
+ }
99
+ async function writeAppFile(projectRoot) {
100
+ await renderTemplate('init/app.ejs', path_1.default.join(projectRoot, 'src/app.ts'));
101
+ }
102
+ async function writeConfigFile(projectRoot) {
103
+ await renderTemplate('init/config.ejs', path_1.default.join(projectRoot, 'src/config/index.ts'));
104
+ }
105
+ async function writeEnvFile(projectRoot) {
106
+ await renderTemplate('init/env.ejs', path_1.default.join(projectRoot, '.env'));
107
+ }
108
+ async function writePrismaFile(projectRoot) {
109
+ await renderTemplate('init/prisma.ejs', path_1.default.join(projectRoot, 'src/lib/prisma.ts'));
110
+ }
111
+ async function writePrismaSchema(projectRoot) {
112
+ await renderTemplate('init/prisma-schema.ejs', path_1.default.join(projectRoot, 'prisma/schema.prisma'));
113
+ }
114
+ async function writeGitIgnore(projectRoot) {
115
+ await renderTemplate('init/gitignore.ejs', path_1.default.join(projectRoot, '.gitignore'));
116
+ }
package/package.json CHANGED
@@ -1,47 +1,53 @@
1
1
  {
2
- "name": "@bayajidalam/apollo-cli",
3
- "version": "1.0.3",
4
- "description": "CLI tool for speed up backend projects",
5
- "main": "dist/index.js",
6
- "types": "dist/index.d.ts",
7
- "bin": {
8
- "apollo-cli": "dist/bin/index.js"
9
- },
10
- "scripts": {
11
- "start": "ts-node src/index.ts",
12
- "build": "tsc",
13
- "watch": "tsc -w",
14
- "test": "echo \"Error: no test specified\" && exit 1",
15
- "cli": "ts-node src/bin/index.ts"
16
- },
17
- "keywords": [
18
- "cli",
19
- "express",
20
- "prisma",
21
- "postgres",
22
- "typescript"
23
- ],
24
- "author": "Bayajid Alam Joyel",
25
- "repository": {
26
- "url": "git+https://github.com/BayajidAlam/apollo-cli.git"
27
- },
28
- "license": "ISC",
29
- "publishConfig": {
30
- "access": "public"
31
- },
32
- "dependencies": {
33
- "chalk": "^4.1.2",
34
- "commander": "^13.1.0",
35
- "ejs": "^3.1.10",
36
- "fs-extra": "^11.3.0",
37
- "inquirer": "^8.2.6"
38
- },
39
- "devDependencies": {
40
- "@types/ejs": "^3.1.5",
41
- "@types/fs-extra": "^11.0.4",
42
- "@types/inquirer": "^8.2.6",
43
- "@types/node": "^22.13.1",
44
- "ts-node": "^10.9.2",
45
- "typescript": "^5.7.3"
46
- }
2
+ "name": "@bayajidalam/apollo-cli",
3
+ "version": "1.0.4",
4
+ "description": "CLI tool for speed up backend projects",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "bin": {
8
+ "apollo-cli": "dist/bin/index.js"
9
+ },
10
+ "scripts": {
11
+ "start": "ts-node src/index.ts",
12
+ "build": "tsc",
13
+ "watch": "tsc -w",
14
+ "test": "echo \"Error: no test specified\" && exit 1",
15
+ "cli": "ts-node src/bin/index.ts",
16
+ "format": "prettier --write ."
17
+ },
18
+ "keywords": [
19
+ "cli",
20
+ "express",
21
+ "prisma",
22
+ "postgres",
23
+ "typescript"
24
+ ],
25
+ "author": "Bayajid Alam Joyel",
26
+ "repository": {
27
+ "url": "git+https://github.com/BayajidAlam/apollo-cli.git"
28
+ },
29
+ "license": "ISC",
30
+ "publishConfig": {
31
+ "access": "public"
32
+ },
33
+ "dependencies": {
34
+ "chalk": "^4.1.2",
35
+ "commander": "^13.1.0",
36
+ "ejs": "^3.1.10",
37
+ "figlet": "^1.10.0",
38
+ "fs-extra": "^11.3.0",
39
+ "inquirer": "^8.2.6"
40
+ },
41
+ "devDependencies": {
42
+ "@types/ejs": "^3.1.5",
43
+ "@types/figlet": "^1.7.0",
44
+ "@types/fs-extra": "^11.0.4",
45
+ "@types/inquirer": "^8.2.6",
46
+ "@types/node": "^22.13.1",
47
+ "prettier": "^3.8.1",
48
+ "prettier-plugin-organize-imports": "^4.3.0",
49
+ "prettier-plugin-sort-json": "^4.2.0",
50
+ "ts-node": "^10.9.2",
51
+ "typescript": "^5.7.3"
52
+ }
47
53
  }