mockaton 5.0.1 → 5.0.3
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/Api.js +6 -15
- package/src/Config.js +2 -1
- package/src/Dashboard.js +9 -6
- package/src/MockBroker.js +2 -4
- package/src/StaticDispatcher.js +11 -10
- package/src/mockBrokersCollection.js +3 -2
- package/src/utils/fs.js +7 -0
- package/src/utils/http-response.js +11 -10
- package/src/utils/validate.js +0 -4
package/package.json
CHANGED
package/src/Api.js
CHANGED
|
@@ -31,21 +31,12 @@ export const apiPatchRequests = new Map([
|
|
|
31
31
|
[API.bulkSelect, bulkUpdateBrokersByCommentTag]
|
|
32
32
|
])
|
|
33
33
|
|
|
34
|
-
function serveDashboard(_, response) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
function
|
|
38
|
-
|
|
39
|
-
}
|
|
40
|
-
function listCookies(_, response) {
|
|
41
|
-
sendJSON(response, cookie.list())
|
|
42
|
-
}
|
|
43
|
-
function listComments(_, response) {
|
|
44
|
-
sendJSON(response, mockBrokersCollection.extractAllComments())
|
|
45
|
-
}
|
|
46
|
-
function listMockBrokers(_, response) {
|
|
47
|
-
sendJSON(response, mockBrokersCollection.getAll())
|
|
48
|
-
}
|
|
34
|
+
function serveDashboard(_, response) { sendFile(response, join(import.meta.dirname, 'Dashboard.html')) }
|
|
35
|
+
function serveDashboardAsset(req, response) { sendFile(response, join(import.meta.dirname, req.url)) }
|
|
36
|
+
|
|
37
|
+
function listCookies(_, response) { sendJSON(response, cookie.list()) }
|
|
38
|
+
function listComments(_, response) { sendJSON(response, mockBrokersCollection.extractAllComments()) }
|
|
39
|
+
function listMockBrokers(_, response) { sendJSON(response, mockBrokersCollection.getAll()) }
|
|
49
40
|
|
|
50
41
|
|
|
51
42
|
function reinitialize(_, response) {
|
package/src/Config.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { openInBrowser } from './utils/openInBrowser.js'
|
|
2
|
-
import { validate, is, optional
|
|
2
|
+
import { validate, is, optional } from './utils/validate.js'
|
|
3
|
+
import { isDirectory } from './utils/fs.js'
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
export const Config = {
|
package/src/Dashboard.js
CHANGED
|
@@ -94,7 +94,6 @@ function CookieSelector({ list }) {
|
|
|
94
94
|
method: 'PATCH',
|
|
95
95
|
body: JSON.stringify(this.value)
|
|
96
96
|
})
|
|
97
|
-
.then(init)
|
|
98
97
|
.catch(console.error)
|
|
99
98
|
}
|
|
100
99
|
}, list.map(([key, selected]) =>
|
|
@@ -202,11 +201,13 @@ function MockSelector({ broker }) {
|
|
|
202
201
|
fetch(API.edit, {
|
|
203
202
|
method: 'PATCH',
|
|
204
203
|
body: JSON.stringify({ [DF.file]: this.value })
|
|
205
|
-
}).then(() => {
|
|
206
|
-
this.closest('tr').querySelector('a').click()
|
|
207
|
-
this.closest('tr').querySelector(`.${CSS.InternalServerErrorToggler}>[type=checkbox]`).checked = status === 500
|
|
208
|
-
this.className = className(this.value === this.options[0].value, status)
|
|
209
204
|
})
|
|
205
|
+
.then(() => {
|
|
206
|
+
this.closest('tr').querySelector('a').click()
|
|
207
|
+
this.closest('tr').querySelector(`.${CSS.InternalServerErrorToggler}>[type=checkbox]`).checked = status === 500
|
|
208
|
+
this.className = className(this.value === this.options[0].value, status)
|
|
209
|
+
})
|
|
210
|
+
.catch(console.error)
|
|
210
211
|
}
|
|
211
212
|
}, files.map(file => r('option', {
|
|
212
213
|
value: file,
|
|
@@ -268,7 +269,9 @@ function InternalServerErrorToggler({ broker }) {
|
|
|
268
269
|
? items.find(f => Route.parseFilename(f).status === 500)
|
|
269
270
|
: items[0]
|
|
270
271
|
})
|
|
271
|
-
})
|
|
272
|
+
})
|
|
273
|
+
.then(init)
|
|
274
|
+
.catch(console.error)
|
|
272
275
|
}
|
|
273
276
|
}),
|
|
274
277
|
r('span', null, '500')
|
package/src/MockBroker.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { join } from 'node:path'
|
|
2
|
-
import { existsSync, lstatSync } from 'node:fs'
|
|
3
|
-
|
|
4
2
|
import { Route } from './Route.js'
|
|
5
3
|
import { Config } from './Config.js'
|
|
4
|
+
import { isDirectory } from './utils/fs.js'
|
|
6
5
|
import { DEFAULT_500_COMMENT } from './ApiConstants.js'
|
|
7
6
|
|
|
8
7
|
|
|
@@ -80,8 +79,7 @@ export class MockBroker {
|
|
|
80
79
|
#registerTemp500() {
|
|
81
80
|
const { urlMask, method } = Route.parseFilename(this.mocks[0] || this.documentation)
|
|
82
81
|
let mask = urlMask
|
|
83
|
-
|
|
84
|
-
if (existsSync(t) && lstatSync(t).isDirectory())
|
|
82
|
+
if (isDirectory(join(Config.mocksDir, urlMask)))
|
|
85
83
|
mask = urlMask + '/'
|
|
86
84
|
mask = mask.replace(/^\//, '') // remove initial slash
|
|
87
85
|
const file = `${mask}${DEFAULT_500_COMMENT}.${method}.500.txt`
|
package/src/StaticDispatcher.js
CHANGED
|
@@ -1,28 +1,29 @@
|
|
|
1
1
|
import { join } from 'node:path'
|
|
2
|
-
import { existsSync as exists, lstatSync as lstat } from 'node:fs'
|
|
3
|
-
|
|
4
2
|
import { Config } from './Config.js'
|
|
5
|
-
import {
|
|
3
|
+
import { isDirectory, isFile } from './utils/fs.js'
|
|
4
|
+
import { sendFile, sendPartialContent, sendNotFound } from './utils/http-response.js'
|
|
6
5
|
|
|
7
6
|
|
|
8
7
|
export function isStatic(req) {
|
|
9
|
-
return Config.staticDir &&
|
|
8
|
+
return Config.staticDir && resolvePath(req)
|
|
10
9
|
}
|
|
11
10
|
|
|
12
11
|
export async function dispatchStatic(req, response) {
|
|
13
12
|
const file = resolvePath(req)
|
|
14
|
-
if (
|
|
13
|
+
if (!file)
|
|
14
|
+
sendNotFound(response)
|
|
15
|
+
else if (req.headers.range)
|
|
15
16
|
await sendPartialContent(response, req.headers.range, file)
|
|
16
17
|
else
|
|
17
18
|
sendFile(response, file)
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
function resolvePath(req) {
|
|
21
|
-
|
|
22
|
-
if (
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
let candidate = join(Config.staticDir, req.url)
|
|
23
|
+
if (isDirectory(candidate))
|
|
24
|
+
candidate += '/index.html'
|
|
25
|
+
if (isFile(candidate))
|
|
26
|
+
return candidate
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { join } from 'node:path'
|
|
2
|
-
import { readdirSync as readDir
|
|
2
|
+
import { readdirSync as readDir } from 'node:fs'
|
|
3
3
|
|
|
4
4
|
import { Route } from './Route.js'
|
|
5
5
|
import { Config } from './Config.js'
|
|
6
6
|
import { cookie } from './cookie.js'
|
|
7
|
+
import { isFile } from './utils/fs.js'
|
|
7
8
|
import { MockBroker } from './MockBroker.js'
|
|
8
9
|
|
|
9
10
|
|
|
@@ -24,7 +25,7 @@ export function init() {
|
|
|
24
25
|
cookie.init(Config.cookies)
|
|
25
26
|
|
|
26
27
|
const files = readDir(Config.mocksDir, { recursive: true })
|
|
27
|
-
.filter(f => Config.allowedExt.test(f) &&
|
|
28
|
+
.filter(f => Config.allowedExt.test(f) && isFile(join(Config.mocksDir, f)))
|
|
28
29
|
.sort()
|
|
29
30
|
|
|
30
31
|
for (const file of files) {
|
package/src/utils/fs.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { lstatSync, readFileSync } from 'node:fs'
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export const isFile = path => lstatSync(path, { throwIfNoEntry: false })?.isFile()
|
|
5
|
+
export const isDirectory = path => lstatSync(path, { throwIfNoEntry: false })?.isDirectory()
|
|
6
|
+
|
|
7
|
+
export const read = path => readFileSync(path)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import fs
|
|
1
|
+
import fs from 'node:fs'
|
|
2
2
|
import { mimeFor } from './mime.js'
|
|
3
|
+
import { isFile, read } from './fs.js'
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
export function sendOK(response) {
|
|
@@ -7,17 +8,17 @@ export function sendOK(response) {
|
|
|
7
8
|
}
|
|
8
9
|
|
|
9
10
|
export function sendJSON(response, payload) {
|
|
10
|
-
response.setHeader('
|
|
11
|
+
response.setHeader('Content-Type', 'application/json')
|
|
11
12
|
response.end(JSON.stringify(payload))
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
export function sendFile(response, file) {
|
|
15
|
-
if (!
|
|
16
|
+
if (!isFile(file))
|
|
16
17
|
sendNotFound(response)
|
|
17
18
|
else {
|
|
18
|
-
response.setHeader('
|
|
19
|
-
response.end(
|
|
20
|
-
}
|
|
19
|
+
response.setHeader('Content-Type', mimeFor(file))
|
|
20
|
+
response.end(read(file))
|
|
21
|
+
}
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
export async function sendPartialContent(response, range, file) {
|
|
@@ -28,14 +29,14 @@ export async function sendPartialContent(response, range, file) {
|
|
|
28
29
|
|
|
29
30
|
if (start < 0 || start > end || start >= size || end >= size) {
|
|
30
31
|
response.statusCode = 416 // Range Not Satisfiable
|
|
31
|
-
response.setHeader('
|
|
32
|
+
response.setHeader('Content-Range', `bytes */${size}`)
|
|
32
33
|
response.end()
|
|
33
34
|
}
|
|
34
35
|
else {
|
|
35
36
|
response.statusCode = 206 // Partial Content
|
|
36
|
-
response.setHeader('
|
|
37
|
-
response.setHeader('
|
|
38
|
-
response.setHeader('
|
|
37
|
+
response.setHeader('Accept-Ranges', 'bytes')
|
|
38
|
+
response.setHeader('Content-Range', `bytes ${start}-${end}/${size}`)
|
|
39
|
+
response.setHeader('Content-Type', mimeFor(file))
|
|
39
40
|
const reader = fs.createReadStream(file, { start, end })
|
|
40
41
|
reader.on('open', function () {
|
|
41
42
|
this.pipe(response)
|
package/src/utils/validate.js
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import { existsSync as exists, lstatSync } from 'node:fs'
|
|
2
|
-
|
|
3
|
-
|
|
4
1
|
export function validate(obj, shape) {
|
|
5
2
|
for (const [field, value] of Object.entries(obj))
|
|
6
3
|
if (!shape[field](value))
|
|
@@ -9,4 +6,3 @@ export function validate(obj, shape) {
|
|
|
9
6
|
|
|
10
7
|
export const is = ctor => val => val.constructor === ctor
|
|
11
8
|
export const optional = tester => val => !val || tester(val)
|
|
12
|
-
export const isDirectory = dir => exists(dir) && lstatSync(dir).isDirectory()
|