mockaton 12.2.2 → 12.3.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 +3 -14
- package/index.d.ts +1 -1
- package/package.json +1 -1
- package/src/client/ApiCommander.js +1 -1
- package/src/client/ApiConstants.js +3 -2
- package/src/client/Filename.js +45 -1
- package/src/client/app-store.js +2 -4
- package/src/client/app.js +200 -184
- package/src/client/dom-utils.js +9 -14
- package/src/client/indexHtml.js +19 -20
- package/src/client/styles.css +33 -85
- package/src/server/Api.js +7 -6
- package/src/server/MockBroker.js +2 -2
- package/src/server/Mockaton.js +2 -1
- package/src/server/Mockaton.test.js +3 -2
- package/src/server/ProxyRelay.js +2 -1
- package/src/server/StaticDispatcher.js +1 -1
- package/src/server/Watcher.js +1 -1
- package/src/server/WatcherDevClient.js +3 -2
- package/src/server/mockBrokersCollection.js +1 -1
- package/src/server/utils/HttpIncomingMessage.js +2 -2
- package/src/server/utils/HttpServerResponse.js +1 -1
- package/src/server/utils/mime.js +1 -1
- package/src/server/ApiConstants.js +0 -32
- package/src/server/Filename.js +0 -65
package/src/client/dom-utils.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export function
|
|
1
|
+
export function classNames(...args) {
|
|
2
2
|
return {
|
|
3
3
|
className: args.filter(Boolean).join(' ')
|
|
4
4
|
}
|
|
@@ -6,12 +6,14 @@ export function className(...args) {
|
|
|
6
6
|
|
|
7
7
|
export function createElement(tag, props, ...children) {
|
|
8
8
|
const elem = document.createElement(tag)
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
if (props)
|
|
10
|
+
for (const [k, v] of Object.entries(props))
|
|
11
|
+
if (v === undefined) continue
|
|
12
|
+
else if (k === 'ref') v.elem = elem
|
|
13
|
+
else if (k === 'style') Object.assign(elem.style, v)
|
|
14
|
+
else if (k.startsWith('on')) elem.addEventListener(k.slice(2).toLowerCase(), ...[v].flat())
|
|
15
|
+
else if (k in elem) elem[k] = v
|
|
16
|
+
else elem.setAttribute(k, v)
|
|
15
17
|
elem.append(...children.flat().filter(Boolean))
|
|
16
18
|
return elem
|
|
17
19
|
}
|
|
@@ -66,13 +68,6 @@ function selectorFor(elem) {
|
|
|
66
68
|
}
|
|
67
69
|
|
|
68
70
|
|
|
69
|
-
|
|
70
|
-
// Minimal implementation of CSS Modules in the browser
|
|
71
|
-
// TODO think about avoiding clashes when using multiple files. e.g.:
|
|
72
|
-
// - should the user pass a prefix?, or
|
|
73
|
-
// - should the ensure there's a unique top-level classname on each file
|
|
74
|
-
// TODO ignore rules in comments?
|
|
75
|
-
|
|
76
71
|
export function adoptCSS(sheet) {
|
|
77
72
|
document.adoptedStyleSheets.push(sheet)
|
|
78
73
|
Object.assign(sheet, extractClassNames(sheet))
|
package/src/client/indexHtml.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { API } from './ApiConstants.js'
|
|
2
2
|
|
|
3
|
-
|
|
4
3
|
export const CSP = [
|
|
5
4
|
`default-src 'self'`,
|
|
6
5
|
`img-src data: blob: 'self'`
|
|
@@ -9,24 +8,24 @@ export const CSP = [
|
|
|
9
8
|
|
|
10
9
|
// language=html
|
|
11
10
|
export const IndexHtml = (hotReloadEnabled, version) => `
|
|
12
|
-
<!DOCTYPE html>
|
|
13
|
-
<html lang="en-US">
|
|
14
|
-
<head>
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
<!DOCTYPE html>
|
|
12
|
+
<html lang="en-US">
|
|
13
|
+
<head>
|
|
14
|
+
<meta charset="UTF-8">
|
|
15
|
+
<base href="${API.dashboard}/">
|
|
16
|
+
|
|
17
|
+
<script type="module" src="app.js"></script>
|
|
18
|
+
<link rel="preload" href="${API.state}" as="fetch" crossorigin>
|
|
17
19
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
: ''}
|
|
30
|
-
</body>
|
|
31
|
-
</html>
|
|
20
|
+
<link rel="icon" href="data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='m235 33.7v202c0 9.19-5.81 14-17.4 14-11.6 0-17.4-4.83-17.4-14v-151c-0.115-4.49-6.72-5.88-8.46-0.87l-48.3 155c-2.22 7.01-7.72 10.1-16 9.9-3.63-0.191-7.01-1.14-9.66-2.89-2.89-1.72-4.83-4.34-5.57-7.72-11.1-37-22.6-74.3-34.1-111-4.34-14-8.95-31.4-14-48.3-1.82-4.83-8.16-5.32-8.46 1.16v156c0 9.19-5.81 14-17.4 14-11.6 0-17.4-4.83-17.4-14v-207c0-5.74 2.62-13.2 9.39-16.3 7.5-3.14 15-4.05 21.8-3.8 3.14 0 6.03 0.686 8.95 1.46 3.14 0.797 6.03 1.98 8.7 3.63 2.65 1.38 5.32 3.14 7.5 5.57 2.22 2.22 3.87 4.83 5.07 7.72l45.8 157c4.63-15.9 32.4-117 33.3-121 4.12-13.8 7.72-26.5 10.9-38.7 1.16-2.65 2.89-5.32 5.07-7.5 2.15-2.15 4.58-4.12 7.5-5.32 2.65-1.57 5.57-2.89 8.46-3.63 3.14-0.797 9.44-0.988 12.1-0.988 11.6 1.07 29.4 9.14 29.4 27z' fill='%23808080'/%3E%3C/svg%3E">
|
|
21
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
22
|
+
<meta name="description" content="HTTP Mock Server">
|
|
23
|
+
<title>Mockaton v${version}</title>
|
|
24
|
+
</head>
|
|
25
|
+
<body>
|
|
26
|
+
${hotReloadEnabled
|
|
27
|
+
? '<script type="module" src="watcherDev.js"></script>'
|
|
28
|
+
: ''}
|
|
29
|
+
</body>
|
|
30
|
+
</html>
|
|
32
31
|
`
|
package/src/client/styles.css
CHANGED
|
@@ -400,7 +400,7 @@ main {
|
|
|
400
400
|
padding-bottom: 4px;
|
|
401
401
|
padding-left: 1px;
|
|
402
402
|
border-top: 24px solid transparent;
|
|
403
|
-
margin-left:
|
|
403
|
+
margin-left: 71px;
|
|
404
404
|
font-weight: bold;
|
|
405
405
|
text-align: left;
|
|
406
406
|
|
|
@@ -409,7 +409,7 @@ main {
|
|
|
409
409
|
}
|
|
410
410
|
|
|
411
411
|
&.canProxy {
|
|
412
|
-
margin-left:
|
|
412
|
+
margin-left: 100px;
|
|
413
413
|
}
|
|
414
414
|
&.nonGroupedByMethod {
|
|
415
415
|
margin-left: 122px;
|
|
@@ -505,11 +505,11 @@ main {
|
|
|
505
505
|
}
|
|
506
506
|
}
|
|
507
507
|
|
|
508
|
-
|
|
509
|
-
.
|
|
508
|
+
|
|
509
|
+
.Toggler {
|
|
510
510
|
display: flex;
|
|
511
511
|
|
|
512
|
-
|
|
512
|
+
input {
|
|
513
513
|
/* For click drag target */
|
|
514
514
|
position: absolute;
|
|
515
515
|
width: 22px;
|
|
@@ -518,137 +518,85 @@ main {
|
|
|
518
518
|
|
|
519
519
|
&:focus-visible {
|
|
520
520
|
outline: 0;
|
|
521
|
-
& +
|
|
521
|
+
& + .checkboxBody {
|
|
522
522
|
outline: 2px solid var(--colorAccent)
|
|
523
523
|
}
|
|
524
524
|
}
|
|
525
|
-
}
|
|
526
525
|
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
}
|
|
526
|
+
&:disabled + .checkboxBody {
|
|
527
|
+
cursor: not-allowed;
|
|
528
|
+
opacity: 0.7;
|
|
529
|
+
}
|
|
532
530
|
|
|
533
|
-
.
|
|
534
|
-
> input {
|
|
535
|
-
&:checked + svg {
|
|
531
|
+
&:checked + .checkboxBody {
|
|
536
532
|
border-color: var(--colorAccent);
|
|
537
533
|
fill: var(--colorAccent);
|
|
538
534
|
background: var(--colorAccent);
|
|
539
535
|
stroke: var(--colorBackground);
|
|
540
536
|
}
|
|
541
537
|
|
|
542
|
-
&:enabled:hover:not(:checked) +
|
|
538
|
+
&:enabled:hover:not(:checked) + .checkboxBody {
|
|
543
539
|
border-color: var(--colorHover);
|
|
544
540
|
background: var(--colorHover);
|
|
545
541
|
stroke: var(--colorText);
|
|
546
542
|
}
|
|
547
543
|
}
|
|
548
544
|
|
|
549
|
-
|
|
545
|
+
.checkboxBody {
|
|
546
|
+
display: flex;
|
|
550
547
|
width: 22px;
|
|
551
548
|
height: 22px;
|
|
549
|
+
align-items: center;
|
|
550
|
+
justify-content: center;
|
|
552
551
|
border: 1px solid var(--colorSecondaryActionBorder);
|
|
552
|
+
fill: none;
|
|
553
|
+
stroke: var(--colorSecondaryAction);
|
|
553
554
|
stroke-width: 2.5px;
|
|
554
555
|
border-radius: 50%;
|
|
555
556
|
}
|
|
556
557
|
|
|
557
558
|
&.canProxy {
|
|
558
|
-
margin-left:
|
|
559
|
+
margin-left: 30px;
|
|
559
560
|
}
|
|
560
561
|
}
|
|
561
562
|
|
|
563
|
+
.DelayToggler {
|
|
564
|
+
}
|
|
565
|
+
|
|
562
566
|
.ProxyToggler {
|
|
563
|
-
border: 1px solid var(--colorSecondaryActionBorder);
|
|
564
567
|
margin-right: 8px;
|
|
565
|
-
border-radius: var(--radius);
|
|
566
|
-
|
|
567
|
-
&:has(input:checked),
|
|
568
|
-
&:has(input:disabled) {
|
|
569
|
-
background: transparent;
|
|
570
|
-
box-shadow: none;
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
> input {
|
|
574
|
-
&:checked + svg {
|
|
575
|
-
fill: var(--colorAccent);
|
|
576
|
-
stroke: var(--colorAccent);
|
|
577
|
-
|
|
578
|
-
path:last-of-type { /* inner cloud curve */
|
|
579
|
-
stroke: var(--colorBackground);
|
|
580
|
-
}
|
|
581
|
-
transform: scale(1.1);
|
|
582
|
-
}
|
|
583
|
-
|
|
584
|
-
&:enabled:hover:not(:checked) + svg {
|
|
585
|
-
fill: var(--colorHover);
|
|
586
|
-
stroke: var(--colorText);
|
|
587
|
-
}
|
|
588
568
|
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
box-shadow: none;
|
|
593
|
-
fill: transparent;
|
|
594
|
-
|
|
595
|
-
path:last-of-type {
|
|
596
|
-
stroke-opacity: 0;
|
|
597
|
-
stroke: transparent;
|
|
598
|
-
}
|
|
569
|
+
.checkboxBody {
|
|
570
|
+
svg {
|
|
571
|
+
width: 16px;
|
|
599
572
|
}
|
|
600
573
|
}
|
|
601
|
-
|
|
602
|
-
> svg {
|
|
603
|
-
width: 26px;
|
|
604
|
-
padding: 1px 4px;
|
|
605
|
-
stroke-width: 2px;
|
|
606
|
-
border-radius: var(--radius);
|
|
607
|
-
}
|
|
608
574
|
}
|
|
609
575
|
|
|
610
|
-
.
|
|
611
|
-
.NotFoundToggler {
|
|
612
|
-
display: flex;
|
|
576
|
+
.StatusCodeToggler {
|
|
613
577
|
margin-right: 10px;
|
|
614
578
|
margin-left: 8px;
|
|
615
|
-
cursor: pointer;
|
|
616
|
-
|
|
617
|
-
> input {
|
|
618
|
-
appearance: none;
|
|
619
579
|
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
& + .checkboxBody {
|
|
623
|
-
outline: 2px solid var(--colorAccent)
|
|
624
|
-
}
|
|
625
|
-
}
|
|
580
|
+
input {
|
|
581
|
+
width: 26px;
|
|
626
582
|
|
|
627
|
-
&:
|
|
628
|
-
|
|
629
|
-
|
|
583
|
+
&:not(:checked):enabled:hover + .checkboxBody {
|
|
584
|
+
border-color: var(--colorRed);
|
|
585
|
+
color: var(--colorRed);
|
|
630
586
|
}
|
|
631
587
|
&:checked + .checkboxBody {
|
|
632
588
|
border-color: var(--colorRed);
|
|
633
589
|
color: white;
|
|
634
590
|
background: var(--colorRed);
|
|
635
591
|
}
|
|
636
|
-
&:not(:checked):enabled:hover + .checkboxBody {
|
|
637
|
-
border-color: var(--colorRed);
|
|
638
|
-
color: var(--colorRed);
|
|
639
|
-
}
|
|
640
|
-
&:enabled:active + .checkboxBody {
|
|
641
|
-
cursor: grabbing;
|
|
642
|
-
}
|
|
643
592
|
}
|
|
644
593
|
|
|
645
|
-
|
|
594
|
+
.checkboxBody {
|
|
595
|
+
width: 27px;
|
|
646
596
|
padding: 4px;
|
|
647
|
-
border: 1px solid var(--colorSecondaryActionBorder);
|
|
648
597
|
font-size: 10px;
|
|
649
598
|
font-weight: bold;
|
|
650
599
|
color: var(--colorSecondaryAction);
|
|
651
|
-
border-radius: var(--radius);
|
|
652
600
|
}
|
|
653
601
|
}
|
|
654
602
|
|
package/src/server/Api.js
CHANGED
|
@@ -13,9 +13,10 @@ import {
|
|
|
13
13
|
import { longPollClientSyncVersion } from './Watcher.js'
|
|
14
14
|
|
|
15
15
|
import pkgJSON from '../../package.json' with { type: 'json' }
|
|
16
|
+
|
|
17
|
+
import { API } from '../client/ApiConstants.js'
|
|
16
18
|
import { IndexHtml, CSP } from '../client/indexHtml.js'
|
|
17
19
|
|
|
18
|
-
import { API } from './ApiConstants.js'
|
|
19
20
|
import { cookie } from './cookie.js'
|
|
20
21
|
import { config, ConfigValidator } from './config.js'
|
|
21
22
|
|
|
@@ -29,7 +30,7 @@ export const apiGetReqs = new Map([
|
|
|
29
30
|
|
|
30
31
|
[API.state, getState],
|
|
31
32
|
[API.syncVersion, longPollClientSyncVersion],
|
|
32
|
-
|
|
33
|
+
|
|
33
34
|
[API.watchHotReload, longPollDevClientHotReload],
|
|
34
35
|
[API.throws, () => { throw new Error('Test500') }]
|
|
35
36
|
])
|
|
@@ -41,17 +42,17 @@ export const apiPatchReqs = new Map([
|
|
|
41
42
|
[API.cookies, selectCookie],
|
|
42
43
|
[API.globalDelay, setGlobalDelay],
|
|
43
44
|
[API.globalDelayJitter, setGlobalDelayJitter],
|
|
44
|
-
|
|
45
|
+
|
|
45
46
|
[API.fallback, setProxyFallback],
|
|
46
47
|
[API.collectProxied, setCollectProxied],
|
|
47
|
-
|
|
48
|
+
|
|
48
49
|
[API.bulkSelect, bulkUpdateBrokersByCommentTag],
|
|
49
50
|
|
|
50
51
|
[API.delay, setRouteIsDelayed],
|
|
51
52
|
[API.select, selectMock],
|
|
52
53
|
[API.proxied, setRouteIsProxied],
|
|
53
54
|
[API.toggle500, toggleRoute500],
|
|
54
|
-
|
|
55
|
+
|
|
55
56
|
[API.delayStatic, setStaticRouteIsDelayed],
|
|
56
57
|
[API.staticStatus, setStaticRouteStatusCode]
|
|
57
58
|
])
|
|
@@ -220,7 +221,7 @@ async function setRouteIsProxied(req, response) {
|
|
|
220
221
|
|
|
221
222
|
const broker = mockBrokersCollection.brokerByRoute(method, urlMask)
|
|
222
223
|
if (!broker)
|
|
223
|
-
response.unprocessable(
|
|
224
|
+
response.unprocessable(`Route does not exist: ${method} ${urlMask}`)
|
|
224
225
|
else if (typeof proxied !== 'boolean')
|
|
225
226
|
response.unprocessable(`Expected boolean for "proxied"`)
|
|
226
227
|
else if (proxied && !config.proxyFallback)
|
package/src/server/MockBroker.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { DEFAULT_MOCK_COMMENT } from '
|
|
2
|
-
import { includesComment, extractComments
|
|
1
|
+
import { DEFAULT_MOCK_COMMENT } from '../client/ApiConstants.js'
|
|
2
|
+
import { parseFilename, includesComment, extractComments } from '../client/Filename.js'
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
/**
|
package/src/server/Mockaton.js
CHANGED
|
@@ -8,7 +8,8 @@ import { IncomingMessage } from './utils/HttpIncomingMessage.js'
|
|
|
8
8
|
import { setCorsHeaders, isPreflight } from './utils/http-cors.js'
|
|
9
9
|
import { BodyReaderError, hasControlChars } from './utils/HttpIncomingMessage.js'
|
|
10
10
|
|
|
11
|
-
import { API } from '
|
|
11
|
+
import { API } from '../client/ApiConstants.js'
|
|
12
|
+
|
|
12
13
|
import { config, setup } from './config.js'
|
|
13
14
|
import { apiPatchReqs, apiGetReqs } from './Api.js'
|
|
14
15
|
|
|
@@ -9,17 +9,18 @@ import { describe, test, before, beforeEach, after } from 'node:test'
|
|
|
9
9
|
import { mkdtempSync } from 'node:fs'
|
|
10
10
|
import { writeFile, unlink, mkdir, readFile, rename } from 'node:fs/promises'
|
|
11
11
|
|
|
12
|
+
import { API } from '../client/ApiConstants.js'
|
|
13
|
+
|
|
12
14
|
import { logger } from './utils/logger.js'
|
|
13
15
|
import { mimeFor } from './utils/mime.js'
|
|
14
16
|
import { readBody } from './utils/HttpIncomingMessage.js'
|
|
15
17
|
import { CorsHeader } from './utils/http-cors.js'
|
|
16
18
|
|
|
17
|
-
import { API } from './ApiConstants.js'
|
|
18
19
|
import { Mockaton } from './Mockaton.js'
|
|
19
|
-
import { parseFilename } from './Filename.js'
|
|
20
20
|
import { watchMocksDir, watchStaticDir } from './Watcher.js'
|
|
21
21
|
|
|
22
22
|
import { Commander } from '../client/ApiCommander.js'
|
|
23
|
+
import { parseFilename } from '../client/Filename.js'
|
|
23
24
|
|
|
24
25
|
|
|
25
26
|
const mocksDir = mkdtempSync(join(tmpdir(), 'mocks'))
|
package/src/server/ProxyRelay.js
CHANGED
|
@@ -6,7 +6,8 @@ import { write, isFile } from './utils/fs.js'
|
|
|
6
6
|
import { readBody, BodyReaderError } from './utils/HttpIncomingMessage.js'
|
|
7
7
|
|
|
8
8
|
import { config } from './config.js'
|
|
9
|
-
|
|
9
|
+
|
|
10
|
+
import { makeMockFilename } from '../client/Filename.js'
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
export async function proxy(req, response, delay) {
|
package/src/server/Watcher.js
CHANGED
|
@@ -5,7 +5,7 @@ import { EventEmitter } from 'node:events'
|
|
|
5
5
|
import {
|
|
6
6
|
HEADER_SYNC_VERSION,
|
|
7
7
|
LONG_POLL_SERVER_TIMEOUT
|
|
8
|
-
} from '
|
|
8
|
+
} from '../client/ApiConstants.js'
|
|
9
9
|
|
|
10
10
|
import { config } from './config.js'
|
|
11
11
|
import { isFile, isDirectory } from './utils/fs.js'
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { join } from 'node:path'
|
|
2
2
|
import { EventEmitter } from 'node:events'
|
|
3
3
|
import { watch, readdirSync } from 'node:fs'
|
|
4
|
+
|
|
4
5
|
import { config } from './config.js'
|
|
5
|
-
import { LONG_POLL_SERVER_TIMEOUT } from '
|
|
6
|
+
import { LONG_POLL_SERVER_TIMEOUT } from '../client/ApiConstants.js'
|
|
6
7
|
|
|
7
8
|
|
|
8
9
|
export const CLIENT_DIR = join(import.meta.dirname, '../client')
|
|
@@ -31,7 +32,7 @@ export function longPollDevClientHotReload(req, response) {
|
|
|
31
32
|
response.notFound()
|
|
32
33
|
return
|
|
33
34
|
}
|
|
34
|
-
|
|
35
|
+
|
|
35
36
|
function onDevChange(file) {
|
|
36
37
|
devClientWatcher.unsubscribe(onDevChange)
|
|
37
38
|
response.json(file)
|
|
@@ -6,7 +6,7 @@ import { listFilesRecursively } from './utils/fs.js'
|
|
|
6
6
|
import { cookie } from './cookie.js'
|
|
7
7
|
import { MockBroker } from './MockBroker.js'
|
|
8
8
|
import { config, isFileAllowed } from './config.js'
|
|
9
|
-
import { parseFilename, validateFilename } from '
|
|
9
|
+
import { parseFilename, validateFilename } from '../client/Filename.js'
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
/**
|
|
@@ -69,7 +69,7 @@ export function hasControlChars(url) {
|
|
|
69
69
|
|
|
70
70
|
export function decode(url) {
|
|
71
71
|
const candidate = decodeURIComponent(url)
|
|
72
|
-
return candidate === decodeURIComponent(candidate)
|
|
73
|
-
? candidate
|
|
72
|
+
return candidate === decodeURIComponent(candidate)
|
|
73
|
+
? candidate
|
|
74
74
|
: '' // reject multiple encodings
|
|
75
75
|
}
|
|
@@ -3,7 +3,7 @@ import fs, { readFileSync } from 'node:fs'
|
|
|
3
3
|
|
|
4
4
|
import { logger } from './logger.js'
|
|
5
5
|
import { mimeFor } from './mime.js'
|
|
6
|
-
import { HEADER_502 } from '
|
|
6
|
+
import { HEADER_502 } from '../../client/ApiConstants.js'
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
export class ServerResponse extends http.ServerResponse {
|
package/src/server/utils/mime.js
CHANGED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
// @KeepSync src/client/ApiConstants.js
|
|
2
|
-
|
|
3
|
-
const MOUNT = '/mockaton'
|
|
4
|
-
export const API = {
|
|
5
|
-
dashboard: MOUNT,
|
|
6
|
-
|
|
7
|
-
bulkSelect: MOUNT + '/bulk-select-by-comment',
|
|
8
|
-
collectProxied: MOUNT + '/collect-proxied',
|
|
9
|
-
cookies: MOUNT + '/cookies',
|
|
10
|
-
cors: MOUNT + '/cors',
|
|
11
|
-
delay: MOUNT + '/delay',
|
|
12
|
-
delayStatic: MOUNT + '/delay-static',
|
|
13
|
-
fallback: MOUNT + '/fallback',
|
|
14
|
-
globalDelay: MOUNT + '/global-delay',
|
|
15
|
-
globalDelayJitter: MOUNT + '/global-delay-jitter',
|
|
16
|
-
proxied: MOUNT + '/proxied',
|
|
17
|
-
reset: MOUNT + '/reset',
|
|
18
|
-
select: MOUNT + '/select',
|
|
19
|
-
state: MOUNT + '/state',
|
|
20
|
-
staticStatus: MOUNT + '/static-status',
|
|
21
|
-
syncVersion: MOUNT + '/sync-version',
|
|
22
|
-
throws: MOUNT + '/throws',
|
|
23
|
-
toggle500: MOUNT + '/toggle500',
|
|
24
|
-
watchHotReload: MOUNT + '/watch-hot-reload',
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export const HEADER_502 = 'Mockaton502'
|
|
28
|
-
export const HEADER_SYNC_VERSION = 'sync_version'
|
|
29
|
-
|
|
30
|
-
export const DEFAULT_MOCK_COMMENT = '(default)'
|
|
31
|
-
export const UNKNOWN_MIME_EXT = 'unknown'
|
|
32
|
-
export const LONG_POLL_SERVER_TIMEOUT = 8_000
|
package/src/server/Filename.js
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
/** @KeepSync src/client/Filename.js */
|
|
2
|
-
|
|
3
|
-
import { METHODS } from 'node:http'
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const reComments = /\(.*?\)/g // Anything within parentheses
|
|
7
|
-
|
|
8
|
-
export function extractComments(file) {
|
|
9
|
-
return Array.from(file.matchAll(reComments), ([c]) => c)
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export function includesComment(file, search) {
|
|
13
|
-
return extractComments(file).some(c => c.includes(search))
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
export function validateFilename(file) {
|
|
18
|
-
const tokens = file.replace(reComments, '').split('.')
|
|
19
|
-
if (tokens.length < 4)
|
|
20
|
-
return 'Invalid Filename Convention'
|
|
21
|
-
|
|
22
|
-
const { status, method } = parseFilename(file)
|
|
23
|
-
if (!responseStatusIsValid(status))
|
|
24
|
-
return `Invalid HTTP Response Status: "${status}"`
|
|
25
|
-
|
|
26
|
-
if (!METHODS.includes(method))
|
|
27
|
-
return `Unrecognized HTTP Method: "${method}"`
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
export function parseFilename(file) {
|
|
32
|
-
const tokens = file.replace(reComments, '').split('.')
|
|
33
|
-
return {
|
|
34
|
-
ext: tokens.pop(),
|
|
35
|
-
status: Number(tokens.pop()),
|
|
36
|
-
method: tokens.pop(),
|
|
37
|
-
urlMask: '/' + removeTrailingSlash(tokens.join('.'))
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function removeTrailingSlash(url = '') {
|
|
42
|
-
return url
|
|
43
|
-
.replace(/\/$/, '')
|
|
44
|
-
.replace('/?', '?')
|
|
45
|
-
.replace('/#', '#')
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function responseStatusIsValid(status) {
|
|
49
|
-
return Number.isInteger(status)
|
|
50
|
-
&& status >= 100
|
|
51
|
-
&& status <= 599
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
export function makeMockFilename(url, method, status, ext) {
|
|
56
|
-
const urlMask = replaceIds(removeTrailingSlash(url))
|
|
57
|
-
return [urlMask, method, status, ext].join('.')
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const reUuidV4 = /([0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})/gi
|
|
61
|
-
function replaceIds(filename) {
|
|
62
|
-
return filename.replaceAll(reUuidV4, '[id]')
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
|