mockaton 13.1.0 → 13.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/package.json +1 -1
- package/src/client/ApiCommander.js +2 -1
- package/src/client/app-store.js +20 -11
- package/src/server/Api.js +35 -28
- package/src/server/Watcher.js +9 -20
package/package.json
CHANGED
|
@@ -61,7 +61,8 @@ export class Commander {
|
|
|
61
61
|
|
|
62
62
|
|
|
63
63
|
/**
|
|
64
|
-
* SSE - Streams an incremental version when a mock is added, deleted, or renamed
|
|
64
|
+
* SSE - Streams an incremental version when a mock is added, deleted, or renamed.
|
|
65
|
+
* Also, when the internal state changes.
|
|
65
66
|
* @returns {Promise<Response>}
|
|
66
67
|
*/
|
|
67
68
|
getSyncVersion = () => fetch(this.addr + API.syncVersion)
|
package/src/client/app-store.js
CHANGED
|
@@ -10,6 +10,7 @@ export const store = {
|
|
|
10
10
|
onError(err) {},
|
|
11
11
|
render() {},
|
|
12
12
|
renderRow(method, urlMask) {},
|
|
13
|
+
skipNextRender: false,
|
|
13
14
|
|
|
14
15
|
brokersByMethod: /** @type ClientBrokersByMethod */ {},
|
|
15
16
|
|
|
@@ -58,49 +59,53 @@ export const store = {
|
|
|
58
59
|
if (store.showProxyField === null) // isFirstCall
|
|
59
60
|
store.showProxyField = Boolean(store.proxyFallback)
|
|
60
61
|
|
|
61
|
-
store.
|
|
62
|
+
if (store.skipNextRender)
|
|
63
|
+
store.skipNextRender = false
|
|
64
|
+
else
|
|
65
|
+
store.render()
|
|
62
66
|
})
|
|
63
67
|
},
|
|
64
68
|
|
|
65
69
|
reset() {
|
|
66
70
|
store._request(api.reset, () => {
|
|
67
71
|
store.setChosenLink('', '')
|
|
68
|
-
store.fetchState()
|
|
69
72
|
})
|
|
70
73
|
},
|
|
71
74
|
|
|
72
75
|
bulkSelectByComment(value) {
|
|
73
|
-
store._request(() => api.bulkSelectByComment(value)
|
|
74
|
-
store.fetchState()
|
|
75
|
-
})
|
|
76
|
+
store._request(() => api.bulkSelectByComment(value))
|
|
76
77
|
},
|
|
77
78
|
|
|
78
79
|
setGlobalDelay(value) {
|
|
80
|
+
store.skipNextRender = true
|
|
79
81
|
store._request(() => api.setGlobalDelay(value), () => {
|
|
80
82
|
store.delay = value
|
|
81
83
|
})
|
|
82
84
|
},
|
|
83
85
|
|
|
84
86
|
setGlobalDelayJitter(value) {
|
|
87
|
+
store.skipNextRender = true
|
|
85
88
|
store._request(() => api.setGlobalDelayJitter(value), () => {
|
|
86
89
|
store.delayJitter = value
|
|
87
90
|
})
|
|
88
91
|
},
|
|
89
92
|
|
|
90
93
|
selectCookie(name) {
|
|
94
|
+
store.skipNextRender = true
|
|
91
95
|
store._request(() => api.selectCookie(name), async response => {
|
|
92
96
|
store.cookies = await response.json()
|
|
93
97
|
})
|
|
94
98
|
},
|
|
95
99
|
|
|
96
100
|
setProxyFallback(value) {
|
|
101
|
+
store.skipNextRender = true
|
|
97
102
|
store._request(() => api.setProxyFallback(value), () => {
|
|
98
103
|
store.proxyFallback = value
|
|
99
|
-
store.render()
|
|
100
104
|
})
|
|
101
105
|
},
|
|
102
106
|
|
|
103
107
|
setCollectProxied(checked) {
|
|
108
|
+
store.skipNextRender = true
|
|
104
109
|
store._request(() => api.setCollectProxied(checked), () => {
|
|
105
110
|
store.collectProxied = checked
|
|
106
111
|
})
|
|
@@ -111,7 +116,7 @@ export const store = {
|
|
|
111
116
|
return store.brokersByMethod[method]?.[urlMask]
|
|
112
117
|
},
|
|
113
118
|
|
|
114
|
-
|
|
119
|
+
_setBroker(broker) {
|
|
115
120
|
const { method, urlMask } = parseFilename(broker.file)
|
|
116
121
|
store.brokersByMethod[method] ??= {}
|
|
117
122
|
store.brokersByMethod[method][urlMask] = broker
|
|
@@ -153,33 +158,37 @@ export const store = {
|
|
|
153
158
|
},
|
|
154
159
|
|
|
155
160
|
selectFile(file) {
|
|
161
|
+
store.skipNextRender = true
|
|
156
162
|
store._request(() => api.select(file), async response => {
|
|
157
163
|
const { method, urlMask } = parseFilename(file)
|
|
158
|
-
store.
|
|
164
|
+
store._setBroker(await response.json())
|
|
159
165
|
store.setChosenLink(method, urlMask)
|
|
160
166
|
store.renderRow(method, urlMask)
|
|
161
167
|
})
|
|
162
168
|
},
|
|
163
169
|
|
|
164
170
|
toggleStatus(method, urlMask, status) {
|
|
171
|
+
store.skipNextRender = true
|
|
165
172
|
store._request(() => api.toggleStatus(method, urlMask, status), async response => {
|
|
166
|
-
store.
|
|
173
|
+
store._setBroker(await response.json())
|
|
167
174
|
store.setChosenLink(method, urlMask)
|
|
168
175
|
store.renderRow(method, urlMask)
|
|
169
176
|
})
|
|
170
177
|
},
|
|
171
178
|
|
|
172
179
|
setProxied(method, urlMask, checked) {
|
|
180
|
+
store.skipNextRender = true
|
|
173
181
|
store._request(() => api.setRouteIsProxied(method, urlMask, checked), async response => {
|
|
174
|
-
store.
|
|
182
|
+
store._setBroker(await response.json())
|
|
175
183
|
store.setChosenLink(method, urlMask)
|
|
176
184
|
store.renderRow(method, urlMask)
|
|
177
185
|
})
|
|
178
186
|
},
|
|
179
187
|
|
|
180
188
|
setDelayed(method, urlMask, checked) {
|
|
189
|
+
store.skipNextRender = true
|
|
181
190
|
store._request(() => api.setRouteIsDelayed(method, urlMask, checked), async response => {
|
|
182
|
-
store.
|
|
191
|
+
store._setBroker(await response.json())
|
|
183
192
|
})
|
|
184
193
|
}
|
|
185
194
|
}
|
package/src/server/Api.js
CHANGED
|
@@ -5,24 +5,18 @@
|
|
|
5
5
|
|
|
6
6
|
import { join } from 'node:path'
|
|
7
7
|
|
|
8
|
-
import {
|
|
9
|
-
sseClientHotReload,
|
|
10
|
-
DASHBOARD_ASSETS,
|
|
11
|
-
CLIENT_DIR
|
|
12
|
-
} from './WatcherDevClient.js'
|
|
13
|
-
import { startWatchers, stopWatchers, sseClientSyncVersion, notifyARR } from './Watcher.js'
|
|
14
|
-
|
|
15
8
|
import pkgJSON from '../../package.json' with { type: 'json' }
|
|
16
9
|
|
|
10
|
+
import { sseClientHotReload, DASHBOARD_ASSETS, CLIENT_DIR } from './WatcherDevClient.js'
|
|
11
|
+
import { stopMocksDirWatcher, sseClientSyncVersion, uiSyncVersion, watchMocksDir } from './Watcher.js'
|
|
12
|
+
|
|
17
13
|
import { API } from '../client/ApiConstants.js'
|
|
18
14
|
import { IndexHtml, CSP } from '../client/IndexHtml.js'
|
|
19
15
|
|
|
20
16
|
import { cookie } from './cookie.js'
|
|
21
17
|
import { config, ConfigValidator } from './config.js'
|
|
22
|
-
|
|
23
|
-
import { write, rm, isFile, resolveIn } from './utils/fs.js'
|
|
24
|
-
|
|
25
18
|
import * as mockBrokersCollection from './mockBrokersCollection.js'
|
|
19
|
+
import { write, rm, isFile, resolveIn } from './utils/fs.js'
|
|
26
20
|
|
|
27
21
|
|
|
28
22
|
export const apiGetReqs = new Map([
|
|
@@ -95,6 +89,7 @@ function getState(_, response) {
|
|
|
95
89
|
function reset(_, response) {
|
|
96
90
|
mockBrokersCollection.init()
|
|
97
91
|
response.ok()
|
|
92
|
+
uiSyncVersion.increment()
|
|
98
93
|
}
|
|
99
94
|
|
|
100
95
|
|
|
@@ -106,21 +101,7 @@ async function setCorsAllowed(req, response) {
|
|
|
106
101
|
else {
|
|
107
102
|
config.corsAllowed = corsAllowed
|
|
108
103
|
response.ok()
|
|
109
|
-
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
async function setWatchMocks(req, response) {
|
|
114
|
-
const enabled = await req.json()
|
|
115
|
-
|
|
116
|
-
if (typeof enabled !== 'boolean')
|
|
117
|
-
response.unprocessable(`Expected boolean for "watchMocks"`)
|
|
118
|
-
else {
|
|
119
|
-
if (enabled)
|
|
120
|
-
startWatchers()
|
|
121
|
-
else
|
|
122
|
-
stopWatchers()
|
|
123
|
-
response.ok()
|
|
104
|
+
uiSyncVersion.increment()
|
|
124
105
|
}
|
|
125
106
|
}
|
|
126
107
|
|
|
@@ -132,7 +113,9 @@ async function setGlobalDelay(req, response) {
|
|
|
132
113
|
response.unprocessable(`Expected non-negative integer for "delay"`)
|
|
133
114
|
else {
|
|
134
115
|
config.delay = delay
|
|
116
|
+
uiSyncVersion.increment()
|
|
135
117
|
response.ok()
|
|
118
|
+
uiSyncVersion.increment()
|
|
136
119
|
}
|
|
137
120
|
}
|
|
138
121
|
|
|
@@ -144,6 +127,7 @@ async function setGlobalDelayJitter(req, response) {
|
|
|
144
127
|
else {
|
|
145
128
|
config.delayJitter = jitter
|
|
146
129
|
response.ok()
|
|
130
|
+
uiSyncVersion.increment()
|
|
147
131
|
}
|
|
148
132
|
}
|
|
149
133
|
|
|
@@ -154,8 +138,10 @@ async function selectCookie(req, response) {
|
|
|
154
138
|
const error = cookie.setCurrent(cookieKey)
|
|
155
139
|
if (error)
|
|
156
140
|
response.unprocessable(error?.message || error)
|
|
157
|
-
else
|
|
141
|
+
else {
|
|
158
142
|
response.json(cookie.list())
|
|
143
|
+
uiSyncVersion.increment()
|
|
144
|
+
}
|
|
159
145
|
}
|
|
160
146
|
|
|
161
147
|
|
|
@@ -167,6 +153,7 @@ async function setProxyFallback(req, response) {
|
|
|
167
153
|
else {
|
|
168
154
|
config.proxyFallback = fallback
|
|
169
155
|
response.ok()
|
|
156
|
+
uiSyncVersion.increment()
|
|
170
157
|
}
|
|
171
158
|
}
|
|
172
159
|
|
|
@@ -178,6 +165,7 @@ async function setCollectProxied(req, response) {
|
|
|
178
165
|
else {
|
|
179
166
|
config.collectProxied = collectProxied
|
|
180
167
|
response.ok()
|
|
168
|
+
uiSyncVersion.increment()
|
|
181
169
|
}
|
|
182
170
|
}
|
|
183
171
|
|
|
@@ -188,6 +176,7 @@ async function bulkUpdateBrokersByCommentTag(req, response) {
|
|
|
188
176
|
|
|
189
177
|
mockBrokersCollection.setMocksMatchingComment(comment)
|
|
190
178
|
response.ok()
|
|
179
|
+
uiSyncVersion.increment()
|
|
191
180
|
}
|
|
192
181
|
|
|
193
182
|
|
|
@@ -200,6 +189,7 @@ async function selectMock(req, response) {
|
|
|
200
189
|
else {
|
|
201
190
|
broker.selectFile(file)
|
|
202
191
|
response.json(broker)
|
|
192
|
+
uiSyncVersion.increment()
|
|
203
193
|
}
|
|
204
194
|
}
|
|
205
195
|
|
|
@@ -213,6 +203,7 @@ async function toggleRouteStatus(req, response) {
|
|
|
213
203
|
else {
|
|
214
204
|
broker.toggleStatus(status)
|
|
215
205
|
response.json(broker)
|
|
206
|
+
uiSyncVersion.increment()
|
|
216
207
|
}
|
|
217
208
|
}
|
|
218
209
|
|
|
@@ -228,6 +219,7 @@ async function setRouteIsDelayed(req, response) {
|
|
|
228
219
|
else {
|
|
229
220
|
broker.setDelayed(delayed)
|
|
230
221
|
response.json(broker)
|
|
222
|
+
uiSyncVersion.increment()
|
|
231
223
|
}
|
|
232
224
|
}
|
|
233
225
|
|
|
@@ -245,6 +237,7 @@ async function setRouteIsProxied(req, response) {
|
|
|
245
237
|
else {
|
|
246
238
|
broker.setProxied(proxied)
|
|
247
239
|
response.json(broker)
|
|
240
|
+
uiSyncVersion.increment()
|
|
248
241
|
}
|
|
249
242
|
}
|
|
250
243
|
|
|
@@ -263,7 +256,7 @@ async function writeMock(req, response) {
|
|
|
263
256
|
|
|
264
257
|
if (!config.watcherEnabled) {
|
|
265
258
|
mockBrokersCollection.registerMock(file, true)
|
|
266
|
-
|
|
259
|
+
uiSyncVersion.increment()
|
|
267
260
|
}
|
|
268
261
|
response.ok()
|
|
269
262
|
}
|
|
@@ -286,10 +279,24 @@ async function deleteMock(req, response) {
|
|
|
286
279
|
|
|
287
280
|
if (!config.watcherEnabled) {
|
|
288
281
|
mockBrokersCollection.unregisterMock(file)
|
|
289
|
-
|
|
282
|
+
uiSyncVersion.increment()
|
|
290
283
|
}
|
|
291
284
|
response.ok()
|
|
292
285
|
}
|
|
293
286
|
|
|
294
287
|
|
|
295
288
|
|
|
289
|
+
async function setWatchMocks(req, response) {
|
|
290
|
+
const enabled = await req.json()
|
|
291
|
+
|
|
292
|
+
if (typeof enabled !== 'boolean')
|
|
293
|
+
response.unprocessable(`Expected boolean for "watchMocks"`)
|
|
294
|
+
else {
|
|
295
|
+
if (enabled)
|
|
296
|
+
watchMocksDir()
|
|
297
|
+
else
|
|
298
|
+
stopMocksDirWatcher()
|
|
299
|
+
response.ok()
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
package/src/server/Watcher.js
CHANGED
|
@@ -12,24 +12,22 @@ let mocksWatcher = null
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
|
-
* ARR Event = Add, Remove, or Rename Mock
|
|
16
|
-
*
|
|
17
15
|
* The emitter is debounced so it handles e.g. bulk deletes,
|
|
18
16
|
* and also renames, which are two events (delete + add).
|
|
19
17
|
*/
|
|
20
|
-
const uiSyncVersion = new class extends EventEmitter {
|
|
18
|
+
export const uiSyncVersion = new class extends EventEmitter {
|
|
21
19
|
version = 0
|
|
22
20
|
|
|
23
21
|
increment = /** @type {function} */ this.#debounce(() => {
|
|
24
22
|
this.version++
|
|
25
|
-
super.emit('
|
|
23
|
+
super.emit('INC')
|
|
26
24
|
})
|
|
27
25
|
|
|
28
26
|
subscribe(listener) {
|
|
29
|
-
this.on('
|
|
27
|
+
this.on('INC', listener)
|
|
30
28
|
}
|
|
31
29
|
unsubscribe(listener) {
|
|
32
|
-
this.removeListener('
|
|
30
|
+
this.removeListener('INC', listener)
|
|
33
31
|
}
|
|
34
32
|
|
|
35
33
|
#debounce(fn) { // TESTME
|
|
@@ -42,11 +40,6 @@ const uiSyncVersion = new class extends EventEmitter {
|
|
|
42
40
|
}
|
|
43
41
|
|
|
44
42
|
|
|
45
|
-
export function notifyARR() {
|
|
46
|
-
uiSyncVersion.increment()
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
|
|
50
43
|
export function watchMocksDir() {
|
|
51
44
|
const dir = config.mocksDir
|
|
52
45
|
mocksWatcher = mocksWatcher || watch(dir, { recursive: true, persistent: false }, (_, file) => {
|
|
@@ -69,8 +62,12 @@ export function watchMocksDir() {
|
|
|
69
62
|
})
|
|
70
63
|
}
|
|
71
64
|
|
|
65
|
+
export function stopMocksDirWatcher() {
|
|
66
|
+
mocksWatcher?.close()
|
|
67
|
+
mocksWatcher = null
|
|
68
|
+
}
|
|
69
|
+
|
|
72
70
|
|
|
73
|
-
/** Realtime notify ARR Events */
|
|
74
71
|
export function sseClientSyncVersion(req, response) {
|
|
75
72
|
response.writeHead(200, {
|
|
76
73
|
'Content-Type': 'text/event-stream',
|
|
@@ -99,11 +96,3 @@ export function sseClientSyncVersion(req, response) {
|
|
|
99
96
|
}
|
|
100
97
|
|
|
101
98
|
|
|
102
|
-
export function startWatchers() {
|
|
103
|
-
watchMocksDir()
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
export function stopWatchers() {
|
|
107
|
-
mocksWatcher?.close()
|
|
108
|
-
mocksWatcher = null
|
|
109
|
-
}
|