@jsenv/core 27.0.0-alpha.94 → 27.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/core",
3
- "version": "27.0.0-alpha.94",
3
+ "version": "27.0.1",
4
4
  "description": "Tool to develop, test and build js projects",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -61,7 +61,7 @@
61
61
  },
62
62
  "dependencies": {
63
63
  "@babel/plugin-proposal-dynamic-import": "7.16.7",
64
- "@babel/plugin-transform-modules-systemjs": "7.18.5",
64
+ "@babel/plugin-transform-modules-systemjs": "7.18.6",
65
65
  "@babel/plugin-transform-modules-umd": "7.18.0",
66
66
  "@c88/v8-coverage": "0.1.1",
67
67
  "@financial-times/polyfill-useragent-normaliser": "2.0.1",
@@ -71,13 +71,13 @@
71
71
  "@jsenv/importmap": "1.2.1",
72
72
  "@jsenv/integrity": "0.0.1",
73
73
  "@jsenv/node-esm-resolution": "0.1.0",
74
- "@jsenv/server": "12.7.3",
74
+ "@jsenv/server": "12.7.4",
75
75
  "@jsenv/uneval": "1.6.0",
76
76
  "@jsenv/url-meta": "7.0.0",
77
77
  "@jsenv/urls": "1.2.6",
78
78
  "@jsenv/utils": "2.0.1",
79
79
  "@jsenv/babel-plugins": "1.0.5",
80
- "@jsenv/log": "2.1.0",
80
+ "@jsenv/log": "3.0.2",
81
81
  "@jsenv/sourcemap": "1.0.1",
82
82
  "acorn-import-assertions": "1.8.0",
83
83
  "cuid": "2.1.8",
@@ -99,15 +99,15 @@
99
99
  "@babel/plugin-syntax-import-assertions": "7.17.12",
100
100
  "@jsenv/assert": "2.6.0",
101
101
  "@jsenv/eslint-config": "16.0.9",
102
- "@jsenv/file-size-impact": "13.0.0",
102
+ "@jsenv/file-size-impact": "13.0.1",
103
103
  "@jsenv/https-local": "2.1.0",
104
- "@jsenv/package-workspace": "0.3.0",
105
- "@jsenv/performance-impact": "3.0.0",
106
- "eslint": "8.18.0",
104
+ "@jsenv/package-workspace": "0.4.1",
105
+ "@jsenv/performance-impact": "3.0.1",
106
+ "eslint": "8.19.0",
107
107
  "eslint-plugin-html": "6.2.0",
108
108
  "eslint-plugin-import": "2.26.0",
109
109
  "eslint-plugin-react": "7.30.1",
110
- "playwright": "1.22.2",
110
+ "playwright": "1.23.1",
111
111
  "prettier": "2.7.1"
112
112
  }
113
- }
113
+ }
@@ -988,7 +988,7 @@ const applyUrlVersioning = async ({
988
988
  // - ignored files:
989
989
  // we don't know their content
990
990
  // - unused files without reference
991
- // File updated such as style.css -> style.css.js or file.js->file.es5.js
991
+ // File updated such as style.css -> style.css.js or file.js->file.nomodule.js
992
992
  // Are used at some point just to be discarded later because they need to be converted
993
993
  // There is no need to version them and we could not because the file have been ignored
994
994
  // so their content is unknown
@@ -56,8 +56,8 @@ export const startBuildServer = async ({
56
56
  "./package.json": true,
57
57
  "./jsenv.config.mjs": true,
58
58
  },
59
+ buildServerAutoreload = false,
59
60
  buildServerMainFile = getCallerPosition().url,
60
- buildServerAutoreload = true,
61
61
  cooldownBetweenFileEvents,
62
62
  }) => {
63
63
  const logger = createLogger({ logLevel })
@@ -69,7 +69,9 @@ export const startBuildServer = async ({
69
69
  `buildIndexPath must be a string, got ${buildIndexPath}`,
70
70
  )
71
71
  }
72
- if (buildIndexPath[0] !== "/") {
72
+ if (buildIndexPath[0] === "/") {
73
+ buildIndexPath = buildIndexPath.slice(1)
74
+ } else {
73
75
  const buildIndexUrl = new URL(buildIndexPath, buildDirectoryUrl).href
74
76
  if (!buildIndexUrl.startsWith(buildDirectoryUrl)) {
75
77
  throw new Error(
@@ -96,55 +98,56 @@ export const startBuildServer = async ({
96
98
  port = await findFreePort(port, { signal: operation.signal })
97
99
  }
98
100
 
99
- const reloadableWorker = createReloadableWorker(buildServerMainFile)
100
- if (buildServerAutoreload && reloadableWorker.isPrimary) {
101
- const buildServerFileChangeCallback = ({ relativeUrl, event }) => {
102
- const url = new URL(relativeUrl, rootDirectoryUrl).href
103
- if (buildServerAutoreload) {
101
+ let reloadableWorker
102
+ if (buildServerAutoreload) {
103
+ reloadableWorker = createReloadableWorker(buildServerMainFile)
104
+ if (reloadableWorker.isPrimary) {
105
+ const buildServerFileChangeCallback = ({ relativeUrl, event }) => {
106
+ const url = new URL(relativeUrl, rootDirectoryUrl).href
104
107
  logger.info(`file ${event} ${url} -> restarting server...`)
105
108
  reloadableWorker.reload()
106
109
  }
107
- }
108
- const stopWatchingBuildServerFiles = registerDirectoryLifecycle(
109
- rootDirectoryUrl,
110
- {
111
- watchPatterns: {
112
- [buildServerMainFile]: true,
113
- ...buildServerFiles,
114
- ".jsenv/": false,
115
- },
116
- cooldownBetweenFileEvents,
117
- keepProcessAlive: false,
118
- recursive: true,
119
- added: ({ relativeUrl }) => {
120
- buildServerFileChangeCallback({ relativeUrl, event: "added" })
121
- },
122
- updated: ({ relativeUrl }) => {
123
- buildServerFileChangeCallback({ relativeUrl, event: "modified" })
124
- },
125
- removed: ({ relativeUrl }) => {
126
- buildServerFileChangeCallback({ relativeUrl, event: "removed" })
110
+ const stopWatchingBuildServerFiles = registerDirectoryLifecycle(
111
+ rootDirectoryUrl,
112
+ {
113
+ watchPatterns: {
114
+ ...buildServerFiles,
115
+ [buildServerMainFile]: true,
116
+ ".jsenv/": false,
117
+ },
118
+ cooldownBetweenFileEvents,
119
+ keepProcessAlive: false,
120
+ recursive: true,
121
+ added: ({ relativeUrl }) => {
122
+ buildServerFileChangeCallback({ relativeUrl, event: "added" })
123
+ },
124
+ updated: ({ relativeUrl }) => {
125
+ buildServerFileChangeCallback({ relativeUrl, event: "modified" })
126
+ },
127
+ removed: ({ relativeUrl }) => {
128
+ buildServerFileChangeCallback({ relativeUrl, event: "removed" })
129
+ },
127
130
  },
128
- },
129
- )
130
- operation.addAbortCallback(() => {
131
- stopWatchingBuildServerFiles()
132
- reloadableWorker.terminate()
133
- })
134
- const worker = await reloadableWorker.load()
135
- const messagePromise = new Promise((resolve) => {
136
- worker.once("message", resolve)
137
- })
138
- await messagePromise
139
- // if (!keepProcessAlive) {
140
- // worker.unref()
141
- // }
142
- return {
143
- origin: `${protocol}://127.0.0.1:${port}`,
144
- stop: () => {
131
+ )
132
+ operation.addAbortCallback(() => {
145
133
  stopWatchingBuildServerFiles()
146
134
  reloadableWorker.terminate()
147
- },
135
+ })
136
+ const worker = await reloadableWorker.load()
137
+ const messagePromise = new Promise((resolve) => {
138
+ worker.once("message", resolve)
139
+ })
140
+ await messagePromise
141
+ // if (!keepProcessAlive) {
142
+ // worker.unref()
143
+ // }
144
+ return {
145
+ origin: `${protocol}://127.0.0.1:${port}`,
146
+ stop: () => {
147
+ stopWatchingBuildServerFiles()
148
+ reloadableWorker.terminate()
149
+ },
150
+ }
148
151
  }
149
152
  }
150
153
 
@@ -196,7 +199,7 @@ export const startBuildServer = async ({
196
199
  logger.info(`- ${server.origins[key]}`)
197
200
  })
198
201
  logger.info(``)
199
- if (reloadableWorker.isWorker) {
202
+ if (reloadableWorker && reloadableWorker.isWorker) {
200
203
  parentPort.postMessage(server.origin)
201
204
  }
202
205
  return {
@@ -4,53 +4,51 @@
4
4
  viewBox="0 0 430 430"
5
5
  enable-background="new 0 0 430 430"
6
6
  >
7
- <g>
8
- <g>
9
- <path
10
- id="j-letter"
11
- fill="#F7931E"
12
- d="M78.879,272.229c3.381-0.441,7.056-1.176,9.408-3.822c2.793-2.939,3.234-8.086,3.234-19.111v-63.064
7
+ <g id="letters">
8
+ <path
9
+ id="j"
10
+ fill="#F7931E"
11
+ d="M78.879,272.229c3.381-0.441,7.056-1.176,9.408-3.822c2.793-2.939,3.234-8.086,3.234-19.111v-63.064
13
12
  h19.404v66.74c0,16.023-3.381,23.52-9.555,28.371c-5.292,4.264-14.112,6.174-21.021,6.174L78.879,272.229z M111.072,167.121
14
13
  c0,6.174-4.41,10.438-10.143,10.438c-5.292,0-9.702-4.263-9.555-10.438c-0.147-6.468,4.41-10.437,9.849-10.437
15
14
  S111.072,160.653,111.072,167.121z"
16
- />
17
- <path
18
- id="s-letter"
19
- fill="#F7931E"
20
- d="M123.714,240.77c2.793,1.764,8.085,3.822,12.936,3.822c4.998,0,7.791-2.205,7.791-6.469
15
+ />
16
+ <path
17
+ id="s"
18
+ fill="#F7931E"
19
+ d="M123.714,240.77c2.793,1.764,8.085,3.822,12.936,3.822c4.998,0,7.791-2.205,7.791-6.469
21
20
  c0-3.675-2.058-6.027-8.379-9.702c-11.76-6.615-14.553-14.112-14.553-20.727c0-12.937,9.261-22.639,23.667-22.639
22
21
  c6.027,0,10.731,1.47,14.553,3.234l-3.381,14.112c-2.793-1.617-6.174-2.94-9.996-2.94c-4.851,0-7.203,2.94-7.203,6.174
23
22
  c0,3.234,1.617,4.998,8.379,8.967c10.584,6.027,14.553,13.524,14.553,21.756c0,14.699-10.584,22.639-25.432,22.639
24
23
  c-6.027,0-13.083-1.617-16.464-4.117L123.714,240.77z"
25
- />
26
- <path
27
- id="e-letter"
28
- fill="#F7931E"
29
- d="M204.414,223.57c0.148,21.756,8.674,26.461,16.906,26.461c4.852,0,8.967-1.176,11.76-2.793l1.764,8.379
24
+ />
25
+ <path
26
+ id="e"
27
+ fill="#F7931E"
28
+ d="M204.414,223.57c0.148,21.756,8.674,26.461,16.906,26.461c4.852,0,8.967-1.176,11.76-2.793l1.764,8.379
30
29
  c-3.969,2.205-9.996,3.381-15.582,3.381c-17.052,0-25.872-13.965-25.872-35.722c0-23.08,9.702-37.486,23.961-37.486
31
30
  c14.553,0,20.285,15.289,20.285,31.459c0,2.646,0,4.557-0.146,6.321H204.414z M226.76,215.191
32
31
  c0.293-14.259-5.145-20.581-10.584-20.581c-7.352,0-11.174,10.878-11.613,20.581H226.76z"
33
- />
34
- <path
35
- id="n-letter"
36
- fill="#F7931E"
37
- d="M249.836,205.342c0-8.379-0.441-12.643-0.588-18.375h9.85l0.588,8.526h0.293
32
+ />
33
+ <path
34
+ id="n"
35
+ fill="#F7931E"
36
+ d="M249.836,205.342c0-8.379-0.441-12.643-0.588-18.375h9.85l0.588,8.526h0.293
38
37
  c3.088-5.733,8.82-9.702,16.318-9.702c9.85,0,17.199,7.35,17.199,24.55v47.775h-11.318V212.25c0-8.379-1.617-16.905-9.85-16.905
39
38
  c-4.705,0-9.262,3.969-10.732,11.613c-0.293,1.764-0.439,3.969-0.439,6.321v44.835h-11.32V205.342z"
40
- />
41
- <path
42
- id="v-letter"
43
- fill="#F7931E"
44
- d="M313.783,186.966l8.967,39.985c1.029,4.851,2.205,11.172,3.088,17.346h0.441
39
+ />
40
+ <path
41
+ id="v"
42
+ fill="#F7931E"
43
+ d="M313.783,186.966l8.967,39.985c1.029,4.851,2.205,11.172,3.088,17.346h0.441
45
44
  c0.734-5.879,1.91-11.907,2.939-17.346l8.82-39.985h11.172l-18.523,71.149h-10.143l-18.521-71.149H313.783z"
46
- />
47
- </g>
48
- <g>
49
- <g>
50
- <path
51
- id="arc1"
52
- fill="#F7931E"
53
- d="M32.118,204.979c0,0,0.105,1.801,0.302,5.179c0.124,3.4,0.638,8.29,1.434,14.48
45
+ />
46
+ </g>
47
+ <g id="arcs">
48
+ <path
49
+ id="arc1"
50
+ fill="#F7931E"
51
+ d="M32.118,204.979c0,0,0.105,1.801,0.302,5.179c0.124,3.4,0.638,8.29,1.434,14.48
54
52
  c0.249,1.546,0.511,3.174,0.786,4.882c0.137,0.853,0.278,1.725,0.421,2.617c0.154,0.89,0.376,1.789,0.558,2.712
55
53
  c0.384,1.843,0.783,3.761,1.197,5.75c0.444,1.981,1.027,4.008,1.56,6.112c2.274,8.378,5.328,17.708,9.758,27.396
56
54
  c4.406,9.688,10.04,19.776,17.062,29.673c7.003,9.901,15.393,19.609,25.102,28.499c9.702,8.888,20.652,17.025,32.581,23.85
@@ -74,13 +72,11 @@
74
72
  c-12.467-7.743-23.632-16.999-33.41-26.861c-9.758-9.893-18.135-20.455-24.833-31.222c-6.743-10.739-11.988-21.536-15.97-31.794
75
73
  c-4.006-10.258-6.601-20.021-8.441-28.721c-1.917-8.698-2.688-16.429-3.245-22.764c-0.396-6.374-0.584-11.386-0.485-14.752
76
74
  c0.026-3.383,0.04-5.188,0.04-5.188c0.003-0.47,0.387-0.848,0.857-0.844C31.725,204.181,32.091,204.536,32.118,204.979z"
77
- />
78
- </g>
79
- <g>
80
- <path
81
- id="arc2"
82
- fill="#F7931E"
83
- d="M393.625,225.021c0,0-0.104-1.731-0.297-4.979c-0.049-0.812-0.103-1.718-0.162-2.716
75
+ />
76
+ <path
77
+ id="arc2"
78
+ fill="#F7931E"
79
+ d="M393.625,225.021c0,0-0.104-1.731-0.297-4.979c-0.049-0.812-0.103-1.718-0.162-2.716
84
80
  c-0.029-0.499-0.061-1.021-0.093-1.565c-0.059-0.538-0.119-1.097-0.182-1.679c-0.269-2.323-0.534-4.99-0.906-7.966
85
81
  c-0.241-1.486-0.496-3.051-0.763-4.693c-0.133-0.82-0.269-1.658-0.408-2.516c-0.126-0.859-0.286-1.731-0.487-2.616
86
82
  c-0.778-3.54-1.458-7.393-2.614-11.413c-0.266-1.009-0.537-2.034-0.812-3.075c-0.264-1.043-0.553-2.096-0.908-3.147
@@ -119,26 +115,26 @@
119
115
  c0.173,3.065,0.257,5.808,0.365,8.183c0.022,0.594,0.045,1.165,0.066,1.714c-0.006,0.545-0.01,1.068-0.015,1.567
120
116
  c-0.009,1-0.017,1.908-0.024,2.721c-0.029,3.252-0.045,4.987-0.045,4.987c-0.004,0.47-0.389,0.847-0.857,0.843
121
117
  C394.018,225.817,393.652,225.463,393.625,225.021z"
122
- />
123
- </g>
124
- <circle
125
- id="circle2"
126
- fill="#F7931E"
127
- stroke-width="9"
128
- stroke-miterlimit="10"
129
- cx="70.536"
130
- cy="110.694"
131
- r="36.011"
132
- />
133
- <circle
134
- id="circle1"
135
- fill="#F7931E"
136
- stroke-width="9"
137
- stroke-miterlimit="10"
138
- cx="362.721"
139
- cy="309.694"
140
- r="36.012"
141
- />
142
- </g>
118
+ />
119
+ </g>
120
+ <g id="circles">
121
+ <circle
122
+ id="circle2"
123
+ fill="#F7931E"
124
+ stroke-width="9"
125
+ stroke-miterlimit="10"
126
+ cx="70.536"
127
+ cy="110.694"
128
+ r="36.011"
129
+ />
130
+ <circle
131
+ id="circle1"
132
+ fill="#F7931E"
133
+ stroke-width="9"
134
+ stroke-miterlimit="10"
135
+ cx="362.721"
136
+ cy="309.694"
137
+ r="36.012"
138
+ />
143
139
  </g>
144
- </svg>
140
+ </svg>
@@ -31,19 +31,21 @@ export const startDevServer = async ({
31
31
  certificate,
32
32
  privateKey,
33
33
  keepProcessAlive = true,
34
+ serverPlugins,
35
+
34
36
  rootDirectoryUrl,
37
+ clientFiles = {
38
+ "./src/": true,
39
+ "./tests/": true,
40
+ },
35
41
  devServerFiles = {
36
42
  "./package.json": true,
37
43
  "./jsenv.config.mjs": true,
38
44
  },
45
+ clientAutoreload = true,
46
+ devServerAutoreload = false,
39
47
  devServerMainFile = getCallerPosition().url,
40
- devServerAutoreload = true,
41
- clientFiles = {
42
- "./src/": true,
43
- "./tests/": true,
44
- },
45
48
  cooldownBetweenFileEvents,
46
- clientAutoreload = true,
47
49
 
48
50
  sourcemaps = "inline",
49
51
  // default runtimeCompat assume dev server will be request by recent browsers
@@ -92,53 +94,57 @@ export const startDevServer = async ({
92
94
  port = await findFreePort(port, { signal: operation.signal })
93
95
  }
94
96
 
95
- const reloadableWorker = createReloadableWorker(devServerMainFile)
96
- if (devServerAutoreload && reloadableWorker.isPrimary) {
97
- const devServerFileChangeCallback = ({ relativeUrl, event }) => {
98
- const url = new URL(relativeUrl, rootDirectoryUrl).href
99
- logger.info(`file ${event} ${url} -> restarting server...`)
100
- reloadableWorker.reload()
101
- }
102
- const stopWatchingDevServerFiles = registerDirectoryLifecycle(
103
- rootDirectoryUrl,
104
- {
105
- watchPatterns: {
106
- [devServerMainFile]: true,
107
- ...devServerFiles,
108
- },
109
- cooldownBetweenFileEvents,
110
- keepProcessAlive: false,
111
- recursive: true,
112
- added: ({ relativeUrl }) => {
113
- devServerFileChangeCallback({ relativeUrl, event: "added" })
114
- },
115
- updated: ({ relativeUrl }) => {
116
- devServerFileChangeCallback({ relativeUrl, event: "modified" })
117
- },
118
- removed: ({ relativeUrl }) => {
119
- devServerFileChangeCallback({ relativeUrl, event: "removed" })
97
+ let reloadableWorker
98
+ if (devServerAutoreload) {
99
+ reloadableWorker = createReloadableWorker(devServerMainFile)
100
+ if (reloadableWorker.isPrimary) {
101
+ const devServerFileChangeCallback = ({ relativeUrl, event }) => {
102
+ const url = new URL(relativeUrl, rootDirectoryUrl).href
103
+ logger.info(`file ${event} ${url} -> restarting server...`)
104
+ reloadableWorker.reload()
105
+ }
106
+ const stopWatchingDevServerFiles = registerDirectoryLifecycle(
107
+ rootDirectoryUrl,
108
+ {
109
+ watchPatterns: {
110
+ ...devServerFiles.include,
111
+ [devServerMainFile]: true,
112
+ ".jsenv/": false,
113
+ },
114
+ cooldownBetweenFileEvents,
115
+ keepProcessAlive: false,
116
+ recursive: true,
117
+ added: ({ relativeUrl }) => {
118
+ devServerFileChangeCallback({ relativeUrl, event: "added" })
119
+ },
120
+ updated: ({ relativeUrl }) => {
121
+ devServerFileChangeCallback({ relativeUrl, event: "modified" })
122
+ },
123
+ removed: ({ relativeUrl }) => {
124
+ devServerFileChangeCallback({ relativeUrl, event: "removed" })
125
+ },
120
126
  },
121
- },
122
- )
123
- operation.addAbortCallback(() => {
124
- stopWatchingDevServerFiles()
125
- reloadableWorker.terminate()
126
- })
127
-
128
- const worker = await reloadableWorker.load()
129
- const messagePromise = new Promise((resolve) => {
130
- worker.once("message", resolve)
131
- })
132
- await messagePromise
133
- // if (!keepProcessAlive) {
134
- // worker.unref()
135
- // }
136
- return {
137
- origin: `${protocol}://127.0.0.1:${port}`,
138
- stop: () => {
127
+ )
128
+ operation.addAbortCallback(() => {
139
129
  stopWatchingDevServerFiles()
140
130
  reloadableWorker.terminate()
141
- },
131
+ })
132
+
133
+ const worker = await reloadableWorker.load()
134
+ const messagePromise = new Promise((resolve) => {
135
+ worker.once("message", resolve)
136
+ })
137
+ await messagePromise
138
+ // if (!keepProcessAlive) {
139
+ // worker.unref()
140
+ // }
141
+ return {
142
+ origin: `${protocol}://127.0.0.1:${port}`,
143
+ stop: () => {
144
+ stopWatchingDevServerFiles()
145
+ reloadableWorker.terminate()
146
+ },
147
+ }
142
148
  }
143
149
  }
144
150
 
@@ -221,6 +227,7 @@ export const startDevServer = async ({
221
227
  urlGraph,
222
228
  kitchen,
223
229
  scenario: "dev",
230
+ serverPlugins,
224
231
  })
225
232
  startDevServerTask.done()
226
233
  logger.info(``)
@@ -233,7 +240,7 @@ export const startDevServer = async ({
233
240
  kitchen.pluginController.callHooks("destroy", {})
234
241
  }
235
242
  })
236
- if (reloadableWorker.isWorker) {
243
+ if (reloadableWorker && reloadableWorker.isWorker) {
237
244
  parentPort.postMessage(server.origin)
238
245
  }
239
246
  return {
@@ -64,6 +64,7 @@ export const createKitchen = ({
64
64
  return RUNTIME_COMPAT.isSupported(runtimeCompat, feature)
65
65
  },
66
66
  }
67
+ pluginController.callHooks("init", kitchenContext)
67
68
  const createReference = ({
68
69
  data = {},
69
70
  node,
@@ -61,7 +61,13 @@ export const createFileService = ({
61
61
  const urlInfo = urlGraph.reuseOrCreateUrlInfo(reference.url)
62
62
 
63
63
  const ifNoneMatch = request.headers["if-none-match"]
64
- if (ifNoneMatch && urlInfo.contentEtag === ifNoneMatch) {
64
+ if (
65
+ ifNoneMatch &&
66
+ urlInfo.contentEtag === ifNoneMatch &&
67
+ // - isValid is true by default
68
+ // - isValid can be overriden by plugins such as cjs_to_esm
69
+ urlInfo.isValid()
70
+ ) {
65
71
  return {
66
72
  status: 304,
67
73
  headers: {
@@ -83,6 +89,7 @@ export const createFileService = ({
83
89
  urlInfo.originalContent = null
84
90
  urlInfo.type = null
85
91
  urlInfo.subtype = null
92
+ urlInfo.dependsOnPackageJson = false
86
93
  urlInfo.timing = {}
87
94
  }
88
95
  const { runtimeName, runtimeVersion } = parseUserAgentHeader(
@@ -121,33 +121,48 @@ export const createUrlGraph = ({
121
121
  }
122
122
 
123
123
  if (clientFileChangeCallbackList) {
124
- const updateModifiedTimestamp = (urlInfo, modifiedTimestamp) => {
125
- const seen = []
126
- const iterate = (urlInfo) => {
127
- if (seen.includes(urlInfo.url)) {
128
- return
129
- }
130
- seen.push(urlInfo.url)
131
- urlInfo.modifiedTimestamp = modifiedTimestamp
132
- urlInfo.dependents.forEach((dependentUrl) => {
133
- const dependentUrlInfo = urlInfos[dependentUrl]
134
- const { hotAcceptDependencies = [] } = dependentUrlInfo.data
135
- if (!hotAcceptDependencies.includes(urlInfo.url)) {
136
- iterate(dependentUrlInfo)
137
- }
138
- })
139
- }
140
- iterate(urlInfo)
141
- }
142
124
  clientFileChangeCallbackList.push(({ url }) => {
143
125
  const urlInfo = urlInfos[url]
144
126
  if (urlInfo) {
145
- updateModifiedTimestamp(urlInfo, Date.now())
146
- urlInfo.contentEtag = null
127
+ considerModified(urlInfo, Date.now())
147
128
  }
148
129
  })
149
130
  }
150
131
 
132
+ const considerModified = (urlInfo, modifiedTimestamp = Date.now()) => {
133
+ const seen = []
134
+ const iterate = (urlInfo) => {
135
+ if (seen.includes(urlInfo.url)) {
136
+ return
137
+ }
138
+ seen.push(urlInfo.url)
139
+ urlInfo.modifiedTimestamp = modifiedTimestamp
140
+ urlInfo.contentEtag = undefined
141
+ urlInfo.dependents.forEach((dependentUrl) => {
142
+ const dependentUrlInfo = urlInfos[dependentUrl]
143
+ const { hotAcceptDependencies = [] } = dependentUrlInfo.data
144
+ if (!hotAcceptDependencies.includes(urlInfo.url)) {
145
+ iterate(dependentUrlInfo)
146
+ }
147
+ })
148
+ }
149
+ iterate(urlInfo)
150
+ }
151
+
152
+ const getRelatedUrlInfos = (url) => {
153
+ const urlInfosUntilNotInline = []
154
+ const parentUrlInfo = getUrlInfo(url)
155
+ if (parentUrlInfo) {
156
+ urlInfosUntilNotInline.push(parentUrlInfo)
157
+ if (parentUrlInfo.inlineUrlSite) {
158
+ urlInfosUntilNotInline.push(
159
+ ...getRelatedUrlInfos(parentUrlInfo.inlineUrlSite.url),
160
+ )
161
+ }
162
+ }
163
+ return urlInfosUntilNotInline
164
+ }
165
+
151
166
  return {
152
167
  urlInfos,
153
168
  reuseOrCreateUrlInfo,
@@ -156,6 +171,8 @@ export const createUrlGraph = ({
156
171
  inferReference,
157
172
  findDependent,
158
173
  updateReferences,
174
+ considerModified,
175
+ getRelatedUrlInfos,
159
176
 
160
177
  toJSON: (rootDirectoryUrl) => {
161
178
  const data = {}
@@ -176,6 +193,9 @@ export const createUrlGraph = ({
176
193
  const createUrlInfo = (url) => {
177
194
  return {
178
195
  modifiedTimestamp: 0,
196
+ contentEtag: null,
197
+ dependsOnPackageJson: false,
198
+ isValid,
179
199
  data: {}, // plugins can put whatever they want here
180
200
  references: [],
181
201
  dependencies: new Set(),
@@ -192,10 +212,12 @@ const createUrlInfo = (url) => {
192
212
  shouldHandle: undefined,
193
213
  originalContent: undefined,
194
214
  content: undefined,
195
- contentEtag: null,
215
+
196
216
  sourcemap: null,
197
217
  sourcemapReference: null,
198
218
  timing: {},
199
219
  headers: {},
200
220
  }
201
221
  }
222
+
223
+ const isValid = () => true