360-mock-server 1.0.1 → 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.
Files changed (3) hide show
  1. package/README.md +48 -41
  2. package/bin/cli.js +193 -72
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # šŸš€ Mock API Server
1
+ # šŸš€ 360 Mock Server
2
2
 
3
3
  Zero-config dynamic mock REST API server. Perfect for frontend development when backend isn't ready.
4
4
 
@@ -8,24 +8,58 @@ Zero-config dynamic mock REST API server. Perfect for frontend development when
8
8
  # Global installation (recommended)
9
9
  npm install -g 360-mock-server
10
10
 
11
- # Or use npx directly
12
- npx 360-mock-server start
11
+ # Or use npx (no install needed)
12
+ npx 360-mock-server
13
13
  ```
14
14
 
15
15
  ## Quick Start
16
16
 
17
17
  ```bash
18
- # Navigate to your project
19
- cd my-frontend-project
18
+ # Just run one command - that's it!
19
+ npx 360-mock-server
20
+ ```
21
+
22
+ This will:
23
+ 1. āœ… Create `mock-data.json` automatically
24
+ 2. āœ… Start the server on port 3000
25
+ 3. āœ… Open interactive mode for easy API requests
26
+
27
+ ---
28
+
29
+ ## Interactive Mode (Recommended!)
20
30
 
21
- # Initialize (creates mock-data.json)
22
- 360-mock init
31
+ After running `npx 360-mock-server`, you get an interactive prompt:
23
32
 
24
- # Start server
25
- 360-mock start
26
33
  ```
34
+ 360-mock> POST /users {"name": "Ali", "email": "ali@test.com"}
35
+ šŸ“¤ POST /users
36
+ āœ… Status: 201
37
+ { "id": 1234567890, "name": "Ali", "email": "ali@test.com" }
38
+
39
+ 360-mock> GET /users
40
+ šŸ“¤ GET /users
41
+ āœ… Status: 200
42
+ [{ "id": 1234567890, "name": "Ali", "email": "ali@test.com" }]
43
+
44
+ 360-mock> POST /products {"name": "Laptop", "price": 999}
45
+ 360-mock> GET /products
46
+ 360-mock> DELETE /users/1234567890
47
+ 360-mock> exit
48
+ ```
49
+
50
+ ### Interactive Commands
27
51
 
28
- Server runs at `http://localhost:3000`
52
+ | Command | Example |
53
+ |---------|---------|
54
+ | GET | `GET /users` |
55
+ | POST | `POST /users {"name": "Ali"}` |
56
+ | PUT | `PUT /users/123 {"name": "Updated"}` |
57
+ | PATCH | `PATCH /users/123 {"email": "new@test.com"}` |
58
+ | DELETE | `DELETE /users/123` |
59
+ | list | Show all resources |
60
+ | clear | Clear screen |
61
+ | help | Show help |
62
+ | exit | Exit |
29
63
 
30
64
  ---
31
65
 
@@ -33,50 +67,23 @@ Server runs at `http://localhost:3000`
33
67
 
34
68
  | Command | Description |
35
69
  |---------|-------------|
36
- | `360-mock start` | Start the server |
70
+ | `360-mock` | Start server + interactive mode |
71
+ | `360-mock start` | Start server only |
37
72
  | `360-mock init` | Create mock-data.json |
38
73
  | `360-mock list` | Show available resources |
39
74
  | `360-mock reset` | Clear all data |
40
- | `360-mock req` | Make API requests |
41
75
 
42
76
  ### Options
43
77
 
44
78
  ```bash
45
- 360-mock start --port 4000 # Custom port
46
- 360-mock start --file db.json # Custom data file
79
+ 360-mock --port 4000 # Custom port
80
+ 360-mock --file db.json # Custom data file
47
81
  360-mock --help # Show help
48
82
  360-mock --version # Show version
49
83
  ```
50
84
 
51
85
  ---
52
86
 
53
- ## Making API Requests (Easy Way!)
54
-
55
- Use the built-in `req` command instead of curl:
56
-
57
- ```bash
58
- # CREATE
59
- 360-mock req POST /users '{"name": "Ali", "email": "ali@test.com"}'
60
- 360-mock req POST /products '{"name": "Laptop", "price": 999}'
61
- 360-mock req POST /orders '{"product": "Laptop", "qty": 2}'
62
-
63
- # READ ALL
64
- 360-mock req GET /users
65
- 360-mock req GET /products
66
-
67
- # READ ONE
68
- 360-mock req GET /users/1234567890
69
-
70
- # UPDATE
71
- 360-mock req PUT /users/1234567890 '{"name": "Ali Khan"}'
72
- 360-mock req PATCH /users/1234567890 '{"email": "ali.khan@test.com"}'
73
-
74
- # DELETE
75
- 360-mock req DELETE /users/1234567890
76
- ```
77
-
78
- ---
79
-
80
87
  ## API Endpoints
81
88
 
82
89
  ### Any endpoint works automatically!
package/bin/cli.js CHANGED
@@ -4,22 +4,204 @@ const { program } = require("commander");
4
4
  const path = require("path");
5
5
  const fs = require("fs");
6
6
  const http = require("http");
7
+ const readline = require("readline");
7
8
 
8
9
  const packageJson = require("../package.json");
9
10
 
11
+ // Helper function for making HTTP requests
12
+ function makeRequest(method, endpoint, data, port = "3000") {
13
+ return new Promise((resolve) => {
14
+ const upperMethod = method.toUpperCase();
15
+ const urlPath = endpoint.startsWith("/") ? endpoint : "/" + endpoint;
16
+
17
+ let jsonData = null;
18
+ if (data) {
19
+ try {
20
+ jsonData = typeof data === "string" ? JSON.parse(data) : data;
21
+ } catch (e) {
22
+ console.log(`āŒ Invalid JSON: ${data}`);
23
+ return resolve();
24
+ }
25
+ }
26
+
27
+ const reqOptions = {
28
+ hostname: "localhost",
29
+ port: port,
30
+ path: urlPath,
31
+ method: upperMethod,
32
+ headers: { "Content-Type": "application/json" },
33
+ };
34
+
35
+ console.log(`\nšŸ“¤ ${upperMethod} ${urlPath}`);
36
+ if (jsonData) {
37
+ console.log(` Body: ${JSON.stringify(jsonData)}`);
38
+ }
39
+
40
+ const req = http.request(reqOptions, (res) => {
41
+ let body = "";
42
+ res.on("data", (chunk) => { body += chunk; });
43
+ res.on("end", () => {
44
+ const emoji = res.statusCode >= 200 && res.statusCode < 300 ? "āœ…" : "āŒ";
45
+ console.log(`${emoji} Status: ${res.statusCode}`);
46
+ try {
47
+ const json = JSON.parse(body);
48
+ console.log(JSON.stringify(json, null, 2));
49
+ } catch {
50
+ console.log(body);
51
+ }
52
+ console.log("");
53
+ resolve();
54
+ });
55
+ });
56
+
57
+ req.on("error", (error) => {
58
+ console.error(`āŒ Error: ${error.message}`);
59
+ console.log("šŸ’” Make sure server is running in another terminal: 360-mock start\n");
60
+ resolve();
61
+ });
62
+
63
+ if (jsonData) req.write(JSON.stringify(jsonData));
64
+ req.end();
65
+ });
66
+ }
67
+
68
+ // Interactive REPL mode
69
+ function startInteractiveMode(port) {
70
+ const rl = readline.createInterface({
71
+ input: process.stdin,
72
+ output: process.stdout,
73
+ });
74
+
75
+ console.log(`
76
+ ╔═══════════════════════════════════════════════════════════╗
77
+ ā•‘ šŸš€ 360 Mock Server - Interactive Mode ā•‘
78
+ ╠═══════════════════════════════════════════════════════════╣
79
+ ā•‘ Server: http://localhost:${port} ā•‘
80
+ ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•
81
+
82
+ šŸ“Œ Commands:
83
+ GET /users - Get all users
84
+ GET /users/123 - Get user by ID
85
+ POST /users {"name":"Ali"} - Create user
86
+ PUT /users/123 {"name":"Updated"} - Replace user
87
+ PATCH /users/123 {"name":"New"} - Update user
88
+ DELETE /users/123 - Delete user
89
+
90
+ list - Show resources
91
+ clear - Clear screen
92
+ help - Show this help
93
+ exit - Exit
94
+
95
+ `);
96
+
97
+ const prompt = () => {
98
+ rl.question("360-mock> ", async (input) => {
99
+ const trimmed = input.trim();
100
+
101
+ if (!trimmed) {
102
+ prompt();
103
+ return;
104
+ }
105
+
106
+ // Handle special commands
107
+ if (trimmed === "exit" || trimmed === "quit") {
108
+ console.log("ļæ½ Goodbye!");
109
+ rl.close();
110
+ process.exit(0);
111
+ }
112
+
113
+ if (trimmed === "help") {
114
+ console.log(`
115
+ šŸ“Œ Commands:
116
+ GET /users - Get all users
117
+ GET /users/123 - Get user by ID
118
+ POST /users {"name":"Ali"} - Create user
119
+ PUT /users/123 {"name":"Updated"} - Replace user
120
+ PATCH /users/123 {"name":"New"} - Update user
121
+ DELETE /users/123 - Delete user
122
+
123
+ list - Show resources
124
+ clear - Clear screen
125
+ exit - Exit
126
+ `);
127
+ prompt();
128
+ return;
129
+ }
130
+
131
+ if (trimmed === "clear" || trimmed === "cls") {
132
+ console.clear();
133
+ prompt();
134
+ return;
135
+ }
136
+
137
+ if (trimmed === "list") {
138
+ await makeRequest("GET", "/", null, port);
139
+ prompt();
140
+ return;
141
+ }
142
+
143
+ // Parse API request: METHOD /endpoint {json}
144
+ const match = trimmed.match(/^(GET|POST|PUT|PATCH|DELETE)\s+(\/\S*)\s*(.*)$/i);
145
+
146
+ if (match) {
147
+ const [, method, endpoint, jsonStr] = match;
148
+ await makeRequest(method, endpoint, jsonStr || null, port);
149
+ } else {
150
+ console.log(`āŒ Invalid command. Type 'help' for usage.\n`);
151
+ }
152
+
153
+ prompt();
154
+ });
155
+ };
156
+
157
+ prompt();
158
+ }
159
+
10
160
  program
11
161
  .name("360-mock")
12
- .description("šŸš€ Dynamic Mock REST API Server - Zero Config")
162
+ .description("ļæ½šŸš€ Dynamic Mock REST API Server - Zero Config")
13
163
  .version(packageJson.version);
14
164
 
165
+ // Default command - start interactive mode
166
+ program
167
+ .command("run", { isDefault: true })
168
+ .description("Start server + interactive mode (recommended)")
169
+ .option("-p, --port <port>", "Port number", "3000")
170
+ .option("-f, --file <filename>", "Data file name", "mock-data.json")
171
+ .action((options) => {
172
+ const dataFile = path.join(process.cwd(), options.file);
173
+
174
+ // Create data file if not exists
175
+ if (!fs.existsSync(dataFile)) {
176
+ fs.writeFileSync(dataFile, JSON.stringify({}, null, 2));
177
+ console.log(`āœ… Created ${options.file}`);
178
+ }
179
+
180
+ process.env.PORT = options.port;
181
+ process.env.DATA_FILE = dataFile;
182
+
183
+ // Start server
184
+ require("../lib/server");
185
+
186
+ // Start interactive mode after a short delay
187
+ setTimeout(() => {
188
+ startInteractiveMode(options.port);
189
+ }, 500);
190
+ });
191
+
15
192
  program
16
193
  .command("start")
17
- .description("Start the mock server")
194
+ .description("Start the mock server only (no interactive mode)")
18
195
  .option("-p, --port <port>", "Port number", "3000")
19
196
  .option("-f, --file <filename>", "Data file name", "mock-data.json")
20
197
  .action((options) => {
198
+ const dataFile = path.join(process.cwd(), options.file);
199
+ if (!fs.existsSync(dataFile)) {
200
+ fs.writeFileSync(dataFile, JSON.stringify({}, null, 2));
201
+ console.log(`āœ… Created ${options.file}`);
202
+ }
21
203
  process.env.PORT = options.port;
22
- process.env.DATA_FILE = path.join(process.cwd(), options.file);
204
+ process.env.DATA_FILE = dataFile;
23
205
  require("../lib/server");
24
206
  });
25
207
 
@@ -33,15 +215,9 @@ program
33
215
  console.log(`āš ļø ${options.file} already exists!`);
34
216
  return;
35
217
  }
36
- const initialData = {
37
- _info: "Add your mock data here. Each key becomes an API endpoint.",
38
- users: [],
39
- products: []
40
- };
41
- fs.writeFileSync(filePath, JSON.stringify(initialData, null, 2));
218
+ fs.writeFileSync(filePath, JSON.stringify({}, null, 2));
42
219
  console.log(`āœ… Created ${options.file}`);
43
- console.log(`\nšŸ“ File location: ${filePath}`);
44
- console.log(`\nšŸš€ Run '360-mock start' to start the server`);
220
+ console.log(`\n Run '360-mock' to start the server`);
45
221
  });
46
222
 
47
223
  program
@@ -65,13 +241,13 @@ program
65
241
  .action((options) => {
66
242
  const filePath = path.join(process.cwd(), options.file);
67
243
  if (!fs.existsSync(filePath)) {
68
- console.log(`āš ļø ${options.file} not found! Run '360-mock init' first.`);
244
+ console.log(`āš ļø ${options.file} not found!`);
69
245
  return;
70
246
  }
71
247
  try {
72
248
  const data = JSON.parse(fs.readFileSync(filePath, "utf-8"));
73
249
  const resources = Object.keys(data).filter(k => !k.startsWith("_"));
74
- console.log(`\nšŸ“¦ Available Resources in ${options.file}:\n`);
250
+ console.log(`\nšŸ“¦ Available Resources:\n`);
75
251
  if (resources.length === 0) {
76
252
  console.log(" No resources yet. POST to any endpoint to create one!");
77
253
  } else {
@@ -86,68 +262,13 @@ program
86
262
  }
87
263
  });
88
264
 
89
- // API Request command
265
+ // API Request command (for non-interactive use)
90
266
  program
91
267
  .command("req <method> <endpoint> [data]")
92
- .alias("request")
93
- .description("Make API request (GET, POST, PUT, PATCH, DELETE)")
268
+ .description("Make single API request")
94
269
  .option("-p, --port <port>", "Server port", "3000")
95
- .action((method, endpoint, data, options) => {
96
- const upperMethod = method.toUpperCase();
97
- const path = endpoint.startsWith("/") ? endpoint : "/" + endpoint;
98
-
99
- let jsonData = null;
100
- if (data) {
101
- try {
102
- jsonData = JSON.parse(data);
103
- } catch (e) {
104
- console.log(`āŒ Invalid JSON: ${data}`);
105
- process.exit(1);
106
- }
107
- }
108
-
109
- const reqOptions = {
110
- hostname: "localhost",
111
- port: options.port,
112
- path: path,
113
- method: upperMethod,
114
- headers: {
115
- "Content-Type": "application/json",
116
- },
117
- };
118
-
119
- console.log(`\nšŸ“¤ ${upperMethod} ${path}`);
120
- if (jsonData) {
121
- console.log(` Body: ${JSON.stringify(jsonData, null, 2)}`);
122
- }
123
- console.log("");
124
-
125
- const req = http.request(reqOptions, (res) => {
126
- let body = "";
127
- res.on("data", (chunk) => { body += chunk; });
128
- res.on("end", () => {
129
- const statusEmoji = res.statusCode >= 200 && res.statusCode < 300 ? "āœ…" : "āŒ";
130
- console.log(`${statusEmoji} Status: ${res.statusCode}`);
131
- console.log(`šŸ“„ Response:`);
132
- try {
133
- const json = JSON.parse(body);
134
- console.log(JSON.stringify(json, null, 2));
135
- } catch {
136
- console.log(body);
137
- }
138
- console.log("");
139
- });
140
- });
141
-
142
- req.on("error", (error) => {
143
- console.error(`āŒ Error: ${error.message}`);
144
- console.log("\nšŸ’” Make sure the server is running: 360-mock start\n");
145
- });
146
-
147
- if (jsonData) {
148
- req.write(JSON.stringify(jsonData));
149
- }
150
- req.end();
270
+ .action(async (method, endpoint, data, options) => {
271
+ await makeRequest(method, endpoint, data, options.port);
151
272
  });
152
273
 
153
274
  program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "360-mock-server",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "description": "šŸš€ Zero-config dynamic mock REST API server for frontend developers",
5
5
  "main": "lib/server.js",
6
6
  "bin": {