@shakil-dev/shakil-stack 1.0.0 → 1.2.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/publish.yml +47 -0
- package/README.md +79 -0
- package/bin/index.js +40 -2
- package/package.json +1 -1
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
name: Publish to NPM
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: write
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
publish:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- name: Checkout Code
|
|
16
|
+
uses: actions/checkout@v4
|
|
17
|
+
with:
|
|
18
|
+
fetch-depth: 0 # We need to fetch all history to push tags
|
|
19
|
+
|
|
20
|
+
- name: Setup Node.js
|
|
21
|
+
uses: actions/setup-node@v4
|
|
22
|
+
with:
|
|
23
|
+
node-version: '20'
|
|
24
|
+
registry-url: 'https://registry.npmjs.org'
|
|
25
|
+
|
|
26
|
+
- name: Install Dependencies
|
|
27
|
+
run: npm ci
|
|
28
|
+
|
|
29
|
+
- name: Debug Git Status
|
|
30
|
+
run: git status
|
|
31
|
+
|
|
32
|
+
- name: Set Git Identity
|
|
33
|
+
run: |
|
|
34
|
+
git config --global user.name "github-actions[bot]"
|
|
35
|
+
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
|
36
|
+
git add . # Ensure any changes like package-lock.json are staged
|
|
37
|
+
|
|
38
|
+
- name: Bump Version
|
|
39
|
+
run: npm version patch
|
|
40
|
+
|
|
41
|
+
- name: Publish to NPM
|
|
42
|
+
run: npm publish --access public
|
|
43
|
+
env:
|
|
44
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
45
|
+
|
|
46
|
+
- name: Push Version Change to GitHub
|
|
47
|
+
run: git push origin main --tags
|
package/README.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Shakil-Stack Project Generator 🚀
|
|
2
|
+
|
|
3
|
+
**Shakil-Stack** is a powerful full-stack project generator CLI that scaffolds a robust, production-ready environment based on the **EchoNet** backend architecture and a modern **Next.js** frontend.
|
|
4
|
+
|
|
5
|
+
## ✨ Features
|
|
6
|
+
|
|
7
|
+
- **🛡️ EchoNet-Style Backend**:
|
|
8
|
+
- **Architecture**: Clean `src/app/...` structure (config, middleware, routes, utils).
|
|
9
|
+
- **Database**: Prisma 7+ with PostgreSQL adapter.
|
|
10
|
+
- **Authentication**: Pre-configured **Better Auth** with User, Session, and Account models.
|
|
11
|
+
- **Security**: Helmet, Express Rate Limit, and Request Sanitizer.
|
|
12
|
+
- **Error Handling**: Global error handler with `ApiError` support.
|
|
13
|
+
- **Validation**: Zod-ready structure.
|
|
14
|
+
- **🌐 Next.js Frontend**:
|
|
15
|
+
- Modern Next.js (App Router, TypeScript, Tailwind CSS).
|
|
16
|
+
- Pre-defined project folders: `config`, `hooks`, `lib`, `services`, `types`.
|
|
17
|
+
- **🛠️ Interactive Setup**: Choose your package manager (npm, pnpm, yarn) and auto-install dependencies.
|
|
18
|
+
|
|
19
|
+
## 🚀 Getting Started
|
|
20
|
+
|
|
21
|
+
You can generate a new project instantly using `npx`:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npx @shakil-dev/shakil-stack my-awesome-project
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Or, if already installed globally:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
shakil-stack my-awesome-project
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## 📂 Project Structure
|
|
34
|
+
|
|
35
|
+
```text
|
|
36
|
+
my-awesome-project/
|
|
37
|
+
├── backend/
|
|
38
|
+
│ ├── prisma/
|
|
39
|
+
│ │ └── schema.prisma (Better Auth & Prisma 7 ready)
|
|
40
|
+
│ ├── src/
|
|
41
|
+
│ │ ├── server.ts
|
|
42
|
+
│ │ └── app/ (EchoNet logic)
|
|
43
|
+
│ └── .env
|
|
44
|
+
├── frontend/ (Next.js App)
|
|
45
|
+
│ ├── src/
|
|
46
|
+
│ │ ├── app/
|
|
47
|
+
│ │ ├── components/
|
|
48
|
+
│ │ └── ...
|
|
49
|
+
└── README.md
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## 🏗️ Post-Installation Steps
|
|
53
|
+
|
|
54
|
+
After the generator finishes, follow these steps to start your development:
|
|
55
|
+
|
|
56
|
+
1. **Configure Database**: Update the `DATABASE_URL` in `backend/.env`.
|
|
57
|
+
2. **Start Backend**:
|
|
58
|
+
```bash
|
|
59
|
+
cd backend
|
|
60
|
+
pnpm dev # or npm run dev
|
|
61
|
+
```
|
|
62
|
+
3. **Start Frontend**:
|
|
63
|
+
```bash
|
|
64
|
+
cd frontend
|
|
65
|
+
pnpm dev # or npm run dev
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## 📜 Commands (Backend)
|
|
69
|
+
|
|
70
|
+
- `pnpm dev`: Starts the server with `tsx` and `nodemon`.
|
|
71
|
+
- `pnpm build`: Builds the project using `tsup`.
|
|
72
|
+
- `pnpm start`: Runs the built project from `dist/`.
|
|
73
|
+
|
|
74
|
+
## 🤝 Contributing
|
|
75
|
+
|
|
76
|
+
Feel free to open issues or submit pull requests to improve the Shakil-Stack generator!
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
Developed with by **Shakil Ahmed Billal**
|
package/bin/index.js
CHANGED
|
@@ -69,6 +69,7 @@ async function main() {
|
|
|
69
69
|
spinner.text = `📦 Running create-next-app for frontend...`;
|
|
70
70
|
spinner.stop();
|
|
71
71
|
|
|
72
|
+
// We run create-next-app in the project root to create the 'frontend' folder
|
|
72
73
|
const nextAppCmd = `npx create-next-app@latest frontend --typescript --tailwind --eslint --app --src-dir --import-alias "@/*" --use-${packageManager} --no-git`;
|
|
73
74
|
try {
|
|
74
75
|
execSync(nextAppCmd, { cwd: projectPath, stdio: 'inherit' });
|
|
@@ -88,9 +89,9 @@ async function main() {
|
|
|
88
89
|
// 5. Root Files
|
|
89
90
|
await fs.outputFile(path.join(projectPath, '.env'), 'DATABASE_URL="postgresql://user:password@localhost:5432/mydb"\nPORT=8000\nNODE_ENV=development\nJWT_SECRET="your-secret-key"');
|
|
90
91
|
await fs.outputFile(path.join(projectPath, '.gitignore'), 'node_modules\n.env\ndist\n*.db\n.next\n.DS_Store');
|
|
91
|
-
await fs.outputFile(path.join(projectPath, 'README.md'), `# ${projectName}\n\nGenerated with Full
|
|
92
|
+
await fs.outputFile(path.join(projectPath, 'README.md'), `# ${projectName}\n\nGenerated with Full Shakil-Stack CLI.`);
|
|
92
93
|
|
|
93
|
-
// 6. Backend Files (
|
|
94
|
+
// 6. Backend Files (Complete EchoNet Clone)
|
|
94
95
|
|
|
95
96
|
const serverTs = `import { Server } from 'http';
|
|
96
97
|
import app from './app.js';
|
|
@@ -304,6 +305,7 @@ export const sanitizeRequest = (req: Request, res: Response, next: NextFunction)
|
|
|
304
305
|
|
|
305
306
|
datasource db {
|
|
306
307
|
provider = "postgresql"
|
|
308
|
+
url = env("DATABASE_URL")
|
|
307
309
|
}
|
|
308
310
|
|
|
309
311
|
model User {
|
|
@@ -342,6 +344,39 @@ model Account {
|
|
|
342
344
|
updatedAt DateTime @updatedAt
|
|
343
345
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
344
346
|
}
|
|
347
|
+
`;
|
|
348
|
+
|
|
349
|
+
const prismaConfigTs = `import "dotenv/config";
|
|
350
|
+
import { defineConfig } from "prisma/config";
|
|
351
|
+
import process from "process";
|
|
352
|
+
|
|
353
|
+
export default defineConfig({
|
|
354
|
+
schema: "prisma/schema.prisma",
|
|
355
|
+
datasource: {
|
|
356
|
+
url: process.env.DATABASE_URL,
|
|
357
|
+
},
|
|
358
|
+
});
|
|
359
|
+
`;
|
|
360
|
+
|
|
361
|
+
const tsconfigTs = `{
|
|
362
|
+
"compilerOptions": {
|
|
363
|
+
"target": "ES2022",
|
|
364
|
+
"module": "NodeNext",
|
|
365
|
+
"moduleResolution": "NodeNext",
|
|
366
|
+
"outDir": "./dist",
|
|
367
|
+
"rootDir": "./src",
|
|
368
|
+
"strict": true,
|
|
369
|
+
"esModuleInterop": true,
|
|
370
|
+
"skipLibCheck": true,
|
|
371
|
+
"forceConsistentCasingInFileNames": true,
|
|
372
|
+
"baseUrl": ".",
|
|
373
|
+
"paths": {
|
|
374
|
+
"@/*": ["src/*"]
|
|
375
|
+
}
|
|
376
|
+
},
|
|
377
|
+
"include": ["src/**/*"],
|
|
378
|
+
"exclude": ["node_modules", "dist"]
|
|
379
|
+
}
|
|
345
380
|
`;
|
|
346
381
|
|
|
347
382
|
// Write backend files
|
|
@@ -358,6 +393,9 @@ model Account {
|
|
|
358
393
|
await fs.outputFile(path.join(projectPath, 'backend', 'src', 'app', 'utils', 'sanitizer.ts'), sanitizerTs);
|
|
359
394
|
await fs.outputFile(path.join(projectPath, 'backend', 'src', 'app', 'errorHelpers', 'ApiError.ts'), apiErrorTs);
|
|
360
395
|
await fs.outputFile(path.join(projectPath, 'backend', 'prisma', 'schema.prisma'), schemaPrisma);
|
|
396
|
+
await fs.outputFile(path.join(projectPath, 'backend', 'prisma.config.ts'), prismaConfigTs);
|
|
397
|
+
await fs.outputFile(path.join(projectPath, 'backend', 'tsconfig.json'), tsconfigTs);
|
|
398
|
+
await fs.outputFile(path.join(projectPath, 'backend', '.gitignore'), 'node_modules\ndist\n.env');
|
|
361
399
|
await fs.outputFile(path.join(projectPath, 'backend', '.env'), 'DATABASE_URL="postgresql://user:password@localhost:5432/mydb"\nJWT_SECRET="your-secret-key"');
|
|
362
400
|
|
|
363
401
|
// Backend package.json
|