mockaton 10.5.1 → 10.5.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 CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "mockaton",
3
3
  "description": "HTTP Mock Server",
4
4
  "type": "module",
5
- "version": "10.5.1",
5
+ "version": "10.5.3",
6
6
  "main": "index.js",
7
7
  "types": "index.d.ts",
8
8
  "license": "MIT",
package/src/Api.js CHANGED
@@ -4,29 +4,26 @@
4
4
  */
5
5
 
6
6
  import { join } from 'node:path'
7
- import { randomBytes } from 'node:crypto'
8
7
 
9
8
  import { cookie } from './cookie.js'
10
- import DashboardHtml from './DashboardHtml.js'
11
9
  import { parseJSON } from './utils/http-request.js'
12
10
  import { uiSyncVersion } from './Watcher.js'
13
11
  import * as staticCollection from './staticCollection.js'
14
12
  import * as mockBrokersCollection from './mockBrokersCollection.js'
15
13
  import { config, ConfigValidator } from './config.js'
14
+ import { DashboardHtml, CSP } from './DashboardHtml.js'
16
15
  import { DF, API, LONG_POLL_SERVER_TIMEOUT } from './ApiConstants.js'
17
16
  import { sendOK, sendJSON, sendUnprocessableContent, sendFile, sendHTML } from './utils/http-response.js'
18
17
 
19
18
 
20
19
  export const apiGetRequests = new Map([
21
- [API.dashboard, serveHtml],
20
+ [API.dashboard, serveDashboard],
22
21
  ...[
23
- '/Dashboard.css',
24
- '/Dashboard.js',
25
- '/ApiConstants.js',
26
- '/ApiCommander.js',
27
- '/Filename.js',
28
- '/Logo.svg'
29
- ].map(f => [API.dashboard + f, serveStatic(f)]),
22
+ 'Dashboard.css',
23
+ 'Dashboard.js',
24
+ 'ApiConstants.js', 'ApiCommander.js', 'Filename.js',
25
+ 'Logo.svg'
26
+ ].map(f => [API.dashboard + '/' + f, serveStatic(f)]),
30
27
 
31
28
  [API.state, getState],
32
29
  [API.syncVersion, longPollClientSyncVersion],
@@ -52,14 +49,8 @@ export const apiPatchRequests = new Map([
52
49
 
53
50
  /** # GET */
54
51
 
55
- function serveHtml(_, response) {
56
- const nonce = randomBytes(12).toString('base64url')
57
- response.setHeader('Content-Security-Policy', [
58
- `default-src 'self'`,
59
- `img-src data: blob: 'self'`,
60
- `script-src 'nonce-${nonce}' 'self'`
61
- ].join(';'))
62
- sendHTML(response, DashboardHtml(nonce))
52
+ function serveDashboard(_, response) {
53
+ sendHTML(response, DashboardHtml, CSP)
63
54
  }
64
55
 
65
56
  function serveStatic(f) {
@@ -17,13 +17,7 @@ export class Commander {
17
17
 
18
18
  /** @returns {JsonPromise<State>} */
19
19
  getState() {
20
- const url = this.#addr + API.state
21
- if (globalThis._aotFetch?.[url]) { // github.com/ericfortis/aot-fetch-demo
22
- const promise = globalThis._aotFetch[url]
23
- delete globalThis._aotFetch[url]
24
- return promise
25
- }
26
- return fetch(url)
20
+ return fetch(this.#addr + API.state)
27
21
  }
28
22
 
29
23
  /** @returns {JsonPromise<number>} */
package/src/Dashboard.js CHANGED
@@ -122,7 +122,7 @@ function Header() {
122
122
  r('header', null,
123
123
  r('img', {
124
124
  alt: t`Mockaton`,
125
- src: 'mockaton/Logo.svg',
125
+ src: 'Logo.svg',
126
126
  width: 120,
127
127
  height: 22
128
128
  }),
@@ -149,7 +149,6 @@ function SettingsMenu() {
149
149
 
150
150
  r('menu', {
151
151
  id,
152
- deferred: true,
153
152
  popover: '',
154
153
  className: CSS.SettingsMenu
155
154
  },
@@ -249,7 +248,7 @@ function GlobalDelayField() {
249
248
  autocomplete: 'none',
250
249
  value: delay,
251
250
  onChange,
252
- onWheel
251
+ onWheel: [onWheel, { passive: true }]
253
252
  })))
254
253
  }
255
254
 
@@ -862,19 +861,11 @@ function className(...args) {
862
861
 
863
862
 
864
863
  function createElement(tag, props, ...children) {
865
- if (props?.deferred) {
866
- delete props.deferred
867
- const placeholder = document.createComment('')
868
- deferred(() =>
869
- placeholder.replaceWith(createElement(tag, props, ...children)))
870
- return placeholder
871
- }
872
-
873
864
  const node = document.createElement(tag)
874
865
  for (const [k, v] of Object.entries(props || {}))
875
866
  if (k === 'ref') v.current = node
876
867
  else if (k === 'style') Object.assign(node.style, v)
877
- else if (k.startsWith('on')) node.addEventListener(k.replace(/^on/, '').toLowerCase(), v)
868
+ else if (k.startsWith('on')) node.addEventListener(k.slice(2).toLowerCase(), ...[v].flat())
878
869
  else if (k in node) node[k] = v
879
870
  else node.setAttribute(k, v)
880
871
  node.append(...children.flat().filter(Boolean))
@@ -1,26 +1,33 @@
1
- export default (nonce) => `
2
- <!DOCTYPE html>
1
+ import { API } from './ApiConstants.js'
2
+
3
+ export const CSP = [
4
+ `default-src 'self'`,
5
+ `img-src data: blob: 'self'`
6
+ ].join(';')
7
+
8
+
9
+ export const DashboardHtml = `<!DOCTYPE html>
3
10
  <html lang="en-US">
4
11
  <head>
5
12
  <meta charset="UTF-8">
13
+ <base href="${API.dashboard}/">
6
14
 
7
- <script nonce="${nonce}">
8
- // Fetches critical API data ahead-of-time.
9
- // It’s before loading the stylesheet because CSS blocks.
10
- // https://github.com/ericfortis/aot-fetch-demo
11
- const initialState = location.origin + '/mockaton/state'
12
- window._aotFetch = { [initialState]: fetch(initialState) }
13
- </script>
14
-
15
- <link rel="stylesheet" href="./mockaton/Dashboard.css" />
15
+ <link rel="stylesheet" href="Dashboard.css">
16
+ <script type="module" src="Dashboard.js"></script>
16
17
 
18
+ <link rel="preload" href="${API.state}" as="fetch" crossorigin>
19
+
20
+ <link rel="modulepreload" href="ApiConstants.js">
21
+ <link rel="modulepreload" href="ApiCommander.js">
22
+ <link rel="modulepreload" href="Filename.js">
23
+ <link rel="preload" href="Logo.svg" as="image">
24
+
17
25
  <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">
18
26
  <meta name="viewport" content="width=device-width, initial-scale=1">
19
27
  <meta name="description" content="HTTP Mock Server">
20
28
  <title>Mockaton</title>
21
29
  </head>
22
30
  <body>
23
- <script type="module" src="./mockaton/Dashboard.js"></script>
24
31
  </body>
25
32
  </html>
26
33
  `
@@ -9,9 +9,10 @@ export function sendOK(response) {
9
9
  response.end()
10
10
  }
11
11
 
12
- export function sendHTML(response, html) {
12
+ export function sendHTML(response, html, csp) {
13
13
  logger.access(response)
14
14
  response.setHeader('Content-Type', mimeFor('html'))
15
+ response.setHeader('Content-Security-Policy', csp)
15
16
  response.end(html)
16
17
  }
17
18