@jsenv/core 23.2.2 → 23.3.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.
Files changed (34) hide show
  1. package/{license → LICENSE} +0 -0
  2. package/package.json +13 -14
  3. package/src/buildProject.js +12 -13
  4. package/src/execute.js +92 -93
  5. package/src/internal/browser-launcher/executeHtmlFile.js +6 -7
  6. package/src/internal/building/buildUsingRollup.js +3 -4
  7. package/src/internal/building/build_logs.js +7 -6
  8. package/src/internal/building/createJsenvRollupPlugin.js +9 -14
  9. package/src/internal/building/url_trace.js +3 -4
  10. package/src/internal/compiling/createCompiledFileService.js +8 -5
  11. package/src/internal/compiling/startCompileServer.js +55 -46
  12. package/src/internal/executing/coverage/relativeUrlToEmptyCoverage.js +2 -3
  13. package/src/internal/executing/createSummaryLog.js +12 -14
  14. package/src/internal/executing/executeConcurrently.js +7 -5
  15. package/src/internal/executing/executePlan.js +80 -80
  16. package/src/internal/executing/executionLogs.js +14 -18
  17. package/src/internal/executing/execution_colors.js +6 -12
  18. package/src/internal/executing/launchAndExecute.js +125 -145
  19. package/src/internal/node-launcher/createControllableNodeProcess.js +26 -23
  20. package/src/launchBrowser.js +64 -61
  21. package/src/launchNode.js +6 -6
  22. package/src/startExploring.js +2 -17
  23. package/src/abort/abortable.js +0 -172
  24. package/src/abort/callback_list.js +0 -64
  25. package/src/abort/callback_race.js +0 -34
  26. package/src/abort/cleaner.js +0 -22
  27. package/src/abort/main.js +0 -32
  28. package/src/abort/process_teardown_events.js +0 -59
  29. package/src/internal/createCallbackList.js +0 -21
  30. package/src/internal/executing/logUtils.js +0 -30
  31. package/src/internal/executing/writeLog.js +0 -106
  32. package/src/internal/executing/writeLog.test-manual.js +0 -62
  33. package/src/internal/logs/log_style.js +0 -40
  34. package/src/signal/signal.js +0 -65
@@ -1,12 +1,14 @@
1
1
  // https://github.com/microsoft/playwright/blob/master/docs/api.md
2
2
 
3
3
  import { createDetailedMessage } from "@jsenv/logger"
4
-
5
4
  import {
6
- Abortable,
5
+ Abort,
6
+ createCallbackListNotifiedOnce,
7
+ createCallbackList,
7
8
  raceProcessTeardownEvents,
8
- } from "@jsenv/core/src/abort/main.js"
9
- import { createSignal } from "@jsenv/core/src/signal/signal.js"
9
+ } from "@jsenv/abort"
10
+ import { memoize } from "@jsenv/filesystem"
11
+
10
12
  import { fetchUrl } from "./internal/fetchUrl.js"
11
13
  import { validateResponse } from "./internal/response_validation.js"
12
14
  import { trackPageToNotify } from "./internal/browser-launcher/trackPageToNotify.js"
@@ -45,7 +47,9 @@ chromiumRuntime.launch = async ({
45
47
  stopOnExit = true,
46
48
  share = false,
47
49
  }) => {
48
- const launchBrowserOperation = Abortable.fromSignal(signal)
50
+ const launchBrowserOperation = Abort.startOperation()
51
+ launchBrowserOperation.addAbortSignal(signal)
52
+
49
53
  const sharingToken = share
50
54
  ? chromiumSharing.getSharingToken({
51
55
  chromiumExecutablePath,
@@ -54,9 +58,7 @@ chromiumRuntime.launch = async ({
54
58
  debugPort,
55
59
  })
56
60
  : chromiumSharing.getUniqueSharingToken()
57
-
58
61
  if (!sharingToken.isUsed()) {
59
- Abortable.throwIfAborted(launchBrowserOperation)
60
62
  const { chromium } = await import("playwright")
61
63
  const launchOperation = launchBrowser("chromium", {
62
64
  browserClass: chromium,
@@ -77,10 +79,9 @@ chromiumRuntime.launch = async ({
77
79
  sharingToken.setSharedValue(launchOperation)
78
80
  }
79
81
 
80
- const [launchOperation, stopUsingBrowser] = sharingToken.useSharedValue()
81
- launchBrowserOperation.cleaner.addCallback(stopUsingBrowser)
82
-
83
- const browser = await launchOperation
82
+ const [browserPromise, stopUsingBrowser] = sharingToken.useSharedValue()
83
+ launchBrowserOperation.addEndCallback(stopUsingBrowser)
84
+ const browser = await browserPromise
84
85
 
85
86
  if (debug) {
86
87
  // https://github.com/puppeteer/puppeteer/blob/v2.0.0/docs/api.md#browserwsendpoint
@@ -105,7 +106,6 @@ chromiumRuntime.launch = async ({
105
106
  }
106
107
 
107
108
  const browserHooks = browserToRuntimeHooks(browser, {
108
- launchBrowserOperation,
109
109
  browserServerLogLevel,
110
110
 
111
111
  projectDirectoryUrl,
@@ -158,13 +158,13 @@ firefoxRuntime.launch = async ({
158
158
  stopOnExit = true,
159
159
  share = false,
160
160
  }) => {
161
- const launchBrowserOperation = Abortable.fromSignal(signal)
161
+ const launchBrowserOperation = Abort.startOperation()
162
+ launchBrowserOperation.addAbortSignal(signal)
163
+
162
164
  const sharingToken = share
163
165
  ? firefoxSharing.getSharingToken({ firefoxExecutablePath, headless })
164
166
  : firefoxSharing.getUniqueSharingToken()
165
-
166
167
  if (!sharingToken.isUsed()) {
167
- Abortable.throwIfAborted(launchBrowserOperation)
168
168
  const { firefox } = await import("playwright")
169
169
  const launchOperation = launchBrowser("firefox", {
170
170
  browserClass: firefox,
@@ -179,10 +179,9 @@ firefoxRuntime.launch = async ({
179
179
  sharingToken.setSharedValue(launchOperation)
180
180
  }
181
181
 
182
- const [launchOperation, stopUsingBrowser] = sharingToken.useSharedValue()
183
- launchBrowserOperation.cleaner.addCallback(stopUsingBrowser)
184
-
185
- const browser = await launchOperation
182
+ const [browserPromise, stopUsingBrowser] = sharingToken.useSharedValue()
183
+ launchBrowserOperation.addEndCallback(stopUsingBrowser)
184
+ const browser = await browserPromise
186
185
 
187
186
  const browserHooks = browserToRuntimeHooks(browser, {
188
187
  launchBrowserOperation,
@@ -237,13 +236,14 @@ webkitRuntime.launch = async ({
237
236
  stopOnExit = true,
238
237
  share = false,
239
238
  }) => {
240
- const launchBrowserOperation = Abortable.fromSignal(signal)
239
+ const launchBrowserOperation = Abort.startOperation()
240
+ launchBrowserOperation.addAbortSignal(signal)
241
+
241
242
  const sharingToken = share
242
243
  ? webkitSharing.getSharingToken({ webkitExecutablePath, headless })
243
244
  : webkitSharing.getUniqueSharingToken()
244
245
 
245
246
  if (!sharingToken.isUsed()) {
246
- Abortable.throwIfAborted(launchBrowserOperation)
247
247
  const { webkit } = await import("playwright")
248
248
  const launchOperation = launchBrowser("webkit", {
249
249
  browserClass: webkit,
@@ -257,10 +257,9 @@ webkitRuntime.launch = async ({
257
257
  sharingToken.setSharedValue(launchOperation)
258
258
  }
259
259
 
260
- const [launchOperation, stopUsingBrowser] = sharingToken.useSharedValue()
261
- launchBrowserOperation.cleaner.addCallback(stopUsingBrowser)
262
-
263
- const browser = await launchOperation
260
+ const [browserPromise, stopUsingBrowser] = sharingToken.useSharedValue()
261
+ launchBrowserOperation.addEndCallback(stopUsingBrowser)
262
+ const browser = await browserPromise
264
263
 
265
264
  const browserHooks = browserToRuntimeHooks(browser, {
266
265
  launchBrowserOperation,
@@ -314,8 +313,8 @@ const launchBrowser = async (
314
313
  { launchBrowserOperation, browserClass, options, stopOnExit },
315
314
  ) => {
316
315
  if (stopOnExit) {
317
- Abortable.effect(launchBrowserOperation, (cb) =>
318
- raceProcessTeardownEvents(
316
+ launchBrowserOperation.addAbortSource((abort) => {
317
+ return raceProcessTeardownEvents(
319
318
  {
320
319
  SIGHUP: true,
321
320
  SIGTERM: true,
@@ -323,9 +322,9 @@ const launchBrowser = async (
323
322
  beforeExit: true,
324
323
  exit: true,
325
324
  },
326
- cb,
327
- ),
328
- )
325
+ abort,
326
+ )
327
+ })
329
328
  }
330
329
 
331
330
  try {
@@ -337,19 +336,16 @@ const launchBrowser = async (
337
336
  handleSIGTERM: false,
338
337
  handleSIGHUP: false,
339
338
  })
340
- launchBrowserOperation.cleaner.addCallback(async () => {
341
- await stopBrowser(browser)
342
- })
343
- if (launchBrowserOperation.signal.aborted) {
344
- await launchBrowserOperation.cleaner.clean()
345
- Abortable.throwIfAborted(launchBrowserOperation)
346
- }
339
+ launchBrowserOperation.throwIfAborted()
347
340
  return browser
348
341
  } catch (e) {
349
342
  if (launchBrowserOperation.signal.aborted && isTargetClosedError(e)) {
350
- return e
343
+ // rethrow the abort error
344
+ launchBrowserOperation.throwIfAborted()
351
345
  }
352
346
  throw e
347
+ } finally {
348
+ await launchBrowserOperation.end()
353
349
  }
354
350
  }
355
351
 
@@ -375,8 +371,6 @@ const stopBrowser = async (browser) => {
375
371
  const browserToRuntimeHooks = (
376
372
  browser,
377
373
  {
378
- launchBrowserOperation,
379
-
380
374
  projectDirectoryUrl,
381
375
  compileServerOrigin,
382
376
  outDirectoryRelativeUrl,
@@ -391,26 +385,40 @@ const browserToRuntimeHooks = (
391
385
  transformErrorHook = (error) => error,
392
386
  },
393
387
  ) => {
394
- const stoppedSignal = createSignal({ once: true })
388
+ const stopCallbackList = createCallbackListNotifiedOnce()
389
+ const stoppedCallbackList = createCallbackListNotifiedOnce()
390
+ const stop = memoize(async (reason) => {
391
+ await stopCallbackList.notify({ reason })
392
+ stoppedCallbackList.notify({ reason })
393
+ return { graceful: false }
394
+ })
395
+
395
396
  // https://github.com/GoogleChrome/puppeteer/blob/v1.4.0/docs/api.md#event-disconnected
396
- browser.on("disconnected", stoppedSignal.emit)
397
+ browser.on("disconnected", () => {
398
+ stop()
399
+ })
400
+
401
+ stopCallbackList.add(async () => {
402
+ await stopBrowser(browser)
403
+ })
397
404
 
398
- const errorSignal = createSignal()
405
+ const errorCallbackList = createCallbackList()
399
406
 
400
- const outputSignal = createSignal()
407
+ const outputCallbackList = createCallbackList()
401
408
 
402
409
  const execute = async ({
403
410
  signal,
404
411
  fileRelativeUrl,
405
412
  ignoreHTTPSErrors = true, // we mostly use self signed certificates during tests
406
413
  }) => {
407
- const executeOperation = Abortable.fromSignal(signal)
408
- Abortable.throwIfAborted(executeOperation)
414
+ const executeOperation = Abort.startOperation()
415
+ executeOperation.addAbortSignal(signal)
416
+ executeOperation.throwIfAborted()
409
417
  // open a tab to execute to the file
410
418
  const browserContext = await browser.newContext({ ignoreHTTPSErrors })
411
- Abortable.throwIfAborted(executeOperation)
419
+ executeOperation.throwIfAborted()
412
420
  const page = await browserContext.newPage()
413
- launchBrowserOperation.cleaner.addCallback(async () => {
421
+ executeOperation.addEndCallback(async () => {
414
422
  try {
415
423
  await browserContext.close()
416
424
  } catch (e) {
@@ -425,15 +433,15 @@ const browserToRuntimeHooks = (
425
433
  onError: (error) => {
426
434
  error = transformErrorHook(error)
427
435
  if (!ignoreErrorHook(error)) {
428
- errorSignal.emit(error)
436
+ errorCallbackList.notify(error)
429
437
  }
430
438
  },
431
- onConsole: outputSignal.emit,
439
+ onConsole: outputCallbackList.notify,
432
440
  })
433
- launchBrowserOperation.cleaner.addCallback(stopTrackingToNotify)
441
+ stoppedCallbackList.add(stopTrackingToNotify)
434
442
 
435
443
  const result = await executeHtmlFile(fileRelativeUrl, {
436
- launchBrowserOperation,
444
+ executeOperation,
437
445
 
438
446
  projectDirectoryUrl,
439
447
  compileServerOrigin,
@@ -451,17 +459,12 @@ const browserToRuntimeHooks = (
451
459
  return result
452
460
  }
453
461
 
454
- Abortable.cleanOnAbort(launchBrowserOperation)
455
-
456
462
  return {
457
- stoppedSignal,
458
- errorSignal,
459
- outputSignal,
463
+ stoppedCallbackList,
464
+ errorCallbackList,
465
+ outputCallbackList,
460
466
  execute,
461
- stop: async (reason) => {
462
- await launchBrowserOperation.cleaner.clean(reason)
463
- return { graceful: false }
464
- },
467
+ stop,
465
468
  }
466
469
  }
467
470
 
package/src/launchNode.js CHANGED
@@ -132,9 +132,9 @@ nodeRuntime.launch = async ({
132
132
  const logLevel = loggerToLogLevel(logger)
133
133
  const {
134
134
  execArgv,
135
- stoppedSignal,
136
- errorSignal,
137
- outputSignal,
135
+ stoppedCallbackList,
136
+ errorCallbackList,
137
+ outputCallbackList,
138
138
  stop,
139
139
  requestActionOnChildProcess,
140
140
  } = await createControllableNodeProcess({
@@ -193,9 +193,9 @@ nodeRuntime.launch = async ({
193
193
  // because process.env is very big
194
194
  // env,
195
195
  },
196
- stoppedSignal,
197
- errorSignal,
198
- outputSignal,
196
+ stoppedCallbackList,
197
+ errorCallbackList,
198
+ outputCallbackList,
199
199
  stop,
200
200
  execute,
201
201
  finalizeExecutionResult,
@@ -4,10 +4,6 @@ import {
4
4
  urlToRelativeUrl,
5
5
  } from "@jsenv/filesystem"
6
6
 
7
- import {
8
- Abortable,
9
- raceProcessTeardownEvents,
10
- } from "@jsenv/core/src/abort/main.js"
11
7
  import { jsenvCoreDirectoryUrl } from "./internal/jsenvCoreDirectoryUrl.js"
12
8
  import {
13
9
  assertProjectDirectoryUrl,
@@ -60,18 +56,6 @@ export const startExploring = async ({
60
56
  projectDirectoryUrl = assertProjectDirectoryUrl({ projectDirectoryUrl })
61
57
  await assertProjectDirectoryExists({ projectDirectoryUrl })
62
58
 
63
- const exploringServerOperation = Abortable.fromSignal(signal)
64
- if (handleSIGINT) {
65
- Abortable.effect(exploringServerOperation, (cb) =>
66
- raceProcessTeardownEvents(
67
- {
68
- SIGINT: true,
69
- },
70
- cb,
71
- ),
72
- )
73
- }
74
-
75
59
  const outDirectoryRelativeUrl = computeOutDirectoryRelativeUrl({
76
60
  projectDirectoryUrl,
77
61
  jsenvDirectoryRelativeUrl,
@@ -95,7 +79,8 @@ export const startExploring = async ({
95
79
  })
96
80
 
97
81
  const compileServer = await startCompileServer({
98
- signal: exploringServerOperation.signal,
82
+ signal,
83
+ handleSIGINT,
99
84
  keepProcessAlive,
100
85
 
101
86
  projectDirectoryUrl,
@@ -1,172 +0,0 @@
1
- /*
2
- * https://github.com/whatwg/dom/issues/920
3
- */
4
-
5
- import { createCleaner } from "./cleaner.js"
6
- import { raceCallbacks } from "./callback_race.js"
7
- import { createCallbackList } from "./callback_list.js"
8
-
9
- export const Abortable = {
10
- throwIfAborted: (operation) => {
11
- if (operation.signal.aborted) {
12
- const error = new Error(`The operation was aborted`)
13
- error.name = "AbortError"
14
- error.type = "aborted"
15
- throw error
16
- }
17
- },
18
-
19
- isAbortError: (error) => {
20
- return error.name === "AbortError"
21
- },
22
-
23
- start: () => {
24
- const abortController = new AbortController()
25
- const abort = (value) => abortController.abort(value)
26
- const signal = abortController.signal
27
- const cleaner = createCleaner()
28
-
29
- // abortCallbackList is used to ignore the max listeners warning from Node.js
30
- // this warning is useful but becomes problematic when it's expected
31
- // (a function doing 20 http call in parallel)
32
- // To be 100% sure we don't have memory leak, only Abortable.asyncCallback
33
- // uses abortCallbackList to know when something is aborted
34
- const abortCallbackList = createCallbackList()
35
- signal.onabort = () => {
36
- const callbacks = abortCallbackList.copy()
37
- abortCallbackList.clear()
38
- callbacks.forEach((callback) => {
39
- callback()
40
- })
41
- }
42
- cleaner.addCallback(() => {
43
- abortCallbackList.clear()
44
- })
45
-
46
- const operation = {
47
- abort,
48
- signal,
49
- abortCallbackList,
50
- cleaner,
51
- }
52
-
53
- return operation
54
- },
55
-
56
- fromSignal: (signal) => {
57
- const operation = Abortable.start()
58
- Abortable.followSignal(operation, signal)
59
- return operation
60
- },
61
-
62
- followSignal: (operation, signal, cleanup = cleanupNoop) => {
63
- if (operation.signal.aborted) {
64
- return () => {}
65
- }
66
-
67
- if (signal.aborted) {
68
- operation.abort()
69
- return () => {}
70
- }
71
-
72
- return raceCallbacks(
73
- {
74
- parent_abort: (cb) => {
75
- return operation.abortCallbackList.add(cb)
76
- },
77
- child_abort: (cb) => {
78
- return addEventListener(signal, "abort", cb)
79
- },
80
- cleaned: (cb) => {
81
- return operation.cleaner.addCallback(cb)
82
- },
83
- },
84
- (winner) => {
85
- const raceEffects = {
86
- parent_abort: () => {
87
- // Nothing to do, exists to remove
88
- // - "abort" event listener on parent
89
- // - "abort" event listener on child
90
- cleanup()
91
- },
92
- child_abort: () => {
93
- operation.abort()
94
- },
95
- cleaned: () => {
96
- // Nothing to do, exists to remove
97
- // - "abort" event listener on parent
98
- // - "abort" event listener on child
99
- cleanup()
100
- },
101
- }
102
- raceEffects[winner.name](winner.value)
103
- },
104
- )
105
- },
106
-
107
- effect: (operation, effect) => {
108
- const abortController = new AbortController()
109
- const returnValue = effect((value) => abortController.abort(value))
110
- const cleanup =
111
- typeof returnValue === "function" ? returnValue : cleanupNoop
112
- const signal = abortController.signal
113
-
114
- Abortable.followSignal(operation, signal, cleanup)
115
- return {
116
- signal,
117
- cleanup,
118
- }
119
- },
120
-
121
- timeout: (operation, ms) => {
122
- return Abortable.effect(operation, (abort) => {
123
- const timeoutId = setTimeout(abort, ms)
124
- return () => {
125
- clearTimeout(timeoutId)
126
- }
127
- })
128
- },
129
-
130
- cleanOnAbort: (operation) => {
131
- const removeAbortEventListener = addEventListener(
132
- operation.signal,
133
- "abort",
134
- () => {
135
- removeAbortEventListener()
136
- operation.cleaner.clean("operation aborted")
137
- },
138
- )
139
- return removeAbortEventListener
140
- },
141
-
142
- // Provide a signal to the callback
143
- // this signal won't inherit the current signal max listeners
144
- asyncCallback: async (operation, asyncFunction) => {
145
- Abortable.throwIfAborted(operation)
146
-
147
- const abortController = new AbortController()
148
- const signal = abortController.signal
149
-
150
- const removeOperationAbortCallback = operation.abortCallbackList.add(() => {
151
- abortController.abort()
152
- })
153
-
154
- try {
155
- const value = await asyncFunction(signal)
156
- removeOperationAbortCallback()
157
- return value
158
- } catch (e) {
159
- removeOperationAbortCallback()
160
- throw e
161
- }
162
- },
163
- }
164
-
165
- const cleanupNoop = () => {}
166
-
167
- const addEventListener = (target, eventName, cb) => {
168
- target.addEventListener(eventName, cb)
169
- return () => {
170
- target.removeEventListener(eventName, cb)
171
- }
172
- }
@@ -1,64 +0,0 @@
1
- export const createCallbackList = () => {
2
- let callbacks = []
3
-
4
- const add = (callback) => {
5
- if (typeof callback !== "function") {
6
- throw new Error(`callback must be a function, got ${callback}`)
7
- }
8
-
9
- // don't register twice
10
- const existingCallback = callbacks.find((callbackCandidate) => {
11
- return callbackCandidate === callback
12
- })
13
- if (existingCallback) {
14
- if (typeof process.emitWarning === "object") {
15
- process.emitWarning(`Trying to register same callback twice`, {
16
- CODE: "CALLBACK_DUPLICATION",
17
- detail: `It's often the sign that code is executd more than once`,
18
- })
19
- } else {
20
- console.warn(`Trying to add same callback twice`)
21
- }
22
- } else {
23
- callbacks = [...callbacks, callback]
24
- }
25
-
26
- return () => {
27
- remove(callback)
28
- }
29
- }
30
-
31
- const remove = (callback) => {
32
- callbacks = arrayWithout(callbacks, callback)
33
- }
34
-
35
- const clear = () => {
36
- callbacks = []
37
- }
38
-
39
- const copy = () => {
40
- return callbacks.slice()
41
- }
42
-
43
- return {
44
- add,
45
- remove,
46
- clear,
47
- copy,
48
- }
49
- }
50
-
51
- const arrayWithout = (array, item) => {
52
- if (array.length === 0) return array
53
- const arrayWithoutItem = []
54
- let i = 0
55
- while (i < array.length) {
56
- const value = array[i]
57
- i++
58
- if (value === item) {
59
- continue
60
- }
61
- arrayWithoutItem.push(value)
62
- }
63
- return arrayWithoutItem
64
- }
@@ -1,34 +0,0 @@
1
- /*
2
- * See callback_race.md
3
- */
4
-
5
- export const raceCallbacks = (raceDescription, winnerCallback) => {
6
- const cleanCallbacks = []
7
- let done = false
8
-
9
- const cleanup = () => {
10
- const cleanCallbacksCopy = cleanCallbacks.slice()
11
- cleanCallbacks.length = 0
12
- cleanCallbacksCopy.forEach((clean) => {
13
- clean()
14
- })
15
- }
16
-
17
- Object.keys(raceDescription).forEach((candidateName) => {
18
- const register = raceDescription[candidateName]
19
- const returnValue = register((data) => {
20
- if (done) return
21
- done = true
22
- cleanup()
23
- winnerCallback({
24
- name: candidateName,
25
- data,
26
- })
27
- })
28
- if (typeof returnValue === "function") {
29
- cleanCallbacks.push(returnValue)
30
- }
31
- })
32
-
33
- return cleanup
34
- }
@@ -1,22 +0,0 @@
1
- import { createCallbackList } from "./callback_list.js"
2
-
3
- export const createCleaner = () => {
4
- const callbackList = createCallbackList()
5
-
6
- const addCallback = (callback) => {
7
- return callbackList.add(callback)
8
- }
9
-
10
- const clean = async (reason) => {
11
- const callbacks = callbackList.copy()
12
- callbackList.clear()
13
-
14
- await Promise.all(
15
- callbacks.map(async (callback) => {
16
- await callback(reason)
17
- }),
18
- )
19
- }
20
-
21
- return { addCallback, clean }
22
- }
package/src/abort/main.js DELETED
@@ -1,32 +0,0 @@
1
- /*
2
- * When starting an http server there is two distinct things
3
- * that code may want to do:
4
- * 1. Abort the server while it's starting
5
- * 2. Stop server onces its started
6
- *
7
- * This can be achieved with the following code where
8
- * server is aborted if it takes more than 1s to start
9
- * and immediatly stopped once started
10
- *
11
- * const abortController = new AbortController()
12
- * setTimeout(() => { abortController.abort() }, 1000)
13
- * const server = await startServer({
14
- * abortSignal: abortController.signal
15
- * })
16
- * await server.stop()
17
- *
18
- * In order to implement this kind of API two helpers are exported
19
- * here:
20
- * 1. "Abort" which can be used to throw an abort error
21
- * while server is starting
22
- * 2. "Cleanup" which can be used to track how to cleanup all the things
23
- * done to start the server
24
- *
25
- * Same concepts could be reused when spwaning a child process, a worker, etc..
26
- *
27
- */
28
-
29
- export { Abortable } from "./abortable.js"
30
-
31
- // when will be a package this should be a Node.js export only
32
- export { raceProcessTeardownEvents } from "./process_teardown_events.js"