@bayajidalam/apollo-cli 1.0.2 → 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.
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UserSearchableFields = void 0;
4
+ exports.UserSearchableFields = [
5
+ // Add searchable fields here
6
+ ];
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UserController = void 0;
4
+ exports.UserController = {
5
+ // Add controller methods here
6
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,9 @@
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.UserRoutes = void 0;
7
+ const express_1 = __importDefault(require("express"));
8
+ const router = express_1.default.Router();
9
+ exports.UserRoutes = router;
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UserService = void 0;
4
+ exports.UserService = {
5
+ // Add service methods here
6
+ };
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.userValidationSchema = void 0;
4
+ // import { z } from 'zod';
5
+ exports.userValidationSchema = {
6
+ // Add validation schemas here
7
+ };
package/dist/bin/index.js CHANGED
@@ -1,17 +1,47 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
3
6
  Object.defineProperty(exports, "__esModule", { value: true });
4
7
  const commander_1 = require("commander");
5
- const generate_1 = require("../commands/generate");
6
8
  const build_1 = require("../commands/build");
7
- const prisma_1 = require("../commands/prisma");
9
+ const generate_1 = require("../commands/generate");
8
10
  const init_1 = require("../commands/init");
11
+ const prisma_1 = require("../commands/prisma");
12
+ // Set up the main CLI program
9
13
  const program = new commander_1.Command();
14
+ const chalk_1 = __importDefault(require("chalk"));
15
+ const figlet_1 = __importDefault(require("figlet"));
16
+ const fs_1 = __importDefault(require("fs"));
17
+ const path_1 = __importDefault(require("path"));
18
+ // Read package.json to get version and description
19
+ const packageJsonPath = path_1.default.join(__dirname, '../../package.json');
20
+ const packageJson = JSON.parse(fs_1.default.readFileSync(packageJsonPath, 'utf-8'));
10
21
  program
11
- .version('1.0.0')
12
- .description('Apollo CLI Tool');
22
+ .version(packageJson.version)
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
13
42
  program.addCommand(generate_1.generateCommand);
14
43
  program.addCommand(build_1.buildCommand);
15
44
  program.addCommand(prisma_1.prismaCommand);
16
45
  program.addCommand(init_1.initCommand);
46
+ // Parse command line arguments
17
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,17 +4,101 @@ 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");
14
+ // Helper function to get the latest version of a package from npm
15
+ async function getLatestVersion(packageName) {
16
+ try {
17
+ const version = (0, child_process_1.execSync)(`npm view ${packageName} version`, {
18
+ encoding: 'utf-8',
19
+ stdio: ['pipe', 'pipe', 'pipe'],
20
+ }).trim();
21
+ return `^${version}`;
22
+ }
23
+ catch (error) {
24
+ console.warn(chalk_1.default.yellow(`⚠️ Could not fetch latest version for ${packageName}, using fallback`));
25
+ return 'latest';
26
+ }
27
+ }
28
+ // Fetch latest versions for all dependencies
29
+ async function getLatestDependencies() {
30
+ console.log(chalk_1.default.blue('📦 Fetching latest package versions...'));
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
+ ];
58
+ const [dependencies, devDependencies] = await Promise.all([
59
+ Promise.all(deps.map(async (dep) => [dep, await getLatestVersion(dep)])),
60
+ Promise.all(devDeps.map(async (dep) => [dep, await getLatestVersion(dep)])),
61
+ ]);
62
+ return {
63
+ dependencies: Object.fromEntries(dependencies),
64
+ devDependencies: Object.fromEntries(devDependencies),
65
+ };
66
+ }
67
+ // Detect available package managers
68
+ function detectPackageManagers() {
69
+ const all = ['npm', 'pnpm', 'yarn'];
70
+ const available = [];
71
+ all.forEach((pm) => {
72
+ try {
73
+ (0, child_process_1.execSync)(`${pm} --version`, { stdio: 'ignore' });
74
+ available.push(pm);
75
+ }
76
+ catch {
77
+ // Package manager not available
78
+ }
79
+ });
80
+ return { available, all };
81
+ }
82
+ // Check if a package manager is installed
83
+ function isPackageManagerInstalled(pm) {
84
+ try {
85
+ (0, child_process_1.execSync)(`${pm} --version`, { stdio: 'ignore' });
86
+ return true;
87
+ }
88
+ catch {
89
+ return false;
90
+ }
91
+ }
13
92
  exports.initCommand = new commander_1.Command('init')
14
93
  .description('Initialize a new Apollo Gears project')
15
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
+ `)
16
100
  .action(async (projectName) => {
17
- // 1. Prompt for Project Name if missing
101
+ // Prompt for Project Name if missing
18
102
  if (!projectName) {
19
103
  const answers = await inquirer_1.default.prompt([
20
104
  {
@@ -22,8 +106,8 @@ exports.initCommand = new commander_1.Command('init')
22
106
  name: 'name',
23
107
  message: 'What is the name of your project?',
24
108
  default: 'my-apollo-app',
25
- validate: (input) => input.trim() !== '' ? true : 'Project name is required'
26
- }
109
+ validate: (input) => input.trim() !== '' ? true : 'Project name is required',
110
+ },
27
111
  ]);
28
112
  projectName = answers.name;
29
113
  }
@@ -32,150 +116,108 @@ exports.initCommand = new commander_1.Command('init')
32
116
  console.error(chalk_1.default.red(`Error: Directory "${projectName}" already exists.`));
33
117
  process.exit(1);
34
118
  }
35
- 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`));
36
120
  try {
37
- // 2. Create Directory
121
+ // Create project directory
38
122
  await fs_extra_1.default.ensureDir(projectRoot);
39
- // 3. Create Package.json
40
- const packageJson = {
41
- name: projectName,
42
- version: "1.0.0",
43
- description: "Backend project generated by Apollo Gears CLI",
44
- main: "dist/server.js",
45
- scripts: {
46
- "start": "node dist/server.js",
47
- "dev": "ts-node-dev --respawn --transpile-only src/server.ts",
48
- "build": "tsc",
49
- "lint": "eslint src/**/*.ts",
50
- "lint:fix": "eslint src/**/*.ts --fix",
51
- "format": "prettier --write ."
52
- },
53
- keywords: ["express", "prisma", "typescript", "apollo-gears"],
54
- author: "",
55
- license: "ISC",
56
- dependencies: {
57
- "express": "^4.18.2",
58
- "cors": "^2.8.5",
59
- "dotenv": "^16.3.1",
60
- "http-status": "^1.7.3",
61
- "@prisma/client": "^5.7.1"
62
- },
63
- devDependencies: {
64
- "typescript": "^5.3.3",
65
- "ts-node-dev": "^2.0.0",
66
- "@types/node": "^20.10.4",
67
- "@types/express": "^4.17.21",
68
- "@types/cors": "^2.8.17",
69
- "prisma": "^5.7.1",
70
- "eslint": "^8.55.0",
71
- "prettier": "^3.1.1"
72
- }
73
- };
74
- await fs_extra_1.default.writeJson(path_1.default.join(projectRoot, 'package.json'), packageJson, { spaces: 2 });
75
- // 4. Create tsconfig.json
76
- const tsconfig = {
77
- "compilerOptions": {
78
- "target": "ES2021",
79
- "module": "commonjs",
80
- "moduleResolution": "node",
81
- "outDir": "./dist",
82
- "rootDir": "./src",
83
- "strict": true,
84
- "esModuleInterop": true,
85
- "skipLibCheck": true,
86
- "forceConsistentCasingInFileNames": true
87
- },
88
- "include": ["src/**/*"],
89
- "exclude": ["node_modules"]
90
- };
91
- await fs_extra_1.default.writeJson(path_1.default.join(projectRoot, 'tsconfig.json'), tsconfig, { spaces: 2 });
92
- // 5. Create Scaffolding Folders
123
+ // Fetch latest versions of dependencies
124
+ const { dependencies, devDependencies } = await getLatestDependencies();
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
93
130
  const folders = [
94
- 'src/app/modules',
95
- 'src/app/middlewares',
96
- 'src/app/routes',
97
- 'src/app/utils',
98
- 'src/app/errors',
99
- 'src/app/config'
131
+ 'src/modules',
132
+ 'src/middlewares',
133
+ 'src/routes',
134
+ 'src/utils',
135
+ 'src/errors',
136
+ 'src/config',
137
+ 'src/lib',
100
138
  ];
139
+ console.log(chalk_1.default.blue('📂 Creating project structure...'));
101
140
  for (const folder of folders) {
102
141
  await fs_extra_1.default.ensureDir(path_1.default.join(projectRoot, folder));
103
142
  }
104
- // 6. Create Essential Files
105
- // src/server.ts
106
- const serverContent = `import app from './app';
107
- import config from './app/config';
108
-
109
- async function main() {
110
- try {
111
- app.listen(config.port, () => {
112
- console.log(\`Example app listening on port \${config.port}\`);
113
- });
114
- } catch (err) {
115
- console.log(err);
116
- }
117
- }
118
-
119
- main();`;
120
- await fs_extra_1.default.writeFile(path_1.default.join(projectRoot, 'src/server.ts'), serverContent);
121
- // src/app.ts
122
- const appContent = `import express, { Application, Request, Response } from 'express';
123
- import cors from 'cors';
124
-
125
- const app: Application = express();
126
-
127
- // parsers
128
- app.use(express.json());
129
- app.use(cors());
130
-
131
- // application routes
132
- // app.use('/api/v1', router);
133
-
134
- app.get('/', (req: Request, res: Response) => {
135
- res.send('Hello from Apollo Gears World!');
136
- });
137
-
138
- export default app;`;
139
- await fs_extra_1.default.writeFile(path_1.default.join(projectRoot, 'src/app.ts'), appContent);
140
- // src/app/config/index.ts
141
- const configContent = `import dotenv from 'dotenv';
142
- import path from 'path';
143
-
144
- dotenv.config({ path: path.join(process.cwd(), '.env') });
145
-
146
- export default {
147
- port: process.env.PORT,
148
- database_url: process.env.DATABASE_URL,
149
- };`;
150
- await fs_extra_1.default.writeFile(path_1.default.join(projectRoot, 'src/app/config/index.ts'), configContent);
151
- // .env
152
- const envContent = `PORT=5000
153
- DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public"`;
154
- await fs_extra_1.default.writeFile(path_1.default.join(projectRoot, '.env'), envContent);
155
- // .gitignore
156
- const gitignoreContent = `node_modules
157
- dist
158
- .env`;
159
- await fs_extra_1.default.writeFile(path_1.default.join(projectRoot, '.gitignore'), gitignoreContent);
160
- console.log(chalk_1.default.green('\n✅ Project structure created successfully!'));
161
- // 7. Install Dependencies Prompt
162
- const { install } = await inquirer_1.default.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
164
+ const { available, all } = detectPackageManagers();
165
+ const pmChoices = all.map((pm) => ({
166
+ name: available.includes(pm) ? `${pm} ✓` : `${pm} (not installed)`,
167
+ value: pm,
168
+ }));
169
+ const answers = await inquirer_1.default.prompt([
170
+ {
171
+ type: 'list',
172
+ name: 'packageManager',
173
+ message: chalk_1.default.blue('Which package manager would you like to use?'),
174
+ choices: pmChoices,
175
+ default: available[0] || 'npm',
176
+ },
163
177
  {
164
178
  type: 'confirm',
165
179
  name: 'install',
166
- message: 'Would you like to install dependencies now?',
167
- default: true
168
- }
180
+ message: chalk_1.default.blue('Would you like to install dependencies now?'),
181
+ default: true,
182
+ },
169
183
  ]);
170
- if (install) {
171
- console.log(chalk_1.default.yellow('\n📦 Installing dependencies...'));
172
- (0, child_process_1.execSync)('npm install', { cwd: projectRoot, stdio: 'inherit' });
173
- console.log(chalk_1.default.green('\n✅ Dependencies installed!'));
184
+ const packageManager = answers.packageManager;
185
+ const { install } = answers;
186
+ // Check if selected package manager is installed
187
+ if (install && !isPackageManagerInstalled(packageManager)) {
188
+ console.log(chalk_1.default.yellow(`\n⚠️ ${packageManager} is not installed on your system.`));
189
+ console.log(chalk_1.default.cyan(`Install it with: npm install -g ${packageManager}`));
190
+ console.log(chalk_1.default.cyan(`Falling back to npm...\n`));
191
+ const installCmd = 'npm install';
192
+ (0, child_process_1.execSync)(installCmd, { cwd: projectRoot, stdio: 'inherit' });
193
+ console.log(chalk_1.default.green('\n✅ Dependencies installed! ✨'));
194
+ const devCmd = 'npm run dev';
195
+ console.log(chalk_1.default.cyan(`\nTo get started:\n cd ${projectName}\n ${devCmd}\n`));
196
+ }
197
+ else if (install) {
198
+ console.log(chalk_1.default.yellow(`\n📦 Installing dependencies with ${packageManager}...\n`));
199
+ const installCmd = packageManager === 'yarn' ? 'yarn' : `${packageManager} install`;
200
+ (0, child_process_1.execSync)(installCmd, { cwd: projectRoot, stdio: 'inherit' });
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`));
208
+ }
209
+ else {
210
+ const devCmd = packageManager === 'npm'
211
+ ? 'npm run dev'
212
+ : packageManager === 'yarn'
213
+ ? 'yarn dev'
214
+ : 'pnpm dev';
215
+ const installCmd = packageManager === 'yarn' ? 'yarn' : `${packageManager} install`;
216
+ console.log(chalk_1.default.cyan(`\nTo get started:\n cd ${projectName}\n ${chalk_1.default.bold(`${installCmd} && ${devCmd}`)}\n`));
174
217
  }
175
- console.log(chalk_1.default.cyan(`\nTo get started:\n cd ${projectName}\n ${install ? 'npm run dev' : 'npm install && npm run dev'}\n`));
176
218
  }
177
219
  catch (error) {
178
- console.error(chalk_1.default.red('❌ Initialization failed:'), error);
220
+ console.error(chalk_1.default.red('\n❌ Initialization failed:'), error);
179
221
  process.exit(1);
180
222
  }
181
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.2",
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": "https://github.com/BayajidAlam/apollo-cli"
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
  }