vasuzex 2.3.11 → 2.3.13
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/CHANGELOG.md +29 -0
- package/README.md +505 -514
- package/framework/Database/Model.js +12 -4
- package/frontend/react-ui/components/DataTable/DataTable.jsx +48 -7
- package/jsconfig.json +1 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,710 +1,701 @@
|
|
|
1
|
-
# Vasuzex
|
|
1
|
+
# Vasuzex
|
|
2
2
|
|
|
3
|
-
> Laravel-inspired Node.js framework
|
|
3
|
+
> A Laravel-inspired Node.js framework built for **multi-app monorepos** — shared models, shared config, multiple APIs and frontends under one roof, powered by Turborepo.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/vasuzex)
|
|
6
|
+
[](https://www.npmjs.com/package/vasuzex)
|
|
6
7
|
[](https://opensource.org/licenses/MIT)
|
|
7
8
|
[](https://nodejs.org)
|
|
8
|
-
[](https://pnpm.io)
|
|
10
|
+
|
|
11
|
+
**[📖 Full Documentation →](https://vasuzex.xdeve.com/guide/)**
|
|
9
12
|
|
|
10
13
|
---
|
|
11
14
|
|
|
12
|
-
|
|
15
|
+
---
|
|
13
16
|
|
|
17
|
+
## What is Vasuzex?
|
|
14
18
|
|
|
15
|
-
|
|
19
|
+
Vasuzex is a Laravel-inspired Node.js framework **purpose-built for monorepo applications**. Unlike traditional Node.js frameworks that manage a single server, Vasuzex treats your entire product as a workspace — with shared database models, shared configuration, and multiple apps (APIs + frontends) all living under one roof.
|
|
16
20
|
|
|
17
|
-
|
|
18
|
-
V2 introduces a revolutionary approach to dependency management in monorepos:
|
|
21
|
+
Most real-world products aren't a single API. You need a customer-facing storefront, a merchant dashboard, and an admin panel — each with its own API, its own frontend, and its own auth rules. But all three share the same database and the same business logic.
|
|
19
22
|
|
|
20
|
-
|
|
21
|
-
✅ **64% Disk Space Savings** - No duplicate packages across apps
|
|
22
|
-
✅ **Centralized Version Control** - Manage all versions from root
|
|
23
|
-
✅ **Faster CI/CD** - One installation for entire monorepo
|
|
24
|
-
✅ **Zero Config for Apps** - Apps inherit all dependencies automatically
|
|
23
|
+
**Vasuzex solves this directly:**
|
|
25
24
|
|
|
26
|
-
|
|
25
|
+
| Without Vasuzex | With Vasuzex |
|
|
26
|
+
|---|---|
|
|
27
|
+
| 3–6 separate repositories | One monorepo project |
|
|
28
|
+
| Duplicated models & migrations across every repo | Shared `database/models/` — one source of truth |
|
|
29
|
+
| Version conflicts between app dependencies | Single `node_modules` via pnpm hoisting |
|
|
30
|
+
| Manual port management | Auto-assigned ports per app |
|
|
31
|
+
| Manual Turborepo setup | Pre-configured `turbo.json` out of the box |
|
|
27
32
|
|
|
28
33
|
---
|
|
29
34
|
|
|
30
|
-
##
|
|
35
|
+
## Requirements
|
|
31
36
|
|
|
32
|
-
|
|
33
|
-
- Node.js >= 18.0.0
|
|
34
|
-
- pnpm >= 10.0.0 (will be installed automatically if missing)
|
|
37
|
+
Before you begin, ensure your machine has:
|
|
35
38
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
```
|
|
39
|
+
- **Node.js v18+** (v22 recommended) — Vasuzex uses ESM modules
|
|
40
|
+
- **pnpm v8+** — Required for workspace management: `npm install -g pnpm`
|
|
41
|
+
- **PostgreSQL 14+**, **MySQL 8+**, or **SQLite** — at least one database engine
|
|
40
42
|
|
|
41
|
-
|
|
42
|
-
- ✅ Install pnpm if not present
|
|
43
|
-
- ✅ Set up project structure
|
|
44
|
-
- ✅ Configure hybrid dependencies
|
|
45
|
-
- ✅ Install all dependencies (single node_modules)
|
|
46
|
-
- ✅ Generate starter apps (optional)
|
|
43
|
+
---
|
|
47
44
|
|
|
48
|
-
|
|
49
|
-
**Disk Space:** 250-300MB (vs 600-800MB in traditional monorepos)
|
|
45
|
+
## Quick Start
|
|
50
46
|
|
|
51
|
-
|
|
47
|
+
### Step 1 — Install Globally
|
|
52
48
|
|
|
53
|
-
|
|
49
|
+
```bash
|
|
50
|
+
npm install -g vasuzex
|
|
51
|
+
|
|
52
|
+
# Verify
|
|
53
|
+
create-vasuzex --version
|
|
54
|
+
vasuzex --version
|
|
55
|
+
```
|
|
54
56
|
|
|
55
|
-
|
|
57
|
+
This makes two commands available system-wide:
|
|
56
58
|
|
|
57
|
-
|
|
59
|
+
| Command | Purpose |
|
|
60
|
+
|---|---|
|
|
61
|
+
| `create-vasuzex` | Scaffold a new Vasuzex project |
|
|
62
|
+
| `vasuzex` | Run framework commands: migrate, seed, generate apps, etc. |
|
|
63
|
+
|
|
64
|
+
### Step 2 — Create a Project
|
|
58
65
|
|
|
59
66
|
```bash
|
|
60
|
-
|
|
61
|
-
|
|
67
|
+
create-vasuzex my-app
|
|
68
|
+
```
|
|
62
69
|
|
|
63
|
-
|
|
64
|
-
# Select web framework (React/Vue/Svelte)
|
|
65
|
-
# Configure database (PostgreSQL/MySQL/SQLite)
|
|
70
|
+
The interactive wizard asks:
|
|
66
71
|
|
|
67
|
-
|
|
72
|
+
| Prompt | Options |
|
|
73
|
+
|---|---|
|
|
74
|
+
| Template | `fullstack`, `api-only`, `web-only`, `api-media`, `minimal` |
|
|
75
|
+
| App name | Any lowercase name, e.g. `blog` |
|
|
76
|
+
| Frontend | React, Vue.js, Svelte, Vanilla JS |
|
|
77
|
+
| Database | PostgreSQL, MySQL, SQLite |
|
|
78
|
+
| DB credentials | host, port, name, user, password — written to `.env` automatically |
|
|
68
79
|
|
|
69
|
-
|
|
70
|
-
# All dependencies installed in root node_modules/
|
|
80
|
+
**What happens behind the scenes (10 automated steps):**
|
|
71
81
|
|
|
72
|
-
|
|
73
|
-
|
|
82
|
+
1. Creates `config/`, `database/`, `apps/` directory structure
|
|
83
|
+
2. Copies 26 config files — auth, cache, database, mail, queue, security, etc.
|
|
84
|
+
3. Generates the `database/` workspace package with models, migrations, seeders
|
|
85
|
+
4. Creates root `package.json` with all dependencies and Turborepo scripts
|
|
86
|
+
5. Sets up `pnpm-workspace.yaml`
|
|
87
|
+
6. Runs `pnpm install` — single installation for the entire monorepo
|
|
88
|
+
7. Generates your apps — API server + Web frontend based on template choice
|
|
89
|
+
8. Creates the database — runs `CREATE DATABASE` automatically
|
|
90
|
+
9. Runs migrations & seeders — tables created, default data seeded
|
|
91
|
+
10. Initializes git — first commit with all generated code
|
|
74
92
|
|
|
75
|
-
|
|
76
|
-
cd apps/blog/api
|
|
77
|
-
pnpm dev
|
|
93
|
+
**Example output:**
|
|
78
94
|
|
|
79
|
-
# Terminal 2 - Start web app
|
|
80
|
-
cd apps/blog/web
|
|
81
|
-
pnpm dev
|
|
82
95
|
```
|
|
96
|
+
$ create-vasuzex my-app
|
|
83
97
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
98
|
+
✔ Template: fullstack
|
|
99
|
+
✔ App name: blog
|
|
100
|
+
✔ Frontend: React
|
|
101
|
+
✔ Database: PostgreSQL
|
|
87
102
|
|
|
88
|
-
|
|
103
|
+
📦 Installing dependencies...
|
|
104
|
+
🔧 Generating API app...
|
|
105
|
+
🎨 Generating Web app...
|
|
106
|
+
🗄️ Creating database...
|
|
107
|
+
📋 Running migrations...
|
|
108
|
+
🌱 Seeding database...
|
|
109
|
+
🎉 Done!
|
|
110
|
+
|
|
111
|
+
Your project is ready at ./my-app
|
|
112
|
+
|
|
113
|
+
cd my-app
|
|
114
|
+
pnpm run dev:blog-api # Start API on port 3000
|
|
115
|
+
pnpm run dev:blog-web # Start Web on port 4000
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Non-Interactive Mode (CI/CD)
|
|
89
119
|
|
|
90
120
|
```bash
|
|
91
|
-
|
|
92
|
-
npx create-vasuzex my-app
|
|
93
|
-
cd my-app
|
|
94
|
-
|
|
95
|
-
# 2. Generate apps manually
|
|
96
|
-
pnpm exec vasuzex generate:app blog --type fullstack
|
|
97
|
-
# or
|
|
98
|
-
pnpm exec vasuzex generate:app shop --type api
|
|
99
|
-
pnpm exec vasuzex generate:app admin --type web
|
|
121
|
+
npx create-fresh my-app
|
|
100
122
|
```
|
|
101
123
|
|
|
102
|
-
|
|
124
|
+
Creates a project with sensible defaults (fullstack, React, PostgreSQL) without any prompts.
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Project Structure
|
|
103
129
|
|
|
104
130
|
```
|
|
105
131
|
my-app/
|
|
106
|
-
├── config/
|
|
107
|
-
│ ├── app.cjs
|
|
108
|
-
│ ├── auth.cjs
|
|
109
|
-
│ ├── database.cjs
|
|
110
|
-
│ ├──
|
|
111
|
-
│ ├── mail.cjs
|
|
112
|
-
│ ├──
|
|
113
|
-
│ ├──
|
|
114
|
-
│ ├── session.cjs
|
|
115
|
-
│ ├──
|
|
116
|
-
│
|
|
117
|
-
|
|
118
|
-
│ ├──
|
|
119
|
-
│ ├──
|
|
120
|
-
│ ├──
|
|
121
|
-
│ ├──
|
|
122
|
-
│ └──
|
|
123
|
-
│
|
|
132
|
+
├── config/ # Shared configuration (26 files)
|
|
133
|
+
│ ├── app.cjs # Application settings
|
|
134
|
+
│ ├── auth.cjs # Guards, providers, JWT
|
|
135
|
+
│ ├── database.cjs # PostgreSQL/MySQL/Redis connections
|
|
136
|
+
│ ├── cache.cjs # Cache drivers (redis, file, memory)
|
|
137
|
+
│ ├── mail.cjs # SMTP, SendGrid, SES, Mailgun
|
|
138
|
+
│ ├── queue.cjs # Job queue drivers
|
|
139
|
+
│ ├── security.cjs # Helmet, CORS, CSRF, rate limiting
|
|
140
|
+
│ ├── session.cjs # Session drivers
|
|
141
|
+
│ ├── payment.cjs # Razorpay, Stripe, PhonePe
|
|
142
|
+
│ └── ... # + 17 more config files
|
|
143
|
+
├── database/ # Shared database layer
|
|
144
|
+
│ ├── models/ # Eloquent models (User, Product, etc.)
|
|
145
|
+
│ ├── migrations/ # Schema migrations
|
|
146
|
+
│ ├── seeders/ # Data seeders
|
|
147
|
+
│ ├── index.js # Database connection entry
|
|
148
|
+
│ └── package.json # @my-app/database workspace package
|
|
124
149
|
├── apps/
|
|
125
|
-
│
|
|
126
|
-
│
|
|
127
|
-
│
|
|
128
|
-
│
|
|
129
|
-
│
|
|
130
|
-
│
|
|
131
|
-
│
|
|
132
|
-
│
|
|
133
|
-
│
|
|
134
|
-
│
|
|
135
|
-
│
|
|
136
|
-
│
|
|
137
|
-
│
|
|
138
|
-
│
|
|
139
|
-
│
|
|
140
|
-
│
|
|
141
|
-
│
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
├──
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
│ └── seeders/ # Database seeders
|
|
149
|
-
│
|
|
150
|
-
├── node_modules/ # ⭐ Single hoisted node_modules (all deps)
|
|
151
|
-
├── package.json # ⭐ ALL dependencies defined here
|
|
152
|
-
├── .env # Root environment config
|
|
153
|
-
├── pnpm-workspace.yaml # Workspace definition
|
|
154
|
-
└── turbo.json # Build pipeline config
|
|
150
|
+
│ ├── customer/
|
|
151
|
+
│ │ ├── api/ # Customer API (port 3000)
|
|
152
|
+
│ │ │ ├── src/
|
|
153
|
+
│ │ │ │ ├── index.js
|
|
154
|
+
│ │ │ │ ├── routes/
|
|
155
|
+
│ │ │ │ ├── controllers/
|
|
156
|
+
│ │ │ │ ├── middleware/
|
|
157
|
+
│ │ │ │ └── services/
|
|
158
|
+
│ │ │ ├── .env # APP_PORT=3000
|
|
159
|
+
│ │ │ └── package.json
|
|
160
|
+
│ │ └── web/ # Customer frontend (port 4000)
|
|
161
|
+
│ │ ├── src/
|
|
162
|
+
│ │ ├── .env
|
|
163
|
+
│ │ └── vite.config.js
|
|
164
|
+
│ └── admin/
|
|
165
|
+
│ ├── api/ # Admin API (port 3001)
|
|
166
|
+
│ └── web/ # Admin frontend (port 4001)
|
|
167
|
+
├── .env # Root environment variables
|
|
168
|
+
├── .gitignore
|
|
169
|
+
├── .npmrc # pnpm hoisting config
|
|
170
|
+
├── package.json # Root — all dependencies + scripts
|
|
171
|
+
├── pnpm-workspace.yaml # Workspace: apps/*/* , database
|
|
172
|
+
└── turbo.json # Turborepo task config
|
|
155
173
|
```
|
|
156
174
|
|
|
157
|
-
**Key Features:**
|
|
158
|
-
- ✅ **All configs in `./config/`** - Easily customize any framework feature
|
|
159
|
-
- ✅ **Single `node_modules/`** - 64% disk space savings
|
|
160
|
-
- ✅ **Centralized dependencies** - Manage versions in one place
|
|
161
|
-
- ✅ **Zero config for apps** - Apps inherit all dependencies
|
|
162
|
-
|
|
163
175
|
---
|
|
164
176
|
|
|
165
|
-
##
|
|
177
|
+
## Generating More Apps
|
|
166
178
|
|
|
167
|
-
|
|
179
|
+
After your initial project, add more apps at any time:
|
|
168
180
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
import { BaseApp } from 'vasuzex';
|
|
181
|
+
```bash
|
|
182
|
+
# Fullstack app (API + Web)
|
|
183
|
+
vasuzex generate:app customer
|
|
173
184
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
185
|
+
# API-only
|
|
186
|
+
vasuzex generate:app customer --type api
|
|
187
|
+
|
|
188
|
+
# Web-only with React
|
|
189
|
+
vasuzex generate:app customer --type web --framework react
|
|
179
190
|
|
|
180
|
-
|
|
181
|
-
|
|
191
|
+
# Remove an app
|
|
192
|
+
vasuzex delete:app customer --force
|
|
193
|
+
vasuzex delete:app customer --type api --force
|
|
182
194
|
```
|
|
183
195
|
|
|
184
|
-
|
|
185
|
-
```javascript
|
|
186
|
-
// apps/blog/web/src/services/api.js
|
|
187
|
-
import { createApiClient } from '@vasuzex/client';
|
|
196
|
+
Port assignment is automatic — API apps start at 3000 and increment; web apps start at 4000.
|
|
188
197
|
|
|
189
|
-
|
|
190
|
-
baseURL: 'http://localhost:3000/api'
|
|
191
|
-
});
|
|
198
|
+
---
|
|
192
199
|
|
|
193
|
-
|
|
194
|
-
const posts = await api.get('/posts');
|
|
195
|
-
const newPost = await api.post('/posts', { title: 'Hello' });
|
|
196
|
-
```
|
|
200
|
+
## Running Your Apps
|
|
197
201
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
202
|
+
Vasuzex uses Turborepo for parallel execution across all apps.
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
# Start everything in parallel
|
|
206
|
+
pnpm run dev
|
|
207
|
+
|
|
208
|
+
# Start a specific app
|
|
209
|
+
pnpm run dev:customer-api # port 3000
|
|
210
|
+
pnpm run dev:customer-web # port 4000
|
|
211
|
+
pnpm run dev:business-api # port 3001
|
|
212
|
+
|
|
213
|
+
# Turborepo filters for custom combinations
|
|
214
|
+
turbo run dev --filter=customer-api --filter=customer-web
|
|
215
|
+
turbo run dev --filter=*-api # all APIs, no frontends
|
|
216
|
+
turbo run dev --filter=!admin-* # everything except admin
|
|
210
217
|
```
|
|
211
218
|
|
|
212
|
-
|
|
219
|
+
**Turborepo Tasks:**
|
|
220
|
+
|
|
221
|
+
| Task | Command | Behavior |
|
|
222
|
+
|---|---|---|
|
|
223
|
+
| `dev` | `pnpm run dev` | Starts all dev servers in parallel |
|
|
224
|
+
| `build` | `pnpm run build` | Builds all apps, caches `dist/` output |
|
|
225
|
+
| `start` | `pnpm run start` | Starts production servers (requires build) |
|
|
226
|
+
| `lint` | `pnpm run lint` | Lints all apps |
|
|
227
|
+
| `clean` | `pnpm run clean` | Removes build artifacts |
|
|
213
228
|
|
|
214
229
|
---
|
|
215
230
|
|
|
216
|
-
##
|
|
231
|
+
## Database Management
|
|
217
232
|
|
|
218
|
-
|
|
219
|
-
```bash
|
|
220
|
-
npx create-vasuzex my-app # Create new project
|
|
221
|
-
```
|
|
233
|
+
The database is shared across all apps. All database commands run at the project root:
|
|
222
234
|
|
|
223
|
-
### App Generation
|
|
224
235
|
```bash
|
|
225
|
-
|
|
226
|
-
pnpm
|
|
227
|
-
pnpm
|
|
228
|
-
|
|
236
|
+
# Migrations
|
|
237
|
+
pnpm run db:migrate # Run pending migrations
|
|
238
|
+
pnpm run db:rollback # Rollback last batch
|
|
239
|
+
pnpm run db:reset # Drop all tables + re-migrate
|
|
240
|
+
pnpm run db:seed # Run seeders
|
|
229
241
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
pnpm
|
|
233
|
-
pnpm
|
|
234
|
-
pnpm db:seed # Run seeders
|
|
235
|
-
pnpm db:fresh # Drop all tables & re-migrate
|
|
242
|
+
# Generators
|
|
243
|
+
pnpm run make:model # Create a new model
|
|
244
|
+
pnpm run make:migration # Create a new migration
|
|
245
|
+
pnpm run make:seeder # Create a new seeder
|
|
236
246
|
```
|
|
237
247
|
|
|
238
|
-
|
|
239
|
-
```bash
|
|
240
|
-
pnpm exec vasuzex make:model User # Create model
|
|
241
|
-
pnpm exec vasuzex make:migration create_users # Create migration
|
|
242
|
-
pnpm exec vasuzex make:seeder UserSeeder # Create seeder
|
|
243
|
-
pnpm exec vasuzex make:controller UserController # Create controller
|
|
244
|
-
```
|
|
248
|
+
---
|
|
245
249
|
|
|
246
|
-
|
|
247
|
-
```bash
|
|
248
|
-
pnpm exec vasuzex add:dep axios # Add dependency to root
|
|
249
|
-
pnpm exec vasuzex delete:app blog # Delete app completely
|
|
250
|
-
```
|
|
250
|
+
## Architecture
|
|
251
251
|
|
|
252
|
-
|
|
253
|
-
```bash
|
|
254
|
-
pnpm dev # Run all apps
|
|
255
|
-
pnpm dev:blog-api # Run specific API
|
|
256
|
-
pnpm dev:blog-web # Run specific web app
|
|
257
|
-
```
|
|
252
|
+
Vasuzex is modeled after Laravel's battle-tested patterns, adapted for Node.js.
|
|
258
253
|
|
|
259
|
-
|
|
254
|
+
### Service Container
|
|
260
255
|
|
|
261
|
-
|
|
256
|
+
The `Application` class extends an IoC Container. Services are registered as bindings and resolved on demand:
|
|
262
257
|
|
|
263
|
-
### Backend Framework
|
|
264
258
|
```javascript
|
|
265
|
-
import
|
|
266
|
-
import cors from 'cors';
|
|
267
|
-
import helmet from 'helmet';
|
|
268
|
-
import bcrypt from 'bcryptjs';
|
|
269
|
-
import jwt from 'jsonwebtoken';
|
|
270
|
-
import Joi from 'joi';
|
|
271
|
-
import multer from 'multer';
|
|
272
|
-
```
|
|
259
|
+
import { Application } from 'vasuzex/Foundation';
|
|
273
260
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
import React from 'react';
|
|
277
|
-
import { createApp } from 'vue';
|
|
278
|
-
import { onMount } from 'svelte';
|
|
279
|
-
```
|
|
261
|
+
const app = new Application(import.meta.dirname);
|
|
262
|
+
await app.bootstrap();
|
|
280
263
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
```
|
|
264
|
+
// Register services
|
|
265
|
+
app.singleton('cache', () => new CacheManager(app));
|
|
266
|
+
app.bind('mailer', () => new MailManager(app));
|
|
267
|
+
app.instance('config', configRepo);
|
|
286
268
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
import axios from 'axios';
|
|
290
|
-
import sharp from 'sharp';
|
|
291
|
-
import { Str } from 'vasuzex/Support/Str';
|
|
292
|
-
import { Collection } from 'vasuzex/Support/Collection';
|
|
269
|
+
// Resolve
|
|
270
|
+
const cache = app.make('cache');
|
|
293
271
|
```
|
|
294
272
|
|
|
295
|
-
###
|
|
273
|
+
### Facades
|
|
274
|
+
|
|
275
|
+
Facades provide static, expressive access to container services:
|
|
276
|
+
|
|
296
277
|
```javascript
|
|
297
|
-
|
|
298
|
-
import { defineConfig } from 'vite';
|
|
299
|
-
import react from '@vitejs/plugin-react';
|
|
300
|
-
import vue from '@vitejs/plugin-vue';
|
|
301
|
-
import svelte from '@sveltejs/vite-plugin-svelte';
|
|
302
|
-
```
|
|
278
|
+
import { Cache, Mail, Auth, DB, Log } from 'vasuzex';
|
|
303
279
|
|
|
304
|
-
|
|
280
|
+
await Cache.put('key', 'value', 3600);
|
|
281
|
+
const value = await Cache.get('key');
|
|
305
282
|
|
|
306
|
-
|
|
283
|
+
await Mail.send({ to: 'user@example.com', subject: 'Welcome' });
|
|
307
284
|
|
|
308
|
-
|
|
285
|
+
const user = Auth.user();
|
|
286
|
+
const posts = await DB.table('posts').get();
|
|
309
287
|
|
|
310
|
-
|
|
311
|
-
vasuzex-v2/
|
|
312
|
-
├── node_modules/ # ✅ SINGLE node_modules (247MB)
|
|
313
|
-
├── package.json # All dependencies declared here
|
|
314
|
-
├── pnpm-lock.yaml # Shared lockfile
|
|
315
|
-
├── pnpm-workspace.yaml # Workspace config
|
|
316
|
-
├── .npmrc # Hoisting configuration
|
|
317
|
-
│
|
|
318
|
-
├── framework/ # Core framework
|
|
319
|
-
│ ├── Foundation/
|
|
320
|
-
│ ├── Database/
|
|
321
|
-
│ ├── Http/
|
|
322
|
-
│ ├── Support/
|
|
323
|
-
│ └── Services/
|
|
324
|
-
│
|
|
325
|
-
├── database/ # Database layer
|
|
326
|
-
│ ├── models/
|
|
327
|
-
│ ├── migrations/
|
|
328
|
-
│ └── seeders/
|
|
329
|
-
│
|
|
330
|
-
├── config/ # Configuration files
|
|
331
|
-
│ ├── app.cjs
|
|
332
|
-
│ ├── database.cjs
|
|
333
|
-
│ └── ...
|
|
334
|
-
│
|
|
335
|
-
├── apps/ # Your applications
|
|
336
|
-
│ ├── blog-api/
|
|
337
|
-
│ │ ├── api/
|
|
338
|
-
│ │ └── web/
|
|
339
|
-
│ └── media-server/
|
|
340
|
-
│
|
|
341
|
-
├── docs/ # Documentation
|
|
342
|
-
│ ├── DEPENDENCY_MANAGEMENT_STRATEGY.md
|
|
343
|
-
│ └── IMPORT_ALIASES.md
|
|
344
|
-
│
|
|
345
|
-
└── examples/ # Working examples
|
|
346
|
-
└── dependency-strategies/
|
|
288
|
+
Log.info('Application started');
|
|
347
289
|
```
|
|
348
290
|
|
|
349
|
-
|
|
291
|
+
**Available Facades:**
|
|
292
|
+
|
|
293
|
+
| Facade | Service | Purpose |
|
|
294
|
+
|---|---|---|
|
|
295
|
+
| `Auth` | AuthManager | Authentication & guards |
|
|
296
|
+
| `Cache` | CacheManager | Array, Redis, file caching |
|
|
297
|
+
| `Config` | ConfigRepository | Configuration access |
|
|
298
|
+
| `DB` | DatabaseManager | Query builder |
|
|
299
|
+
| `Hash` | HashManager | Password hashing |
|
|
300
|
+
| `Log` | LogManager | Logging |
|
|
301
|
+
| `Mail` | MailManager | Email sending |
|
|
302
|
+
| `Queue` | QueueManager | Job queues |
|
|
303
|
+
| `Security` | SecurityService | JWT, OTP, hashing |
|
|
304
|
+
| `Session` | SessionManager | Session management |
|
|
305
|
+
| `SMS` | SMSManager | SMS sending |
|
|
306
|
+
| `Storage` | StorageManager | File storage (local, S3) |
|
|
307
|
+
| `Upload` | UploadManager | File uploads |
|
|
308
|
+
| `Validator` | ValidationFactory | Validation |
|
|
309
|
+
|
|
310
|
+
### Service Providers
|
|
350
311
|
|
|
351
|
-
|
|
312
|
+
Providers are the central place to register and boot services:
|
|
352
313
|
|
|
353
|
-
### 1. **Database (GuruORM)**
|
|
354
314
|
```javascript
|
|
355
|
-
import {
|
|
315
|
+
import { ServiceProvider } from 'vasuzex/Foundation';
|
|
356
316
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
317
|
+
class PaymentServiceProvider extends ServiceProvider {
|
|
318
|
+
register() {
|
|
319
|
+
this.app.singleton('payment', () => {
|
|
320
|
+
return new PaymentGateway(this.app.make('config'));
|
|
321
|
+
});
|
|
322
|
+
}
|
|
363
323
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
posts() {
|
|
369
|
-
return this.hasMany(Post, 'user_id');
|
|
324
|
+
boot() {
|
|
325
|
+
// Safe to use other services here — all providers are registered
|
|
326
|
+
const event = this.app.make('events');
|
|
327
|
+
event.listen('order.completed', handlePayment);
|
|
370
328
|
}
|
|
371
329
|
}
|
|
372
|
-
|
|
373
|
-
const user = await User.find(1);
|
|
374
|
-
const posts = await user.posts();
|
|
375
330
|
```
|
|
376
331
|
|
|
377
|
-
|
|
332
|
+
---
|
|
333
|
+
|
|
334
|
+
## HTTP Layer
|
|
335
|
+
|
|
336
|
+
### Routing
|
|
337
|
+
|
|
378
338
|
```javascript
|
|
379
|
-
import { Router } from 'vasuzex
|
|
339
|
+
import { Router } from 'vasuzex';
|
|
380
340
|
|
|
381
|
-
const router = Router();
|
|
341
|
+
const router = new Router();
|
|
382
342
|
|
|
383
343
|
router.get('/users', async (req, res) => {
|
|
384
344
|
const users = await User.all();
|
|
385
|
-
res.json(users);
|
|
345
|
+
res.json({ success: true, data: users });
|
|
386
346
|
});
|
|
387
347
|
|
|
388
348
|
router.post('/users', async (req, res) => {
|
|
389
349
|
const user = await User.create(req.body);
|
|
390
|
-
res.json(user);
|
|
350
|
+
res.status(201).json({ success: true, data: user });
|
|
391
351
|
});
|
|
392
|
-
```
|
|
393
352
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
353
|
+
// Route Groups — shared prefix + middleware
|
|
354
|
+
router.group({ prefix: '/admin', middleware: [authMiddleware] }, (r) => {
|
|
355
|
+
r.get('/dashboard', AdminController.dashboard);
|
|
356
|
+
r.get('/users', AdminController.users);
|
|
357
|
+
r.post('/users', AdminController.createUser);
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
// Nested groups
|
|
361
|
+
router.group({ prefix: '/api' }, (r) => {
|
|
362
|
+
r.post('/auth/login', AuthController.login);
|
|
397
363
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
364
|
+
r.group({ middleware: [authenticate()] }, (r) => {
|
|
365
|
+
r.get('/me', AuthController.me);
|
|
366
|
+
r.put('/me', AuthController.updateProfile);
|
|
367
|
+
});
|
|
402
368
|
});
|
|
403
369
|
|
|
404
|
-
|
|
370
|
+
// Mount on the application
|
|
371
|
+
app.use('/api', router.getRouter());
|
|
405
372
|
```
|
|
406
373
|
|
|
407
|
-
|
|
408
|
-
```javascript
|
|
409
|
-
import bcrypt from 'bcryptjs';
|
|
410
|
-
import jwt from 'jsonwebtoken';
|
|
374
|
+
**All Router Methods:**
|
|
411
375
|
|
|
412
|
-
|
|
413
|
-
|
|
376
|
+
| Method | Signature |
|
|
377
|
+
|---|---|
|
|
378
|
+
| `get()` | `router.get(path, ...handlers)` |
|
|
379
|
+
| `post()` | `router.post(path, ...handlers)` |
|
|
380
|
+
| `put()` | `router.put(path, ...handlers)` |
|
|
381
|
+
| `patch()` | `router.patch(path, ...handlers)` |
|
|
382
|
+
| `delete()` | `router.delete(path, ...handlers)` |
|
|
383
|
+
| `any()` | `router.any(path, ...handlers)` — all HTTP methods |
|
|
384
|
+
| `group()` | `router.group(options, callback)` |
|
|
385
|
+
| `use()` | `router.use(...middleware)` |
|
|
414
386
|
|
|
415
|
-
|
|
416
|
-
const token = jwt.sign({ userId: user.id }, process.env.JWT_SECRET);
|
|
387
|
+
---
|
|
417
388
|
|
|
418
|
-
|
|
419
|
-
const decoded = jwt.verify(token, process.env.JWT_SECRET);
|
|
420
|
-
```
|
|
389
|
+
## Database — Eloquent Models
|
|
421
390
|
|
|
422
|
-
|
|
423
|
-
```javascript
|
|
424
|
-
import multer from 'multer';
|
|
425
|
-
import sharp from 'sharp';
|
|
426
|
-
|
|
427
|
-
const upload = multer({ dest: 'uploads/' });
|
|
428
|
-
|
|
429
|
-
app.post('/upload', upload.single('image'), async (req, res) => {
|
|
430
|
-
// Resize image
|
|
431
|
-
await sharp(req.file.path)
|
|
432
|
-
.resize(800, 600)
|
|
433
|
-
.toFile('uploads/resized.jpg');
|
|
434
|
-
|
|
435
|
-
res.json({ success: true });
|
|
436
|
-
});
|
|
437
|
-
```
|
|
391
|
+
Vasuzex uses GuruORM's Eloquent-inspired Active Record ORM.
|
|
438
392
|
|
|
439
|
-
###
|
|
440
|
-
```javascript
|
|
441
|
-
import { LocationManager, GeoIPManager, SmsManager } from 'vasuzex';
|
|
393
|
+
### Defining Models
|
|
442
394
|
|
|
443
|
-
|
|
444
|
-
|
|
395
|
+
```javascript
|
|
396
|
+
import Model from 'vasuzex/Database/Model';
|
|
445
397
|
|
|
446
|
-
|
|
447
|
-
|
|
398
|
+
class User extends Model {
|
|
399
|
+
// table inferred as 'users' from class name
|
|
400
|
+
}
|
|
448
401
|
|
|
449
|
-
|
|
450
|
-
|
|
402
|
+
class BlogPost extends Model {
|
|
403
|
+
static table = 'blog_posts'; // override table name
|
|
404
|
+
static primaryKey = 'post_id'; // override primary key
|
|
405
|
+
static timestamps = true; // auto-manage created_at/updated_at
|
|
406
|
+
static softDeletes = true; // enable soft deletes
|
|
407
|
+
static fillable = ['title', 'body', 'user_id'];
|
|
408
|
+
static hidden = ['deleted_at'];
|
|
409
|
+
static casts = {
|
|
410
|
+
is_published: 'boolean',
|
|
411
|
+
metadata: 'json',
|
|
412
|
+
published_at: 'date',
|
|
413
|
+
};
|
|
414
|
+
}
|
|
451
415
|
```
|
|
452
416
|
|
|
453
|
-
|
|
417
|
+
### Querying
|
|
454
418
|
|
|
455
|
-
|
|
419
|
+
```javascript
|
|
420
|
+
// Simple lookups
|
|
421
|
+
const users = await User.all();
|
|
422
|
+
const user = await User.find(42);
|
|
423
|
+
const user = await User.findOrFail(42); // throws ModelNotFoundException
|
|
424
|
+
|
|
425
|
+
// Fluent query builder
|
|
426
|
+
const admins = await User.where('role', 'admin').get();
|
|
427
|
+
const recent = await User.query()
|
|
428
|
+
.where('role', 'admin')
|
|
429
|
+
.where('active', true)
|
|
430
|
+
.orderBy('name')
|
|
431
|
+
.limit(10)
|
|
432
|
+
.get();
|
|
456
433
|
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
hoist-pattern[]=*
|
|
461
|
-
shamefully-hoist=true
|
|
462
|
-
shared-workspace-lockfile=true
|
|
463
|
-
strict-peer-dependencies=false
|
|
464
|
-
auto-install-peers=true
|
|
434
|
+
// Pagination
|
|
435
|
+
const result = await User.paginate(15, 1);
|
|
436
|
+
// { data: [...], total: 100, perPage: 15, currentPage: 1, lastPage: 7 }
|
|
465
437
|
```
|
|
466
438
|
|
|
467
|
-
|
|
439
|
+
### Creating, Updating, Deleting
|
|
468
440
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
- 'apps/**/api'
|
|
473
|
-
- 'apps/**/web'
|
|
474
|
-
- 'apps/media-server'
|
|
475
|
-
```
|
|
476
|
-
|
|
477
|
-
### Environment Variables (.env)
|
|
478
|
-
```env
|
|
479
|
-
# Database
|
|
480
|
-
DB_HOST=localhost
|
|
481
|
-
DB_PORT=5432
|
|
482
|
-
DB_NAME=mydb
|
|
483
|
-
DB_USER=postgres
|
|
484
|
-
DB_PASS=secret
|
|
441
|
+
```javascript
|
|
442
|
+
// Create
|
|
443
|
+
const user = await User.create({ name: 'John', email: 'john@example.com' });
|
|
485
444
|
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
445
|
+
// Update
|
|
446
|
+
const user = await User.find(1);
|
|
447
|
+
user.name = 'Jane';
|
|
448
|
+
await user.save();
|
|
489
449
|
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
NODE_ENV=development
|
|
493
|
-
```
|
|
450
|
+
// Or: fill + save
|
|
451
|
+
await user.fill({ name: 'Jane', email: 'jane@example.com' }).save();
|
|
494
452
|
|
|
495
|
-
|
|
453
|
+
// Bulk update
|
|
454
|
+
await User.updateWhere({ role: 'guest' }, { active: false });
|
|
496
455
|
|
|
497
|
-
|
|
456
|
+
// Delete
|
|
457
|
+
await user.delete();
|
|
458
|
+
await User.destroy(1);
|
|
498
459
|
|
|
499
|
-
|
|
460
|
+
// Soft delete / restore
|
|
461
|
+
await user.delete(); // sets deleted_at
|
|
462
|
+
await user.restore(); // clears deleted_at
|
|
463
|
+
await user.forceDelete(); // permanent removal
|
|
500
464
|
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
# Add to root package.json
|
|
504
|
-
pnpm add axios -w
|
|
465
|
+
const all = await User.withTrashed().get();
|
|
466
|
+
const trashed = await User.onlyTrashed().get();
|
|
505
467
|
```
|
|
506
468
|
|
|
507
|
-
|
|
508
|
-
```bash
|
|
509
|
-
# Add to app package.json
|
|
510
|
-
cd apps/my-api
|
|
511
|
-
pnpm add some-package
|
|
512
|
-
```
|
|
469
|
+
### Accessors & Mutators
|
|
513
470
|
|
|
514
|
-
|
|
471
|
+
```javascript
|
|
472
|
+
class User extends Model {
|
|
473
|
+
getFullNameAttribute() {
|
|
474
|
+
return `${this.attributes.first_name} ${this.attributes.last_name}`;
|
|
475
|
+
}
|
|
515
476
|
|
|
516
|
-
|
|
517
|
-
|
|
477
|
+
// Async mutators are fully supported
|
|
478
|
+
async setPasswordAttribute(value) {
|
|
479
|
+
const bcrypt = await import('bcryptjs');
|
|
480
|
+
this.attributes.password = await bcrypt.hash(value, 12);
|
|
481
|
+
}
|
|
518
482
|
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
{
|
|
522
|
-
"pnpm": {
|
|
523
|
-
"overrides": {
|
|
524
|
-
"express": "^5.2.1",
|
|
525
|
-
"react": "^18.2.0"
|
|
526
|
-
}
|
|
483
|
+
setEmailAttribute(value) {
|
|
484
|
+
this.attributes.email = value.toLowerCase().trim();
|
|
527
485
|
}
|
|
528
486
|
}
|
|
529
|
-
```
|
|
530
487
|
|
|
531
|
-
|
|
488
|
+
const user = await User.find(1);
|
|
489
|
+
user.full_name; // 'John Doe'
|
|
490
|
+
```
|
|
532
491
|
|
|
533
|
-
|
|
492
|
+
### Query Scopes
|
|
534
493
|
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
494
|
+
```javascript
|
|
495
|
+
class Post extends Model {
|
|
496
|
+
scopePublished(query) {
|
|
497
|
+
return query.where('status', 'published');
|
|
498
|
+
}
|
|
539
499
|
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
500
|
+
scopeRecent(query, days = 7) {
|
|
501
|
+
const since = new Date(Date.now() - days * 86400000);
|
|
502
|
+
return query.where('created_at', '>=', since);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
544
505
|
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
506
|
+
const posts = await Post.query()
|
|
507
|
+
.published()
|
|
508
|
+
.recent(14)
|
|
509
|
+
.get();
|
|
548
510
|
```
|
|
549
511
|
|
|
550
|
-
###
|
|
551
|
-
```bash
|
|
552
|
-
pnpm test:watch
|
|
553
|
-
```
|
|
512
|
+
### Import Aliases
|
|
554
513
|
|
|
555
|
-
|
|
514
|
+
Every app in the monorepo can import shared code via built-in aliases:
|
|
556
515
|
|
|
557
|
-
|
|
516
|
+
| Alias | Resolves to | Purpose |
|
|
517
|
+
|---|---|---|
|
|
518
|
+
| `vasuzex` | `./framework/index.js` | Framework classes |
|
|
519
|
+
| `#framework` | `./framework/index.js` | Same as above |
|
|
520
|
+
| `#database` | `./database/index.js` | DB connection + query builder |
|
|
521
|
+
| `#models` | `./database/models/index.js` | All Eloquent models |
|
|
522
|
+
| `#config` | `./config/index.cjs` | Config loader |
|
|
558
523
|
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
pnpm dev
|
|
524
|
+
```javascript
|
|
525
|
+
// In any app's controller
|
|
526
|
+
import { Product, Order, User } from '#models';
|
|
563
527
|
|
|
564
|
-
|
|
565
|
-
|
|
528
|
+
class ProductController extends Controller {
|
|
529
|
+
async index(req, res) {
|
|
530
|
+
const products = await Product.where('active', true).paginate(15);
|
|
531
|
+
return this.success(res, products);
|
|
532
|
+
}
|
|
533
|
+
}
|
|
566
534
|
```
|
|
567
535
|
|
|
568
|
-
|
|
569
|
-
```bash
|
|
570
|
-
pnpm build
|
|
571
|
-
```
|
|
536
|
+
---
|
|
572
537
|
|
|
573
|
-
|
|
574
|
-
```bash
|
|
575
|
-
pnpm start
|
|
576
|
-
```
|
|
538
|
+
## React UI
|
|
577
539
|
|
|
578
|
-
|
|
540
|
+
Vasuzex ships a React UI library (`vasuzex/react`) with production-ready components used internally for admin interfaces.
|
|
579
541
|
|
|
580
|
-
|
|
542
|
+
### DataTable
|
|
581
543
|
|
|
582
|
-
|
|
583
|
-
- 🚀 [**Full Stack Setup**](./docs/FULL_STACK_SETUP.md) - Quick reference for fullstack apps
|
|
584
|
-
- 📖 [Full Stack Guide](./docs/getting-started/fullstack-guide.md) - Complete fullstack tutorial
|
|
585
|
-
- 📦 [Installation](./docs/getting-started/installation.md) - Detailed setup guide
|
|
586
|
-
- 🏗️ [Project Structure](./docs/getting-started/project-structure.md) - Understanding the structure
|
|
544
|
+
A full-featured data table with server-side pagination, sorting, per-column searching, and **built-in debounce + request cancellation** — search requests fire only after the user stops typing (400 ms debounce) and any in-flight request is automatically aborted if the user types again before it resolves.
|
|
587
545
|
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
- 📦 [Dependency Strategy](./docs/DEPENDENCY_MANAGEMENT_STRATEGY.md) - Why hybrid approach?
|
|
591
|
-
- 🔗 [Import Aliases](./docs/IMPORT_ALIASES.md) - How to import modules
|
|
592
|
-
- 🗄️ [Database Guide](./docs/database/getting-started.md) - Database & migrations
|
|
546
|
+
```jsx
|
|
547
|
+
import { DataTable } from 'vasuzex/react';
|
|
593
548
|
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
549
|
+
function UsersPage() {
|
|
550
|
+
const columns = [
|
|
551
|
+
{ key: 'name', label: 'Name', sortable: true, searchable: true },
|
|
552
|
+
{ key: 'email', label: 'Email', sortable: true, searchable: true },
|
|
553
|
+
{ key: 'role', label: 'Role' },
|
|
554
|
+
{ key: 'created_at', label: 'Created', sortable: true },
|
|
555
|
+
];
|
|
556
|
+
|
|
557
|
+
return (
|
|
558
|
+
<DataTable
|
|
559
|
+
title="Users"
|
|
560
|
+
columns={columns}
|
|
561
|
+
apiEndpoint="/api/users"
|
|
562
|
+
/>
|
|
563
|
+
);
|
|
564
|
+
}
|
|
565
|
+
```
|
|
598
566
|
|
|
599
567
|
---
|
|
600
568
|
|
|
601
|
-
##
|
|
569
|
+
## Manual Setup
|
|
602
570
|
|
|
603
|
-
|
|
571
|
+
If you prefer to add Vasuzex to an existing Node.js project:
|
|
604
572
|
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
4. Push to the branch
|
|
609
|
-
5. Open a Pull Request
|
|
573
|
+
```bash
|
|
574
|
+
npm install vasuzex
|
|
575
|
+
```
|
|
610
576
|
|
|
611
|
-
|
|
577
|
+
```javascript
|
|
578
|
+
// src/index.js
|
|
579
|
+
import { Application } from 'vasuzex/Foundation';
|
|
612
580
|
|
|
613
|
-
|
|
581
|
+
const app = new Application(import.meta.dirname);
|
|
582
|
+
await app.bootstrap();
|
|
614
583
|
|
|
615
|
-
|
|
584
|
+
app.listen(3000, () => {
|
|
585
|
+
console.log('Server running on http://localhost:3000');
|
|
586
|
+
});
|
|
587
|
+
```
|
|
616
588
|
|
|
617
|
-
|
|
589
|
+
**Minimum `.env`:**
|
|
618
590
|
|
|
619
|
-
|
|
591
|
+
```env
|
|
592
|
+
APP_NAME=my-app
|
|
593
|
+
APP_ENV=development
|
|
594
|
+
APP_PORT=3000
|
|
620
595
|
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
| **Version Control** | Per-app | Centralized |
|
|
628
|
-
| **CI/CD Speed** | Slower | Faster |
|
|
629
|
-
| **Breaking Changes** | - | None (backward compatible) |
|
|
596
|
+
DB_CONNECTION=pgsql
|
|
597
|
+
DB_HOST=127.0.0.1
|
|
598
|
+
DB_PORT=5432
|
|
599
|
+
DB_DATABASE=my_app
|
|
600
|
+
DB_USERNAME=postgres
|
|
601
|
+
DB_PASSWORD=
|
|
630
602
|
|
|
631
|
-
|
|
603
|
+
JWT_SECRET=your-secret-key-here
|
|
604
|
+
JWT_EXPIRES_IN=7d
|
|
605
|
+
```
|
|
632
606
|
|
|
633
|
-
|
|
607
|
+
**Environment file cascade** (later files override earlier ones):
|
|
634
608
|
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
609
|
+
| File | Priority | Committed |
|
|
610
|
+
|---|---|---|
|
|
611
|
+
| `.env` | 1 (lowest) | Yes |
|
|
612
|
+
| `.env.local` | 2 | No (gitignored) |
|
|
613
|
+
| `.env.development` | 3 | Yes |
|
|
614
|
+
| `.env.production` | 3 | Yes |
|
|
615
|
+
| `.env.<env>.local` | 4 (highest) | No |
|
|
639
616
|
|
|
640
617
|
---
|
|
641
618
|
|
|
642
|
-
##
|
|
619
|
+
## CLI Reference
|
|
643
620
|
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
621
|
+
```bash
|
|
622
|
+
# Project creation
|
|
623
|
+
create-vasuzex my-app # Interactive scaffold
|
|
624
|
+
npx create-fresh my-app # Non-interactive (fullstack defaults)
|
|
648
625
|
|
|
649
|
-
|
|
650
|
-
app
|
|
626
|
+
# App management
|
|
627
|
+
vasuzex generate:app customer # Fullstack
|
|
628
|
+
vasuzex generate:app customer --type api # API only
|
|
629
|
+
vasuzex generate:app customer --type web --framework react
|
|
630
|
+
vasuzex delete:app customer --force
|
|
651
631
|
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
632
|
+
# Database
|
|
633
|
+
vasuzex migrate # Run pending migrations
|
|
634
|
+
pnpm run db:rollback # Rollback last batch
|
|
635
|
+
pnpm run db:reset # Drop all + re-migrate
|
|
636
|
+
pnpm run db:seed # Run seeders
|
|
656
637
|
|
|
657
|
-
|
|
658
|
-
|
|
638
|
+
# Generators
|
|
639
|
+
vasuzex make:model User
|
|
640
|
+
vasuzex make:migration create_users_table
|
|
641
|
+
vasuzex make:seeder UserSeeder
|
|
659
642
|
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
const html = renderToString(<App />);
|
|
643
|
+
# Testing
|
|
644
|
+
pnpm test
|
|
645
|
+
pnpm test:coverage
|
|
646
|
+
pnpm test:watch
|
|
666
647
|
```
|
|
667
648
|
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
import App from './App.vue';
|
|
649
|
+
---
|
|
650
|
+
|
|
651
|
+
## Testing
|
|
672
652
|
|
|
673
|
-
|
|
653
|
+
```bash
|
|
654
|
+
pnpm test # Run all tests
|
|
655
|
+
pnpm test:coverage # With coverage report
|
|
656
|
+
pnpm test:watch # Watch mode
|
|
674
657
|
```
|
|
675
658
|
|
|
676
|
-
|
|
677
|
-
```javascript
|
|
678
|
-
import { DB } from 'vasuzex/Database';
|
|
659
|
+
---
|
|
679
660
|
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
661
|
+
## Documentation
|
|
662
|
+
|
|
663
|
+
Full documentation with examples, API reference, and guides lives at:
|
|
664
|
+
|
|
665
|
+
**[https://vasuzex.xdeve.com/guide/](https://vasuzex.xdeve.com/guide/)**
|
|
666
|
+
|
|
667
|
+
| Section | URL |
|
|
668
|
+
|---|---|
|
|
669
|
+
| Installation | https://vasuzex.xdeve.com/guide/ |
|
|
670
|
+
| Architecture | https://vasuzex.xdeve.com/guide/architecture |
|
|
671
|
+
| Configuration | https://vasuzex.xdeve.com/guide/configuration |
|
|
672
|
+
| Routing | https://vasuzex.xdeve.com/guide/routing |
|
|
673
|
+
| Request | https://vasuzex.xdeve.com/guide/request |
|
|
674
|
+
| Response | https://vasuzex.xdeve.com/guide/response |
|
|
675
|
+
| Controllers | https://vasuzex.xdeve.com/guide/controllers |
|
|
676
|
+
| Middleware | https://vasuzex.xdeve.com/guide/middleware |
|
|
677
|
+
| Models | https://vasuzex.xdeve.com/guide/models |
|
|
678
|
+
| Relationships | https://vasuzex.xdeve.com/guide/relationships |
|
|
679
|
+
| Observers & Events | https://vasuzex.xdeve.com/guide/observers |
|
|
680
|
+
| Migrations | https://vasuzex.xdeve.com/guide/migrations |
|
|
681
|
+
| Seeding | https://vasuzex.xdeve.com/guide/seeding |
|
|
682
|
+
| Validation | https://vasuzex.xdeve.com/guide/validation |
|
|
687
683
|
|
|
688
684
|
---
|
|
689
685
|
|
|
690
|
-
##
|
|
686
|
+
## Contributing
|
|
691
687
|
|
|
692
|
-
|
|
693
|
-
2. **Monorepo Ready** - Built for multi-app projects
|
|
694
|
-
3. **Optimized Dependencies** - 64% smaller than traditional setup
|
|
695
|
-
4. **Full-Stack** - Backend + Frontend in one framework
|
|
696
|
-
5. **Modern Stack** - ES Modules, async/await, latest Node.js
|
|
697
|
-
6. **Type Safe** - TypeScript support (coming soon)
|
|
698
|
-
7. **Battle Tested** - Proven in production environments
|
|
688
|
+
Contributions are welcome. Please open an issue to discuss what you'd like to change before submitting a pull request. See [CONTRIBUTING.md](./CONTRIBUTING.md).
|
|
699
689
|
|
|
700
690
|
---
|
|
701
691
|
|
|
702
|
-
|
|
692
|
+
## License
|
|
693
|
+
|
|
694
|
+
MIT © Vasuzex
|
|
703
695
|
|
|
704
696
|
---
|
|
705
697
|
|
|
706
|
-
**
|
|
698
|
+
**NPM:** https://www.npmjs.com/package/vasuzex
|
|
707
699
|
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
**Status:** 🚧 Alpha (Ready for testing)
|
|
700
|
+
|
|
701
|
+
---
|