apiwatcher-cli 0.1.0
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/changesets/stripe/2025-09-30.clover__2026-08-26.dahlia.json +4576 -0
- package/changesets/stripe/index.json +16 -0
- package/data/stripe/events.json +271 -0
- package/data/stripe/method-map.json +5718 -0
- package/dist/changeset/index-file.d.ts +30 -0
- package/dist/changeset/index-file.d.ts.map +1 -0
- package/dist/changeset/index-file.js +34 -0
- package/dist/changeset/index-file.js.map +1 -0
- package/dist/changeset/load.d.ts +21 -0
- package/dist/changeset/load.d.ts.map +1 -0
- package/dist/changeset/load.js +113 -0
- package/dist/changeset/load.js.map +1 -0
- package/dist/changeset/types.d.ts +97 -0
- package/dist/changeset/types.d.ts.map +1 -0
- package/dist/changeset/types.js +18 -0
- package/dist/changeset/types.js.map +1 -0
- package/dist/changeset/version.d.ts +17 -0
- package/dist/changeset/version.d.ts.map +1 -0
- package/dist/changeset/version.js +33 -0
- package/dist/changeset/version.js.map +1 -0
- package/dist/cli/args.d.ts +15 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +82 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/index.d.ts +5 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +333 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/config.d.ts +26 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +92 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/report/impact.d.ts +40 -0
- package/dist/report/impact.d.ts.map +1 -0
- package/dist/report/impact.js +331 -0
- package/dist/report/impact.js.map +1 -0
- package/dist/report/impact.test.d.ts +2 -0
- package/dist/report/impact.test.d.ts.map +1 -0
- package/dist/report/impact.test.js +247 -0
- package/dist/report/impact.test.js.map +1 -0
- package/dist/report/render.d.ts +9 -0
- package/dist/report/render.d.ts.map +1 -0
- package/dist/report/render.js +211 -0
- package/dist/report/render.js.map +1 -0
- package/dist/scanner/ast.d.ts +74 -0
- package/dist/scanner/ast.d.ts.map +1 -0
- package/dist/scanner/ast.js +930 -0
- package/dist/scanner/ast.js.map +1 -0
- package/dist/scanner/paths.d.ts +42 -0
- package/dist/scanner/paths.d.ts.map +1 -0
- package/dist/scanner/paths.js +179 -0
- package/dist/scanner/paths.js.map +1 -0
- package/dist/scanner/scan.d.ts +11 -0
- package/dist/scanner/scan.d.ts.map +1 -0
- package/dist/scanner/scan.js +268 -0
- package/dist/scanner/scan.js.map +1 -0
- package/dist/scanner/scan.test.d.ts +2 -0
- package/dist/scanner/scan.test.d.ts.map +1 -0
- package/dist/scanner/scan.test.js +134 -0
- package/dist/scanner/scan.test.js.map +1 -0
- package/dist/scanner/types.d.ts +74 -0
- package/dist/scanner/types.d.ts.map +1 -0
- package/dist/scanner/types.js +7 -0
- package/dist/scanner/types.js.map +1 -0
- package/dist/scanner/version.d.ts +23 -0
- package/dist/scanner/version.d.ts.map +1 -0
- package/dist/scanner/version.js +155 -0
- package/dist/scanner/version.js.map +1 -0
- package/dist/scanner/walk.d.ts +26 -0
- package/dist/scanner/walk.d.ts.map +1 -0
- package/dist/scanner/walk.js +117 -0
- package/dist/scanner/walk.js.map +1 -0
- package/dist/scanner/wrapper.test.d.ts +2 -0
- package/dist/scanner/wrapper.test.d.ts.map +1 -0
- package/dist/scanner/wrapper.test.js +92 -0
- package/dist/scanner/wrapper.test.js.map +1 -0
- package/dist/specdiff/build-method-map.d.ts +6 -0
- package/dist/specdiff/build-method-map.d.ts.map +1 -0
- package/dist/specdiff/build-method-map.js +231 -0
- package/dist/specdiff/build-method-map.js.map +1 -0
- package/dist/specdiff/compat.d.ts +20 -0
- package/dist/specdiff/compat.d.ts.map +1 -0
- package/dist/specdiff/compat.js +58 -0
- package/dist/specdiff/compat.js.map +1 -0
- package/dist/specdiff/diff.d.ts +28 -0
- package/dist/specdiff/diff.d.ts.map +1 -0
- package/dist/specdiff/diff.js +529 -0
- package/dist/specdiff/diff.js.map +1 -0
- package/dist/specdiff/diff.test.d.ts +2 -0
- package/dist/specdiff/diff.test.d.ts.map +1 -0
- package/dist/specdiff/diff.test.js +260 -0
- package/dist/specdiff/diff.test.js.map +1 -0
- package/dist/specdiff/fetch.d.ts +28 -0
- package/dist/specdiff/fetch.d.ts.map +1 -0
- package/dist/specdiff/fetch.js +68 -0
- package/dist/specdiff/fetch.js.map +1 -0
- package/dist/specdiff/methodmap.d.ts +45 -0
- package/dist/specdiff/methodmap.d.ts.map +1 -0
- package/dist/specdiff/methodmap.js +109 -0
- package/dist/specdiff/methodmap.js.map +1 -0
- package/dist/specdiff/openapi.d.ts +166 -0
- package/dist/specdiff/openapi.d.ts.map +1 -0
- package/dist/specdiff/openapi.js +282 -0
- package/dist/specdiff/openapi.js.map +1 -0
- package/package.json +33 -0
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
import { normalizePath } from '../specdiff/methodmap.js';
|
|
2
|
+
export function buildReport(input) {
|
|
3
|
+
const { scan, targetVersion } = input;
|
|
4
|
+
const ignore = new Set(input.ignoreIds ?? []);
|
|
5
|
+
const minConfidence = input.minConfidence ?? 0.4;
|
|
6
|
+
const index = indexUsages(scan.usages);
|
|
7
|
+
const findings = [];
|
|
8
|
+
let unaffectedChanges = 0;
|
|
9
|
+
for (const change of input.changes) {
|
|
10
|
+
if (ignore.has(change.id))
|
|
11
|
+
continue;
|
|
12
|
+
const sites = dedupeSites(matchUsages(change, index).filter((u) => u.confidence >= minConfidence));
|
|
13
|
+
if (sites.length === 0) {
|
|
14
|
+
unaffectedChanges += 1;
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
sites.sort((a, b) => b.confidence - a.confidence ||
|
|
18
|
+
a.evidence.file.localeCompare(b.evidence.file) ||
|
|
19
|
+
a.evidence.line - b.evidence.line);
|
|
20
|
+
findings.push({
|
|
21
|
+
change,
|
|
22
|
+
sites,
|
|
23
|
+
severity: change.severity,
|
|
24
|
+
confidence: sites[0]?.confidence ?? 0,
|
|
25
|
+
suggestion: suggest(change),
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
findings.sort((a, b) => rank(a.severity) - rank(b.severity) ||
|
|
29
|
+
b.sites.length - a.sites.length ||
|
|
30
|
+
a.change.id.localeCompare(b.change.id));
|
|
31
|
+
const totals = { breaking: 0, deprecating: 0, additive: 0 };
|
|
32
|
+
for (const f of findings)
|
|
33
|
+
totals[f.severity] += 1;
|
|
34
|
+
const { version } = scan;
|
|
35
|
+
const currentVersion = version.apiVersion ?? version.sdkDefaultApiVersion ?? null;
|
|
36
|
+
const currentVersionSource = version.apiVersion
|
|
37
|
+
? 'pinned'
|
|
38
|
+
: version.sdkDefaultApiVersion
|
|
39
|
+
? 'sdkDefault'
|
|
40
|
+
: 'unknown';
|
|
41
|
+
return {
|
|
42
|
+
api: 'stripe',
|
|
43
|
+
currentVersion,
|
|
44
|
+
currentVersionSource,
|
|
45
|
+
targetVersion,
|
|
46
|
+
scannedAt: new Date().toISOString(),
|
|
47
|
+
root: scan.root,
|
|
48
|
+
filesScanned: scan.filesScanned,
|
|
49
|
+
findings,
|
|
50
|
+
unaffectedChanges,
|
|
51
|
+
totals,
|
|
52
|
+
warnings: scan.warnings,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function key(method, path) {
|
|
56
|
+
if (!path)
|
|
57
|
+
return null;
|
|
58
|
+
return `${(method ?? 'get').toLowerCase()} ${normalizePath(path)}`;
|
|
59
|
+
}
|
|
60
|
+
function push(map, k, usage) {
|
|
61
|
+
let bucket = map.get(k);
|
|
62
|
+
if (!bucket) {
|
|
63
|
+
bucket = [];
|
|
64
|
+
map.set(k, bucket);
|
|
65
|
+
}
|
|
66
|
+
bucket.push(usage);
|
|
67
|
+
}
|
|
68
|
+
function indexUsages(usages) {
|
|
69
|
+
const index = {
|
|
70
|
+
byEndpoint: new Map(),
|
|
71
|
+
requestParams: new Map(),
|
|
72
|
+
responseFields: new Map(),
|
|
73
|
+
events: new Map(),
|
|
74
|
+
paramsByCall: new Map(),
|
|
75
|
+
};
|
|
76
|
+
for (const usage of usages) {
|
|
77
|
+
const k = key(usage.httpMethod, usage.path);
|
|
78
|
+
switch (usage.kind) {
|
|
79
|
+
case 'sdkCall':
|
|
80
|
+
case 'rawUrl':
|
|
81
|
+
if (k)
|
|
82
|
+
push(index.byEndpoint, k, usage);
|
|
83
|
+
break;
|
|
84
|
+
case 'requestParam':
|
|
85
|
+
if (k)
|
|
86
|
+
push(index.requestParams, k, usage);
|
|
87
|
+
if (usage.callId && usage.field) {
|
|
88
|
+
let set = index.paramsByCall.get(usage.callId);
|
|
89
|
+
if (!set) {
|
|
90
|
+
set = new Set();
|
|
91
|
+
index.paramsByCall.set(usage.callId, set);
|
|
92
|
+
}
|
|
93
|
+
set.add(usage.field);
|
|
94
|
+
}
|
|
95
|
+
break;
|
|
96
|
+
case 'responseField':
|
|
97
|
+
if (k)
|
|
98
|
+
push(index.responseFields, k, usage);
|
|
99
|
+
break;
|
|
100
|
+
case 'webhookEvent':
|
|
101
|
+
if (usage.event)
|
|
102
|
+
push(index.events, usage.event, usage);
|
|
103
|
+
break;
|
|
104
|
+
case 'clientInit':
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return index;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* One source line should appear once per finding.
|
|
112
|
+
*
|
|
113
|
+
* A nested object literal puts several matching param paths on the same line
|
|
114
|
+
* (`tipping: { bgn: { fixed_amounts: [...] } }` matches a `tipping.bgn` removal
|
|
115
|
+
* twice over). The reader needs the line, not every path within it. Keeps the
|
|
116
|
+
* highest-confidence usage per line.
|
|
117
|
+
*/
|
|
118
|
+
function dedupeSites(usages) {
|
|
119
|
+
const best = new Map();
|
|
120
|
+
for (const usage of usages) {
|
|
121
|
+
const k = `${usage.evidence.file}:${usage.evidence.line}`;
|
|
122
|
+
const existing = best.get(k);
|
|
123
|
+
if (!existing || usage.confidence > existing.confidence)
|
|
124
|
+
best.set(k, usage);
|
|
125
|
+
}
|
|
126
|
+
return [...best.values()];
|
|
127
|
+
}
|
|
128
|
+
/** Every (method, path) a change touches: its own, plus attributed endpoints. */
|
|
129
|
+
function changeEndpoints(change) {
|
|
130
|
+
const out = [];
|
|
131
|
+
if (change.path)
|
|
132
|
+
out.push({ method: change.method, path: change.path });
|
|
133
|
+
for (const ep of change.endpoints ?? []) {
|
|
134
|
+
if (!out.some((e) => e.path === ep.path && e.method === ep.method))
|
|
135
|
+
out.push(ep);
|
|
136
|
+
}
|
|
137
|
+
return out;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* A raw URL usage has no reliable HTTP verb, so endpoint lookups also try the
|
|
141
|
+
* path alone. Better to over-report a raw `fetch` than to miss it.
|
|
142
|
+
*/
|
|
143
|
+
function endpointUsages(index, change) {
|
|
144
|
+
const out = [];
|
|
145
|
+
const seen = new Set();
|
|
146
|
+
const take = (usage) => {
|
|
147
|
+
if (seen.has(usage))
|
|
148
|
+
return;
|
|
149
|
+
seen.add(usage);
|
|
150
|
+
out.push(usage);
|
|
151
|
+
};
|
|
152
|
+
for (const { method, path } of changeEndpoints(change)) {
|
|
153
|
+
for (const usage of index.byEndpoint.get(key(method, path)) ?? [])
|
|
154
|
+
take(usage);
|
|
155
|
+
// A raw `fetch` whose verb we could not read still matches on path alone.
|
|
156
|
+
const wantPath = normalizePath(path);
|
|
157
|
+
for (const [k, list] of index.byEndpoint) {
|
|
158
|
+
if (k.slice(k.indexOf(' ') + 1) !== wantPath)
|
|
159
|
+
continue;
|
|
160
|
+
for (const usage of list) {
|
|
161
|
+
if (usage.kind === 'rawUrl' && usage.httpMethod === undefined)
|
|
162
|
+
take(usage);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return out;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Does a usage's field path touch the changed field?
|
|
170
|
+
*
|
|
171
|
+
* Only the field itself or something below it counts. Matching an *ancestor*
|
|
172
|
+
* would mean flagging `line_items: [{ price, quantity }]` because some unrelated
|
|
173
|
+
* `line_items[].dynamic_tax_rates` was removed — code that never sent the field
|
|
174
|
+
* is not affected by it disappearing. The scanner records nested param paths, so
|
|
175
|
+
* a caller who really does pass the field still produces an exact match.
|
|
176
|
+
*
|
|
177
|
+
* Array markers are dropped so `lines.data[].amount` matches `lines.data.amount`.
|
|
178
|
+
*/
|
|
179
|
+
function fieldTouches(usageField, changeField) {
|
|
180
|
+
if (!usageField)
|
|
181
|
+
return false;
|
|
182
|
+
const a = usageField.replace(/\[\]/g, '');
|
|
183
|
+
const b = changeField.replace(/\[\]/g, '');
|
|
184
|
+
return a === b || a.startsWith(`${b}.`);
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Field paths a response change can appear as at a call site.
|
|
188
|
+
*
|
|
189
|
+
* Response changes are diffed against the owning resource, so `field` is
|
|
190
|
+
* relative to that resource while `fieldPaths` holds the paths a caller actually
|
|
191
|
+
* reads. Match against both: the bare field covers code that destructured the
|
|
192
|
+
* resource directly.
|
|
193
|
+
*/
|
|
194
|
+
function candidateFields(change) {
|
|
195
|
+
const out = new Set();
|
|
196
|
+
if (change.field)
|
|
197
|
+
out.add(change.field);
|
|
198
|
+
for (const p of change.fieldPaths ?? [])
|
|
199
|
+
out.add(p);
|
|
200
|
+
return [...out];
|
|
201
|
+
}
|
|
202
|
+
function matchUsages(change, index) {
|
|
203
|
+
if (change.location === 'event') {
|
|
204
|
+
return change.event ? [...(index.events.get(change.event) ?? [])] : [];
|
|
205
|
+
}
|
|
206
|
+
if (change.location === 'operation') {
|
|
207
|
+
return endpointUsages(index, change);
|
|
208
|
+
}
|
|
209
|
+
if (change.location === 'response') {
|
|
210
|
+
if (!change.field)
|
|
211
|
+
return endpointUsages(index, change);
|
|
212
|
+
const fields = candidateFields(change);
|
|
213
|
+
const out = [];
|
|
214
|
+
const seen = new Set();
|
|
215
|
+
for (const { method, path } of changeEndpoints(change)) {
|
|
216
|
+
const k = key(method, path);
|
|
217
|
+
if (!k)
|
|
218
|
+
continue;
|
|
219
|
+
for (const usage of index.responseFields.get(k) ?? []) {
|
|
220
|
+
if (seen.has(usage))
|
|
221
|
+
continue;
|
|
222
|
+
if (!fields.some((f) => fieldTouches(usage.field, f)))
|
|
223
|
+
continue;
|
|
224
|
+
seen.add(usage);
|
|
225
|
+
out.push(usage);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return out;
|
|
229
|
+
}
|
|
230
|
+
// requestBody / queryParam / pathParam — always scoped to one operation.
|
|
231
|
+
const k = key(change.method, change.path);
|
|
232
|
+
if (!k)
|
|
233
|
+
return [];
|
|
234
|
+
if (change.kind === 'required') {
|
|
235
|
+
const calls = endpointUsages(index, change).filter((u) => u.kind === 'sdkCall');
|
|
236
|
+
const field = change.field;
|
|
237
|
+
if (!field)
|
|
238
|
+
return calls;
|
|
239
|
+
// A nested required field only binds callers who send its parent object, so
|
|
240
|
+
// flag a call only when it reaches the field's parent but omits the field.
|
|
241
|
+
const idx = field.lastIndexOf('.');
|
|
242
|
+
const parent = idx === -1 ? null : field.slice(0, idx);
|
|
243
|
+
return calls.filter((call) => {
|
|
244
|
+
// No params object we could read: cannot rule it out, so report it.
|
|
245
|
+
if (!call.callId)
|
|
246
|
+
return true;
|
|
247
|
+
const passed = index.paramsByCall.get(call.callId);
|
|
248
|
+
if (!passed)
|
|
249
|
+
return parent === null;
|
|
250
|
+
if (passed.has(field))
|
|
251
|
+
return false; // already supplies it
|
|
252
|
+
if (parent === null)
|
|
253
|
+
return true; // top-level: every call needs it
|
|
254
|
+
return reachesParent(passed, parent);
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
if (!change.field)
|
|
258
|
+
return endpointUsages(index, change);
|
|
259
|
+
return (index.requestParams.get(k) ?? []).filter((u) => fieldTouches(u.field, change.field));
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Does a call site pass the object a nested required field lives in?
|
|
263
|
+
*
|
|
264
|
+
* Exact evidence wins: if the call passes `a.b` (or anything inside it), a field
|
|
265
|
+
* required under `a.b` applies. Otherwise fall back on what the scanner could
|
|
266
|
+
* see. It only descends a couple of levels into object literals, so a recorded
|
|
267
|
+
* ancestor with no recorded children means "we did not look inside" — stay safe
|
|
268
|
+
* and report. But when the children *were* enumerated and the wanted branch is
|
|
269
|
+
* not among them, the call demonstrably does not pass it, and reporting would be
|
|
270
|
+
* a false alarm.
|
|
271
|
+
*/
|
|
272
|
+
function reachesParent(passed, parent) {
|
|
273
|
+
const want = parent.replace(/\[\]/g, '');
|
|
274
|
+
const have = [...passed].map((p) => p.replace(/\[\]/g, ''));
|
|
275
|
+
for (const p of have) {
|
|
276
|
+
if (p === want || p.startsWith(`${want}.`))
|
|
277
|
+
return true;
|
|
278
|
+
}
|
|
279
|
+
// Deepest recorded ancestor of the wanted path.
|
|
280
|
+
let deepest = null;
|
|
281
|
+
for (const p of have) {
|
|
282
|
+
if (!want.startsWith(`${p}.`))
|
|
283
|
+
continue;
|
|
284
|
+
if (deepest === null || p.length > deepest.length)
|
|
285
|
+
deepest = p;
|
|
286
|
+
}
|
|
287
|
+
if (deepest === null)
|
|
288
|
+
return false;
|
|
289
|
+
const enumeratedChildren = have.some((p) => p.startsWith(`${deepest}.`));
|
|
290
|
+
// Children listed and ours absent -> not passed. Nothing listed -> unknown.
|
|
291
|
+
return !enumeratedChildren;
|
|
292
|
+
}
|
|
293
|
+
function suggest(change) {
|
|
294
|
+
const field = change.field ?? change.event ?? '';
|
|
295
|
+
switch (change.kind) {
|
|
296
|
+
case 'renamed':
|
|
297
|
+
return `Rename \`${field}\` to \`${change.replacement ?? '?'}\`.`;
|
|
298
|
+
case 'removed':
|
|
299
|
+
if (change.location === 'operation') {
|
|
300
|
+
return `Replace this call — ${String(change.method).toUpperCase()} ${change.path} no longer exists.`;
|
|
301
|
+
}
|
|
302
|
+
if (change.location === 'event')
|
|
303
|
+
return `Remove the handler for \`${field}\`.`;
|
|
304
|
+
return change.replacement
|
|
305
|
+
? `Stop reading \`${field}\`; use \`${change.replacement}\` instead.`
|
|
306
|
+
: `Stop using \`${field}\` — it is gone in ${change.severity === 'breaking' ? 'the target version' : 'a later version'}.`;
|
|
307
|
+
case 'required':
|
|
308
|
+
return `Pass \`${field}\` in this call; it is now required.`;
|
|
309
|
+
case 'typeChanged':
|
|
310
|
+
return `\`${field}\` is now \`${change.toType ?? '?'}\` (was \`${change.fromType ?? '?'}\`). Update the code that reads it.`;
|
|
311
|
+
case 'deprecated':
|
|
312
|
+
return change.location === 'operation'
|
|
313
|
+
? 'Plan a migration off this endpoint before it is removed.'
|
|
314
|
+
: `Plan to stop using \`${field}\` before it is removed.`;
|
|
315
|
+
case 'added':
|
|
316
|
+
return change.location === 'operation'
|
|
317
|
+
? 'New endpoint available; no action needed.'
|
|
318
|
+
: `New field \`${field}\` available; no action needed.`;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
function rank(severity) {
|
|
322
|
+
return severity === 'breaking' ? 0 : severity === 'deprecating' ? 1 : 2;
|
|
323
|
+
}
|
|
324
|
+
/** Exit code contract: non-zero only when something is actually breaking. */
|
|
325
|
+
export function exitCodeFor(report, failOn = 'breaking') {
|
|
326
|
+
if (failOn === 'never')
|
|
327
|
+
return 0;
|
|
328
|
+
const thresholds = failOn === 'breaking' ? ['breaking'] : failOn === 'deprecating' ? ['breaking', 'deprecating'] : ['breaking', 'deprecating', 'additive'];
|
|
329
|
+
return thresholds.some((s) => report.totals[s] > 0) ? 1 : 0;
|
|
330
|
+
}
|
|
331
|
+
//# sourceMappingURL=impact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"impact.js","sourceRoot":"","sources":["../../src/report/impact.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"impact.test.d.ts","sourceRoot":"","sources":["../../src/report/impact.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { test } from 'node:test';
|
|
3
|
+
import { buildReport, exitCodeFor } from './impact.js';
|
|
4
|
+
import { renderMarkdown, renderTerminal } from './render.js';
|
|
5
|
+
let seq = 0;
|
|
6
|
+
function usage(partial) {
|
|
7
|
+
seq += 1;
|
|
8
|
+
return {
|
|
9
|
+
confidence: 1,
|
|
10
|
+
evidence: { file: 'src/a.ts', line: seq, column: 1, snippet: 'code' },
|
|
11
|
+
...partial,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
function scanOf(usages, apiVersion = '2025-01-01') {
|
|
15
|
+
return {
|
|
16
|
+
root: '/repo',
|
|
17
|
+
filesScanned: 1,
|
|
18
|
+
usages,
|
|
19
|
+
version: { apiVersion, sdkRange: '^22.0.0' },
|
|
20
|
+
clients: [],
|
|
21
|
+
warnings: [],
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function change(partial) {
|
|
25
|
+
return {
|
|
26
|
+
id: 'c1',
|
|
27
|
+
kind: 'removed',
|
|
28
|
+
severity: 'breaking',
|
|
29
|
+
location: 'requestBody',
|
|
30
|
+
note: 'note',
|
|
31
|
+
...partial,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
const TARGET = '2025-06-01';
|
|
35
|
+
test('a removed request parameter matches the call that passes it', () => {
|
|
36
|
+
const report = buildReport({
|
|
37
|
+
scan: scanOf([
|
|
38
|
+
usage({ kind: 'sdkCall', httpMethod: 'post', path: '/v1/x', callId: 'k1' }),
|
|
39
|
+
usage({ kind: 'requestParam', httpMethod: 'post', path: '/v1/x', field: 'gone', callId: 'k1' }),
|
|
40
|
+
]),
|
|
41
|
+
changes: [change({ method: 'post', path: '/v1/x', field: 'gone' })],
|
|
42
|
+
targetVersion: TARGET,
|
|
43
|
+
});
|
|
44
|
+
assert.equal(report.findings.length, 1);
|
|
45
|
+
assert.equal(report.totals.breaking, 1);
|
|
46
|
+
});
|
|
47
|
+
test('passing only an ancestor is not affected by a child being removed', () => {
|
|
48
|
+
// `line_items: [{ price, quantity }]` must not be flagged because some
|
|
49
|
+
// unrelated `line_items[].dynamic_tax_rates` disappeared.
|
|
50
|
+
const report = buildReport({
|
|
51
|
+
scan: scanOf([
|
|
52
|
+
usage({ kind: 'sdkCall', httpMethod: 'post', path: '/v1/x', callId: 'k1' }),
|
|
53
|
+
usage({ kind: 'requestParam', httpMethod: 'post', path: '/v1/x', field: 'line_items', callId: 'k1' }),
|
|
54
|
+
]),
|
|
55
|
+
changes: [change({ method: 'post', path: '/v1/x', field: 'line_items[].dynamic_tax_rates' })],
|
|
56
|
+
targetVersion: TARGET,
|
|
57
|
+
});
|
|
58
|
+
assert.equal(report.findings.length, 0);
|
|
59
|
+
assert.equal(report.unaffectedChanges, 1);
|
|
60
|
+
});
|
|
61
|
+
test('a newly required top-level parameter flags calls that omit it', () => {
|
|
62
|
+
const omitting = buildReport({
|
|
63
|
+
scan: scanOf([
|
|
64
|
+
usage({ kind: 'sdkCall', httpMethod: 'post', path: '/v1/x', callId: 'k1' }),
|
|
65
|
+
usage({ kind: 'requestParam', httpMethod: 'post', path: '/v1/x', field: 'other', callId: 'k1' }),
|
|
66
|
+
]),
|
|
67
|
+
changes: [change({ kind: 'required', method: 'post', path: '/v1/x', field: 'currency' })],
|
|
68
|
+
targetVersion: TARGET,
|
|
69
|
+
});
|
|
70
|
+
assert.equal(omitting.findings.length, 1);
|
|
71
|
+
const supplying = buildReport({
|
|
72
|
+
scan: scanOf([
|
|
73
|
+
usage({ kind: 'sdkCall', httpMethod: 'post', path: '/v1/x', callId: 'k2' }),
|
|
74
|
+
usage({ kind: 'requestParam', httpMethod: 'post', path: '/v1/x', field: 'currency', callId: 'k2' }),
|
|
75
|
+
]),
|
|
76
|
+
changes: [change({ kind: 'required', method: 'post', path: '/v1/x', field: 'currency' })],
|
|
77
|
+
targetVersion: TARGET,
|
|
78
|
+
});
|
|
79
|
+
assert.equal(supplying.findings.length, 0, 'a call already passing the field is fine');
|
|
80
|
+
});
|
|
81
|
+
test('a conditionally required field only flags calls that reach its parent', () => {
|
|
82
|
+
const field = 'cfg.anchor.day';
|
|
83
|
+
// Passes `cfg.other` — we enumerated cfg's children and `anchor` is absent.
|
|
84
|
+
const unrelated = buildReport({
|
|
85
|
+
scan: scanOf([
|
|
86
|
+
usage({ kind: 'sdkCall', httpMethod: 'post', path: '/v1/x', callId: 'k1' }),
|
|
87
|
+
usage({ kind: 'requestParam', httpMethod: 'post', path: '/v1/x', field: 'cfg', callId: 'k1' }),
|
|
88
|
+
usage({ kind: 'requestParam', httpMethod: 'post', path: '/v1/x', field: 'cfg.other', callId: 'k1' }),
|
|
89
|
+
]),
|
|
90
|
+
changes: [change({ kind: 'required', method: 'post', path: '/v1/x', field })],
|
|
91
|
+
targetVersion: TARGET,
|
|
92
|
+
});
|
|
93
|
+
assert.equal(unrelated.findings.length, 0, 'cfg.anchor demonstrably not passed');
|
|
94
|
+
// Passes `cfg.anchor` but not the newly required `day` inside it.
|
|
95
|
+
const affected = buildReport({
|
|
96
|
+
scan: scanOf([
|
|
97
|
+
usage({ kind: 'sdkCall', httpMethod: 'post', path: '/v1/x', callId: 'k2' }),
|
|
98
|
+
usage({ kind: 'requestParam', httpMethod: 'post', path: '/v1/x', field: 'cfg', callId: 'k2' }),
|
|
99
|
+
usage({ kind: 'requestParam', httpMethod: 'post', path: '/v1/x', field: 'cfg.anchor', callId: 'k2' }),
|
|
100
|
+
]),
|
|
101
|
+
changes: [change({ kind: 'required', method: 'post', path: '/v1/x', field })],
|
|
102
|
+
targetVersion: TARGET,
|
|
103
|
+
});
|
|
104
|
+
assert.equal(affected.findings.length, 1);
|
|
105
|
+
});
|
|
106
|
+
test('a conditionally required field is reported when we could not look inside', () => {
|
|
107
|
+
// `cfg` recorded with no children means the scanner did not descend, so we
|
|
108
|
+
// cannot rule it out and should say so rather than stay silent.
|
|
109
|
+
const report = buildReport({
|
|
110
|
+
scan: scanOf([
|
|
111
|
+
usage({ kind: 'sdkCall', httpMethod: 'post', path: '/v1/x', callId: 'k1' }),
|
|
112
|
+
usage({ kind: 'requestParam', httpMethod: 'post', path: '/v1/x', field: 'cfg', callId: 'k1' }),
|
|
113
|
+
]),
|
|
114
|
+
changes: [change({ kind: 'required', method: 'post', path: '/v1/x', field: 'cfg.anchor.day' })],
|
|
115
|
+
targetVersion: TARGET,
|
|
116
|
+
});
|
|
117
|
+
assert.equal(report.findings.length, 1);
|
|
118
|
+
});
|
|
119
|
+
test('a response change matches through its attributed endpoint and field path', () => {
|
|
120
|
+
const report = buildReport({
|
|
121
|
+
scan: scanOf([
|
|
122
|
+
usage({
|
|
123
|
+
kind: 'responseField',
|
|
124
|
+
httpMethod: 'get',
|
|
125
|
+
path: '/v1/parents',
|
|
126
|
+
field: 'items[].legacy',
|
|
127
|
+
}),
|
|
128
|
+
]),
|
|
129
|
+
changes: [
|
|
130
|
+
change({
|
|
131
|
+
location: 'response',
|
|
132
|
+
resource: 'item',
|
|
133
|
+
field: 'legacy',
|
|
134
|
+
endpoints: [{ method: 'get', path: '/v1/parents' }],
|
|
135
|
+
fieldPaths: ['items[].legacy'],
|
|
136
|
+
}),
|
|
137
|
+
],
|
|
138
|
+
targetVersion: TARGET,
|
|
139
|
+
});
|
|
140
|
+
assert.equal(report.findings.length, 1);
|
|
141
|
+
});
|
|
142
|
+
test('a raw URL with no verb still matches an endpoint change', () => {
|
|
143
|
+
const report = buildReport({
|
|
144
|
+
scan: scanOf([usage({ kind: 'rawUrl', path: '/v1/payment_intents/{}/cancel', confidence: 1 })]),
|
|
145
|
+
changes: [
|
|
146
|
+
change({
|
|
147
|
+
location: 'operation',
|
|
148
|
+
method: 'post',
|
|
149
|
+
path: '/v1/payment_intents/{intent}/cancel',
|
|
150
|
+
}),
|
|
151
|
+
],
|
|
152
|
+
targetVersion: TARGET,
|
|
153
|
+
});
|
|
154
|
+
assert.equal(report.findings.length, 1, 'parameter names should not prevent the match');
|
|
155
|
+
});
|
|
156
|
+
test('several matching paths on one line are cited once', () => {
|
|
157
|
+
const report = buildReport({
|
|
158
|
+
scan: scanOf([
|
|
159
|
+
usage({ kind: 'sdkCall', httpMethod: 'post', path: '/v1/x', callId: 'k1' }),
|
|
160
|
+
{
|
|
161
|
+
kind: 'requestParam',
|
|
162
|
+
confidence: 1,
|
|
163
|
+
httpMethod: 'post',
|
|
164
|
+
path: '/v1/x',
|
|
165
|
+
field: 'tipping.bgn',
|
|
166
|
+
callId: 'k1',
|
|
167
|
+
evidence: { file: 'src/a.ts', line: 22, column: 16, snippet: 'tipping: { bgn: {...} }' },
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
kind: 'requestParam',
|
|
171
|
+
confidence: 1,
|
|
172
|
+
httpMethod: 'post',
|
|
173
|
+
path: '/v1/x',
|
|
174
|
+
field: 'tipping.bgn.amount',
|
|
175
|
+
callId: 'k1',
|
|
176
|
+
evidence: { file: 'src/a.ts', line: 22, column: 23, snippet: 'tipping: { bgn: {...} }' },
|
|
177
|
+
},
|
|
178
|
+
]),
|
|
179
|
+
changes: [change({ method: 'post', path: '/v1/x', field: 'tipping.bgn' })],
|
|
180
|
+
targetVersion: TARGET,
|
|
181
|
+
});
|
|
182
|
+
assert.equal(report.findings.length, 1);
|
|
183
|
+
assert.equal(report.findings[0]?.sites.length, 1, 'one line, one citation');
|
|
184
|
+
});
|
|
185
|
+
test('ignored change ids are suppressed', () => {
|
|
186
|
+
const scan = scanOf([
|
|
187
|
+
usage({ kind: 'sdkCall', httpMethod: 'post', path: '/v1/x', callId: 'k1' }),
|
|
188
|
+
usage({ kind: 'requestParam', httpMethod: 'post', path: '/v1/x', field: 'gone', callId: 'k1' }),
|
|
189
|
+
]);
|
|
190
|
+
const changes = [change({ id: 'noisy', method: 'post', path: '/v1/x', field: 'gone' })];
|
|
191
|
+
assert.equal(buildReport({ scan, changes, targetVersion: TARGET }).findings.length, 1);
|
|
192
|
+
assert.equal(buildReport({ scan, changes, targetVersion: TARGET, ignoreIds: ['noisy'] }).findings.length, 0);
|
|
193
|
+
});
|
|
194
|
+
test('low-confidence matches are dropped by minConfidence', () => {
|
|
195
|
+
const scan = scanOf([
|
|
196
|
+
usage({ kind: 'sdkCall', httpMethod: 'post', path: '/v1/x', callId: 'k1', confidence: 0.5 }),
|
|
197
|
+
usage({
|
|
198
|
+
kind: 'requestParam',
|
|
199
|
+
httpMethod: 'post',
|
|
200
|
+
path: '/v1/x',
|
|
201
|
+
field: 'gone',
|
|
202
|
+
callId: 'k1',
|
|
203
|
+
confidence: 0.5,
|
|
204
|
+
}),
|
|
205
|
+
]);
|
|
206
|
+
const changes = [change({ method: 'post', path: '/v1/x', field: 'gone' })];
|
|
207
|
+
assert.equal(buildReport({ scan, changes, targetVersion: TARGET, minConfidence: 0.4 }).findings.length, 1);
|
|
208
|
+
assert.equal(buildReport({ scan, changes, targetVersion: TARGET, minConfidence: 0.9 }).findings.length, 0);
|
|
209
|
+
});
|
|
210
|
+
test('exit code reflects the configured failure threshold', () => {
|
|
211
|
+
const report = buildReport({
|
|
212
|
+
scan: scanOf([
|
|
213
|
+
usage({ kind: 'sdkCall', httpMethod: 'post', path: '/v1/x', callId: 'k1' }),
|
|
214
|
+
usage({ kind: 'requestParam', httpMethod: 'post', path: '/v1/x', field: 'old', callId: 'k1' }),
|
|
215
|
+
]),
|
|
216
|
+
changes: [
|
|
217
|
+
change({ id: 'd1', kind: 'deprecated', severity: 'deprecating', method: 'post', path: '/v1/x', field: 'old' }),
|
|
218
|
+
],
|
|
219
|
+
targetVersion: TARGET,
|
|
220
|
+
});
|
|
221
|
+
assert.equal(report.totals.deprecating, 1);
|
|
222
|
+
assert.equal(exitCodeFor(report, 'breaking'), 0, 'deprecations alone should not fail a build');
|
|
223
|
+
assert.equal(exitCodeFor(report, 'deprecating'), 1);
|
|
224
|
+
assert.equal(exitCodeFor(report, 'never'), 0);
|
|
225
|
+
});
|
|
226
|
+
test('renderers produce readable output for an empty report', () => {
|
|
227
|
+
const report = buildReport({ scan: scanOf([]), changes: [], targetVersion: TARGET });
|
|
228
|
+
const pretty = renderTerminal(report, { color: false });
|
|
229
|
+
assert.match(pretty, /Nothing in this repo is affected/);
|
|
230
|
+
assert.doesNotMatch(pretty, /\[/, 'color:false should emit no ANSI codes');
|
|
231
|
+
assert.match(renderMarkdown(report), /# Stripe API impact report/);
|
|
232
|
+
});
|
|
233
|
+
test('markdown output lists findings with their evidence', () => {
|
|
234
|
+
const report = buildReport({
|
|
235
|
+
scan: scanOf([
|
|
236
|
+
usage({ kind: 'sdkCall', httpMethod: 'post', path: '/v1/x', callId: 'k1' }),
|
|
237
|
+
usage({ kind: 'requestParam', httpMethod: 'post', path: '/v1/x', field: 'gone', callId: 'k1' }),
|
|
238
|
+
]),
|
|
239
|
+
changes: [change({ method: 'post', path: '/v1/x', field: 'gone', note: 'Field gone was removed.' })],
|
|
240
|
+
targetVersion: TARGET,
|
|
241
|
+
});
|
|
242
|
+
const md = renderMarkdown(report);
|
|
243
|
+
assert.match(md, /## Breaking/);
|
|
244
|
+
assert.match(md, /Field gone was removed\./);
|
|
245
|
+
assert.match(md, /src\/a\.ts:/);
|
|
246
|
+
});
|
|
247
|
+
//# sourceMappingURL=impact.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"impact.test.js","sourceRoot":"","sources":["../../src/report/impact.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ImpactReport } from './impact.js';
|
|
2
|
+
export declare function supportsColor(): boolean;
|
|
3
|
+
export declare function renderTerminal(report: ImpactReport, options?: {
|
|
4
|
+
color?: boolean;
|
|
5
|
+
}): string;
|
|
6
|
+
export declare function renderMarkdown(report: ImpactReport): string;
|
|
7
|
+
/** Machine-readable output, for the GitHub App and for piping into other tools. */
|
|
8
|
+
export declare function renderJson(report: ImpactReport): string;
|
|
9
|
+
//# sourceMappingURL=render.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/report/render.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAW,YAAY,EAAE,MAAM,aAAa,CAAC;AAgBzD,wBAAgB,aAAa,IAAI,OAAO,CAIvC;AAgCD,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,MAAM,CAyC9F;AAyCD,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAmD3D;AAkDD,mFAAmF;AACnF,wBAAgB,UAAU,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAEvD"}
|