mockaton 9.1.1 → 9.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/README.md +22 -11
- package/lcov.info +780 -774
- package/package.json +1 -1
- package/src/Api.js +2 -1
- package/src/ApiConstants.js +2 -1
- package/src/Dashboard.js +19 -19
- package/src/MockDispatcher.js +3 -6
- package/src/Mockaton.js +2 -19
- package/src/cli.js +34 -16
- package/src/config.js +8 -13
- package/src/utils/http-response.js +1 -1
package/package.json
CHANGED
package/src/Api.js
CHANGED
|
@@ -27,6 +27,7 @@ export const apiGetRequests = new Map([
|
|
|
27
27
|
|
|
28
28
|
[API.state, getState],
|
|
29
29
|
[API.syncVersion, longPollClientSyncVersion],
|
|
30
|
+
[API.throws, () => { throw new Error('Test500') }]
|
|
30
31
|
])
|
|
31
32
|
|
|
32
33
|
export const apiPatchRequests = new Map([
|
|
@@ -51,7 +52,7 @@ function serveDashboardAsset(f) {
|
|
|
51
52
|
return (_, response) => {
|
|
52
53
|
if (f.endsWith('.html'))
|
|
53
54
|
response.setHeader('Content-Security-Policy', `default-src 'self'; img-src data: blob: 'self'`)
|
|
54
|
-
|
|
55
|
+
sendFile(response, join(import.meta.dirname, f))
|
|
55
56
|
}
|
|
56
57
|
}
|
|
57
58
|
|
package/src/ApiConstants.js
CHANGED
|
@@ -14,7 +14,8 @@ export const API = {
|
|
|
14
14
|
select: MOUNT + '/select',
|
|
15
15
|
state: MOUNT + '/state',
|
|
16
16
|
staticStatus: MOUNT + '/static-status',
|
|
17
|
-
syncVersion: MOUNT + '/sync-version'
|
|
17
|
+
syncVersion: MOUNT + '/sync-version',
|
|
18
|
+
throws: MOUNT + '/throws',
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
export const DF = { // Dashboard Fields (XHR)
|
package/src/Dashboard.js
CHANGED
|
@@ -87,7 +87,7 @@ const state = {
|
|
|
87
87
|
delay: 0,
|
|
88
88
|
collectProxied: false,
|
|
89
89
|
proxyFallback: '',
|
|
90
|
-
|
|
90
|
+
|
|
91
91
|
groupByMethod: true, // TODO read from localstorage
|
|
92
92
|
|
|
93
93
|
get canProxy() {
|
|
@@ -692,13 +692,18 @@ async function updatePayloadViewer(method, urlMask, response) {
|
|
|
692
692
|
const body = await response.text() || Strings.empty_response_body
|
|
693
693
|
if (mime === 'application/json')
|
|
694
694
|
payloadViewerRef.current.replaceChildren(r('span', className(CSS.json), syntaxJSON(body)))
|
|
695
|
-
else if (mime
|
|
695
|
+
else if (isXML(mime))
|
|
696
696
|
payloadViewerRef.current.replaceChildren(syntaxXML(body))
|
|
697
697
|
else
|
|
698
698
|
payloadViewerRef.current.innerText = body
|
|
699
699
|
}
|
|
700
700
|
}
|
|
701
701
|
|
|
702
|
+
function isXML(mime) {
|
|
703
|
+
return ['text/html', 'text/xml', 'application/xml'].includes(mime)
|
|
704
|
+
|| /application\/.*\+xml/.test(mime)
|
|
705
|
+
}
|
|
706
|
+
|
|
702
707
|
|
|
703
708
|
function trFor(method, urlMask) {
|
|
704
709
|
return document.querySelector(`tr[data-method="${method}"][data-urlMask="${urlMask}"]`)
|
|
@@ -811,30 +816,25 @@ function className(...args) {
|
|
|
811
816
|
}
|
|
812
817
|
|
|
813
818
|
|
|
814
|
-
function createElement(
|
|
815
|
-
if (typeof
|
|
816
|
-
return
|
|
819
|
+
function createElement(tag, props, ...children) {
|
|
820
|
+
if (typeof tag === 'function')
|
|
821
|
+
return tag(props)
|
|
817
822
|
|
|
818
|
-
const node = document.createElement(
|
|
819
|
-
for (const [
|
|
820
|
-
if (
|
|
821
|
-
|
|
822
|
-
else if (
|
|
823
|
-
|
|
824
|
-
else
|
|
825
|
-
Object.assign(node.style, value)
|
|
826
|
-
else if (key in node)
|
|
827
|
-
node[key] = value
|
|
828
|
-
else
|
|
829
|
-
node.setAttribute(key, value)
|
|
823
|
+
const node = document.createElement(tag)
|
|
824
|
+
for (const [k, v] of Object.entries(props || {}))
|
|
825
|
+
if (k === 'ref') v.current = node
|
|
826
|
+
else if (k === 'style') Object.assign(node.style, v)
|
|
827
|
+
else if (k.startsWith('on')) node.addEventListener(k.replace(/^on/, '').toLowerCase(), v)
|
|
828
|
+
else if (k in node) node[k] = v
|
|
829
|
+
else node.setAttribute(k, v)
|
|
830
830
|
node.append(...children.flat().filter(Boolean))
|
|
831
831
|
return node
|
|
832
832
|
}
|
|
833
833
|
|
|
834
834
|
function createSvgElement(tagName, props, ...children) {
|
|
835
835
|
const elem = document.createElementNS('http://www.w3.org/2000/svg', tagName)
|
|
836
|
-
for (const [
|
|
837
|
-
elem.setAttribute(
|
|
836
|
+
for (const [k, v] of Object.entries(props))
|
|
837
|
+
elem.setAttribute(k, v)
|
|
838
838
|
elem.append(...children.flat().filter(Boolean))
|
|
839
839
|
return elem
|
|
840
840
|
}
|
package/src/MockDispatcher.js
CHANGED
|
@@ -7,9 +7,8 @@ import { proxy } from './ProxyRelay.js'
|
|
|
7
7
|
import { cookie } from './cookie.js'
|
|
8
8
|
import { mimeFor } from './utils/mime.js'
|
|
9
9
|
import { config, calcDelay } from './config.js'
|
|
10
|
-
import { BodyReaderError } from './utils/http-request.js'
|
|
11
10
|
import * as mockBrokerCollection from './mockBrokersCollection.js'
|
|
12
|
-
import { sendInternalServerError, sendNotFound
|
|
11
|
+
import { sendInternalServerError, sendNotFound } from './utils/http-response.js'
|
|
13
12
|
|
|
14
13
|
|
|
15
14
|
export async function dispatchMock(req, response) {
|
|
@@ -40,11 +39,9 @@ export async function dispatchMock(req, response) {
|
|
|
40
39
|
setTimeout(() => response.end(body), Number(broker.delayed && calcDelay()))
|
|
41
40
|
}
|
|
42
41
|
catch (error) {
|
|
43
|
-
if (error
|
|
44
|
-
sendUnprocessableContent(response, error.name)
|
|
45
|
-
else if (error.code === 'ENOENT') // mock-file has been deleted
|
|
42
|
+
if (error?.code === 'ENOENT') // mock-file has been deleted
|
|
46
43
|
sendNotFound(response)
|
|
47
|
-
else if (error
|
|
44
|
+
else if (error?.code === 'ERR_UNKNOWN_FILE_EXTENSION') {
|
|
48
45
|
if (error.toString().includes('Unknown file extension ".ts'))
|
|
49
46
|
log.warn('\nLooks like you need a TypeScript compiler\n')
|
|
50
47
|
sendInternalServerError(response, error)
|
package/src/Mockaton.js
CHANGED
|
@@ -14,15 +14,8 @@ import { apiPatchRequests, apiGetRequests } from './Api.js'
|
|
|
14
14
|
import { sendNoContent, sendInternalServerError, sendUnprocessableContent } from './utils/http-response.js'
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
process.on('unhandledRejection', error => { throw error })
|
|
18
|
-
|
|
19
17
|
export function Mockaton(options) {
|
|
20
|
-
|
|
21
|
-
if (error) {
|
|
22
|
-
log.error(error)
|
|
23
|
-
process.exitCode = 1
|
|
24
|
-
return
|
|
25
|
-
}
|
|
18
|
+
setup(options)
|
|
26
19
|
|
|
27
20
|
mockBrokerCollection.init()
|
|
28
21
|
staticCollection.init()
|
|
@@ -31,12 +24,7 @@ export function Mockaton(options) {
|
|
|
31
24
|
|
|
32
25
|
const server = createServer(onRequest)
|
|
33
26
|
|
|
34
|
-
server.listen(config.port, config.host, function (
|
|
35
|
-
if (error) {
|
|
36
|
-
log.error(error)
|
|
37
|
-
process.exit(1)
|
|
38
|
-
return
|
|
39
|
-
}
|
|
27
|
+
server.listen(config.port, config.host, function () {
|
|
40
28
|
const { address, port } = this.address()
|
|
41
29
|
const url = `http://${address}:${port}`
|
|
42
30
|
log.info('Listening', url)
|
|
@@ -44,11 +32,6 @@ export function Mockaton(options) {
|
|
|
44
32
|
config.onReady(url + API.dashboard)
|
|
45
33
|
})
|
|
46
34
|
|
|
47
|
-
server.on('error', error => {
|
|
48
|
-
log.error(error.message)
|
|
49
|
-
process.exit(1)
|
|
50
|
-
})
|
|
51
|
-
|
|
52
35
|
return server
|
|
53
36
|
}
|
|
54
37
|
|
package/src/cli.js
CHANGED
|
@@ -8,26 +8,35 @@ import { Mockaton } from '../index.js'
|
|
|
8
8
|
import pkgJSON from '../package.json' with { type: 'json' }
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
options: {
|
|
13
|
-
config: { short: 'c', type: 'string' },
|
|
11
|
+
process.on('unhandledRejection', error => { throw error })
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
let args
|
|
14
|
+
try {
|
|
15
|
+
args = parseArgs({
|
|
16
|
+
options: {
|
|
17
|
+
config: { short: 'c', type: 'string' },
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
port: { short: 'p', type: 'string' },
|
|
20
|
+
host: { short: 'H', type: 'string' },
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
}).values
|
|
22
|
+
'mocks-dir': { short: 'm', type: 'string' },
|
|
23
|
+
'static-dir': { short: 's', type: 'string' },
|
|
24
|
+
|
|
25
|
+
quiet: { short: 'q', type: 'boolean' },
|
|
26
|
+
'no-open': { short: 'n', type: 'boolean' },
|
|
28
27
|
|
|
28
|
+
help: { short: 'h', type: 'boolean' },
|
|
29
|
+
version: { short: 'v', type: 'boolean' }
|
|
30
|
+
}
|
|
31
|
+
}).values
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
console.error(error.message)
|
|
35
|
+
process.exit(1)
|
|
36
|
+
}
|
|
29
37
|
|
|
30
|
-
|
|
38
|
+
|
|
39
|
+
if (args.version)
|
|
31
40
|
console.log(pkgJSON.version)
|
|
32
41
|
|
|
33
42
|
else if (args.help)
|
|
@@ -73,5 +82,14 @@ else {
|
|
|
73
82
|
if (args.quiet) opts.logLevel = 'quiet'
|
|
74
83
|
if (args['no-open']) opts.onReady = () => {}
|
|
75
84
|
|
|
76
|
-
|
|
85
|
+
try {
|
|
86
|
+
Mockaton(opts).on('error', error => {
|
|
87
|
+
console.error(error.message)
|
|
88
|
+
process.exit(1)
|
|
89
|
+
})
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
console.error(err?.message || err)
|
|
93
|
+
process.exit(1)
|
|
94
|
+
}
|
|
77
95
|
}
|
package/src/config.js
CHANGED
|
@@ -22,9 +22,9 @@ const schema = {
|
|
|
22
22
|
|
|
23
23
|
host: ['127.0.0.1', is(String)],
|
|
24
24
|
port: [0, port => Number.isInteger(port) && port >= 0 && port < 2 ** 16], // 0 means auto-assigned
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
logLevel: ['normal', val => ['normal', 'quiet'].includes(val)],
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
delay: [1200, ms => Number.isInteger(ms) && ms >= 0],
|
|
29
29
|
delayJitter: [0, percent => percent >= 0 && percent <= 3],
|
|
30
30
|
|
|
@@ -43,13 +43,13 @@ const schema = {
|
|
|
43
43
|
corsExposedHeaders: [[], Array.isArray],
|
|
44
44
|
corsCredentials: [true, is(Boolean)],
|
|
45
45
|
corsMaxAge: [0, is(Number)],
|
|
46
|
-
|
|
46
|
+
|
|
47
47
|
plugins: [
|
|
48
48
|
[
|
|
49
49
|
[/\.(js|ts)$/, jsToJsonPlugin]
|
|
50
50
|
], Array.isArray],
|
|
51
51
|
|
|
52
|
-
onReady: [await openInBrowser, is(Function)]
|
|
52
|
+
onReady: [await openInBrowser, is(Function)]
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
|
|
@@ -77,15 +77,10 @@ export function setup(options) {
|
|
|
77
77
|
|
|
78
78
|
if (!options.staticDir && !isDirectory(defaults.staticDir))
|
|
79
79
|
options.staticDir = ''
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
log.setLevel(config.logLevel)
|
|
85
|
-
}
|
|
86
|
-
catch (err) {
|
|
87
|
-
return err.message
|
|
88
|
-
}
|
|
80
|
+
|
|
81
|
+
Object.assign(config, options)
|
|
82
|
+
validate(config, ConfigValidator)
|
|
83
|
+
log.setLevel(config.logLevel)
|
|
89
84
|
}
|
|
90
85
|
|
|
91
86
|
|
|
@@ -35,7 +35,7 @@ export function sendUnprocessableContent(response, error) {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
export function sendInternalServerError(response, error) {
|
|
38
|
-
log.error(error)
|
|
38
|
+
log.error(error?.message || error, error?.stack || undefined)
|
|
39
39
|
response.statusCode = 500
|
|
40
40
|
response.end()
|
|
41
41
|
}
|