@jsenv/core 27.8.0 → 28.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.
Files changed (38) hide show
  1. package/dist/js/autoreload.js +2 -2
  2. package/dist/js/html_supervisor_installer.js +3 -3
  3. package/dist/js/server_events_client.js +1 -1
  4. package/dist/main.js +520 -469
  5. package/package.json +2 -2
  6. package/readme.md +1 -1
  7. package/src/build/build.js +8 -8
  8. package/src/build/{resync_ressource_hints.js → resync_resource_hints.js} +10 -12
  9. package/src/build/start_build_server.js +6 -9
  10. package/src/dev/start_dev_server.js +2 -2
  11. package/src/execute/execute.js +14 -52
  12. package/src/execute/runtimes/browsers/from_playwright.js +19 -8
  13. package/src/main.js +3 -0
  14. package/src/omega/kitchen.js +5 -5
  15. package/src/omega/omega_server.js +2 -2
  16. package/src/omega/server/file_service.js +3 -3
  17. package/src/omega/url_graph/url_graph_load.js +4 -4
  18. package/src/omega/url_graph.js +3 -3
  19. package/src/ping_server.js +30 -0
  20. package/src/plugins/autoreload/client/reload.js +2 -2
  21. package/src/plugins/autoreload/jsenv_plugin_autoreload_client.js +1 -1
  22. package/src/plugins/autoreload/jsenv_plugin_autoreload_server.js +3 -3
  23. package/src/plugins/autoreload/jsenv_plugin_hmr.js +1 -1
  24. package/src/plugins/explorer/jsenv_plugin_explorer.js +1 -1
  25. package/src/plugins/html_supervisor/client/error_formatter.js +3 -3
  26. package/src/plugins/html_supervisor/jsenv_plugin_html_supervisor.js +5 -5
  27. package/src/plugins/import_meta_hot/html_hot_dependencies.js +4 -4
  28. package/src/plugins/import_meta_scenarios/jsenv_plugin_import_meta_scenarios.js +1 -9
  29. package/src/plugins/plugin_controller.js +2 -2
  30. package/src/plugins/server_events/client/server_events_client.js +1 -1
  31. package/src/plugins/toolbar/jsenv_plugin_toolbar.js +1 -1
  32. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic.js +2 -2
  33. package/src/plugins/transpilation/as_js_classic/jsenv_plugin_as_js_classic_html.js +3 -3
  34. package/src/plugins/transpilation/babel/jsenv_plugin_babel.js +13 -0
  35. package/src/plugins/url_analysis/html/html_urls.js +2 -2
  36. package/src/plugins/url_analysis/jsenv_plugin_url_analysis.js +1 -1
  37. package/src/test/execute_plan.js +15 -68
  38. package/src/test/execute_test_plan.js +4 -26
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsenv/core",
3
- "version": "27.8.0",
3
+ "version": "28.0.1",
4
4
  "description": "Tool to develop, test and build js projects",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -73,7 +73,7 @@
73
73
  "@jsenv/integrity": "0.0.1",
74
74
  "@jsenv/log": "3.1.0",
75
75
  "@jsenv/node-esm-resolution": "0.1.0",
76
- "@jsenv/server": "13.1.0",
76
+ "@jsenv/server": "14.1.0",
77
77
  "@jsenv/sourcemap": "1.0.4",
78
78
  "@jsenv/uneval": "1.6.0",
79
79
  "@jsenv/url-meta": "7.0.0",
package/readme.md CHANGED
@@ -16,7 +16,7 @@ npm create jsenv@latest
16
16
  ```
17
17
 
18
18
  This command prompts to choose a demo from a list.
19
- Each demo contains preconfigured scripts such as:
19
+ Each demo contains preconfigured scripts:
20
20
 
21
21
  - `npm run dev`: starts a dev server with autoreload.
22
22
  - `npm run test`: execute test files on browsers(s) and/or Node.js.
@@ -45,7 +45,7 @@ import { createBuilUrlsGenerator } from "./build_urls_generator.js"
45
45
  import { injectGlobalVersionMapping } from "./inject_global_version_mappings.js"
46
46
  import { createVersionGenerator } from "./version_generator.js"
47
47
  import { injectServiceWorkerUrls } from "./inject_service_worker_urls.js"
48
- import { resyncRessourceHints } from "./resync_ressource_hints.js"
48
+ import { resyncResourceHints } from "./resync_resource_hints.js"
49
49
 
50
50
  // default runtimeCompat corresponds to
51
51
  // "we can keep <script type="module"> intact":
@@ -314,13 +314,13 @@ build ${entryPointKeys.length} entry points`)
314
314
  })
315
315
  rawUrlInfo.references.forEach((reference) => {
316
316
  if (
317
- reference.isRessourceHint &&
317
+ reference.isResourceHint &&
318
318
  reference.expectedType === "js_module"
319
319
  ) {
320
320
  const referencedUrlInfo = rawGraph.getUrlInfo(reference.url)
321
321
  if (
322
322
  referencedUrlInfo &&
323
- // something else than the ressource hint is using this url
323
+ // something else than the resource hint is using this url
324
324
  referencedUrlInfo.dependents.size > 0
325
325
  ) {
326
326
  addToBundlerIfAny(referencedUrlInfo)
@@ -611,7 +611,7 @@ build ${entryPointKeys.length} entry points`)
611
611
  `urls should be inside build directory at this stage, found "${reference.url}"`,
612
612
  )
613
613
  }
614
- if (reference.isRessourceHint) {
614
+ if (reference.isResourceHint) {
615
615
  // return the raw url, we will resync at the end
616
616
  return rawUrls[reference.url]
617
617
  }
@@ -717,7 +717,7 @@ build ${entryPointKeys.length} entry points`)
717
717
  kitchen: finalGraphKitchen,
718
718
  outDirectoryUrl: new URL(".jsenv/postbuild/", rootDirectoryUrl),
719
719
  writeGeneratedFiles,
720
- skipRessourceHint: true,
720
+ skipResourceHint: true,
721
721
  startLoading: (cookEntryFile) => {
722
722
  entryUrls.forEach((entryUrl) => {
723
723
  const [, postBuildEntryUrlInfo] = cookEntryFile({
@@ -786,7 +786,7 @@ ${Array.from(finalGraph.urlInfoMap.keys()).join("\n")}`,
786
786
  urlInfo.data.buildUrlIsVersioned = useVersionedUrl
787
787
  urlInfo.data.buildUrlSpecifier = buildUrlSpecifier
788
788
  })
789
- await resyncRessourceHints({
789
+ await resyncResourceHints({
790
790
  logger,
791
791
  finalGraphKitchen,
792
792
  finalGraph,
@@ -1116,7 +1116,7 @@ const applyUrlVersioning = async ({
1116
1116
  if (reference.isInline || reference.url.startsWith("data:")) {
1117
1117
  return null
1118
1118
  }
1119
- if (reference.isRessourceHint) {
1119
+ if (reference.isResourceHint) {
1120
1120
  return null
1121
1121
  }
1122
1122
  // specifier comes from "normalize" hook done a bit earlier in this file
@@ -1185,7 +1185,7 @@ const applyUrlVersioning = async ({
1185
1185
  operation: buildOperation,
1186
1186
  urlGraph: finalGraph,
1187
1187
  kitchen: versioningKitchen,
1188
- skipRessourceHint: true,
1188
+ skipResourceHint: true,
1189
1189
  writeGeneratedFiles,
1190
1190
  startLoading: (cookEntryFile) => {
1191
1191
  postBuildEntryUrls.forEach((postBuildEntryUrl) => {
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  * Update <link rel="preload"> and friends after build (once we know everything)
3
3
  *
4
- * - Used to remove ressource hint targeting an url that is no longer used:
4
+ * - Used to remove resource hint targeting an url that is no longer used:
5
5
  * - Happens because of import assertions transpilation (file is inlined into JS)
6
6
  */
7
7
 
@@ -16,19 +16,19 @@ import {
16
16
 
17
17
  import { GRAPH } from "./graph_utils.js"
18
18
 
19
- export const resyncRessourceHints = async ({
19
+ export const resyncResourceHints = async ({
20
20
  logger,
21
21
  finalGraphKitchen,
22
22
  finalGraph,
23
23
  rawUrls,
24
24
  postBuildRedirections,
25
25
  }) => {
26
- const ressourceHintActions = []
26
+ const resourceHintActions = []
27
27
  GRAPH.forEach(finalGraph, (urlInfo) => {
28
28
  if (urlInfo.type !== "html") {
29
29
  return
30
30
  }
31
- ressourceHintActions.push(async () => {
31
+ resourceHintActions.push(async () => {
32
32
  const htmlAst = parseHtmlString(urlInfo.content, {
33
33
  storeOriginalPositions: false,
34
34
  })
@@ -38,14 +38,14 @@ export const resyncRessourceHints = async ({
38
38
  return
39
39
  }
40
40
  const rel = getHtmlNodeAttribute(linkNode, "rel")
41
- const isRessourceHint = [
41
+ const isresourceHint = [
42
42
  "preconnect",
43
43
  "dns-prefetch",
44
44
  "prefetch",
45
45
  "preload",
46
46
  "modulepreload",
47
47
  ].includes(rel)
48
- if (!isRessourceHint) {
48
+ if (!isresourceHint) {
49
49
  return
50
50
  }
51
51
 
@@ -57,7 +57,7 @@ export const resyncRessourceHints = async ({
57
57
  }
58
58
  }
59
59
  if (!buildUrl) {
60
- logger.warn(`remove ressource hint because cannot find "${href}"`)
60
+ logger.warn(`remove resource hint because cannot find "${href}"`)
61
61
  actions.push(() => {
62
62
  removeHtmlNode(linkNode)
63
63
  })
@@ -67,7 +67,7 @@ export const resyncRessourceHints = async ({
67
67
  const urlInfo = finalGraph.getUrlInfo(buildUrl)
68
68
  if (!urlInfo) {
69
69
  logger.warn(
70
- `remove ressource hint because cannot find "${buildUrl}" in the graph`,
70
+ `remove resource hint because cannot find "${buildUrl}" in the graph`,
71
71
  )
72
72
  actions.push(() => {
73
73
  removeHtmlNode(linkNode)
@@ -75,9 +75,7 @@ export const resyncRessourceHints = async ({
75
75
  return
76
76
  }
77
77
  if (urlInfo.dependents.size === 0) {
78
- logger.info(
79
- `remove ressource hint because "${href}" not used anymore`,
80
- )
78
+ logger.info(`remove resource hint because "${href}" not used anymore`)
81
79
  actions.push(() => {
82
80
  removeHtmlNode(linkNode)
83
81
  })
@@ -109,6 +107,6 @@ export const resyncRessourceHints = async ({
109
107
  })
110
108
  })
111
109
  await Promise.all(
112
- ressourceHintActions.map((ressourceHintAction) => ressourceHintAction()),
110
+ resourceHintActions.map((resourceHintAction) => resourceHintAction()),
113
111
  )
114
112
  }
@@ -41,7 +41,7 @@ export const startBuildServer = async ({
41
41
  certificate,
42
42
  privateKey,
43
43
  acceptAnyIp,
44
- host,
44
+ hostname,
45
45
  port = 9779,
46
46
  services = [],
47
47
  keepProcessAlive = true,
@@ -163,7 +163,7 @@ export const startBuildServer = async ({
163
163
  certificate,
164
164
  privateKey,
165
165
  acceptAnyIp,
166
- host,
166
+ hostname,
167
167
  port,
168
168
  serverTiming: true,
169
169
  requestWaitingMs: 60_000,
@@ -208,18 +208,15 @@ export const startBuildServer = async ({
208
208
 
209
209
  const createBuildFilesService = ({ buildDirectoryUrl, buildIndexPath }) => {
210
210
  return (request) => {
211
- const urlIsVersioned = new URL(
212
- request.ressource,
213
- request.origin,
214
- ).searchParams.has("v")
215
- if (buildIndexPath && request.ressource === "/") {
211
+ const urlIsVersioned = new URL(request.url).searchParams.has("v")
212
+ if (buildIndexPath && request.resource === "/") {
216
213
  request = {
217
214
  ...request,
218
- ressource: `/${buildIndexPath}`,
215
+ resource: `/${buildIndexPath}`,
219
216
  }
220
217
  }
221
218
  return fetchFileSystem(
222
- new URL(request.ressource.slice(1), buildDirectoryUrl),
219
+ new URL(request.resource.slice(1), buildDirectoryUrl),
223
220
  {
224
221
  headers: request.headers,
225
222
  cacheControl: urlIsVersioned
@@ -22,7 +22,7 @@ export const startDevServer = async ({
22
22
  http2 = false,
23
23
  certificate,
24
24
  privateKey,
25
- host,
25
+ hostname,
26
26
  port = 3456,
27
27
  acceptAnyIp,
28
28
  keepProcessAlive = true,
@@ -150,7 +150,7 @@ export const startDevServer = async ({
150
150
  http2,
151
151
  certificate,
152
152
  privateKey,
153
- host,
153
+ hostname,
154
154
  port,
155
155
  services,
156
156
 
@@ -1,9 +1,8 @@
1
1
  import { Abort, raceProcessTeardownEvents } from "@jsenv/abort"
2
-
3
2
  import { assertAndNormalizeDirectoryUrl } from "@jsenv/filesystem"
4
3
  import { createLogger } from "@jsenv/log"
5
4
 
6
- import { startOmegaServer } from "@jsenv/core/src/omega/omega_server.js"
5
+ import { pingServer } from "../ping_server.js"
7
6
  import { run } from "./run.js"
8
7
 
9
8
  export const execute = async ({
@@ -11,12 +10,13 @@ export const execute = async ({
11
10
  handleSIGINT = true,
12
11
  logLevel,
13
12
  rootDirectoryUrl,
13
+ devServerOrigin,
14
14
 
15
15
  fileRelativeUrl,
16
16
  allocatedMs,
17
17
  mirrorConsole = true,
18
18
  keepRunning = false,
19
- services,
19
+
20
20
  collectConsole,
21
21
  collectCoverage,
22
22
  coverageTempDirectoryUrl,
@@ -24,21 +24,6 @@ export const execute = async ({
24
24
  runtime,
25
25
  runtimeParams,
26
26
 
27
- scenarios = { dev: true },
28
- plugins = [],
29
- nodeEsmResolution,
30
- fileSystemMagicResolution,
31
- transpilation,
32
- htmlSupervisor = true,
33
- sourcemaps = "inline",
34
- writeGeneratedFiles = false,
35
-
36
- port,
37
- protocol,
38
- http2,
39
- certificate,
40
- privateKey,
41
-
42
27
  ignoreError = false,
43
28
  }) => {
44
29
  const logger = createLogger({ logLevel })
@@ -59,44 +44,21 @@ export const execute = async ({
59
44
  let resultTransformer = (result) => result
60
45
  runtimeParams = {
61
46
  rootDirectoryUrl,
47
+ devServerOrigin,
62
48
  fileRelativeUrl,
63
49
  ...runtimeParams,
64
50
  }
65
- if (runtime.needsServer) {
66
- const server = await startOmegaServer({
67
- signal: executeOperation.signal,
68
- logLevel: "warn",
69
- keepProcessAlive: false,
70
- services,
71
- port,
72
- protocol,
73
- http2,
74
- certificate,
75
- privateKey,
76
-
77
- rootDirectoryUrl,
78
- scenarios,
79
- runtimeCompat: { [runtime.name]: runtime.version },
80
-
81
- plugins,
82
-
83
- htmlSupervisor,
84
- nodeEsmResolution,
85
- fileSystemMagicResolution,
86
- transpilation,
87
- sourcemaps,
88
- writeGeneratedFiles,
89
- })
90
- executeOperation.addEndCallback(async () => {
91
- await server.stop("execution done")
92
- })
93
- runtimeParams = {
94
- ...runtimeParams,
95
- server,
51
+ if (runtime.type === "browser") {
52
+ if (!devServerOrigin) {
53
+ throw new TypeError(
54
+ `devServerOrigin is required when running tests on browser(s)`,
55
+ )
96
56
  }
97
- resultTransformer = (result) => {
98
- result.server = server
99
- return result
57
+ const devServerStarted = await pingServer(devServerOrigin)
58
+ if (!devServerStarted) {
59
+ throw new Error(
60
+ `dev server not started at ${devServerOrigin}. It is required to run tests`,
61
+ )
100
62
  }
101
63
  }
102
64
 
@@ -27,7 +27,6 @@ export const createRuntimeFromPlaywright = ({
27
27
  type: "browser",
28
28
  name: browserName,
29
29
  version: browserVersion,
30
- needsServer: true,
31
30
  }
32
31
  let browserAndContextPromise
33
32
  runtime.run = async ({
@@ -35,7 +34,7 @@ export const createRuntimeFromPlaywright = ({
35
34
  logger,
36
35
  rootDirectoryUrl,
37
36
  fileRelativeUrl,
38
- server,
37
+ devServerOrigin,
39
38
 
40
39
  // measurePerformance,
41
40
  collectPerformance,
@@ -98,7 +97,19 @@ export const createRuntimeFromPlaywright = ({
98
97
  }
99
98
  await disconnected
100
99
  }
101
- const page = await browserContext.newPage()
100
+ const coverageInHeaders =
101
+ coverageEnabled &&
102
+ (!coveragePlaywrightAPIAvailable ||
103
+ coverageMethodForBrowsers !== "playwright_api")
104
+ const page = await browserContext.newPage({
105
+ extraHTTPHeaders: {
106
+ ...(coverageInHeaders
107
+ ? {
108
+ "x-coverage-istanbul": JSON.stringify(coverageConfig),
109
+ }
110
+ : {}),
111
+ },
112
+ })
102
113
  const closePage = async () => {
103
114
  try {
104
115
  await page.close()
@@ -128,7 +139,7 @@ export const createRuntimeFromPlaywright = ({
128
139
  (v8CoveragesWithWebUrl) => {
129
140
  const fsUrl = moveUrl({
130
141
  url: v8CoveragesWithWebUrl.url,
131
- from: `${server.origin}/`,
142
+ from: `${devServerOrigin}/`,
132
143
  to: rootDirectoryUrl,
133
144
  preferAbsolute: true,
134
145
  })
@@ -202,7 +213,7 @@ export const createRuntimeFromPlaywright = ({
202
213
  })
203
214
  }
204
215
 
205
- const fileClientUrl = new URL(fileRelativeUrl, `${server.origin}/`).href
216
+ const fileClientUrl = new URL(fileRelativeUrl, `${devServerOrigin}/`).href
206
217
 
207
218
  // https://github.com/GoogleChrome/puppeteer/blob/v1.4.0/docs/api.md#event-console
208
219
  const removeConsoleListener = registerEvent({
@@ -302,7 +313,7 @@ export const createRuntimeFromPlaywright = ({
302
313
  const { exceptionSource } = returnValue
303
314
  const error = evalException(exceptionSource, {
304
315
  rootDirectoryUrl,
305
- server,
316
+ devServerOrigin,
306
317
  transformErrorHook,
307
318
  })
308
319
  cb({
@@ -525,13 +536,13 @@ const registerEvent = ({ object, eventType, callback }) => {
525
536
 
526
537
  const evalException = (
527
538
  exceptionSource,
528
- { rootDirectoryUrl, server, transformErrorHook },
539
+ { rootDirectoryUrl, devServerOrigin, transformErrorHook },
529
540
  ) => {
530
541
  const script = new Script(exceptionSource, { filename: "" })
531
542
  const error = script.runInThisContext()
532
543
  if (error && error instanceof Error) {
533
544
  const remoteRootRegexp = new RegExp(
534
- escapeRegexpSpecialChars(`${server.origin}/`),
545
+ escapeRegexpSpecialChars(`${devServerOrigin}/`),
535
546
  "g",
536
547
  )
537
548
  error.stack = error.stack.replace(remoteRootRegexp, rootDirectoryUrl)
package/src/main.js CHANGED
@@ -21,6 +21,9 @@ export { nodeWorkerThread } from "./execute/runtimes/node/node_worker_thread.js"
21
21
  export { build } from "./build/build.js"
22
22
  export { startBuildServer } from "./build/start_build_server.js"
23
23
 
24
+ // helpers
25
+ export { pingServer } from "./ping_server.js"
26
+
24
27
  // advanced
25
28
  export { execute } from "./execute/execute.js"
26
29
  export { jsenvPluginInjectGlobals } from "./plugins/inject_globals/jsenv_plugin_inject_globals.js"
@@ -88,7 +88,7 @@ export const createKitchen = ({
88
88
  isEntryPoint = false,
89
89
  isInline = false,
90
90
  injected = false,
91
- isRessourceHint = false,
91
+ isResourceHint = false,
92
92
  content,
93
93
  contentType,
94
94
  assert,
@@ -125,8 +125,8 @@ export const createKitchen = ({
125
125
  isEntryPoint,
126
126
  isInline,
127
127
  injected,
128
- isRessourceHint,
129
- // for inline ressources the reference contains the content
128
+ isResourceHint,
129
+ // for inline resources the reference contains the content
130
130
  content,
131
131
  contentType,
132
132
  timing: {},
@@ -182,8 +182,8 @@ export const createKitchen = ({
182
182
  // And this is because this hook inject query params used to:
183
183
  // - bypass browser cache (?v)
184
184
  // - convey information (?hmr)
185
- // But do not represent an other ressource, it is considered as
186
- // the same ressource under the hood
185
+ // But do not represent an other resource, it is considered as
186
+ // the same resource under the hood
187
187
  pluginController.callHooks(
188
188
  "transformUrlSearchParams",
189
189
  reference,
@@ -18,7 +18,7 @@ export const startOmegaServer = async ({
18
18
  privateKey,
19
19
  certificate,
20
20
  acceptAnyIp,
21
- host,
21
+ hostname,
22
22
  port = 0,
23
23
  keepProcessAlive = false,
24
24
  onStop = () => {},
@@ -62,7 +62,7 @@ export const startOmegaServer = async ({
62
62
  certificate,
63
63
  privateKey,
64
64
  acceptAnyIp,
65
- host,
65
+ hostname,
66
66
  port,
67
67
  requestWaitingMs: 60_1000,
68
68
  services: [
@@ -185,7 +185,7 @@ export const createFileService = ({
185
185
 
186
186
  return async (request) => {
187
187
  // serve file inside ".jsenv" directory
188
- const requestFileUrl = new URL(request.ressource.slice(1), rootDirectoryUrl)
188
+ const requestFileUrl = new URL(request.resource.slice(1), rootDirectoryUrl)
189
189
  .href
190
190
  if (urlIsInsideOf(requestFileUrl, jsenvDirectoryUrl)) {
191
191
  return fetchFileSystem(requestFileUrl, {
@@ -206,14 +206,14 @@ export const createFileService = ({
206
206
  let reference
207
207
  const parentUrl = inferParentFromRequest(request, rootDirectoryUrl)
208
208
  if (parentUrl) {
209
- reference = urlGraph.inferReference(request.ressource, parentUrl)
209
+ reference = urlGraph.inferReference(request.resource, parentUrl)
210
210
  }
211
211
  if (!reference) {
212
212
  const entryPoint = kitchen.injectReference({
213
213
  trace: { message: parentUrl || rootDirectoryUrl },
214
214
  parentUrl: parentUrl || rootDirectoryUrl,
215
215
  type: "http_request",
216
- specifier: request.ressource,
216
+ specifier: request.resource,
217
217
  })
218
218
  reference = entryPoint[0]
219
219
  }
@@ -31,11 +31,11 @@ export const loadUrlGraph = async ({
31
31
  })
32
32
  const { references } = urlInfo
33
33
  references.forEach((reference) => {
34
- // we don't cook ressource hints
35
- // because they might refer to ressource that will be modified during build
34
+ // we don't cook resource hints
35
+ // because they might refer to resource that will be modified during build
36
36
  // It also means something else have to reference that url in order to cook it
37
- // so that the preload is deleted by "resync_ressource_hints.js" otherwise
38
- if (reference.isRessourceHint) {
37
+ // so that the preload is deleted by "resync_resource_hints.js" otherwise
38
+ if (reference.isResourceHint) {
39
39
  return
40
40
  }
41
41
  // we use reference.generatedUrl to mimic what a browser would do:
@@ -70,10 +70,10 @@ export const createUrlGraph = ({
70
70
  }
71
71
 
72
72
  references.forEach((reference) => {
73
- if (reference.isRessourceHint) {
74
- // ressource hint are a special kind of reference.
73
+ if (reference.isResourceHint) {
74
+ // resource hint are a special kind of reference.
75
75
  // They are a sort of weak reference to an url.
76
- // We ignore them so that url referenced only by ressource hints
76
+ // We ignore them so that url referenced only by resource hints
77
77
  // have url.dependents.size === 0 and can be considered as not used
78
78
  // It means html won't consider url referenced solely
79
79
  // by <link> as dependency and it's fine
@@ -0,0 +1,30 @@
1
+ import { createServer } from "node:net"
2
+
3
+ export const pingServer = async (url) => {
4
+ const server = createServer()
5
+ const { hostname, port } = new URL(url)
6
+
7
+ try {
8
+ await new Promise((resolve, reject) => {
9
+ server.on("error", reject)
10
+ server.on("listening", () => {
11
+ resolve()
12
+ })
13
+ server.listen(port, hostname)
14
+ })
15
+ } catch (error) {
16
+ if (error && error.code === "EADDRINUSE") {
17
+ return true
18
+ }
19
+ if (error && error.code === "EACCES") {
20
+ return true
21
+ }
22
+ throw error
23
+ }
24
+ await new Promise((resolve, reject) => {
25
+ server.on("error", reject)
26
+ server.on("close", resolve)
27
+ server.close()
28
+ })
29
+ return false
30
+ }
@@ -62,8 +62,8 @@ export const getDOMNodesUsingUrl = (urlToReload) => {
62
62
  }
63
63
  }
64
64
  })
65
- // There is no real need to update a.href because the ressource will be fetched when clicked.
66
- // But in a scenario where the ressource was already visited and is in browser cache, adding
65
+ // There is no real need to update a.href because the resource will be fetched when clicked.
66
+ // But in a scenario where the resource was already visited and is in browser cache, adding
67
67
  // the dynamic query param ensure the cache is invalidated
68
68
  Array.from(document.querySelectorAll("a")).forEach((a) => {
69
69
  visitNodeAttributeAsUrl(a, "href")
@@ -13,7 +13,7 @@ export const jsenvPluginAutoreloadClient = () => {
13
13
 
14
14
  return {
15
15
  name: "jsenv:autoreload_client",
16
- appliesDuring: { dev: true, test: false },
16
+ appliesDuring: "dev",
17
17
  transformUrlContent: {
18
18
  html: (htmlUrlInfo, context) => {
19
19
  const htmlAst = parseHtmlString(htmlUrlInfo.content)
@@ -6,7 +6,7 @@ export const jsenvPluginAutoreloadServer = ({
6
6
  }) => {
7
7
  return {
8
8
  name: "jsenv:autoreload_server",
9
- appliesDuring: { dev: true, test: false },
9
+ appliesDuring: "dev",
10
10
  serverEvents: {
11
11
  reload: ({ sendServerEvent, rootDirectoryUrl, urlGraph }) => {
12
12
  const formatUrlForClient = (url) => {
@@ -140,7 +140,7 @@ export const jsenvPluginAutoreloadServer = ({
140
140
  const cause = `following files are no longer referenced: ${prunedUrlInfos.map(
141
141
  (prunedUrlInfo) => formatUrlForClient(prunedUrlInfo.url),
142
142
  )}`
143
- // now check if we can hot update the main ressource
143
+ // now check if we can hot update the main resource
144
144
  // then if we can hot update all dependencies
145
145
  if (mainHotUpdate.declined) {
146
146
  notifyDeclined({
@@ -179,7 +179,7 @@ export const jsenvPluginAutoreloadServer = ({
179
179
  },
180
180
  },
181
181
  serve: (request, { rootDirectoryUrl, urlGraph }) => {
182
- if (request.ressource === "/__graph__") {
182
+ if (request.pathname === "/__graph__") {
183
183
  const graphJson = JSON.stringify(urlGraph.toJSON(rootDirectoryUrl))
184
184
  return {
185
185
  status: 200,
@@ -1,7 +1,7 @@
1
1
  export const jsenvPluginHmr = () => {
2
2
  return {
3
3
  name: "jsenv:hmr",
4
- appliesDuring: { dev: true, test: false },
4
+ appliesDuring: "dev",
5
5
  redirectUrl: (reference) => {
6
6
  const urlObject = new URL(reference.url)
7
7
  if (!urlObject.searchParams.has("hmr")) {
@@ -11,7 +11,7 @@ export const jsenvPluginExplorer = ({ groups }) => {
11
11
  name: "jsenv:explorer",
12
12
  appliesDuring: "dev",
13
13
  serve: async (request, { rootDirectoryUrl }) => {
14
- if (request.ressource !== "/") {
14
+ if (request.pathname !== "/") {
15
15
  return null
16
16
  }
17
17
  const associationsForExplorable = {}
@@ -154,13 +154,13 @@ export const formatError = (
154
154
  }
155
155
  }
156
156
  if (urlSite.line !== undefined) {
157
- let ressourceToFetch = `/__get_code_frame__/${formatUrlWithLineAndColumn(
157
+ let resourceToFetch = `/__get_code_frame__/${formatUrlWithLineAndColumn(
158
158
  urlSite,
159
159
  )}`
160
160
  if (!Error.captureStackTrace) {
161
- ressourceToFetch += `?remap`
161
+ resourceToFetch += `?remap`
162
162
  }
163
- const response = await window.fetch(ressourceToFetch)
163
+ const response = await window.fetch(resourceToFetch)
164
164
  const codeFrame = await response.text()
165
165
  return {
166
166
  codeFrame: formatErrorText({ message: codeFrame }),