@knighted/duel 4.0.0-rc.0 → 4.0.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/esm/util.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { pathToFileURL } from 'node:url';
2
- import { realpath, readFile, writeFile, symlink } from 'node:fs/promises';
3
- import { existsSync } from 'node:fs';
2
+ import { realpath, readFile, writeFile, symlink, rm } from 'node:fs/promises';
3
+ import { existsSync, rmSync } from 'node:fs';
4
4
  import { spawnSync } from 'node:child_process';
5
5
  import { cwd, platform } from 'node:process';
6
6
  import { join, resolve, relative, parse as parsePath, posix, isAbsolute, sep, normalize as normalizePath, } from 'node:path';
@@ -35,6 +35,83 @@ const log = (msg = '', level = 'info', opts = {}) => {
35
35
  const logSuccess = msg => log(msg, 'success');
36
36
  const logWarn = msg => log(msg, 'warn');
37
37
  const logError = msg => log(msg, 'error');
38
+ const createTempCleanup = ({ subDir, keepTemp = false, logWarnFn = logWarn }) => {
39
+ let cleaned = false;
40
+ let cleanupPromise = null;
41
+ // Marks cleanup as started; returns false when already running or completed.
42
+ const beginCleanup = () => {
43
+ if (cleaned)
44
+ return false;
45
+ cleaned = true;
46
+ return true;
47
+ };
48
+ const cleanupTempSync = () => {
49
+ if (!beginCleanup())
50
+ return;
51
+ if (keepTemp) {
52
+ logWarnFn(`DUEL_KEEP_TEMP=1 set; temp workspace preserved at ${subDir}`);
53
+ return;
54
+ }
55
+ try {
56
+ rmSync(subDir, { force: true, recursive: true });
57
+ }
58
+ catch {
59
+ /* ignore */
60
+ }
61
+ };
62
+ const cleanupTemp = async () => {
63
+ if (cleanupPromise)
64
+ return cleanupPromise;
65
+ const runCleanup = async () => {
66
+ if (!beginCleanup())
67
+ return;
68
+ if (keepTemp) {
69
+ logWarnFn(`DUEL_KEEP_TEMP=1 set; temp workspace preserved at ${subDir}`);
70
+ return;
71
+ }
72
+ try {
73
+ await rm(subDir, { force: true, recursive: true });
74
+ }
75
+ catch {
76
+ /* ignore */
77
+ }
78
+ };
79
+ cleanupPromise = runCleanup();
80
+ return cleanupPromise;
81
+ };
82
+ return { cleanupTempSync, cleanupTemp };
83
+ };
84
+ const registerCleanupHandlers = cleanupTempSync => {
85
+ const onExit = () => cleanupTempSync();
86
+ const onSigint = () => {
87
+ cleanupTempSync();
88
+ process.exit(1);
89
+ };
90
+ const onSigterm = () => {
91
+ cleanupTempSync();
92
+ process.exit(1);
93
+ };
94
+ const onUncaught = err => {
95
+ cleanupTempSync();
96
+ throw err;
97
+ };
98
+ const onUnhandled = reason => {
99
+ cleanupTempSync();
100
+ throw reason instanceof Error ? reason : new Error(String(reason));
101
+ };
102
+ process.once('exit', onExit);
103
+ process.once('SIGINT', onSigint);
104
+ process.once('SIGTERM', onSigterm);
105
+ process.once('uncaughtException', onUncaught);
106
+ process.once('unhandledRejection', onUnhandled);
107
+ return () => {
108
+ process.removeListener('exit', onExit);
109
+ process.removeListener('SIGINT', onSigint);
110
+ process.removeListener('SIGTERM', onSigterm);
111
+ process.removeListener('uncaughtException', onUncaught);
112
+ process.removeListener('unhandledRejection', onUnhandled);
113
+ };
114
+ };
38
115
  const getRealPathAsFileUrl = async (path) => {
39
116
  const realPath = await realpath(path);
40
117
  const asFileUrl = pathToFileURL(realPath).href;
@@ -332,8 +409,10 @@ const maybeLinkNodeModules = async (projectRoot, subDir, symlinkFn = symlink, fi
332
409
  try {
333
410
  await symlinkFn(nodeModules, join(subDir, 'node_modules'), 'junction');
334
411
  }
335
- catch {
336
- /* If symlink fails, fall back to existing resolution. */
412
+ catch (err) {
413
+ if (err?.code === 'EEXIST')
414
+ return;
415
+ logWarn(`Failed to link node_modules into temp workspace (falling back to existing resolution): ${err.message}`);
337
416
  }
338
417
  }
339
418
  };
@@ -361,4 +440,4 @@ const runExportsValidationBlock = async (options) => {
361
440
  }
362
441
  return result;
363
442
  };
364
- export { log, logError, logSuccess, logWarn, getRealPathAsFileUrl, getCompileFiles, readExportsConfig, getSubpath, generateExports, stripKnownExt, ensureDotSlash, processDiagnosticsForFile, exitOnDiagnostics, maybeLinkNodeModules, runExportsValidationBlock, };
443
+ export { log, logError, logSuccess, logWarn, getRealPathAsFileUrl, getCompileFiles, readExportsConfig, getSubpath, generateExports, stripKnownExt, ensureDotSlash, createTempCleanup, registerCleanupHandlers, processDiagnosticsForFile, exitOnDiagnostics, maybeLinkNodeModules, runExportsValidationBlock, };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@knighted/duel",
3
- "version": "4.0.0-rc.0",
3
+ "version": "4.0.0-rc.2",
4
4
  "description": "TypeScript dual packages.",
5
5
  "type": "module",
6
6
  "main": "dist/esm/duel.js",
@@ -20,14 +20,16 @@
20
20
  },
21
21
  "engineStrict": true,
22
22
  "scripts": {
23
- "prettier": "prettier -w *.js *.md docs/*.md src/*.js test/*.js",
24
- "prettier:check": "prettier --check --ignore-unknown *.js *.md docs/*.md src/*.js test/*.js",
25
- "lint": "eslint src/*.js test/*.js",
26
- "test:focus": "node --test --test-reporter=spec test/unit.js",
23
+ "prettier": "prettier -w *.js *.md docs/*.md src/*.js test/*.js scripts/*.js",
24
+ "prettier:check": "prettier --check --ignore-unknown *.js *.md docs/*.md src/*.js test/*.js scripts/*.js",
25
+ "lint": "eslint src/*.js test/*.js scripts/*.js",
27
26
  "test:unit": "c8 --reporter=text --reporter=text-summary --reporter=lcov node --test --test-reporter=spec test/unit.js",
28
27
  "test:integration": "node --test --test-reporter=spec test/integration.js",
29
28
  "test:monorepos": "node --test --test-reporter=spec test/monorepos.js",
30
- "test": "c8 --reporter=text --reporter=text-summary --reporter=lcov node --trace-deprecation --test --test-reporter=spec test/integration.js test/monorepos.js test/rewritePolicy.js test/unit.js",
29
+ "test:cleanup": "node --test --test-reporter=spec test/cleanup.integration.js",
30
+ "test": "c8 --reporter=text --reporter=text-summary --reporter=lcov node --trace-deprecation --test --test-reporter=spec test/*.js",
31
+ "clean:fixtures": "node scripts/clean-fixtures.js",
32
+ "pretest": "npm run clean:fixtures",
31
33
  "build": "node src/duel.js --dirs --mode globals",
32
34
  "prepack": "npm run build",
33
35
  "prepare": "husky"
@@ -85,7 +87,7 @@
85
87
  "vite": "^7.2.4"
86
88
  },
87
89
  "dependencies": {
88
- "@knighted/module": "^1.4.0-rc.2",
90
+ "@knighted/module": "^1.4.0",
89
91
  "find-up": "^8.0.0",
90
92
  "get-tsconfig": "^4.13.0",
91
93
  "glob": "^13.0.0",