pruneguard 0.2.1 → 0.3.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/README.md +234 -120
- package/bin/pruneguard +0 -0
- package/configuration_schema.json +110 -0
- package/dist/bin.mjs +5 -1
- package/dist/index.d.mts +177 -4
- package/dist/index.mjs +64 -5
- package/dist/{runtime-BxlGT_W-.mjs → runtime-BSHQsTbN.mjs} +71 -9
- package/package.json +11 -9
- package/report_schema.json +216 -0
- package/review_report_schema.json +624 -0
- package/safe_delete_report_schema.json +200 -0
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
//#region src-js/runtime.d.ts
|
|
2
|
+
type ResolutionSource = "env" | "platform-package" | "dev" | "path";
|
|
3
|
+
type ResolutionInfo = {
|
|
4
|
+
binaryPath: string;
|
|
5
|
+
source: ResolutionSource;
|
|
6
|
+
platformPackage?: string;
|
|
7
|
+
schemaPath?: string;
|
|
8
|
+
version?: string;
|
|
9
|
+
platform?: string;
|
|
10
|
+
};
|
|
2
11
|
type CommandResult = {
|
|
3
12
|
args: string[];
|
|
4
13
|
cwd?: string;
|
|
@@ -14,12 +23,14 @@ declare class PruneguardExecutionError extends Error {
|
|
|
14
23
|
stderr?: string;
|
|
15
24
|
binaryPath?: string;
|
|
16
25
|
args?: string[];
|
|
26
|
+
resolutionSource?: ResolutionSource;
|
|
17
27
|
constructor(code: PruneguardExecutionError["code"], message: string, details?: {
|
|
18
28
|
exitCode?: number;
|
|
19
29
|
stdout?: string;
|
|
20
30
|
stderr?: string;
|
|
21
31
|
binaryPath?: string;
|
|
22
32
|
args?: string[];
|
|
33
|
+
resolutionSource?: ResolutionSource;
|
|
23
34
|
});
|
|
24
35
|
}
|
|
25
36
|
//#endregion
|
|
@@ -113,6 +124,8 @@ type AnalysisReport = {
|
|
|
113
124
|
}>;
|
|
114
125
|
suggestion?: string;
|
|
115
126
|
ruleName?: string;
|
|
127
|
+
primaryActionKind?: string;
|
|
128
|
+
actionKinds?: string[];
|
|
116
129
|
}>;
|
|
117
130
|
entrypoints: Array<{
|
|
118
131
|
path: string;
|
|
@@ -164,6 +177,12 @@ type AnalysisReport = {
|
|
|
164
177
|
cacheEntriesRead: number;
|
|
165
178
|
cacheEntriesWritten: number;
|
|
166
179
|
affectedScopeIncomplete: boolean;
|
|
180
|
+
executionMode?: "oneshot" | "daemon";
|
|
181
|
+
indexWarm?: boolean;
|
|
182
|
+
indexAgeMs?: number;
|
|
183
|
+
reusedGraphNodes?: number;
|
|
184
|
+
reusedGraphEdges?: number;
|
|
185
|
+
watcherLagMs?: number;
|
|
167
186
|
};
|
|
168
187
|
};
|
|
169
188
|
type MigrationOutput = {
|
|
@@ -197,8 +216,156 @@ type ExplainReport = {
|
|
|
197
216
|
focusFiltered: boolean;
|
|
198
217
|
};
|
|
199
218
|
type PruneguardConfig = Record<string, unknown>;
|
|
219
|
+
type ReviewOptions = {
|
|
220
|
+
cwd?: string;
|
|
221
|
+
config?: string;
|
|
222
|
+
profile?: Profile;
|
|
223
|
+
baseRef?: string;
|
|
224
|
+
noCache?: boolean;
|
|
225
|
+
noBaseline?: boolean;
|
|
226
|
+
};
|
|
227
|
+
type ReviewReport = {
|
|
228
|
+
baseRef?: string;
|
|
229
|
+
changedFiles: string[];
|
|
230
|
+
newFindings: AnalysisReport["findings"];
|
|
231
|
+
blockingFindings: AnalysisReport["findings"];
|
|
232
|
+
advisoryFindings: AnalysisReport["findings"];
|
|
233
|
+
trust: {
|
|
234
|
+
fullScope: boolean;
|
|
235
|
+
baselineApplied: boolean;
|
|
236
|
+
unresolvedPressure: number;
|
|
237
|
+
confidenceCounts: {
|
|
238
|
+
high: number;
|
|
239
|
+
medium: number;
|
|
240
|
+
low: number;
|
|
241
|
+
};
|
|
242
|
+
};
|
|
243
|
+
recommendations: string[];
|
|
244
|
+
proposedActions?: Array<{
|
|
245
|
+
id: string;
|
|
246
|
+
kind: string;
|
|
247
|
+
targets: string[];
|
|
248
|
+
why: string;
|
|
249
|
+
preconditions: string[];
|
|
250
|
+
steps: Array<{
|
|
251
|
+
description: string;
|
|
252
|
+
file?: string;
|
|
253
|
+
action?: string;
|
|
254
|
+
}>;
|
|
255
|
+
verification: string[];
|
|
256
|
+
risk: "low" | "medium" | "high";
|
|
257
|
+
confidence: "high" | "medium" | "low";
|
|
258
|
+
}>;
|
|
259
|
+
executionMode?: "oneshot" | "daemon";
|
|
260
|
+
latencyMs?: number;
|
|
261
|
+
};
|
|
262
|
+
type SafeDeleteOptions = {
|
|
263
|
+
cwd?: string;
|
|
264
|
+
config?: string;
|
|
265
|
+
profile?: Profile;
|
|
266
|
+
targets: string[];
|
|
267
|
+
noCache?: boolean;
|
|
268
|
+
};
|
|
269
|
+
type SafeDeleteReport = {
|
|
270
|
+
targets: string[];
|
|
271
|
+
safe: Array<{
|
|
272
|
+
target: string;
|
|
273
|
+
confidence?: "high" | "medium" | "low";
|
|
274
|
+
reasons: string[];
|
|
275
|
+
}>;
|
|
276
|
+
needsReview: Array<{
|
|
277
|
+
target: string;
|
|
278
|
+
confidence?: "high" | "medium" | "low";
|
|
279
|
+
reasons: string[];
|
|
280
|
+
}>;
|
|
281
|
+
blocked: Array<{
|
|
282
|
+
target: string;
|
|
283
|
+
confidence?: "high" | "medium" | "low";
|
|
284
|
+
reasons: string[];
|
|
285
|
+
}>;
|
|
286
|
+
deletionOrder: string[];
|
|
287
|
+
evidence: Array<{
|
|
288
|
+
kind: string;
|
|
289
|
+
file?: string;
|
|
290
|
+
line?: number;
|
|
291
|
+
description: string;
|
|
292
|
+
}>;
|
|
293
|
+
};
|
|
294
|
+
type FixPlanOptions = {
|
|
295
|
+
cwd?: string;
|
|
296
|
+
config?: string;
|
|
297
|
+
profile?: Profile;
|
|
298
|
+
targets: string[];
|
|
299
|
+
noCache?: boolean;
|
|
300
|
+
};
|
|
301
|
+
type SuggestRulesOptions = {
|
|
302
|
+
cwd?: string;
|
|
303
|
+
config?: string;
|
|
304
|
+
profile?: Profile;
|
|
305
|
+
noCache?: boolean;
|
|
306
|
+
};
|
|
307
|
+
type SuggestRulesReport = {
|
|
308
|
+
suggestedRules: Array<{
|
|
309
|
+
kind: string;
|
|
310
|
+
name: string;
|
|
311
|
+
description: string;
|
|
312
|
+
configFragment: Record<string, unknown>;
|
|
313
|
+
confidence: "high" | "medium" | "low";
|
|
314
|
+
evidence?: string[];
|
|
315
|
+
}>;
|
|
316
|
+
tags?: Array<{
|
|
317
|
+
name: string;
|
|
318
|
+
glob: string;
|
|
319
|
+
rationale: string;
|
|
320
|
+
}>;
|
|
321
|
+
ownershipHints?: Array<{
|
|
322
|
+
pathGlob: string;
|
|
323
|
+
suggestedOwner: string;
|
|
324
|
+
crossTeamEdges: number;
|
|
325
|
+
rationale: string;
|
|
326
|
+
}>;
|
|
327
|
+
hotspots?: Array<{
|
|
328
|
+
file: string;
|
|
329
|
+
crossPackageImports: number;
|
|
330
|
+
crossOwnerImports: number;
|
|
331
|
+
incomingEdges: number;
|
|
332
|
+
outgoingEdges: number;
|
|
333
|
+
suggestion: string;
|
|
334
|
+
}>;
|
|
335
|
+
rationale?: string[];
|
|
336
|
+
};
|
|
337
|
+
type FixPlanReport = {
|
|
338
|
+
query: string[];
|
|
339
|
+
matchedFindings: AnalysisReport["findings"];
|
|
340
|
+
actions: Array<{
|
|
341
|
+
id: string;
|
|
342
|
+
kind: string;
|
|
343
|
+
targets: string[];
|
|
344
|
+
why: string;
|
|
345
|
+
preconditions: string[];
|
|
346
|
+
steps: Array<{
|
|
347
|
+
description: string;
|
|
348
|
+
file?: string;
|
|
349
|
+
action?: string;
|
|
350
|
+
}>;
|
|
351
|
+
verification: string[];
|
|
352
|
+
risk: "low" | "medium" | "high";
|
|
353
|
+
confidence: "high" | "medium" | "low";
|
|
354
|
+
}>;
|
|
355
|
+
blockedBy: string[];
|
|
356
|
+
verificationSteps: string[];
|
|
357
|
+
riskLevel: "low" | "medium" | "high";
|
|
358
|
+
confidence: "high" | "medium" | "low";
|
|
359
|
+
};
|
|
360
|
+
type DaemonStatusReport = {
|
|
361
|
+
running: boolean;
|
|
362
|
+
pid?: number;
|
|
363
|
+
port?: number;
|
|
364
|
+
version?: string;
|
|
365
|
+
startedAt?: string;
|
|
366
|
+
projectRoot?: string;
|
|
367
|
+
};
|
|
200
368
|
declare function scan(options?: ScanOptions): Promise<AnalysisReport>;
|
|
201
|
-
/** @experimental */
|
|
202
369
|
declare function scanDot(options?: ScanOptions): Promise<string>;
|
|
203
370
|
declare function impact(options: ImpactOptions): Promise<ImpactReport>;
|
|
204
371
|
declare function explain(options: ExplainOptions): Promise<ExplainReport>;
|
|
@@ -208,21 +375,27 @@ declare function loadConfig(options?: {
|
|
|
208
375
|
}): Promise<PruneguardConfig>;
|
|
209
376
|
declare function schemaPath(): string;
|
|
210
377
|
declare function binaryPath(): string;
|
|
378
|
+
declare function resolutionInfo(): ResolutionInfo;
|
|
211
379
|
declare function run(args: string[], options?: {
|
|
212
380
|
cwd?: string;
|
|
213
381
|
}): Promise<CommandResult>;
|
|
214
382
|
declare function debugResolve(options: DebugResolveOptions): Promise<string>;
|
|
215
383
|
declare function debugEntrypoints(options?: DebugEntrypointsOptions): Promise<string[]>;
|
|
216
|
-
|
|
384
|
+
declare function review(options?: ReviewOptions): Promise<ReviewReport>;
|
|
385
|
+
declare function safeDelete(options: SafeDeleteOptions): Promise<SafeDeleteReport>;
|
|
386
|
+
declare function fixPlan(options: FixPlanOptions): Promise<FixPlanReport>;
|
|
387
|
+
declare function suggestRules(options?: SuggestRulesOptions): Promise<SuggestRulesReport>;
|
|
217
388
|
declare function migrateKnip(options?: {
|
|
218
389
|
cwd?: string;
|
|
219
390
|
file?: string;
|
|
220
391
|
}): Promise<MigrationOutput>;
|
|
221
|
-
/** @experimental */
|
|
222
392
|
declare function migrateDepcruise(options?: {
|
|
223
393
|
cwd?: string;
|
|
224
394
|
file?: string;
|
|
225
395
|
node?: boolean;
|
|
226
396
|
}): Promise<MigrationOutput>;
|
|
397
|
+
declare function daemonStatus(options?: {
|
|
398
|
+
cwd?: string;
|
|
399
|
+
}): Promise<DaemonStatusReport>;
|
|
227
400
|
//#endregion
|
|
228
|
-
export { AnalysisReport, type CommandResult, DebugEntrypointsOptions, DebugResolveOptions, ExplainOptions, ExplainReport, ImpactOptions, ImpactReport, MigrationOutput, Profile, PruneguardConfig, PruneguardExecutionError, ScanOptions, binaryPath, debugEntrypoints, debugResolve, explain, impact, loadConfig, migrateDepcruise, migrateKnip, run, scan, scanDot, schemaPath };
|
|
401
|
+
export { AnalysisReport, type CommandResult, DaemonStatusReport, DebugEntrypointsOptions, DebugResolveOptions, ExplainOptions, ExplainReport, FixPlanOptions, FixPlanReport, ImpactOptions, ImpactReport, MigrationOutput, Profile, PruneguardConfig, PruneguardExecutionError, type ResolutionInfo, type ResolutionSource, ReviewOptions, ReviewReport, SafeDeleteOptions, SafeDeleteReport, ScanOptions, SuggestRulesOptions, SuggestRulesReport, binaryPath, daemonStatus, debugEntrypoints, debugResolve, explain, fixPlan, impact, loadConfig, migrateDepcruise, migrateKnip, resolutionInfo, review, run, safeDelete, scan, scanDot, schemaPath, suggestRules };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as binaryPath$1, r as
|
|
1
|
+
import { i as run$1, n as binaryPath$1, r as resolutionInfo$1, t as PruneguardExecutionError } from "./runtime-BSHQsTbN.mjs";
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
3
|
//#region src-js/index.ts
|
|
4
4
|
function parseJson(result) {
|
|
@@ -44,7 +44,6 @@ async function scan(options = {}) {
|
|
|
44
44
|
if (result.exitCode !== 0 && result.exitCode !== 1) requireSuccess(result);
|
|
45
45
|
return parseJson(result);
|
|
46
46
|
}
|
|
47
|
-
/** @experimental */
|
|
48
47
|
async function scanDot(options = {}) {
|
|
49
48
|
const args = [
|
|
50
49
|
"--format",
|
|
@@ -93,6 +92,9 @@ function schemaPath() {
|
|
|
93
92
|
function binaryPath() {
|
|
94
93
|
return binaryPath$1();
|
|
95
94
|
}
|
|
95
|
+
function resolutionInfo() {
|
|
96
|
+
return resolutionInfo$1();
|
|
97
|
+
}
|
|
96
98
|
function run(args, options) {
|
|
97
99
|
return run$1(args, options);
|
|
98
100
|
}
|
|
@@ -113,7 +115,49 @@ async function debugEntrypoints(options = {}) {
|
|
|
113
115
|
requireSuccess(result);
|
|
114
116
|
return result.stdout.trimEnd().split("\n").filter(Boolean);
|
|
115
117
|
}
|
|
116
|
-
|
|
118
|
+
async function review(options = {}) {
|
|
119
|
+
const args = [
|
|
120
|
+
"--format",
|
|
121
|
+
"json",
|
|
122
|
+
"--severity",
|
|
123
|
+
"info"
|
|
124
|
+
];
|
|
125
|
+
pushGlobalFlags(args, options);
|
|
126
|
+
if (options.baseRef) args.push("--changed-since", options.baseRef);
|
|
127
|
+
if (options.noCache) args.push("--no-cache");
|
|
128
|
+
if (options.noBaseline) args.push("--no-baseline");
|
|
129
|
+
args.push("review");
|
|
130
|
+
const result = await run$1(args, { cwd: options.cwd });
|
|
131
|
+
if (result.exitCode !== 0 && result.exitCode !== 1) requireSuccess(result);
|
|
132
|
+
return parseJson(result);
|
|
133
|
+
}
|
|
134
|
+
async function safeDelete(options) {
|
|
135
|
+
const args = ["--format", "json"];
|
|
136
|
+
pushGlobalFlags(args, options);
|
|
137
|
+
if (options.noCache) args.push("--no-cache");
|
|
138
|
+
args.push("safe-delete", ...options.targets);
|
|
139
|
+
const result = await run$1(args, { cwd: options.cwd });
|
|
140
|
+
if (result.exitCode !== 0 && result.exitCode !== 1) requireSuccess(result);
|
|
141
|
+
return parseJson(result);
|
|
142
|
+
}
|
|
143
|
+
async function fixPlan(options) {
|
|
144
|
+
const args = ["--format", "json"];
|
|
145
|
+
pushGlobalFlags(args, options);
|
|
146
|
+
if (options.noCache) args.push("--no-cache");
|
|
147
|
+
args.push("fix-plan", ...options.targets);
|
|
148
|
+
const result = await run$1(args, { cwd: options.cwd });
|
|
149
|
+
requireSuccess(result);
|
|
150
|
+
return parseJson(result);
|
|
151
|
+
}
|
|
152
|
+
async function suggestRules(options = {}) {
|
|
153
|
+
const args = ["--format", "json"];
|
|
154
|
+
pushGlobalFlags(args, options);
|
|
155
|
+
if (options.noCache) args.push("--no-cache");
|
|
156
|
+
args.push("suggest-rules");
|
|
157
|
+
const result = await run$1(args, { cwd: options.cwd });
|
|
158
|
+
requireSuccess(result);
|
|
159
|
+
return parseJson(result);
|
|
160
|
+
}
|
|
117
161
|
async function migrateKnip(options = {}) {
|
|
118
162
|
const args = [
|
|
119
163
|
"--format",
|
|
@@ -126,7 +170,6 @@ async function migrateKnip(options = {}) {
|
|
|
126
170
|
requireSuccess(result);
|
|
127
171
|
return parseJson(result);
|
|
128
172
|
}
|
|
129
|
-
/** @experimental */
|
|
130
173
|
async function migrateDepcruise(options = {}) {
|
|
131
174
|
const args = [
|
|
132
175
|
"--format",
|
|
@@ -140,5 +183,21 @@ async function migrateDepcruise(options = {}) {
|
|
|
140
183
|
requireSuccess(result);
|
|
141
184
|
return parseJson(result);
|
|
142
185
|
}
|
|
186
|
+
async function daemonStatus(options) {
|
|
187
|
+
const result = await run$1(["daemon", "status"], { cwd: options?.cwd });
|
|
188
|
+
if (result.exitCode === 1 && result.stdout.includes("no running daemon")) return { running: false };
|
|
189
|
+
if (result.exitCode !== 0) return { running: false };
|
|
190
|
+
const lines = result.stdout.trim().split("\n");
|
|
191
|
+
const report = { running: true };
|
|
192
|
+
for (const line of lines) {
|
|
193
|
+
const [key, ...rest] = line.split(": ");
|
|
194
|
+
const value = rest.join(": ").trim();
|
|
195
|
+
if (key === "pid") report.pid = parseInt(value, 10);
|
|
196
|
+
else if (key === "port") report.port = parseInt(value, 10);
|
|
197
|
+
else if (key === "version") report.version = value;
|
|
198
|
+
else if (key === "started_at") report.startedAt = value;
|
|
199
|
+
}
|
|
200
|
+
return report;
|
|
201
|
+
}
|
|
143
202
|
//#endregion
|
|
144
|
-
export { PruneguardExecutionError, binaryPath, debugEntrypoints, debugResolve, explain, impact, loadConfig, migrateDepcruise, migrateKnip, run, scan, scanDot, schemaPath };
|
|
203
|
+
export { PruneguardExecutionError, binaryPath, daemonStatus, debugEntrypoints, debugResolve, explain, fixPlan, impact, loadConfig, migrateDepcruise, migrateKnip, resolutionInfo, review, run, safeDelete, scan, scanDot, schemaPath, suggestRules };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
3
|
import { execFileSync, spawn } from "node:child_process";
|
|
4
|
-
import { existsSync } from "node:fs";
|
|
4
|
+
import { accessSync, constants, existsSync } from "node:fs";
|
|
5
5
|
import { dirname, join } from "node:path";
|
|
6
6
|
//#region src-js/runtime.ts
|
|
7
7
|
const require = createRequire(import.meta.url);
|
|
@@ -13,6 +13,7 @@ var PruneguardExecutionError = class extends Error {
|
|
|
13
13
|
stderr;
|
|
14
14
|
binaryPath;
|
|
15
15
|
args;
|
|
16
|
+
resolutionSource;
|
|
16
17
|
constructor(code, message, details) {
|
|
17
18
|
super(message);
|
|
18
19
|
this.name = "PruneguardExecutionError";
|
|
@@ -22,6 +23,7 @@ var PruneguardExecutionError = class extends Error {
|
|
|
22
23
|
this.stderr = details?.stderr;
|
|
23
24
|
this.binaryPath = details?.binaryPath;
|
|
24
25
|
this.args = details?.args;
|
|
26
|
+
this.resolutionSource = details?.resolutionSource;
|
|
25
27
|
}
|
|
26
28
|
};
|
|
27
29
|
const PLATFORM_PACKAGES = {
|
|
@@ -40,7 +42,10 @@ function findPlatformBinary() {
|
|
|
40
42
|
if (!candidates) return void 0;
|
|
41
43
|
for (const pkg of candidates) try {
|
|
42
44
|
const binPath = join(dirname(require.resolve(`${pkg}/package.json`)), "bin", exeName());
|
|
43
|
-
if (existsSync(binPath)) return
|
|
45
|
+
if (existsSync(binPath)) return {
|
|
46
|
+
path: binPath,
|
|
47
|
+
packageName: pkg
|
|
48
|
+
};
|
|
44
49
|
} catch {
|
|
45
50
|
continue;
|
|
46
51
|
}
|
|
@@ -63,38 +68,94 @@ function findPathBinary() {
|
|
|
63
68
|
} catch {}
|
|
64
69
|
}
|
|
65
70
|
let cachedBinaryPath;
|
|
71
|
+
let cachedResolutionSource;
|
|
72
|
+
let cachedPlatformPackage;
|
|
73
|
+
function validateExecutable(binPath, source) {
|
|
74
|
+
if (!existsSync(binPath)) throw new PruneguardExecutionError("PRUNEGUARD_BINARY_NOT_FOUND", `[${source}] Binary does not exist: ${binPath}. Run "pruneguard debug runtime" for diagnostics.`, {
|
|
75
|
+
binaryPath: binPath,
|
|
76
|
+
resolutionSource: source
|
|
77
|
+
});
|
|
78
|
+
if (process.platform !== "win32") try {
|
|
79
|
+
accessSync(binPath, constants.X_OK);
|
|
80
|
+
} catch {
|
|
81
|
+
throw new PruneguardExecutionError("PRUNEGUARD_BINARY_NOT_FOUND", `[${source}] Binary exists but is not executable: ${binPath}. Try: chmod +x "${binPath}"`, {
|
|
82
|
+
binaryPath: binPath,
|
|
83
|
+
resolutionSource: source
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
66
87
|
function binaryPath(options) {
|
|
67
88
|
if (cachedBinaryPath) return cachedBinaryPath;
|
|
68
89
|
const envPath = process.env.PRUNEGUARD_BINARY;
|
|
69
90
|
if (envPath) {
|
|
70
|
-
|
|
91
|
+
validateExecutable(envPath, "env");
|
|
71
92
|
cachedBinaryPath = envPath;
|
|
93
|
+
cachedResolutionSource = "env";
|
|
72
94
|
return envPath;
|
|
73
95
|
}
|
|
74
96
|
const platformBin = findPlatformBinary();
|
|
75
97
|
if (platformBin) {
|
|
76
|
-
|
|
77
|
-
|
|
98
|
+
validateExecutable(platformBin.path, "platform-package");
|
|
99
|
+
cachedBinaryPath = platformBin.path;
|
|
100
|
+
cachedResolutionSource = "platform-package";
|
|
101
|
+
cachedPlatformPackage = platformBin.packageName;
|
|
102
|
+
return platformBin.path;
|
|
78
103
|
}
|
|
79
104
|
const devBin = findDevBinary();
|
|
80
105
|
if (devBin) {
|
|
106
|
+
validateExecutable(devBin, "dev");
|
|
81
107
|
cachedBinaryPath = devBin;
|
|
108
|
+
cachedResolutionSource = "dev";
|
|
82
109
|
return devBin;
|
|
83
110
|
}
|
|
84
111
|
if (options?.allowPathFallback) {
|
|
85
112
|
const pathBin = findPathBinary();
|
|
86
113
|
if (pathBin) {
|
|
114
|
+
validateExecutable(pathBin, "path");
|
|
87
115
|
cachedBinaryPath = pathBin;
|
|
116
|
+
cachedResolutionSource = "path";
|
|
88
117
|
return pathBin;
|
|
89
118
|
}
|
|
90
119
|
}
|
|
91
|
-
|
|
120
|
+
const expectedPkgs = PLATFORM_PACKAGES[`${process.platform}-${process.arch === "arm64" ? "arm64" : "x64"}`];
|
|
121
|
+
const tried = [
|
|
122
|
+
"env(PRUNEGUARD_BINARY)",
|
|
123
|
+
"platform-package",
|
|
124
|
+
"dev(cargo build)"
|
|
125
|
+
];
|
|
126
|
+
if (options?.allowPathFallback) tried.push("PATH");
|
|
127
|
+
const pkgHint = expectedPkgs?.length ? `\n Expected platform package: ${expectedPkgs.join(" or ")}` : "";
|
|
128
|
+
throw new PruneguardExecutionError("PRUNEGUARD_BINARY_NOT_FOUND", `Could not find the pruneguard binary for ${`${process.platform}-${process.arch}`}.\n Tried: ${tried.join(", ")}${pkgHint}\n Fix: npm install pruneguard (or set PRUNEGUARD_BINARY)\n Debug: npx pruneguard debug runtime`);
|
|
129
|
+
}
|
|
130
|
+
function resolutionInfo() {
|
|
131
|
+
return {
|
|
132
|
+
binaryPath: binaryPath(),
|
|
133
|
+
source: cachedResolutionSource,
|
|
134
|
+
...cachedPlatformPackage ? { platformPackage: cachedPlatformPackage } : {},
|
|
135
|
+
schemaPath: join(dirname(fileURLToPath(import.meta.url)), "..", "configuration_schema.json"),
|
|
136
|
+
platform: `${process.platform}-${process.arch}`
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Returns `true` if the current process is running in a CI environment.
|
|
141
|
+
*
|
|
142
|
+
* Checks the common `CI` env var used by GitHub Actions, GitLab CI,
|
|
143
|
+
* CircleCI, Travis CI, Jenkins, and most other CI providers.
|
|
144
|
+
*/
|
|
145
|
+
function isCI() {
|
|
146
|
+
const ci = process.env.CI;
|
|
147
|
+
return ci !== void 0 && ci !== "" && ci !== "0" && ci.toLowerCase() !== "false";
|
|
92
148
|
}
|
|
93
149
|
function run(args, options) {
|
|
94
150
|
const binary = binaryPath();
|
|
95
151
|
const start = performance.now();
|
|
152
|
+
const finalArgs = args.some((arg) => arg === "--daemon" || arg.startsWith("--daemon=")) ? args : [
|
|
153
|
+
"--daemon",
|
|
154
|
+
options?.daemon ?? (isCI() ? "off" : "auto"),
|
|
155
|
+
...args
|
|
156
|
+
];
|
|
96
157
|
return new Promise((resolve, reject) => {
|
|
97
|
-
const child = spawn(binary,
|
|
158
|
+
const child = spawn(binary, finalArgs, {
|
|
98
159
|
cwd: options?.cwd,
|
|
99
160
|
stdio: [
|
|
100
161
|
"ignore",
|
|
@@ -113,7 +174,8 @@ function run(args, options) {
|
|
|
113
174
|
child.on("error", (err) => {
|
|
114
175
|
reject(new PruneguardExecutionError("PRUNEGUARD_EXECUTION_FAILED", `Failed to spawn pruneguard: ${err.message}`, {
|
|
115
176
|
binaryPath: binary,
|
|
116
|
-
args
|
|
177
|
+
args,
|
|
178
|
+
resolutionSource: cachedResolutionSource
|
|
117
179
|
}));
|
|
118
180
|
});
|
|
119
181
|
child.on("close", (exitCode) => {
|
|
@@ -129,4 +191,4 @@ function run(args, options) {
|
|
|
129
191
|
});
|
|
130
192
|
}
|
|
131
193
|
//#endregion
|
|
132
|
-
export { binaryPath as n,
|
|
194
|
+
export { run as i, binaryPath as n, resolutionInfo as r, PruneguardExecutionError as t };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pruneguard",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Repo truth engine for JS/TS monorepos",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"javascript",
|
|
@@ -27,6 +27,8 @@
|
|
|
27
27
|
"files": [
|
|
28
28
|
"configuration_schema.json",
|
|
29
29
|
"report_schema.json",
|
|
30
|
+
"review_report_schema.json",
|
|
31
|
+
"safe_delete_report_schema.json",
|
|
30
32
|
"dist",
|
|
31
33
|
"README.md",
|
|
32
34
|
"bin/pruneguard"
|
|
@@ -41,14 +43,14 @@
|
|
|
41
43
|
}
|
|
42
44
|
},
|
|
43
45
|
"optionalDependencies": {
|
|
44
|
-
"@pruneguard/cli-darwin-arm64": "0.
|
|
45
|
-
"@pruneguard/cli-darwin-x64": "0.
|
|
46
|
-
"@pruneguard/cli-linux-arm64-gnu": "0.
|
|
47
|
-
"@pruneguard/cli-linux-arm64-musl": "0.
|
|
48
|
-
"@pruneguard/cli-linux-x64-gnu": "0.
|
|
49
|
-
"@pruneguard/cli-linux-x64-musl": "0.
|
|
50
|
-
"@pruneguard/cli-win32-arm64-msvc": "0.
|
|
51
|
-
"@pruneguard/cli-win32-x64-msvc": "0.
|
|
46
|
+
"@pruneguard/cli-darwin-arm64": "0.3.1",
|
|
47
|
+
"@pruneguard/cli-darwin-x64": "0.3.1",
|
|
48
|
+
"@pruneguard/cli-linux-arm64-gnu": "0.3.1",
|
|
49
|
+
"@pruneguard/cli-linux-arm64-musl": "0.3.1",
|
|
50
|
+
"@pruneguard/cli-linux-x64-gnu": "0.3.1",
|
|
51
|
+
"@pruneguard/cli-linux-x64-musl": "0.3.1",
|
|
52
|
+
"@pruneguard/cli-win32-arm64-msvc": "0.3.1",
|
|
53
|
+
"@pruneguard/cli-win32-x64-msvc": "0.3.1"
|
|
52
54
|
},
|
|
53
55
|
"engines": {
|
|
54
56
|
"node": ">=18.0.0"
|