mockaton 12.7.2 → 13.0.1

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.
@@ -11,14 +11,15 @@ export class MockBroker {
11
11
  this.file = '' // selected mock filename
12
12
  this.mocks = [] // filenames
13
13
  this.status = -1
14
+ this.isStatic = false // doesn’t follow filename convention
14
15
  this.delayed = false
15
16
  this.proxied = false
16
- this.auto500 = false
17
+ this.autoStatus = 0
17
18
  this.urlMaskMatches = new UrlMatcher(file).urlMaskMatches
18
19
  this.register(file)
19
20
  }
20
21
 
21
- #is500 = file => parseFilename(file).status === 500
22
+ #isStatus = (file, status) => parseFilename(file).status === status
22
23
 
23
24
  #sortMocks() {
24
25
  this.mocks.sort()
@@ -27,7 +28,7 @@ export class MockBroker {
27
28
  }
28
29
 
29
30
  register(file) {
30
- if (this.auto500 && this.#is500(file))
31
+ if (this.autoStatus && this.#isStatus(file, this.autoStatus))
31
32
  this.selectFile(file)
32
33
  this.mocks.push(file)
33
34
  this.#sortMocks()
@@ -44,27 +45,29 @@ export class MockBroker {
44
45
  hasMock = file => this.mocks.includes(file)
45
46
 
46
47
  selectFile(filename) {
48
+ const { status, isStatic } = parseFilename(filename)
47
49
  this.file = filename
50
+ this.status = status
51
+ this.isStatic = isStatic
48
52
  this.proxied = false
49
- this.auto500 = false
50
- this.status = parseFilename(filename).status
53
+ this.autoStatus = 0
51
54
  }
52
55
 
53
56
  selectDefaultFile() {
54
57
  this.selectFile(this.mocks[0])
55
58
  }
56
59
 
57
- toggle500() {
58
- const shouldUnset = this.auto500 || this.status === 500
60
+ toggleStatus(status) {
61
+ const shouldUnset = this.autoStatus === status || (!this.autoStatus && this.status === status)
59
62
  if (shouldUnset)
60
63
  this.selectDefaultFile()
61
64
  else {
62
- const f500 = this.mocks.find(this.#is500)
63
- if (f500)
64
- this.selectFile(f500)
65
+ const fStatus = this.mocks.find(f => parseFilename(f).status === status)
66
+ if (fStatus)
67
+ this.selectFile(fStatus)
65
68
  else {
66
- this.auto500 = true
67
- this.status = 500
69
+ this.autoStatus = status
70
+ this.status = status
68
71
  }
69
72
  }
70
73
  this.proxied = false
@@ -75,7 +78,7 @@ export class MockBroker {
75
78
  }
76
79
 
77
80
  setProxied(proxied) {
78
- this.auto500 = false
81
+ this.autoStatus = 0
79
82
  this.proxied = proxied
80
83
  }
81
84
 
@@ -4,6 +4,7 @@ import { logger } from './utils/logger.js'
4
4
 
5
5
  import { proxy } from './ProxyRelay.js'
6
6
  import { cookie } from './cookie.js'
7
+ import { parseFilename } from '../client/Filename.js'
7
8
  import { echoFilePlugin } from './MockDispatcherPlugins.js'
8
9
  import { brokerByRoute } from './mockBrokersCollection.js'
9
10
  import { config, calcDelay } from './config.js'
@@ -29,12 +30,25 @@ export async function dispatchMock(req, response) {
29
30
  if (cookie.getCurrent())
30
31
  response.setHeader('Set-Cookie', cookie.getCurrent())
31
32
 
32
- response.statusCode = broker.auto500
33
- ? 500
33
+ const { isStatic } = parseFilename(broker.file)
34
+
35
+ if (isStatic && req.headers.range && !broker.autoStatus) {
36
+ setTimeout(async () => {
37
+ await response.partialContent(req.headers.range, join(config.mocksDir, broker.file))
38
+ }, Number(broker.delayed && calcDelay()))
39
+ logger.accessMock(req.url, broker.file)
40
+ return
41
+ }
42
+
43
+ response.statusCode = broker.autoStatus
44
+ ? broker.autoStatus
34
45
  : broker.status
35
- const { mime, body } = broker.auto500
46
+
47
+ const { mime, body } = broker.autoStatus
36
48
  ? { mime: '', body: '' }
37
- : await applyPlugins(join(config.mocksDir, broker.file), req, response)
49
+ : isStatic
50
+ ? echoFilePlugin(join(config.mocksDir, broker.file))
51
+ : await applyPlugins(join(config.mocksDir, broker.file), req, response)
38
52
 
39
53
  response.setHeader('Content-Type', mime)
40
54
  response.setHeader('Content-Length', length(body))
@@ -15,25 +15,21 @@ import { config, setup } from './config.js'
15
15
  import { apiPatchReqs, apiGetReqs } from './Api.js'
16
16
 
17
17
  import { dispatchMock } from './MockDispatcher.js'
18
- import { dispatchStatic } from './StaticDispatcher.js'
19
18
 
20
- import * as staticCollection from './staticCollection.js'
21
19
  import * as mockBrokerCollection from './mockBrokersCollection.js'
22
20
 
23
21
  import { watchDevSPA } from './WatcherDevClient.js'
24
- import { watchMocksDir, watchStaticDir } from './Watcher.js'
22
+ import { watchMocksDir } from './Watcher.js'
25
23
 
26
24
 
27
25
  export function Mockaton(options) {
28
26
  return new Promise((resolve, reject) => {
29
27
  setup(options)
30
28
  mockBrokerCollection.init()
31
- staticCollection.init()
32
29
 
33
30
  if (config.watcherEnabled) {
34
31
  register('./cacheBustResolver.js', import.meta.url)
35
32
  watchMocksDir()
36
- watchStaticDir()
37
33
  }
38
34
  if (config.hotReload)
39
35
  watchDevSPA()
@@ -84,9 +80,6 @@ async function onRequest(req, response) {
84
80
  else if (method === 'GET' && apiGetReqs.has(pathname))
85
81
  apiGetReqs.get(pathname)(req, response)
86
82
 
87
- else if (method === 'GET' && staticCollection.brokerByRoute(pathname))
88
- await dispatchStatic(req, response)
89
-
90
83
  else
91
84
  await dispatchMock(req, response)
92
85
  }
@@ -6,9 +6,7 @@ export default {
6
6
  userB: jwtCookie('CookieB', { email: 'john@example.test' }),
7
7
  },
8
8
  extraHeaders: ['custom_header_name', 'custom_header_val'],
9
- extraMimes: {
10
- ['custom_extension']: 'custom_mime'
11
- },
9
+ extraMimes: { ['custom_extension']: 'custom_mime' },
12
10
  logLevel: 'verbose',
13
11
  corsOrigins: ['https://example.test'],
14
12
  corsExposedHeaders: ['Content-Encoding'],
@@ -17,14 +17,12 @@ import CONFIG from './Mockaton.test.config.js'
17
17
 
18
18
 
19
19
  const mocksDir = mkdtempSync(join(tmpdir(), 'mocks'))
20
- const staticDir = mkdtempSync(join(tmpdir(), 'static'))
21
20
 
22
21
  const stdout = []
23
22
  const stderr = []
24
23
  const proc = spawn(join(import.meta.dirname, 'cli.js'), [
24
+ mocksDir,
25
25
  '--config', join(import.meta.dirname, 'Mockaton.test.config.js'),
26
- '--mocks-dir', mocksDir,
27
- '--static-dir', staticDir,
28
26
  '--no-open'
29
27
  ])
30
28
 
@@ -47,10 +45,8 @@ const listFromMocksDir = d => readdir(join(mocksDir, d))
47
45
  const readFromMocksDir = f => readFile(join(mocksDir, f), 'utf8')
48
46
 
49
47
  const makeDirInMocks = dir => mkdir(join(mocksDir, dir), { recursive: true })
50
- const makeDirInStaticMocks = dir => mkdir(join(staticDir, dir), { recursive: true })
51
48
 
52
49
  const renameInMocksDir = (src, target) => rename(join(mocksDir, src), join(mocksDir, target))
53
- const renameInStaticMocksDir = (src, target) => rename(join(staticDir, src), join(staticDir, target))
54
50
 
55
51
 
56
52
  const api = new Commander(serverAddr)
@@ -128,7 +124,7 @@ class Fixture extends BaseFixture {
128
124
  class FixtureStatic extends BaseFixture {
129
125
  constructor(file, body = '') {
130
126
  super(file, body)
131
- this.dir = staticDir
127
+ this.dir = mocksDir
132
128
  this.urlMask = '/' + file
133
129
  this.method = 'GET'
134
130
  }
@@ -149,26 +145,24 @@ describe('Windows', () => {
149
145
 
150
146
  describe('Rejects malicious URLs', () => {
151
147
  [
152
- ['double-encoded', `/${encodeURIComponent(encodeURIComponent('/'))}user`, 400],
153
- ['encoded null byte', '/user%00/admin', 400],
154
- ['invalid percent-encoding', '/user%ZZ', 400],
155
- ['encoded CRLF sequence', '/user%0d%0aSet-Cookie:%20x=1', 400],
156
- ['overlong/illegal UTF-8 sequence', '/user%C0%AF', 400],
157
- ['double-double-encoding trick', '/%25252Fuser', 400],
158
- ['zero-width/invisible char', '/user%E2%80%8Binfo', 404],
159
- ['encoded path traversal', '/user/..%2Fadmin', 404],
160
- ['raw path traversal', '/../user', 404],
161
-
162
- ['very long path', '/'.repeat(2048 + 1), 414]
148
+ ['double-encoded', 400, `/${encodeURIComponent(encodeURIComponent('/'))}user`],
149
+ ['encoded null byte', 400, '/user%00/admin'],
150
+ ['invalid percent-encoding', 400, '/user%ZZ'],
151
+ ['encoded CRLF sequence', 400, '/user%0d%0aSet-Cookie:%20x=1'],
152
+ ['overlong/illegal UTF-8 sequence', 400, '/user%C0%AF'],
153
+ ['double-double-encoding trick', 400, '/%25252Fuser'],
154
+ ['zero-width/invisible char', 404, '/user%E2%80%8Binfo'],
155
+ ['encoded path traversal', 404, '/user/..%2Fadmin'],
156
+ ['raw path traversal', 404, '/../user'],
157
+ ['very long path', 414, '/'.repeat(2048 + 1)]
163
158
  ]
164
- .map(([title, url, status]) =>
165
- test(title, async () =>
166
- equal((await request(url)).status, status)))
159
+ .forEach(([title, status, url]) => test(title, async () =>
160
+ equal((await request(url)).status, status)))
167
161
  })
168
162
 
169
163
 
170
- describe('Warnings', () => {
171
- test('rejects invalid filenames', async () => {
164
+ describe('Filename Convention', () => {
165
+ test('registers invalid filenames as GET 200', async () => {
172
166
  const fx0 = new Fixture('bar.GET._INVALID_STATUS_.json')
173
167
  const fx1 = new Fixture('foo._INVALID_METHOD_.202.json')
174
168
  const fx2 = new Fixture('missing-method-and-status.json')
@@ -177,10 +171,10 @@ describe('Warnings', () => {
177
171
  await fx2.write()
178
172
  await api.reset()
179
173
 
180
- const log = stderr.join('')
181
- match(log, /Invalid HTTP Response Status: "NaN"/)
182
- match(log, /Unrecognized HTTP Method: "_INVALID_METHOD_"/)
183
- match(log, /Invalid Filename Convention/)
174
+ const s = await fetchState()
175
+ equal(s.brokersByMethod.GET['/bar.GET._INVALID_STATUS_.json'].file, 'bar.GET._INVALID_STATUS_.json')
176
+ equal(s.brokersByMethod.GET['/foo._INVALID_METHOD_.202.json'].file, 'foo._INVALID_METHOD_.202.json')
177
+ equal(s.brokersByMethod.GET['/missing-method-and-status.json'].file, 'missing-method-and-status.json')
184
178
 
185
179
  await fx0.unlink()
186
180
  await fx1.unlink()
@@ -373,7 +367,7 @@ describe('Proxy Fallback', () => {
373
367
  const CUSTOM_COOKIES = ['cookieX=x', 'cookieY=y']
374
368
  const BODY_PAYLOAD = { a: 'b' }
375
369
  const expectedBody = JSON.stringify(BODY_PAYLOAD, null, ' ') // config.formatCollectedJSON=true
376
-
370
+
377
371
  before(async () => {
378
372
  fallbackServer = createServer(async (req, response) => {
379
373
  response.writeHead(423, {
@@ -499,20 +493,20 @@ describe('Proxy Fallback', () => {
499
493
  equal((await r.json()).proxied, false)
500
494
  })
501
495
 
502
- test('unsets auto500', async () => {
496
+ test('unsets autoStatus', async () => {
503
497
  const fx = new Fixture('unset-500-on-proxy.GET.200.txt')
504
498
  await fx.sync()
505
499
  await api.setProxyFallback('https://example.test')
506
500
 
507
- const r0 = await api.toggle500(fx.method, fx.urlMask)
501
+ const r0 = await api.toggleStatus(500, fx.method, fx.urlMask)
508
502
  const b0 = await r0.json()
509
503
  equal(b0.proxied, false)
510
- equal(b0.auto500, true)
504
+ equal(b0.autoStatus, 500)
511
505
 
512
506
  const r1 = await api.setRouteIsProxied(fx.method, fx.urlMask, true)
513
507
  const b1 = await r1.json()
514
508
  equal(b1.proxied, true)
515
- equal(b1.auto500, false)
509
+ equal(b1.autoStatus, 0)
516
510
 
517
511
  await fx.unlink()
518
512
  await api.setProxyFallback('')
@@ -555,14 +549,6 @@ describe('404', () => {
555
549
  await fx.unlink()
556
550
  })
557
551
 
558
- test('404s ignored static files', async () => {
559
- const fx = new FixtureStatic('static-ignored.js~')
560
- await fx.write()
561
- await api.reset()
562
- const r = await fx.request()
563
- equal(r.status, 404)
564
- await fx.unlink()
565
- })
566
552
  })
567
553
 
568
554
 
@@ -662,7 +648,7 @@ describe('Static Files', () => {
662
648
  await fxsIndex.write()
663
649
  await fxsAsset.write()
664
650
  await api.reset()
665
- }) // the last test deletes them
651
+ })
666
652
 
667
653
  describe('Static File Serving', () => {
668
654
  test('Defaults to index.html', async () => {
@@ -680,64 +666,10 @@ describe('Static Files', () => {
680
666
  })
681
667
  })
682
668
 
683
- test('Static File List', async () => {
684
- const { staticBrokers } = await fetchState()
685
- deepEqual(Object.keys(staticBrokers), [
686
- fxsAsset.urlMask,
687
- fxsIndex.urlMask
688
- ])
689
- })
690
-
691
- describe('Set Static Route is Delayed', () => {
692
- test('422 for non-existing route', async () => {
693
- const r = await api.setStaticRouteIsDelayed('/non-existing', true)
694
- equal(r.status, 422)
695
- equal(await r.text(), `Static route does not exist: /non-existing`)
696
- })
697
-
698
- test('422 for invalid delayed value', async () => {
699
- const r = await api.setStaticRouteIsDelayed(fxsIndex.urlMask, 'not-a-boolean')
700
- equal(await r.text(), 'Expected boolean for "delayed"')
701
- })
702
-
703
- test('200', async () => {
704
- await api.setStaticRouteIsDelayed(fxsIndex.urlMask, true)
705
- const { staticBrokers } = await fetchState()
706
- equal(staticBrokers[fxsIndex.urlMask].delayed, true)
707
- })
708
- })
709
-
710
- describe('Set Static Route Status Code', () => {
711
- test('422 for non-existing route', async () => {
712
- const r = await api.setStaticRouteStatus('/non-existing', 200)
713
- equal(r.status, 422)
714
- equal(await r.text(), `Static route does not exist: /non-existing`)
715
- })
716
-
717
- test('422 for invalid delayed value', async () => {
718
- const r = await api.setStaticRouteStatus(fxsIndex.urlMask, 'not-200-or-404')
719
- equal(r.status, 422)
720
- equal(await r.text(), 'Expected 200 or 404 status code')
721
- })
722
-
723
- test('sets 404 and 200', async () => {
724
- await api.setStaticRouteStatus(fxsIndex.urlMask, 404)
725
- const r0 = await fxsIndex.request()
726
- equal(r0.status, 404)
727
-
728
- await api.setStaticRouteStatus(fxsIndex.urlMask, 200)
729
- const r1 = await fxsIndex.request()
730
- equal(r1.status, 200)
731
- })
732
-
733
- test('404s on a registered route but its file has been deleted', async () => {
734
- // Possible: (1) due to watcher delay. (2) or, when not-watching and deleting.
735
- const fx = new FixtureStatic('to-be-deleted.js')
736
- await fx.sync()
737
- await fx.unlink()
738
- const r = await fx.request()
739
- equal(r.status, 404)
740
- })
669
+ test('are part of the normal mocks list', async () => {
670
+ const s = await fetchState()
671
+ equal(s.brokersByMethod.GET[fxsAsset.urlMask].file, fxsAsset.file)
672
+ equal(s.brokersByMethod.GET[fxsIndex.urlMask].file, fxsIndex.file)
741
673
  })
742
674
 
743
675
  describe('Static Partial Content', () => {
@@ -761,27 +693,27 @@ describe('Static Files', () => {
761
693
  await fxsIndex.unlink()
762
694
  await fxsAsset.unlink()
763
695
  await api.reset()
764
- const { staticBrokers } = await fetchState()
765
- equal(staticBrokers[fxsIndex.urlMask], undefined)
766
- equal(staticBrokers[fxsAsset.urlMask], undefined)
696
+ const s = await fetchState()
697
+ equal(s.brokersByMethod.GET?.[fxsIndex.urlMask], undefined)
698
+ equal(s.brokersByMethod.GET?.[fxsAsset.urlMask], undefined)
767
699
  })
768
700
  })
769
701
 
770
702
 
771
- describe('500', () => {
703
+ describe('Auto Status', () => {
772
704
  test('toggling ON 500 on a route without 500 auto-generates one', async () => {
773
705
  const fx = new Fixture('toggling-500-without-500.GET.200.json')
774
706
  await fx.sync()
775
707
  equal((await fx.request()).status, fx.status)
776
708
 
777
- const bp0 = await api.toggle500(fx.method, fx.urlMask)
709
+ const bp0 = await api.toggleStatus(500, fx.method, fx.urlMask)
778
710
  const b0 = await bp0.json()
779
- equal(b0.auto500, true)
711
+ equal(b0.autoStatus, 500)
780
712
  equal(b0.status, 500)
781
713
  equal((await fx.request()).status, 500)
782
714
 
783
- const r1 = await api.toggle500(fx.method, fx.urlMask)
784
- equal((await r1.json()).auto500, false)
715
+ const r1 = await api.toggleStatus(500, fx.method, fx.urlMask)
716
+ equal((await r1.json()).autoStatus, 0)
785
717
  equal((await fx.request()).status, fx.status)
786
718
  })
787
719
 
@@ -792,15 +724,15 @@ describe('500', () => {
792
724
  await fx500.write()
793
725
  await api.reset()
794
726
 
795
- const bp0 = await api.toggle500(fx200.method, fx200.urlMask)
727
+ const bp0 = await api.toggleStatus(500, fx200.method, fx200.urlMask)
796
728
  const b0 = await bp0.json()
797
- equal(b0.auto500, false)
729
+ equal(b0.autoStatus, 0)
798
730
  equal(b0.status, 500)
799
731
  equal(await (await fx200.request()).text(), fx500.body)
800
732
 
801
- const bp1 = await api.toggle500(fx200.method, fx200.urlMask)
733
+ const bp1 = await api.toggleStatus(500, fx200.method, fx200.urlMask)
802
734
  const b1 = await bp1.json()
803
- equal(b0.auto500, false)
735
+ equal(b0.autoStatus, 0)
804
736
  equal(b1.status, 200)
805
737
  equal(await (await fx200.request()).text(), fx200.body)
806
738
 
@@ -813,11 +745,29 @@ describe('500', () => {
813
745
  await fx.sync()
814
746
  await api.setProxyFallback('https://example.test')
815
747
  await api.setRouteIsProxied(fx.method, fx.urlMask, true)
816
- await api.toggle500(fx.method, fx.urlMask)
748
+ await api.toggleStatus(500, fx.method, fx.urlMask)
817
749
  equal((await fx.fetchBroker()).proxied, false)
818
750
  await fx.unlink()
819
751
  await api.setProxyFallback('')
820
752
  })
753
+
754
+ test('toggling ON 404 for static routes', async () => {
755
+ const fx = new FixtureStatic('static-404.txt')
756
+ await fx.sync()
757
+ equal((await fx.request()).status, 200)
758
+
759
+ const bp0 = await api.toggleStatus(404, fx.method, fx.urlMask)
760
+ const b0 = await bp0.json()
761
+ equal(b0.autoStatus, 404)
762
+ equal(b0.status, 404)
763
+ equal((await fx.request()).status, 404)
764
+
765
+ const r1 = await api.toggleStatus(404, fx.method, fx.urlMask)
766
+ equal((await r1.json()).autoStatus, 0)
767
+ equal((await fx.request()).status, 200)
768
+
769
+ await fx.unlink()
770
+ })
821
771
  })
822
772
 
823
773
 
@@ -1110,16 +1060,16 @@ describe('Registering Mocks', () => {
1110
1060
  equal(b, undefined)
1111
1061
  })
1112
1062
 
1113
- test('registering a 500 unsets auto500', async () => {
1063
+ test('registering a 500 unsets autoStatus', async () => {
1114
1064
  const fx200 = new Fixture('reg-error.GET.200.txt')
1115
1065
  const fx500 = new Fixture('reg-error.GET.500.txt')
1116
1066
  await fx200.register()
1117
- await api.toggle500(fx200.method, fx200.urlMask)
1067
+ await api.toggleStatus(500, fx200.method, fx200.urlMask)
1118
1068
  const b0 = await fx200.fetchBroker()
1119
- equal(b0.auto500, true)
1069
+ equal(b0.autoStatus, 500)
1120
1070
  await fx500.register()
1121
1071
  const b1 = await fx200.fetchBroker()
1122
- equal(b1.auto500, false)
1072
+ equal(b1.autoStatus, 0)
1123
1073
  deepEqual(b1.mocks, [
1124
1074
  fx200.file,
1125
1075
  fx500.file
@@ -1162,72 +1112,6 @@ describe('Registering Mocks', () => {
1162
1112
  })
1163
1113
 
1164
1114
 
1165
- describe('Registering Static Mocks', () => {
1166
- test('when watcher is off, newly added mocks do not get registered', async () => {
1167
- await api.setWatchMocks(false)
1168
- const fx = new FixtureStatic('non-auto-registered-file.txt')
1169
- await fx.write()
1170
- await sleep()
1171
- const { staticBrokers } = await fetchState()
1172
- equal(staticBrokers['/' + fx.file], undefined)
1173
- await fx.unlink()
1174
- })
1175
-
1176
- const fx = new FixtureStatic('static-register.txt', 'static-body')
1177
- test('registers static', async () => {
1178
- await api.setWatchMocks(true)
1179
- await fx.register()
1180
- const { staticBrokers } = await fetchState()
1181
- deepEqual(staticBrokers, {
1182
- ['/' + fx.file]: {
1183
- route: '/' + fx.file,
1184
- status: 200,
1185
- delayed: false
1186
- }
1187
- })
1188
- const response = await fx.request()
1189
- equal(response.status, 200)
1190
- equal(await response.text(), fx.body)
1191
- })
1192
-
1193
- test('unregisters static', async () => {
1194
- await fx.unregister()
1195
- const { staticBrokers } = await fetchState()
1196
- deepEqual(staticBrokers, {})
1197
- })
1198
-
1199
- describe('getSyncVersion', () => {
1200
- const fx0 = new FixtureStatic('reg0/static0.txt')
1201
- let version
1202
- before(async () => {
1203
- await makeDirInStaticMocks('reg0')
1204
- await fx0.sync()
1205
- version = await resolveOnNextSyncVersion(-1)
1206
- })
1207
-
1208
- const fx = new FixtureStatic('static1.txt')
1209
- test('responds when a file is added', async () => {
1210
- const prom = resolveOnNextSyncVersion(version)
1211
- await fx.write()
1212
- equal(await prom, version + 1)
1213
- })
1214
-
1215
- test('responds when a file is deleted', async () => {
1216
- const prom = resolveOnNextSyncVersion(version + 1)
1217
- await fx.unlink()
1218
- equal(await prom, version + 2)
1219
- })
1220
-
1221
- test('responds when dir is renamed', async () => {
1222
- const p0 = resolveOnNextSyncVersion(version + 2)
1223
- await renameInStaticMocksDir('reg0', 'reg1')
1224
- equal(await p0, version + 3)
1225
-
1226
- const s = await fetchState()
1227
- equal(s.staticBrokers['/reg1/static0.txt'].route, '/reg1/static0.txt')
1228
- })
1229
- })
1230
- })
1231
1115
 
1232
1116
 
1233
1117
  function sleep(ms = 100) {
@@ -5,12 +5,10 @@ import { EventEmitter } from 'node:events'
5
5
  import { config } from './config.js'
6
6
  import { isFile, isDirectory } from './utils/fs.js'
7
7
 
8
- import * as staticCollection from './staticCollection.js'
9
8
  import * as mockBrokerCollection from './mockBrokersCollection.js'
10
9
 
11
10
 
12
11
  let mocksWatcher = null
13
- let staticWatcher = null
14
12
 
15
13
 
16
14
  /**
@@ -67,33 +65,6 @@ export function watchMocksDir() {
67
65
  }
68
66
 
69
67
 
70
- export function watchStaticDir() {
71
- const dir = config.staticDir
72
- if (!dir)
73
- return
74
-
75
- staticWatcher = staticWatcher || watch(dir, { recursive: true, persistent: false }, (_, file) => {
76
- if (!file)
77
- return
78
-
79
- if (isDirectory(join(dir, file))) {
80
- staticCollection.init()
81
- uiSyncVersion.increment()
82
- }
83
- else if (!isFile(join(dir, file))) { // file deleted
84
- staticCollection.unregisterMock(file)
85
- uiSyncVersion.increment()
86
- }
87
- else if (staticCollection.registerMock(file))
88
- uiSyncVersion.increment()
89
- else {
90
- // ignore file edits
91
- }
92
- })
93
- }
94
-
95
-
96
-
97
68
  /** Realtime notify ARR Events */
98
69
  export function sseClientSyncVersion(req, response) {
99
70
  response.writeHead(200, {
@@ -125,12 +96,9 @@ export function sseClientSyncVersion(req, response) {
125
96
 
126
97
  export function startWatchers() {
127
98
  watchMocksDir()
128
- watchStaticDir()
129
99
  }
130
100
 
131
101
  export function stopWatchers() {
132
102
  mocksWatcher?.close()
133
- staticWatcher?.close()
134
103
  mocksWatcher = null
135
- staticWatcher = null
136
104
  }
package/src/server/cli.js CHANGED
@@ -11,25 +11,25 @@ import pkgJSON from '../../package.json' with { type: 'json' }
11
11
 
12
12
  process.on('unhandledRejection', error => { throw error })
13
13
 
14
- let args
14
+ let args, positionals
15
15
  try {
16
- args = parseArgs({
16
+ const result = parseArgs({
17
17
  options: {
18
18
  config: { short: 'c', type: 'string' },
19
19
 
20
20
  port: { short: 'p', type: 'string' },
21
21
  host: { short: 'H', type: 'string' },
22
22
 
23
- 'mocks-dir': { short: 'm', type: 'string' },
24
- 'static-dir': { short: 's', type: 'string' },
25
-
26
23
  quiet: { short: 'q', type: 'boolean' },
27
24
  'no-open': { short: 'n', type: 'boolean' },
28
25
 
29
26
  help: { short: 'h', type: 'boolean' },
30
27
  version: { short: 'v', type: 'boolean' }
31
- }
32
- }).values
28
+ },
29
+ allowPositionals: true
30
+ })
31
+ args = result.values
32
+ positionals = result.positionals
33
33
  }
34
34
  catch (error) {
35
35
  console.error(error.message)
@@ -45,14 +45,11 @@ if (args.version)
45
45
 
46
46
  else if (args.help)
47
47
  console.log(`
48
- Usage: mockaton [options]
48
+ Usage: mockaton [mocks-dir] [options]
49
49
 
50
50
  Options:
51
51
  -c, --config <file> (default: ./mockaton.config.js)
52
52
 
53
- -m, --mocks-dir <dir> (default: ./mockaton-mocks/)
54
- -s, --static-dir <dir> (default: ./mockaton-static-mocks/)
55
-
56
53
  -H, --host <host> (default: 127.0.0.1)
57
54
  -p, --port <port> (default: 0) which means auto-assigned
58
55
 
@@ -80,8 +77,7 @@ else {
80
77
  if (args.host) opts.host = args.host
81
78
  if (args.port) opts.port = Number.isNaN(Number(args.port)) ? args.port : Number(args.port)
82
79
 
83
- if (args['mocks-dir']) opts.mocksDir = args['mocks-dir']
84
- if (args['static-dir']) opts.staticDir = args['static-dir']
80
+ if (positionals[0]) opts.mocksDir = positionals[0]
85
81
 
86
82
  if (args.quiet) opts.logLevel = 'quiet'
87
83
  if (args['no-open']) opts.onReady = () => {}