@wrongstack/tools 0.6.0 → 0.6.1
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/builtin.js +50 -55
- package/dist/builtin.js.map +1 -1
- package/dist/index.js +50 -55
- package/dist/index.js.map +1 -1
- package/dist/outdated.js +2 -7
- package/dist/outdated.js.map +1 -1
- package/dist/pack.js +50 -55
- package/dist/pack.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as fs4 from 'fs/promises';
|
|
2
|
+
import { stat } from 'fs/promises';
|
|
2
3
|
import * as path from 'path';
|
|
3
4
|
import { dirname } from 'path';
|
|
4
5
|
import { atomicWrite, unifiedDiff, detectNewlineStyle, normalizeToLf, toStyle, compileGlob, buildChildEnv, stripAnsi, loadPlan, emptyPlan, clearPlan, savePlan, getPlanTemplate, addPlanItem, deriveTodosFromPlanItem, removePlanItem, setPlanItemStatus, formatPlan } from '@wrongstack/core';
|
|
@@ -8,12 +9,7 @@ import * as dns from 'dns/promises';
|
|
|
8
9
|
import * as net from 'net';
|
|
9
10
|
import { statSync } from 'fs';
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
13
|
-
}) : x)(function(x) {
|
|
14
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
15
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
16
|
-
});
|
|
12
|
+
// src/read.ts
|
|
17
13
|
function resolvePath(input, ctx) {
|
|
18
14
|
return path.isAbsolute(input) ? path.normalize(input) : path.resolve(ctx.cwd, input);
|
|
19
15
|
}
|
|
@@ -67,17 +63,17 @@ var readTool = {
|
|
|
67
63
|
async execute(input, ctx) {
|
|
68
64
|
if (!input?.path) throw new Error("read: path is required");
|
|
69
65
|
const absPath = safeResolve(input.path, ctx);
|
|
70
|
-
let
|
|
66
|
+
let stat10;
|
|
71
67
|
try {
|
|
72
|
-
|
|
68
|
+
stat10 = await fs4.stat(absPath);
|
|
73
69
|
} catch (err) {
|
|
74
70
|
const code = err.code;
|
|
75
71
|
if (code === "ENOENT") throw new Error(`read: file not found "${input.path}"`);
|
|
76
72
|
throw new Error(`read: failed to stat "${input.path}": ${err instanceof Error ? err.message : String(err)}`);
|
|
77
73
|
}
|
|
78
|
-
if (!
|
|
79
|
-
if (
|
|
80
|
-
throw new Error(`read: file too large (${
|
|
74
|
+
if (!stat10.isFile()) throw new Error(`read: "${input.path}" is not a regular file`);
|
|
75
|
+
if (stat10.size > MAX_BYTES) {
|
|
76
|
+
throw new Error(`read: file too large (${stat10.size} bytes, limit ${MAX_BYTES})`);
|
|
81
77
|
}
|
|
82
78
|
const buf = await fs4.readFile(absPath);
|
|
83
79
|
if (isBinaryBuffer(buf)) {
|
|
@@ -89,14 +85,14 @@ var readTool = {
|
|
|
89
85
|
const offset = Math.max(1, input.offset ?? 1);
|
|
90
86
|
const limit = Math.max(0, Math.min(input.limit ?? 2e3, 5e3));
|
|
91
87
|
if (limit === 0) {
|
|
92
|
-
ctx.recordRead(absPath,
|
|
88
|
+
ctx.recordRead(absPath, stat10.mtimeMs);
|
|
93
89
|
return { text: "", total_lines: total, encoding: "utf8", truncated: total > 0 };
|
|
94
90
|
}
|
|
95
91
|
const slice = allLines.slice(offset - 1, offset - 1 + limit);
|
|
96
92
|
const truncated = offset - 1 + slice.length < total;
|
|
97
93
|
const width = String(offset + slice.length - 1).length;
|
|
98
94
|
const numbered = slice.map((line, i) => `${String(offset + i).padStart(width, " ")}\u2192${line}`).join("\n");
|
|
99
|
-
ctx.recordRead(absPath,
|
|
95
|
+
ctx.recordRead(absPath, stat10.mtimeMs);
|
|
100
96
|
return {
|
|
101
97
|
text: numbered,
|
|
102
98
|
total_lines: total,
|
|
@@ -128,12 +124,12 @@ var writeTool = {
|
|
|
128
124
|
let existed = false;
|
|
129
125
|
let prev = "";
|
|
130
126
|
try {
|
|
131
|
-
const
|
|
132
|
-
existed =
|
|
127
|
+
const stat11 = await fs4.stat(absPath);
|
|
128
|
+
existed = stat11.isFile();
|
|
133
129
|
if (existed) {
|
|
134
130
|
if (!ctx.hasRead(absPath)) {
|
|
135
131
|
prev = await fs4.readFile(absPath, "utf8");
|
|
136
|
-
ctx.recordRead(absPath,
|
|
132
|
+
ctx.recordRead(absPath, stat11.mtimeMs);
|
|
137
133
|
} else {
|
|
138
134
|
prev = await fs4.readFile(absPath, "utf8");
|
|
139
135
|
}
|
|
@@ -146,8 +142,8 @@ var writeTool = {
|
|
|
146
142
|
await atomicWrite(absPath, input.content);
|
|
147
143
|
const diff = existed ? unifiedDiff(prev, input.content, { fromFile: input.path, toFile: input.path }) : `+++ ${input.path}
|
|
148
144
|
+ (new file, ${input.content.split("\n").length} lines)`;
|
|
149
|
-
const
|
|
150
|
-
ctx.recordRead(absPath,
|
|
145
|
+
const stat10 = await fs4.stat(absPath);
|
|
146
|
+
ctx.recordRead(absPath, stat10.mtimeMs);
|
|
151
147
|
ctx.session.recordFileChange({
|
|
152
148
|
path: absPath,
|
|
153
149
|
action: existed ? "modified" : "created",
|
|
@@ -186,13 +182,13 @@ var editTool = {
|
|
|
186
182
|
if (input.new_string === void 0) throw new Error("edit: new_string is required");
|
|
187
183
|
if (input.old_string === "") throw new Error("edit: old_string cannot be empty");
|
|
188
184
|
const absPath = safeResolve(input.path, ctx);
|
|
189
|
-
const
|
|
185
|
+
const stat10 = await fs4.stat(absPath).catch((err) => {
|
|
190
186
|
if (err.code === "ENOENT") {
|
|
191
187
|
throw new Error(`edit: file "${input.path}" does not exist. Use \`write\` instead.`);
|
|
192
188
|
}
|
|
193
189
|
throw err;
|
|
194
190
|
});
|
|
195
|
-
if (!
|
|
191
|
+
if (!stat10.isFile()) throw new Error(`edit: "${input.path}" is not a regular file`);
|
|
196
192
|
if (!ctx.hasRead(absPath)) {
|
|
197
193
|
throw new Error(`edit: file "${input.path}" was not read in this session. Read it first.`);
|
|
198
194
|
}
|
|
@@ -384,8 +380,8 @@ var replaceTool = {
|
|
|
384
380
|
}
|
|
385
381
|
const rel = path.relative(ctx.projectRoot, realPath);
|
|
386
382
|
if (rel.startsWith("..") || path.isAbsolute(rel)) continue;
|
|
387
|
-
const
|
|
388
|
-
if (!
|
|
383
|
+
const stat10 = await fs4.stat(realPath).catch(() => null);
|
|
384
|
+
if (!stat10 || !stat10.isFile()) continue;
|
|
389
385
|
let content;
|
|
390
386
|
try {
|
|
391
387
|
const buf = await fs4.readFile(realPath);
|
|
@@ -410,7 +406,7 @@ var replaceTool = {
|
|
|
410
406
|
totalReplacements += count;
|
|
411
407
|
if (!dryRun) {
|
|
412
408
|
const newContent = toStyle(newContentLf, style);
|
|
413
|
-
await atomicWrite(realPath, newContent, { mode:
|
|
409
|
+
await atomicWrite(realPath, newContent, { mode: stat10.mode & 511 });
|
|
414
410
|
}
|
|
415
411
|
const diff = dryRun || matches.length > 0 ? unifiedDiff(content, toStyle(newContentLf, style), {
|
|
416
412
|
fromFile: absPath,
|
|
@@ -440,8 +436,8 @@ async function resolveFiles(filesInput, ctx, extraGlob) {
|
|
|
440
436
|
const resolved = [];
|
|
441
437
|
for (const p of parts) {
|
|
442
438
|
const absPath = safeResolve(p, ctx);
|
|
443
|
-
const
|
|
444
|
-
if (
|
|
439
|
+
const stat10 = await fs4.stat(absPath).catch(() => null);
|
|
440
|
+
if (stat10?.isFile()) {
|
|
445
441
|
resolved.push(absPath);
|
|
446
442
|
}
|
|
447
443
|
}
|
|
@@ -500,8 +496,8 @@ async function globNative(pattern, base, extraGlob) {
|
|
|
500
496
|
if (DEFAULT_IGNORE.includes(e.name)) continue;
|
|
501
497
|
const full = path.join(dir, e.name);
|
|
502
498
|
try {
|
|
503
|
-
const
|
|
504
|
-
if (
|
|
499
|
+
const stat10 = await fs4.lstat(full);
|
|
500
|
+
if (stat10.isSymbolicLink()) continue;
|
|
505
501
|
} catch {
|
|
506
502
|
continue;
|
|
507
503
|
}
|
|
@@ -817,8 +813,8 @@ async function runNative(input, base, mode, limit, signal) {
|
|
|
817
813
|
if (globRe && !globRe.test(e.name) && !globRe.test(full)) continue;
|
|
818
814
|
if (globRe) globRe.lastIndex = 0;
|
|
819
815
|
try {
|
|
820
|
-
const
|
|
821
|
-
if (
|
|
816
|
+
const stat10 = await fs4.stat(full);
|
|
817
|
+
if (stat10.size > 1e6) continue;
|
|
822
818
|
const head = await fs4.readFile(full);
|
|
823
819
|
if (isBinaryBuffer(head)) continue;
|
|
824
820
|
const text = head.toString("utf8");
|
|
@@ -2424,8 +2420,8 @@ function findGitDir(cwd, projectRoot) {
|
|
|
2424
2420
|
let dir = cwd;
|
|
2425
2421
|
for (let i = 0; i < 20; i++) {
|
|
2426
2422
|
try {
|
|
2427
|
-
const
|
|
2428
|
-
if (
|
|
2423
|
+
const stat10 = statSync(`${dir}/.git`);
|
|
2424
|
+
if (stat10.isDirectory()) return dir;
|
|
2429
2425
|
} catch {
|
|
2430
2426
|
}
|
|
2431
2427
|
if (dir === root) break;
|
|
@@ -2810,8 +2806,8 @@ function findGitDir2(cwd) {
|
|
|
2810
2806
|
let dir = cwd;
|
|
2811
2807
|
for (let i = 0; i < 20; i++) {
|
|
2812
2808
|
try {
|
|
2813
|
-
const
|
|
2814
|
-
if (
|
|
2809
|
+
const stat10 = statSync(path.join(dir, ".git"));
|
|
2810
|
+
if (stat10.isDirectory()) return dir;
|
|
2815
2811
|
} catch {
|
|
2816
2812
|
}
|
|
2817
2813
|
const parent = path.dirname(dir);
|
|
@@ -2850,8 +2846,8 @@ async function fileDiff(input, ctx, signal) {
|
|
|
2850
2846
|
const results = [];
|
|
2851
2847
|
for (const file of files) {
|
|
2852
2848
|
const absPath = safeResolve(file, ctx);
|
|
2853
|
-
const
|
|
2854
|
-
if (!
|
|
2849
|
+
const stat10 = await fs4.stat(absPath).catch(() => null);
|
|
2850
|
+
if (!stat10?.isFile()) continue;
|
|
2855
2851
|
const content = await fs4.readFile(absPath, "utf8");
|
|
2856
2852
|
const lines = content.split(/\r?\n/);
|
|
2857
2853
|
results.push(`--- ${file}
|
|
@@ -3193,11 +3189,11 @@ var lintTool = {
|
|
|
3193
3189
|
}
|
|
3194
3190
|
};
|
|
3195
3191
|
async function detectLinter(cwd) {
|
|
3196
|
-
const { stat:
|
|
3192
|
+
const { stat: stat10 } = await import('fs/promises');
|
|
3197
3193
|
const checks = ["biome.json", ".eslintrc.json", "tslint.json", ".eslintrc.js", "tsconfig.json"];
|
|
3198
3194
|
for (const f of checks) {
|
|
3199
3195
|
try {
|
|
3200
|
-
await
|
|
3196
|
+
await stat10(`${cwd}/${f}`);
|
|
3201
3197
|
if (f.includes("biome")) return "biome";
|
|
3202
3198
|
if (f.includes("eslint")) return "eslint";
|
|
3203
3199
|
if (f.includes("tslint")) return "tslint";
|
|
@@ -3292,13 +3288,13 @@ var formatTool = {
|
|
|
3292
3288
|
}
|
|
3293
3289
|
};
|
|
3294
3290
|
async function detectFixer(cwd) {
|
|
3295
|
-
const { stat:
|
|
3291
|
+
const { stat: stat10 } = await import('fs/promises');
|
|
3296
3292
|
try {
|
|
3297
|
-
await
|
|
3293
|
+
await stat10(`${cwd}/biome.json`);
|
|
3298
3294
|
return "biome";
|
|
3299
3295
|
} catch {
|
|
3300
3296
|
try {
|
|
3301
|
-
await
|
|
3297
|
+
await stat10(`${cwd}/.prettierrc`);
|
|
3302
3298
|
return "prettier";
|
|
3303
3299
|
} catch {
|
|
3304
3300
|
return "biome";
|
|
@@ -3374,11 +3370,11 @@ var typecheckTool = {
|
|
|
3374
3370
|
}
|
|
3375
3371
|
};
|
|
3376
3372
|
async function findTsConfig(cwd) {
|
|
3377
|
-
const { stat:
|
|
3373
|
+
const { stat: stat10 } = await import('fs/promises');
|
|
3378
3374
|
const candidates = ["tsconfig.json", "tsconfig.base.json"];
|
|
3379
3375
|
for (const f of candidates) {
|
|
3380
3376
|
try {
|
|
3381
|
-
const s = await
|
|
3377
|
+
const s = await stat10(path.join(cwd, f));
|
|
3382
3378
|
if (s.isFile()) return path.join(cwd, f);
|
|
3383
3379
|
} catch {
|
|
3384
3380
|
}
|
|
@@ -3455,11 +3451,11 @@ var testTool = {
|
|
|
3455
3451
|
}
|
|
3456
3452
|
};
|
|
3457
3453
|
async function detectRunner(cwd) {
|
|
3458
|
-
const { stat:
|
|
3454
|
+
const { stat: stat10 } = await import('fs/promises');
|
|
3459
3455
|
const candidates = ["vitest.config.ts", "jest.config.js", ".mocharc.json"];
|
|
3460
3456
|
for (const f of candidates) {
|
|
3461
3457
|
try {
|
|
3462
|
-
await
|
|
3458
|
+
await stat10(path.join(cwd, f));
|
|
3463
3459
|
if (f.includes("vitest")) return "vitest";
|
|
3464
3460
|
if (f.includes("jest")) return "jest";
|
|
3465
3461
|
if (f.includes("mocha")) return "mocha";
|
|
@@ -3630,13 +3626,13 @@ var installTool = {
|
|
|
3630
3626
|
}
|
|
3631
3627
|
};
|
|
3632
3628
|
async function detectPackageManager(cwd) {
|
|
3633
|
-
const { stat:
|
|
3629
|
+
const { stat: stat10 } = await import('fs/promises');
|
|
3634
3630
|
try {
|
|
3635
|
-
await
|
|
3631
|
+
await stat10(`${cwd}/pnpm-lock.yaml`);
|
|
3636
3632
|
return "pnpm";
|
|
3637
3633
|
} catch {
|
|
3638
3634
|
try {
|
|
3639
|
-
await
|
|
3635
|
+
await stat10(`${cwd}/yarn.lock`);
|
|
3640
3636
|
return "yarn";
|
|
3641
3637
|
} catch {
|
|
3642
3638
|
return "npm";
|
|
@@ -3695,14 +3691,14 @@ var auditTool = {
|
|
|
3695
3691
|
}
|
|
3696
3692
|
};
|
|
3697
3693
|
async function detectManager(cwd) {
|
|
3698
|
-
const { stat:
|
|
3694
|
+
const { stat: stat10 } = await import('fs/promises');
|
|
3699
3695
|
try {
|
|
3700
|
-
await
|
|
3696
|
+
await stat10(`${cwd}/pnpm-lock.yaml`);
|
|
3701
3697
|
return "pnpm";
|
|
3702
3698
|
} catch {
|
|
3703
3699
|
}
|
|
3704
3700
|
try {
|
|
3705
|
-
await
|
|
3701
|
+
await stat10(`${cwd}/yarn.lock`);
|
|
3706
3702
|
return "yarn";
|
|
3707
3703
|
} catch {
|
|
3708
3704
|
}
|
|
@@ -3790,14 +3786,13 @@ var outdatedTool = {
|
|
|
3790
3786
|
}
|
|
3791
3787
|
};
|
|
3792
3788
|
async function detectManager2(cwd) {
|
|
3793
|
-
const { stat: stat9 } = __require("fs/promises");
|
|
3794
3789
|
try {
|
|
3795
|
-
await
|
|
3790
|
+
await stat(`${cwd}/pnpm-lock.yaml`);
|
|
3796
3791
|
return "pnpm";
|
|
3797
3792
|
} catch {
|
|
3798
3793
|
}
|
|
3799
3794
|
try {
|
|
3800
|
-
await
|
|
3795
|
+
await stat(`${cwd}/yarn.lock`);
|
|
3801
3796
|
return "yarn";
|
|
3802
3797
|
} catch {
|
|
3803
3798
|
}
|
|
@@ -4133,8 +4128,8 @@ async function resolveFiles2(filesInput, cwd) {
|
|
|
4133
4128
|
for (const f of files) {
|
|
4134
4129
|
const absPath = f.trim().startsWith("/") ? f.trim() : `${cwd}/${f.trim()}`;
|
|
4135
4130
|
try {
|
|
4136
|
-
const
|
|
4137
|
-
if (
|
|
4131
|
+
const stat10 = await fs4.stat(absPath);
|
|
4132
|
+
if (stat10.isFile()) resolved.push(absPath);
|
|
4138
4133
|
} catch {
|
|
4139
4134
|
}
|
|
4140
4135
|
}
|