@wrongstack/tools 0.306.2 → 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/tree.js CHANGED
@@ -4,6 +4,7 @@ import * as path2 from "node:path";
4
4
  import { DEFAULT_WALK_IGNORE_DIRS, expectDefined } from "@wrongstack/core/utils";
5
5
 
6
6
  // src/_util.ts
7
+ import * as fsp from "node:fs/promises";
7
8
  import * as path from "node:path";
8
9
  import * as Core from "@wrongstack/core/utils";
9
10
  function resolvePath(input, ctx) {
@@ -27,6 +28,40 @@ function ensureInsideRoot(absPath, ctx) {
27
28
  function safeResolve(input, ctx) {
28
29
  return ensureInsideRoot(resolvePath(input, ctx), ctx);
29
30
  }
31
+ async function resolveRealInsideRoot(absPath, ctx) {
32
+ if (ctx.allowOutsideProjectRoot) return absPath;
33
+ const realRoots = await Promise.all(
34
+ allowedRoots(ctx).map((r) => fsp.realpath(r).catch(() => path.resolve(r)))
35
+ );
36
+ let probe = absPath;
37
+ const pendingTail = [];
38
+ for (; ; ) {
39
+ let real;
40
+ try {
41
+ real = await fsp.realpath(probe);
42
+ } catch (err) {
43
+ if (err.code === "ENOENT") {
44
+ const parent = path.dirname(probe);
45
+ if (parent === probe) return absPath;
46
+ pendingTail.unshift(path.basename(probe));
47
+ probe = parent;
48
+ continue;
49
+ }
50
+ throw err;
51
+ }
52
+ const candidate = pendingTail.length > 0 ? path.join(real, ...pendingTail) : real;
53
+ if (isInsideAny(candidate, realRoots)) {
54
+ return candidate;
55
+ }
56
+ throw new Error(
57
+ `Path "${absPath}" resolves through a symlink outside project root "${realRoots[0]}"`
58
+ );
59
+ }
60
+ }
61
+ async function safeResolveReal(input, ctx) {
62
+ const abs = safeResolve(input, ctx);
63
+ return await resolveRealInsideRoot(abs, ctx);
64
+ }
30
65
 
31
66
  // src/tree.ts
32
67
  var DEFAULT_IGNORE = /* @__PURE__ */ new Set([
@@ -102,7 +137,7 @@ var treeTool = {
102
137
  return final;
103
138
  },
104
139
  async *executeStream(input, ctx, opts) {
105
- const basePath = input.path ? safeResolve(input.path, ctx) : ctx.cwd;
140
+ const basePath = input.path ? await safeResolveReal(input.path, ctx) : ctx.cwd;
106
141
  const maxDepth = input.depth ?? 3;
107
142
  const showFiles = input.show_files ?? true;
108
143
  const showDirs = input.show_dirs ?? true;
package/dist/typecheck.js CHANGED
@@ -1044,6 +1044,7 @@ function utf8Prefix(text, maxBytes) {
1044
1044
  }
1045
1045
 
1046
1046
  // src/_util.ts
1047
+ import * as fsp2 from "node:fs/promises";
1047
1048
  import * as path3 from "node:path";
1048
1049
  import * as Core from "@wrongstack/core/utils";
1049
1050
  async function detectPackageManager(cwd, stopAt) {
@@ -1110,6 +1111,40 @@ function ensureInsideRoot(absPath, ctx) {
1110
1111
  function safeResolve(input, ctx) {
1111
1112
  return ensureInsideRoot(resolvePath(input, ctx), ctx);
1112
1113
  }
1114
+ async function resolveRealInsideRoot(absPath, ctx) {
1115
+ if (ctx.allowOutsideProjectRoot) return absPath;
1116
+ const realRoots = await Promise.all(
1117
+ allowedRoots(ctx).map((r) => fsp2.realpath(r).catch(() => path3.resolve(r)))
1118
+ );
1119
+ let probe = absPath;
1120
+ const pendingTail = [];
1121
+ for (; ; ) {
1122
+ let real;
1123
+ try {
1124
+ real = await fsp2.realpath(probe);
1125
+ } catch (err) {
1126
+ if (err.code === "ENOENT") {
1127
+ const parent = path3.dirname(probe);
1128
+ if (parent === probe) return absPath;
1129
+ pendingTail.unshift(path3.basename(probe));
1130
+ probe = parent;
1131
+ continue;
1132
+ }
1133
+ throw err;
1134
+ }
1135
+ const candidate = pendingTail.length > 0 ? path3.join(real, ...pendingTail) : real;
1136
+ if (isInsideAny(candidate, realRoots)) {
1137
+ return candidate;
1138
+ }
1139
+ throw new Error(
1140
+ `Path "${absPath}" resolves through a symlink outside project root "${realRoots[0]}"`
1141
+ );
1142
+ }
1143
+ }
1144
+ async function safeResolveReal(input, ctx) {
1145
+ const abs = safeResolve(input, ctx);
1146
+ return await resolveRealInsideRoot(abs, ctx);
1147
+ }
1113
1148
  var COMMAND_OUTPUT_MAX_BYTES = 32768;
1114
1149
  var REPEAT_RUN_THRESHOLD = 3;
1115
1150
  function collapseCarriageReturns(text) {
@@ -3629,7 +3664,7 @@ var typecheckTool = {
3629
3664
  return final;
3630
3665
  },
3631
3666
  async *executeStream(input, ctx, opts) {
3632
- const cwd = input.cwd ? safeResolve(input.cwd, ctx) : ctx.cwd;
3667
+ const cwd = input.cwd ? await safeResolveReal(input.cwd, ctx) : ctx.cwd;
3633
3668
  const bridge = await tryLegacyCodeOperation("semantic", {
3634
3669
  cwd,
3635
3670
  projectRoot: ctx.projectRoot,
@@ -3666,7 +3701,7 @@ var typecheckTool = {
3666
3701
  cmdArgs = ["tsc", ...tscArgs];
3667
3702
  }
3668
3703
  } else {
3669
- const tsconfig = input.project ? safeResolve(input.project, ctx) : await findTsConfig(cwd);
3704
+ const tsconfig = input.project ? await safeResolveReal(input.project, ctx) : await findTsConfig(cwd);
3670
3705
  const tscArgs = ["--noEmit"];
3671
3706
  if (input.strict) tscArgs.push("--strict");
3672
3707
  if (tsconfig) tscArgs.push("--project", tsconfig);
package/dist/write.js CHANGED
@@ -144,8 +144,9 @@ async function resolveRealInsideRoot(absPath, ctx) {
144
144
  }
145
145
  throw err;
146
146
  }
147
- if (isInsideAny(real, realRoots)) {
148
- return pendingTail.length > 0 ? path2.join(real, ...pendingTail) : real;
147
+ const candidate = pendingTail.length > 0 ? path2.join(real, ...pendingTail) : real;
148
+ if (isInsideAny(candidate, realRoots)) {
149
+ return candidate;
149
150
  }
150
151
  throw new Error(
151
152
  `Path "${absPath}" resolves through a symlink outside project root "${realRoots[0]}"`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wrongstack/tools",
3
- "version": "0.306.2",
3
+ "version": "0.306.4",
4
4
  "license": "MIT",
5
5
  "description": "WrongStack built-in tools: read/write/edit, bash/exec, grep/glob, git, fetch, test, lint, and more.",
6
6
  "repository": {
@@ -253,9 +253,9 @@
253
253
  "turndown": "^7.2.4",
254
254
  "undici": "^8.9.0",
255
255
  "web-tree-sitter": "0.26.12",
256
- "@wrongstack/core": "0.306.2",
257
- "@wrongstack/kanban": "0.306.2",
258
- "@wrongstack/persistence": "0.306.2"
256
+ "@wrongstack/kanban": "0.306.4",
257
+ "@wrongstack/core": "0.306.4",
258
+ "@wrongstack/persistence": "0.306.4"
259
259
  },
260
260
  "devDependencies": {
261
261
  "@types/node": "^26.1.2",