sxy-test-runner 2.5.3 → 2.5.5

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 (55) hide show
  1. package/AGENTS.md +47 -21
  2. package/dist/cli/lib/agentReport.d.ts +1 -0
  3. package/dist/cli/lib/agentReport.js +3 -0
  4. package/dist/cli/lib/agentReport.js.map +1 -1
  5. package/dist/cli/lib/buildDependencyTree.d.ts +1 -2
  6. package/dist/cli/lib/buildDependencyTree.js +25 -23
  7. package/dist/cli/lib/buildDependencyTree.js.map +1 -1
  8. package/dist/cli/lib/buildDependencyTrees.d.ts +1 -2
  9. package/dist/cli/lib/buildDependencyTrees.js +18 -16
  10. package/dist/cli/lib/buildDependencyTrees.js.map +1 -1
  11. package/dist/cli/lib/esmGraphReload.d.ts +5 -0
  12. package/dist/cli/lib/esmGraphReload.js +24 -0
  13. package/dist/cli/lib/esmGraphReload.js.map +1 -0
  14. package/dist/cli/lib/esmTreeReload.d.ts +4 -0
  15. package/dist/cli/lib/esmTreeReload.js +62 -0
  16. package/dist/cli/lib/esmTreeReload.js.map +1 -0
  17. package/dist/cli/lib/handleUserInput.d.ts +2 -2
  18. package/dist/cli/lib/handleUserInput.js +13 -6
  19. package/dist/cli/lib/handleUserInput.js.map +1 -1
  20. package/dist/cli/lib/listenToUser.d.ts +2 -2
  21. package/dist/cli/lib/listenToUser.js.map +1 -1
  22. package/dist/cli/lib/loadTestFile.d.ts +0 -1
  23. package/dist/cli/lib/loadTestFile.js +23 -8
  24. package/dist/cli/lib/loadTestFile.js.map +1 -1
  25. package/dist/cli/lib/makeDependencyGraph.d.ts +10 -0
  26. package/dist/cli/lib/makeDependencyGraph.js +210 -0
  27. package/dist/cli/lib/makeDependencyGraph.js.map +1 -0
  28. package/dist/cli/lib/reRunManager.js +4 -6
  29. package/dist/cli/lib/reRunManager.js.map +1 -1
  30. package/dist/cli/lib/runTests.js +7 -2
  31. package/dist/cli/lib/runTests.js.map +1 -1
  32. package/dist/cli/lib/showTestResultsSummary.d.ts +1 -1
  33. package/dist/cli/lib/showTestResultsSummary.js +5 -1
  34. package/dist/cli/lib/showTestResultsSummary.js.map +1 -1
  35. package/dist/cli/lib/statusFile.js +20 -1
  36. package/dist/cli/lib/statusFile.js.map +1 -1
  37. package/dist/cli/lib/watchFilesAndRunTestsNodeWatch.d.ts +3 -2
  38. package/dist/cli/lib/watchFilesAndRunTestsNodeWatch.js +24 -48
  39. package/dist/cli/lib/watchFilesAndRunTestsNodeWatch.js.map +1 -1
  40. package/dist/cli/watch.js +25 -12
  41. package/dist/cli/watch.js.map +1 -1
  42. package/dist/describe.js +5 -3
  43. package/dist/describe.js.map +1 -1
  44. package/dist/meta.js +2 -1
  45. package/dist/meta.js.map +1 -1
  46. package/dist/registration.d.ts +4 -0
  47. package/dist/registration.js +34 -0
  48. package/dist/registration.js.map +1 -0
  49. package/dist/types.d.ts +8 -0
  50. package/dist/types.js.map +1 -1
  51. package/package.json +11 -6
  52. package/readme.md +16 -123
  53. package/dist/packages/esmReload.d.ts +0 -11
  54. package/dist/packages/esmReload.js +0 -43
  55. package/dist/packages/esmReload.js.map +0 -1
package/AGENTS.md CHANGED
@@ -138,12 +138,11 @@ filters select no runnable tests, `once` exits `22` - `21` means no test file ma
138
138
  stdout - nothing else is printed, setup progress included. `--status-file` is watch-only,
139
139
  writing the latest run's result to a file. Both are covered under "Watch mode" below.
140
140
 
141
- Describe and test filters run after the selected test files have loaded. The runner gives
142
- each test file a fresh ESM instance and propagates it through the file's static dependency
143
- graph, bypassing the ordinary ESM cache. Loading many files and filtering their registered
144
- describes or tests afterward can therefore be much slower than file filtering. Prefer
145
- `--filter` when a file glob can narrow the run, then use `--filter-describe` or
146
- `--filter-it` only for further narrowing inside those files.
141
+ Describe and test filters run after the selected test files have loaded, so every selected
142
+ file and its module graph is still imported and evaluated. Loading many files and filtering
143
+ their registered describes or tests afterward can therefore be much slower than file
144
+ filtering. Prefer `--filter` when a file glob can narrow the run, then use
145
+ `--filter-describe` or `--filter-it` only for further narrowing inside those files.
147
146
 
148
147
  `--fail-fast` (`-x`) stops the run at the first failure - whether that is a failing test, a
149
148
  describe that threw, or a test file that would not load. It is a `once` flag with no config
@@ -179,14 +178,23 @@ forms exclude exactly the same files, so it costs nothing to prefer the shorter
179
178
 
180
179
  ## Test lifecycle and data flow
181
180
 
182
- All test files run in one Node.js process. A test file is imported with a fresh
183
- `?sxyt-instance=N` query, and the runner's ESM resolver propagates that instance through its
184
- static dependency graph. Importing the file registers its describe blocks in
185
- `global.__sxy_test_runner__`; execution happens afterward.
181
+ All test files run in one Node.js process. Importing a test file registers its describe
182
+ blocks; execution happens afterward.
186
183
 
187
- A module whose filename contains the explicit `._cached_.js` marker uses Node's ordinary
188
- process-wide module cache instead. Its static dependencies are cached with it, allowing
189
- explicitly shared state across test files:
184
+ Modules are shared between test files, through Node's ordinary module cache: a module
185
+ imported by several test files is evaluated once, and its state carries from one file to the
186
+ next. Tests should set up any shared state they depend on rather than assume a fresh module.
187
+ How modules are reloaded in watch mode is covered under "Watch mode" below.
188
+
189
+ A describe belongs to the test file whose top level made it, directly or through a function
190
+ it calls - a shared suite in a helper module registers in whichever test file calls it. A
191
+ test file imported by another test file still runs its own describes when it is loaded
192
+ itself, but they are not run again as part of the file importing it, and a module that calls
193
+ `describe` as soon as it is imported registers nothing.
194
+
195
+ A module whose filename contains the explicit `._cached_.js` marker is never reloaded, in
196
+ any mode. Its static dependencies are cached with it, allowing explicitly shared state that
197
+ lasts for the whole process:
190
198
 
191
199
  ```js
192
200
  import { database } from './fixtures/database._cached_.js'
@@ -333,13 +341,31 @@ for two things: startup stops paying for dependency analysis, which is the slowe
333
341
  it on a large suite, and the blind spots below stop mattering, because nothing is being
334
342
  predicted. On a small or fast suite it is often the better setting.
335
343
 
344
+ The same setting decides how a rerun reloads modules. Every test file in a rerun is
345
+ evaluated again, so its describes register afresh. Beyond that:
346
+
347
+ - With dependency evaluation on, only a changed file and the files that import it, directly
348
+ or not, are loaded again; everything else stays shared from earlier runs. A rerun with
349
+ nothing changed reloads only the test files themselves.
350
+ - With it off, each test file in a rerun gets a fresh copy of its whole static module graph.
351
+
352
+ In both, packages under `node_modules` are loaded once and never reloaded. A linked package
353
+ (a workspace or `npm link` dependency) resolves to its real path outside `node_modules`, so
354
+ it reloads like the project's own files.
355
+
336
356
  Important limitations:
337
357
 
338
- - Dynamic imports are not found by dependency analysis, so a test reached only that way is
339
- not rerun when its dependency changes. `watch.dependencyEvaluation: false` avoids this.
340
- - All reruns still share one long-lived process.
341
- - A fresh ESM instance reloads the test's static module graph, but unrelated global state
342
- and external resources remain the test author's responsibility.
358
+ - Dependency analysis finds `import()` only when its path is a plain string literal. A path
359
+ computed at runtime (`import(name)`, `import('./' + name)`), or written as a template
360
+ literal, is not found, so a test reached only that way is not rerun when its dependency
361
+ changes. `watch.dependencyEvaluation: false` avoids this.
362
+ - With dependency evaluation on, a module is only reloaded when the watcher sees it change
363
+ or sees a change to something it imports. One it cannot connect - a file outside
364
+ `watch.watchFiles` such as a `.json` fixture, or one reached only through a computed
365
+ `import()` - keeps its first loaded copy for the rest of the session. Restart watch mode,
366
+ or set `watch.dependencyEvaluation: false`, to pick up such a change.
367
+ - All reruns still share one long-lived process. Global state and external resources are
368
+ never reset between runs and remain the test author's responsibility.
343
369
  - Modules imported through a `._cached_.*` boundary also remain loaded for the life of the
344
370
  process. Keep mutable access sequential or provide application-level synchronization,
345
371
  and arrange explicit cleanup for resources such as servers and database connections.
@@ -469,9 +495,9 @@ maps it to a test. Either half can miss:
469
495
  all**. The stream simply stays quiet, and the previous `done` remains the last word while
470
496
  silently going stale.
471
497
  - Even for a watched file, the changed-to-test mapping is the static import graph, so it
472
- misses dynamic imports and anything reached through a `._cached_.*` boundary. A test file
473
- that was neither changed nor already failing is not re-run, so a break in it never reaches
474
- `failing`. Setting `watch.dependencyEvaluation: false` removes this gap - every watched
498
+ misses imports whose path is computed at runtime and anything reached through a
499
+ `._cached_.*` boundary. A test file that was neither changed nor already failing is not
500
+ re-run, so a break in it never reaches `failing`. Setting `watch.dependencyEvaluation: false` removes this gap - every watched
475
501
  change then reruns everything, and those runs report `covers=all`.
476
502
 
477
503
  So `failing=0` means "nothing is known to be broken", not "everything passes", and silence
@@ -8,6 +8,7 @@ export declare function agentEnabled(config: FinalConfig): boolean;
8
8
  export declare function agentInit(enabled: boolean): void;
9
9
  export declare function agentFound(config: FinalConfig, files: number): void;
10
10
  export declare function agentSetRunReason(reason: RunReason): void;
11
+ export declare function currentRunReason(): RunReason;
11
12
  export declare function agentRunStart(config: FinalConfig, files: number): number;
12
13
  export declare function agentFailure(config: FinalConfig, run: number, entry: FailureEntry): void;
13
14
  export declare function agentDone(config: FinalConfig, run: number, code: StatusCode, description: string, summary: TestsResultsSummary | null, durationMs: number, failingFiles: number): void;
@@ -40,6 +40,9 @@ export function agentFound(config, files) {
40
40
  export function agentSetRunReason(reason) {
41
41
  nextRunReason = reason;
42
42
  }
43
+ export function currentRunReason() {
44
+ return nextRunReason;
45
+ }
43
46
  // claims the next run number and announces the run, so a reader knows work is in flight
44
47
  // before any result arrives
45
48
  export function agentRunStart(config, files) {
@@ -1 +1 @@
1
- {"version":3,"file":"agentReport.js","sourceRoot":"","sources":["../../../src/cli/lib/agentReport.ts"],"names":[],"mappings":"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","sourcesContent":["\nimport type { FinalConfig } from '../../types.js'\nimport type { FailureEntry } from './failureEntries.js'\nimport type { RunType } from './reRunManager.js'\nimport type { TestsResultsSummary } from './runTests.js'\nimport { out as mainOut } from '../../output.js'\nimport { statusNames, type StatusCode } from './statusFile.js'\n\n\n// Agent mode reports a watch session as a stream of single lines, for a reader tailing the\n// process rather than watching the terminal. Every line is one complete event:\n//\n// [sxyt] <event> | <key>=<value> | <key>=<value>\n//\n// Values are never quoted, so free text is flattened to keep the grammar intact - one event\n// can never span two lines, and a stray `|` can never look like a field boundary.\n\nconst prefix = '[sxyt]'\n\nexport type RunReason = RunType | 'startup' | 'once'\n\nlet runCounter = 0\n// requestRun sets this before handing a run to runTests; the initial run never goes through\n// the queue, so 'startup' is the right default\nlet nextRunReason: RunReason = 'startup'\n\ntype Field = [string, string | number]\n\nfunction emit(event: string, fields: Field[] = []): void {\n mainOut(prefix + ` ${event}` + fields.map(([key, value]) => ` | ${key}=${value}`).join(''))\n}\n\n// newlines would split one event across two lines, and a `|` would read as a field boundary\nfunction flatten(text: string): string {\n return text.replace(/\\s*[\\r\\n]+\\s*/g, ' ').replace(/\\|/g, '/').trim()\n}\n\nexport function agentEnabled(config: FinalConfig): boolean {\n return config.agent\n}\n\n// the process is up, before the config is even loaded - so a slow startup is\n// distinguishable from one that never began. Takes the flag rather than the config for that\n// reason, and resets the counters so repeated in process sessions start from 1.\nexport function agentInit(enabled: boolean): void {\n runCounter = 0\n nextRunReason = 'startup'\n if (!enabled) return\n emit('init', [['pid', process.pid]])\n}\n\nexport function agentFound(config: FinalConfig, files: number): void {\n if (!agentEnabled(config)) return\n emit('found', [['files', files]])\n}\n\nexport function agentSetRunReason(reason: RunReason): void {\n nextRunReason = reason\n}\n\n// claims the next run number and announces the run, so a reader knows work is in flight\n// before any result arrives\nexport function agentRunStart(config: FinalConfig, files: number): number {\n if (!agentEnabled(config)) return 0\n runCounter++\n emit('running', [\n ['n', runCounter],\n ['files', files],\n ['why', nextRunReason],\n ['covers', runScope(config)]\n ])\n return runCounter\n}\n\n// what the run was built from. A reader needs this to know how far the run's own `status`\n// generalises - only a run covering everything can speak for the whole suite.\nfunction runScope(config: FinalConfig): string {\n // known before the run starts: fail fast means it is built to stop early, so it cannot\n // promise to have covered anything beyond the first failure\n if (config.failFast) return 'until-first-failure'\n\n switch (nextRunReason) {\n case 'startup':\n case 'once':\n case 'all': return 'all'\n case 'last': return 'last'\n case 'failed': return 'failing'\n case 'auto': {\n // with dependency evaluation off a change runs the whole suite, so an auto run\n // carries the same weight as a startup one\n if (!config.watch.dependencyEvaluation) return 'all'\n // the reRunFailingTests case is the one worth spelling out: without it a run says\n // nothing about files that were already failing\n return (config.watch.reRunFailingTests) ? 'changed+failing' : 'changed'\n }\n default: return 'changed'\n }\n}\n\n// failures are emitted before the run's done line, so done is a complete end of run marker\nexport function agentFailure(config: FinalConfig, run: number, entry: FailureEntry): void {\n if (!agentEnabled(config)) return\n emit('fail', [\n ['n', run],\n ['file', flatten(entry.file)],\n ...(entry.describe === undefined)\n ? []\n : [['describe', flatten(entry.describe)] as Field],\n ...(entry.test === undefined) ? [] : [['test', flatten(entry.test)] as Field],\n ['error', flatten(entry.error)]\n ])\n}\n\n// `failing` counts the test files still failing across the whole session, not just this\n// run. A watch re-run usually covers only the changed files, so its own tallies can read as\n// a clean pass while the suite is still broken elsewhere.\nexport function agentDone(\n config: FinalConfig,\n run: number,\n code: StatusCode,\n description: string,\n summary: TestsResultsSummary | null,\n durationMs: number,\n failingFiles: number\n): void {\n if (!agentEnabled(config)) return\n emit('done', [\n ['n', run],\n // named, not numbered: `status=failed` needs no lookup table, and cannot be misread\n // as the process exit code the way a bare `code=1` could\n ['status', statusNames[code]],\n ['desc', flatten(description)],\n ...(summary === null) ? [] : [\n ['tests', `${summary.itsPasses}/${summary.itsTotal}`] as Field,\n ['items', `${summary.describesPasses}/${summary.describesTotal}`] as Field,\n ['files', `${summary.passes}/${summary.total}`] as Field\n ],\n ['failing', failingFiles],\n ['ms', durationMs]\n ])\n}\n\nexport function agentWatching(config: FinalConfig, files: number): void {\n if (!agentEnabled(config)) return\n emit('watching', [['files', files]])\n}\n\nexport function agentChange(config: FinalConfig, file: string, event: string): void {\n if (!agentEnabled(config)) return\n emit('change', [['file', flatten(file)], ['event', flatten(event)]])\n}\n\n// agent mode owns stdout, so the ordinary coloured output is routed into a sink\nexport function agentSilentOut(): void {\n // deliberately nothing - the agent lines are the whole stream\n}\n"]}
1
+ {"version":3,"file":"agentReport.js","sourceRoot":"","sources":["../../../src/cli/lib/agentReport.ts"],"names":[],"mappings":"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","sourcesContent":["\nimport type { FinalConfig } from '../../types.js'\nimport type { FailureEntry } from './failureEntries.js'\nimport type { RunType } from './reRunManager.js'\nimport type { TestsResultsSummary } from './runTests.js'\nimport { out as mainOut } from '../../output.js'\nimport { statusNames, type StatusCode } from './statusFile.js'\n\n\n// Agent mode reports a watch session as a stream of single lines, for a reader tailing the\n// process rather than watching the terminal. Every line is one complete event:\n//\n// [sxyt] <event> | <key>=<value> | <key>=<value>\n//\n// Values are never quoted, so free text is flattened to keep the grammar intact - one event\n// can never span two lines, and a stray `|` can never look like a field boundary.\n\nconst prefix = '[sxyt]'\n\nexport type RunReason = RunType | 'startup' | 'once'\n\nlet runCounter = 0\n// requestRun sets this before handing a run to runTests; the initial run never goes through\n// the queue, so 'startup' is the right default\nlet nextRunReason: RunReason = 'startup'\n\ntype Field = [string, string | number]\n\nfunction emit(event: string, fields: Field[] = []): void {\n mainOut(prefix + ` ${event}` + fields.map(([key, value]) => ` | ${key}=${value}`).join(''))\n}\n\n// newlines would split one event across two lines, and a `|` would read as a field boundary\nfunction flatten(text: string): string {\n return text.replace(/\\s*[\\r\\n]+\\s*/g, ' ').replace(/\\|/g, '/').trim()\n}\n\nexport function agentEnabled(config: FinalConfig): boolean {\n return config.agent\n}\n\n// the process is up, before the config is even loaded - so a slow startup is\n// distinguishable from one that never began. Takes the flag rather than the config for that\n// reason, and resets the counters so repeated in process sessions start from 1.\nexport function agentInit(enabled: boolean): void {\n runCounter = 0\n nextRunReason = 'startup'\n if (!enabled) return\n emit('init', [['pid', process.pid]])\n}\n\nexport function agentFound(config: FinalConfig, files: number): void {\n if (!agentEnabled(config)) return\n emit('found', [['files', files]])\n}\n\nexport function agentSetRunReason(reason: RunReason): void {\n nextRunReason = reason\n}\n\nexport function currentRunReason(): RunReason {\n return nextRunReason\n}\n\n// claims the next run number and announces the run, so a reader knows work is in flight\n// before any result arrives\nexport function agentRunStart(config: FinalConfig, files: number): number {\n if (!agentEnabled(config)) return 0\n runCounter++\n emit('running', [\n ['n', runCounter],\n ['files', files],\n ['why', nextRunReason],\n ['covers', runScope(config)]\n ])\n return runCounter\n}\n\n// what the run was built from. A reader needs this to know how far the run's own `status`\n// generalises - only a run covering everything can speak for the whole suite.\nfunction runScope(config: FinalConfig): string {\n // known before the run starts: fail fast means it is built to stop early, so it cannot\n // promise to have covered anything beyond the first failure\n if (config.failFast) return 'until-first-failure'\n\n switch (nextRunReason) {\n case 'startup':\n case 'once':\n case 'all': return 'all'\n case 'last': return 'last'\n case 'failed': return 'failing'\n case 'auto': {\n // with dependency evaluation off a change runs the whole suite, so an auto run\n // carries the same weight as a startup one\n if (!config.watch.dependencyEvaluation) return 'all'\n // the reRunFailingTests case is the one worth spelling out: without it a run says\n // nothing about files that were already failing\n return (config.watch.reRunFailingTests) ? 'changed+failing' : 'changed'\n }\n default: return 'changed'\n }\n}\n\n// failures are emitted before the run's done line, so done is a complete end of run marker\nexport function agentFailure(config: FinalConfig, run: number, entry: FailureEntry): void {\n if (!agentEnabled(config)) return\n emit('fail', [\n ['n', run],\n ['file', flatten(entry.file)],\n ...(entry.describe === undefined)\n ? []\n : [['describe', flatten(entry.describe)] as Field],\n ...(entry.test === undefined) ? [] : [['test', flatten(entry.test)] as Field],\n ['error', flatten(entry.error)]\n ])\n}\n\n// `failing` counts the test files still failing across the whole session, not just this\n// run. A watch re-run usually covers only the changed files, so its own tallies can read as\n// a clean pass while the suite is still broken elsewhere.\nexport function agentDone(\n config: FinalConfig,\n run: number,\n code: StatusCode,\n description: string,\n summary: TestsResultsSummary | null,\n durationMs: number,\n failingFiles: number\n): void {\n if (!agentEnabled(config)) return\n emit('done', [\n ['n', run],\n // named, not numbered: `status=failed` needs no lookup table, and cannot be misread\n // as the process exit code the way a bare `code=1` could\n ['status', statusNames[code]],\n ['desc', flatten(description)],\n ...(summary === null) ? [] : [\n ['tests', `${summary.itsPasses}/${summary.itsTotal}`] as Field,\n ['items', `${summary.describesPasses}/${summary.describesTotal}`] as Field,\n ['files', `${summary.passes}/${summary.total}`] as Field\n ],\n ['failing', failingFiles],\n ['ms', durationMs]\n ])\n}\n\nexport function agentWatching(config: FinalConfig, files: number): void {\n if (!agentEnabled(config)) return\n emit('watching', [['files', files]])\n}\n\nexport function agentChange(config: FinalConfig, file: string, event: string): void {\n if (!agentEnabled(config)) return\n emit('change', [['file', flatten(file)], ['event', flatten(event)]])\n}\n\n// agent mode owns stdout, so the ordinary coloured output is routed into a sink\nexport function agentSilentOut(): void {\n // deliberately nothing - the agent lines are the whole stream\n}\n"]}
@@ -1,3 +1,2 @@
1
- import type { FinalConfig } from '../../types.js';
2
- export declare function buildDependencyTree(config: FinalConfig, filename: string): string[];
1
+ export {};
3
2
  //# sourceMappingURL=buildDependencyTree.d.ts.map
@@ -1,24 +1,26 @@
1
- import dependencyTree from 'dependency-tree';
2
- import { debug } from '../../output.js';
3
- import slash from '../../packages/slash.js';
4
- export function buildDependencyTree(config, filename) {
5
- filename = slash(filename);
6
- const dependencyTreeConfig = {
7
- filename,
8
- isListForm: true,
9
- directory: config.watch.watchFilesBase,
10
- filter: (path) => path.indexOf('node_modules') === -1
11
- };
12
- // isListForm:true makes dependency-tree return a flat string[] at runtime,
13
- // which its shipped types don't model (they only type the tree-object form).
14
- const dt = dependencyTree(dependencyTreeConfig);
15
- // process the results into final format
16
- // (forward slashes and convert full path to rel path)
17
- const cwd = process.cwd();
18
- const processed = dt
19
- .map(file => slash(file).slice(cwd.length + 1))
20
- .filter(file => file !== filename); // remove the current file
21
- debug('found dep tree', processed);
22
- return processed;
23
- }
1
+ // import dependencyTree from 'dependency-tree'
2
+ export {};
3
+ // import type { FinalConfig } from '../../types.js'
4
+ // import { debug } from '../../output.js'
5
+ // import slash from '../../packages/slash.js'
6
+ // export function buildDependencyTree(config: FinalConfig, filename: string): string[] {
7
+ // filename = slash(filename)
8
+ // const dependencyTreeConfig = {
9
+ // filename,
10
+ // isListForm: true,
11
+ // directory: config.watch.watchFilesBase,
12
+ // filter: (path: string) => path.indexOf('node_modules') === -1
13
+ // }
14
+ // // isListForm:true makes dependency-tree return a flat string[] at runtime,
15
+ // // which its shipped types don't model (they only type the tree-object form).
16
+ // const dt = dependencyTree(dependencyTreeConfig) as unknown as string[]
17
+ // // process the results into final format
18
+ // // (forward slashes and convert full path to rel path)
19
+ // const cwd = process.cwd()
20
+ // const processed = dt
21
+ // .map(file => slash(file).slice(cwd.length + 1))
22
+ // .filter(file => file !== filename) // remove the current file
23
+ // debug('found dep tree', processed)
24
+ // return processed
25
+ // }
24
26
  //# sourceMappingURL=buildDependencyTree.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"buildDependencyTree.js","sourceRoot":"","sources":["../../../src/cli/lib/buildDependencyTree.ts"],"names":[],"mappings":"AACA,OAAO,cAAc,MAAM,iBAAiB,CAAA;AAG5C,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AACvC,OAAO,KAAK,MAAM,yBAAyB,CAAA;AAG3C,MAAM,UAAU,mBAAmB,CAAC,MAAmB,EAAE,QAAgB;IACrE,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAA;IAE1B,MAAM,oBAAoB,GAAG;QACzB,QAAQ;QACR,UAAU,EAAE,IAAI;QAChB,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,cAAc;QACtC,MAAM,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;KAChE,CAAA;IAED,2EAA2E;IAC3E,6EAA6E;IAC7E,MAAM,EAAE,GAAG,cAAc,CAAC,oBAAoB,CAAwB,CAAA;IAEtE,wCAAwC;IACxC,sDAAsD;IACtD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAA;IACzB,MAAM,SAAS,GAAG,EAAE;SACf,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;SAC9C,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAA,CAAC,0BAA0B;IAEjE,KAAK,CAAC,gBAAgB,EAAE,SAAS,CAAC,CAAA;IAElC,OAAO,SAAS,CAAA;AACpB,CAAC","sourcesContent":["\nimport dependencyTree from 'dependency-tree'\n\nimport type { FinalConfig } from '../../types.js'\nimport { debug } from '../../output.js'\nimport slash from '../../packages/slash.js'\n\n\nexport function buildDependencyTree(config: FinalConfig, filename: string): string[] {\n filename = slash(filename)\n\n const dependencyTreeConfig = {\n filename,\n isListForm: true,\n directory: config.watch.watchFilesBase,\n filter: (path: string) => path.indexOf('node_modules') === -1\n }\n\n // isListForm:true makes dependency-tree return a flat string[] at runtime,\n // which its shipped types don't model (they only type the tree-object form).\n const dt = dependencyTree(dependencyTreeConfig) as unknown as string[]\n\n // process the results into final format\n // (forward slashes and convert full path to rel path)\n const cwd = process.cwd()\n const processed = dt\n .map(file => slash(file).slice(cwd.length + 1))\n .filter(file => file !== filename) // remove the current file\n\n debug('found dep tree', processed)\n\n return processed\n}\n"]}
1
+ {"version":3,"file":"buildDependencyTree.js","sourceRoot":"","sources":["../../../src/cli/lib/buildDependencyTree.ts"],"names":[],"mappings":"AACA,+CAA+C;;AAE/C,oDAAoD;AACpD,0CAA0C;AAC1C,8CAA8C;AAG9C,yFAAyF;AACzF,iCAAiC;AAEjC,qCAAqC;AACrC,oBAAoB;AACpB,4BAA4B;AAC5B,kDAAkD;AAClD,wEAAwE;AACxE,QAAQ;AAER,kFAAkF;AAClF,oFAAoF;AACpF,6EAA6E;AAE7E,+CAA+C;AAC/C,6DAA6D;AAC7D,gCAAgC;AAChC,2BAA2B;AAC3B,0DAA0D;AAC1D,wEAAwE;AAExE,yCAAyC;AAEzC,uBAAuB;AACvB,IAAI","sourcesContent":["\n// import dependencyTree from 'dependency-tree'\n\n// import type { FinalConfig } from '../../types.js'\n// import { debug } from '../../output.js'\n// import slash from '../../packages/slash.js'\n\n\n// export function buildDependencyTree(config: FinalConfig, filename: string): string[] {\n// filename = slash(filename)\n\n// const dependencyTreeConfig = {\n// filename,\n// isListForm: true,\n// directory: config.watch.watchFilesBase,\n// filter: (path: string) => path.indexOf('node_modules') === -1\n// }\n\n// // isListForm:true makes dependency-tree return a flat string[] at runtime,\n// // which its shipped types don't model (they only type the tree-object form).\n// const dt = dependencyTree(dependencyTreeConfig) as unknown as string[]\n\n// // process the results into final format\n// // (forward slashes and convert full path to rel path)\n// const cwd = process.cwd()\n// const processed = dt\n// .map(file => slash(file).slice(cwd.length + 1))\n// .filter(file => file !== filename) // remove the current file\n\n// debug('found dep tree', processed)\n\n// return processed\n// }\n"]}
@@ -1,3 +1,2 @@
1
- import type { FinalConfig, DependencyTrees } from '../../types.js';
2
- export declare function buildDependencyTrees(config: FinalConfig, testFiles: Set<string>): DependencyTrees;
1
+ export {};
3
2
  //# sourceMappingURL=buildDependencyTrees.d.ts.map
@@ -1,17 +1,19 @@
1
- import { createTimeProfiler } from '../../packages/timeProfiler.js';
2
- import { showTimeProfiling } from '../../config.js';
3
- import { debug } from '../../output.js';
4
- import { buildDependencyTree } from './buildDependencyTree.js';
5
- const { timeProfile } = createTimeProfiler(showTimeProfiling);
6
- export function buildDependencyTrees(config, testFiles) {
7
- return timeProfile('build dependency trees', () => {
8
- const dependencyTrees = {};
9
- for (const testFile of testFiles) {
10
- const dependencyTree = buildDependencyTree(config, testFile);
11
- dependencyTrees[testFile] = dependencyTree;
12
- debug('final dep tree', dependencyTrees[testFile]);
13
- }
14
- return dependencyTrees;
15
- });
16
- }
1
+ // import type { FinalConfig, DependencyTrees } from '../../types.js'
2
+ // import { createTimeProfiler } from '../../packages/timeProfiler.js'
3
+ // import { showTimeProfiling } from '../../config.js'
4
+ // import { debug } from '../../output.js'
5
+ // import { buildDependencyTree } from './buildDependencyTree.js'
6
+ export {};
7
+ // const { timeProfile } = createTimeProfiler(showTimeProfiling)
8
+ // export function buildDependencyTrees(config: FinalConfig, testFiles: Set<string>): DependencyTrees {
9
+ // return timeProfile('build dependency trees', () => {
10
+ // const dependencyTrees: DependencyTrees = {}
11
+ // for (const testFile of testFiles) {
12
+ // const dependencyTree = buildDependencyTree(config, testFile)
13
+ // dependencyTrees[testFile] = dependencyTree
14
+ // debug('final dep tree', dependencyTrees[testFile])
15
+ // }
16
+ // return dependencyTrees
17
+ // })
18
+ // }
17
19
  //# sourceMappingURL=buildDependencyTrees.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"buildDependencyTrees.js","sourceRoot":"","sources":["../../../src/cli/lib/buildDependencyTrees.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAA;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AACnD,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AACvC,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAG9D,MAAM,EAAE,WAAW,EAAE,GAAG,kBAAkB,CAAC,iBAAiB,CAAC,CAAA;AAE7D,MAAM,UAAU,oBAAoB,CAAC,MAAmB,EAAE,SAAsB;IAC5E,OAAO,WAAW,CAAC,wBAAwB,EAAE,GAAG,EAAE;QAC9C,MAAM,eAAe,GAAoB,EAAE,CAAA;QAE3C,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;YAC/B,MAAM,cAAc,GAAG,mBAAmB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;YAC5D,eAAe,CAAC,QAAQ,CAAC,GAAG,cAAc,CAAA;YAC1C,KAAK,CAAC,gBAAgB,EAAE,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAA;QACtD,CAAC;QAED,OAAO,eAAe,CAAA;IAC1B,CAAC,CAAC,CAAA;AACN,CAAC","sourcesContent":["\nimport type { FinalConfig, DependencyTrees } from '../../types.js'\nimport { createTimeProfiler } from '../../packages/timeProfiler.js'\nimport { showTimeProfiling } from '../../config.js'\nimport { debug } from '../../output.js'\nimport { buildDependencyTree } from './buildDependencyTree.js'\n\n\nconst { timeProfile } = createTimeProfiler(showTimeProfiling)\n\nexport function buildDependencyTrees(config: FinalConfig, testFiles: Set<string>): DependencyTrees {\n return timeProfile('build dependency trees', () => {\n const dependencyTrees: DependencyTrees = {}\n\n for (const testFile of testFiles) {\n const dependencyTree = buildDependencyTree(config, testFile)\n dependencyTrees[testFile] = dependencyTree\n debug('final dep tree', dependencyTrees[testFile])\n }\n\n return dependencyTrees\n })\n}\n"]}
1
+ {"version":3,"file":"buildDependencyTrees.js","sourceRoot":"","sources":["../../../src/cli/lib/buildDependencyTrees.ts"],"names":[],"mappings":"AACA,qEAAqE;AACrE,sEAAsE;AACtE,sDAAsD;AACtD,0CAA0C;AAC1C,iEAAiE;;AAGjE,gEAAgE;AAEhE,uGAAuG;AACvG,2DAA2D;AAC3D,sDAAsD;AAEtD,8CAA8C;AAC9C,2EAA2E;AAC3E,yDAAyD;AACzD,iEAAiE;AACjE,YAAY;AAEZ,iCAAiC;AACjC,SAAS;AACT,IAAI","sourcesContent":["\n// import type { FinalConfig, DependencyTrees } from '../../types.js'\n// import { createTimeProfiler } from '../../packages/timeProfiler.js'\n// import { showTimeProfiling } from '../../config.js'\n// import { debug } from '../../output.js'\n// import { buildDependencyTree } from './buildDependencyTree.js'\n\n\n// const { timeProfile } = createTimeProfiler(showTimeProfiling)\n\n// export function buildDependencyTrees(config: FinalConfig, testFiles: Set<string>): DependencyTrees {\n// return timeProfile('build dependency trees', () => {\n// const dependencyTrees: DependencyTrees = {}\n\n// for (const testFile of testFiles) {\n// const dependencyTree = buildDependencyTree(config, testFile)\n// dependencyTrees[testFile] = dependencyTree\n// debug('final dep tree', dependencyTrees[testFile])\n// }\n\n// return dependencyTrees\n// })\n// }\n"]}
@@ -0,0 +1,5 @@
1
+ export type VersionLookup = (file: string) => number | undefined;
2
+ export declare function registerGraphReload(getVersion: VersionLookup): {
3
+ handle: import("module").ModuleHooks;
4
+ };
5
+ //# sourceMappingURL=esmGraphReload.d.ts.map
@@ -0,0 +1,24 @@
1
+ import { registerHooks } from 'node:module';
2
+ import { fileURLToPath } from 'node:url';
3
+ const cachedModulePattern = /\._cached_\.(?:[cm]?js|[cm]?ts|jsx|tsx)$/i;
4
+ export function registerGraphReload(getVersion) {
5
+ const resolve = (specifier, context, nextResolve) => {
6
+ const result = nextResolve(specifier, context);
7
+ if (!result.url.startsWith('file:'))
8
+ return result;
9
+ const url = new URL(result.url);
10
+ if (cachedModulePattern.test(url.pathname))
11
+ return result;
12
+ // packages load once; a linked one resolves to its real path outside node_modules, so still reloads
13
+ if (url.pathname.includes('/node_modules/'))
14
+ return result;
15
+ const version = getVersion(fileURLToPath(url));
16
+ if (version === undefined)
17
+ return result;
18
+ url.searchParams.set('sxyt-v', String(version));
19
+ return { ...result, url: url.href };
20
+ };
21
+ const handle = registerHooks({ resolve });
22
+ return { handle };
23
+ }
24
+ //# sourceMappingURL=esmGraphReload.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"esmGraphReload.js","sourceRoot":"","sources":["../../../src/cli/lib/esmGraphReload.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAwB,MAAM,aAAa,CAAA;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAMxC,MAAM,mBAAmB,GAAG,2CAA2C,CAAA;AAEvE,MAAM,UAAU,mBAAmB,CAAC,UAAyB;IACzD,MAAM,OAAO,GAAoB,CAAC,SAAS,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE;QACjE,MAAM,MAAM,GAAG,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;QAC9C,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC;YAAE,OAAO,MAAM,CAAA;QAElD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QAC/B,IAAI,mBAAmB,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC;YAAE,OAAO,MAAM,CAAA;QACzD,oGAAoG;QACpG,IAAI,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,gBAAgB,CAAC;YAAE,OAAO,MAAM,CAAA;QAE1D,MAAM,OAAO,GAAG,UAAU,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAA;QAC9C,IAAI,OAAO,KAAK,SAAS;YAAE,OAAO,MAAM,CAAA;QAExC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,CAAA;QAC/C,OAAO,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,CAAA;IACvC,CAAC,CAAA;IAED,MAAM,MAAM,GAAG,aAAa,CAAC,EAAE,OAAO,EAAE,CAAC,CAAA;IACzC,OAAO,EAAE,MAAM,EAAE,CAAA;AACrB,CAAC","sourcesContent":["\nimport { registerHooks, type ResolveHookSync } from 'node:module'\nimport { fileURLToPath } from 'node:url'\n\n\n// a module's current version, or undefined to leave it on Node's ordinary module cache\nexport type VersionLookup = (file: string) => number | undefined\n\nconst cachedModulePattern = /\\._cached_\\.(?:[cm]?js|[cm]?ts|jsx|tsx)$/i\n\nexport function registerGraphReload(getVersion: VersionLookup) {\n const resolve: ResolveHookSync = (specifier, context, nextResolve) => {\n const result = nextResolve(specifier, context)\n if (!result.url.startsWith('file:')) return result\n\n const url = new URL(result.url)\n if (cachedModulePattern.test(url.pathname)) return result\n // packages load once; a linked one resolves to its real path outside node_modules, so still reloads\n if (url.pathname.includes('/node_modules/')) return result\n\n const version = getVersion(fileURLToPath(url))\n if (version === undefined) return result\n\n url.searchParams.set('sxyt-v', String(version))\n return { ...result, url: url.href }\n }\n \n const handle = registerHooks({ resolve })\n return { handle }\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import { type ModuleHooks, type ResolveHookSync } from 'node:module';
2
+ export declare const resolve: ResolveHookSync;
3
+ export declare function registerTreeReload(): ModuleHooks;
4
+ //# sourceMappingURL=esmTreeReload.d.ts.map
@@ -0,0 +1,62 @@
1
+ import { isBuiltin, registerHooks } from 'node:module';
2
+ /*
3
+ * Based on esm-reload by Marcel Laverdet and Pierre-Yves Gérardy.
4
+ *
5
+ * ISC License
6
+ *
7
+ * Copyright 2024 Marcel Laverdet & Pierre-Yves Gérardy
8
+ *
9
+ * Permission to use, copy, modify, and/or distribute this software for any
10
+ * purpose with or without fee is hereby granted, provided that the above
11
+ * copyright notice and this permission notice appear in all copies.
12
+ *
13
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20
+ */
21
+ const cachedModulePattern = /\._cached_\.(?:[cm]?js|[cm]?ts|jsx|tsx)$/i;
22
+ let reloadId = 0;
23
+ function isThisModule(url) {
24
+ const candidate = new URL(url);
25
+ const current = new URL(import.meta.url);
26
+ candidate.search = '';
27
+ current.search = '';
28
+ return candidate.href === current.href;
29
+ }
30
+ function isCachedModule(url) {
31
+ return cachedModulePattern.test(url.pathname);
32
+ }
33
+ export const resolve = (specifier, context, nextResolve) => {
34
+ const result = nextResolve(specifier, context);
35
+ if (isThisModule(result.url) || isBuiltin(result.url) || context.parentURL === undefined) {
36
+ return result;
37
+ }
38
+ const url = new URL(result.url);
39
+ // A *._cached_.js/ts module and its dependency graph use Node's ordinary
40
+ // process-wide module cache instead of inheriting the test file instance.
41
+ if (isCachedModule(url))
42
+ return result;
43
+ // packages load once; a linked one resolves to its real path outside node_modules, so still reloads
44
+ if (url.pathname.includes('/node_modules/'))
45
+ return result;
46
+ const parentUrl = new URL(context.parentURL);
47
+ const instance = url.searchParams.get('reload') === ''
48
+ ? `sxy-test-runner-reload-${reloadId++}`
49
+ : parentUrl.searchParams.get('sxyt-instance');
50
+ if (instance === null)
51
+ return result;
52
+ url.searchParams.delete('reload');
53
+ url.searchParams.set('sxyt-instance', instance);
54
+ return {
55
+ ...result,
56
+ url: url.href
57
+ };
58
+ };
59
+ export function registerTreeReload() {
60
+ return registerHooks({ resolve });
61
+ }
62
+ //# sourceMappingURL=esmTreeReload.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"esmTreeReload.js","sourceRoot":"","sources":["../../../src/cli/lib/esmTreeReload.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,aAAa,EAA0C,MAAM,aAAa,CAAA;AAG9F;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,mBAAmB,GAAG,2CAA2C,CAAA;AAEvE,IAAI,QAAQ,GAAG,CAAC,CAAA;AAEhB,SAAS,YAAY,CAAC,GAAW;IAC7B,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAA;IAC9B,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACxC,SAAS,CAAC,MAAM,GAAG,EAAE,CAAA;IACrB,OAAO,CAAC,MAAM,GAAG,EAAE,CAAA;IACnB,OAAO,SAAS,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI,CAAA;AAC1C,CAAC;AAED,SAAS,cAAc,CAAC,GAAQ;IAC5B,OAAO,mBAAmB,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;AACjD,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAoB,CAAC,SAAS,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE;IACxE,MAAM,MAAM,GAAG,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;IAE9C,IAAI,YAAY,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QACvF,OAAO,MAAM,CAAA;IACjB,CAAC;IAED,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;IAE/B,yEAAyE;IACzE,0EAA0E;IAC1E,IAAI,cAAc,CAAC,GAAG,CAAC;QAAE,OAAO,MAAM,CAAA;IACtC,oGAAoG;IACpG,IAAI,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,gBAAgB,CAAC;QAAE,OAAO,MAAM,CAAA;IAE1D,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;IAC5C,MAAM,QAAQ,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,EAAE;QAClD,CAAC,CAAC,0BAA0B,QAAQ,EAAE,EAAE;QACxC,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,GAAG,CAAC,eAAe,CAAC,CAAA;IAEjD,IAAI,QAAQ,KAAK,IAAI;QAAE,OAAO,MAAM,CAAA;IAEpC,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;IACjC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAA;IAE/C,OAAO;QACH,GAAG,MAAM;QACT,GAAG,EAAE,GAAG,CAAC,IAAI;KAChB,CAAA;AACL,CAAC,CAAA;AAED,MAAM,UAAU,kBAAkB;IAC9B,OAAO,aAAa,CAAC,EAAE,OAAO,EAAE,CAAC,CAAA;AACrC,CAAC","sourcesContent":["\nimport { isBuiltin, registerHooks, type ModuleHooks, type ResolveHookSync } from 'node:module'\n\n\n/*\n * Based on esm-reload by Marcel Laverdet and Pierre-Yves Gérardy.\n *\n * ISC License\n *\n * Copyright 2024 Marcel Laverdet & Pierre-Yves Gérardy\n *\n * Permission to use, copy, modify, and/or distribute this software for any\n * purpose with or without fee is hereby granted, provided that the above\n * copyright notice and this permission notice appear in all copies.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\n * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\n * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\n * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\n * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\n * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n */\n\nconst cachedModulePattern = /\\._cached_\\.(?:[cm]?js|[cm]?ts|jsx|tsx)$/i\n\nlet reloadId = 0\n\nfunction isThisModule(url: string): boolean {\n const candidate = new URL(url)\n const current = new URL(import.meta.url)\n candidate.search = ''\n current.search = ''\n return candidate.href === current.href\n}\n\nfunction isCachedModule(url: URL): boolean {\n return cachedModulePattern.test(url.pathname)\n}\n\nexport const resolve: ResolveHookSync = (specifier, context, nextResolve) => {\n const result = nextResolve(specifier, context)\n\n if (isThisModule(result.url) || isBuiltin(result.url) || context.parentURL === undefined) {\n return result\n }\n\n const url = new URL(result.url)\n\n // A *._cached_.js/ts module and its dependency graph use Node's ordinary\n // process-wide module cache instead of inheriting the test file instance.\n if (isCachedModule(url)) return result\n // packages load once; a linked one resolves to its real path outside node_modules, so still reloads\n if (url.pathname.includes('/node_modules/')) return result\n\n const parentUrl = new URL(context.parentURL)\n const instance = url.searchParams.get('reload') === ''\n ? `sxy-test-runner-reload-${reloadId++}`\n : parentUrl.searchParams.get('sxyt-instance')\n\n if (instance === null) return result\n\n url.searchParams.delete('reload')\n url.searchParams.set('sxyt-instance', instance)\n\n return {\n ...result,\n url: url.href\n }\n}\n\nexport function registerTreeReload(): ModuleHooks {\n return registerHooks({ resolve })\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import type { ReRunManager } from './reRunManager.js';
2
- import type { RerunTestsFactory } from './listenToUser.js';
2
+ import type { RerunTestsFunction } from './listenToUser.js';
3
3
  import type { OutFn } from '../../types.js';
4
- export declare function handleUserInput(input: string, reRunManager: ReRunManager, rerunTestsCallback: RerunTestsFactory, customOut?: OutFn): void;
4
+ export declare function handleUserInput(input: string, reRunManager: ReRunManager, rerunTestsCallback: RerunTestsFunction, customOut?: OutFn): void;
5
5
  //# sourceMappingURL=handleUserInput.d.ts.map
@@ -25,28 +25,35 @@ export function handleUserInput(input, reRunManager, rerunTestsCallback, customO
25
25
  //console.log('watchRunState.activeRuns', watchRunState.activeRuns)
26
26
  // if (rerunManager.watchRunState.activeRuns > 0) return
27
27
  let type;
28
- let testFiles;
28
+ let testFilesSet;
29
29
  if (command === 'r' || command === 'l') {
30
30
  type = 'last';
31
- testFiles = reRunManager.state.lastTestFiles;
31
+ testFilesSet = reRunManager.state.lastTestFiles;
32
32
  }
33
33
  else if (command === 'a') {
34
34
  type = 'all';
35
- testFiles = reRunManager.state.allTestFiles;
35
+ testFilesSet = reRunManager.state.allTestFiles;
36
36
  }
37
37
  else if (command === 'f') {
38
38
  type = 'failed';
39
- testFiles = reRunManager.state.failedTestFiles;
39
+ testFilesSet = reRunManager.state.failedTestFiles;
40
40
  }
41
41
  else {
42
42
  return;
43
43
  }
44
44
  //console.log('type', type)
45
45
  //console.log('testFiles', testFiles)
46
- if (testFiles.size === 0) {
46
+ if (testFilesSet.size === 0) {
47
47
  out('No suitable test files to run');
48
48
  return;
49
49
  }
50
- void reRunManager.requestRun(type, rerunTestsCallback(new Set(testFiles))); /// CHECK is it appropriate to copy here?
50
+ void reRunManager.requestRun(type, () => {
51
+ if (testFilesSet.size === 0) {
52
+ out(type + ': No suitable test files to run');
53
+ return Promise.resolve(null);
54
+ }
55
+ return rerunTestsCallback(new Set(testFilesSet));
56
+ });
57
+ //rerunTestsCallback(new Set(testFilesSet))) /// CHECK is it appropriate to copy here?
51
58
  }
52
59
  //# sourceMappingURL=handleUserInput.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"handleUserInput.js","sourceRoot":"","sources":["../../../src/cli/lib/handleUserInput.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,MAAM,yBAAyB,CAAA;AAC3C,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAA;AAGrC,SAAS,gBAAgB,CAAC,KAAuB,EAAE,SAAgB;IAC/D,MAAM,OAAO,GAAG,CAAC,GAAG,KAAK,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,CAAA;IAChD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,SAAS,CAAC,qCAAqC,CAAC,CAAA;QAChD,OAAM;IACV,CAAC;IAED,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC,CAAA;IACvD,MAAM,MAAM,GAAG,IAAI,CAAA;IACnB,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC1B,IAAI,KAAK,CAAC,gBAAgB;YAAE,SAAS,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAA;QACxE,KAAK,MAAM,QAAQ,IAAI,KAAK,CAAC,SAAS;YAAE,SAAS,CAAC,GAAG,MAAM,GAAG,KAAK,CAAC,IAAI,KAAK,GAAG,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAA;IAC/G,CAAC;AACL,CAAC;AAGD,MAAM,UAAU,eAAe,CAC3B,KAAa,EACb,YAA0B,EAC1B,kBAAqC,EACrC,YAAmB,GAAG;IAEtB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;IAE1C,IAAI,OAAO,KAAK,GAAG,EAAE,CAAC;QAClB,gBAAgB,CAAC,YAAY,CAAC,KAAK,EAAE,SAAS,CAAC,CAAA;QAC/C,OAAM;IACV,CAAC;IAED,iCAAiC;IAEjC,mEAAmE;IACnE,wDAAwD;IAExD,IAAI,IAAa,CAAA;IACjB,IAAI,SAAsB,CAAA;IAC1B,IAAI,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,GAAG,EAAE,CAAC;QACrC,IAAI,GAAG,MAAM,CAAA;QACb,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,aAAa,CAAA;IAChD,CAAC;SAAM,IAAI,OAAO,KAAK,GAAG,EAAE,CAAC;QACzB,IAAI,GAAG,KAAK,CAAA;QACZ,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,YAAY,CAAA;IAC/C,CAAC;SAAM,IAAI,OAAO,KAAK,GAAG,EAAE,CAAC;QACzB,IAAI,GAAG,QAAQ,CAAA;QACf,SAAS,GAAG,YAAY,CAAC,KAAK,CAAC,eAAe,CAAA;IAClD,CAAC;SAAM,CAAC;QACJ,OAAM;IACV,CAAC;IAED,2BAA2B;IAC3B,qCAAqC;IAErC,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACvB,GAAG,CAAC,+BAA+B,CAAC,CAAA;QACpC,OAAM;IACV,CAAC;IACD,KAAK,YAAY,CAAC,UAAU,CAAC,IAAI,EAAE,kBAAkB,CAAC,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA,CAAC,yCAAyC;AAExH,CAAC","sourcesContent":["\r\nimport type { ReRunManager, RunType } from './reRunManager.js'\r\nimport type { RerunTestsFactory } from './listenToUser.js'\r\nimport type { ReRunManageState } from './makeWatchRunState.js'\r\nimport type { OutFn } from '../../types.js'\r\nimport chalk from '../../packages/chalk.js'\r\nimport { out } from '../../output.js'\r\n\r\n\r\nfunction showWithoutTests(state: ReRunManageState, customOut: OutFn): void {\r\n const entries = [...state.withoutTests.values()]\r\n if (entries.length === 0) {\r\n customOut('No files or describes without tests')\r\n return\r\n }\r\n\r\n customOut(chalk.grey('Files/describes without tests:'))\r\n const indent = ' '\r\n for (const entry of entries) {\r\n if (entry.fileWithoutTests) customOut(indent + chalk.yellow(entry.file))\r\n for (const describe of entry.describes) customOut(`${indent}${entry.file} > ` + chalk.brightblue(describe))\r\n }\r\n}\r\n\r\n\r\nexport function handleUserInput(\r\n input: string,\r\n reRunManager: ReRunManager,\r\n rerunTestsCallback: RerunTestsFactory,\r\n customOut: OutFn = out\r\n): void {\r\n const command = input.trim().toLowerCase()\r\n\r\n if (command === 'n') {\r\n showWithoutTests(reRunManager.state, customOut)\r\n return\r\n }\r\n\r\n //console.log('command', command)\r\n\r\n //console.log('watchRunState.activeRuns', watchRunState.activeRuns)\r\n // if (rerunManager.watchRunState.activeRuns > 0) return\r\n\r\n let type: RunType\r\n let testFiles: Set<string>\r\n if (command === 'r' || command === 'l') {\r\n type = 'last'\r\n testFiles = reRunManager.state.lastTestFiles\r\n } else if (command === 'a') {\r\n type = 'all'\r\n testFiles = reRunManager.state.allTestFiles\r\n } else if (command === 'f') {\r\n type = 'failed'\r\n testFiles = reRunManager.state.failedTestFiles\r\n } else {\r\n return\r\n }\r\n\r\n //console.log('type', type)\r\n //console.log('testFiles', testFiles)\r\n\r\n if (testFiles.size === 0) {\r\n out('No suitable test files to run')\r\n return\r\n }\r\n void reRunManager.requestRun(type, rerunTestsCallback(new Set(testFiles))) /// CHECK is it appropriate to copy here?\r\n \r\n}\r\n"]}
1
+ {"version":3,"file":"handleUserInput.js","sourceRoot":"","sources":["../../../src/cli/lib/handleUserInput.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,MAAM,yBAAyB,CAAA;AAC3C,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAA;AAGrC,SAAS,gBAAgB,CAAC,KAAuB,EAAE,SAAgB;IAC/D,MAAM,OAAO,GAAG,CAAC,GAAG,KAAK,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,CAAA;IAChD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,SAAS,CAAC,qCAAqC,CAAC,CAAA;QAChD,OAAM;IACV,CAAC;IAED,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC,CAAA;IACvD,MAAM,MAAM,GAAG,IAAI,CAAA;IACnB,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC1B,IAAI,KAAK,CAAC,gBAAgB;YAAE,SAAS,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAA;QACxE,KAAK,MAAM,QAAQ,IAAI,KAAK,CAAC,SAAS;YAAE,SAAS,CAAC,GAAG,MAAM,GAAG,KAAK,CAAC,IAAI,KAAK,GAAG,KAAK,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAA;IAC/G,CAAC;AACL,CAAC;AAGD,MAAM,UAAU,eAAe,CAC3B,KAAa,EACb,YAA0B,EAC1B,kBAAsC,EACtC,YAAmB,GAAG;IAEtB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;IAE1C,IAAI,OAAO,KAAK,GAAG,EAAE,CAAC;QAClB,gBAAgB,CAAC,YAAY,CAAC,KAAK,EAAE,SAAS,CAAC,CAAA;QAC/C,OAAM;IACV,CAAC;IAED,iCAAiC;IAEjC,mEAAmE;IACnE,wDAAwD;IAExD,IAAI,IAAa,CAAA;IACjB,IAAI,YAAyB,CAAA;IAC7B,IAAI,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,GAAG,EAAE,CAAC;QACrC,IAAI,GAAG,MAAM,CAAA;QACb,YAAY,GAAG,YAAY,CAAC,KAAK,CAAC,aAAa,CAAA;IACnD,CAAC;SAAM,IAAI,OAAO,KAAK,GAAG,EAAE,CAAC;QACzB,IAAI,GAAG,KAAK,CAAA;QACZ,YAAY,GAAG,YAAY,CAAC,KAAK,CAAC,YAAY,CAAA;IAClD,CAAC;SAAM,IAAI,OAAO,KAAK,GAAG,EAAE,CAAC;QACzB,IAAI,GAAG,QAAQ,CAAA;QACf,YAAY,GAAG,YAAY,CAAC,KAAK,CAAC,eAAe,CAAA;IACrD,CAAC;SAAM,CAAC;QACJ,OAAM;IACV,CAAC;IAED,2BAA2B;IAC3B,qCAAqC;IAErC,IAAI,YAAY,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QAC1B,GAAG,CAAC,+BAA+B,CAAC,CAAA;QACpC,OAAM;IACV,CAAC;IACD,KAAK,YAAY,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,EAAE;QACpC,IAAI,YAAY,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YAC1B,GAAG,CAAC,IAAI,GAAG,iCAAiC,CAAC,CAAA;YAC7C,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QAChC,CAAC;QACD,OAAO,kBAAkB,CAAC,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC,CAAA;IACpD,CAAC,CAAC,CAAA;IACF,sFAAsF;AAE1F,CAAC","sourcesContent":["\r\nimport type { ReRunManager, RunType } from './reRunManager.js'\r\nimport type { RerunTestsFunction } from './listenToUser.js'\r\nimport type { ReRunManageState } from './makeWatchRunState.js'\r\nimport type { OutFn } from '../../types.js'\r\nimport chalk from '../../packages/chalk.js'\r\nimport { out } from '../../output.js'\r\n\r\n\r\nfunction showWithoutTests(state: ReRunManageState, customOut: OutFn): void {\r\n const entries = [...state.withoutTests.values()]\r\n if (entries.length === 0) {\r\n customOut('No files or describes without tests')\r\n return\r\n }\r\n\r\n customOut(chalk.grey('Files/describes without tests:'))\r\n const indent = ' '\r\n for (const entry of entries) {\r\n if (entry.fileWithoutTests) customOut(indent + chalk.yellow(entry.file))\r\n for (const describe of entry.describes) customOut(`${indent}${entry.file} > ` + chalk.brightblue(describe))\r\n }\r\n}\r\n\r\n\r\nexport function handleUserInput(\r\n input: string,\r\n reRunManager: ReRunManager,\r\n rerunTestsCallback: RerunTestsFunction,\r\n customOut: OutFn = out\r\n): void {\r\n const command = input.trim().toLowerCase()\r\n\r\n if (command === 'n') {\r\n showWithoutTests(reRunManager.state, customOut)\r\n return\r\n }\r\n\r\n //console.log('command', command)\r\n\r\n //console.log('watchRunState.activeRuns', watchRunState.activeRuns)\r\n // if (rerunManager.watchRunState.activeRuns > 0) return\r\n\r\n let type: RunType\r\n let testFilesSet: Set<string>\r\n if (command === 'r' || command === 'l') {\r\n type = 'last'\r\n testFilesSet = reRunManager.state.lastTestFiles\r\n } else if (command === 'a') {\r\n type = 'all'\r\n testFilesSet = reRunManager.state.allTestFiles\r\n } else if (command === 'f') {\r\n type = 'failed'\r\n testFilesSet = reRunManager.state.failedTestFiles\r\n } else {\r\n return\r\n }\r\n\r\n //console.log('type', type)\r\n //console.log('testFiles', testFiles)\r\n\r\n if (testFilesSet.size === 0) {\r\n out('No suitable test files to run')\r\n return\r\n }\r\n void reRunManager.requestRun(type, () => {\r\n if (testFilesSet.size === 0) {\r\n out(type + ': No suitable test files to run')\r\n return Promise.resolve(null)\r\n }\r\n return rerunTestsCallback(new Set(testFilesSet))\r\n })\r\n //rerunTestsCallback(new Set(testFilesSet))) /// CHECK is it appropriate to copy here?\r\n \r\n}\r\n"]}
@@ -1,6 +1,6 @@
1
1
  import type { OutFn } from '../../types.js';
2
2
  import { type ReRunManager } from './reRunManager.js';
3
3
  import type { RunTestsPromise } from './runTests.js';
4
- export type RerunTestsFactory = (testFiles: Set<string>) => () => RunTestsPromise;
5
- export declare function listenToUser(rerunManager: ReRunManager, rerunTestsCallback: RerunTestsFactory, ttyActionsOnKeypress: boolean | undefined, initialTestRun: Promise<boolean | null> | null, input?: NodeJS.ReadStream, customOut?: OutFn): () => void;
4
+ export type RerunTestsFunction = (testFiles: Set<string>) => RunTestsPromise;
5
+ export declare function listenToUser(rerunManager: ReRunManager, rerunTestsCallback: RerunTestsFunction, ttyActionsOnKeypress: boolean | undefined, initialTestRun: Promise<boolean | null> | null, input?: NodeJS.ReadStream, customOut?: OutFn): () => void;
6
6
  //# sourceMappingURL=listenToUser.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"listenToUser.js","sourceRoot":"","sources":["../../../src/cli/lib/listenToUser.ts"],"names":[],"mappings":"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","sourcesContent":["\nimport { createInterface, emitKeypressEvents, type Key } from 'node:readline'\n\nimport type { OutFn } from '../../types.js'\nimport { type ReRunManager } from './reRunManager.js'\nimport type { RunTestsPromise } from './runTests.js'\nimport { showTtyHelp } from './showTtyHelp.js'\nimport { handleUserInput } from './handleUserInput.js'\nimport { out as mainOut, error as printError } from '../../output.js'\n\n\nexport type RerunTestsFactory = (testFiles: Set<string>) => () => RunTestsPromise\n\nexport function listenToUser(\n //allTestFiles: Set<string>,\n //failingTests: Set<string>,\n rerunManager: ReRunManager,\n rerunTestsCallback: RerunTestsFactory,\n ttyActionsOnKeypress = false,\n initialTestRun: Promise<boolean | null> | null,\n input: NodeJS.ReadStream = process.stdin,\n customOut?: OutFn\n): () => void {\n // an agent spawned session has no TTY, so these notices would otherwise be the only\n // lines in agent mode that are not agent events\n const out = customOut ?? mainOut\n\n //console.log('initia test run', initialTestRun)\n //console.log('listen to user')\n\n //setInterval(() => console.log('active runs: ', rerunManager.state.activeRuns), 10_000)\n\n // set by whichever branch attaches listeners below\n let disposeInput = (): void => {}\n\n if (!input.isTTY) {\n out('No TTY available, not receiving cli input')\n return () => {}\n }\n\n if (ttyActionsOnKeypress) {\n \n //console.log('ttyActionsOnKeypress')\n\n emitKeypressEvents(input)\n\n const wasRaw = input.isRaw\n const restoreRawMode = (): void => {\n //console.log('restoreRawMode')\n if (input.isRaw === wasRaw) return\n try {\n input.setRawMode(wasRaw)\n } catch {\n // The terminal stream may already be closed during process shutdown.\n }\n }\n\n input.setRawMode(true)\n input.resume()\n input.once('close', restoreRawMode)\n if (input === process.stdin) process.once('exit', restoreRawMode)\n\n const onKeypress = (keypressInput: string, key: Key): void => {\n //console.log('keypress', keypressInput)\n if (key.ctrl === true && key.name === 'c') {\n restoreRawMode()\n // process.kill(process.pid, 'SIGINT') terminates unconditionally on Windows\n // rather than raising the event, which skips the shutdown handlers and so\n // skips the user's teardown. Emitting reaches them on every platform.\n // Nothing listening means nobody will exit for us, so do it here.\n if (!process.emit('SIGINT', 'SIGINT')) process.exit(130)\n return\n }\n\n handleUserInput(keypressInput, rerunManager, rerunTestsCallback, out)\n }\n input.on('keypress', onKeypress)\n\n disposeInput = () => {\n input.off('keypress', onKeypress)\n // a `once` listener that never fired is still attached\n input.off('close', restoreRawMode)\n process.off('exit', restoreRawMode)\n restoreRawMode()\n // undoes the resume above, so stdin stops holding the event loop open\n input.pause()\n }\n } else {\n //console.log('no ttyActionsOnKeypress')\n\n const userInput = createInterface({ input })\n\n userInput.on('line', input => {\n //console.log('line input', input)\n handleUserInput(input, rerunManager, rerunTestsCallback, out)\n })\n\n disposeInput = () => {\n // close() takes readline's own data/end/error listeners off the stream\n userInput.close()\n input.pause()\n }\n }\n\n let stopped = false\n\n //console.log('initialTestRun 2', initialTestRun)\n initialTestRun\n ?.then(\n () => { if (!stopped) showTtyHelp(input.isTTY, out, rerunManager.state.withoutTests.size > 0) },\n e => printError('Error in initial test run', e)\n )\n .catch(e => { printError('Error showing TTY help', e) })\n\n return () => {\n if (!stopped) {\n stopped = true\n disposeInput()\n }\n }\n}\n"]}
1
+ {"version":3,"file":"listenToUser.js","sourceRoot":"","sources":["../../../src/cli/lib/listenToUser.ts"],"names":[],"mappings":"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","sourcesContent":["\nimport { createInterface, emitKeypressEvents, type Key } from 'node:readline'\n\nimport type { OutFn } from '../../types.js'\nimport { type ReRunManager } from './reRunManager.js'\nimport type { RunTestsPromise } from './runTests.js'\nimport { showTtyHelp } from './showTtyHelp.js'\nimport { handleUserInput } from './handleUserInput.js'\nimport { out as mainOut, error as printError } from '../../output.js'\n\n\nexport type RerunTestsFunction = (testFiles: Set<string>) => RunTestsPromise\n\nexport function listenToUser(\n //allTestFiles: Set<string>,\n //failingTests: Set<string>,\n rerunManager: ReRunManager,\n rerunTestsCallback: RerunTestsFunction,\n ttyActionsOnKeypress = false,\n initialTestRun: Promise<boolean | null> | null,\n input: NodeJS.ReadStream = process.stdin,\n customOut?: OutFn\n): () => void {\n // an agent spawned session has no TTY, so these notices would otherwise be the only\n // lines in agent mode that are not agent events\n const out = customOut ?? mainOut\n\n //console.log('initia test run', initialTestRun)\n //console.log('listen to user')\n\n //setInterval(() => console.log('active runs: ', rerunManager.state.activeRuns), 10_000)\n\n // set by whichever branch attaches listeners below\n let disposeInput = (): void => {}\n\n if (!input.isTTY) {\n out('No TTY available, not receiving cli input')\n return () => {}\n }\n\n if (ttyActionsOnKeypress) {\n \n //console.log('ttyActionsOnKeypress')\n\n emitKeypressEvents(input)\n\n const wasRaw = input.isRaw\n const restoreRawMode = (): void => {\n //console.log('restoreRawMode')\n if (input.isRaw === wasRaw) return\n try {\n input.setRawMode(wasRaw)\n } catch {\n // The terminal stream may already be closed during process shutdown.\n }\n }\n\n input.setRawMode(true)\n input.resume()\n input.once('close', restoreRawMode)\n if (input === process.stdin) process.once('exit', restoreRawMode)\n\n const onKeypress = (keypressInput: string, key: Key): void => {\n //console.log('keypress', keypressInput)\n if (key.ctrl === true && key.name === 'c') {\n restoreRawMode()\n // process.kill(process.pid, 'SIGINT') terminates unconditionally on Windows\n // rather than raising the event, which skips the shutdown handlers and so\n // skips the user's teardown. Emitting reaches them on every platform.\n // Nothing listening means nobody will exit for us, so do it here.\n if (!process.emit('SIGINT', 'SIGINT')) process.exit(130)\n return\n }\n\n handleUserInput(keypressInput, rerunManager, rerunTestsCallback, out)\n }\n input.on('keypress', onKeypress)\n\n disposeInput = () => {\n input.off('keypress', onKeypress)\n // a `once` listener that never fired is still attached\n input.off('close', restoreRawMode)\n process.off('exit', restoreRawMode)\n restoreRawMode()\n // undoes the resume above, so stdin stops holding the event loop open\n input.pause()\n }\n } else {\n //console.log('no ttyActionsOnKeypress')\n\n const userInput = createInterface({ input })\n\n userInput.on('line', input => {\n //console.log('line input', input)\n handleUserInput(input, rerunManager, rerunTestsCallback, out)\n })\n\n disposeInput = () => {\n // close() takes readline's own data/end/error listeners off the stream\n userInput.close()\n input.pause()\n }\n }\n\n let stopped = false\n\n //console.log('initialTestRun 2', initialTestRun)\n initialTestRun\n ?.then(\n () => { if (!stopped) showTtyHelp(input.isTTY, out, rerunManager.state.withoutTests.size > 0) },\n e => printError('Error in initial test run', e)\n )\n .catch(e => { printError('Error showing TTY help', e) })\n\n return () => {\n if (!stopped) {\n stopped = true\n disposeInput()\n }\n }\n}\n"]}
@@ -1,6 +1,5 @@
1
1
  import type { Describe, FinalConfig } from '../../types.js';
2
2
  import type { FileMeta } from '../../meta.js';
3
- import '../../packages/esmReload.js';
4
3
  export type TestFile = {
5
4
  file: string;
6
5
  sourceFile?: string;