phantomback 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Madhav Chaturvedi
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,459 @@
1
+ <div align="center">
2
+
3
+ # ๐Ÿ‘ป PhantomBack
4
+
5
+ ### Instant Fake Backend Generator with Smart Responses
6
+
7
+ [![npm version](https://img.shields.io/npm/v/phantomback.svg?style=flat-square&color=a78bfa)](https://www.npmjs.com/package/phantomback)
8
+ [![license](https://img.shields.io/npm/l/phantomback.svg?style=flat-square)](LICENSE)
9
+ [![node](https://img.shields.io/node/v/phantomback.svg?style=flat-square)](package.json)
10
+
11
+ **Stop waiting for the backend. Start building now.**
12
+
13
+ Drop in your API schema โ†’ get a fully functional REST server with realistic data,
14
+ JWT auth, pagination, filtering, sorting, search, and nested routes โ€” in seconds.
15
+
16
+ [Getting Started](#-quick-start) ยท [Config Guide](#-configuration) ยท [API Reference](#-auto-generated-routes) ยท [Examples](#-real-world-examples)
17
+
18
+ </div>
19
+
20
+ ---
21
+
22
+ ## โœจ Features
23
+
24
+ - ๐Ÿš€ **Zero-config mode** โ€” one command, full working API
25
+ - ๐Ÿ“ฆ **Auto CRUD** โ€” GET, POST, PUT, PATCH, DELETE for every resource
26
+ - ๐ŸŽญ **Realistic data** โ€” powered by Faker.js (names, emails, prices, avatars...)
27
+ - ๐Ÿ“„ **Pagination** โ€” `?page=1&limit=10` with total counts & page metadata
28
+ - ๐Ÿ” **Search** โ€” `?q=term` full-text search across all fields
29
+ - ๐ŸŽฏ **Filtering** โ€” `?role=admin`, `?age_gte=18`, `?price_lte=100`, `?name_like=john`
30
+ - โ†•๏ธ **Sorting** โ€” `?sort=-price`, `?sort=name,createdAt`
31
+ - ๐Ÿ”— **Relations & Nested Routes** โ€” `GET /users/:id/posts` auto-detected from foreign keys
32
+ - ๐Ÿ”’ **JWT Auth** โ€” register, login, protected routes with Bearer tokens
33
+ - โฑ๏ธ **Response Delay** โ€” simulate slow networks with fixed or random latency
34
+ - โœ… **Validation** โ€” required fields, type checks, unique constraints, email format
35
+ - ๐Ÿ–ฅ๏ธ **CLI + Library** โ€” use as a CLI tool or import in your code
36
+ - ๐Ÿง  **Smart Defaults** โ€” sensible conventions, override only what you need
37
+
38
+ ---
39
+
40
+ ## ๐Ÿ“ฆ Installation
41
+
42
+ ```bash
43
+ # Global install (recommended for CLI)
44
+ npm install -g phantomback
45
+
46
+ # Or as a dev dependency in your project
47
+ npm install --save-dev phantomback
48
+ ```
49
+
50
+ ---
51
+
52
+ ## ๐Ÿš€ Quick Start
53
+
54
+ ### One command โ€” full API:
55
+
56
+ ```bash
57
+ phantomback start --zero
58
+ ```
59
+
60
+ That's it. You now have a REST API running at `http://localhost:3777` with:
61
+ - ๐Ÿ‘ค 25 Users (protected with auth)
62
+ - ๐Ÿ“ 50 Posts
63
+ - ๐Ÿ’ฌ 100 Comments
64
+ - ๐Ÿ“ฆ 30 Products
65
+ - โœ… 40 Todos
66
+
67
+ ### Or with your own config:
68
+
69
+ ```bash
70
+ # Generate a starter config
71
+ phantomback init
72
+
73
+ # Edit phantom.config.js to your needs, then:
74
+ phantomback start
75
+ ```
76
+
77
+ ### Or as a library:
78
+
79
+ ```js
80
+ import { createPhantom } from 'phantomback';
81
+
82
+ const server = await createPhantom({
83
+ port: 3777,
84
+ resources: {
85
+ users: {
86
+ fields: {
87
+ name: { type: 'name', required: true },
88
+ email: { type: 'email', unique: true },
89
+ role: { type: 'enum', values: ['admin', 'user'] },
90
+ },
91
+ seed: 25,
92
+ },
93
+ },
94
+ });
95
+
96
+ // server.stop() โ€” shut down
97
+ // server.reset() โ€” re-seed all data
98
+ // server.getStore() โ€” export current state as JSON
99
+ ```
100
+
101
+ One line for zero-config:
102
+
103
+ ```js
104
+ import { createPhantomZero } from 'phantomback';
105
+ await createPhantomZero(); // Full demo API on port 3777
106
+ ```
107
+
108
+ ---
109
+
110
+ ## โš™๏ธ Configuration
111
+
112
+ Create a `phantom.config.js` in your project root:
113
+
114
+ ```js
115
+ export default {
116
+ port: 3777,
117
+ prefix: '/api',
118
+
119
+ // Global response latency (ms)
120
+ // latency: 500,
121
+ // latency: [200, 800], // random range
122
+
123
+ auth: {
124
+ secret: 'my-secret-key',
125
+ expiresIn: '24h',
126
+ },
127
+
128
+ resources: {
129
+ users: {
130
+ fields: {
131
+ name: { type: 'name', required: true },
132
+ email: { type: 'email', unique: true },
133
+ age: { type: 'number', min: 18, max: 65 },
134
+ role: { type: 'enum', values: ['admin', 'user', 'moderator'] },
135
+ avatar: { type: 'avatar' },
136
+ isActive: { type: 'boolean' },
137
+ },
138
+ seed: 25, // auto-generate 25 records
139
+ auth: true, // protect with JWT
140
+ },
141
+
142
+ posts: {
143
+ fields: {
144
+ title: { type: 'title', required: true },
145
+ body: { type: 'paragraphs', count: 3 },
146
+ userId: { type: 'relation', resource: 'users' },
147
+ views: { type: 'number', min: 0, max: 10000 },
148
+ },
149
+ seed: 50,
150
+ },
151
+ },
152
+ };
153
+ ```
154
+
155
+ ### Supported Field Types
156
+
157
+ | Type | Generates | Options |
158
+ |------|-----------|---------|
159
+ | `name` | Full name | โ€” |
160
+ | `firstName` | First name | โ€” |
161
+ | `lastName` | Last name | โ€” |
162
+ | `username` | Username | โ€” |
163
+ | `email` | Email address | `unique: true` |
164
+ | `avatar` | Avatar URL | โ€” |
165
+ | `phone` | Phone number | โ€” |
166
+ | `bio` | Short bio | โ€” |
167
+ | `jobTitle` | Job title | โ€” |
168
+ | `sentence` | One sentence | โ€” |
169
+ | `paragraph` | One paragraph | โ€” |
170
+ | `paragraphs` | Multiple paragraphs | `count: 3` |
171
+ | `title` | Short title | โ€” |
172
+ | `description` | 2-4 sentences | โ€” |
173
+ | `slug` | URL slug | โ€” |
174
+ | `number` | Integer | `min`, `max` |
175
+ | `float` | Decimal | `min`, `max`, `precision` |
176
+ | `price` | Price string | โ€” |
177
+ | `rating` | 1.0 โ€“ 5.0 | โ€” |
178
+ | `boolean` | true/false | โ€” |
179
+ | `date` | ISO date | โ€” |
180
+ | `pastDate` | Past date | โ€” |
181
+ | `futureDate` | Future date | โ€” |
182
+ | `url` | URL | โ€” |
183
+ | `image` | Image URL | โ€” |
184
+ | `color` | Color name | โ€” |
185
+ | `address` | Street address | โ€” |
186
+ | `city` | City name | โ€” |
187
+ | `country` | Country name | โ€” |
188
+ | `product` | Product name | โ€” |
189
+ | `company` | Company name | โ€” |
190
+ | `enum` | Random from list | `values: [...]` |
191
+ | `relation` | Foreign key | `resource: 'users'` |
192
+ | `uuid` | UUID string | โ€” |
193
+
194
+ ### Field Options
195
+
196
+ ```js
197
+ {
198
+ type: 'email',
199
+ required: true, // validation: must be present
200
+ unique: true, // validation: no duplicates
201
+ min: 0, // for numbers: minimum value
202
+ max: 100, // for numbers: maximum value
203
+ }
204
+ ```
205
+
206
+ ---
207
+
208
+ ## ๐Ÿ›ฃ๏ธ Auto-Generated Routes
209
+
210
+ For each resource (e.g., `users`), PhantomBack generates:
211
+
212
+ | Method | Endpoint | Description |
213
+ |--------|----------|-------------|
214
+ | `GET` | `/api/users` | List all (paginated) |
215
+ | `GET` | `/api/users/:id` | Get one by ID |
216
+ | `POST` | `/api/users` | Create new |
217
+ | `PUT` | `/api/users/:id` | Full update |
218
+ | `PATCH` | `/api/users/:id` | Partial update |
219
+ | `DELETE` | `/api/users/:id` | Delete |
220
+
221
+ ### Nested Routes (auto-detected from relations)
222
+
223
+ If `posts` has `userId: { type: 'relation', resource: 'users' }`, you get:
224
+
225
+ ```
226
+ GET /api/users/:id/posts โ†’ all posts by this user
227
+ ```
228
+
229
+ ### Special Routes
230
+
231
+ | Method | Endpoint | Description |
232
+ |--------|----------|-------------|
233
+ | `GET` | `/api` | List all endpoints |
234
+ | `GET` | `/api/_health` | Server health check |
235
+ | `POST` | `/api/auth/register` | Register (email + password) |
236
+ | `POST` | `/api/auth/login` | Login (returns JWT) |
237
+ | `GET` | `/api/auth/me` | Current user (requires token) |
238
+
239
+ ---
240
+
241
+ ## ๐Ÿ” Query Parameters
242
+
243
+ ### Pagination
244
+
245
+ ```bash
246
+ GET /api/users?page=2&limit=10
247
+ GET /api/users?offset=20&limit=10
248
+ ```
249
+
250
+ Response includes:
251
+ ```json
252
+ {
253
+ "meta": {
254
+ "page": 2,
255
+ "limit": 10,
256
+ "total": 50,
257
+ "totalPages": 5,
258
+ "hasNext": true,
259
+ "hasPrev": true
260
+ }
261
+ }
262
+ ```
263
+
264
+ ### Filtering
265
+
266
+ ```bash
267
+ GET /api/users?role=admin # exact match
268
+ GET /api/users?age_gte=18 # greater than or equal
269
+ GET /api/users?age_lte=30 # less than or equal
270
+ GET /api/users?age_gt=18 # greater than
271
+ GET /api/users?age_lt=30 # less than
272
+ GET /api/users?role_ne=admin # not equal
273
+ GET /api/users?name_like=john # contains (case-insensitive)
274
+ ```
275
+
276
+ ### Sorting
277
+
278
+ ```bash
279
+ GET /api/users?sort=name # ascending
280
+ GET /api/users?sort=-name # descending
281
+ GET /api/users?sort=role,-age # multi-field
282
+ ```
283
+
284
+ ### Search
285
+
286
+ ```bash
287
+ GET /api/users?q=john # search across all fields
288
+ ```
289
+
290
+ ### Field Selection
291
+
292
+ ```bash
293
+ GET /api/users?fields=name,email,role # only return these fields
294
+ ```
295
+
296
+ ---
297
+
298
+ ## ๐Ÿ”’ Authentication
299
+
300
+ 1. **Register:**
301
+ ```bash
302
+ curl -X POST http://localhost:3777/api/auth/register \
303
+ -H "Content-Type: application/json" \
304
+ -d '{"email": "user@example.com", "password": "secret123", "name": "John"}'
305
+ ```
306
+
307
+ 2. **Login:**
308
+ ```bash
309
+ curl -X POST http://localhost:3777/api/auth/login \
310
+ -H "Content-Type: application/json" \
311
+ -d '{"email": "user@example.com", "password": "secret123"}'
312
+ ```
313
+
314
+ 3. **Access protected routes:**
315
+ ```bash
316
+ curl http://localhost:3777/api/users \
317
+ -H "Authorization: Bearer <your-token>"
318
+ ```
319
+
320
+ ---
321
+
322
+ ## ๐Ÿ’ป CLI Reference
323
+
324
+ ```bash
325
+ # Start with auto-detected config file
326
+ phantomback start
327
+
328
+ # Start with zero-config (demo mode)
329
+ phantomback start --zero
330
+
331
+ # Custom port
332
+ phantomback start --port 4000
333
+
334
+ # Specific config file
335
+ phantomback start --config ./my-api.config.js
336
+
337
+ # Generate starter config
338
+ phantomback init
339
+
340
+ # Show help
341
+ phantomback --help
342
+ ```
343
+
344
+ ---
345
+
346
+ ## ๐Ÿ—๏ธ Real-World Examples
347
+
348
+ ### Hospital Management
349
+
350
+ ```js
351
+ export default {
352
+ resources: {
353
+ doctors: {
354
+ fields: {
355
+ name: { type: 'name', required: true },
356
+ specialization: { type: 'enum', values: ['Cardiology', 'Neurology', 'Orthopedics'] },
357
+ experience: { type: 'number', min: 1, max: 30 },
358
+ available: { type: 'boolean' },
359
+ },
360
+ seed: 15,
361
+ },
362
+ patients: {
363
+ fields: {
364
+ name: { type: 'name', required: true },
365
+ age: { type: 'number', min: 1, max: 100 },
366
+ bloodGroup: { type: 'enum', values: ['A+', 'A-', 'B+', 'B-', 'O+', 'O-'] },
367
+ doctorId: { type: 'relation', resource: 'doctors' },
368
+ },
369
+ seed: 40,
370
+ },
371
+ },
372
+ };
373
+ ```
374
+
375
+ ### E-Commerce
376
+
377
+ ```js
378
+ export default {
379
+ resources: {
380
+ products: {
381
+ fields: {
382
+ name: { type: 'product', required: true },
383
+ price: { type: 'price' },
384
+ category: { type: 'enum', values: ['Electronics', 'Clothing', 'Books', 'Food'] },
385
+ inStock: { type: 'boolean' },
386
+ rating: { type: 'rating' },
387
+ },
388
+ seed: 100,
389
+ },
390
+ orders: {
391
+ fields: {
392
+ customerName: { type: 'name' },
393
+ total: { type: 'number', min: 10, max: 5000 },
394
+ status: { type: 'enum', values: ['pending', 'processing', 'shipped', 'delivered'] },
395
+ },
396
+ seed: 50,
397
+ },
398
+ },
399
+ };
400
+ ```
401
+
402
+ ---
403
+
404
+ ## ๐Ÿ“œ Response Format
405
+
406
+ All responses follow a consistent format:
407
+
408
+ **Success:**
409
+ ```json
410
+ {
411
+ "success": true,
412
+ "data": { ... },
413
+ "meta": { "page": 1, "limit": 10, "total": 50, "totalPages": 5 }
414
+ }
415
+ ```
416
+
417
+ **Error:**
418
+ ```json
419
+ {
420
+ "success": false,
421
+ "error": {
422
+ "status": 404,
423
+ "message": "users with id \"abc\" not found"
424
+ }
425
+ }
426
+ ```
427
+
428
+ **Validation Error:**
429
+ ```json
430
+ {
431
+ "success": false,
432
+ "error": {
433
+ "status": 400,
434
+ "message": "Validation failed",
435
+ "details": [
436
+ { "field": "email", "message": "\"email\" is required" }
437
+ ]
438
+ }
439
+ }
440
+ ```
441
+
442
+ ---
443
+
444
+ ## ๐ŸŒŸ Why PhantomBack?
445
+
446
+ | Problem | PhantomBack Solution |
447
+ |---------|---------------------|
448
+ | Backend not ready yet | Start frontend dev instantly |
449
+ | Static JSON mocks are unrealistic | Stateful CRUD with realistic Faker data |
450
+ | No pagination/filtering in mocks | Full query support out of the box |
451
+ | Auth testing is painful | JWT auth simulation built-in |
452
+ | Setting up mock servers takes time | One command / one line of code |
453
+ | Different projects need different schemas | Define any resource with a config file |
454
+
455
+ ---
456
+
457
+ ## ๐Ÿ“„ License
458
+
459
+ MIT ยฉ [Madhav Chaturvedi](https://github.com/madhavchaturvedi)
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { Command } from 'commander';
4
+ import { readFileSync } from 'node:fs';
5
+ import { fileURLToPath } from 'node:url';
6
+ import { dirname, resolve } from 'node:path';
7
+
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = dirname(__filename);
10
+ const pkg = JSON.parse(readFileSync(resolve(__dirname, '..', 'package.json'), 'utf-8'));
11
+
12
+ const program = new Command();
13
+
14
+ program
15
+ .name('phantomback')
16
+ .description('๐Ÿ‘ป Instant fake backend generator with smart responses')
17
+ .version(pkg.version);
18
+
19
+ program
20
+ .command('start')
21
+ .description('Start the PhantomBack fake API server')
22
+ .option('-p, --port <port>', 'Server port', '3777')
23
+ .option('--prefix <prefix>', 'API route prefix', '/api')
24
+ .option('-c, --config <path>', 'Path to config file')
25
+ .option('-z, --zero', 'Zero-config mode: generate a full demo backend')
26
+ .action(async (options) => {
27
+ const { startCommand } = await import('../src/cli/commands.js');
28
+ await startCommand(options);
29
+ });
30
+
31
+ program
32
+ .command('init')
33
+ .description('Generate a starter phantom.config.js file')
34
+ .action(async () => {
35
+ const { initCommand } = await import('../src/cli/commands.js');
36
+ await initCommand();
37
+ });
38
+
39
+ program.parse();
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "phantomback",
3
+ "version": "1.0.0",
4
+ "description": "Instant fake backend generator with smart responses & chaos engineering. Drop in your API schema โ†’ get a fully functional, stateful REST server with realistic data, auth, pagination, filtering, and Reality Mode for chaos testing.",
5
+ "type": "module",
6
+ "main": "./src/index.js",
7
+ "exports": {
8
+ ".": "./src/index.js"
9
+ },
10
+ "bin": {
11
+ "phantomback": "./bin/phantomback.js"
12
+ },
13
+ "scripts": {
14
+ "start": "node bin/phantomback.js start",
15
+ "lint": "eslint .",
16
+ "lint:fix": "eslint . --fix",
17
+ "format": "prettier --write .",
18
+ "format:check": "prettier --check ."
19
+ },
20
+ "keywords": [
21
+ "mock",
22
+ "fake-backend",
23
+ "fake-api",
24
+ "mock-server",
25
+ "rest-api",
26
+ "api-mock",
27
+ "development",
28
+ "prototyping",
29
+ "chaos-engineering",
30
+ "testing",
31
+ "frontend",
32
+ "faker",
33
+ "crud",
34
+ "json-server",
35
+ "phantom"
36
+ ],
37
+ "author": "Madhav Chaturvedi",
38
+ "license": "MIT",
39
+ "engines": {
40
+ "node": ">=18.0.0"
41
+ },
42
+ "files": [
43
+ "bin/",
44
+ "src/",
45
+ "README.md",
46
+ "LICENSE"
47
+ ],
48
+ "dependencies": {
49
+ "@faker-js/faker": "^10.3.0",
50
+ "chalk": "^5.6.2",
51
+ "commander": "^14.0.3",
52
+ "cors": "^2.8.6",
53
+ "express": "^5.2.1",
54
+ "jsonwebtoken": "^9.0.3"
55
+ },
56
+ "devDependencies": {
57
+ "@eslint/js": "^10.0.1",
58
+ "eslint": "^10.0.2",
59
+ "eslint-config-prettier": "^10.1.8",
60
+ "globals": "^17.3.0",
61
+ "prettier": "^3.8.1"
62
+ }
63
+ }