@wrongstack/tools 0.306.3 → 0.306.4

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/audit.js CHANGED
@@ -1041,6 +1041,7 @@ function utf8Prefix(text, maxBytes) {
1041
1041
  }
1042
1042
 
1043
1043
  // src/_util.ts
1044
+ import * as fsp2 from "node:fs/promises";
1044
1045
  import * as path3 from "node:path";
1045
1046
  import * as Core from "@wrongstack/core/utils";
1046
1047
  async function detectPackageManager(cwd, stopAt) {
@@ -1107,6 +1108,40 @@ function ensureInsideRoot(absPath, ctx) {
1107
1108
  function safeResolve(input, ctx) {
1108
1109
  return ensureInsideRoot(resolvePath(input, ctx), ctx);
1109
1110
  }
1111
+ async function resolveRealInsideRoot(absPath, ctx) {
1112
+ if (ctx.allowOutsideProjectRoot) return absPath;
1113
+ const realRoots = await Promise.all(
1114
+ allowedRoots(ctx).map((r) => fsp2.realpath(r).catch(() => path3.resolve(r)))
1115
+ );
1116
+ let probe = absPath;
1117
+ const pendingTail = [];
1118
+ for (; ; ) {
1119
+ let real;
1120
+ try {
1121
+ real = await fsp2.realpath(probe);
1122
+ } catch (err) {
1123
+ if (err.code === "ENOENT") {
1124
+ const parent = path3.dirname(probe);
1125
+ if (parent === probe) return absPath;
1126
+ pendingTail.unshift(path3.basename(probe));
1127
+ probe = parent;
1128
+ continue;
1129
+ }
1130
+ throw err;
1131
+ }
1132
+ const candidate = pendingTail.length > 0 ? path3.join(real, ...pendingTail) : real;
1133
+ if (isInsideAny(candidate, realRoots)) {
1134
+ return candidate;
1135
+ }
1136
+ throw new Error(
1137
+ `Path "${absPath}" resolves through a symlink outside project root "${realRoots[0]}"`
1138
+ );
1139
+ }
1140
+ }
1141
+ async function safeResolveReal(input, ctx) {
1142
+ const abs = safeResolve(input, ctx);
1143
+ return await resolveRealInsideRoot(abs, ctx);
1144
+ }
1110
1145
  var COMMAND_OUTPUT_MAX_BYTES = 32768;
1111
1146
  var REPEAT_RUN_THRESHOLD = 3;
1112
1147
  function collapseCarriageReturns(text) {
@@ -3890,7 +3925,7 @@ var auditTool = {
3890
3925
  "audit: `fix: true` is not supported \u2014 this tool is read-only (mutating: false). To remediate vulnerabilities, upgrade the affected packages with the `install` tool (or `language_package` for non-JS ecosystems)."
3891
3926
  );
3892
3927
  }
3893
- const cwd = input.cwd ? safeResolve(input.cwd, ctx) : ctx.cwd;
3928
+ const cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.cwd;
3894
3929
  const bridge = await tryLegacyPackageOperation("package-audit", {
3895
3930
  cwd,
3896
3931
  projectRoot: ctx.projectRoot,
package/dist/builtin.js CHANGED
@@ -1202,8 +1202,9 @@ async function resolveRealInsideRoot(absPath, ctx) {
1202
1202
  }
1203
1203
  throw err;
1204
1204
  }
1205
- if (isInsideAny(real, realRoots)) {
1206
- return pendingTail.length > 0 ? path3.join(real, ...pendingTail) : real;
1205
+ const candidate = pendingTail.length > 0 ? path3.join(real, ...pendingTail) : real;
1206
+ if (isInsideAny(candidate, realRoots)) {
1207
+ return candidate;
1207
1208
  }
1208
1209
  throw new Error(
1209
1210
  `Path "${absPath}" resolves through a symlink outside project root "${realRoots[0]}"`
@@ -7737,7 +7738,7 @@ var auditTool = {
7737
7738
  "audit: `fix: true` is not supported \u2014 this tool is read-only (mutating: false). To remediate vulnerabilities, upgrade the affected packages with the `install` tool (or `language_package` for non-JS ecosystems)."
7738
7739
  );
7739
7740
  }
7740
- const cwd = input.cwd ? safeResolve(input.cwd, ctx) : ctx.cwd;
7741
+ const cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.cwd;
7741
7742
  const bridge = await tryLegacyPackageOperation("package-audit", {
7742
7743
  cwd,
7743
7744
  projectRoot: ctx.projectRoot,
@@ -18062,7 +18063,7 @@ var documentTool = {
18062
18063
  }
18063
18064
  },
18064
18065
  async execute(input, ctx) {
18065
- const cwd = input.cwd ? safeResolve(input.cwd, ctx) : ctx.cwd;
18066
+ const cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.cwd;
18066
18067
  const style = input.style ?? "jsdoc";
18067
18068
  const results = [];
18068
18069
  let filesProcessed = 0;
@@ -18071,7 +18072,7 @@ var documentTool = {
18071
18072
  Array.isArray(input.files) ? input.files.join(",") : input.files,
18072
18073
  cwd,
18073
18074
  ctx
18074
- ) : input.path ? [safeResolve(input.path, ctx)] : [];
18075
+ ) : input.path ? [await safeResolveReal(input.path, ctx)] : [];
18075
18076
  for (const absPath of fileList) {
18076
18077
  try {
18077
18078
  const content = await fs23.readFile(absPath, "utf8");
@@ -21187,7 +21188,7 @@ var formatTool = {
21187
21188
  return final;
21188
21189
  },
21189
21190
  async *executeStream(input, ctx, opts) {
21190
- const cwd = input.cwd ? safeResolve(input.cwd, ctx) : ctx.cwd;
21191
+ const cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.cwd;
21191
21192
  const fixer = input.fixer ?? "auto";
21192
21193
  if (fixer === "auto" && !input.files) {
21193
21194
  const op = input.check ? "format-check" : "format-write";
@@ -22405,7 +22406,7 @@ var installTool = {
22405
22406
  return final;
22406
22407
  },
22407
22408
  async *executeStream(input, ctx, opts) {
22408
- const cwd = input.cwd ? safeResolve(input.cwd, ctx) : ctx.cwd;
22409
+ const cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.cwd;
22409
22410
  if (!input.global) {
22410
22411
  const pkgList2 = input.packages ? Array.isArray(input.packages) ? input.packages : input.packages.split(",").map((p) => p.trim()) : [];
22411
22412
  const bridge = await tryLegacyPackageOperation(
@@ -25581,7 +25582,7 @@ var lintTool = {
25581
25582
  return final;
25582
25583
  },
25583
25584
  async *executeStream(input, ctx, opts) {
25584
- const cwd = input.cwd ? safeResolve(input.cwd, ctx) : ctx.cwd;
25585
+ const cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.cwd;
25585
25586
  const linter = input.linter ?? "auto";
25586
25587
  if (linter === "auto" && !input.files) {
25587
25588
  const bridge = await tryLegacyCodeOperation("lint", {
@@ -25707,7 +25708,7 @@ var logsTool = {
25707
25708
  }
25708
25709
  },
25709
25710
  async execute(input, ctx, opts) {
25710
- const cwd = input.cwd ? safeResolve(input.cwd, ctx) : ctx.cwd;
25711
+ const cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.cwd;
25711
25712
  const lines = input.lines ?? 100;
25712
25713
  let filterRe = null;
25713
25714
  if (input.filter) {
@@ -25914,7 +25915,7 @@ var outdatedTool = {
25914
25915
  }
25915
25916
  },
25916
25917
  async execute(input, ctx, opts) {
25917
- const cwd = input.cwd ? safeResolve(input.cwd, ctx) : ctx.cwd;
25918
+ const cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.cwd;
25918
25919
  const manager = await detectPackageManager(cwd, ctx.projectRoot);
25919
25920
  if (manager === "npm") {
25920
25921
  try {
@@ -27628,7 +27629,7 @@ async function resolveFiles2(filesInput, ctx, extraGlob) {
27628
27629
  const parts = normalized.split(",").map((s) => s.trim()).filter(Boolean);
27629
27630
  const resolved = [];
27630
27631
  for (const p of parts) {
27631
- const absPath = safeResolve(p, ctx);
27632
+ const absPath = await safeResolveReal(p, ctx);
27632
27633
  if (extraGlob && !passesExtraGlob(extraGlob, path35.basename(absPath), absPath)) continue;
27633
27634
  const stat19 = await fs30.stat(absPath).catch(() => null);
27634
27635
  if (stat19?.isFile()) {
@@ -27866,7 +27867,7 @@ var scaffoldTool = {
27866
27867
  required: ["template", "name"]
27867
27868
  },
27868
27869
  async execute(input, ctx) {
27869
- const cwd = input.cwd ? safeResolve(input.cwd, ctx) : ctx.cwd;
27870
+ const cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.cwd;
27870
27871
  const name = input.name;
27871
27872
  const vars = { name, ...input.vars };
27872
27873
  const builtIn = BUILT_IN_TEMPLATES[input.template];
@@ -28954,7 +28955,7 @@ var testTool = {
28954
28955
  return final;
28955
28956
  },
28956
28957
  async *executeStream(input, ctx, opts) {
28957
- const cwd = input.cwd ? safeResolve(input.cwd, ctx) : ctx.cwd;
28958
+ const cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.cwd;
28958
28959
  const runner = input.runner ?? "auto";
28959
28960
  if (runner === "auto") {
28960
28961
  const bridge = await tryLegacyCodeOperation("test", {
@@ -29469,7 +29470,7 @@ var treeTool = {
29469
29470
  return final;
29470
29471
  },
29471
29472
  async *executeStream(input, ctx, opts) {
29472
- const basePath = input.path ? safeResolve(input.path, ctx) : ctx.cwd;
29473
+ const basePath = input.path ? await safeResolveReal(input.path, ctx) : ctx.cwd;
29473
29474
  const maxDepth = input.depth ?? 3;
29474
29475
  const showFiles = input.show_files ?? true;
29475
29476
  const showDirs = input.show_dirs ?? true;
@@ -29649,7 +29650,7 @@ var typecheckTool = {
29649
29650
  return final;
29650
29651
  },
29651
29652
  async *executeStream(input, ctx, opts) {
29652
- const cwd = input.cwd ? safeResolve(input.cwd, ctx) : ctx.cwd;
29653
+ const cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.cwd;
29653
29654
  const bridge = await tryLegacyCodeOperation("semantic", {
29654
29655
  cwd,
29655
29656
  projectRoot: ctx.projectRoot,
@@ -29686,7 +29687,7 @@ var typecheckTool = {
29686
29687
  cmdArgs = ["tsc", ...tscArgs];
29687
29688
  }
29688
29689
  } else {
29689
- const tsconfig = input.project ? safeResolve(input.project, ctx) : await findTsConfig(cwd);
29690
+ const tsconfig = input.project ? await safeResolveReal(input.project, ctx) : await findTsConfig(cwd);
29690
29691
  const tscArgs = ["--noEmit"];
29691
29692
  if (input.strict) tscArgs.push("--strict");
29692
29693
  if (tsconfig) tscArgs.push("--project", tsconfig);
package/dist/diff.js CHANGED
@@ -52,8 +52,9 @@ async function resolveRealInsideRoot(absPath, ctx) {
52
52
  }
53
53
  throw err;
54
54
  }
55
- if (isInsideAny(real, realRoots)) {
56
- return pendingTail.length > 0 ? path.join(real, ...pendingTail) : real;
55
+ const candidate = pendingTail.length > 0 ? path.join(real, ...pendingTail) : real;
56
+ if (isInsideAny(candidate, realRoots)) {
57
+ return candidate;
57
58
  }
58
59
  throw new Error(
59
60
  `Path "${absPath}" resolves through a symlink outside project root "${realRoots[0]}"`
package/dist/document.js CHANGED
@@ -3,6 +3,7 @@ import * as fs from "node:fs/promises";
3
3
  import * as path2 from "node:path";
4
4
 
5
5
  // src/_util.ts
6
+ import * as fsp from "node:fs/promises";
6
7
  import * as path from "node:path";
7
8
  import * as Core from "@wrongstack/core/utils";
8
9
  function resolvePath(input, ctx) {
@@ -26,6 +27,40 @@ function ensureInsideRoot(absPath, ctx) {
26
27
  function safeResolve(input, ctx) {
27
28
  return ensureInsideRoot(resolvePath(input, ctx), ctx);
28
29
  }
30
+ async function resolveRealInsideRoot(absPath, ctx) {
31
+ if (ctx.allowOutsideProjectRoot) return absPath;
32
+ const realRoots = await Promise.all(
33
+ allowedRoots(ctx).map((r) => fsp.realpath(r).catch(() => path.resolve(r)))
34
+ );
35
+ let probe = absPath;
36
+ const pendingTail = [];
37
+ for (; ; ) {
38
+ let real;
39
+ try {
40
+ real = await fsp.realpath(probe);
41
+ } catch (err) {
42
+ if (err.code === "ENOENT") {
43
+ const parent = path.dirname(probe);
44
+ if (parent === probe) return absPath;
45
+ pendingTail.unshift(path.basename(probe));
46
+ probe = parent;
47
+ continue;
48
+ }
49
+ throw err;
50
+ }
51
+ const candidate = pendingTail.length > 0 ? path.join(real, ...pendingTail) : real;
52
+ if (isInsideAny(candidate, realRoots)) {
53
+ return candidate;
54
+ }
55
+ throw new Error(
56
+ `Path "${absPath}" resolves through a symlink outside project root "${realRoots[0]}"`
57
+ );
58
+ }
59
+ }
60
+ async function safeResolveReal(input, ctx) {
61
+ const abs = safeResolve(input, ctx);
62
+ return await resolveRealInsideRoot(abs, ctx);
63
+ }
29
64
 
30
65
  // src/document.ts
31
66
  var documentTool = {
@@ -63,7 +98,7 @@ var documentTool = {
63
98
  }
64
99
  },
65
100
  async execute(input, ctx) {
66
- const cwd = input.cwd ? safeResolve(input.cwd, ctx) : ctx.cwd;
101
+ const cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.cwd;
67
102
  const style = input.style ?? "jsdoc";
68
103
  const results = [];
69
104
  let filesProcessed = 0;
@@ -72,7 +107,7 @@ var documentTool = {
72
107
  Array.isArray(input.files) ? input.files.join(",") : input.files,
73
108
  cwd,
74
109
  ctx
75
- ) : input.path ? [safeResolve(input.path, ctx)] : [];
110
+ ) : input.path ? [await safeResolveReal(input.path, ctx)] : [];
76
111
  for (const absPath of fileList) {
77
112
  try {
78
113
  const content = await fs.readFile(absPath, "utf8");
package/dist/e2e.js CHANGED
@@ -48,8 +48,9 @@ async function resolveRealInsideRoot(absPath, ctx) {
48
48
  }
49
49
  throw err;
50
50
  }
51
- if (isInsideAny(real, realRoots)) {
52
- return pendingTail.length > 0 ? path.join(real, ...pendingTail) : real;
51
+ const candidate = pendingTail.length > 0 ? path.join(real, ...pendingTail) : real;
52
+ if (isInsideAny(candidate, realRoots)) {
53
+ return candidate;
53
54
  }
54
55
  throw new Error(
55
56
  `Path "${absPath}" resolves through a symlink outside project root "${realRoots[0]}"`
package/dist/edit.js CHANGED
@@ -369,8 +369,9 @@ async function resolveRealInsideRoot(absPath, ctx) {
369
369
  }
370
370
  throw err;
371
371
  }
372
- if (isInsideAny(real, realRoots)) {
373
- return pendingTail.length > 0 ? path2.join(real, ...pendingTail) : real;
372
+ const candidate = pendingTail.length > 0 ? path2.join(real, ...pendingTail) : real;
373
+ if (isInsideAny(candidate, realRoots)) {
374
+ return candidate;
374
375
  }
375
376
  throw new Error(
376
377
  `Path "${absPath}" resolves through a symlink outside project root "${realRoots[0]}"`
package/dist/exec.js CHANGED
@@ -487,8 +487,9 @@ async function resolveRealInsideRoot(absPath, ctx) {
487
487
  }
488
488
  throw err;
489
489
  }
490
- if (isInsideAny(real, realRoots)) {
491
- return pendingTail.length > 0 ? path2.join(real, ...pendingTail) : real;
490
+ const candidate = pendingTail.length > 0 ? path2.join(real, ...pendingTail) : real;
491
+ if (isInsideAny(candidate, realRoots)) {
492
+ return candidate;
492
493
  }
493
494
  throw new Error(
494
495
  `Path "${absPath}" resolves through a symlink outside project root "${realRoots[0]}"`
package/dist/format.js CHANGED
@@ -1041,6 +1041,7 @@ function utf8Prefix(text, maxBytes) {
1041
1041
  }
1042
1042
 
1043
1043
  // src/_util.ts
1044
+ import * as fsp2 from "node:fs/promises";
1044
1045
  import * as path3 from "node:path";
1045
1046
  import * as Core from "@wrongstack/core/utils";
1046
1047
  function resolvePath(input, ctx) {
@@ -1064,6 +1065,40 @@ function ensureInsideRoot(absPath, ctx) {
1064
1065
  function safeResolve(input, ctx) {
1065
1066
  return ensureInsideRoot(resolvePath(input, ctx), ctx);
1066
1067
  }
1068
+ async function resolveRealInsideRoot(absPath, ctx) {
1069
+ if (ctx.allowOutsideProjectRoot) return absPath;
1070
+ const realRoots = await Promise.all(
1071
+ allowedRoots(ctx).map((r) => fsp2.realpath(r).catch(() => path3.resolve(r)))
1072
+ );
1073
+ let probe = absPath;
1074
+ const pendingTail = [];
1075
+ for (; ; ) {
1076
+ let real;
1077
+ try {
1078
+ real = await fsp2.realpath(probe);
1079
+ } catch (err) {
1080
+ if (err.code === "ENOENT") {
1081
+ const parent = path3.dirname(probe);
1082
+ if (parent === probe) return absPath;
1083
+ pendingTail.unshift(path3.basename(probe));
1084
+ probe = parent;
1085
+ continue;
1086
+ }
1087
+ throw err;
1088
+ }
1089
+ const candidate = pendingTail.length > 0 ? path3.join(real, ...pendingTail) : real;
1090
+ if (isInsideAny(candidate, realRoots)) {
1091
+ return candidate;
1092
+ }
1093
+ throw new Error(
1094
+ `Path "${absPath}" resolves through a symlink outside project root "${realRoots[0]}"`
1095
+ );
1096
+ }
1097
+ }
1098
+ async function safeResolveReal(input, ctx) {
1099
+ const abs = safeResolve(input, ctx);
1100
+ return await resolveRealInsideRoot(abs, ctx);
1101
+ }
1067
1102
  var COMMAND_OUTPUT_MAX_BYTES = 32768;
1068
1103
  var REPEAT_RUN_THRESHOLD = 3;
1069
1104
  function collapseCarriageReturns(text) {
@@ -3590,7 +3625,7 @@ var formatTool = {
3590
3625
  return final;
3591
3626
  },
3592
3627
  async *executeStream(input, ctx, opts) {
3593
- const cwd = input.cwd ? safeResolve(input.cwd, ctx) : ctx.cwd;
3628
+ const cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.cwd;
3594
3629
  const fixer = input.fixer ?? "auto";
3595
3630
  if (fixer === "auto" && !input.files) {
3596
3631
  const op = input.check ? "format-check" : "format-write";
package/dist/glob.js CHANGED
@@ -125,8 +125,9 @@ async function resolveRealInsideRoot(absPath, ctx) {
125
125
  }
126
126
  throw err;
127
127
  }
128
- if (isInsideAny(real, realRoots)) {
129
- return pendingTail.length > 0 ? path2.join(real, ...pendingTail) : real;
128
+ const candidate = pendingTail.length > 0 ? path2.join(real, ...pendingTail) : real;
129
+ if (isInsideAny(candidate, realRoots)) {
130
+ return candidate;
130
131
  }
131
132
  throw new Error(
132
133
  `Path "${absPath}" resolves through a symlink outside project root "${realRoots[0]}"`
package/dist/grep.js CHANGED
@@ -199,8 +199,9 @@ async function resolveRealInsideRoot(absPath, ctx) {
199
199
  }
200
200
  throw err;
201
201
  }
202
- if (isInsideAny(real, realRoots)) {
203
- return pendingTail.length > 0 ? path.join(real, ...pendingTail) : real;
202
+ const candidate = pendingTail.length > 0 ? path.join(real, ...pendingTail) : real;
203
+ if (isInsideAny(candidate, realRoots)) {
204
+ return candidate;
204
205
  }
205
206
  throw new Error(
206
207
  `Path "${absPath}" resolves through a symlink outside project root "${realRoots[0]}"`
package/dist/index.js CHANGED
@@ -1205,8 +1205,9 @@ async function resolveRealInsideRoot(absPath, ctx) {
1205
1205
  }
1206
1206
  throw err;
1207
1207
  }
1208
- if (isInsideAny(real, realRoots)) {
1209
- return pendingTail.length > 0 ? path3.join(real, ...pendingTail) : real;
1208
+ const candidate = pendingTail.length > 0 ? path3.join(real, ...pendingTail) : real;
1209
+ if (isInsideAny(candidate, realRoots)) {
1210
+ return candidate;
1210
1211
  }
1211
1212
  throw new Error(
1212
1213
  `Path "${absPath}" resolves through a symlink outside project root "${realRoots[0]}"`
@@ -8095,7 +8096,7 @@ var auditTool = {
8095
8096
  "audit: `fix: true` is not supported \u2014 this tool is read-only (mutating: false). To remediate vulnerabilities, upgrade the affected packages with the `install` tool (or `language_package` for non-JS ecosystems)."
8096
8097
  );
8097
8098
  }
8098
- const cwd = input.cwd ? safeResolve(input.cwd, ctx) : ctx.cwd;
8099
+ const cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.cwd;
8099
8100
  const bridge = await tryLegacyPackageOperation("package-audit", {
8100
8101
  cwd,
8101
8102
  projectRoot: ctx.projectRoot,
@@ -18609,7 +18610,7 @@ var documentTool = {
18609
18610
  }
18610
18611
  },
18611
18612
  async execute(input, ctx) {
18612
- const cwd = input.cwd ? safeResolve(input.cwd, ctx) : ctx.cwd;
18613
+ const cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.cwd;
18613
18614
  const style = input.style ?? "jsdoc";
18614
18615
  const results = [];
18615
18616
  let filesProcessed = 0;
@@ -18618,7 +18619,7 @@ var documentTool = {
18618
18619
  Array.isArray(input.files) ? input.files.join(",") : input.files,
18619
18620
  cwd,
18620
18621
  ctx
18621
- ) : input.path ? [safeResolve(input.path, ctx)] : [];
18622
+ ) : input.path ? [await safeResolveReal(input.path, ctx)] : [];
18622
18623
  for (const absPath of fileList) {
18623
18624
  try {
18624
18625
  const content = await fs23.readFile(absPath, "utf8");
@@ -21438,7 +21439,7 @@ var formatTool = {
21438
21439
  return final;
21439
21440
  },
21440
21441
  async *executeStream(input, ctx, opts) {
21441
- const cwd = input.cwd ? safeResolve(input.cwd, ctx) : ctx.cwd;
21442
+ const cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.cwd;
21442
21443
  const fixer = input.fixer ?? "auto";
21443
21444
  if (fixer === "auto" && !input.files) {
21444
21445
  const op = input.check ? "format-check" : "format-write";
@@ -22656,7 +22657,7 @@ var installTool = {
22656
22657
  return final;
22657
22658
  },
22658
22659
  async *executeStream(input, ctx, opts) {
22659
- const cwd = input.cwd ? safeResolve(input.cwd, ctx) : ctx.cwd;
22660
+ const cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.cwd;
22660
22661
  if (!input.global) {
22661
22662
  const pkgList2 = input.packages ? Array.isArray(input.packages) ? input.packages : input.packages.split(",").map((p) => p.trim()) : [];
22662
22663
  const bridge = await tryLegacyPackageOperation(
@@ -26261,7 +26262,7 @@ var lintTool = {
26261
26262
  return final;
26262
26263
  },
26263
26264
  async *executeStream(input, ctx, opts) {
26264
- const cwd = input.cwd ? safeResolve(input.cwd, ctx) : ctx.cwd;
26265
+ const cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.cwd;
26265
26266
  const linter = input.linter ?? "auto";
26266
26267
  if (linter === "auto" && !input.files) {
26267
26268
  const bridge = await tryLegacyCodeOperation("lint", {
@@ -26387,7 +26388,7 @@ var logsTool = {
26387
26388
  }
26388
26389
  },
26389
26390
  async execute(input, ctx, opts) {
26390
- const cwd = input.cwd ? safeResolve(input.cwd, ctx) : ctx.cwd;
26391
+ const cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.cwd;
26391
26392
  const lines = input.lines ?? 100;
26392
26393
  let filterRe = null;
26393
26394
  if (input.filter) {
@@ -26594,7 +26595,7 @@ var outdatedTool = {
26594
26595
  }
26595
26596
  },
26596
26597
  async execute(input, ctx, opts) {
26597
- const cwd = input.cwd ? safeResolve(input.cwd, ctx) : ctx.cwd;
26598
+ const cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.cwd;
26598
26599
  const manager = await detectPackageManager(cwd, ctx.projectRoot);
26599
26600
  if (manager === "npm") {
26600
26601
  try {
@@ -28308,7 +28309,7 @@ async function resolveFiles2(filesInput, ctx, extraGlob) {
28308
28309
  const parts = normalized.split(",").map((s) => s.trim()).filter(Boolean);
28309
28310
  const resolved = [];
28310
28311
  for (const p of parts) {
28311
- const absPath = safeResolve(p, ctx);
28312
+ const absPath = await safeResolveReal(p, ctx);
28312
28313
  if (extraGlob && !passesExtraGlob(extraGlob, path35.basename(absPath), absPath)) continue;
28313
28314
  const stat20 = await fs30.stat(absPath).catch(() => null);
28314
28315
  if (stat20?.isFile()) {
@@ -28546,7 +28547,7 @@ var scaffoldTool = {
28546
28547
  required: ["template", "name"]
28547
28548
  },
28548
28549
  async execute(input, ctx) {
28549
- const cwd = input.cwd ? safeResolve(input.cwd, ctx) : ctx.cwd;
28550
+ const cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.cwd;
28550
28551
  const name = input.name;
28551
28552
  const vars = { name, ...input.vars };
28552
28553
  const builtIn = BUILT_IN_TEMPLATES[input.template];
@@ -29634,7 +29635,7 @@ var testTool = {
29634
29635
  return final;
29635
29636
  },
29636
29637
  async *executeStream(input, ctx, opts) {
29637
- const cwd = input.cwd ? safeResolve(input.cwd, ctx) : ctx.cwd;
29638
+ const cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.cwd;
29638
29639
  const runner = input.runner ?? "auto";
29639
29640
  if (runner === "auto") {
29640
29641
  const bridge = await tryLegacyCodeOperation("test", {
@@ -30149,7 +30150,7 @@ var treeTool = {
30149
30150
  return final;
30150
30151
  },
30151
30152
  async *executeStream(input, ctx, opts) {
30152
- const basePath = input.path ? safeResolve(input.path, ctx) : ctx.cwd;
30153
+ const basePath = input.path ? await safeResolveReal(input.path, ctx) : ctx.cwd;
30153
30154
  const maxDepth = input.depth ?? 3;
30154
30155
  const showFiles = input.show_files ?? true;
30155
30156
  const showDirs = input.show_dirs ?? true;
@@ -30329,7 +30330,7 @@ var typecheckTool = {
30329
30330
  return final;
30330
30331
  },
30331
30332
  async *executeStream(input, ctx, opts) {
30332
- const cwd = input.cwd ? safeResolve(input.cwd, ctx) : ctx.cwd;
30333
+ const cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.cwd;
30333
30334
  const bridge = await tryLegacyCodeOperation("semantic", {
30334
30335
  cwd,
30335
30336
  projectRoot: ctx.projectRoot,
@@ -30366,7 +30367,7 @@ var typecheckTool = {
30366
30367
  cmdArgs = ["tsc", ...tscArgs];
30367
30368
  }
30368
30369
  } else {
30369
- const tsconfig = input.project ? safeResolve(input.project, ctx) : await findTsConfig(cwd);
30370
+ const tsconfig = input.project ? await safeResolveReal(input.project, ctx) : await findTsConfig(cwd);
30370
30371
  const tscArgs = ["--noEmit"];
30371
30372
  if (input.strict) tscArgs.push("--strict");
30372
30373
  if (tsconfig) tscArgs.push("--project", tsconfig);
package/dist/install.js CHANGED
@@ -1048,6 +1048,7 @@ function utf8Prefix(text, maxBytes) {
1048
1048
  }
1049
1049
 
1050
1050
  // src/_util.ts
1051
+ import * as fsp2 from "node:fs/promises";
1051
1052
  import * as path3 from "node:path";
1052
1053
  import * as Core from "@wrongstack/core/utils";
1053
1054
  async function detectPackageManager(cwd, stopAt) {
@@ -1114,6 +1115,40 @@ function ensureInsideRoot(absPath, ctx) {
1114
1115
  function safeResolve(input, ctx) {
1115
1116
  return ensureInsideRoot(resolvePath(input, ctx), ctx);
1116
1117
  }
1118
+ async function resolveRealInsideRoot(absPath, ctx) {
1119
+ if (ctx.allowOutsideProjectRoot) return absPath;
1120
+ const realRoots = await Promise.all(
1121
+ allowedRoots(ctx).map((r) => fsp2.realpath(r).catch(() => path3.resolve(r)))
1122
+ );
1123
+ let probe = absPath;
1124
+ const pendingTail = [];
1125
+ for (; ; ) {
1126
+ let real;
1127
+ try {
1128
+ real = await fsp2.realpath(probe);
1129
+ } catch (err) {
1130
+ if (err.code === "ENOENT") {
1131
+ const parent = path3.dirname(probe);
1132
+ if (parent === probe) return absPath;
1133
+ pendingTail.unshift(path3.basename(probe));
1134
+ probe = parent;
1135
+ continue;
1136
+ }
1137
+ throw err;
1138
+ }
1139
+ const candidate = pendingTail.length > 0 ? path3.join(real, ...pendingTail) : real;
1140
+ if (isInsideAny(candidate, realRoots)) {
1141
+ return candidate;
1142
+ }
1143
+ throw new Error(
1144
+ `Path "${absPath}" resolves through a symlink outside project root "${realRoots[0]}"`
1145
+ );
1146
+ }
1147
+ }
1148
+ async function safeResolveReal(input, ctx) {
1149
+ const abs = safeResolve(input, ctx);
1150
+ return await resolveRealInsideRoot(abs, ctx);
1151
+ }
1117
1152
  var COMMAND_OUTPUT_MAX_BYTES = 32768;
1118
1153
  var REPEAT_RUN_THRESHOLD = 3;
1119
1154
  function collapseCarriageReturns(text) {
@@ -3905,7 +3940,7 @@ var installTool = {
3905
3940
  return final;
3906
3941
  },
3907
3942
  async *executeStream(input, ctx, opts) {
3908
- const cwd = input.cwd ? safeResolve(input.cwd, ctx) : ctx.cwd;
3943
+ const cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.cwd;
3909
3944
  if (!input.global) {
3910
3945
  const pkgList2 = input.packages ? Array.isArray(input.packages) ? input.packages : input.packages.split(",").map((p) => p.trim()) : [];
3911
3946
  const bridge = await tryLegacyPackageOperation(
package/dist/json.js CHANGED
@@ -174,8 +174,9 @@ async function resolveRealInsideRoot(absPath, ctx) {
174
174
  }
175
175
  throw err;
176
176
  }
177
- if (isInsideAny(real, realRoots)) {
178
- return pendingTail.length > 0 ? path.join(real, ...pendingTail) : real;
177
+ const candidate = pendingTail.length > 0 ? path.join(real, ...pendingTail) : real;
178
+ if (isInsideAny(candidate, realRoots)) {
179
+ return candidate;
179
180
  }
180
181
  throw new Error(
181
182
  `Path "${absPath}" resolves through a symlink outside project root "${realRoots[0]}"`
@@ -3214,8 +3214,9 @@ async function resolveRealInsideRoot(absPath, ctx) {
3214
3214
  }
3215
3215
  throw err;
3216
3216
  }
3217
- if (isInsideAny(real, realRoots)) {
3218
- return pendingTail.length > 0 ? path5.join(real, ...pendingTail) : real;
3217
+ const candidate = pendingTail.length > 0 ? path5.join(real, ...pendingTail) : real;
3218
+ if (isInsideAny(candidate, realRoots)) {
3219
+ return candidate;
3219
3220
  }
3220
3221
  throw new Error(
3221
3222
  `Path "${absPath}" resolves through a symlink outside project root "${realRoots[0]}"`
package/dist/lint.js CHANGED
@@ -1041,6 +1041,7 @@ function utf8Prefix(text, maxBytes) {
1041
1041
  }
1042
1042
 
1043
1043
  // src/_util.ts
1044
+ import * as fsp2 from "node:fs/promises";
1044
1045
  import * as path3 from "node:path";
1045
1046
  import * as Core from "@wrongstack/core/utils";
1046
1047
  function resolvePath(input, ctx) {
@@ -1064,6 +1065,40 @@ function ensureInsideRoot(absPath, ctx) {
1064
1065
  function safeResolve(input, ctx) {
1065
1066
  return ensureInsideRoot(resolvePath(input, ctx), ctx);
1066
1067
  }
1068
+ async function resolveRealInsideRoot(absPath, ctx) {
1069
+ if (ctx.allowOutsideProjectRoot) return absPath;
1070
+ const realRoots = await Promise.all(
1071
+ allowedRoots(ctx).map((r) => fsp2.realpath(r).catch(() => path3.resolve(r)))
1072
+ );
1073
+ let probe = absPath;
1074
+ const pendingTail = [];
1075
+ for (; ; ) {
1076
+ let real;
1077
+ try {
1078
+ real = await fsp2.realpath(probe);
1079
+ } catch (err) {
1080
+ if (err.code === "ENOENT") {
1081
+ const parent = path3.dirname(probe);
1082
+ if (parent === probe) return absPath;
1083
+ pendingTail.unshift(path3.basename(probe));
1084
+ probe = parent;
1085
+ continue;
1086
+ }
1087
+ throw err;
1088
+ }
1089
+ const candidate = pendingTail.length > 0 ? path3.join(real, ...pendingTail) : real;
1090
+ if (isInsideAny(candidate, realRoots)) {
1091
+ return candidate;
1092
+ }
1093
+ throw new Error(
1094
+ `Path "${absPath}" resolves through a symlink outside project root "${realRoots[0]}"`
1095
+ );
1096
+ }
1097
+ }
1098
+ async function safeResolveReal(input, ctx) {
1099
+ const abs = safeResolve(input, ctx);
1100
+ return await resolveRealInsideRoot(abs, ctx);
1101
+ }
1067
1102
  var COMMAND_OUTPUT_MAX_BYTES = 32768;
1068
1103
  var REPEAT_RUN_THRESHOLD = 3;
1069
1104
  function collapseCarriageReturns(text) {
@@ -3584,7 +3619,7 @@ var lintTool = {
3584
3619
  return final;
3585
3620
  },
3586
3621
  async *executeStream(input, ctx, opts) {
3587
- const cwd = input.cwd ? safeResolve(input.cwd, ctx) : ctx.cwd;
3622
+ const cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.cwd;
3588
3623
  const linter = input.linter ?? "auto";
3589
3624
  if (linter === "auto" && !input.files) {
3590
3625
  const bridge = await tryLegacyCodeOperation("lint", {