360-mock-server 1.1.1 → 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/README.md +52 -0
- package/lib/server.js +134 -2
- package/package.json +6 -3
package/README.md
CHANGED
|
@@ -3,11 +3,14 @@
|
|
|
3
3
|
**360 Mock Server** is a zero-configuration mock REST API designed for frontend developers.
|
|
4
4
|
It allows you to instantly create and manage RESTful APIs **without building a backend**, making it ideal for frontend development, testing, demos, and rapid prototyping.
|
|
5
5
|
|
|
6
|
+
Now with **Faker.js integration** for automatic fake data generation!
|
|
7
|
+
|
|
6
8
|
|
|
7
9
|
## ✨ Why 360 Mock Server?
|
|
8
10
|
|
|
9
11
|
* No backend setup required
|
|
10
12
|
* Works instantly with **any endpoint**
|
|
13
|
+
* **Auto-generate fake data** with Faker.js
|
|
11
14
|
* Interactive CLI + REST API
|
|
12
15
|
* Persistent JSON-based storage
|
|
13
16
|
* Ideal for React, React Native, Vue, Angular, Redux apps
|
|
@@ -101,6 +104,54 @@ Content-Type: application/json
|
|
|
101
104
|
```
|
|
102
105
|
|
|
103
106
|
|
|
107
|
+
## 🎲 Auto-Generate Fake Data with Faker.js
|
|
108
|
+
|
|
109
|
+
Generate realistic fake data instantly! Just send a POST request with `fields` array:
|
|
110
|
+
|
|
111
|
+
### Generate 10 Users (default count)
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
POST /users
|
|
115
|
+
{
|
|
116
|
+
"fields": ["name", "email", "avatar", "phone"]
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Generate 50 Products with custom count
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
POST /products
|
|
124
|
+
{
|
|
125
|
+
"fields": ["productName", "price", "category", "description", "image"],
|
|
126
|
+
"count": 50
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Available Faker Fields
|
|
131
|
+
|
|
132
|
+
| Category | Fields |
|
|
133
|
+
| ----------- | ---------------------------------------------------------------------- |
|
|
134
|
+
| **Person** | `name`, `firstName`, `lastName`, `username`, `email`, `phone`, `avatar`, `bio`, `jobTitle`, `gender` |
|
|
135
|
+
| **Location**| `address`, `city`, `state`, `country`, `zipCode`, `latitude`, `longitude` |
|
|
136
|
+
| **Company** | `company`, `companyName`, `department` |
|
|
137
|
+
| **Internet**| `website`, `url`, `ip`, `password` |
|
|
138
|
+
| **Content** | `title`, `description`, `body`, `text`, `sentence`, `paragraph`, `slug`|
|
|
139
|
+
| **Commerce**| `price`, `product`, `productName`, `productDescription`, `category` |
|
|
140
|
+
| **Images** | `image`, `imageUrl` |
|
|
141
|
+
| **Dates** | `date`, `pastDate`, `futureDate`, `birthDate` |
|
|
142
|
+
| **Numbers** | `number`, `age`, `rating`, `quantity` |
|
|
143
|
+
| **Boolean** | `boolean`, `isActive`, `isVerified` |
|
|
144
|
+
| **Misc** | `uuid`, `color`, `word`, `words` |
|
|
145
|
+
|
|
146
|
+
### Get All Available Fields
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
GET /faker/fields
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
> **Note:** If your POST body contains a `fields` array, it generates fake data. Otherwise, it creates a single item with your provided key-value pairs.
|
|
153
|
+
|
|
154
|
+
|
|
104
155
|
## 🔌 Frontend Integration Examples
|
|
105
156
|
|
|
106
157
|
<details open>
|
|
@@ -191,6 +242,7 @@ npx 360-mock-server --file db.json
|
|
|
191
242
|
* ✅ Zero-config setup
|
|
192
243
|
* ✅ Supports **any REST endpoint**
|
|
193
244
|
* ✅ Full CRUD operations
|
|
245
|
+
* ✅ **Auto-generate fake data** with Faker.js
|
|
194
246
|
* ✅ Auto-generated unique IDs
|
|
195
247
|
* ✅ Automatic timestamps (`createdAt`, `updatedAt`)
|
|
196
248
|
* ✅ Persistent JSON storage
|
package/lib/server.js
CHANGED
|
@@ -2,6 +2,7 @@ const express = require("express");
|
|
|
2
2
|
const fs = require("fs");
|
|
3
3
|
const path = require("path");
|
|
4
4
|
const cors = require("cors");
|
|
5
|
+
const { faker } = require("@faker-js/faker");
|
|
5
6
|
|
|
6
7
|
const app = express();
|
|
7
8
|
const PORT = process.env.PORT || 3000;
|
|
@@ -46,6 +47,99 @@ app.use((req, res, next) => {
|
|
|
46
47
|
next();
|
|
47
48
|
});
|
|
48
49
|
|
|
50
|
+
// Faker field mappings for automatic data generation
|
|
51
|
+
const fakerFieldMap = {
|
|
52
|
+
// Person
|
|
53
|
+
name: () => faker.person.fullName(),
|
|
54
|
+
firstName: () => faker.person.firstName(),
|
|
55
|
+
lastName: () => faker.person.lastName(),
|
|
56
|
+
username: () => faker.internet.username(),
|
|
57
|
+
email: () => faker.internet.email(),
|
|
58
|
+
phone: () => faker.phone.number(),
|
|
59
|
+
avatar: () => faker.image.avatar(),
|
|
60
|
+
bio: () => faker.person.bio(),
|
|
61
|
+
jobTitle: () => faker.person.jobTitle(),
|
|
62
|
+
gender: () => faker.person.sex(),
|
|
63
|
+
|
|
64
|
+
// Location
|
|
65
|
+
address: () => faker.location.streetAddress(),
|
|
66
|
+
city: () => faker.location.city(),
|
|
67
|
+
state: () => faker.location.state(),
|
|
68
|
+
country: () => faker.location.country(),
|
|
69
|
+
zipCode: () => faker.location.zipCode(),
|
|
70
|
+
latitude: () => faker.location.latitude(),
|
|
71
|
+
longitude: () => faker.location.longitude(),
|
|
72
|
+
|
|
73
|
+
// Company
|
|
74
|
+
company: () => faker.company.name(),
|
|
75
|
+
companyName: () => faker.company.name(),
|
|
76
|
+
department: () => faker.commerce.department(),
|
|
77
|
+
|
|
78
|
+
// Internet
|
|
79
|
+
website: () => faker.internet.url(),
|
|
80
|
+
url: () => faker.internet.url(),
|
|
81
|
+
ip: () => faker.internet.ip(),
|
|
82
|
+
password: () => faker.internet.password(),
|
|
83
|
+
|
|
84
|
+
// Content
|
|
85
|
+
title: () => faker.lorem.sentence(),
|
|
86
|
+
description: () => faker.lorem.paragraph(),
|
|
87
|
+
body: () => faker.lorem.paragraphs(3),
|
|
88
|
+
text: () => faker.lorem.text(),
|
|
89
|
+
sentence: () => faker.lorem.sentence(),
|
|
90
|
+
paragraph: () => faker.lorem.paragraph(),
|
|
91
|
+
slug: () => faker.lorem.slug(),
|
|
92
|
+
|
|
93
|
+
// Commerce
|
|
94
|
+
price: () => parseFloat(faker.commerce.price()),
|
|
95
|
+
product: () => faker.commerce.productName(),
|
|
96
|
+
productName: () => faker.commerce.productName(),
|
|
97
|
+
productDescription: () => faker.commerce.productDescription(),
|
|
98
|
+
category: () => faker.commerce.department(),
|
|
99
|
+
|
|
100
|
+
// Images
|
|
101
|
+
image: () => faker.image.url(),
|
|
102
|
+
imageUrl: () => faker.image.url(),
|
|
103
|
+
|
|
104
|
+
// Date/Time
|
|
105
|
+
date: () => faker.date.recent().toISOString(),
|
|
106
|
+
pastDate: () => faker.date.past().toISOString(),
|
|
107
|
+
futureDate: () => faker.date.future().toISOString(),
|
|
108
|
+
birthDate: () => faker.date.birthdate().toISOString(),
|
|
109
|
+
|
|
110
|
+
// Numbers
|
|
111
|
+
number: () => faker.number.int({ min: 1, max: 1000 }),
|
|
112
|
+
age: () => faker.number.int({ min: 18, max: 80 }),
|
|
113
|
+
rating: () => faker.number.int({ min: 1, max: 5 }),
|
|
114
|
+
quantity: () => faker.number.int({ min: 1, max: 100 }),
|
|
115
|
+
|
|
116
|
+
// Boolean
|
|
117
|
+
boolean: () => faker.datatype.boolean(),
|
|
118
|
+
isActive: () => faker.datatype.boolean(),
|
|
119
|
+
isVerified: () => faker.datatype.boolean(),
|
|
120
|
+
|
|
121
|
+
// Misc
|
|
122
|
+
uuid: () => faker.string.uuid(),
|
|
123
|
+
color: () => faker.color.human(),
|
|
124
|
+
word: () => faker.word.noun(),
|
|
125
|
+
words: () => faker.word.words(3),
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
// Get available faker fields
|
|
129
|
+
app.get("/faker/fields", (req, res) => {
|
|
130
|
+
res.json({
|
|
131
|
+
message: "Available faker fields for auto-generation",
|
|
132
|
+
fields: Object.keys(fakerFieldMap),
|
|
133
|
+
usage: {
|
|
134
|
+
endpoint: "POST /:resource",
|
|
135
|
+
example: {
|
|
136
|
+
fields: ["name", "email", "avatar"],
|
|
137
|
+
count: 20
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
|
|
49
143
|
app.get("/", (req, res) => {
|
|
50
144
|
const data = readData();
|
|
51
145
|
const resources = Object.keys(data).filter(k => !k.startsWith("_"));
|
|
@@ -56,10 +150,11 @@ app.get("/", (req, res) => {
|
|
|
56
150
|
endpoints: {
|
|
57
151
|
"GET /:resource": "Get all items",
|
|
58
152
|
"GET /:resource/:id": "Get single item",
|
|
59
|
-
"POST /:resource": "Create new item",
|
|
153
|
+
"POST /:resource": "Create new item OR generate fake data with { fields: [...], count: N }",
|
|
60
154
|
"PUT /:resource/:id": "Replace item",
|
|
61
155
|
"PATCH /:resource/:id": "Update item",
|
|
62
|
-
"DELETE /:resource/:id": "Delete item"
|
|
156
|
+
"DELETE /:resource/:id": "Delete item",
|
|
157
|
+
"GET /faker/fields": "List available faker fields"
|
|
63
158
|
}
|
|
64
159
|
});
|
|
65
160
|
});
|
|
@@ -127,6 +222,43 @@ app.post("/:resource", (req, res) => {
|
|
|
127
222
|
data[resource] = [];
|
|
128
223
|
console.log(` 📁 Created new resource: ${resource}`);
|
|
129
224
|
}
|
|
225
|
+
|
|
226
|
+
// Check if this is a faker request (has 'fields' array)
|
|
227
|
+
if (Array.isArray(req.body.fields) && req.body.fields.length > 0) {
|
|
228
|
+
const { fields, count = 10 } = req.body;
|
|
229
|
+
|
|
230
|
+
const generatedItems = [];
|
|
231
|
+
for (let i = 0; i < count; i++) {
|
|
232
|
+
const item = {
|
|
233
|
+
id: faker.string.uuid(),
|
|
234
|
+
createdAt: new Date().toISOString()
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
fields.forEach(field => {
|
|
238
|
+
if (fakerFieldMap[field]) {
|
|
239
|
+
item[field] = fakerFieldMap[field]();
|
|
240
|
+
} else {
|
|
241
|
+
// Default to random words if field not mapped
|
|
242
|
+
item[field] = faker.word.words(2);
|
|
243
|
+
}
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
data[resource].push(item);
|
|
247
|
+
generatedItems.push(item);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
writeData(data);
|
|
251
|
+
console.log(` ✅ Generated ${count} fake ${resource}`);
|
|
252
|
+
|
|
253
|
+
return res.status(201).json({
|
|
254
|
+
message: `Successfully generated ${count} ${resource}`,
|
|
255
|
+
count: count,
|
|
256
|
+
sample: generatedItems.slice(0, 3),
|
|
257
|
+
total: data[resource].length
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Normal POST - create single item with provided key-value pairs
|
|
130
262
|
const newId = req.body.id || Date.now();
|
|
131
263
|
if (data[resource].some(item => String(item.id) === String(newId))) {
|
|
132
264
|
return res.status(409).json({
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "360-mock-server",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "🚀 Zero-config dynamic mock REST API server for frontend developers",
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "🚀 Zero-config dynamic mock REST API server with Faker.js auto-generation for frontend developers",
|
|
5
5
|
"main": "lib/server.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"360-mock": "./bin/cli.js"
|
|
@@ -17,11 +17,13 @@
|
|
|
17
17
|
"server",
|
|
18
18
|
"json",
|
|
19
19
|
"fake",
|
|
20
|
+
"faker",
|
|
20
21
|
"backend",
|
|
21
22
|
"frontend",
|
|
22
23
|
"development",
|
|
23
24
|
"testing",
|
|
24
|
-
"crud"
|
|
25
|
+
"crud",
|
|
26
|
+
"auto-generate"
|
|
25
27
|
],
|
|
26
28
|
"author": "zahidrahimoon",
|
|
27
29
|
"license": "MIT",
|
|
@@ -42,6 +44,7 @@
|
|
|
42
44
|
"node": ">=14.0.0"
|
|
43
45
|
},
|
|
44
46
|
"dependencies": {
|
|
47
|
+
"@faker-js/faker": "^10.2.0",
|
|
45
48
|
"commander": "^11.1.0",
|
|
46
49
|
"cors": "^2.8.5",
|
|
47
50
|
"express": "^4.18.2"
|