@jsenv/core 23.1.2 → 23.2.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 (85) hide show
  1. package/dist/jsenv_browser_system.js +36 -99
  2. package/dist/jsenv_browser_system.js.map +12 -21
  3. package/dist/jsenv_compile_proxy.js +18 -82
  4. package/dist/jsenv_compile_proxy.js.map +11 -21
  5. package/dist/jsenv_exploring_index.js +127 -274
  6. package/dist/jsenv_exploring_index.js.map +76 -90
  7. package/dist/jsenv_exploring_redirector.js +21 -89
  8. package/dist/jsenv_exploring_redirector.js.map +13 -25
  9. package/dist/jsenv_toolbar.js +81 -149
  10. package/dist/jsenv_toolbar.js.map +50 -61
  11. package/dist/jsenv_toolbar_injector.js +185 -231
  12. package/dist/jsenv_toolbar_injector.js.map +30 -42
  13. package/{LICENSE → license} +0 -0
  14. package/package.json +9 -11
  15. package/src/abort/abortable.js +172 -0
  16. package/src/abort/callback_list.js +64 -0
  17. package/src/abort/callback_race.js +34 -0
  18. package/src/abort/cleaner.js +22 -0
  19. package/src/abort/main.js +32 -0
  20. package/src/abort/process_teardown_events.js +59 -0
  21. package/src/buildProject.js +132 -123
  22. package/src/execute.js +108 -107
  23. package/src/executeTestPlan.js +107 -125
  24. package/src/importUsingChildProcess.js +2 -1
  25. package/src/internal/browser-launcher/executeHtmlFile.js +33 -12
  26. package/src/internal/browser-utils/fetch-browser.js +4 -29
  27. package/src/internal/browser-utils/fetchUsingXHR.js +5 -7
  28. package/src/internal/building/buildUsingRollup.js +60 -24
  29. package/src/internal/building/createJsenvRollupPlugin.js +13 -31
  30. package/src/internal/building/ressource_builder.js +3 -6
  31. package/src/internal/building/sourcemap_loader.js +4 -5
  32. package/src/internal/building/url_fetcher.js +2 -5
  33. package/src/internal/building/url_loader.js +3 -6
  34. package/src/internal/compiling/compileFile.js +1 -2
  35. package/src/internal/compiling/createCompiledFileService.js +10 -10
  36. package/src/internal/compiling/jsenvCompilerForHtml.js +21 -7
  37. package/src/internal/compiling/jsenvCompilerForJavaScript.js +2 -0
  38. package/src/internal/compiling/startCompileServer.js +82 -134
  39. package/src/internal/executing/coverage/generateCoverageJsonFile.js +20 -3
  40. package/src/internal/executing/coverage/relativeUrlToEmptyCoverage.js +19 -30
  41. package/src/internal/executing/coverage/reportToCoverage.js +44 -24
  42. package/src/internal/executing/coverage/v8CoverageFromNodeV8Directory.js +2 -15
  43. package/src/internal/executing/createSummaryLog.js +50 -37
  44. package/src/internal/executing/executeConcurrently.js +89 -47
  45. package/src/internal/executing/executePlan.js +33 -7
  46. package/src/internal/executing/executionLogs.js +25 -28
  47. package/src/internal/executing/execution_colors.js +15 -0
  48. package/src/internal/executing/generateExecutionSteps.js +3 -2
  49. package/src/internal/executing/launchAndExecute.js +213 -257
  50. package/src/internal/exploring/fetchExploringJson.js +3 -4
  51. package/src/internal/fetchUrl.js +6 -2
  52. package/src/internal/logs/log_style.js +16 -28
  53. package/src/internal/logs/msAsDuration.js +1 -1
  54. package/src/internal/node-launcher/createChildProcessOptions.js +4 -5
  55. package/src/internal/node-launcher/createControllableNodeProcess.js +117 -229
  56. package/src/internal/node-launcher/kill_process_tree.js +76 -0
  57. package/src/internal/node-launcher/nodeControllableFile.mjs +16 -10
  58. package/src/internal/{promise_track_race.js → promise_race.js} +2 -2
  59. package/src/internal/runtime/s.js +25 -24
  60. package/src/internal/toolbar/toolbar.html +157 -61
  61. package/src/internal/toolbar/toolbar.injector.js +8 -0
  62. package/src/internal/toolbar/util/animation.js +3 -7
  63. package/src/internal/toolbar/util/fetching.js +1 -30
  64. package/src/jsenvServiceWorkerFinalizer.js +1 -2
  65. package/src/launchBrowser.js +131 -127
  66. package/src/launchNode.js +29 -17
  67. package/src/playwright_browser_versions.js +3 -3
  68. package/src/requireUsingChildProcess.js +2 -1
  69. package/src/signal/signal.js +65 -0
  70. package/src/startExploring.js +71 -71
  71. package/src/internal/executeJsenvAsyncFunction.js +0 -34
  72. package/src/internal/toolbar/animation/toolbar-movie-icon.svg +0 -15
  73. package/src/internal/toolbar/compilation/flask.svg +0 -7
  74. package/src/internal/toolbar/compilation/info.svg +0 -9
  75. package/src/internal/toolbar/compilation/loupe.svg +0 -11
  76. package/src/internal/toolbar/compilation/toolbar_compilation.svg +0 -11
  77. package/src/internal/toolbar/eventsource/toolbar-power-icon.svg +0 -10
  78. package/src/internal/toolbar/eventsource/toolbar-power-off-icon.svg +0 -10
  79. package/src/internal/toolbar/responsive/toolbar-dots-icon.svg +0 -10
  80. package/src/internal/toolbar/settings/toolbar-settings-icon.svg +0 -9
  81. package/src/internal/toolbar/theme/toolbar-palette-icon.svg +0 -10
  82. package/src/internal/toolbar/toolbar-cross-icon.svg +0 -10
  83. package/src/internal/toolbar/toolbar-loading-icon.svg +0 -102
  84. package/src/internal/toolbar/toolbar-notif-icon.svg +0 -9
  85. package/src/internal/trackRessources.js +0 -23
@@ -1,14 +1,7 @@
1
- import {
2
- createCancellationToken,
3
- createOperation,
4
- createStoppableOperation,
5
- createCancellationSource,
6
- composeCancellationToken,
7
- errorToCancelReason,
8
- } from "@jsenv/cancellation"
9
1
  import { createLogger, createDetailedMessage } from "@jsenv/logger"
10
2
 
11
- import { promiseTrackRace } from "../promise_track_race.js"
3
+ import { Abortable } from "@jsenv/core/src/abort/main.js"
4
+ import { raceCallbacks } from "../../abort/callback_race.js"
12
5
  import { composeIstanbulCoverages } from "./coverage/composeIstanbulCoverages.js"
13
6
 
14
7
  const TIMING_BEFORE_EXECUTION = "before-execution"
@@ -16,8 +9,8 @@ const TIMING_DURING_EXECUTION = "during-execution"
16
9
  const TIMING_AFTER_EXECUTION = "after-execution"
17
10
 
18
11
  export const launchAndExecute = async ({
12
+ signal = new AbortController().signal,
19
13
  launchAndExecuteLogLevel,
20
- cancellationToken = createCancellationToken(),
21
14
 
22
15
  runtime,
23
16
  runtimeParams,
@@ -39,7 +32,7 @@ export const launchAndExecute = async ({
39
32
  // however unit test will pass true because they want to move on
40
33
  stopAfterExecute = false,
41
34
  stopAfterExecuteReason = "stop after execute",
42
- // when launch returns { disconnected, gracefulStop, stop }
35
+ // when launch returns { stoppedSignal, gracefulStop, stop }
43
36
  // the launched runtime have that amount of ms for disconnected to resolve
44
37
  // before we call stop
45
38
  gracefulStopAllocatedMs = 4000,
@@ -51,7 +44,6 @@ export const launchAndExecute = async ({
51
44
  // by default throw on error after execution
52
45
  throw error
53
46
  },
54
- runtimeDisconnectCallback = () => {},
55
47
 
56
48
  coverageV8MergeConflictIsExpected,
57
49
  } = {}) => {
@@ -68,6 +60,29 @@ export const launchAndExecute = async ({
68
60
 
69
61
  let executionResultTransformer = (executionResult) => executionResult
70
62
 
63
+ const launchAndExecuteOperation = Abortable.fromSignal(signal)
64
+
65
+ const hasAllocatedMs =
66
+ typeof allocatedMs === "number" && allocatedMs !== Infinity
67
+ let timeoutAbortEffect
68
+
69
+ if (hasAllocatedMs) {
70
+ timeoutAbortEffect = Abortable.timeout(
71
+ launchAndExecuteOperation,
72
+ // FIXME: if allocatedMs is veryyyyyy big
73
+ // setTimeout may be called immediatly
74
+ // in that case we should just throw that the number is too big
75
+ allocatedMs,
76
+ )
77
+ executionResultTransformer = composeTransformer(
78
+ executionResultTransformer,
79
+ (executionResult) => {
80
+ timeoutAbortEffect.cleanup()
81
+ return executionResult
82
+ },
83
+ )
84
+ }
85
+
71
86
  if (measureDuration) {
72
87
  const startMs = Date.now()
73
88
  executionResultTransformer = composeTransformer(
@@ -166,7 +181,7 @@ export const launchAndExecute = async ({
166
181
  executionResultTransformer = composeTransformer(
167
182
  executionResultTransformer,
168
183
  (executionResult) => {
169
- const { coverage, indirectCoverage } = executionResult
184
+ const { coverage = {}, indirectCoverage } = executionResult
170
185
  if (indirectCoverage) {
171
186
  executionResult.coverage = composeIstanbulCoverages(
172
187
  [coverage, indirectCoverage],
@@ -191,274 +206,199 @@ export const launchAndExecute = async ({
191
206
  )
192
207
  }
193
208
 
194
- let executionResult
195
- const executionParams = {
196
- logger,
197
- cancellationToken,
209
+ if (stopAfterExecute) {
210
+ executionResultTransformer = composeTransformer(
211
+ executionResultTransformer,
212
+ async (executionResult) => {
213
+ // if there is an error while cleaning (stopping the runtime)
214
+ // the execution is considered as failed
215
+ try {
216
+ await launchAndExecuteOperation.cleaner.clean(stopAfterExecuteReason)
217
+ return executionResult
218
+ } catch (e) {
219
+ return executionResultTransformer(
220
+ createErroredExecutionResult({
221
+ error: e,
222
+ }),
223
+ )
224
+ }
225
+ },
226
+ )
227
+ }
198
228
 
199
- runtime,
200
- runtimeParams: {
229
+ try {
230
+ const runtimeLabel = `${runtime.name}/${runtime.version}`
231
+ logger.debug(`launch ${runtimeLabel} to execute something in it`)
232
+
233
+ Abortable.throwIfAborted(launchAndExecuteOperation)
234
+ const launchReturnValue = await runtime.launch({
235
+ signal: launchAndExecuteOperation.signal,
236
+ logger,
237
+ stopAfterExecute,
201
238
  measurePerformance,
202
239
  collectPerformance,
203
240
  ...runtimeParams,
204
- },
205
- executeParams,
206
-
207
- stopAfterExecute,
208
- stopAfterExecuteReason,
209
- gracefulStopAllocatedMs,
210
- runtimeConsoleCallback,
211
- runtimeErrorAfterExecutionCallback,
212
- runtimeDisconnectCallback,
213
- runtimeStartedCallback,
214
- runtimeStoppedCallback,
215
- }
216
- const hasAllocatedMs =
217
- typeof allocatedMs === "number" && allocatedMs !== Infinity
218
- if (hasAllocatedMs) {
219
- const TIMEOUT_CANCEL_REASON = "timeout"
220
-
221
- const timeoutCancellationSource = createCancellationSource()
222
-
223
- const id = setTimeout(() => {
224
- // here if allocatedMs is very big
225
- // setTimeout may be called immediatly
226
- // in that case we should just throw that hte number is too big
227
- timeoutCancellationSource.cancel(TIMEOUT_CANCEL_REASON)
228
- }, allocatedMs)
229
- const timeoutCancel = () => clearTimeout(id)
230
-
231
- cancellationToken.register(timeoutCancel)
232
-
233
- const externalOrTimeoutCancellationToken = composeCancellationToken(
234
- cancellationToken,
235
- timeoutCancellationSource.token,
236
- )
237
-
238
- try {
239
- executionResult = await computeExecutionResult({
240
- ...executionParams,
241
- cancellationToken: externalOrTimeoutCancellationToken,
241
+ })
242
+ validateLaunchReturnValue(launchReturnValue)
243
+ launchAndExecuteOperation.cleaner.addCallback(async (reason) => {
244
+ await stopRuntime({
245
+ logger,
246
+ runtimeLabel,
247
+ launchReturnValue,
248
+ gracefulStopAllocatedMs,
249
+ reason,
242
250
  })
243
- timeoutCancel()
244
- } catch (e) {
245
- if (errorToCancelReason(e) === TIMEOUT_CANCEL_REASON) {
246
- executionResult = createTimedoutExecutionResult()
247
- } else {
248
- throw e
249
- }
250
- }
251
- } else {
252
- executionResult = await computeExecutionResult(executionParams)
253
- }
254
-
255
- return executionResultTransformer(executionResult)
256
- }
251
+ })
252
+
253
+ logger.debug(createDetailedMessage(`${runtimeLabel}: runtime launched`))
254
+ runtimeStartedCallback()
255
+
256
+ logger.debug(`${runtimeLabel}: start execution`)
257
+ const {
258
+ errorSignal,
259
+ outputSignal,
260
+ stoppedSignal,
261
+ execute,
262
+ finalizeExecutionResult = (executionResult) => executionResult,
263
+ } = launchReturnValue
264
+ executionResultTransformer = composeTransformer(
265
+ executionResultTransformer,
266
+ finalizeExecutionResult,
267
+ )
268
+ outputSignal.addCallback(runtimeConsoleCallback)
269
+
270
+ let timing = TIMING_BEFORE_EXECUTION
271
+ stoppedSignal.addCallback(() => {
272
+ logger.debug(`${runtimeLabel}: runtime stopped ${timing}`)
273
+ runtimeStoppedCallback()
274
+ })
275
+
276
+ const winnerPromise = new Promise((resolve, reject) => {
277
+ raceCallbacks(
278
+ {
279
+ aborted: (cb) => {
280
+ launchAndExecuteOperation.signal.addEventListener("abort", cb)
281
+ return () => {
282
+ launchAndExecuteOperation.signal.removeEventListener("abort", cb)
283
+ }
284
+ },
285
+ error: (cb) => {
286
+ return errorSignal.addCallback(cb)
287
+ },
288
+ stopped: (cb) => {
289
+ return stoppedSignal.addCallback(cb)
290
+ },
291
+ executed: (cb) => {
292
+ timing = TIMING_DURING_EXECUTION
293
+ const executed = execute({
294
+ signal: launchAndExecuteOperation.signal,
295
+ ...executeParams,
296
+ })
297
+ executed.then(cb, reject)
298
+ },
299
+ },
300
+ resolve,
301
+ )
302
+ })
257
303
 
258
- const composeCallback = (previousCallback, callback) => {
259
- return (...args) => {
260
- previousCallback(...args)
261
- return callback(...args)
262
- }
263
- }
304
+ Abortable.throwIfAborted(launchAndExecuteOperation)
264
305
 
265
- const composeTransformer = (previousTransformer, transformer) => {
266
- return (value) => {
267
- const transformedValue = previousTransformer(value)
268
- return transformer(transformedValue)
269
- }
270
- }
306
+ const winner = await winnerPromise
271
307
 
272
- const computeExecutionResult = async ({
273
- logger,
274
- cancellationToken,
308
+ if (winner.name === "aborted") {
309
+ Abortable.throwIfAborted(launchAndExecuteOperation)
310
+ }
275
311
 
276
- runtime,
277
- runtimeParams,
278
- executeParams,
312
+ if (winner.name === "error") {
313
+ return executionResultTransformer(
314
+ createErroredExecutionResult({
315
+ error: winner.data,
316
+ }),
317
+ )
318
+ }
279
319
 
280
- stopAfterExecute,
281
- stopAfterExecuteReason,
282
- gracefulStopAllocatedMs,
283
- runtimeStartedCallback,
284
- runtimeStoppedCallback,
285
- runtimeConsoleCallback,
286
- runtimeErrorAfterExecutionCallback,
287
- runtimeDisconnectCallback,
288
- }) => {
289
- const runtimeLabel = `${runtime.name}/${runtime.version}`
320
+ if (winner.name === "stopped") {
321
+ return executionResultTransformer(
322
+ createErroredExecutionResult({
323
+ error: new Error(`runtime stopped during execution`),
324
+ }),
325
+ )
326
+ }
290
327
 
291
- logger.debug(`launch ${runtimeLabel} to execute something in it`)
328
+ timing = TIMING_AFTER_EXECUTION
292
329
 
293
- const launchOperation = createStoppableOperation({
294
- cancellationToken,
295
- start: async () => {
296
- const value = await runtime.launch({
297
- logger,
298
- cancellationToken,
299
- stopAfterExecute,
300
- ...runtimeParams,
330
+ if (!stopAfterExecute) {
331
+ // when the process is still alive
332
+ // we want to catch error to notify runtimeErrorAfterExecutionCallback
333
+ // and throw that error by default
334
+ errorSignal.addCallback((error) => {
335
+ runtimeErrorAfterExecutionCallback(error)
301
336
  })
302
- runtimeStartedCallback()
303
- return value
304
- },
305
- stop: async ({ gracefulStop, stop }, reason) => {
306
- // external code can cancel using cancellationToken at any time.
307
- // it is important to keep the code inside this stop function because once cancelled
308
- // all code after the operation won't execute because it will be rejected with
309
- // the cancellation error
310
-
311
- let stoppedGracefully
312
-
313
- if (gracefulStop && gracefulStopAllocatedMs) {
314
- logger.debug(
315
- `${runtimeLabel}: runtime.gracefulStop() because ${reason}`,
316
- )
317
-
318
- const gracefulStopPromise = (async () => {
319
- await gracefulStop({ reason })
320
- return true
321
- })()
322
-
323
- const stopPromise = (async () => {
324
- stoppedGracefully = await new Promise(async (resolve) => {
325
- const timeoutId = setTimeout(() => {
326
- resolve(false)
327
- }, gracefulStopAllocatedMs)
328
- try {
329
- await gracefulStopPromise
330
- resolve(true)
331
- } finally {
332
- clearTimeout(timeoutId)
333
- }
334
- })
335
- if (stoppedGracefully) {
336
- return stoppedGracefully
337
- }
338
-
339
- logger.debug(
340
- `${runtimeLabel}: runtime.stop() because gracefulStop still pending after ${gracefulStopAllocatedMs}ms`,
341
- )
342
- await stop({ reason, gracefulFailed: true })
343
- return false
344
- })()
337
+ }
345
338
 
346
- stoppedGracefully = await Promise.race([
347
- gracefulStopPromise,
348
- stopPromise,
349
- ])
350
- } else {
351
- await stop({ reason, gracefulFailed: false })
352
- stoppedGracefully = false
353
- }
339
+ const executeResult = winner.data
340
+ const { status } = executeResult
354
341
 
342
+ if (status === "errored") {
343
+ // debug log level because this error happens during execution
344
+ // there is no need to log it.
345
+ // the code will know the execution errored because it receives
346
+ // an errored execution result
355
347
  logger.debug(
356
- `${runtimeLabel}: runtime stopped${
357
- stoppedGracefully ? " gracefully" : ""
358
- }`,
348
+ createDetailedMessage(`error ${TIMING_DURING_EXECUTION}`, {
349
+ ["error stack"]: executeResult.error.stack,
350
+ ["execute params"]: JSON.stringify(executeParams, null, " "),
351
+ ["runtime"]: runtime,
352
+ }),
359
353
  )
360
- runtimeStoppedCallback({ stoppedGracefully })
361
- },
362
- })
363
-
364
- const launchReturnValue = await launchOperation
365
- validateLaunchReturnValue(launchReturnValue)
366
- const {
367
- execute,
368
- disconnected,
369
- registerErrorCallback = () => {},
370
- registerConsoleCallback = () => {},
371
- finalizeExecutionResult = (executionResult) => executionResult,
372
- } = launchReturnValue
373
-
374
- logger.debug(createDetailedMessage(`${runtimeLabel}: runtime launched.`))
375
-
376
- logger.debug(`${runtimeLabel}: start execution.`)
377
- registerConsoleCallback(runtimeConsoleCallback)
378
-
379
- const executeOperation = createOperation({
380
- cancellationToken,
381
- start: async () => {
382
- let timing = TIMING_BEFORE_EXECUTION
383
-
384
- disconnected.then(() => {
385
- logger.debug(`${runtimeLabel}: runtime disconnected ${timing}.`)
386
- runtimeDisconnectCallback({ timing })
387
- })
388
-
389
- const executed = execute(executeParams)
390
-
391
- timing = TIMING_DURING_EXECUTION
392
-
393
- const raceResult = await promiseTrackRace([disconnected, executed])
394
- timing = TIMING_AFTER_EXECUTION
395
-
396
- if (raceResult.winner === disconnected) {
397
- return createDisconnectedExecutionResult()
398
- }
399
-
400
- if (stopAfterExecute) {
401
- // if there is an error while stopping the runtine
402
- // the execution is considered as failed
403
- try {
404
- await launchOperation.stop(stopAfterExecuteReason)
405
- } catch (e) {
406
- return finalizeExecutionResult(
407
- createErroredExecutionResult({
408
- error: e,
409
- }),
410
- )
411
- }
412
- } else {
413
- // when the process is still alive
414
- // we want to catch error to notify runtimeErrorAfterExecutionCallback
415
- // and throw that error by default
416
- registerErrorCallback((error) => {
417
- runtimeErrorAfterExecutionCallback(error)
418
- })
419
- }
420
-
421
- const executionResult = raceResult.value
422
- const { status } = executionResult
423
-
424
- if (status === "errored") {
425
- // debug log level because this error happens during execution
426
- // there is no need to log it.
427
- // the code will know the execution errored because it receives
428
- // an errored execution result
429
- logger.debug(
430
- createDetailedMessage(`error ${TIMING_DURING_EXECUTION}.`, {
431
- ["error stack"]: executionResult.error.stack,
432
- ["execute params"]: JSON.stringify(executeParams, null, " "),
433
- ["runtime"]: runtime,
434
- }),
435
- )
436
- return finalizeExecutionResult(
437
- createErroredExecutionResult(executionResult),
438
- )
439
- }
440
-
441
- logger.debug(`${runtimeLabel}: execution completed.`)
442
- return finalizeExecutionResult(
443
- createCompletedExecutionResult(executionResult),
354
+ return executionResultTransformer(
355
+ createErroredExecutionResult(executeResult),
444
356
  )
445
- },
446
- })
357
+ }
447
358
 
448
- const executionResult = await executeOperation
359
+ logger.debug(`${runtimeLabel}: execution completed`)
360
+ return executionResultTransformer(
361
+ createCompletedExecutionResult(executeResult),
362
+ )
363
+ } catch (e) {
364
+ if (e.name === "AbortError") {
365
+ if (timeoutAbortEffect && timeoutAbortEffect.signal.aborted) {
366
+ const executionResult = createTimedoutExecutionResult()
367
+ return executionResultTransformer(executionResult)
368
+ }
369
+ const executionResult = createAbortedExecutionResult()
370
+ return executionResultTransformer(executionResult)
371
+ }
372
+ throw e
373
+ }
374
+ }
449
375
 
450
- return executionResult
376
+ const stopRuntime = async ({
377
+ logger,
378
+ runtimeLabel,
379
+ launchReturnValue,
380
+ gracefulStopAllocatedMs,
381
+ reason,
382
+ }) => {
383
+ const { stop } = launchReturnValue
384
+ logger.debug(`${runtimeLabel}: stop() because ${reason}`)
385
+ const { graceful } = await stop({ reason, gracefulStopAllocatedMs })
386
+ if (graceful) {
387
+ logger.debug(`${runtimeLabel}: runtime stopped gracefully`)
388
+ } else {
389
+ logger.debug(`${runtimeLabel}: runtime stopped`)
390
+ }
451
391
  }
452
392
 
453
- const createTimedoutExecutionResult = () => {
393
+ const createAbortedExecutionResult = () => {
454
394
  return {
455
- status: "timedout",
395
+ status: "aborted",
456
396
  }
457
397
  }
458
398
 
459
- const createDisconnectedExecutionResult = () => {
399
+ const createTimedoutExecutionResult = () => {
460
400
  return {
461
- status: "disconnected",
401
+ status: "timedout",
462
402
  }
463
403
  }
464
404
 
@@ -488,6 +428,20 @@ const normalizeNamespace = (namespace) => {
488
428
  return normalized
489
429
  }
490
430
 
431
+ const composeCallback = (previousCallback, callback) => {
432
+ return (...args) => {
433
+ previousCallback(...args)
434
+ return callback(...args)
435
+ }
436
+ }
437
+
438
+ const composeTransformer = (previousTransformer, transformer) => {
439
+ return async (value) => {
440
+ const transformedValue = await previousTransformer(value)
441
+ return transformer(transformedValue)
442
+ }
443
+ }
444
+
491
445
  const validateLaunchReturnValue = (launchReturnValue) => {
492
446
  if (launchReturnValue === null) {
493
447
  throw new Error(`launch must return an object, got null`)
@@ -502,8 +456,10 @@ const validateLaunchReturnValue = (launchReturnValue) => {
502
456
  throw new Error(`launch must return an execute function, got ${execute}`)
503
457
  }
504
458
 
505
- const { disconnected } = launchReturnValue
506
- if (!disconnected || typeof disconnected.then !== "function") {
507
- throw new Error(`launch must return a disconnected promise, got ${execute}`)
459
+ const { stoppedSignal } = launchReturnValue
460
+ if (!stoppedSignal) {
461
+ throw new Error(
462
+ `launch must return a stoppedSignal object, got ${stoppedSignal}`,
463
+ )
508
464
  }
509
465
  }
@@ -1,16 +1,15 @@
1
1
  import { createDetailedMessage } from "@jsenv/logger"
2
- import { isCancelError } from "@jsenv/cancellation/main.browser.js"
3
2
 
4
3
  import { fetchJson } from "../browser-utils/fetchJson.js"
5
4
 
6
- export const fetchExploringJson = async ({ cancellationToken } = {}) => {
5
+ export const fetchExploringJson = async ({ signal } = {}) => {
7
6
  try {
8
7
  const exploringInfo = await fetchJson("/.jsenv/exploring.json", {
9
- cancellationToken,
8
+ signal,
10
9
  })
11
10
  return exploringInfo
12
11
  } catch (e) {
13
- if (isCancelError(e)) {
12
+ if (signal && signal.aborted && e.name === "AbortError") {
14
13
  throw e
15
14
  }
16
15
  throw new Error(
@@ -1,5 +1,6 @@
1
1
  import { globalAgent } from "node:https"
2
- import { fetchUrl as serverFetchUrl, headersToObject } from "@jsenv/server"
2
+ import { fetchUrl as serverFetchUrl } from "@jsenv/server"
3
+ import { headersToObject } from "@jsenv/server/src/internal/headersToObject.js"
3
4
 
4
5
  // ideally we should only pass this to the fetch below
5
6
  globalAgent.options.rejectUnauthorized = false
@@ -8,7 +9,10 @@ export const fetchUrl = async (
8
9
  url,
9
10
  { ignoreHttpsError = true, ...rest } = {},
10
11
  ) => {
11
- const response = await serverFetchUrl(url, { ignoreHttpsError, ...rest })
12
+ const response = await serverFetchUrl(url, {
13
+ ignoreHttpsError,
14
+ ...rest,
15
+ })
12
16
 
13
17
  return {
14
18
  url: response.url,
@@ -16,37 +16,25 @@ if (process.env.GITHUB_WORKFLOW) {
16
16
  }
17
17
  }
18
18
 
19
- const ansiStyles = {
20
- red: { open: 31, close: 39 },
21
- green: { open: 32, close: 39 },
22
- yellow: { open: 33, close: 39 },
23
- blue: { open: 34, close: 39 },
24
- magenta: { open: 35, close: 39 },
25
- grey: { open: 39, close: 39 },
26
- }
27
-
28
- export const ANSI_RED = ansiStyles.red
29
- export const ANSI_GREEN = ansiStyles.green
30
- export const ANSI_YELLOW = ansiStyles.yellow
31
- export const ANSI_BLUE = ansiStyles.blue
32
- export const ANSI_MAGENTA = ansiStyles.magenta
33
- export const ANSI_GREY = ansiStyles.grey
34
-
19
+ // https://github.com/Marak/colors.js/blob/master/lib/styles.js
20
+ export const ANSI_RED = "\x1b[31m"
21
+ export const ANSI_GREEN = "\x1b[32m"
22
+ export const ANSI_YELLOW = "\x1b[33m"
23
+ export const ANSI_BLUE = "\x1b[34m"
24
+ export const ANSI_MAGENTA = "\x1b[35m"
25
+ export const ANSI_GREY = "\x1b[90m"
35
26
  export const ANSI_RESET = "\x1b[0m"
36
27
 
37
28
  export const setANSIColor = canUseColors
38
- ? (text, ansiColor) =>
39
- `\x1b[${ansiColor.open}m${text}\x1b[${ansiColor.close}m`
29
+ ? (text, ANSI_COLOR) => `${ANSI_COLOR}${text}${ANSI_RESET}`
40
30
  : (text) => text
41
31
 
42
- export const commandSignDefault = canUseUnicode ? `❯` : `>`
43
- export const okSignDefault = canUseUnicode ? `✔` : `√`
44
- export const failureSignDefault = canUseUnicode ? `✖` : `×`
45
- export const infoSignDefault = canUseUnicode ? `ℹ` : `i`
46
- export const warningSignDefault = canUseUnicode ? `⚠` : `‼`
32
+ export const commandSignColorLess = canUseUnicode ? `❯` : `>`
33
+ export const okSignColorLess = canUseUnicode ? `✔` : `√`
34
+ export const failureSignColorLess = canUseUnicode ? `✖` : `×`
47
35
 
48
- export const commandSign = setANSIColor(commandSignDefault, ANSI_GREY) // ANSI_MAGENTA)
49
- export const okSign = setANSIColor(okSignDefault, ANSI_GREEN)
50
- export const failureSign = setANSIColor(failureSignDefault, ANSI_RED)
51
- export const infoSign = setANSIColor(infoSignDefault, ANSI_BLUE)
52
- export const warningSign = setANSIColor(warningSignDefault, ANSI_YELLOW)
36
+ export const commandSign = setANSIColor(commandSignColorLess, ANSI_GREY) // ANSI_MAGENTA)
37
+ export const okSign = setANSIColor(okSignColorLess, ANSI_GREEN)
38
+ export const failureSign = setANSIColor(failureSignColorLess, ANSI_RED)
39
+ export const infoSign = setANSIColor(canUseUnicode ? `ℹ` : `i`, ANSI_BLUE)
40
+ export const warningSign = setANSIColor(canUseUnicode ? `⚠` : `‼`, ANSI_YELLOW)
@@ -5,7 +5,7 @@ const humanizeDuration = require("humanize-duration")
5
5
  export const msAsDuration = (metricValue) => {
6
6
  return humanizeDuration(metricValue, {
7
7
  largest: 2,
8
- maxDecimalPoints: metricValue < 1 ? 4 : metricValue < 1000 ? 3 : 2,
8
+ maxDecimalPoints: metricValue < 0.1 ? 3 : metricValue < 1000 ? 2 : 1,
9
9
  // units: ["s"]
10
10
  })
11
11
  }