mockaton 11.2.5 → 11.2.6
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 +30 -28
- package/package.json +1 -1
- package/src/client/ApiCommander.js +54 -39
- package/src/client/ApiConstants.js +1 -1
- package/src/client/Filename.js +3 -3
- package/src/client/app.js +62 -61
- package/src/client/dom-utils.js +5 -3
- package/src/client/styles.css +77 -46
- package/src/server/Api.js +88 -125
- package/src/server/Filename.js +8 -6
- package/src/server/MockBroker.js +1 -1
- package/src/server/MockDispatcher.js +3 -2
- package/src/server/Mockaton.js +16 -11
- package/src/server/ProxyRelay.js +3 -2
- package/src/server/StaticDispatcher.js +2 -1
- package/src/server/Watcher.js +31 -3
- package/src/server/WatcherDevClient.js +38 -5
- package/src/server/cli.js +1 -0
- package/src/server/config.js +2 -1
- package/src/server/mockBrokersCollection.js +2 -1
- package/src/server/utils/fs.js +1 -0
- package/src/server/utils/http-response.js +6 -0
package/src/server/Watcher.js
CHANGED
|
@@ -2,19 +2,26 @@ import { join } from 'node:path'
|
|
|
2
2
|
import { watch } from 'node:fs'
|
|
3
3
|
import { EventEmitter } from 'node:events'
|
|
4
4
|
|
|
5
|
+
import {
|
|
6
|
+
HEADER_SYNC_VERSION,
|
|
7
|
+
LONG_POLL_SERVER_TIMEOUT
|
|
8
|
+
} from './ApiConstants.js'
|
|
9
|
+
|
|
5
10
|
import { config } from './config.js'
|
|
11
|
+
import { sendJSON } from './utils/http-response.js'
|
|
6
12
|
import { isFile, isDirectory } from './utils/fs.js'
|
|
13
|
+
|
|
7
14
|
import * as staticCollection from './staticCollection.js'
|
|
8
15
|
import * as mockBrokerCollection from './mockBrokersCollection.js'
|
|
9
16
|
|
|
10
17
|
|
|
11
18
|
/**
|
|
12
|
-
* ARR = Add, Remove, or Rename Mock
|
|
19
|
+
* ARR Event = Add, Remove, or Rename Mock
|
|
13
20
|
*
|
|
14
21
|
* The emitter is debounced so it handles e.g. bulk deletes,
|
|
15
22
|
* and also renames, which are two events (delete + add).
|
|
16
23
|
*/
|
|
17
|
-
|
|
24
|
+
const uiSyncVersion = new class extends EventEmitter {
|
|
18
25
|
delay = Number(process.env.MOCKATON_WATCHER_DEBOUNCE_MS ?? 80)
|
|
19
26
|
version = 0
|
|
20
27
|
|
|
@@ -39,6 +46,7 @@ export const uiSyncVersion = new class extends EventEmitter {
|
|
|
39
46
|
}
|
|
40
47
|
}
|
|
41
48
|
|
|
49
|
+
|
|
42
50
|
export function watchMocksDir() {
|
|
43
51
|
const dir = config.mocksDir
|
|
44
52
|
watch(dir, { recursive: true, persistent: false }, (_, file) => {
|
|
@@ -61,6 +69,7 @@ export function watchMocksDir() {
|
|
|
61
69
|
})
|
|
62
70
|
}
|
|
63
71
|
|
|
72
|
+
|
|
64
73
|
export function watchStaticDir() {
|
|
65
74
|
const dir = config.staticDir
|
|
66
75
|
if (!dir)
|
|
@@ -86,4 +95,23 @@ export function watchStaticDir() {
|
|
|
86
95
|
})
|
|
87
96
|
}
|
|
88
97
|
|
|
89
|
-
|
|
98
|
+
|
|
99
|
+
/** Realtime notify ARR Events */
|
|
100
|
+
export function longPollClientSyncVersion(req, response) {
|
|
101
|
+
const clientVersion = req.headers[HEADER_SYNC_VERSION]
|
|
102
|
+
if (clientVersion !== undefined && uiSyncVersion.version !== Number(clientVersion)) {
|
|
103
|
+
// e.g., tab was hidden while new mocks were added or removed
|
|
104
|
+
sendJSON(response, uiSyncVersion.version)
|
|
105
|
+
return
|
|
106
|
+
}
|
|
107
|
+
function onARR() {
|
|
108
|
+
uiSyncVersion.unsubscribe(onARR)
|
|
109
|
+
sendJSON(response, uiSyncVersion.version)
|
|
110
|
+
}
|
|
111
|
+
response.setTimeout(LONG_POLL_SERVER_TIMEOUT, onARR)
|
|
112
|
+
req.on('error', () => {
|
|
113
|
+
uiSyncVersion.unsubscribe(onARR)
|
|
114
|
+
response.destroy()
|
|
115
|
+
})
|
|
116
|
+
uiSyncVersion.subscribe(onARR)
|
|
117
|
+
}
|
|
@@ -1,17 +1,50 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { join } from 'node:path'
|
|
2
2
|
import { EventEmitter } from 'node:events'
|
|
3
|
+
import { watch, readdirSync } from 'node:fs'
|
|
4
|
+
import { sendJSON, sendNotFound } from './utils/http-response.js'
|
|
5
|
+
import { LONG_POLL_SERVER_TIMEOUT } from './ApiConstants.js'
|
|
3
6
|
|
|
4
7
|
|
|
5
|
-
|
|
8
|
+
const DEV = process.env.NODE_ENV === 'development'
|
|
9
|
+
|
|
10
|
+
export const CLIENT_DIR = join(import.meta.dirname, '../client')
|
|
11
|
+
export const DASHBOARD_ASSETS = readdirSync(CLIENT_DIR)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
const devClientWatcher = new class extends EventEmitter {
|
|
6
15
|
emit(file) { super.emit('RELOAD', file) }
|
|
7
16
|
subscribe(listener) { this.once('RELOAD', listener) }
|
|
8
17
|
unsubscribe(listener) { this.removeListener('RELOAD', listener) }
|
|
9
18
|
}
|
|
10
19
|
|
|
11
|
-
|
|
12
|
-
//
|
|
20
|
+
|
|
21
|
+
// Although `client/indexHtml.js` is watched, it returns a stale version.
|
|
22
|
+
// i.e., it would need to be a dynamic import + cache busting.
|
|
13
23
|
export function watchDevSPA() {
|
|
14
|
-
watch(
|
|
24
|
+
watch(CLIENT_DIR, (_, file) => {
|
|
15
25
|
devClientWatcher.emit(file)
|
|
16
26
|
})
|
|
17
27
|
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
/** Realtime notify Dev UI changes */
|
|
31
|
+
export function longPollDevClientHotReload(req, response) {
|
|
32
|
+
if (!DEV) {
|
|
33
|
+
sendNotFound(response)
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function onDevChange(file) {
|
|
38
|
+
devClientWatcher.unsubscribe(onDevChange)
|
|
39
|
+
sendJSON(response, file)
|
|
40
|
+
}
|
|
41
|
+
response.setTimeout(LONG_POLL_SERVER_TIMEOUT, () => {
|
|
42
|
+
devClientWatcher.unsubscribe(onDevChange)
|
|
43
|
+
sendJSON(response, '')
|
|
44
|
+
})
|
|
45
|
+
req.on('error', () => {
|
|
46
|
+
devClientWatcher.unsubscribe(onDevChange)
|
|
47
|
+
response.destroy()
|
|
48
|
+
})
|
|
49
|
+
devClientWatcher.subscribe(onDevChange)
|
|
50
|
+
}
|
package/src/server/cli.js
CHANGED
package/src/server/config.js
CHANGED
|
@@ -3,11 +3,12 @@ import { resolve } from 'node:path'
|
|
|
3
3
|
import { logger } from './utils/logger.js'
|
|
4
4
|
import { isDirectory } from './utils/fs.js'
|
|
5
5
|
import { openInBrowser } from './utils/openInBrowser.js'
|
|
6
|
-
import { jsToJsonPlugin } from './MockDispatcher.js'
|
|
7
6
|
import { optional, is, validate } from './utils/validate.js'
|
|
8
7
|
import { SUPPORTED_METHODS } from './utils/http-request.js'
|
|
9
8
|
import { validateCorsAllowedMethods, validateCorsAllowedOrigins } from './utils/http-cors.js'
|
|
10
9
|
|
|
10
|
+
import { jsToJsonPlugin } from './MockDispatcher.js'
|
|
11
|
+
|
|
11
12
|
|
|
12
13
|
/** @type {{
|
|
13
14
|
* [K in keyof Config]-?: [
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { basename } from 'node:path'
|
|
2
2
|
|
|
3
3
|
import { logger } from './utils/logger.js'
|
|
4
|
+
import { listFilesRecursively } from './utils/fs.js'
|
|
5
|
+
|
|
4
6
|
import { cookie } from './cookie.js'
|
|
5
7
|
import { MockBroker } from './MockBroker.js'
|
|
6
|
-
import { listFilesRecursively } from './utils/fs.js'
|
|
7
8
|
import { config, isFileAllowed } from './config.js'
|
|
8
9
|
import { parseFilename, validateFilename } from './Filename.js'
|
|
9
10
|
|
package/src/server/utils/fs.js
CHANGED
|
@@ -47,6 +47,12 @@ export function sendBadRequest(response) {
|
|
|
47
47
|
response.end()
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
export function sendNotFound(response) {
|
|
51
|
+
response.statusCode = 404
|
|
52
|
+
logger.access(response)
|
|
53
|
+
response.end()
|
|
54
|
+
}
|
|
55
|
+
|
|
50
56
|
export function sendMockNotFound(response) {
|
|
51
57
|
response.statusCode = 404
|
|
52
58
|
logger.accessMock(response.req.url, '404')
|