@nishant0121/set-it-up 0.0.9 → 0.1.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.
- package/DESCRIPTION.md +75 -64
- package/README.md +39 -3
- package/package.json +1 -1
- package/src/engines/express.js +134 -0
- package/src/templates/express/configuration.js +77 -0
- package/src/templates/express/controllers.js +9 -0
- package/src/templates/express/database.js +17 -0
- package/src/templates/express/entry.js +80 -0
- package/src/templates/express/main.js +6 -0
- package/src/templates/express/prisma.js +8 -0
- package/src/templates/express/routes.js +11 -0
- package/src/utils/checkEnv.js +25 -25
- package/src/wizard.js +20 -1
package/DESCRIPTION.md
CHANGED
|
@@ -1,64 +1,75 @@
|
|
|
1
|
-
# @nishant0121/set-it-up: The Ultimate Project Scaffolding CLI
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
|
|
5
|
-
**Set It Up** is a powerful, developer-centric CLI tool engineered to eliminate the repetitive boilerplate work associated with starting new React and React Native projects. It bridges the gap between "Hello World" and a production-ready architecture.
|
|
6
|
-
|
|
7
|
-
Unlike standard create scripts that give you a bare-bones entry point, `set-it-up` (via its command `forge`) constructs a robust, scalable foundation tailored to your preferences (TypeScript/JavaScript, Styling, Routing, etc.).
|
|
8
|
-
|
|
9
|
-
## Why Use This?
|
|
10
|
-
|
|
11
|
-
Starting a modern frontend project often involves 30-60 minutes of configuration:
|
|
12
|
-
- Setting up tailwind.
|
|
13
|
-
- configuring the router.
|
|
14
|
-
- creating folder structures (`pages`, `components`, `context`).
|
|
15
|
-
- installing navigation libraries for mobile.
|
|
16
|
-
- handling safe area contexts.
|
|
17
|
-
|
|
18
|
-
**Set It Up** does this in seconds.
|
|
19
|
-
|
|
20
|
-
## Key Capabilities
|
|
21
|
-
|
|
22
|
-
### 1. Interactive "Forge" Wizard
|
|
23
|
-
The `forge` command launches an intuitive,inquirer-based terminal wizard that asks you exactly what you need. No complex flags to remember—just answer the questions, and the CLI handles the rest.
|
|
24
|
-
|
|
25
|
-
### 2. React (Web) Excellence
|
|
26
|
-
- **Vite-Powered:** Uses the fastest build tool in the ecosystem.
|
|
27
|
-
- **Tailwind CSS v4:** Automatically configured with the latest version using the Vite plugin.
|
|
28
|
-
- **Shadcn UI Integration:** The only CLI that can set up Shadcn UI and automatically transpile its TypeScript components to JavaScript if you prefer a JS-only project.
|
|
29
|
-
- **Auto-configured Path Aliases:** Pre-sets `@/` aliases in Vite and TS/JS configs for cleaner imports.
|
|
30
|
-
- **Structure:** Automatically creates `src/pages`, `src/components`, and `src/layouts`.
|
|
31
|
-
- **Router Ready:** Installs `react-router-dom` and sets up a default routing configuration with a Layout and Navbar.
|
|
32
|
-
- **State & Theme:** Optional `AppContext` boilerplating for global state and dark-mode ready theme management.
|
|
33
|
-
|
|
34
|
-
### 3. React Native (Mobile) Mastery
|
|
35
|
-
- **Modular Architecture:** Moves away from the monolithic `App.tsx` pattern. It generates a clean separation of concerns:
|
|
36
|
-
- `src/pages/` (Screens)
|
|
37
|
-
- `src/components/` (Reusable UI)
|
|
38
|
-
- **Navigation Pre-baked:** Installs and configures React Navigation (Native Stack).
|
|
39
|
-
- **Auto-configured Path Aliases:** Ready-to-use path resolution for cleaner codebase management.
|
|
40
|
-
- **Safe Area Handling:** Implements `react-native-safe-area-context` with `SafeAreaProvider` wrapping the app and `SafeAreaView` in screens.
|
|
41
|
-
- **Polished Templates:** The generated starter screens (`HomeScreen`, `DetailsScreen`) are not blank white pages. They feature modern design, cards, shadows, and proper typography, giving you a beautiful starting point.
|
|
42
|
-
|
|
43
|
-
### 4.
|
|
44
|
-
- **
|
|
45
|
-
-
|
|
46
|
-
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
- **
|
|
51
|
-
- **
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
- **
|
|
56
|
-
- **
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
1
|
+
# @nishant0121/set-it-up: The Ultimate Project Scaffolding CLI
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
**Set It Up** is a powerful, developer-centric CLI tool engineered to eliminate the repetitive boilerplate work associated with starting new React and React Native projects. It bridges the gap between "Hello World" and a production-ready architecture.
|
|
6
|
+
|
|
7
|
+
Unlike standard create scripts that give you a bare-bones entry point, `set-it-up` (via its command `forge`) constructs a robust, scalable foundation tailored to your preferences (TypeScript/JavaScript, Styling, Routing, etc.).
|
|
8
|
+
|
|
9
|
+
## Why Use This?
|
|
10
|
+
|
|
11
|
+
Starting a modern frontend project often involves 30-60 minutes of configuration:
|
|
12
|
+
- Setting up tailwind.
|
|
13
|
+
- configuring the router.
|
|
14
|
+
- creating folder structures (`pages`, `components`, `context`).
|
|
15
|
+
- installing navigation libraries for mobile.
|
|
16
|
+
- handling safe area contexts.
|
|
17
|
+
|
|
18
|
+
**Set It Up** does this in seconds.
|
|
19
|
+
|
|
20
|
+
## Key Capabilities
|
|
21
|
+
|
|
22
|
+
### 1. Interactive "Forge" Wizard
|
|
23
|
+
The `forge` command launches an intuitive,inquirer-based terminal wizard that asks you exactly what you need. No complex flags to remember—just answer the questions, and the CLI handles the rest.
|
|
24
|
+
|
|
25
|
+
### 2. React (Web) Excellence
|
|
26
|
+
- **Vite-Powered:** Uses the fastest build tool in the ecosystem.
|
|
27
|
+
- **Tailwind CSS v4:** Automatically configured with the latest version using the Vite plugin.
|
|
28
|
+
- **Shadcn UI Integration:** The only CLI that can set up Shadcn UI and automatically transpile its TypeScript components to JavaScript if you prefer a JS-only project.
|
|
29
|
+
- **Auto-configured Path Aliases:** Pre-sets `@/` aliases in Vite and TS/JS configs for cleaner imports.
|
|
30
|
+
- **Structure:** Automatically creates `src/pages`, `src/components`, and `src/layouts`.
|
|
31
|
+
- **Router Ready:** Installs `react-router-dom` and sets up a default routing configuration with a Layout and Navbar.
|
|
32
|
+
- **State & Theme:** Optional `AppContext` boilerplating for global state and dark-mode ready theme management.
|
|
33
|
+
|
|
34
|
+
### 3. React Native (Mobile) Mastery
|
|
35
|
+
- **Modular Architecture:** Moves away from the monolithic `App.tsx` pattern. It generates a clean separation of concerns:
|
|
36
|
+
- `src/pages/` (Screens)
|
|
37
|
+
- `src/components/` (Reusable UI)
|
|
38
|
+
- **Navigation Pre-baked:** Installs and configures React Navigation (Native Stack).
|
|
39
|
+
- **Auto-configured Path Aliases:** Ready-to-use path resolution for cleaner codebase management.
|
|
40
|
+
- **Safe Area Handling:** Implements `react-native-safe-area-context` with `SafeAreaProvider` wrapping the app and `SafeAreaView` in screens.
|
|
41
|
+
- **Polished Templates:** The generated starter screens (`HomeScreen`, `DetailsScreen`) are not blank white pages. They feature modern design, cards, shadows, and proper typography, giving you a beautiful starting point.
|
|
42
|
+
|
|
43
|
+
### 4. Express.js (Backend) Mastery
|
|
44
|
+
- **Modular Architecture:** Encourages clean code with a dedicated folder structure:
|
|
45
|
+
- `src/routes/` (Endpoint definitions)
|
|
46
|
+
- `src/controllers/` (Business logic)
|
|
47
|
+
- `src/config/` (Database & client configurations)
|
|
48
|
+
- **Database Integration:** First-class support for **MongoDB (Mongoose)** and **PostgreSQL (Prisma ORM)**. The CLI generates connection logic and ensures the server only starts after a successful DB connection.
|
|
49
|
+
- **Modern ESM:** Strictly uses `import`/`export` syntax and `"type": "module"` for a modern Node.js experience.
|
|
50
|
+
- **TypeScript Ready:** Seamless integration using `tsx` for instant execution and watch modes, avoiding common ESM/TS configuration pitfalls.
|
|
51
|
+
- **Pre-configured Middleware:** Comes out of the box with `cors`, `helmet` (security), `morgan` (logging), and `dotenv`.
|
|
52
|
+
|
|
53
|
+
### 5. Smart & Safe
|
|
54
|
+
- **Prerequisite Checking:** Scans your environment for Node.js, Git, and other tools before starting to prevent mid-install failures.
|
|
55
|
+
- **Package Manager Agnostic:** Works seamlessly with `npm`, `yarn`, and `pnpm`.
|
|
56
|
+
- **Lightning Fast Conversion:** Uses `esbuild` for instant TypeScript to JavaScript transpilation when bridging Shadcn UI into JS projects.
|
|
57
|
+
|
|
58
|
+
## Technology Stack
|
|
59
|
+
|
|
60
|
+
- **CLI Engine:** Node.js, Commander, Inquirer, Ora (spinners), Chalk (styling), Boxen, Gradient-String.
|
|
61
|
+
- **Automation:** Execa (process execution), FS-Extra (file system), Esbuild (fast transpilation).
|
|
62
|
+
- **Templates:** React (Vite), React Native (CLI), Express.js, Tailwind CSS v4, Mongoose, Prisma, tsx.
|
|
63
|
+
|
|
64
|
+
## Roadmap (Coming Soon)
|
|
65
|
+
- **Next.js Support:** Full App Router scaffolding with advanced features.
|
|
66
|
+
- **Custom GitHub Templates:** Forge projects from your own private or public repositories.
|
|
67
|
+
- **Authentication Boilerplates:** Ready-to-use JWT or NextAuth configurations.
|
|
68
|
+
- **FastAPI Forging:** Python-based backend starter templates.
|
|
69
|
+
|
|
70
|
+
## Get Started
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
npm install -g @nishant0121/set-it-up
|
|
74
|
+
forge
|
|
75
|
+
```
|
package/README.md
CHANGED
|
@@ -18,6 +18,13 @@ set-it-up is a high-performance CLI tool designed to bootstrap and forge new pro
|
|
|
18
18
|
- Rapid initialization with @react-native-community/cli.
|
|
19
19
|
- Full support for both TypeScript and JavaScript.
|
|
20
20
|
- Automated React Navigation integration with boilerplate code.
|
|
21
|
+
- Express.js Support:
|
|
22
|
+
- Modular project structure (routes, controllers, config).
|
|
23
|
+
- Modern ESM (`import`/`export`) setup with `"type": "module"`.
|
|
24
|
+
- TypeScript support using `tsx` for high performance and ESM compatibility.
|
|
25
|
+
- Optional Database integration: **MongoDB (Mongoose)** or **PostgreSQL (Prisma)**.
|
|
26
|
+
- Automatic `.env` generation and database connection logic.
|
|
27
|
+
- Pre-configured security (Helmet) and logging (Morgan) middleware.
|
|
21
28
|
- Smart Defaults: Supports npm, yarn, and pnpm based on user preference.
|
|
22
29
|
|
|
23
30
|
## Installation
|
|
@@ -44,13 +51,27 @@ forge
|
|
|
44
51
|
|
|
45
52
|
Follow the prompts to:
|
|
46
53
|
|
|
47
|
-
1. Select your project type (React
|
|
54
|
+
1. Select your project type (React, React Native, or Express.js).
|
|
48
55
|
2. Provide a project name.
|
|
49
56
|
3. Choose your preferred package manager.
|
|
50
57
|
4. Select language (TypeScript or JavaScript).
|
|
51
|
-
5. Configure additional features (Shadcn UI, Router,
|
|
58
|
+
5. Configure additional features (Database, Shadcn UI, Router, etc.).
|
|
52
59
|
|
|
53
|
-
### Example Workflow
|
|
60
|
+
### Example Workflow (Express.js)
|
|
61
|
+
|
|
62
|
+
```text
|
|
63
|
+
SET-IT-UP
|
|
64
|
+
|
|
65
|
+
Hi there! Let's configure your new project.
|
|
66
|
+
|
|
67
|
+
? What do you want to build today? Express.js
|
|
68
|
+
? Enter your project name: my-api
|
|
69
|
+
? Select your preferred package manager: pnpm
|
|
70
|
+
? Which language do you want to use? TypeScript
|
|
71
|
+
? Which database do you want to use? PostgreSQL (Prisma)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Example Workflow (React)
|
|
54
75
|
|
|
55
76
|
```text
|
|
56
77
|
SET-IT-UP
|
|
@@ -66,6 +87,21 @@ Hi there! Let's configure your new project.
|
|
|
66
87
|
? Would you like to setup a global AppContext? Yes
|
|
67
88
|
```
|
|
68
89
|
|
|
90
|
+
### Example Workflow (React Native)
|
|
91
|
+
|
|
92
|
+
```text
|
|
93
|
+
SET-IT-UP
|
|
94
|
+
|
|
95
|
+
Hi there! Let's configure your new project.
|
|
96
|
+
|
|
97
|
+
? What do you want to build today? React Native
|
|
98
|
+
? Enter your project name: my-mobile-app
|
|
99
|
+
? Select your preferred package manager: yarn
|
|
100
|
+
? Which platform do you want to target? Both
|
|
101
|
+
? Which language do you want to use? TypeScript
|
|
102
|
+
? Would you like to add React Navigation setup? Yes
|
|
103
|
+
```
|
|
104
|
+
|
|
69
105
|
## Contributing
|
|
70
106
|
|
|
71
107
|
Contributions are welcome. Please open an issue or submit a pull request for improvements.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nishant0121/set-it-up",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "A high-performance CLI tool to bootstrap and forge new projects with pre-configured templates, prerequisite checking, and interactive setup.",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"author": "Nishant Patil",
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { execa } from 'execa';
|
|
2
|
+
import ora from 'ora';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import fs from 'fs-extra';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
getPackageJson,
|
|
9
|
+
getTsConfig,
|
|
10
|
+
getIndex,
|
|
11
|
+
getRouteIndex,
|
|
12
|
+
getController,
|
|
13
|
+
getDatabaseConfig,
|
|
14
|
+
getPrismaClient
|
|
15
|
+
} from '../templates/express/main.js';
|
|
16
|
+
|
|
17
|
+
export async function setupExpress(answers, expressAnswers) {
|
|
18
|
+
const spinner = ora('Initializing Express project...').start();
|
|
19
|
+
try {
|
|
20
|
+
const { projectName, packageManager } = answers;
|
|
21
|
+
const isTypescript = expressAnswers.language === 'TypeScript';
|
|
22
|
+
const database = expressAnswers.database;
|
|
23
|
+
const projectPath = path.join(process.cwd(), projectName);
|
|
24
|
+
|
|
25
|
+
// 1. Create Project Directory
|
|
26
|
+
await fs.ensureDir(projectPath);
|
|
27
|
+
|
|
28
|
+
// 2. Create package.json
|
|
29
|
+
spinner.text = 'Creating package.json...';
|
|
30
|
+
const packageJsonContent = getPackageJson(projectName, isTypescript, database);
|
|
31
|
+
await fs.writeFile(path.join(projectPath, 'package.json'), packageJsonContent);
|
|
32
|
+
|
|
33
|
+
// 3. Create tsconfig.json (if TypeScript)
|
|
34
|
+
if (isTypescript) {
|
|
35
|
+
spinner.text = 'Creating tsconfig.json...';
|
|
36
|
+
const tsConfigContent = getTsConfig();
|
|
37
|
+
await fs.writeFile(path.join(projectPath, 'tsconfig.json'), tsConfigContent);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// 4. Create Source Directories and Files
|
|
41
|
+
spinner.text = 'Generating project structure...';
|
|
42
|
+
const srcDir = path.join(projectPath, 'src');
|
|
43
|
+
const routesDir = path.join(srcDir, 'routes');
|
|
44
|
+
const controllersDir = path.join(srcDir, 'controllers');
|
|
45
|
+
|
|
46
|
+
await fs.ensureDir(srcDir);
|
|
47
|
+
await fs.ensureDir(routesDir);
|
|
48
|
+
await fs.ensureDir(controllersDir);
|
|
49
|
+
|
|
50
|
+
const ext = isTypescript ? 'ts' : 'js';
|
|
51
|
+
|
|
52
|
+
// Handle Database Setup
|
|
53
|
+
let envContent = 'PORT=3000\n';
|
|
54
|
+
|
|
55
|
+
if (database === 'MongoDB (Mongoose)') {
|
|
56
|
+
const configDir = path.join(srcDir, 'config');
|
|
57
|
+
await fs.ensureDir(configDir);
|
|
58
|
+
await fs.writeFile(path.join(configDir, `db.${ext}`), getDatabaseConfig(isTypescript));
|
|
59
|
+
envContent += 'MONGO_URI=mongodb://127.0.0.1:27017/my-awesome-app\n';
|
|
60
|
+
} else if (database === 'PostgreSQL (Prisma)') {
|
|
61
|
+
const configDir = path.join(srcDir, 'config');
|
|
62
|
+
const prismaDir = path.join(projectPath, 'prisma');
|
|
63
|
+
|
|
64
|
+
await fs.ensureDir(configDir);
|
|
65
|
+
await fs.ensureDir(prismaDir);
|
|
66
|
+
|
|
67
|
+
// Create Prisma Client Instance
|
|
68
|
+
await fs.writeFile(path.join(configDir, `client.${ext}`), getPrismaClient(isTypescript));
|
|
69
|
+
|
|
70
|
+
// Create schema.prisma
|
|
71
|
+
const schemaPrisma = `generator client {
|
|
72
|
+
provider = "prisma-client-js"
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
datasource db {
|
|
76
|
+
provider = "postgresql"
|
|
77
|
+
url = env("DATABASE_URL")
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
model User {
|
|
81
|
+
id Int @id @default(autoincrement())
|
|
82
|
+
email String @unique
|
|
83
|
+
name String?
|
|
84
|
+
}
|
|
85
|
+
`;
|
|
86
|
+
await fs.writeFile(path.join(prismaDir, 'schema.prisma'), schemaPrisma);
|
|
87
|
+
|
|
88
|
+
envContent += 'DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public"\n';
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// src/index.ts or src/index.js
|
|
92
|
+
await fs.writeFile(path.join(srcDir, `index.${ext}`), getIndex(isTypescript, database));
|
|
93
|
+
|
|
94
|
+
// src/routes/index.ts or src/routes/index.js
|
|
95
|
+
await fs.writeFile(path.join(routesDir, `index.${ext}`), getRouteIndex(isTypescript));
|
|
96
|
+
|
|
97
|
+
// src/controllers/exampleController.ts or src/controllers/exampleController.js
|
|
98
|
+
await fs.writeFile(path.join(controllersDir, `exampleController.${ext}`), getController(isTypescript));
|
|
99
|
+
|
|
100
|
+
// Create .env file
|
|
101
|
+
await fs.writeFile(path.join(projectPath, '.env'), envContent);
|
|
102
|
+
|
|
103
|
+
// Create .gitignore
|
|
104
|
+
const gitignoreContent = `node_modules
|
|
105
|
+
.env
|
|
106
|
+
dist
|
|
107
|
+
.DS_Store
|
|
108
|
+
coverage
|
|
109
|
+
`;
|
|
110
|
+
await fs.writeFile(path.join(projectPath, '.gitignore'), gitignoreContent);
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
// 5. Install Dependencies
|
|
114
|
+
spinner.text = 'Installing dependencies...';
|
|
115
|
+
const installCmd = packageManager === 'npm' ? 'install' : 'add';
|
|
116
|
+
await execa(packageManager, [installCmd], { cwd: projectPath });
|
|
117
|
+
|
|
118
|
+
// 6. Generate Prisma Client (if Prisma selected)
|
|
119
|
+
if (database === 'PostgreSQL (Prisma)') {
|
|
120
|
+
spinner.text = 'Generating Prisma Client...';
|
|
121
|
+
await execa('npx', ['prisma', 'generate'], { cwd: projectPath });
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
spinner.succeed(chalk.green(`Express project ${projectName} created successfully! 🚀`));
|
|
125
|
+
console.log(chalk.cyan(`
|
|
126
|
+
To get started:
|
|
127
|
+
cd ${projectName}
|
|
128
|
+
${packageManager} run dev`));
|
|
129
|
+
|
|
130
|
+
} catch (error) {
|
|
131
|
+
spinner.fail('Setup failed.');
|
|
132
|
+
console.error(error);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
export const getPackageJson = (projectName, isTypescript, database) => {
|
|
2
|
+
const commonScripts = {
|
|
3
|
+
"start": "node src/index.js",
|
|
4
|
+
"dev": "nodemon src/index.js"
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
const tsScripts = {
|
|
8
|
+
"start": "tsx src/index.ts",
|
|
9
|
+
"dev": "tsx watch src/index.ts",
|
|
10
|
+
"build": "tsc"
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const dependencies = {
|
|
14
|
+
"express": "^4.18.2",
|
|
15
|
+
"cors": "^2.8.5",
|
|
16
|
+
"dotenv": "^16.3.1",
|
|
17
|
+
"helmet": "^7.1.0",
|
|
18
|
+
"morgan": "^1.10.0"
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
if (database === 'MongoDB (Mongoose)') {
|
|
22
|
+
dependencies["mongoose"] = "^8.0.3";
|
|
23
|
+
} else if (database === 'PostgreSQL (Prisma)') {
|
|
24
|
+
dependencies["@prisma/client"] = "^5.7.1";
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const devDependencies = isTypescript ? {
|
|
28
|
+
"typescript": "^5.3.3",
|
|
29
|
+
"tsx": "^4.7.0",
|
|
30
|
+
"@types/node": "^20.10.6",
|
|
31
|
+
"@types/express": "^4.17.21",
|
|
32
|
+
"@types/cors": "^2.8.17",
|
|
33
|
+
"@types/morgan": "^1.9.9"
|
|
34
|
+
} : {
|
|
35
|
+
"nodemon": "^3.0.2"
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
if (isTypescript && database === 'MongoDB (Mongoose)') {
|
|
39
|
+
devDependencies["@types/mongoose"] = "^5.11.97";
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (database === 'PostgreSQL (Prisma)') {
|
|
43
|
+
devDependencies["prisma"] = "^5.7.1";
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return JSON.stringify({
|
|
47
|
+
name: projectName,
|
|
48
|
+
version: "1.0.0",
|
|
49
|
+
description: "Express.js application generated by set-it-up",
|
|
50
|
+
main: isTypescript ? "src/index.ts" : "src/index.js",
|
|
51
|
+
type: "module",
|
|
52
|
+
scripts: isTypescript ? tsScripts : commonScripts,
|
|
53
|
+
dependencies,
|
|
54
|
+
devDependencies,
|
|
55
|
+
keywords: [],
|
|
56
|
+
author: "",
|
|
57
|
+
license: "ISC"
|
|
58
|
+
}, null, 2);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export const getTsConfig = () => {
|
|
62
|
+
return JSON.stringify({
|
|
63
|
+
"compilerOptions": {
|
|
64
|
+
"target": "es2020",
|
|
65
|
+
"module": "esnext",
|
|
66
|
+
"moduleResolution": "node",
|
|
67
|
+
"outDir": "./dist",
|
|
68
|
+
"rootDir": "./src",
|
|
69
|
+
"strict": true,
|
|
70
|
+
"esModuleInterop": true,
|
|
71
|
+
"skipLibCheck": true,
|
|
72
|
+
"forceConsistentCasingInFileNames": true
|
|
73
|
+
},
|
|
74
|
+
"include": ["src/**/*"],
|
|
75
|
+
"exclude": ["node_modules"]
|
|
76
|
+
}, null, 2);
|
|
77
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const getController = (isTypescript) => {
|
|
2
|
+
const importStatement = isTypescript ? "import { Request, Response } from 'express';\n" : "";
|
|
3
|
+
return `${importStatement}
|
|
4
|
+
export const getExample = (req${isTypescript ? ': Request' : ''}, res${isTypescript ? ': Response' : ''}) => {
|
|
5
|
+
res.json({ message: 'This is an example controller response' });
|
|
6
|
+
};
|
|
7
|
+
`;
|
|
8
|
+
};
|
|
9
|
+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const getDatabaseConfig = (isTypescript) => {
|
|
2
|
+
return `import mongoose from 'mongoose';
|
|
3
|
+
|
|
4
|
+
const connectDB = async () => {
|
|
5
|
+
try {
|
|
6
|
+
const conn = await mongoose.connect(process.env.MONGO_URI || 'mongodb://127.0.0.1:27017/my-awesome-app');
|
|
7
|
+
console.log(\`MongoDB Connected: \${conn.connection.host}\`);
|
|
8
|
+
} catch (error) {
|
|
9
|
+
console.error(\`Error: \${error.message}\`);
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default connectDB;
|
|
15
|
+
`;
|
|
16
|
+
};
|
|
17
|
+
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
export const getIndex = (isTypescript, database) => {
|
|
2
|
+
const portVar = isTypescript ? 'const PORT: number | string = process.env.PORT || 3000;' : 'const PORT = process.env.PORT || 3000;';
|
|
3
|
+
|
|
4
|
+
let dbImport = "";
|
|
5
|
+
let listenBlock = "";
|
|
6
|
+
|
|
7
|
+
if (database === 'MongoDB (Mongoose)') {
|
|
8
|
+
dbImport = "import connectDB from './config/db.js';\n";
|
|
9
|
+
listenBlock = `
|
|
10
|
+
// Connect to Database and Start Server
|
|
11
|
+
connectDB().then(() => {
|
|
12
|
+
app.listen(PORT, () => {
|
|
13
|
+
console.log(\`Server is running on port \${PORT}\`);
|
|
14
|
+
console.log('Visit http://localhost:' + PORT);
|
|
15
|
+
console.log('Press CTRL+C to stop the server');
|
|
16
|
+
});
|
|
17
|
+
});`;
|
|
18
|
+
} else if (database === 'PostgreSQL (Prisma)') {
|
|
19
|
+
dbImport = "import prisma from './config/client.js';\n";
|
|
20
|
+
listenBlock = `
|
|
21
|
+
// Connect to Database and Start Server
|
|
22
|
+
const startServer = async () => {
|
|
23
|
+
try {
|
|
24
|
+
await prisma.$connect();
|
|
25
|
+
console.log('Connected to PostgreSQL via Prisma');
|
|
26
|
+
app.listen(PORT, () => {
|
|
27
|
+
console.log(\`Server is running on port \${PORT}\`);
|
|
28
|
+
console.log('Visit http://localhost:' + PORT);
|
|
29
|
+
console.log('Press CTRL+C to stop the server');
|
|
30
|
+
});
|
|
31
|
+
} catch (error) {
|
|
32
|
+
console.error('Failed to connect to the database:', error);
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
startServer();`;
|
|
38
|
+
} else {
|
|
39
|
+
listenBlock = `
|
|
40
|
+
app.listen(PORT, () => {
|
|
41
|
+
console.log(\`Server is running on port \${PORT}\`);
|
|
42
|
+
console.log('Visit http://localhost:' + PORT);
|
|
43
|
+
console.log('Press CTRL+C to stop the server');
|
|
44
|
+
});`;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return `import express${isTypescript ? ', { Express, Request, Response }' : ''} from 'express';
|
|
48
|
+
import cors from 'cors';
|
|
49
|
+
import helmet from 'helmet';
|
|
50
|
+
import morgan from 'morgan';
|
|
51
|
+
import dotenv from 'dotenv';
|
|
52
|
+
import router from './routes/index.js';
|
|
53
|
+
${dbImport}
|
|
54
|
+
dotenv.config();
|
|
55
|
+
|
|
56
|
+
const app${isTypescript ? ': Express' : ''} = express();
|
|
57
|
+
${portVar}
|
|
58
|
+
|
|
59
|
+
// Middleware
|
|
60
|
+
app.use(express.json());
|
|
61
|
+
app.use(express.urlencoded({ extended: true }));
|
|
62
|
+
app.use(cors());
|
|
63
|
+
app.use(helmet());
|
|
64
|
+
app.use(morgan('dev'));
|
|
65
|
+
|
|
66
|
+
// Routes
|
|
67
|
+
app.use('/api', router);
|
|
68
|
+
|
|
69
|
+
app.get('/', (req${isTypescript ? ': Request' : ''}, res${isTypescript ? ': Response' : ''}) => {
|
|
70
|
+
res.send('Welcome to your Express.js API!');
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// Error handling middleware
|
|
74
|
+
app.use((err${isTypescript ? ': any' : ''}, req${isTypescript ? ': Request' : ''}, res${isTypescript ? ': Response' : ''}, next${isTypescript ? ': Function' : ''}) => {
|
|
75
|
+
console.error(err.stack);
|
|
76
|
+
res.status(500).send('Something broke!');
|
|
77
|
+
});
|
|
78
|
+
${listenBlock}
|
|
79
|
+
`;
|
|
80
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const getRouteIndex = (isTypescript) => {
|
|
2
|
+
return `import { Router } from 'express';
|
|
3
|
+
import { getExample } from '../controllers/exampleController.js';
|
|
4
|
+
|
|
5
|
+
const router = Router();
|
|
6
|
+
|
|
7
|
+
router.get('/example', getExample);
|
|
8
|
+
|
|
9
|
+
export default router;
|
|
10
|
+
`;
|
|
11
|
+
};
|
package/src/utils/checkEnv.js
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
import commandExists from 'command-exists';
|
|
2
|
-
import chalk from 'chalk';
|
|
3
|
-
|
|
4
|
-
export async function checkPrerequisites(type, options = {}) {
|
|
5
|
-
const requirements = {
|
|
6
|
-
'React Native': ['node', 'git', 'npm', 'java'],
|
|
7
|
-
'React': ['node', 'git', 'npm'],
|
|
8
|
-
'Next.js': ['node', 'git']
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
if (type === 'React Native' && options.targetPlatform !== 'Android') {
|
|
12
|
-
requirements['React Native'].push('pod');
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
console.log(chalk.blue('\n🔍 Checking prerequisites...'));
|
|
16
|
-
|
|
17
|
-
for (const cmd of requirements[type]) {
|
|
18
|
-
try {
|
|
19
|
-
await commandExists(cmd);
|
|
20
|
-
console.log(chalk.green(` ✔ ${cmd} is installed`));
|
|
21
|
-
} catch {
|
|
22
|
-
console.log(chalk.red(` ✘ ${cmd} is missing. Please install it to continue.`));
|
|
23
|
-
process.exit(1);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
1
|
+
import commandExists from 'command-exists';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
|
|
4
|
+
export async function checkPrerequisites(type, options = {}) {
|
|
5
|
+
const requirements = {
|
|
6
|
+
'React Native': ['node', 'git', 'npm', 'java'],
|
|
7
|
+
'React': ['node', 'git', 'npm'],
|
|
8
|
+
'Next.js': ['node', 'git']
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
if (type === 'React Native' && options.targetPlatform !== 'Android') {
|
|
12
|
+
requirements['React Native'].push('pod');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
console.log(chalk.blue('\n🔍 Checking prerequisites...'));
|
|
16
|
+
|
|
17
|
+
for (const cmd of requirements[type]) {
|
|
18
|
+
try {
|
|
19
|
+
await commandExists(cmd);
|
|
20
|
+
console.log(chalk.green(` ✔ ${cmd} is installed`));
|
|
21
|
+
} catch {
|
|
22
|
+
console.log(chalk.red(` ✘ ${cmd} is missing. Please install it to continue.`));
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
26
|
}
|
package/src/wizard.js
CHANGED
|
@@ -5,6 +5,7 @@ import boxen from 'boxen';
|
|
|
5
5
|
import { checkPrerequisites } from './utils/checkEnv.js';
|
|
6
6
|
import { setupReactNative } from './engines/reactNative.js';
|
|
7
7
|
import { setupReact } from './engines/react.js';
|
|
8
|
+
import { setupExpress } from './engines/express.js';
|
|
8
9
|
|
|
9
10
|
export async function mainWizard() {
|
|
10
11
|
// Clear the console for a fresh start
|
|
@@ -39,7 +40,7 @@ export async function mainWizard() {
|
|
|
39
40
|
type: 'rawlist',
|
|
40
41
|
name: 'projectType',
|
|
41
42
|
message: 'What do you want to build today?',
|
|
42
|
-
choices: ['React', 'React Native', 'Next.js (Coming Soon)', 'Custom GitHub Template'],
|
|
43
|
+
choices: ['React', 'React Native', 'Express.js', 'Next.js (Coming Soon)', 'Custom GitHub Template'],
|
|
43
44
|
},
|
|
44
45
|
{
|
|
45
46
|
type: 'input',
|
|
@@ -118,6 +119,24 @@ export async function mainWizard() {
|
|
|
118
119
|
|
|
119
120
|
await setupReact(answers, reactAnswers);
|
|
120
121
|
|
|
122
|
+
} else if (answers.projectType === 'Express.js') {
|
|
123
|
+
const expressAnswers = await inquirer.prompt([
|
|
124
|
+
{
|
|
125
|
+
type: 'rawlist',
|
|
126
|
+
name: 'language',
|
|
127
|
+
message: 'Which language do you want to use?',
|
|
128
|
+
choices: ['TypeScript', 'JavaScript'],
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
type: 'rawlist',
|
|
132
|
+
name: 'database',
|
|
133
|
+
message: 'Which database do you want to use?',
|
|
134
|
+
choices: ['None', 'MongoDB (Mongoose)', 'PostgreSQL (Prisma)'],
|
|
135
|
+
}
|
|
136
|
+
]);
|
|
137
|
+
|
|
138
|
+
await setupExpress(answers, expressAnswers);
|
|
139
|
+
|
|
121
140
|
} else {
|
|
122
141
|
console.log(chalk.yellow('\n🚧 This feature is coming soon! Stay tuned.\n'));
|
|
123
142
|
}
|