@shivasankaran18/stackd 1.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/.github/workflows/ci.yml +30 -0
- package/LICENSE +21 -0
- package/README.md +115 -0
- package/apps/cli/package.json +32 -0
- package/apps/cli/src/cli.ts +271 -0
- package/apps/cli/src/commands/create.ts +162 -0
- package/apps/cli/src/scripts/Auth/jwt.ts +83 -0
- package/apps/cli/src/scripts/Auth/nextAuth.ts +146 -0
- package/apps/cli/src/scripts/Auth/passport.ts +234 -0
- package/apps/cli/src/scripts/backend/django.ts +30 -0
- package/apps/cli/src/scripts/backend/expressjs.ts +72 -0
- package/apps/cli/src/scripts/backend/expressts.ts +95 -0
- package/apps/cli/src/scripts/frontend/angularjs.ts +0 -0
- package/apps/cli/src/scripts/frontend/angularts.ts +29 -0
- package/apps/cli/src/scripts/frontend/nextjs.ts +72 -0
- package/apps/cli/src/scripts/frontend/reactjs.ts +36 -0
- package/apps/cli/src/scripts/frontend/reactts.ts +34 -0
- package/apps/cli/src/scripts/frontend/vuejs.ts +43 -0
- package/apps/cli/src/scripts/frontend/vuets.ts +53 -0
- package/apps/cli/src/scripts/orms/drizzleSetup.ts +102 -0
- package/apps/cli/src/scripts/orms/mongoSetup.ts +68 -0
- package/apps/cli/src/scripts/orms/prismaSetup.ts +14 -0
- package/apps/cli/src/scripts/ui/shadcn.ts +228 -0
- package/apps/cli/src/scripts/ui/tailwindcss.ts +126 -0
- package/apps/cli/tsconfig.json +111 -0
- package/apps/web/app/api/auth/[...nextauth]/route.ts +7 -0
- package/apps/web/app/api/scaffold/route.ts +274 -0
- package/apps/web/app/favicon.ico +0 -0
- package/apps/web/app/fonts/GeistMonoVF.woff +0 -0
- package/apps/web/app/fonts/GeistVF.woff +0 -0
- package/apps/web/app/globals.css +158 -0
- package/apps/web/app/home/page.tsx +22 -0
- package/apps/web/app/layout.tsx +35 -0
- package/apps/web/app/page.module.css +188 -0
- package/apps/web/app/page.tsx +1 -0
- package/apps/web/app/providers.tsx +9 -0
- package/apps/web/app/scaffold/page.tsx +472 -0
- package/apps/web/components/Sidebar.tsx +108 -0
- package/apps/web/components/theme-provider.tsx +9 -0
- package/apps/web/components/ui/button.tsx +57 -0
- package/apps/web/components/ui/card.tsx +76 -0
- package/apps/web/components/ui/dropdown-menu.tsx +200 -0
- package/apps/web/components/ui/input.tsx +22 -0
- package/apps/web/components/ui/label.tsx +26 -0
- package/apps/web/components/ui/scroll-area.tsx +48 -0
- package/apps/web/components/ui/sonner.tsx +31 -0
- package/apps/web/components/ui/steps.tsx +36 -0
- package/apps/web/components/ui/switch.tsx +29 -0
- package/apps/web/components.json +21 -0
- package/apps/web/eslint.config.js +4 -0
- package/apps/web/lib/auth.ts +35 -0
- package/apps/web/lib/redis.ts +13 -0
- package/apps/web/lib/utils.ts +8 -0
- package/apps/web/next-env.d.ts +5 -0
- package/apps/web/next.config.js +4 -0
- package/apps/web/package.json +52 -0
- package/apps/web/postcss.config.js +6 -0
- package/apps/web/public/file-text.svg +3 -0
- package/apps/web/public/globe.svg +10 -0
- package/apps/web/public/next.svg +1 -0
- package/apps/web/public/turborepo-dark.svg +19 -0
- package/apps/web/public/turborepo-light.svg +19 -0
- package/apps/web/public/vercel.svg +10 -0
- package/apps/web/public/window.svg +3 -0
- package/apps/web/tailwind.config.js +65 -0
- package/apps/web/tsconfig.json +23 -0
- package/apps/web/types/global.d.ts +4 -0
- package/docker-compose.yml +14 -0
- package/package.json +55 -0
- package/packages/eslint-config/README.md +3 -0
- package/packages/eslint-config/base.js +32 -0
- package/packages/eslint-config/next.js +49 -0
- package/packages/eslint-config/package.json +24 -0
- package/packages/eslint-config/react-internal.js +39 -0
- package/packages/scripts/Auth/jwt.ts +83 -0
- package/packages/scripts/Auth/nextAuth.ts +146 -0
- package/packages/scripts/Auth/passport.ts +234 -0
- package/packages/scripts/backend/django.ts +30 -0
- package/packages/scripts/backend/expressjs.ts +72 -0
- package/packages/scripts/backend/expressts.ts +95 -0
- package/packages/scripts/frontend/angularjs.ts +0 -0
- package/packages/scripts/frontend/angularts.ts +29 -0
- package/packages/scripts/frontend/nextjs.ts +72 -0
- package/packages/scripts/frontend/reactjs.ts +36 -0
- package/packages/scripts/frontend/reactts.ts +34 -0
- package/packages/scripts/frontend/vuejs.ts +43 -0
- package/packages/scripts/frontend/vuets.ts +53 -0
- package/packages/scripts/orms/drizzleSetup.ts +102 -0
- package/packages/scripts/orms/mongoSetup.ts +68 -0
- package/packages/scripts/orms/prismaSetup.ts +14 -0
- package/packages/scripts/ui/shadcn.ts +228 -0
- package/packages/scripts/ui/tailwindcss.ts +126 -0
- package/packages/typescript-config/base.json +19 -0
- package/packages/typescript-config/nextjs.json +12 -0
- package/packages/typescript-config/package.json +9 -0
- package/packages/typescript-config/react-library.json +7 -0
- package/packages/ui/eslint.config.mjs +4 -0
- package/packages/ui/package.json +27 -0
- package/packages/ui/src/button.tsx +20 -0
- package/packages/ui/src/card.tsx +27 -0
- package/packages/ui/src/code.tsx +11 -0
- package/packages/ui/tsconfig.json +8 -0
- package/packages/ui/turbo/generators/config.ts +30 -0
- package/packages/ui/turbo/generators/templates/component.hbs +8 -0
- package/stackd.ts +134 -0
- package/start-web.sh +5 -0
- package/tsconfig.json +111 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/turbo.json +21 -0
@@ -0,0 +1,30 @@
|
|
1
|
+
name: CI/CD Pipeline
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches:
|
6
|
+
- main
|
7
|
+
pull_request:
|
8
|
+
branches:
|
9
|
+
- main
|
10
|
+
|
11
|
+
jobs:
|
12
|
+
build-and-test:
|
13
|
+
name: Build and Test Next.js
|
14
|
+
runs-on: ubuntu-latest
|
15
|
+
|
16
|
+
steps:
|
17
|
+
- name: Checkout code
|
18
|
+
uses: actions/checkout@v4
|
19
|
+
|
20
|
+
- name: Setup Node.js
|
21
|
+
uses: actions/setup-node@v4
|
22
|
+
with:
|
23
|
+
node-version: 18
|
24
|
+
cache: 'npm'
|
25
|
+
|
26
|
+
- name: Install dependencies
|
27
|
+
run: npm install
|
28
|
+
|
29
|
+
- name: Build Next.js App
|
30
|
+
run: npm run build
|
package/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2025 Shiva
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
# STACKD - Full-Stack Scaffolding Tool
|
2
|
+
|
3
|
+
STACKD (Abbreviation TBD) is an open-source scaffolding tool that simplifies the process of setting up a full-stack web application. It allows developers to generate a project with pre-configured frontend, backend, database, authentication, and other essential components in just a few clicks.
|
4
|
+
|
5
|
+
## 📖 Table of Contents
|
6
|
+
|
7
|
+
- [Motivation](#motivation)
|
8
|
+
- [Features](#features)
|
9
|
+
- [Tech Stack Options](#tech-stack-options)
|
10
|
+
- [Installation](#installation)
|
11
|
+
- [Usage](#usage)
|
12
|
+
- [Future Ideas](#future-ideas)
|
13
|
+
- [License](#license)
|
14
|
+
|
15
|
+
## 💡 Motivation
|
16
|
+
|
17
|
+
Every time my team and I participated in a hackathon, we found ourselves spending a significant amount of time setting up the project’s basic structure—configuring the frontend, backend, database, authentication, and other essential components. The same challenge extends to professionals in the industry, where initial setup can be tedious and time-consuming. To solve this, we created STACKD—a tool that eliminates repetitive setup tasks, allowing developers to focus on building their applications right away.
|
18
|
+
|
19
|
+
## 🚀 Features
|
20
|
+
|
21
|
+
- **Flexible Project Setup**: Choose from multiple frontend, backend, database, and authentication options.
|
22
|
+
- **Automated Configuration**: Generates all necessary files, environment variables, and configurations.
|
23
|
+
- **Git Integration**: Initializes a Git repository and sets up the remote origin.
|
24
|
+
- **Pre-configured ORM & Database**: Automatically connects the chosen ORM with the selected database.
|
25
|
+
- **Instant Deployment Readiness**: Sets up authentication, UI frameworks, and other dependencies for a fully functional project.
|
26
|
+
- **Multiple Interfaces**: STACKD provides both a **CLI** and a **Graphical User Interface (GUI)** for easy project setup.
|
27
|
+
|
28
|
+
## 🎥 Demo
|
29
|
+
|
30
|
+
### CLI Demo
|
31
|
+
https://github.com/user-attachments/assets/debe9515-a38f-4ba2-9126-b9b6f95e3a87
|
32
|
+
|
33
|
+
### Web Tool Demo
|
34
|
+
https://github.com/user-attachments/assets/465451f2-1e1a-48b6-a99e-253ef4f28e2d
|
35
|
+
|
36
|
+
|
37
|
+
## 🛠️ Tech Stack Options
|
38
|
+
|
39
|
+
### **Frontend**
|
40
|
+
|
41
|
+
- React.js
|
42
|
+
- React TypeScript
|
43
|
+
- Next.js
|
44
|
+
- Vue.js
|
45
|
+
- Vue TypeScript
|
46
|
+
- Angular TypeScript
|
47
|
+
- Django (Frontend Templates)
|
48
|
+
|
49
|
+
### **Backend**
|
50
|
+
|
51
|
+
- Express.js
|
52
|
+
- Express TypeScript
|
53
|
+
- Django Rest Framework
|
54
|
+
|
55
|
+
### **Database**
|
56
|
+
|
57
|
+
- PostgreSQL
|
58
|
+
- MongoDB
|
59
|
+
|
60
|
+
### **ORM**
|
61
|
+
|
62
|
+
- Prisma
|
63
|
+
- Hazel
|
64
|
+
- Mongoose
|
65
|
+
|
66
|
+
### **UI Framework**
|
67
|
+
|
68
|
+
- ShadCN
|
69
|
+
- Tailwind CSS
|
70
|
+
|
71
|
+
### **Authentication**
|
72
|
+
|
73
|
+
- JWT
|
74
|
+
- NextAuth
|
75
|
+
- Passport
|
76
|
+
|
77
|
+
### 🛆 Installation
|
78
|
+
|
79
|
+
### Prerequisites
|
80
|
+
|
81
|
+
Make sure you have the following installed on your system:
|
82
|
+
|
83
|
+
- Node.js
|
84
|
+
- Git
|
85
|
+
|
86
|
+
### Using `npm`
|
87
|
+
|
88
|
+
```sh
|
89
|
+
npm i @shivasankaran18/stackd
|
90
|
+
npx stackd create
|
91
|
+
```
|
92
|
+
|
93
|
+
### Using `npx`
|
94
|
+
|
95
|
+
```sh
|
96
|
+
npx @shivasankaran18/stackd create
|
97
|
+
```
|
98
|
+
|
99
|
+
## ⚡ Usage
|
100
|
+
|
101
|
+
Select the frontend, backend, UI, database, ORM, authentication method, database URL, and GitHub URL, and **BOOM!** Your project is ready to work.
|
102
|
+
|
103
|
+
## 🔮 Future Ideas
|
104
|
+
|
105
|
+
- Adding desktop tools like **Electron**.
|
106
|
+
- Expanding support for more development tools and frameworks.
|
107
|
+
- Adding mobile app development tools.
|
108
|
+
- Building a **robust and efficient** platform that works across **Windows, Linux, and macOS**.
|
109
|
+
- Integrating **automated deployment** features, allowing users to deploy their applications instantly.
|
110
|
+
- Enabling **Git commit automation and CI/CD integration**, so projects stay updated with minimal manual effort.
|
111
|
+
|
112
|
+
## 📜 License
|
113
|
+
|
114
|
+
This project is licensed under the MIT License. You are free to use, modify, and distribute this software under the terms of the MIT LICENSE.
|
115
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
{
|
2
|
+
"name": "@shivasankaran18/stackd",
|
3
|
+
"version": "1.0.0",
|
4
|
+
"main": "index.js",
|
5
|
+
"type": "module",
|
6
|
+
"scripts": {
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
8
|
+
},
|
9
|
+
"bin": {
|
10
|
+
"mycli": "./cli.js"
|
11
|
+
},
|
12
|
+
"keywords": [],
|
13
|
+
"author": "",
|
14
|
+
"license": "ISC",
|
15
|
+
"description": "",
|
16
|
+
"dependencies": {
|
17
|
+
"@types/chalk": "^2.2.4",
|
18
|
+
"@types/commander": "^2.12.5",
|
19
|
+
"@types/node": "^22.13.5",
|
20
|
+
"chalk": "4",
|
21
|
+
"commander": "^13.1.0",
|
22
|
+
"fs": "^0.0.1-security",
|
23
|
+
"gradient-string": "^3.0.0",
|
24
|
+
"inquirer": "^12.4.2",
|
25
|
+
"ora": "^8.2.0",
|
26
|
+
"path": "^0.12.7"
|
27
|
+
},
|
28
|
+
"devDependencies": {
|
29
|
+
"ts-node": "^10.9.2",
|
30
|
+
"typescript": "^5.7.3"
|
31
|
+
}
|
32
|
+
}
|
@@ -0,0 +1,271 @@
|
|
1
|
+
#!/usr/bin/env node
|
2
|
+
import { program } from 'commander';
|
3
|
+
import inquirer from 'inquirer';
|
4
|
+
import chalk from 'chalk';
|
5
|
+
import { createProject } from './commands/create.js'
|
6
|
+
|
7
|
+
export interface ProjectConfig {
|
8
|
+
projectName: string;
|
9
|
+
projectPath: string;
|
10
|
+
frontendPort: number;
|
11
|
+
backendPort: number;
|
12
|
+
frontend: string;
|
13
|
+
backend: string;
|
14
|
+
database: string;
|
15
|
+
orm: string;
|
16
|
+
auth: string;
|
17
|
+
dbUrl: string;
|
18
|
+
}
|
19
|
+
|
20
|
+
interface Answers {
|
21
|
+
projectPath: string;
|
22
|
+
frontendPort: number;
|
23
|
+
backendPort: number;
|
24
|
+
frontend: string;
|
25
|
+
backend: string;
|
26
|
+
database: string;
|
27
|
+
orm: string;
|
28
|
+
auth: string;
|
29
|
+
dbUrl: string;
|
30
|
+
projectName:string;
|
31
|
+
}
|
32
|
+
|
33
|
+
const showBanner = () => {
|
34
|
+
console.log(chalk.cyan(`
|
35
|
+
██████╗████████╗ █████╗ ██████╗██╗ ██╗'██████╗
|
36
|
+
██╔════╝╚══██╔══╝██╔══██╗██╔════╝██║ ██╔╝██╔══██╗
|
37
|
+
╚█████╗ ██║ ███████║██║ █████═╝ ██║ ██║
|
38
|
+
╚═══██╗ ██║ ██╔══██║██║ ██╔═██╗ ██║ ██║
|
39
|
+
██████╔╝ ██║ ██║ ██║╚██████╗██║ ██╗██████╔╝
|
40
|
+
╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚═════╝
|
41
|
+
`));
|
42
|
+
console.log(chalk.yellow.bold(' 🚀 Full Stack Project Generator\n'));
|
43
|
+
};
|
44
|
+
|
45
|
+
|
46
|
+
const createBorder = () => {
|
47
|
+
const border = '='.repeat(60);
|
48
|
+
return chalk.cyan(border);
|
49
|
+
|
50
|
+
};
|
51
|
+
|
52
|
+
const CHOICES = {
|
53
|
+
EXPRESS_TS: 'Express + TypeScript',
|
54
|
+
EXPRESS_JS: 'Express (JavaScript)',
|
55
|
+
DJANGO: 'Django',
|
56
|
+
REACT_TS: 'React + TypeScript',
|
57
|
+
REACT_JS: 'React (JavaScript)',
|
58
|
+
VUE_TS: 'Vue + TypeScript',
|
59
|
+
VUE_JS: 'Vue (JavaScript)',
|
60
|
+
DJANGO_TEMPLATES: 'Django Templates',
|
61
|
+
NONE: 'None',
|
62
|
+
SKIP: 'Skip',
|
63
|
+
POSTGRESQL: 'PostgreSQL',
|
64
|
+
MONGODB: 'MongoDB',
|
65
|
+
PRISMA: 'Prisma',
|
66
|
+
DRIZZLE: 'Drizzle',
|
67
|
+
MONGOOSE: 'Mongoose',
|
68
|
+
JWT: 'JWT',
|
69
|
+
NEXTAUTH: 'NextAuth',
|
70
|
+
PASSPORT: 'Passport'
|
71
|
+
};
|
72
|
+
|
73
|
+
program
|
74
|
+
.command('run ')
|
75
|
+
.description('Create a new full-stack project')
|
76
|
+
.action(async () => {
|
77
|
+
// showBanner();
|
78
|
+
// console.log(createBorder());
|
79
|
+
// console.log(chalk.bgCyan.white.bold('\n 💫 Let\'s create something awesome! \n'));
|
80
|
+
// console.log(createBorder() + '\n');
|
81
|
+
|
82
|
+
const projectSettings = await inquirer.prompt([
|
83
|
+
{
|
84
|
+
type: 'input',
|
85
|
+
name: 'projectPath',
|
86
|
+
message: chalk.magenta.bold('📁 Where do you want to create the project?'),
|
87
|
+
|
88
|
+
},
|
89
|
+
{
|
90
|
+
type:'input',
|
91
|
+
name:'projectName',
|
92
|
+
message:chalk.magenta.bold('💫 Enter the project name:'),
|
93
|
+
},
|
94
|
+
|
95
|
+
{
|
96
|
+
type: 'number',
|
97
|
+
name: 'frontendPort',
|
98
|
+
message: chalk.blue.bold('🌐 Enter frontend port:'),
|
99
|
+
default: 3000,
|
100
|
+
},
|
101
|
+
{
|
102
|
+
type: 'number',
|
103
|
+
name: 'backendPort',
|
104
|
+
message: chalk.green.bold('⚙️ Enter backend port:'),
|
105
|
+
default: 3001,
|
106
|
+
}
|
107
|
+
]);
|
108
|
+
|
109
|
+
|
110
|
+
const frontendChoice = await inquirer.prompt([
|
111
|
+
{
|
112
|
+
type: 'list',
|
113
|
+
name: 'frontend',
|
114
|
+
message: chalk.yellow.bold('🎨 Choose a frontend framework:'),
|
115
|
+
choices: [
|
116
|
+
chalk.blue(CHOICES.REACT_TS),
|
117
|
+
chalk.blue(CHOICES.REACT_JS),
|
118
|
+
chalk.green(CHOICES.VUE_TS),
|
119
|
+
chalk.green(CHOICES.VUE_JS),
|
120
|
+
chalk.green(CHOICES.DJANGO_TEMPLATES),
|
121
|
+
CHOICES.SKIP
|
122
|
+
],
|
123
|
+
default: CHOICES.SKIP,
|
124
|
+
}
|
125
|
+
]);
|
126
|
+
|
127
|
+
|
128
|
+
const backendChoice = await inquirer.prompt([
|
129
|
+
{
|
130
|
+
type: 'list',
|
131
|
+
name: 'backend',
|
132
|
+
message: chalk.cyan.bold('🛠️ Choose a backend framework:'),
|
133
|
+
choices: (answers) => {
|
134
|
+
if (frontendChoice.frontend === chalk.green(CHOICES.DJANGO_TEMPLATES)) {
|
135
|
+
return [chalk.green(CHOICES.DJANGO)];
|
136
|
+
}
|
137
|
+
return [
|
138
|
+
chalk.blue(CHOICES.EXPRESS_TS),
|
139
|
+
chalk.blue(CHOICES.EXPRESS_JS),
|
140
|
+
chalk.green(CHOICES.DJANGO),
|
141
|
+
CHOICES.SKIP
|
142
|
+
];
|
143
|
+
},
|
144
|
+
default: chalk.blue(CHOICES.EXPRESS_TS),
|
145
|
+
}
|
146
|
+
]);
|
147
|
+
|
148
|
+
|
149
|
+
const databaseChoice = await inquirer.prompt([
|
150
|
+
{
|
151
|
+
type: 'list',
|
152
|
+
name: 'database',
|
153
|
+
message: chalk.magenta.bold('🗄️ Choose a database:'),
|
154
|
+
choices: [
|
155
|
+
chalk.blue(CHOICES.POSTGRESQL),
|
156
|
+
chalk.green(CHOICES.MONGODB),
|
157
|
+
CHOICES.SKIP
|
158
|
+
],
|
159
|
+
default: CHOICES.SKIP,
|
160
|
+
}
|
161
|
+
]);
|
162
|
+
|
163
|
+
|
164
|
+
let ormChoice = { orm: CHOICES.SKIP };
|
165
|
+
if (databaseChoice.database !== CHOICES.SKIP) {
|
166
|
+
ormChoice = await inquirer.prompt([
|
167
|
+
{
|
168
|
+
type: 'list',
|
169
|
+
name: 'orm',
|
170
|
+
message: chalk.yellow.bold('🔗 Choose an ORM:'),
|
171
|
+
choices: () => {
|
172
|
+
const cleanDatabase = databaseChoice.database.replace(/\u001b\[\d+m/g, '').trim();
|
173
|
+
return cleanDatabase === CHOICES.POSTGRESQL
|
174
|
+
? [chalk.magenta(CHOICES.PRISMA), chalk.cyan(CHOICES.DRIZZLE), CHOICES.SKIP]
|
175
|
+
: [chalk.green(CHOICES.MONGOOSE), CHOICES.SKIP];
|
176
|
+
},
|
177
|
+
default: CHOICES.SKIP,
|
178
|
+
}
|
179
|
+
]);
|
180
|
+
}
|
181
|
+
|
182
|
+
// Step 6: Authentication Selection
|
183
|
+
const authChoice = await inquirer.prompt([
|
184
|
+
{
|
185
|
+
type: 'list',
|
186
|
+
name: 'auth',
|
187
|
+
message: chalk.cyan.bold('🔐 Choose an authentication method:'),
|
188
|
+
choices: [
|
189
|
+
chalk.yellow(CHOICES.JWT),
|
190
|
+
chalk.blue(CHOICES.NEXTAUTH),
|
191
|
+
chalk.green(CHOICES.PASSPORT),
|
192
|
+
CHOICES.SKIP
|
193
|
+
],
|
194
|
+
default: CHOICES.SKIP,
|
195
|
+
}
|
196
|
+
]);
|
197
|
+
|
198
|
+
let dbUrlChoice = { dbUrl: '' };
|
199
|
+
if (databaseChoice.database !== CHOICES.SKIP) {
|
200
|
+
dbUrlChoice = await inquirer.prompt([
|
201
|
+
{
|
202
|
+
type: 'input',
|
203
|
+
name: 'dbUrl',
|
204
|
+
message: chalk.green.bold('🔌 Enter database connection URL:'),
|
205
|
+
}
|
206
|
+
]);
|
207
|
+
}
|
208
|
+
|
209
|
+
|
210
|
+
const answers = {
|
211
|
+
...projectSettings,
|
212
|
+
...frontendChoice,
|
213
|
+
...backendChoice,
|
214
|
+
...databaseChoice,
|
215
|
+
...ormChoice,
|
216
|
+
...authChoice,
|
217
|
+
...dbUrlChoice,
|
218
|
+
};
|
219
|
+
|
220
|
+
|
221
|
+
const cleanAnswers = Object.entries(answers).reduce((acc, [key, value]) => {
|
222
|
+
if (typeof value === 'string') {
|
223
|
+
const cleanValue = value.replace(/\u001b\[\d+m/g, '').trim();
|
224
|
+
// @ts-ignore
|
225
|
+
acc[key] = cleanValue;
|
226
|
+
} else {
|
227
|
+
// @ts-ignore
|
228
|
+
acc[key] = value;
|
229
|
+
}
|
230
|
+
return acc;
|
231
|
+
}, {});
|
232
|
+
|
233
|
+
|
234
|
+
// @ts-ignore
|
235
|
+
if (cleanAnswers.database !== 'Skip' && cleanAnswers.orm !== 'Skip') {
|
236
|
+
// @ts-ignore
|
237
|
+
if (cleanAnswers.database === 'MongoDB' && cleanAnswers.orm !== 'Mongoose') {
|
238
|
+
console.log('\n' + createBorder());
|
239
|
+
console.error(chalk.bgRed.white.bold(" ❌ Error: MongoDB supports only Mongoose ORM. "));
|
240
|
+
console.log(createBorder());
|
241
|
+
process.exit(1);
|
242
|
+
}
|
243
|
+
// @ts-ignore
|
244
|
+
if (cleanAnswers.database === 'PostgreSQL' && !['Prisma', 'Drizzle'].includes(cleanAnswers.orm)) {
|
245
|
+
console.log('\n' + createBorder());
|
246
|
+
console.error(chalk.bgRed.white.bold(" ❌ Error: PostgreSQL supports only Prisma or Drizzle ORM. "));
|
247
|
+
console.log(createBorder());
|
248
|
+
process.exit(1);
|
249
|
+
}
|
250
|
+
}
|
251
|
+
|
252
|
+
|
253
|
+
// @ts-ignore
|
254
|
+
if (cleanAnswers.frontend === 'Django Templates') {
|
255
|
+
// @ts-ignore
|
256
|
+
cleanAnswers.backend = 'Django';
|
257
|
+
}
|
258
|
+
// @ts-ignore
|
259
|
+
if (cleanAnswers.backend === 'Django') {
|
260
|
+
// @ts-ignore
|
261
|
+
cleanAnswers.frontend = 'Django Templates';
|
262
|
+
}
|
263
|
+
|
264
|
+
console.log('\n' + createBorder());
|
265
|
+
console.log(chalk.bgGreen.black.bold("\n 📦 Creating your project... \n"));
|
266
|
+
console.log(createBorder() + '\n');
|
267
|
+
// @ts-ignore
|
268
|
+
await createProject(projectSettings.projectName, cleanAnswers);
|
269
|
+
});
|
270
|
+
|
271
|
+
program.parse(process.argv);
|
@@ -0,0 +1,162 @@
|
|
1
|
+
import { join } from 'path';
|
2
|
+
import { createReactTS } from '../scripts/frontend/reactts.js';
|
3
|
+
import { createReactJS } from '../scripts/frontend/reactjs.js';
|
4
|
+
import { createVueTS } from '../scripts/frontend/vuets.js';
|
5
|
+
import { createVueJS } from '../scripts/frontend/vuejs.js';
|
6
|
+
import { createExpressTS } from '../scripts/backend/expressts.js';
|
7
|
+
import { createExpressJS } from '../scripts/backend/expressjs.js';
|
8
|
+
import { installDjangoDependencies } from '../scripts/backend/django.js';
|
9
|
+
import { setupPrisma } from '../scripts/orms/prismaSetup.js';
|
10
|
+
import { setupDrizzle } from '../scripts/orms/drizzleSetup.js';
|
11
|
+
import { setupMongoose } from '../scripts/orms/mongoSetup.js';
|
12
|
+
import { setupNextAuth } from '../scripts/Auth/nextAuth.js';
|
13
|
+
import { setupPassport } from '../scripts/Auth/passport.js';
|
14
|
+
import { jwtAuthts } from '../scripts/Auth/jwt.js';
|
15
|
+
import chalk from 'chalk';
|
16
|
+
import ora from 'ora';
|
17
|
+
import { mkdir } from 'fs/promises';
|
18
|
+
import { ProjectConfig } from '../cli.js';
|
19
|
+
|
20
|
+
const emitLog = (message: string): void => {
|
21
|
+
console.log(`[Emit Logs]: ${message}`);
|
22
|
+
};
|
23
|
+
|
24
|
+
export async function createProject(projectName: string, options: ProjectConfig) {
|
25
|
+
const spinner = ora('Creating project...').start();
|
26
|
+
console.log(options);
|
27
|
+
console.log(projectName);
|
28
|
+
try {
|
29
|
+
const projectDir = join(options.projectPath, projectName);
|
30
|
+
const config = {
|
31
|
+
projectName,
|
32
|
+
projectPath: options.projectPath,
|
33
|
+
frontendPort: options.frontendPort,
|
34
|
+
backendPort: options.backendPort,
|
35
|
+
dbUrl: options.dbUrl,
|
36
|
+
};
|
37
|
+
|
38
|
+
// Create project directory
|
39
|
+
await mkdir(projectDir, { recursive: true });
|
40
|
+
|
41
|
+
// Frontend setup
|
42
|
+
spinner.text = 'Setting up frontend...';
|
43
|
+
switch(options.frontend) {
|
44
|
+
case 'React + TypeScript':
|
45
|
+
await createReactTS(config, projectDir, emitLog);
|
46
|
+
break;
|
47
|
+
case 'React (JavaScript)':
|
48
|
+
await createReactJS(config, projectDir, emitLog);
|
49
|
+
break;
|
50
|
+
case 'Vue + TypeScript':
|
51
|
+
await createVueTS(config, projectDir, emitLog);
|
52
|
+
break;
|
53
|
+
case 'Vue (JavaScript)':
|
54
|
+
await createVueJS(config, projectDir, emitLog);
|
55
|
+
break;
|
56
|
+
case 'Django Templates':
|
57
|
+
// Django templates will be handled with backend setup
|
58
|
+
break;
|
59
|
+
case 'Skip':
|
60
|
+
emitLog('Skipping frontend setup');
|
61
|
+
break;
|
62
|
+
default:
|
63
|
+
emitLog('Unknown frontend choice');
|
64
|
+
break;
|
65
|
+
}
|
66
|
+
|
67
|
+
// Backend setup
|
68
|
+
spinner.text = 'Setting up backend...';
|
69
|
+
switch(options.backend) {
|
70
|
+
case 'Express + TypeScript':
|
71
|
+
await createExpressTS(config, projectDir,emitLog);
|
72
|
+
break;
|
73
|
+
case 'Express (JavaScript)':
|
74
|
+
await createExpressJS(config, projectDir,emitLog);
|
75
|
+
break;
|
76
|
+
case 'Django':
|
77
|
+
await installDjangoDependencies(projectDir);
|
78
|
+
break;
|
79
|
+
case 'Skip':
|
80
|
+
emitLog('Skipping backend setup');
|
81
|
+
break;
|
82
|
+
default:
|
83
|
+
emitLog('Unknown backend choice');
|
84
|
+
break;
|
85
|
+
}
|
86
|
+
|
87
|
+
// Database & ORM setup
|
88
|
+
if (options.database !== 'Skip') {
|
89
|
+
spinner.text = 'Setting up database and ORM...';
|
90
|
+
|
91
|
+
// Set up ORM based on database choice
|
92
|
+
if (options.orm !== 'Skip') {
|
93
|
+
switch(options.orm) {
|
94
|
+
case 'Prisma':
|
95
|
+
await setupPrisma(config, projectDir,emitLog);
|
96
|
+
break;
|
97
|
+
case 'Drizzle':
|
98
|
+
await setupDrizzle(config, projectDir,emitLog);
|
99
|
+
break;
|
100
|
+
case 'Mongoose':
|
101
|
+
await setupMongoose(config, projectDir,emitLog);
|
102
|
+
break;
|
103
|
+
default:
|
104
|
+
emitLog('Unknown ORM choice');
|
105
|
+
break;
|
106
|
+
}
|
107
|
+
}
|
108
|
+
}
|
109
|
+
|
110
|
+
// Authentication setup
|
111
|
+
if (options.auth !== 'Skip') {
|
112
|
+
spinner.text = 'Setting up authentication...';
|
113
|
+
switch(options.auth ) {
|
114
|
+
case 'JWT':
|
115
|
+
await jwtAuthts(config, projectDir,emitLog);
|
116
|
+
break;
|
117
|
+
// case 'NextAuth':
|
118
|
+
// await setupNextAuth(config, projectDir,emitLog);
|
119
|
+
// break;
|
120
|
+
case 'Passport':
|
121
|
+
await setupPassport(config, projectDir,emitLog );
|
122
|
+
break;
|
123
|
+
default:
|
124
|
+
emitLog('Unknown authentication choice');
|
125
|
+
break;
|
126
|
+
}
|
127
|
+
}
|
128
|
+
|
129
|
+
spinner.succeed(chalk.green('Project created successfully!'));
|
130
|
+
|
131
|
+
|
132
|
+
console.log('\nTo get started:');
|
133
|
+
console.log(chalk.cyan(` cd ${projectName}`));
|
134
|
+
|
135
|
+
// Add specific instructions based on choices
|
136
|
+
if (options.frontend !== 'Skip' || options.backend !== 'Skip') {
|
137
|
+
// console.log(chalk.cyan(' npm install'));
|
138
|
+
|
139
|
+
if (options.frontend === 'Django Templates' || options.backend === 'Django') {
|
140
|
+
console.log(chalk.cyan(' python manage.py runserver'));
|
141
|
+
} else {
|
142
|
+
console.log(chalk.cyan(' npm run dev'));
|
143
|
+
}
|
144
|
+
}
|
145
|
+
|
146
|
+
// Add database specific instructions
|
147
|
+
if (options.database !== 'Skip') {
|
148
|
+
console.log(chalk.yellow('\nDatabase Setup:'));
|
149
|
+
if (options.orm === 'Prisma') {
|
150
|
+
console.log(chalk.cyan(' npx prisma generate'));
|
151
|
+
console.log(chalk.cyan(' npx prisma migrate dev'));
|
152
|
+
} else if (options.orm === 'Mongoose') {
|
153
|
+
console.log(chalk.cyan(' Make sure MongoDB is running'));
|
154
|
+
}
|
155
|
+
}
|
156
|
+
|
157
|
+
} catch (error) {
|
158
|
+
spinner.fail(chalk.red('Failed to create project'));
|
159
|
+
console.error(error);
|
160
|
+
process.exit(1);
|
161
|
+
}
|
162
|
+
}
|