mockaton 10.4.1 → 10.5.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 CHANGED
@@ -431,8 +431,12 @@ config.plugins = [
431
431
  // IOW, your plugins array overwrites the default list. This way you can remove it.
432
432
  [/\.(js|ts)$/, jsToJsonPlugin],
433
433
 
434
+
434
435
  [/\.yml$/, yamlToJsonPlugin],
435
- [/foo\.GET\.200\.txt$/, capitalizePlugin], // e.g. GET /api/foo would be capitalized
436
+
437
+
438
+ // e.g. GET /api/foo would be capitalized
439
+ [/foo\.GET\.200\.txt$/, capitalizePlugin]
436
440
  ]
437
441
 
438
442
  function yamlToJsonPlugin(filePath) {
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "mockaton",
3
3
  "description": "HTTP Mock Server",
4
4
  "type": "module",
5
- "version": "10.4.1",
5
+ "version": "10.5.0",
6
6
  "main": "index.js",
7
7
  "types": "index.d.ts",
8
8
  "license": "MIT",
package/src/Dashboard.css CHANGED
@@ -385,7 +385,7 @@ table {
385
385
  border-top: 20px solid transparent;
386
386
  text-align: left;
387
387
  }
388
-
388
+
389
389
  > tr:first-child > th {
390
390
  border-top: 0;
391
391
  }
@@ -633,7 +633,7 @@ table {
633
633
  height: 2px;
634
634
  background: var(--colorComboBoxHeaderBackground);
635
635
 
636
- div {
636
+ > div {
637
637
  position: absolute;
638
638
  top: 0;
639
639
  left: 0;
package/src/Dashboard.js CHANGED
@@ -3,38 +3,6 @@ import { parseFilename, extractComments } from './Filename.js'
3
3
  import { Commander } from './ApiCommander.js'
4
4
 
5
5
 
6
- const Strings = {
7
- auto500: 'Auto500',
8
- bulk_select: 'Bulk Select',
9
- bulk_select_disabled_title: 'No mock files have comments, which are anything within parentheses on the filename.',
10
- click_link_to_preview: 'Click a link to preview it',
11
- cookie: 'Cookie',
12
- cookie_disabled_title: 'No cookies specified in config.cookies',
13
- delay: 'Delay',
14
- delay_ms: 'Delay (ms)',
15
- empty_response_body: '/* Empty Response Body */',
16
- fallback_server: 'Fallback',
17
- fallback_server_error: '⛔ Fallback Backend Error',
18
- fallback_server_placeholder: 'Type backend address',
19
- fetching: 'Fetching…',
20
- got: 'Got',
21
- group_by_method: 'Group by Method',
22
- internal_server_error: 'Internal Server Error',
23
- mock_selector: 'Mock Selector',
24
- no_mocks_found: 'No mocks found',
25
- none: 'None',
26
- not_found: 'Not Found',
27
- pick_comment: 'Pick Comment…',
28
- preview: 'Preview',
29
- proxied: 'Proxied',
30
- proxy_toggler: 'Proxy Toggler',
31
- reset: 'Reset',
32
- save_proxied: 'Save Mocks',
33
- settings: 'Settings',
34
- static_get: 'Static GET',
35
- title: 'Mockaton'
36
- }
37
-
38
6
  const CSS = {
39
7
  BulkSelector: null,
40
8
  CookieSelector: null,
@@ -70,26 +38,19 @@ const CSS = {
70
38
  status4xx: null,
71
39
 
72
40
  json: null,
73
- syntaxKey: null,
74
- syntaxStr: null,
75
- syntaxVal: null,
76
-
77
41
  syntaxAttr: null,
78
42
  syntaxAttrVal: null,
43
+ syntaxKey: null,
44
+ syntaxPunc: null,
45
+ syntaxStr: null,
79
46
  syntaxTag: null,
80
- syntaxPunc: null
47
+ syntaxVal: null
81
48
  }
82
49
  for (const k of Object.keys(CSS))
83
50
  CSS[k] = k
84
51
 
85
52
 
86
- /** @type {State & {
87
- * canProxy: boolean
88
- * groupByMethod: boolean
89
- * toggleGroupByMethod: () => void
90
- * leftSideWidth?: number
91
- * }} */
92
- const state = {
53
+ const state = /** @type {State} */ {
93
54
  brokersByMethod: {},
94
55
  staticBrokers: {},
95
56
  cookies: [],
@@ -99,19 +60,21 @@ const state = {
99
60
  collectProxied: false,
100
61
  proxyFallback: '',
101
62
  get canProxy() {
102
- return Boolean(this.proxyFallback)
63
+ return Boolean(state.proxyFallback)
103
64
  },
104
65
 
105
- groupByMethod: localStorage.getItem('groupByMethod') !== 'false',
66
+ groupByMethod: initPreference('groupByMethod'),
106
67
  toggleGroupByMethod() {
107
- this.groupByMethod = !this.groupByMethod
108
- localStorage.setItem('groupByMethod', String(this.groupByMethod))
68
+ state.groupByMethod = !state.groupByMethod
69
+ togglePreference('groupByMethod', state.groupByMethod)
70
+ updateState()
109
71
  },
110
72
 
111
73
  leftSideWidth: undefined
112
74
  }
113
75
 
114
- const mockaton = new Commander(window.location.origin)
76
+
77
+ const mockaton = new Commander(location.origin)
115
78
  updateState()
116
79
  initLongPoll()
117
80
 
@@ -124,13 +87,15 @@ async function updateState() {
124
87
  document.body.replaceChildren(...App())
125
88
  }
126
89
  catch (error) {
127
- onError(parseError(error))
90
+ onError(error)
128
91
  }
129
92
  }
130
93
 
131
94
  const r = createElement
132
95
  const s = createSvgElement
133
96
 
97
+ const t = translation => translation[0]
98
+
134
99
  const leftSideRef = useRef()
135
100
 
136
101
  function App() {
@@ -157,7 +122,7 @@ function Header() {
157
122
  return (
158
123
  r('header', null,
159
124
  r('img', {
160
- alt: Strings.title,
125
+ alt: t`Mockaton`,
161
126
  src: 'mockaton/Logo.svg',
162
127
  width: 160
163
128
  }),
@@ -171,47 +136,38 @@ function Header() {
171
136
  }
172
137
 
173
138
  function SettingsMenu() {
174
- const id = '_SettingsMenu_'
139
+ const { groupByMethod, toggleGroupByMethod } = state
140
+
141
+ const id = '_settings_menu_'
142
+ return (
143
+ r('button', {
144
+ title: t`Settings`,
145
+ popovertarget: id,
146
+ className: CSS.MenuTrigger
147
+ },
148
+ SettingsIcon(),
175
149
 
176
- function MenuContent() {
177
- return (
178
150
  r('menu', {
179
151
  id,
152
+ deferred: true,
180
153
  popover: '',
181
- className: CSS.SettingsMenu,
182
- onToggle(event) {
183
- if (event.newState === 'closed')
184
- this.parentNode.removeChild(this)
185
- }
154
+ className: CSS.SettingsMenu
186
155
  },
156
+
187
157
  r('label', className(CSS.GroupByMethod),
188
158
  r('input', {
189
159
  type: 'checkbox',
190
- checked: state.groupByMethod,
191
- onChange() {
192
- state.toggleGroupByMethod()
193
- updateState()
194
- }
160
+ checked: groupByMethod,
161
+ autofocus: true,
162
+ onChange: toggleGroupByMethod
195
163
  }),
196
- r('span', null, Strings.group_by_method)),
164
+ r('span', null, t`Group by Method`)),
197
165
 
198
166
  r('a', {
199
167
  href: 'https://github.com/ericfortis/mockaton',
200
168
  target: '_blank',
201
169
  rel: 'noopener noreferrer'
202
- }, 'Documentation')))
203
- }
204
-
205
- return (
206
- r('button', {
207
- title: Strings.settings,
208
- onClick() {
209
- if (!this.querySelector('menu'))
210
- this.appendChild(MenuContent())
211
- },
212
- className: CSS.MenuTrigger,
213
- popovertarget: id
214
- }, SettingsIcon()))
170
+ }, t`Documentation`))))
215
171
  }
216
172
 
217
173
  function CookieSelector() {
@@ -222,14 +178,14 @@ function CookieSelector() {
222
178
  .catch(onError)
223
179
  }
224
180
  const disabled = cookies.length <= 1
225
- const list = cookies.length ? cookies : [[Strings.none, true]]
181
+ const list = cookies.length ? cookies : [[t`None`, true]]
226
182
  return (
227
183
  r('label', className(CSS.Field, CSS.CookieSelector),
228
- r('span', null, Strings.cookie),
184
+ r('span', null, t`Cookie`),
229
185
  r('select', {
230
186
  autocomplete: 'off',
231
187
  disabled,
232
- title: disabled ? Strings.cookie_disabled_title : '',
188
+ title: disabled ? t`No cookies specified in config.cookies` : '',
233
189
  onChange
234
190
  }, list.map(([value, selected]) =>
235
191
  r('option', { value, selected }, value)))))
@@ -239,7 +195,7 @@ function BulkSelector() {
239
195
  const { comments } = state
240
196
  // UX wise this should be a menu instead of this `select`.
241
197
  // But this way is easier to implement, with a few hacks.
242
- const firstOption = Strings.pick_comment
198
+ const firstOption = t`Pick Comment…`
243
199
  function onChange() {
244
200
  const value = this.value
245
201
  this.value = firstOption // Hack
@@ -252,12 +208,12 @@ function BulkSelector() {
252
208
  const disabled = !comments.length
253
209
  return (
254
210
  r('label', className(CSS.Field),
255
- r('span', null, Strings.bulk_select),
211
+ r('span', null, t`Bulk Select`),
256
212
  r('select', {
257
213
  className: CSS.BulkSelector,
258
214
  autocomplete: 'off',
259
215
  disabled,
260
- title: disabled ? Strings.bulk_select_disabled_title : '',
216
+ title: disabled ? t`No mock files have comments which are anything within parentheses on the filename.` : '',
261
217
  onChange
262
218
  },
263
219
  r('option', { value: firstOption }, firstOption),
@@ -265,7 +221,7 @@ function BulkSelector() {
265
221
  comments.map(value =>
266
222
  r('option', { value }, value)),
267
223
  r('hr'),
268
- r('option', { value: AUTOGENERATED_500_COMMENT }, Strings.auto500)
224
+ r('option', { value: AUTOGENERATED_500_COMMENT }, t`Auto500`)
269
225
  )))
270
226
  }
271
227
 
@@ -285,7 +241,7 @@ function GlobalDelayField() {
285
241
  }
286
242
  return (
287
243
  r('label', className(CSS.Field, CSS.GlobalDelayField),
288
- r('span', null, Strings.delay_ms),
244
+ r('span', null, t`Delay (ms)`),
289
245
  r('input', {
290
246
  type: 'number',
291
247
  min: 0,
@@ -315,11 +271,11 @@ function ProxyFallbackField() {
315
271
  return (
316
272
  r('div', className(CSS.Field, CSS.FallbackBackend),
317
273
  r('label', null,
318
- r('span', null, Strings.fallback_server),
274
+ r('span', null, t`Fallback`),
319
275
  r('input', {
320
276
  type: 'url',
321
277
  autocomplete: 'none',
322
- placeholder: Strings.fallback_server_placeholder,
278
+ placeholder: t`Type backend address`,
323
279
  value: proxyFallback,
324
280
  onChange
325
281
  })),
@@ -341,7 +297,7 @@ function SaveProxiedCheckbox() {
341
297
  checked: collectProxied,
342
298
  onChange
343
299
  }),
344
- r('span', null, Strings.save_proxied)))
300
+ r('span', null, t`Save Mocks`)))
345
301
  }
346
302
 
347
303
  function ResetButton() {
@@ -356,7 +312,7 @@ function ResetButton() {
356
312
  r('button', {
357
313
  className: CSS.ResetButton,
358
314
  onClick
359
- }, Strings.reset))
315
+ }, t`Reset`))
360
316
  }
361
317
 
362
318
 
@@ -369,7 +325,7 @@ function MockList() {
369
325
  if (!Object.keys(brokersByMethod).length)
370
326
  return (
371
327
  r('div', className(CSS.empty),
372
- Strings.no_mocks_found))
328
+ t`No mocks found`))
373
329
 
374
330
  if (groupByMethod)
375
331
  return Object.keys(brokersByMethod).map((method) => Fragment(
@@ -437,6 +393,8 @@ function PreviewLink(method, urlMask, urlMaskDittoed) {
437
393
  : tail))
438
394
  }
439
395
 
396
+ const STR_PROXIED = t`Proxied`
397
+
440
398
  /** @param {ClientMockBroker} broker */
441
399
  function MockSelector(broker) {
442
400
  function onChange() {
@@ -449,25 +407,25 @@ function MockSelector(broker) {
449
407
  }
450
408
 
451
409
  let selected = broker.currentMock.file
452
- const { status, urlMask } = parseFilename(selected)
410
+ const { status } = parseFilename(selected)
453
411
  const files = broker.mocks.filter(item =>
454
412
  status === 500 ||
455
413
  !item.includes(AUTOGENERATED_500_COMMENT))
456
414
  if (!selected) {
457
- selected = Strings.proxied
415
+ selected = STR_PROXIED
458
416
  files.push(selected)
459
417
  }
460
418
 
461
419
  function nameFor(file) {
462
- if (file === Strings.proxied)
463
- return Strings.proxied
464
- const { status, ext, method } = parseFilename(file)
420
+ if (file === STR_PROXIED)
421
+ return STR_PROXIED
422
+ const { status, ext } = parseFilename(file)
465
423
  const comments = extractComments(file)
466
424
  const isAutogen500 = comments.includes(AUTOGENERATED_500_COMMENT)
467
425
  return [
468
426
  isAutogen500 ? '' : status,
469
427
  ext === 'empty' || ext === 'unknown' ? '' : ext,
470
- isAutogen500 ? Strings.auto500 : comments.join(' ')
428
+ isAutogen500 ? t`Auto500` : comments.join(' ')
471
429
  ].filter(Boolean).join(' ')
472
430
  }
473
431
 
@@ -475,7 +433,7 @@ function MockSelector(broker) {
475
433
  r('select', {
476
434
  onChange,
477
435
  autocomplete: 'off',
478
- 'aria-label': Strings.mock_selector,
436
+ 'aria-label': t`Mock Selector`,
479
437
  disabled: files.length <= 1,
480
438
  ...className(
481
439
  CSS.MockSelector,
@@ -516,7 +474,7 @@ function InternalServerErrorToggler(broker) {
516
474
  return (
517
475
  r('label', {
518
476
  className: CSS.InternalServerErrorToggler,
519
- title: Strings.internal_server_error
477
+ title: t`Internal Server Error`
520
478
  },
521
479
  r('input', {
522
480
  type: 'checkbox',
@@ -524,7 +482,7 @@ function InternalServerErrorToggler(broker) {
524
482
  checked: parseFilename(broker.currentMock.file).status === 500,
525
483
  onChange
526
484
  }),
527
- r('span', null, '500')))
485
+ r('span', null, t`500`)))
528
486
  }
529
487
 
530
488
  /** @param {ClientMockBroker} broker */
@@ -540,7 +498,7 @@ function ProxyToggler(broker) {
540
498
  return (
541
499
  r('label', {
542
500
  className: CSS.ProxyToggler,
543
- title: Strings.proxy_toggler
501
+ title: t`Proxy Toggler`
544
502
  },
545
503
  r('input', {
546
504
  type: 'checkbox',
@@ -565,10 +523,10 @@ function StaticFilesList() {
565
523
  Fragment(
566
524
  r('tr', null,
567
525
  r('th', { colspan: (2 + Number(!groupByMethod)) + Number(canProxy) }),
568
- r('th', null, Strings.static_get)),
526
+ r('th', null, t`Static GET`)),
569
527
  Object.values(staticBrokers).map((broker, i) =>
570
528
  r('tr', null,
571
- canProxy && r('td', null, ProxyStaticToggler()),
529
+ canProxy && r('td'),
572
530
  r('td', null, DelayStaticRouteToggler(broker)),
573
531
  r('td', null, NotFoundToggler(broker)),
574
532
  !groupByMethod && r('td', className(CSS.Method), 'GET'),
@@ -603,31 +561,14 @@ function NotFoundToggler(broker) {
603
561
  return (
604
562
  r('label', {
605
563
  className: CSS.NotFoundToggler,
606
- title: Strings.not_found
564
+ title: t`Not Found`
607
565
  },
608
566
  r('input', {
609
567
  type: 'checkbox',
610
568
  checked: broker.status === 404,
611
569
  onChange
612
570
  }),
613
- r('span', null, '404')))
614
- }
615
-
616
- function ProxyStaticToggler() { // TODO
617
- function onChange() {
618
- }
619
- return (
620
- r('label', {
621
- style: { visibility: 'hidden' },
622
- className: CSS.ProxyToggler,
623
- title: Strings.proxy_toggler
624
- },
625
- r('input', {
626
- type: 'checkbox',
627
- disabled: true,
628
- onChange
629
- }),
630
- CloudIcon()))
571
+ r('span', null, t`404`)))
631
572
  }
632
573
 
633
574
 
@@ -650,7 +591,7 @@ function ClickDragToggler({ checked, commit }) {
650
591
  return (
651
592
  r('label', {
652
593
  className: CSS.DelayToggler,
653
- title: Strings.delay
594
+ title: t`Delay`
654
595
  },
655
596
  r('input', {
656
597
  type: 'checkbox',
@@ -708,20 +649,15 @@ const payloadViewerRef = useRef()
708
649
  function PayloadViewer() {
709
650
  return (
710
651
  r('div', className(CSS.PayloadViewer),
711
- r('h2', { ref: payloadViewerTitleRef }, Strings.preview),
652
+ r('h2', { ref: payloadViewerTitleRef }, t`Preview`),
712
653
  r('pre', null,
713
- r('code', { ref: payloadViewerRef }, Strings.click_link_to_preview))))
654
+ r('code', { ref: payloadViewerRef }, t`Click a link to preview it`))))
714
655
  }
715
656
 
716
657
  function PayloadViewerProgressBar() {
717
658
  return (
718
659
  r('div', className(CSS.ProgressBar),
719
- r('div', {
720
- style: {
721
- animationDelay: 80 + 'ms',
722
- animationDuration: -80 + state.delay + 'ms'
723
- }
724
- })))
660
+ r('div', { style: { animationDuration: state.delay + 'ms' } })))
725
661
  }
726
662
 
727
663
  function PayloadViewerTitle({ file, statusText }) {
@@ -740,8 +676,8 @@ function PayloadViewerTitleWhenProxied({ mime, status, statusText, gatewayIsBad
740
676
  return (
741
677
  r('span', null,
742
678
  gatewayIsBad
743
- ? r('span', className(CSS.red), Strings.fallback_server_error + ' ')
744
- : r('span', null, Strings.got + ' '),
679
+ ? r('span', className(CSS.red), t`⛔ Fallback Backend Error` + ' ')
680
+ : r('span', null, t`Got` + ' '),
745
681
  r('abbr', { title: statusText }, status),
746
682
  ' ' + mime))
747
683
  }
@@ -750,14 +686,17 @@ async function previewMock(method, urlMask, href) {
750
686
  previewMock.controller?.abort()
751
687
  previewMock.controller = new AbortController
752
688
 
753
- payloadViewerTitleRef.current.replaceChildren(r('span', null, Strings.fetching))
754
- payloadViewerRef.current.replaceChildren(PayloadViewerProgressBar())
689
+ const spinnerTimer = setTimeout(() => {
690
+ payloadViewerTitleRef.current.replaceChildren(t`Fetching…`)
691
+ payloadViewerRef.current.replaceChildren(PayloadViewerProgressBar())
692
+ }, 80)
755
693
 
756
694
  try {
757
695
  const response = await fetch(href, {
758
696
  method,
759
697
  signal: previewMock.controller.signal
760
698
  })
699
+ clearTimeout(spinnerTimer)
761
700
  await updatePayloadViewer(method, urlMask, response)
762
701
  }
763
702
  catch (err) {
@@ -766,11 +705,12 @@ async function previewMock(method, urlMask, href) {
766
705
  }
767
706
  }
768
707
 
708
+
769
709
  async function updatePayloadViewer(method, urlMask, response) {
770
710
  const mime = response.headers.get('content-type') || ''
771
711
 
772
712
  const file = mockSelectorFor(method, urlMask).value
773
- if (file === Strings.proxied)
713
+ if (file === STR_PROXIED)
774
714
  payloadViewerTitleRef.current.replaceChildren(PayloadViewerTitleWhenProxied({
775
715
  status: response.status,
776
716
  statusText: response.statusText,
@@ -790,7 +730,7 @@ async function updatePayloadViewer(method, urlMask, response) {
790
730
  }))
791
731
  }
792
732
  else {
793
- const body = await response.text() || Strings.empty_response_body
733
+ const body = await response.text() || t`/* Empty Response Body */`
794
734
  if (mime === 'application/json')
795
735
  payloadViewerRef.current.replaceChildren(r('span', className(CSS.json), syntaxJSON(body)))
796
736
  else if (isXML(mime))
@@ -834,9 +774,9 @@ function onError(error) {
834
774
  if (error?.name === 'AbortError')
835
775
  return
836
776
  if (error?.message === 'Failed to fetch')
837
- showErrorToast('Looks like the Mockaton server is not running')
777
+ showErrorToast(t`Looks like the Mockaton server is not running`)
838
778
  else
839
- showErrorToast(error || 'Unexpected Error')
779
+ showErrorToast(error || t`Unexpected Error`)
840
780
  console.error(error)
841
781
  }
842
782
 
@@ -921,6 +861,14 @@ function className(...args) {
921
861
 
922
862
 
923
863
  function createElement(tag, props, ...children) {
864
+ if (props?.deferred) {
865
+ delete props.deferred
866
+ const placeholder = document.createComment('')
867
+ deferred(() =>
868
+ placeholder.replaceWith(createElement(tag, props, ...children)))
869
+ return placeholder
870
+ }
871
+
924
872
  const node = document.createElement(tag)
925
873
  for (const [k, v] of Object.entries(props || {}))
926
874
  if (k === 'ref') v.current = node
@@ -954,6 +902,43 @@ function Fragment(...args) {
954
902
  return frag
955
903
  }
956
904
 
905
+ function deferred(cb) {
906
+ return window.requestIdleCallback
907
+ ? requestIdleCallback(cb)
908
+ : setTimeout(cb, 100) // Safari
909
+ }
910
+
911
+
912
+ // When false, the URL will be updated with param=false
913
+ function initPreference(param) {
914
+ const qs = new URLSearchParams(location.search)
915
+ if (!qs.has(param)) {
916
+ const group = localStorage.getItem(param) !== 'false'
917
+ if (!group) {
918
+ const url = new URL(location.href)
919
+ url.searchParams.set(param, false)
920
+ history.replaceState(null, '', url)
921
+ }
922
+ return group
923
+ }
924
+ return qs.get(param) !== 'false'
925
+ }
926
+
927
+ // When false, the URL and localStorage will have param=false
928
+ function togglePreference(param, nextVal) {
929
+ if (nextVal)
930
+ localStorage.removeItem(param)
931
+ else
932
+ localStorage.setItem(param, nextVal)
933
+
934
+ const url = new URL(location.href)
935
+ if (nextVal)
936
+ url.searchParams.delete(param)
937
+ else
938
+ url.searchParams.set(param, false)
939
+ history.replaceState(null, '', url)
940
+ }
941
+
957
942
 
958
943
  /**
959
944
  * Think of this as a way of printing a directory tree in which
package/src/Mockaton.js CHANGED
@@ -52,8 +52,9 @@ async function onRequest(req, response) {
52
52
  sendBadRequest(response)
53
53
  return
54
54
  }
55
-
55
+
56
56
  try {
57
+ const route = new URL(url, 'http://_').pathname
57
58
  const { method } = req
58
59
 
59
60
  if (config.corsAllowed)
@@ -61,11 +62,11 @@ async function onRequest(req, response) {
61
62
 
62
63
  if (isPreflight(req))
63
64
  sendNoContent(response)
64
- else if (method === 'PATCH' && apiPatchRequests.has(url))
65
- await apiPatchRequests.get(url)(req, response)
66
- else if (method === 'GET' && apiGetRequests.has(url))
67
- apiGetRequests.get(url)(req, response)
68
- else if (method === 'GET' && staticCollection.brokerByRoute(url))
65
+ else if (method === 'PATCH' && apiPatchRequests.has(route))
66
+ await apiPatchRequests.get(route)(req, response)
67
+ else if (method === 'GET' && apiGetRequests.has(route))
68
+ apiGetRequests.get(route)(req, response)
69
+ else if (method === 'GET' && staticCollection.brokerByRoute(route))
69
70
  await dispatchStatic(req, response)
70
71
  else
71
72
  await dispatchMock(req, response)