@davmash/bygone 0.11.0 → 0.11.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/CHANGELOG.md +6 -0
- package/README.md +57 -25
- package/bin/bygone.js +11 -1
- package/cli/commandSpec.js +12 -1
- package/cli/completions.js +23 -2
- package/cli/dependencies.js +62 -0
- package/cli/evidence.js +67 -0
- package/cli/tour.js +11 -1
- package/completions/_bygone +11 -1
- package/completions/bygone +10 -2
- package/completions/bygone.fish +7 -0
- package/docs/dependencies.md +94 -0
- package/docs/evidence-review.md +163 -0
- package/docs/product-surface.md +2 -1
- package/docs/vscode-integration.md +183 -0
- package/media/webview.js +167 -167
- package/out/changeTour.js +1 -1
- package/out/dependencyGraph.js +213939 -0
- package/out/requirements.js +427 -0
- package/out/reviewDependencies.js +669 -0
- package/out/reviewWorkspace.js +1129 -0
- package/out/standalone-main.js +119 -9
- package/package.json +1 -1
- package/web/export-runtime.json +3 -3
- package/web/index.html +1 -0
- package/web/web-host.js +1 -1
|
@@ -0,0 +1,669 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
9
|
+
try {
|
|
10
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
11
|
+
} catch (e) {
|
|
12
|
+
throw mod = 0, e;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
var __export = (target, all) => {
|
|
16
|
+
for (var name in all)
|
|
17
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
18
|
+
};
|
|
19
|
+
var __copyProps = (to, from, except, desc) => {
|
|
20
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
21
|
+
for (let key of __getOwnPropNames(from))
|
|
22
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
23
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
24
|
+
}
|
|
25
|
+
return to;
|
|
26
|
+
};
|
|
27
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
28
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
29
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
30
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
31
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
32
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
33
|
+
mod
|
|
34
|
+
));
|
|
35
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
36
|
+
|
|
37
|
+
// packages/strand/src/input.js
|
|
38
|
+
var require_input = __commonJS({
|
|
39
|
+
"packages/strand/src/input.js"(exports2, module2) {
|
|
40
|
+
"use strict";
|
|
41
|
+
var LIMITS = Object.freeze({ maxFiles: 50, maxFileBytes: 1048576, maxBytes: 4194304, maxRecords: 2e4, timeoutMs: 3e4, maxOutputBytes: 16777216 });
|
|
42
|
+
function inputProblem(before, after, limits) {
|
|
43
|
+
if (!before || !after || typeof before !== "object" || typeof after !== "object" || Array.isArray(before) || Array.isArray(after)) return "invalid-snapshot-map";
|
|
44
|
+
if ((/* @__PURE__ */ new Set([...Object.keys(before), ...Object.keys(after)])).size > Math.min(limits.maxFiles, LIMITS.maxFiles)) return "file-budget";
|
|
45
|
+
let bytes = 0;
|
|
46
|
+
for (const files of [before, after]) for (const value of Object.values(files)) {
|
|
47
|
+
if (typeof value !== "string") return "invalid-snapshot-text";
|
|
48
|
+
const size = Buffer.byteLength(value);
|
|
49
|
+
bytes += size;
|
|
50
|
+
if (size > Math.min(limits.maxFileBytes, LIMITS.maxFileBytes)) return "file-byte-budget";
|
|
51
|
+
}
|
|
52
|
+
return bytes > Math.min(limits.maxBytes, LIMITS.maxBytes) ? "comparison-byte-budget" : null;
|
|
53
|
+
}
|
|
54
|
+
function boundedProcessOptions(options, timeoutKey, outputKey, defaultTimeout) {
|
|
55
|
+
const timeout = options[timeoutKey] === void 0 ? defaultTimeout : options[timeoutKey];
|
|
56
|
+
const maxBuffer = options[outputKey] === void 0 ? LIMITS.maxOutputBytes : options[outputKey];
|
|
57
|
+
if (![timeout, maxBuffer].every((value) => Number.isSafeInteger(value) && value > 0)) return null;
|
|
58
|
+
return { timeout: Math.min(timeout, defaultTimeout), maxBuffer: Math.min(maxBuffer, LIMITS.maxOutputBytes) };
|
|
59
|
+
}
|
|
60
|
+
module2.exports = { LIMITS, inputProblem, boundedProcessOptions };
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// packages/strand/src/source-references.js
|
|
65
|
+
var require_source_references = __commonJS({
|
|
66
|
+
"packages/strand/src/source-references.js"(exports2, module2) {
|
|
67
|
+
"use strict";
|
|
68
|
+
var { createHash } = require("node:crypto");
|
|
69
|
+
var { inputProblem, LIMITS } = require_input();
|
|
70
|
+
var digest = (text2) => createHash("sha256").update(text2, "utf8").digest("hex");
|
|
71
|
+
var key = (ref) => JSON.stringify([ref.revision, ref.path, ref.start, ref.end, ref.digest]);
|
|
72
|
+
function identifier(value) {
|
|
73
|
+
if (typeof value !== "string" || !value.trim() || value.length > 1e5) {
|
|
74
|
+
throw new TypeError("Expected bounded nonempty identifier");
|
|
75
|
+
}
|
|
76
|
+
return value;
|
|
77
|
+
}
|
|
78
|
+
function parseSourceRef4(value) {
|
|
79
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) throw new TypeError("Expected source reference");
|
|
80
|
+
const revision = identifier(value.revision), path = identifier(value.path);
|
|
81
|
+
if (path.startsWith("/") || /^[A-Za-z]:/.test(path) || path.includes("\\") || path.includes("\0") || path.split("/").some((part) => !part || part === "." || part === "..")) {
|
|
82
|
+
throw new TypeError("Invalid relative source path");
|
|
83
|
+
}
|
|
84
|
+
if (!Number.isSafeInteger(value.start) || !Number.isSafeInteger(value.end) || value.start < 0 || value.end <= value.start) {
|
|
85
|
+
throw new TypeError("Invalid UTF-16 range");
|
|
86
|
+
}
|
|
87
|
+
if (typeof value.digest !== "string" || !/^[a-f0-9]{64}$/.test(value.digest)) throw new TypeError("Expected SHA-256");
|
|
88
|
+
return { revision, path, start: value.start, end: value.end, digest: value.digest };
|
|
89
|
+
}
|
|
90
|
+
function checkSnapshot(snapshot) {
|
|
91
|
+
if (!snapshot || typeof snapshot !== "object" || Array.isArray(snapshot)) throw new TypeError("Expected snapshot");
|
|
92
|
+
identifier(snapshot.revision);
|
|
93
|
+
const problem = inputProblem(snapshot.files, {}, LIMITS);
|
|
94
|
+
if (problem) throw new TypeError(problem);
|
|
95
|
+
}
|
|
96
|
+
function sourceAt(snapshot, path) {
|
|
97
|
+
return Object.prototype.hasOwnProperty.call(snapshot.files, path) ? snapshot.files[path] : void 0;
|
|
98
|
+
}
|
|
99
|
+
function pinSourceRef2(snapshot, path, start, end) {
|
|
100
|
+
checkSnapshot(snapshot);
|
|
101
|
+
const ref = parseSourceRef4({ revision: snapshot.revision, path, start, end, digest: "0".repeat(64) });
|
|
102
|
+
const text2 = sourceAt(snapshot, ref.path);
|
|
103
|
+
if (typeof text2 !== "string" || end > text2.length) throw new TypeError("Source is unavailable or range exceeds file");
|
|
104
|
+
return { ...ref, digest: digest(text2.slice(start, end)) };
|
|
105
|
+
}
|
|
106
|
+
function resolveChecked(ref, snapshot) {
|
|
107
|
+
if (snapshot.revision !== ref.revision) return { status: "broken", reason: "Revision unavailable in this comparison" };
|
|
108
|
+
const text2 = sourceAt(snapshot, ref.path);
|
|
109
|
+
if (typeof text2 !== "string" || ref.end > text2.length) return { status: "broken", reason: "Source path or range unavailable" };
|
|
110
|
+
const slice = text2.slice(ref.start, ref.end);
|
|
111
|
+
if (digest(slice) !== ref.digest) return { status: "broken", reason: "Source digest mismatch" };
|
|
112
|
+
return { status: "valid", text: slice };
|
|
113
|
+
}
|
|
114
|
+
function resolveSourceRef4(value, snapshot) {
|
|
115
|
+
const ref = parseSourceRef4(value);
|
|
116
|
+
checkSnapshot(snapshot);
|
|
117
|
+
return resolveChecked(ref, snapshot);
|
|
118
|
+
}
|
|
119
|
+
function boundedList(value) {
|
|
120
|
+
if (!Array.isArray(value) || value.length > LIMITS.maxRecords) throw new TypeError("Expected bounded reference array");
|
|
121
|
+
return value;
|
|
122
|
+
}
|
|
123
|
+
function relocateSourceRefs2(values, before, after, pairs) {
|
|
124
|
+
checkSnapshot(before);
|
|
125
|
+
checkSnapshot(after);
|
|
126
|
+
const problem = inputProblem(before.files, after.files, LIMITS);
|
|
127
|
+
if (problem) throw new TypeError(problem);
|
|
128
|
+
if (before.revision === after.revision) throw new TypeError("Relocation requires distinct snapshot revisions");
|
|
129
|
+
const refs = boundedList(values).map(parseSourceRef4);
|
|
130
|
+
const candidates = boundedList(pairs).map((pair) => {
|
|
131
|
+
if (!pair || typeof pair !== "object") throw new TypeError("Expected correspondence pair");
|
|
132
|
+
return { before: parseSourceRef4(pair.before), after: parseSourceRef4(pair.after) };
|
|
133
|
+
});
|
|
134
|
+
const destinations = /* @__PURE__ */ new Map(), usedAfter = /* @__PURE__ */ new Set();
|
|
135
|
+
for (const pair of candidates) {
|
|
136
|
+
const from = key(pair.before), to = key(pair.after);
|
|
137
|
+
if (destinations.has(from) || usedAfter.has(to)) throw new TypeError("Duplicate correspondence endpoint");
|
|
138
|
+
destinations.set(from, pair.after);
|
|
139
|
+
usedAfter.add(to);
|
|
140
|
+
}
|
|
141
|
+
for (const pair of candidates) {
|
|
142
|
+
if (resolveChecked(pair.before, before).status !== "valid" || resolveChecked(pair.after, after).status !== "valid") {
|
|
143
|
+
throw new TypeError("Invalid correspondence endpoint");
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return refs.map((ref) => {
|
|
147
|
+
let destination;
|
|
148
|
+
if (resolveChecked(ref, before).status === "valid") {
|
|
149
|
+
destination = sourceAt(before, ref.path) === sourceAt(after, ref.path) ? { ...ref, revision: after.revision } : destinations.get(key(ref));
|
|
150
|
+
}
|
|
151
|
+
if (!destination) return { status: "unresolved", before: ref };
|
|
152
|
+
const status = ref.digest !== destination.digest ? "changed" : ref.path !== destination.path || ref.start !== destination.start ? "relocated" : "unchanged";
|
|
153
|
+
return { status, before: ref, after: { ...destination } };
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
module2.exports = { parseSourceRef: parseSourceRef4, pinSourceRef: pinSourceRef2, resolveSourceRef: resolveSourceRef4, relocateSourceRefs: relocateSourceRefs2 };
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
// packages/strand/source-references.js
|
|
161
|
+
var require_source_references2 = __commonJS({
|
|
162
|
+
"packages/strand/source-references.js"(exports2, module2) {
|
|
163
|
+
"use strict";
|
|
164
|
+
module2.exports = require_source_references();
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
// src/reviewDependencies.ts
|
|
169
|
+
var reviewDependencies_exports = {};
|
|
170
|
+
__export(reviewDependencies_exports, {
|
|
171
|
+
inspectDependencies: () => inspectDependencies
|
|
172
|
+
});
|
|
173
|
+
module.exports = __toCommonJS(reviewDependencies_exports);
|
|
174
|
+
var import_source_references3 = __toESM(require_source_references2());
|
|
175
|
+
|
|
176
|
+
// src/reviewWorkspace.ts
|
|
177
|
+
var import_child_process = require("child_process");
|
|
178
|
+
var import_util = require("util");
|
|
179
|
+
var import_source_references2 = __toESM(require_source_references2());
|
|
180
|
+
|
|
181
|
+
// src/requirements.ts
|
|
182
|
+
var import_source_references = __toESM(require_source_references2());
|
|
183
|
+
|
|
184
|
+
// node_modules/diff/lib/index.mjs
|
|
185
|
+
function Diff() {
|
|
186
|
+
}
|
|
187
|
+
Diff.prototype = {
|
|
188
|
+
diff: function diff(oldString, newString) {
|
|
189
|
+
var _options$timeout;
|
|
190
|
+
var options = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : {};
|
|
191
|
+
var callback = options.callback;
|
|
192
|
+
if (typeof options === "function") {
|
|
193
|
+
callback = options;
|
|
194
|
+
options = {};
|
|
195
|
+
}
|
|
196
|
+
this.options = options;
|
|
197
|
+
var self = this;
|
|
198
|
+
function done(value) {
|
|
199
|
+
if (callback) {
|
|
200
|
+
setTimeout(function() {
|
|
201
|
+
callback(void 0, value);
|
|
202
|
+
}, 0);
|
|
203
|
+
return true;
|
|
204
|
+
} else {
|
|
205
|
+
return value;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
oldString = this.castInput(oldString);
|
|
209
|
+
newString = this.castInput(newString);
|
|
210
|
+
oldString = this.removeEmpty(this.tokenize(oldString));
|
|
211
|
+
newString = this.removeEmpty(this.tokenize(newString));
|
|
212
|
+
var newLen = newString.length, oldLen = oldString.length;
|
|
213
|
+
var editLength = 1;
|
|
214
|
+
var maxEditLength = newLen + oldLen;
|
|
215
|
+
if (options.maxEditLength) {
|
|
216
|
+
maxEditLength = Math.min(maxEditLength, options.maxEditLength);
|
|
217
|
+
}
|
|
218
|
+
var maxExecutionTime = (_options$timeout = options.timeout) !== null && _options$timeout !== void 0 ? _options$timeout : Infinity;
|
|
219
|
+
var abortAfterTimestamp = Date.now() + maxExecutionTime;
|
|
220
|
+
var bestPath = [{
|
|
221
|
+
oldPos: -1,
|
|
222
|
+
lastComponent: void 0
|
|
223
|
+
}];
|
|
224
|
+
var newPos = this.extractCommon(bestPath[0], newString, oldString, 0);
|
|
225
|
+
if (bestPath[0].oldPos + 1 >= oldLen && newPos + 1 >= newLen) {
|
|
226
|
+
return done([{
|
|
227
|
+
value: this.join(newString),
|
|
228
|
+
count: newString.length
|
|
229
|
+
}]);
|
|
230
|
+
}
|
|
231
|
+
var minDiagonalToConsider = -Infinity, maxDiagonalToConsider = Infinity;
|
|
232
|
+
function execEditLength() {
|
|
233
|
+
for (var diagonalPath = Math.max(minDiagonalToConsider, -editLength); diagonalPath <= Math.min(maxDiagonalToConsider, editLength); diagonalPath += 2) {
|
|
234
|
+
var basePath = void 0;
|
|
235
|
+
var removePath = bestPath[diagonalPath - 1], addPath = bestPath[diagonalPath + 1];
|
|
236
|
+
if (removePath) {
|
|
237
|
+
bestPath[diagonalPath - 1] = void 0;
|
|
238
|
+
}
|
|
239
|
+
var canAdd = false;
|
|
240
|
+
if (addPath) {
|
|
241
|
+
var addPathNewPos = addPath.oldPos - diagonalPath;
|
|
242
|
+
canAdd = addPath && 0 <= addPathNewPos && addPathNewPos < newLen;
|
|
243
|
+
}
|
|
244
|
+
var canRemove = removePath && removePath.oldPos + 1 < oldLen;
|
|
245
|
+
if (!canAdd && !canRemove) {
|
|
246
|
+
bestPath[diagonalPath] = void 0;
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
if (!canRemove || canAdd && removePath.oldPos + 1 < addPath.oldPos) {
|
|
250
|
+
basePath = self.addToPath(addPath, true, void 0, 0);
|
|
251
|
+
} else {
|
|
252
|
+
basePath = self.addToPath(removePath, void 0, true, 1);
|
|
253
|
+
}
|
|
254
|
+
newPos = self.extractCommon(basePath, newString, oldString, diagonalPath);
|
|
255
|
+
if (basePath.oldPos + 1 >= oldLen && newPos + 1 >= newLen) {
|
|
256
|
+
return done(buildValues(self, basePath.lastComponent, newString, oldString, self.useLongestToken));
|
|
257
|
+
} else {
|
|
258
|
+
bestPath[diagonalPath] = basePath;
|
|
259
|
+
if (basePath.oldPos + 1 >= oldLen) {
|
|
260
|
+
maxDiagonalToConsider = Math.min(maxDiagonalToConsider, diagonalPath - 1);
|
|
261
|
+
}
|
|
262
|
+
if (newPos + 1 >= newLen) {
|
|
263
|
+
minDiagonalToConsider = Math.max(minDiagonalToConsider, diagonalPath + 1);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
editLength++;
|
|
268
|
+
}
|
|
269
|
+
if (callback) {
|
|
270
|
+
(function exec() {
|
|
271
|
+
setTimeout(function() {
|
|
272
|
+
if (editLength > maxEditLength || Date.now() > abortAfterTimestamp) {
|
|
273
|
+
return callback();
|
|
274
|
+
}
|
|
275
|
+
if (!execEditLength()) {
|
|
276
|
+
exec();
|
|
277
|
+
}
|
|
278
|
+
}, 0);
|
|
279
|
+
})();
|
|
280
|
+
} else {
|
|
281
|
+
while (editLength <= maxEditLength && Date.now() <= abortAfterTimestamp) {
|
|
282
|
+
var ret = execEditLength();
|
|
283
|
+
if (ret) {
|
|
284
|
+
return ret;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
},
|
|
289
|
+
addToPath: function addToPath(path, added, removed, oldPosInc) {
|
|
290
|
+
var last = path.lastComponent;
|
|
291
|
+
if (last && last.added === added && last.removed === removed) {
|
|
292
|
+
return {
|
|
293
|
+
oldPos: path.oldPos + oldPosInc,
|
|
294
|
+
lastComponent: {
|
|
295
|
+
count: last.count + 1,
|
|
296
|
+
added,
|
|
297
|
+
removed,
|
|
298
|
+
previousComponent: last.previousComponent
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
} else {
|
|
302
|
+
return {
|
|
303
|
+
oldPos: path.oldPos + oldPosInc,
|
|
304
|
+
lastComponent: {
|
|
305
|
+
count: 1,
|
|
306
|
+
added,
|
|
307
|
+
removed,
|
|
308
|
+
previousComponent: last
|
|
309
|
+
}
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
},
|
|
313
|
+
extractCommon: function extractCommon(basePath, newString, oldString, diagonalPath) {
|
|
314
|
+
var newLen = newString.length, oldLen = oldString.length, oldPos = basePath.oldPos, newPos = oldPos - diagonalPath, commonCount = 0;
|
|
315
|
+
while (newPos + 1 < newLen && oldPos + 1 < oldLen && this.equals(newString[newPos + 1], oldString[oldPos + 1])) {
|
|
316
|
+
newPos++;
|
|
317
|
+
oldPos++;
|
|
318
|
+
commonCount++;
|
|
319
|
+
}
|
|
320
|
+
if (commonCount) {
|
|
321
|
+
basePath.lastComponent = {
|
|
322
|
+
count: commonCount,
|
|
323
|
+
previousComponent: basePath.lastComponent
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
basePath.oldPos = oldPos;
|
|
327
|
+
return newPos;
|
|
328
|
+
},
|
|
329
|
+
equals: function equals(left, right) {
|
|
330
|
+
if (this.options.comparator) {
|
|
331
|
+
return this.options.comparator(left, right);
|
|
332
|
+
} else {
|
|
333
|
+
return left === right || this.options.ignoreCase && left.toLowerCase() === right.toLowerCase();
|
|
334
|
+
}
|
|
335
|
+
},
|
|
336
|
+
removeEmpty: function removeEmpty(array) {
|
|
337
|
+
var ret = [];
|
|
338
|
+
for (var i = 0; i < array.length; i++) {
|
|
339
|
+
if (array[i]) {
|
|
340
|
+
ret.push(array[i]);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
return ret;
|
|
344
|
+
},
|
|
345
|
+
castInput: function castInput(value) {
|
|
346
|
+
return value;
|
|
347
|
+
},
|
|
348
|
+
tokenize: function tokenize(value) {
|
|
349
|
+
return value.split("");
|
|
350
|
+
},
|
|
351
|
+
join: function join(chars) {
|
|
352
|
+
return chars.join("");
|
|
353
|
+
}
|
|
354
|
+
};
|
|
355
|
+
function buildValues(diff2, lastComponent, newString, oldString, useLongestToken) {
|
|
356
|
+
var components = [];
|
|
357
|
+
var nextComponent;
|
|
358
|
+
while (lastComponent) {
|
|
359
|
+
components.push(lastComponent);
|
|
360
|
+
nextComponent = lastComponent.previousComponent;
|
|
361
|
+
delete lastComponent.previousComponent;
|
|
362
|
+
lastComponent = nextComponent;
|
|
363
|
+
}
|
|
364
|
+
components.reverse();
|
|
365
|
+
var componentPos = 0, componentLen = components.length, newPos = 0, oldPos = 0;
|
|
366
|
+
for (; componentPos < componentLen; componentPos++) {
|
|
367
|
+
var component = components[componentPos];
|
|
368
|
+
if (!component.removed) {
|
|
369
|
+
if (!component.added && useLongestToken) {
|
|
370
|
+
var value = newString.slice(newPos, newPos + component.count);
|
|
371
|
+
value = value.map(function(value2, i) {
|
|
372
|
+
var oldValue = oldString[oldPos + i];
|
|
373
|
+
return oldValue.length > value2.length ? oldValue : value2;
|
|
374
|
+
});
|
|
375
|
+
component.value = diff2.join(value);
|
|
376
|
+
} else {
|
|
377
|
+
component.value = diff2.join(newString.slice(newPos, newPos + component.count));
|
|
378
|
+
}
|
|
379
|
+
newPos += component.count;
|
|
380
|
+
if (!component.added) {
|
|
381
|
+
oldPos += component.count;
|
|
382
|
+
}
|
|
383
|
+
} else {
|
|
384
|
+
component.value = diff2.join(oldString.slice(oldPos, oldPos + component.count));
|
|
385
|
+
oldPos += component.count;
|
|
386
|
+
if (componentPos && components[componentPos - 1].added) {
|
|
387
|
+
var tmp = components[componentPos - 1];
|
|
388
|
+
components[componentPos - 1] = components[componentPos];
|
|
389
|
+
components[componentPos] = tmp;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
var finalComponent = components[componentLen - 1];
|
|
394
|
+
if (componentLen > 1 && typeof finalComponent.value === "string" && (finalComponent.added || finalComponent.removed) && diff2.equals("", finalComponent.value)) {
|
|
395
|
+
components[componentLen - 2].value += finalComponent.value;
|
|
396
|
+
components.pop();
|
|
397
|
+
}
|
|
398
|
+
return components;
|
|
399
|
+
}
|
|
400
|
+
var characterDiff = new Diff();
|
|
401
|
+
var extendedWordChars = /^[A-Za-z\xC0-\u02C6\u02C8-\u02D7\u02DE-\u02FF\u1E00-\u1EFF]+$/;
|
|
402
|
+
var reWhitespace = /\S/;
|
|
403
|
+
var wordDiff = new Diff();
|
|
404
|
+
wordDiff.equals = function(left, right) {
|
|
405
|
+
if (this.options.ignoreCase) {
|
|
406
|
+
left = left.toLowerCase();
|
|
407
|
+
right = right.toLowerCase();
|
|
408
|
+
}
|
|
409
|
+
return left === right || this.options.ignoreWhitespace && !reWhitespace.test(left) && !reWhitespace.test(right);
|
|
410
|
+
};
|
|
411
|
+
wordDiff.tokenize = function(value) {
|
|
412
|
+
var tokens = value.split(/([^\S\r\n]+|[()[\]{}'"\r\n]|\b)/);
|
|
413
|
+
for (var i = 0; i < tokens.length - 1; i++) {
|
|
414
|
+
if (!tokens[i + 1] && tokens[i + 2] && extendedWordChars.test(tokens[i]) && extendedWordChars.test(tokens[i + 2])) {
|
|
415
|
+
tokens[i] += tokens[i + 2];
|
|
416
|
+
tokens.splice(i + 1, 2);
|
|
417
|
+
i--;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
return tokens;
|
|
421
|
+
};
|
|
422
|
+
var lineDiff = new Diff();
|
|
423
|
+
lineDiff.tokenize = function(value) {
|
|
424
|
+
if (this.options.stripTrailingCr) {
|
|
425
|
+
value = value.replace(/\r\n/g, "\n");
|
|
426
|
+
}
|
|
427
|
+
var retLines = [], linesAndNewlines = value.split(/(\n|\r\n)/);
|
|
428
|
+
if (!linesAndNewlines[linesAndNewlines.length - 1]) {
|
|
429
|
+
linesAndNewlines.pop();
|
|
430
|
+
}
|
|
431
|
+
for (var i = 0; i < linesAndNewlines.length; i++) {
|
|
432
|
+
var line = linesAndNewlines[i];
|
|
433
|
+
if (i % 2 && !this.options.newlineIsToken) {
|
|
434
|
+
retLines[retLines.length - 1] += line;
|
|
435
|
+
} else {
|
|
436
|
+
if (this.options.ignoreWhitespace) {
|
|
437
|
+
line = line.trim();
|
|
438
|
+
}
|
|
439
|
+
retLines.push(line);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
return retLines;
|
|
443
|
+
};
|
|
444
|
+
var sentenceDiff = new Diff();
|
|
445
|
+
sentenceDiff.tokenize = function(value) {
|
|
446
|
+
return value.split(/(\S.+?[.!?])(?=\s+|$)/);
|
|
447
|
+
};
|
|
448
|
+
var cssDiff = new Diff();
|
|
449
|
+
cssDiff.tokenize = function(value) {
|
|
450
|
+
return value.split(/([{}:;,]|\s+)/);
|
|
451
|
+
};
|
|
452
|
+
function _typeof(obj) {
|
|
453
|
+
"@babel/helpers - typeof";
|
|
454
|
+
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
|
|
455
|
+
_typeof = function(obj2) {
|
|
456
|
+
return typeof obj2;
|
|
457
|
+
};
|
|
458
|
+
} else {
|
|
459
|
+
_typeof = function(obj2) {
|
|
460
|
+
return obj2 && typeof Symbol === "function" && obj2.constructor === Symbol && obj2 !== Symbol.prototype ? "symbol" : typeof obj2;
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
return _typeof(obj);
|
|
464
|
+
}
|
|
465
|
+
var objectPrototypeToString = Object.prototype.toString;
|
|
466
|
+
var jsonDiff = new Diff();
|
|
467
|
+
jsonDiff.useLongestToken = true;
|
|
468
|
+
jsonDiff.tokenize = lineDiff.tokenize;
|
|
469
|
+
jsonDiff.castInput = function(value) {
|
|
470
|
+
var _this$options = this.options, undefinedReplacement = _this$options.undefinedReplacement, _this$options$stringi = _this$options.stringifyReplacer, stringifyReplacer = _this$options$stringi === void 0 ? function(k, v) {
|
|
471
|
+
return typeof v === "undefined" ? undefinedReplacement : v;
|
|
472
|
+
} : _this$options$stringi;
|
|
473
|
+
return typeof value === "string" ? value : JSON.stringify(canonicalize(value, null, null, stringifyReplacer), stringifyReplacer, " ");
|
|
474
|
+
};
|
|
475
|
+
jsonDiff.equals = function(left, right) {
|
|
476
|
+
return Diff.prototype.equals.call(jsonDiff, left.replace(/,([\r\n])/g, "$1"), right.replace(/,([\r\n])/g, "$1"));
|
|
477
|
+
};
|
|
478
|
+
function canonicalize(obj, stack, replacementStack, replacer, key) {
|
|
479
|
+
stack = stack || [];
|
|
480
|
+
replacementStack = replacementStack || [];
|
|
481
|
+
if (replacer) {
|
|
482
|
+
obj = replacer(key, obj);
|
|
483
|
+
}
|
|
484
|
+
var i;
|
|
485
|
+
for (i = 0; i < stack.length; i += 1) {
|
|
486
|
+
if (stack[i] === obj) {
|
|
487
|
+
return replacementStack[i];
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
var canonicalizedObj;
|
|
491
|
+
if ("[object Array]" === objectPrototypeToString.call(obj)) {
|
|
492
|
+
stack.push(obj);
|
|
493
|
+
canonicalizedObj = new Array(obj.length);
|
|
494
|
+
replacementStack.push(canonicalizedObj);
|
|
495
|
+
for (i = 0; i < obj.length; i += 1) {
|
|
496
|
+
canonicalizedObj[i] = canonicalize(obj[i], stack, replacementStack, replacer, key);
|
|
497
|
+
}
|
|
498
|
+
stack.pop();
|
|
499
|
+
replacementStack.pop();
|
|
500
|
+
return canonicalizedObj;
|
|
501
|
+
}
|
|
502
|
+
if (obj && obj.toJSON) {
|
|
503
|
+
obj = obj.toJSON();
|
|
504
|
+
}
|
|
505
|
+
if (_typeof(obj) === "object" && obj !== null) {
|
|
506
|
+
stack.push(obj);
|
|
507
|
+
canonicalizedObj = {};
|
|
508
|
+
replacementStack.push(canonicalizedObj);
|
|
509
|
+
var sortedKeys = [], _key;
|
|
510
|
+
for (_key in obj) {
|
|
511
|
+
if (obj.hasOwnProperty(_key)) {
|
|
512
|
+
sortedKeys.push(_key);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
sortedKeys.sort();
|
|
516
|
+
for (i = 0; i < sortedKeys.length; i += 1) {
|
|
517
|
+
_key = sortedKeys[i];
|
|
518
|
+
canonicalizedObj[_key] = canonicalize(obj[_key], stack, replacementStack, replacer, _key);
|
|
519
|
+
}
|
|
520
|
+
stack.pop();
|
|
521
|
+
replacementStack.pop();
|
|
522
|
+
} else {
|
|
523
|
+
canonicalizedObj = obj;
|
|
524
|
+
}
|
|
525
|
+
return canonicalizedObj;
|
|
526
|
+
}
|
|
527
|
+
var arrayDiff = new Diff();
|
|
528
|
+
arrayDiff.tokenize = function(value) {
|
|
529
|
+
return value.slice();
|
|
530
|
+
};
|
|
531
|
+
arrayDiff.join = arrayDiff.removeEmpty = function(value) {
|
|
532
|
+
return value;
|
|
533
|
+
};
|
|
534
|
+
|
|
535
|
+
// src/changeCorrespondence.ts
|
|
536
|
+
var MAX_BYTES = 16 * 1024 * 1024;
|
|
537
|
+
var MAX_SOURCE_BYTES = 8 * 1024 * 1024;
|
|
538
|
+
|
|
539
|
+
// src/reviewWorkspace.ts
|
|
540
|
+
var MAX_BYTES2 = 16 * 1024 * 1024;
|
|
541
|
+
function git(root, args, deadline) {
|
|
542
|
+
const remaining = deadline === void 0 ? 1e4 : deadline - Date.now();
|
|
543
|
+
if (remaining <= 0) throw new Error("Dependency source validation time budget exhausted");
|
|
544
|
+
return (0, import_child_process.execFileSync)("git", ["--no-replace-objects", "-C", root, ...args], { timeout: Math.min(1e4, remaining), maxBuffer: MAX_BYTES2, stdio: ["ignore", "pipe", "pipe"] });
|
|
545
|
+
}
|
|
546
|
+
function commitOid(root, revision, deadline) {
|
|
547
|
+
const oid = git(root, ["rev-parse", "--verify", "--end-of-options", `${revision}^{commit}`], deadline).toString().trim();
|
|
548
|
+
if (!/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(oid)) throw new Error("Expected a Git commit");
|
|
549
|
+
return oid;
|
|
550
|
+
}
|
|
551
|
+
function readPinnedFile(root, revision, file, deadline) {
|
|
552
|
+
(0, import_source_references2.parseSourceRef)({ revision, path: file, start: 0, end: 1, digest: "0".repeat(64) });
|
|
553
|
+
if (commitOid(root, revision, deadline) !== revision) throw new Error("Evidence requires a full immutable commit ID");
|
|
554
|
+
const entry = git(root, ["ls-tree", "-z", revision, "--", `:(literal)${file}`], deadline).toString();
|
|
555
|
+
if (!entry) return void 0;
|
|
556
|
+
const match = /^(100644|100755) blob ([a-f0-9]+)\t([^\0]+)\0$/.exec(entry);
|
|
557
|
+
if (!match || match[3] !== file) throw new Error(`Evidence is not a regular file: ${file}`);
|
|
558
|
+
const bytes = git(root, ["cat-file", "blob", match[2]], deadline);
|
|
559
|
+
if (bytes.length > 1024 * 1024 || bytes.includes(0)) throw new Error(`Evidence requires text up to 1 MiB: ${file}`);
|
|
560
|
+
return { text: new import_util.TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes), blob: match[2] };
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
// src/reviewDependencies.ts
|
|
564
|
+
var object = (value) => {
|
|
565
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("Invalid dependency evidence object");
|
|
566
|
+
return value;
|
|
567
|
+
};
|
|
568
|
+
var text = (value) => {
|
|
569
|
+
if (typeof value !== "string" || !value.length || value.length > 1e4) throw new Error("Invalid dependency evidence text");
|
|
570
|
+
return value;
|
|
571
|
+
};
|
|
572
|
+
var list = (value) => {
|
|
573
|
+
if (!Array.isArray(value) || value.length > 2e4) throw new Error("Invalid dependency evidence list");
|
|
574
|
+
return value;
|
|
575
|
+
};
|
|
576
|
+
function inspectDependencies(root, review, input) {
|
|
577
|
+
const data = object(input), range = object(data.range);
|
|
578
|
+
if (data.version !== 1 || range.baseOid !== review.base || range.headOid !== review.head || typeof range.dirtyWorkingTreeExcluded !== "boolean") throw new Error("Dependency report does not match pinned review");
|
|
579
|
+
const limits = object(data.limits), producer = object(data.producer);
|
|
580
|
+
if (producer.name !== "bygone") throw new Error("Unsupported dependency producer");
|
|
581
|
+
text(producer.typescript);
|
|
582
|
+
for (const [key, maximum] of Object.entries({ maxFiles: 2e3, maxFileBytes: 1024 * 1024, maxBytes: 16 * 1024 * 1024, maxRecords: 2e4, timeoutMs: 3e4 })) {
|
|
583
|
+
if (!Number.isSafeInteger(limits[key]) || Number(limits[key]) < 1 || Number(limits[key]) > maximum) throw new Error("Invalid dependency limits");
|
|
584
|
+
}
|
|
585
|
+
const deadline = Date.now() + Number(limits.timeoutMs);
|
|
586
|
+
const checkTime = () => {
|
|
587
|
+
if (Date.now() >= deadline) throw new Error("Dependency source validation time budget exhausted");
|
|
588
|
+
};
|
|
589
|
+
const limitations = list(data.assumptions).map(text);
|
|
590
|
+
limitations.push(
|
|
591
|
+
"Syntactic module evidence only. Unchanged edges do not prove unchanged imported bindings, behavior, or call relationships.",
|
|
592
|
+
"Dirty buffers are excluded. TypeScript syntax/options and malformed package metadata may limit resolution; absent diagnostics do not prove complete analysis."
|
|
593
|
+
);
|
|
594
|
+
const links = [];
|
|
595
|
+
const changes = object(data.changes), consumers = object(data.unchangedConsumers);
|
|
596
|
+
const identity = (value) => {
|
|
597
|
+
const edge = object(value), s = object(edge.source);
|
|
598
|
+
return JSON.stringify([s.revision, s.oid, s.blobOid, s.file, s.start, s.end, s.digest, edge.kind, edge.relationship, edge.phase, edge.loading, edge.specifier, edge.target, edge.resolution]);
|
|
599
|
+
};
|
|
600
|
+
const cache = /* @__PURE__ */ new Map();
|
|
601
|
+
let totalBytes = 0;
|
|
602
|
+
for (const side of ["base", "head"]) {
|
|
603
|
+
checkTime();
|
|
604
|
+
const sourceFiles = /* @__PURE__ */ new Set();
|
|
605
|
+
let sourceBytes = 0;
|
|
606
|
+
const snapshot = object(data[side]), oid = side === "base" ? review.base : review.head;
|
|
607
|
+
if (snapshot.oid !== oid) throw new Error("Dependency snapshot revision mismatch");
|
|
608
|
+
const coverage = object(snapshot.coverage);
|
|
609
|
+
if (typeof coverage.indexComplete !== "boolean") throw new Error("Invalid dependency coverage");
|
|
610
|
+
for (const key of ["candidateFiles", "indexedFiles", "omittedFiles", "readBytes", "unresolvedEdges", "omittedDiagnostics"]) {
|
|
611
|
+
if (!Number.isSafeInteger(coverage[key]) || Number(coverage[key]) < 0) throw new Error("Invalid dependency coverage");
|
|
612
|
+
}
|
|
613
|
+
limitations.push(`${side}: ${coverage.indexedFiles}/${coverage.candidateFiles} files indexed; ${coverage.omittedFiles} omitted; ${coverage.unresolvedEdges} unresolved edges; ${coverage.omittedDiagnostics} omitted diagnostics; index ${coverage.indexComplete ? "complete within limits" : "partial"}.`);
|
|
614
|
+
for (const diagnostic of list(snapshot.diagnostics)) {
|
|
615
|
+
const d = object(diagnostic);
|
|
616
|
+
limitations.push(`${side}: ${text(d.code)}: ${text(d.message)}`);
|
|
617
|
+
}
|
|
618
|
+
const inventory = list(snapshot.edges), initialization = list(snapshot.initialization);
|
|
619
|
+
if (inventory.length + initialization.length > Number(limits.maxRecords) || Number(coverage.indexedFiles) > Number(limits.maxFiles) || Number(coverage.readBytes) > Number(limits.maxBytes) || Number(coverage.indexedFiles) + Number(coverage.omittedFiles) !== Number(coverage.candidateFiles) || Number(coverage.unresolvedEdges) !== inventory.filter((value) => object(value).resolution !== "resolved").length || coverage.indexComplete && Number(coverage.omittedFiles) > 0) throw new Error("Dependency coverage exceeds declared limits");
|
|
620
|
+
const inventoryKeys = new Set(inventory.map(identity));
|
|
621
|
+
const changed = list(changes[side === "base" ? "removed" : "added"]);
|
|
622
|
+
const unchanged = list(consumers[side]);
|
|
623
|
+
for (const edge of [...changed, ...unchanged]) if (!inventoryKeys.has(identity(edge))) throw new Error("Dependency summary references unknown inventory evidence");
|
|
624
|
+
const changedKeys = new Set(changed.map(identity)), consumerKeys = new Set(unchanged.map(identity));
|
|
625
|
+
for (const value of [...inventory, ...initialization]) {
|
|
626
|
+
checkTime();
|
|
627
|
+
const edge = object(value), source = object(edge.source);
|
|
628
|
+
if (edge.evidence !== "syntactic" || source.revision !== side || source.oid !== oid) throw new Error("Invalid dependency source provenance");
|
|
629
|
+
const ref = (0, import_source_references3.parseSourceRef)({ revision: oid, path: source.file, start: source.start, end: source.end, digest: source.digest });
|
|
630
|
+
const key = `${oid}:${ref.path}`;
|
|
631
|
+
if (!cache.has(key)) {
|
|
632
|
+
const file2 = readPinnedFile(root, oid, ref.path, deadline);
|
|
633
|
+
totalBytes += file2 ? Buffer.byteLength(file2.text) : 0;
|
|
634
|
+
if (totalBytes > 2 * Number(limits.maxBytes)) throw new Error("Dependency sources exceed declared combined snapshot limits");
|
|
635
|
+
cache.set(key, file2);
|
|
636
|
+
}
|
|
637
|
+
const file = cache.get(key);
|
|
638
|
+
checkTime();
|
|
639
|
+
if (!file || file.blob !== source.blobOid) throw new Error("Dependency blob mismatch");
|
|
640
|
+
if (!sourceFiles.has(ref.path)) {
|
|
641
|
+
sourceFiles.add(ref.path);
|
|
642
|
+
const bytes = Buffer.byteLength(file.text);
|
|
643
|
+
sourceBytes += bytes;
|
|
644
|
+
if (bytes > Number(limits.maxFileBytes) || sourceFiles.size > Number(limits.maxFiles) || sourceBytes > Number(limits.maxBytes) || sourceFiles.size > Number(coverage.indexedFiles) || sourceBytes > Number(coverage.readBytes)) throw new Error("Dependency sources exceed declared limits or coverage");
|
|
645
|
+
}
|
|
646
|
+
if ((0, import_source_references3.resolveSourceRef)(ref, { revision: oid, files: { [ref.path]: file.text } }).status !== "valid") throw new Error("Dependency source digest mismatch");
|
|
647
|
+
const keyInInventory = identity(value);
|
|
648
|
+
const category = changedKeys.has(keyInInventory) ? `reported ${side === "base" ? "removed" : "added"} edge` : consumerKeys.has(keyInInventory) ? "direct unchanged consumer" : initialization.includes(value) ? "initialization site" : void 0;
|
|
649
|
+
if (!category) continue;
|
|
650
|
+
const relationship = typeof edge.relationship === "string" ? edge.relationship : String(edge.kind ?? "dependency");
|
|
651
|
+
const destination = typeof edge.target === "string" ? edge.target : typeof edge.specifier === "string" ? edge.specifier : "(computed target)";
|
|
652
|
+
const detail = initialization.includes(value) ? `${relationship} ${ref.path}` : `${ref.path} \u2014 ${relationship} ${JSON.stringify(edge.specifier ?? "(computed)")} \u2192 ${destination}`;
|
|
653
|
+
links.push({
|
|
654
|
+
title: `${side}: ${category} \xB7 ${detail}`,
|
|
655
|
+
ref,
|
|
656
|
+
phase: typeof edge.phase === "string" ? edge.phase : "unspecified",
|
|
657
|
+
loading: typeof edge.loading === "string" ? edge.loading : "unspecified",
|
|
658
|
+
resolution: typeof edge.resolution === "string" ? edge.resolution : "initialization site"
|
|
659
|
+
});
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
checkTime();
|
|
663
|
+
return { links, limitations };
|
|
664
|
+
}
|
|
665
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
666
|
+
0 && (module.exports = {
|
|
667
|
+
inspectDependencies
|
|
668
|
+
});
|
|
669
|
+
//# sourceMappingURL=reviewDependencies.js.map
|