360-mock-server 1.0.0 → 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 +49 -14
  2. package/bin/cli.js +199 -13
  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
+ ---
20
28
 
21
- # Initialize (creates mock-data.json)
22
- 360-mock init
29
+ ## Interactive Mode (Recommended!)
23
30
 
24
- # Start server
25
- 360-mock start
31
+ After running `npx 360-mock-server`, you get an interactive prompt:
32
+
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
26
48
  ```
27
49
 
28
- Server runs at `http://localhost:3000`
50
+ ### Interactive Commands
51
+
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,7 +67,8 @@ 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 |
@@ -41,15 +76,15 @@ Server runs at `http://localhost:3000`
41
76
  ### Options
42
77
 
43
78
  ```bash
44
- 360-mock start --port 4000 # Custom port
45
- 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
46
81
  360-mock --help # Show help
47
82
  360-mock --version # Show version
48
83
  ```
49
84
 
50
85
  ---
51
86
 
52
- ## API Usage
87
+ ## API Endpoints
53
88
 
54
89
  ### Any endpoint works automatically!
55
90
 
package/bin/cli.js CHANGED
@@ -3,22 +3,205 @@
3
3
  const { program } = require("commander");
4
4
  const path = require("path");
5
5
  const fs = require("fs");
6
+ const http = require("http");
7
+ const readline = require("readline");
6
8
 
7
9
  const packageJson = require("../package.json");
8
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
+
9
160
  program
10
161
  .name("360-mock")
11
- .description("šŸš€ Dynamic Mock REST API Server - Zero Config")
162
+ .description("ļæ½šŸš€ Dynamic Mock REST API Server - Zero Config")
12
163
  .version(packageJson.version);
13
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
+
14
192
  program
15
193
  .command("start")
16
- .description("Start the mock server")
194
+ .description("Start the mock server only (no interactive mode)")
17
195
  .option("-p, --port <port>", "Port number", "3000")
18
196
  .option("-f, --file <filename>", "Data file name", "mock-data.json")
19
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
+ }
20
203
  process.env.PORT = options.port;
21
- process.env.DATA_FILE = path.join(process.cwd(), options.file);
204
+ process.env.DATA_FILE = dataFile;
22
205
  require("../lib/server");
23
206
  });
24
207
 
@@ -32,15 +215,9 @@ program
32
215
  console.log(`āš ļø ${options.file} already exists!`);
33
216
  return;
34
217
  }
35
- const initialData = {
36
- _info: "Add your mock data here. Each key becomes an API endpoint.",
37
- users: [],
38
- products: []
39
- };
40
- fs.writeFileSync(filePath, JSON.stringify(initialData, null, 2));
218
+ fs.writeFileSync(filePath, JSON.stringify({}, null, 2));
41
219
  console.log(`āœ… Created ${options.file}`);
42
- console.log(`\nšŸ“ File location: ${filePath}`);
43
- console.log(`\nšŸš€ Run '360-mock start' to start the server`);
220
+ console.log(`\n Run '360-mock' to start the server`);
44
221
  });
45
222
 
46
223
  program
@@ -64,13 +241,13 @@ program
64
241
  .action((options) => {
65
242
  const filePath = path.join(process.cwd(), options.file);
66
243
  if (!fs.existsSync(filePath)) {
67
- console.log(`āš ļø ${options.file} not found! Run '360-mock init' first.`);
244
+ console.log(`āš ļø ${options.file} not found!`);
68
245
  return;
69
246
  }
70
247
  try {
71
248
  const data = JSON.parse(fs.readFileSync(filePath, "utf-8"));
72
249
  const resources = Object.keys(data).filter(k => !k.startsWith("_"));
73
- console.log(`\nšŸ“¦ Available Resources in ${options.file}:\n`);
250
+ console.log(`\nšŸ“¦ Available Resources:\n`);
74
251
  if (resources.length === 0) {
75
252
  console.log(" No resources yet. POST to any endpoint to create one!");
76
253
  } else {
@@ -85,4 +262,13 @@ program
85
262
  }
86
263
  });
87
264
 
265
+ // API Request command (for non-interactive use)
266
+ program
267
+ .command("req <method> <endpoint> [data]")
268
+ .description("Make single API request")
269
+ .option("-p, --port <port>", "Server port", "3000")
270
+ .action(async (method, endpoint, data, options) => {
271
+ await makeRequest(method, endpoint, data, options.port);
272
+ });
273
+
88
274
  program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "360-mock-server",
3
- "version": "1.0.0",
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": {