mockaton 11.0.0 → 11.0.2
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/Makefile +6 -6
- package/README.md +81 -37
- package/package.json +4 -1
- package/src/Api.js +5 -4
- package/src/ApiCommander.js +29 -58
- package/src/ApiConstants.js +4 -3
- package/src/Dashboard.js +5 -7
- package/src/Filename.js +6 -12
- package/src/MockBroker.js +2 -2
- package/src/Mockaton.js +1 -1
- package/src/Watcher.js +3 -2
- package/src/mockBrokersCollection.js +1 -1
- package/src/utils/http-request.js +1 -0
- package/src/utils/http-response.js +2 -2
- package/src/utils/mime.js +2 -2
package/Makefile
CHANGED
|
@@ -6,23 +6,23 @@ watch:
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
test:
|
|
9
|
-
node --test 'src/**/*.test.js'
|
|
9
|
+
@MOCKATON_WATCHER_DEBOUNCE_MS=0 node --test 'src/**/*.test.js'
|
|
10
10
|
|
|
11
11
|
test-docker:
|
|
12
|
-
docker run --rm
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
@docker run --rm --interactive --tty \
|
|
13
|
+
--volume .:/app \
|
|
14
|
+
--workdir /app \
|
|
15
15
|
node:24 \
|
|
16
16
|
make test
|
|
17
17
|
|
|
18
18
|
coverage:
|
|
19
|
-
node --test --experimental-test-coverage \
|
|
19
|
+
@MOCKATON_WATCHER_DEBOUNCE_MS=0 node --test --experimental-test-coverage \
|
|
20
20
|
--test-reporter=spec --test-reporter-destination=stdout \
|
|
21
21
|
--test-reporter=lcov --test-reporter-destination=lcov.info \
|
|
22
22
|
'src/**/*.test.js'
|
|
23
23
|
|
|
24
24
|
pixaton:
|
|
25
|
-
node --test --experimental-test-isolation=none \
|
|
25
|
+
@node --test --experimental-test-isolation=none \
|
|
26
26
|
--import=./pixaton-tests/_setup.js \
|
|
27
27
|
'pixaton-tests/**/*.test.js'
|
|
28
28
|
|
package/README.md
CHANGED
|
@@ -77,7 +77,7 @@ get saved following Mockaton’s filename convention.
|
|
|
77
77
|
|
|
78
78
|
### Option 2: Fallback to Your Backend
|
|
79
79
|
<details>
|
|
80
|
-
<summary>
|
|
80
|
+
<summary>Learn more…</summary>
|
|
81
81
|
|
|
82
82
|
This option could be a bit elaborate if your backend uses third-party authentication,
|
|
83
83
|
because you’d have to manually inject cookies or `sessionStorage` tokens.
|
|
@@ -93,7 +93,12 @@ They will be saved in your `config.mocksDir` following the filename convention.
|
|
|
93
93
|
|
|
94
94
|
<br/>
|
|
95
95
|
|
|
96
|
+
<br/>
|
|
97
|
+
|
|
98
|
+
|
|
96
99
|
## Motivation
|
|
100
|
+
<details>
|
|
101
|
+
<summary>Motivation…</summary>
|
|
97
102
|
|
|
98
103
|
**No API state should be too hard to test.**
|
|
99
104
|
With Mockaton, developers can achieve correctness and speed.
|
|
@@ -116,27 +121,54 @@ With Mockaton, developers can achieve correctness and speed.
|
|
|
116
121
|
- checking out long-lived branches
|
|
117
122
|
- bisecting bugs
|
|
118
123
|
|
|
124
|
+
</details>
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
## Use Cases
|
|
129
|
+
<details>
|
|
130
|
+
<summary>Use Cases…</summary>
|
|
131
|
+
|
|
132
|
+
### Testing Backend or Frontend
|
|
133
|
+
- Empty responses
|
|
134
|
+
- Errors such as _Bad Request_ and _Internal Server Error_
|
|
135
|
+
- Mocking third-party APIs
|
|
136
|
+
- Polled resources (for triggering their different states)
|
|
137
|
+
- alerts
|
|
138
|
+
- notifications
|
|
139
|
+
- slow to build resources
|
|
140
|
+
|
|
141
|
+
### Testing Frontend
|
|
142
|
+
- Spinners by delaying responses
|
|
143
|
+
- Setting up UI tests
|
|
144
|
+
|
|
145
|
+
### Demoing complex backend states
|
|
146
|
+
Sometimes, the ideal flow you need is too difficult to reproduce from the actual backend.
|
|
147
|
+
For this, you can **Bulk Select** mocks by comments to simulate the complete states
|
|
148
|
+
you want. For example, by adding `(demo-part1)`, `(demo-part2)` to the filenames.
|
|
149
|
+
|
|
150
|
+
Similarly, you can deploy a **Standalone Demo Server** by compiling the frontend app and
|
|
151
|
+
putting its built assets in `config.staticDir`. And simulate the flow by Bulk Selecting mocks.
|
|
152
|
+
The [aot-fetch-demo repo](https://github.com/ericfortis/aot-fetch-demo) has a working example.
|
|
153
|
+
|
|
154
|
+
</details>
|
|
119
155
|
|
|
120
156
|
<br/>
|
|
121
157
|
|
|
122
|
-
|
|
123
|
-
- Zero dependencies (no runtime and no build packages).
|
|
124
|
-
- Does not write to disk. Except when you select ✅ **Save Mocks** for scraping mocks from a backend.
|
|
125
|
-
- Does not initiate network connections (no logs, no telemetry).
|
|
126
|
-
- Does not hijack your HTTP client.
|
|
127
|
-
- Auditable. Organized and small — under 4 KLoC (half is UI and tests).
|
|
158
|
+
|
|
128
159
|
|
|
129
160
|
<br/>
|
|
130
161
|
|
|
131
162
|
## Basic Usage
|
|
132
|
-
|
|
163
|
+
|
|
164
|
+
1. Install Node.js (v22.18+ support writing mocks in TypeScript)
|
|
133
165
|
|
|
134
166
|
2. Create a sample mock in the default mocks directory (`./mockaton-mocks`)
|
|
135
167
|
```sh
|
|
136
168
|
mkdir -p mockaton-mocks/api
|
|
137
169
|
echo "[1,2,3]" > mockaton-mocks/api/foo.GET.200.json
|
|
138
170
|
```
|
|
139
|
-
3. Run Mockaton (`npx` installs
|
|
171
|
+
3. Run Mockaton (`npx` comes with Node, and installs Mockaton if needed)
|
|
140
172
|
```shell
|
|
141
173
|
npx mockaton --port 2345
|
|
142
174
|
```
|
|
@@ -146,6 +178,16 @@ npx mockaton --port 2345
|
|
|
146
178
|
curl localhost:2345/api/foo
|
|
147
179
|
```
|
|
148
180
|
|
|
181
|
+
5. Optionally, use a `mockaton.config.js`
|
|
182
|
+
```js
|
|
183
|
+
import { defineConfig } from 'mockaton'
|
|
184
|
+
|
|
185
|
+
export default defineConfig({
|
|
186
|
+
port: 2345,
|
|
187
|
+
})
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
|
|
149
191
|
### Alternative Installations
|
|
150
192
|
<details>
|
|
151
193
|
<summary>With NPM (package.json)…</summary>
|
|
@@ -184,6 +226,9 @@ ln -s `realpath mockaton/src/cli.js` ~/bin/mockaton # some dir in your $PATH
|
|
|
184
226
|
## CLI Options
|
|
185
227
|
The CLI options override their counterparts in `mockaton.config.js`
|
|
186
228
|
|
|
229
|
+
<details>
|
|
230
|
+
<summary>CLI Options…</summary>
|
|
231
|
+
|
|
187
232
|
```txt
|
|
188
233
|
-c, --config <file> (default: ./mockaton.config.js)
|
|
189
234
|
|
|
@@ -199,10 +244,17 @@ The CLI options override their counterparts in `mockaton.config.js`
|
|
|
199
244
|
-h, --help Show this help
|
|
200
245
|
-v, --version Show version
|
|
201
246
|
```
|
|
247
|
+
</details>
|
|
202
248
|
|
|
203
249
|
|
|
204
250
|
## mockaton.config.js (Optional)
|
|
251
|
+
Mockaton looks for a file `mockaton.config.js` in its current working directory.
|
|
252
|
+
|
|
253
|
+
<details>
|
|
254
|
+
<summary>Defaults Overview… </summary>
|
|
255
|
+
|
|
205
256
|
As an overview, these are the defaults:
|
|
257
|
+
|
|
206
258
|
```js
|
|
207
259
|
import {
|
|
208
260
|
defineConfig,
|
|
@@ -249,8 +301,10 @@ export default defineConfig({
|
|
|
249
301
|
})
|
|
250
302
|
```
|
|
251
303
|
|
|
304
|
+
</details>
|
|
305
|
+
|
|
252
306
|
<details>
|
|
253
|
-
<summary
|
|
307
|
+
<summary>Config Documentation…</summary>
|
|
254
308
|
|
|
255
309
|
### `mocksDir?: string`
|
|
256
310
|
Defaults to `'mockaton-mocks'`.
|
|
@@ -498,7 +552,7 @@ Defaults to `'normal'`.
|
|
|
498
552
|
|
|
499
553
|
|
|
500
554
|
<details>
|
|
501
|
-
<summary>Programmatic Launch (Optional)
|
|
555
|
+
<summary>Programmatic Launch (Optional)…</summary>
|
|
502
556
|
|
|
503
557
|
|
|
504
558
|
```js
|
|
@@ -535,32 +589,6 @@ permutations for out-of-stock, new-arrival, and discontinued.
|
|
|
535
589
|
<br/>
|
|
536
590
|
|
|
537
591
|
|
|
538
|
-
## Use Cases
|
|
539
|
-
### Testing Backend or Frontend
|
|
540
|
-
- Empty responses
|
|
541
|
-
- Errors such as _Bad Request_ and _Internal Server Error_
|
|
542
|
-
- Mocking third-party APIs
|
|
543
|
-
- Polled resources (for triggering their different states)
|
|
544
|
-
- alerts
|
|
545
|
-
- notifications
|
|
546
|
-
- slow to build resources
|
|
547
|
-
|
|
548
|
-
### Testing Frontend
|
|
549
|
-
- Spinners by delaying responses
|
|
550
|
-
- Setting up UI tests
|
|
551
|
-
|
|
552
|
-
### Demoing complex backend states
|
|
553
|
-
Sometimes, the ideal flow you need is too difficult to reproduce from the actual backend.
|
|
554
|
-
For this, you can **Bulk Select** mocks by comments to simulate the complete states
|
|
555
|
-
you want. For example, by adding `(demo-part1)`, `(demo-part2)` to the filenames.
|
|
556
|
-
|
|
557
|
-
Similarly, you can deploy a **Standalone Demo Server** by compiling the frontend app and
|
|
558
|
-
putting its built assets in `config.staticDir`. And simulate the flow by Bulk Selecting mocks.
|
|
559
|
-
The [aot-fetch-demo repo](https://github.com/ericfortis/aot-fetch-demo) has a working example.
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
<br/>
|
|
563
|
-
|
|
564
592
|
|
|
565
593
|
## You can write JSON mocks in JavaScript or TypeScript
|
|
566
594
|
For example, `api/foo.GET.200.js`
|
|
@@ -840,6 +868,16 @@ await mockaton.reset()
|
|
|
840
868
|
</details>
|
|
841
869
|
|
|
842
870
|
|
|
871
|
+
<br/>
|
|
872
|
+
|
|
873
|
+
## Privacy and Security
|
|
874
|
+
- Zero dependencies (no runtime and no build packages).
|
|
875
|
+
- Does not write to disk. Except when you select ✅ **Save Mocks** for scraping mocks from a backend.
|
|
876
|
+
- Does not initiate network connections (no logs, no telemetry).
|
|
877
|
+
- Does not hijack your HTTP client.
|
|
878
|
+
- Auditable. Organized and small — under 4 KLoC (half is UI and tests).
|
|
879
|
+
|
|
880
|
+
|
|
843
881
|
<br/>
|
|
844
882
|
|
|
845
883
|
## Alternatives worth learning as well
|
|
@@ -861,6 +899,12 @@ hijack the HTTP client in Node.js and browsers.
|
|
|
861
899
|
- [Fetch Mock](https://github.com/wheresrhys/fetch-mock)
|
|
862
900
|
- [Mentoss](https://github.com/humanwhocodes/mentoss) Has a server side too
|
|
863
901
|
|
|
902
|
+
### Server Side
|
|
903
|
+
|
|
904
|
+
- [Wire Mock](https://github.com/wiremock/wiremock)
|
|
905
|
+
- [Mock](https://github.com/dhuan/mock)
|
|
906
|
+
- [Swagger](https://swagger.io/)
|
|
907
|
+
|
|
864
908
|
<br/>
|
|
865
909
|
|
|
866
910
|
---
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "mockaton",
|
|
3
3
|
"description": "HTTP Mock Server",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "11.0.
|
|
5
|
+
"version": "11.0.2",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"types": "index.d.ts",
|
|
8
8
|
"license": "MIT",
|
|
@@ -23,5 +23,8 @@
|
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"pixaton": "1.1.3",
|
|
25
25
|
"puppeteer": "24.24.1"
|
|
26
|
+
},
|
|
27
|
+
"engines": {
|
|
28
|
+
"node": ">=22.18 <23 || >=23.6"
|
|
26
29
|
}
|
|
27
30
|
}
|
package/src/Api.js
CHANGED
|
@@ -13,7 +13,7 @@ import * as mockBrokersCollection from './mockBrokersCollection.js'
|
|
|
13
13
|
import { config, ConfigValidator } from './config.js'
|
|
14
14
|
import { DashboardHtml, CSP } from './DashboardHtml.js'
|
|
15
15
|
import { sendOK, sendJSON, sendUnprocessableContent, sendFile, sendHTML } from './utils/http-response.js'
|
|
16
|
-
import { API, LONG_POLL_SERVER_TIMEOUT,
|
|
16
|
+
import { API, LONG_POLL_SERVER_TIMEOUT, HEADER_SYNC_VERSION } from './ApiConstants.js'
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
export const apiGetRequests = new Map([
|
|
@@ -81,7 +81,8 @@ function getState(_, response) {
|
|
|
81
81
|
|
|
82
82
|
|
|
83
83
|
function longPollClientSyncVersion(req, response) {
|
|
84
|
-
|
|
84
|
+
const clientVersion = req.headers[HEADER_SYNC_VERSION]
|
|
85
|
+
if (clientVersion !== undefined && uiSyncVersion.version !== Number(clientVersion)) {
|
|
85
86
|
// e.g., tab was hidden while new mocks were added or removed
|
|
86
87
|
sendJSON(response, uiSyncVersion.version)
|
|
87
88
|
return
|
|
@@ -111,9 +112,9 @@ function reinitialize(_, response) {
|
|
|
111
112
|
|
|
112
113
|
|
|
113
114
|
async function selectCookie(req, response) {
|
|
114
|
-
const
|
|
115
|
+
const cookieKey = await parseJSON(req)
|
|
115
116
|
|
|
116
|
-
const error = cookie.setCurrent(
|
|
117
|
+
const error = cookie.setCurrent(cookieKey)
|
|
117
118
|
if (error)
|
|
118
119
|
sendUnprocessableContent(response, error?.message || error)
|
|
119
120
|
else
|
package/src/ApiCommander.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { API, LONG_POLL_SERVER_TIMEOUT,
|
|
1
|
+
import { API, LONG_POLL_SERVER_TIMEOUT, HEADER_SYNC_VERSION } from './ApiConstants.js'
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
/** Client for controlling Mockaton via its HTTP API */
|
|
@@ -9,78 +9,49 @@ export class Commander {
|
|
|
9
9
|
this.#addr = addr
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
#patch = (api, body) =>
|
|
13
|
-
fetch(this.#addr + api, {
|
|
14
|
-
method: 'PATCH',
|
|
15
|
-
body: JSON.stringify(body)
|
|
16
|
-
})
|
|
17
|
-
|
|
18
12
|
/** @returns {JsonPromise<State>} */
|
|
19
13
|
getState = () =>
|
|
20
14
|
fetch(this.#addr + API.state)
|
|
21
15
|
|
|
22
|
-
/**
|
|
23
|
-
|
|
16
|
+
/**
|
|
17
|
+
* @param {number?} currSyncVer - On mismatch, it responds immediately. Otherwise, long polls.
|
|
18
|
+
* @param {AbortSignal} abortSignal
|
|
19
|
+
* @returns {JsonPromise<number>}
|
|
20
|
+
*/
|
|
21
|
+
getSyncVersion = (currSyncVer = undefined, abortSignal = undefined) =>
|
|
24
22
|
fetch(this.#addr + API.syncVersion, {
|
|
25
23
|
signal: AbortSignal.any([
|
|
26
24
|
abortSignal,
|
|
27
25
|
AbortSignal.timeout(LONG_POLL_SERVER_TIMEOUT + 1000)
|
|
28
|
-
]),
|
|
29
|
-
headers:
|
|
30
|
-
[
|
|
31
|
-
|
|
26
|
+
].filter(Boolean)),
|
|
27
|
+
headers: currSyncVer !== undefined
|
|
28
|
+
? { [HEADER_SYNC_VERSION]: currSyncVer }
|
|
29
|
+
: {}
|
|
32
30
|
})
|
|
33
31
|
|
|
34
32
|
|
|
35
|
-
|
|
36
|
-
return this.#
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
return this.#patch(API.select, file)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
toggle500(method, urlMask) {
|
|
44
|
-
return this.#patch(API.toggle500, [method, urlMask])
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
bulkSelectByComment(comment) {
|
|
48
|
-
return this.#patch(API.bulkSelect, comment)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
setRouteIsDelayed(method, urlMask, delayed) {
|
|
52
|
-
return this.#patch(API.delay, [method, urlMask, delayed])
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
setStaticRouteIsDelayed(urlMask, delayed) {
|
|
56
|
-
return this.#patch(API.delayStatic, [urlMask, delayed])
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
setStaticRouteStatus(urlMask, status) {
|
|
60
|
-
return this.#patch(API.staticStatus, [urlMask, status])
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
setRouteIsProxied(method, urlMask, proxied) {
|
|
64
|
-
return this.#patch(API.proxied, [method, urlMask, proxied])
|
|
33
|
+
#patch(api, body) {
|
|
34
|
+
return fetch(this.#addr + api, {
|
|
35
|
+
method: 'PATCH',
|
|
36
|
+
body: JSON.stringify(body)
|
|
37
|
+
})
|
|
65
38
|
}
|
|
66
39
|
|
|
67
|
-
|
|
68
|
-
return this.#patch(API.cookies, cookieKey)
|
|
69
|
-
}
|
|
40
|
+
reset = () => this.#patch(API.reset)
|
|
70
41
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
42
|
+
selectCookie = label => this.#patch(API.cookies, label)
|
|
43
|
+
setGlobalDelay = delay => this.#patch(API.globalDelay, delay)
|
|
44
|
+
setCorsAllowed = value => this.#patch(API.cors, value)
|
|
45
|
+
setProxyFallback = proxyAddr => this.#patch(API.fallback, proxyAddr)
|
|
46
|
+
setCollectProxied = shouldCollect => this.#patch(API.collectProxied, shouldCollect)
|
|
74
47
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
48
|
+
select = file => this.#patch(API.select, file)
|
|
49
|
+
bulkSelectByComment = comment => this.#patch(API.bulkSelect, comment)
|
|
78
50
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
51
|
+
toggle500 = (method, urlMask) => this.#patch(API.toggle500, [method, urlMask])
|
|
52
|
+
setRouteIsProxied = (method, urlMask, proxied) => this.#patch(API.proxied, [method, urlMask, proxied])
|
|
53
|
+
setRouteIsDelayed = (method, urlMask, delayed) => this.#patch(API.delay, [method, urlMask, delayed])
|
|
82
54
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
55
|
+
setStaticRouteStatus = (urlMask, status) => this.#patch(API.staticStatus, [urlMask, status])
|
|
56
|
+
setStaticRouteIsDelayed = (urlMask, delayed) => this.#patch(API.delayStatic, [urlMask, delayed])
|
|
86
57
|
}
|
package/src/ApiConstants.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const MOUNT = '/mockaton'
|
|
2
2
|
export const API = {
|
|
3
3
|
dashboard: MOUNT,
|
|
4
|
+
|
|
4
5
|
bulkSelect: MOUNT + '/bulk-select-by-comment',
|
|
5
6
|
collectProxied: MOUNT + '/collect-proxied',
|
|
6
7
|
cookies: MOUNT + '/cookies',
|
|
@@ -19,9 +20,9 @@ export const API = {
|
|
|
19
20
|
toggle500: MOUNT + '/toggle500'
|
|
20
21
|
}
|
|
21
22
|
|
|
22
|
-
export const
|
|
23
|
-
export const
|
|
23
|
+
export const HEADER_502 = 'Mockaton502'
|
|
24
|
+
export const HEADER_SYNC_VERSION = 'sync_version'
|
|
24
25
|
|
|
25
26
|
export const DEFAULT_MOCK_COMMENT = '(default)'
|
|
26
|
-
export const
|
|
27
|
+
export const UNKNOWN_MIME_EXT = 'unknown'
|
|
27
28
|
export const LONG_POLL_SERVER_TIMEOUT = 8_000
|
package/src/Dashboard.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createElement as r, createSvgElement as s, className, restoreFocus, Defer, Fragment } from './DashboardDom.js'
|
|
2
|
-
import {
|
|
2
|
+
import { HEADER_502 } from './ApiConstants.js'
|
|
3
3
|
import { parseFilename } from './Filename.js'
|
|
4
4
|
import { store } from './DashboardStore.js'
|
|
5
5
|
|
|
@@ -448,7 +448,7 @@ function StaticRow(row) {
|
|
|
448
448
|
!groupByMethod && r('td', className(CSS.Method),
|
|
449
449
|
'GET'),
|
|
450
450
|
|
|
451
|
-
r('td',
|
|
451
|
+
r('td', { colspan: 2 },
|
|
452
452
|
r('a', {
|
|
453
453
|
href: row.urlMask,
|
|
454
454
|
target: '_blank',
|
|
@@ -593,7 +593,7 @@ function PayloadViewerTitle(file, statusText) {
|
|
|
593
593
|
|
|
594
594
|
function PayloadViewerTitleWhenProxied(response) {
|
|
595
595
|
const mime = response.headers.get('content-type') || ''
|
|
596
|
-
const badGateway = response.headers.get(
|
|
596
|
+
const badGateway = response.headers.get(HEADER_502)
|
|
597
597
|
return (
|
|
598
598
|
r('span', null,
|
|
599
599
|
badGateway
|
|
@@ -734,7 +734,7 @@ function SettingsIcon() {
|
|
|
734
734
|
* The version increments when a mock file is added, removed, or renamed.
|
|
735
735
|
*/
|
|
736
736
|
function initRealTimeUpdates() {
|
|
737
|
-
let oldVersion =
|
|
737
|
+
let oldVersion = undefined
|
|
738
738
|
let controller = new AbortController()
|
|
739
739
|
|
|
740
740
|
longPoll()
|
|
@@ -755,11 +755,9 @@ function initRealTimeUpdates() {
|
|
|
755
755
|
ErrorToast.close()
|
|
756
756
|
|
|
757
757
|
const version = await response.json()
|
|
758
|
-
const skipUpdate = oldVersion === -1
|
|
759
758
|
if (oldVersion !== version) { // because it could be < or >
|
|
760
759
|
oldVersion = version
|
|
761
|
-
|
|
762
|
-
store.fetchState()
|
|
760
|
+
store.fetchState()
|
|
763
761
|
}
|
|
764
762
|
longPoll()
|
|
765
763
|
}
|
package/src/Filename.js
CHANGED
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
const httpMethods = [ // @KeepSync with node:http.METHODS
|
|
2
|
-
'ACL', 'BIND', 'CHECKOUT',
|
|
3
|
-
'
|
|
4
|
-
'
|
|
5
|
-
'
|
|
6
|
-
'
|
|
7
|
-
'
|
|
8
|
-
'PATCH', 'POST', 'PROPFIND',
|
|
9
|
-
'PROPPATCH', 'PURGE', 'PUT',
|
|
10
|
-
'QUERY', 'REBIND', 'REPORT',
|
|
11
|
-
'SEARCH', 'SOURCE', 'SUBSCRIBE',
|
|
12
|
-
'TRACE', 'UNBIND', 'UNLINK',
|
|
13
|
-
'UNLOCK', 'UNSUBSCRIBE'
|
|
2
|
+
'ACL', 'BIND', 'CHECKOUT', 'CONNECT', 'COPY', 'DELETE',
|
|
3
|
+
'GET', 'HEAD', 'LINK', 'LOCK', 'M-SEARCH', 'MERGE',
|
|
4
|
+
'MKACTIVITY', 'MKCALENDAR', 'MKCOL', 'MOVE', 'NOTIFY', 'OPTIONS',
|
|
5
|
+
'PATCH', 'POST', 'PROPFIND', 'PROPPATCH', 'PURGE', 'PUT',
|
|
6
|
+
'QUERY', 'REBIND', 'REPORT', 'SEARCH', 'SOURCE', 'SUBSCRIBE',
|
|
7
|
+
'TRACE', 'UNBIND', 'UNLINK', 'UNLOCK', 'UNSUBSCRIBE'
|
|
14
8
|
]
|
|
15
9
|
|
|
16
10
|
const reComments = /\(.*?\)/g // Anything within parentheses
|
package/src/MockBroker.js
CHANGED
|
@@ -4,7 +4,7 @@ import { DEFAULT_MOCK_COMMENT } from './ApiConstants.js'
|
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* MockBroker is a state for a particular route. It knows the available mock
|
|
7
|
-
* files that can be served for the route,
|
|
7
|
+
* files that can be served for the route, the currently selected file, etc.
|
|
8
8
|
*/
|
|
9
9
|
export class MockBroker {
|
|
10
10
|
constructor(file) {
|
|
@@ -114,7 +114,7 @@ class UrlMatcher {
|
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
#disregardVariables(str) { // Stars out all parts that are in square brackets
|
|
117
|
-
return str.replace(/\[.*?]/g, '[^/]
|
|
117
|
+
return str.replace(/\[.*?]/g, '[^/]+')
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
// Appending a '/' so URLs ending with variables don't match
|
package/src/Mockaton.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createServer } from 'node:http'
|
|
2
2
|
|
|
3
|
-
import { logger } from './utils/logger.js'
|
|
4
3
|
import { API } from './ApiConstants.js'
|
|
4
|
+
import { logger } from './utils/logger.js'
|
|
5
5
|
import { config, setup } from './config.js'
|
|
6
6
|
import { dispatchMock } from './MockDispatcher.js'
|
|
7
7
|
import { dispatchStatic } from './StaticDispatcher.js'
|
package/src/Watcher.js
CHANGED
|
@@ -15,6 +15,7 @@ import * as mockBrokerCollection from './mockBrokersCollection.js'
|
|
|
15
15
|
* and also renames, which are two events (delete + add).
|
|
16
16
|
*/
|
|
17
17
|
export const uiSyncVersion = new class extends EventEmitter {
|
|
18
|
+
delay = Number(process.env.MOCKATON_WATCHER_DEBOUNCE_MS ?? 80)
|
|
18
19
|
version = 0
|
|
19
20
|
|
|
20
21
|
increment = this.#debounce(() => {
|
|
@@ -33,7 +34,7 @@ export const uiSyncVersion = new class extends EventEmitter {
|
|
|
33
34
|
let timer
|
|
34
35
|
return () => {
|
|
35
36
|
clearTimeout(timer)
|
|
36
|
-
timer = setTimeout(fn,
|
|
37
|
+
timer = setTimeout(fn, this.delay)
|
|
37
38
|
}
|
|
38
39
|
}
|
|
39
40
|
}
|
|
@@ -64,7 +65,7 @@ export function watchStaticDir() {
|
|
|
64
65
|
const dir = config.staticDir
|
|
65
66
|
if (!dir)
|
|
66
67
|
return
|
|
67
|
-
|
|
68
|
+
|
|
68
69
|
watch(dir, { recursive: true, persistent: false }, (_, file) => {
|
|
69
70
|
if (!file)
|
|
70
71
|
return
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs, { readFileSync } from 'node:fs'
|
|
2
2
|
import { logger } from './logger.js'
|
|
3
3
|
import { mimeFor } from './mime.js'
|
|
4
|
-
import {
|
|
4
|
+
import { HEADER_502 } from '../ApiConstants.js'
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
export function sendOK(response) {
|
|
@@ -69,7 +69,7 @@ export function sendInternalServerError(response, error) {
|
|
|
69
69
|
export function sendBadGateway(response, error) {
|
|
70
70
|
logger.warn('Fallback Proxy Error:', error.cause.message)
|
|
71
71
|
response.statusCode = 502
|
|
72
|
-
response.setHeader(
|
|
72
|
+
response.setHeader(HEADER_502, 1)
|
|
73
73
|
response.end()
|
|
74
74
|
}
|
|
75
75
|
|
package/src/utils/mime.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { config } from '../config.js'
|
|
2
|
-
import {
|
|
2
|
+
import { UNKNOWN_MIME_EXT } from '../ApiConstants.js'
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
// Generated with:
|
|
@@ -119,7 +119,7 @@ export function extFor(mime) {
|
|
|
119
119
|
function findExt(rawMime) {
|
|
120
120
|
const m = parseMime(rawMime)
|
|
121
121
|
const extraMimeToExt = mapMimeToExt(config.extraMimes)
|
|
122
|
-
return extraMimeToExt[m] || mimeToExt[m] ||
|
|
122
|
+
return extraMimeToExt[m] || mimeToExt[m] || UNKNOWN_MIME_EXT
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
export function parseMime(mime) {
|