@secureport/core 2.2.0 → 2.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/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/report/csv.d.ts +41 -0
- package/dist/report/csv.d.ts.map +1 -0
- package/dist/report/csv.js +158 -0
- package/dist/report/csv.js.map +1 -0
- package/dist/report/fonts.d.ts +53 -0
- package/dist/report/fonts.d.ts.map +1 -0
- package/dist/report/fonts.js +53 -0
- package/dist/report/fonts.js.map +1 -0
- package/dist/report/html.d.ts.map +1 -1
- package/dist/report/html.js +48 -13
- package/dist/report/html.js.map +1 -1
- package/dist/report/json.d.ts +15 -0
- package/dist/report/json.d.ts.map +1 -1
- package/dist/report/json.js +1 -0
- package/dist/report/json.js.map +1 -1
- package/dist/report/markdown.d.ts +33 -2
- package/dist/report/markdown.d.ts.map +1 -1
- package/dist/report/markdown.js +67 -16
- package/dist/report/markdown.js.map +1 -1
- package/dist/report/model.d.ts +108 -1
- package/dist/report/model.d.ts.map +1 -1
- package/dist/report/model.js +173 -36
- package/dist/report/model.js.map +1 -1
- package/dist/report/sarif.d.ts +60 -0
- package/dist/report/sarif.d.ts.map +1 -0
- package/dist/report/sarif.js +125 -0
- package/dist/report/sarif.js.map +1 -0
- package/dist/report/stream.d.ts +119 -0
- package/dist/report/stream.d.ts.map +1 -0
- package/dist/report/stream.js +546 -0
- package/dist/report/stream.js.map +1 -0
- package/package.json +5 -3
- package/src/index.ts +7 -1
- package/src/report/csv.ts +186 -0
- package/src/report/fonts.ts +55 -0
- package/src/report/html.ts +57 -14
- package/src/report/json.ts +17 -0
- package/src/report/markdown.ts +79 -15
- package/src/report/model.ts +242 -45
- package/src/report/sarif.ts +166 -0
- package/src/report/stream.ts +727 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
const SARIF_LEVEL = Object.freeze({
|
|
2
|
+
critical: 'error',
|
|
3
|
+
high: 'error',
|
|
4
|
+
medium: 'warning',
|
|
5
|
+
low: 'note',
|
|
6
|
+
advisory: 'note',
|
|
7
|
+
});
|
|
8
|
+
/**
|
|
9
|
+
* The `security-severity` GitHub code scanning reads to rank an alert, as a
|
|
10
|
+
* string 0.0–10.0 — GitHub's convention, not part of the SARIF spec itself.
|
|
11
|
+
* Fixed bands rather than a CVSS score, because not every finding has one
|
|
12
|
+
* and two issues at the same {@link Severity} should rank the same.
|
|
13
|
+
*/
|
|
14
|
+
const SECURITY_SEVERITY = Object.freeze({
|
|
15
|
+
critical: '9.0',
|
|
16
|
+
high: '7.5',
|
|
17
|
+
medium: '5.0',
|
|
18
|
+
low: '3.0',
|
|
19
|
+
advisory: '1.0',
|
|
20
|
+
});
|
|
21
|
+
/** `SEVERITY_ORDER`, duplicated as an index rather than imported, to keep this file's only dependency on `severity.ts` the type. */
|
|
22
|
+
const FLOOR_RANK = Object.freeze({
|
|
23
|
+
critical: 0,
|
|
24
|
+
high: 1,
|
|
25
|
+
medium: 2,
|
|
26
|
+
low: 3,
|
|
27
|
+
advisory: 4,
|
|
28
|
+
});
|
|
29
|
+
/** `"key":value`, run through `JSON.stringify` so nothing is hand-escaped. */
|
|
30
|
+
function field(key, value) {
|
|
31
|
+
return `${JSON.stringify(key)}:${JSON.stringify(value)}`;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Renders a snapshot's open issues as SARIF 2.1.0, from a header and a
|
|
35
|
+
* cursor — the machine path's format for GitHub code scanning (P8), and the
|
|
36
|
+
* streaming sibling of {@link renderJsonStream} and
|
|
37
|
+
* {@link renderMarkdownStream}. See {@link renderJsonStream} for the memory
|
|
38
|
+
* argument.
|
|
39
|
+
*
|
|
40
|
+
* **Resolved issues never appear, unconditionally — there is no
|
|
41
|
+
* `includeResolved` option.** SARIF is not a document a person reads; it is
|
|
42
|
+
* the input to GitHub's own diffing, which closes an alert when a new
|
|
43
|
+
* upload no longer contains it. Including a resolved issue would tell
|
|
44
|
+
* GitHub the finding is still open, which is the opposite of what resolving
|
|
45
|
+
* it meant.
|
|
46
|
+
*
|
|
47
|
+
* **Suppressed issues never appear either, and take no `suppressed`
|
|
48
|
+
* parameter at all.** An accepted risk is not a code-scanning alert; SARIF
|
|
49
|
+
* has no accepted-risk register to carry it in the way the appendix does
|
|
50
|
+
* for the human and other machine formats.
|
|
51
|
+
*
|
|
52
|
+
* **`ruleId` is `Issue.vulnKey`, not `Finding.sourceRuleId` or
|
|
53
|
+
* `sourceEngine`.** `vulnKey` is engine-independent by construction
|
|
54
|
+
* (`fingerprint.ts`), and naming a scanner in a customer-facing artefact is
|
|
55
|
+
* the thing this package's report options have twice had to stop doing
|
|
56
|
+
* (`ReportOptions.evidenceVerbosity`'s own TSDoc records it). `rules[]` is
|
|
57
|
+
* built from the same stream, deduplicated on `vulnKey` — bounded by the
|
|
58
|
+
* number of distinct weakness classes, not by issue count, so buffering it
|
|
59
|
+
* (unlike `results`) costs nothing worth avoiding.
|
|
60
|
+
*
|
|
61
|
+
* @param header - The run and the target. Never scales with issue count.
|
|
62
|
+
* @param issues - Every open issue, in any order — SARIF results are an
|
|
63
|
+
* unordered set, so this format is the one place in the streaming
|
|
64
|
+
* contract with no ordering requirement on its input.
|
|
65
|
+
* @param options - A severity floor, and nothing else.
|
|
66
|
+
* @returns Chunks of JSON text; concatenated, they are one SARIF document.
|
|
67
|
+
*/
|
|
68
|
+
export async function* renderSarifStream(header, issues, options = {}) {
|
|
69
|
+
const floor = options.severityFloor;
|
|
70
|
+
const floorAt = floor === undefined ? 4 : FLOOR_RANK[floor];
|
|
71
|
+
// Small — bounded by distinct weakness classes, not by issue count — and
|
|
72
|
+
// known only once the stream is exhausted. So `results` (the one array
|
|
73
|
+
// that must never be buffered) is written first and `tool.driver.rules`
|
|
74
|
+
// last, the one key order that lets both be true without a second pass
|
|
75
|
+
// over `issues`: JSON does not care which key comes first.
|
|
76
|
+
const rules = new Map();
|
|
77
|
+
yield '{';
|
|
78
|
+
// The schema's own `id`, not a GitHub raw link — checked by hand, because
|
|
79
|
+
// an unreachable $schema is a broken document a validator would still call
|
|
80
|
+
// valid, and getting it wrong once cost the trip to the OASIS repo to
|
|
81
|
+
// learn its real path (`tests/fixtures/README.md` records that trip).
|
|
82
|
+
yield field('$schema', 'https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/schemas/sarif-schema-2.1.0.json');
|
|
83
|
+
yield ',' + field('version', '2.1.0');
|
|
84
|
+
yield ',"runs":[{"results":[';
|
|
85
|
+
let firstResult = true;
|
|
86
|
+
for await (const entry of issues) {
|
|
87
|
+
const { issue } = entry;
|
|
88
|
+
if (issue.status === 'resolved')
|
|
89
|
+
continue;
|
|
90
|
+
if (FLOOR_RANK[issue.effectiveSeverity] > floorAt)
|
|
91
|
+
continue;
|
|
92
|
+
if (!rules.has(issue.vulnKey)) {
|
|
93
|
+
rules.set(issue.vulnKey, { title: issue.title, cwe: issue.cwe });
|
|
94
|
+
}
|
|
95
|
+
const message = entry.findings[0]?.description ?? issue.title;
|
|
96
|
+
const result = {
|
|
97
|
+
ruleId: issue.vulnKey,
|
|
98
|
+
level: SARIF_LEVEL[issue.effectiveSeverity],
|
|
99
|
+
message: { text: message },
|
|
100
|
+
locations: [
|
|
101
|
+
{
|
|
102
|
+
physicalLocation: {
|
|
103
|
+
artifactLocation: { uri: issue.location },
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
partialFingerprints: { secureportFingerprint: issue.fingerprint },
|
|
108
|
+
properties: { 'security-severity': SECURITY_SEVERITY[issue.effectiveSeverity] },
|
|
109
|
+
};
|
|
110
|
+
yield (firstResult ? '' : ',') + JSON.stringify(result);
|
|
111
|
+
firstResult = false;
|
|
112
|
+
}
|
|
113
|
+
yield ']';
|
|
114
|
+
const ruleDefs = [...rules.entries()].map(([vulnKey, rule]) => ({
|
|
115
|
+
id: vulnKey,
|
|
116
|
+
shortDescription: { text: rule.title },
|
|
117
|
+
...(rule.cwe === undefined ? {} : { properties: { tags: [rule.cwe] } }),
|
|
118
|
+
}));
|
|
119
|
+
yield ',"tool":{"driver":{';
|
|
120
|
+
yield field('name', 'Secureport');
|
|
121
|
+
yield ',' + field('informationUri', 'https://secureport.io/');
|
|
122
|
+
yield ',"rules":' + JSON.stringify(ruleDefs);
|
|
123
|
+
yield '}}}]}';
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=sarif.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sarif.js","sourceRoot":"","sources":["../../src/report/sarif.ts"],"names":[],"mappings":"AA4BA,MAAM,WAAW,GAA2C,MAAM,CAAC,MAAM,CAAC;IACxE,QAAQ,EAAE,OAAO;IACjB,IAAI,EAAE,OAAO;IACb,MAAM,EAAE,SAAS;IACjB,GAAG,EAAE,MAAM;IACX,QAAQ,EAAE,MAAM;CACjB,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,iBAAiB,GAAuC,MAAM,CAAC,MAAM,CAAC;IAC1E,QAAQ,EAAE,KAAK;IACf,IAAI,EAAE,KAAK;IACX,MAAM,EAAE,KAAK;IACb,GAAG,EAAE,KAAK;IACV,QAAQ,EAAE,KAAK;CAChB,CAAC,CAAC;AAEH,oIAAoI;AACpI,MAAM,UAAU,GAAuC,MAAM,CAAC,MAAM,CAAC;IACnE,QAAQ,EAAE,CAAC;IACX,IAAI,EAAE,CAAC;IACP,MAAM,EAAE,CAAC;IACT,GAAG,EAAE,CAAC;IACN,QAAQ,EAAE,CAAC;CACZ,CAAC,CAAC;AAEH,8EAA8E;AAC9E,SAAS,KAAK,CAAC,GAAW,EAAE,KAAc;IACxC,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;AAC3D,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,iBAAiB,CACtC,MAAoB,EACpB,MAAoC,EACpC,UAAwB,EAAE;IAE1B,MAAM,KAAK,GAAG,OAAO,CAAC,aAAa,CAAC;IACpC,MAAM,OAAO,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IAC5D,yEAAyE;IACzE,uEAAuE;IACvE,wEAAwE;IACxE,uEAAuE;IACvE,2DAA2D;IAC3D,MAAM,KAAK,GAAG,IAAI,GAAG,EAAwE,CAAC;IAE9F,MAAM,GAAG,CAAC;IACV,0EAA0E;IAC1E,2EAA2E;IAC3E,sEAAsE;IACtE,sEAAsE;IACtE,MAAM,KAAK,CACT,SAAS,EACT,4FAA4F,CAC7F,CAAC;IACF,MAAM,GAAG,GAAG,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACtC,MAAM,uBAAuB,CAAC;IAE9B,IAAI,WAAW,GAAG,IAAI,CAAC;IACvB,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QACjC,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,CAAC;QACxB,IAAI,KAAK,CAAC,MAAM,KAAK,UAAU;YAAE,SAAS;QAC1C,IAAI,UAAU,CAAC,KAAK,CAAC,iBAAiB,CAAC,GAAG,OAAO;YAAE,SAAS;QAE5D,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9B,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;QACnE,CAAC;QAED,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,WAAW,IAAI,KAAK,CAAC,KAAK,CAAC;QAC9D,MAAM,MAAM,GAAG;YACb,MAAM,EAAE,KAAK,CAAC,OAAO;YACrB,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC,iBAAiB,CAAC;YAC3C,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;YAC1B,SAAS,EAAE;gBACT;oBACE,gBAAgB,EAAE;wBAChB,gBAAgB,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,QAAQ,EAAE;qBAC1C;iBACF;aACF;YACD,mBAAmB,EAAE,EAAE,qBAAqB,EAAE,KAAK,CAAC,WAAW,EAAE;YACjE,UAAU,EAAE,EAAE,mBAAmB,EAAE,iBAAiB,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE;SAChF,CAAC;QACF,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACxD,WAAW,GAAG,KAAK,CAAC;IACtB,CAAC;IACD,MAAM,GAAG,CAAC;IAEV,MAAM,QAAQ,GAAG,CAAC,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;QAC9D,EAAE,EAAE,OAAO;QACX,gBAAgB,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE;QACtC,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;KACxE,CAAC,CAAC,CAAC;IACJ,MAAM,qBAAqB,CAAC;IAC5B,MAAM,KAAK,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAClC,MAAM,GAAG,GAAG,KAAK,CAAC,gBAAgB,EAAE,wBAAwB,CAAC,CAAC;IAC9D,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC7C,MAAM,OAAO,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import type { RunSummary } from '../run.js';
|
|
2
|
+
import type { SnapshotIssue, SuppressedIssue, Target } from '../snapshot.js';
|
|
3
|
+
import { type ReportOptions } from './model.js';
|
|
4
|
+
/**
|
|
5
|
+
* Everything a streaming machine-readable report needs that is not per-issue.
|
|
6
|
+
*
|
|
7
|
+
* **Deliberately not a {@link Snapshot}.** A `Snapshot`'s `issues` and
|
|
8
|
+
* `suppressed` are eagerly-materialised arrays — the right shape for PDF and
|
|
9
|
+
* HTML, which are queued, capped at 500 issues, and fully in memory before
|
|
10
|
+
* Chromium ever runs. The machine formats have no such cap, so their
|
|
11
|
+
* assembler must never hold every issue at once; a `ReportHeader` carries
|
|
12
|
+
* only the handful of fields that do not scale with issue count, and the
|
|
13
|
+
* issues themselves arrive as an `AsyncIterable`.
|
|
14
|
+
*/
|
|
15
|
+
export interface ReportHeader {
|
|
16
|
+
/** The run this report describes. */
|
|
17
|
+
readonly run: RunSummary;
|
|
18
|
+
/** What to compare against, for a retest. Absent for a first run. */
|
|
19
|
+
readonly baseline?: RunSummary;
|
|
20
|
+
/** The system under test. */
|
|
21
|
+
readonly target: Target;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Renders a report as JSON, from a header and a cursor over its issues,
|
|
25
|
+
* rather than from a fully-assembled {@link Snapshot}.
|
|
26
|
+
*
|
|
27
|
+
* **This is the machine path's whole reason to exist (B124).** `renderJson`
|
|
28
|
+
* holds every issue in one array before `JSON.stringify` walks it — measured
|
|
29
|
+
* at 239 MiB for 25,000 issues — so memory scales with the result and three
|
|
30
|
+
* concurrent exports exhaust a 512 MiB instance. This function instead
|
|
31
|
+
* yields the document a fragment at a time: everything that does not depend
|
|
32
|
+
* on having seen every issue is emitted immediately, the `issues` and
|
|
33
|
+
* `suppressed` arrays are written one element per row as the cursors
|
|
34
|
+
* produce them, and the handful of fields that need a full pass —
|
|
35
|
+
* `basis.includesManual`, `breached`, `omitted`, the retest counts — are
|
|
36
|
+
* accumulated in a fold whose state is a few counters, never the issues
|
|
37
|
+
* themselves, and written once both cursors are exhausted. Concatenating
|
|
38
|
+
* every yielded chunk produces one JSON document; nothing here buffers it
|
|
39
|
+
* as a string first.
|
|
40
|
+
*
|
|
41
|
+
* **`sections` grouped by severity and the sorted `resolved` list do not
|
|
42
|
+
* exist here.** Both require holding the whole array to sort; this function
|
|
43
|
+
* instead trusts that `issues` and `suppressed` already arrive in the order
|
|
44
|
+
* the document should show them; a cursor-based caller supplies that with a
|
|
45
|
+
* SQL `ORDER BY`, not with an in-memory sort. `includeResolved` and
|
|
46
|
+
* `severityFloor` still apply, filtering rows out of the stream rather than
|
|
47
|
+
* out of an array.
|
|
48
|
+
*
|
|
49
|
+
* @param header - The run, its baseline, and the target. Never scales with
|
|
50
|
+
* issue count.
|
|
51
|
+
* @param issues - Every issue in scope, most urgent first, in the order the
|
|
52
|
+
* document should list them.
|
|
53
|
+
* @param suppressed - The accepted-risk register, in the order the appendix
|
|
54
|
+
* should list it.
|
|
55
|
+
* @param options - Which report, attribution, and the render time.
|
|
56
|
+
* @returns Chunks of JSON text; concatenated, they are one document.
|
|
57
|
+
*/
|
|
58
|
+
export declare function renderJsonStream(header: ReportHeader, issues: AsyncIterable<SnapshotIssue>, suppressed: AsyncIterable<SuppressedIssue>, options: ReportOptions): AsyncGenerator<string>;
|
|
59
|
+
/**
|
|
60
|
+
* Renders a report as Markdown, from a header and a cursor over its issues,
|
|
61
|
+
* rather than from a fully-assembled {@link Snapshot}. The streaming sibling
|
|
62
|
+
* of {@link renderJsonStream} — see it for the memory argument, which applies
|
|
63
|
+
* here identically: `renderMarkdown` holds every issue in one array before
|
|
64
|
+
* formatting any of it.
|
|
65
|
+
*
|
|
66
|
+
* **The document is reordered relative to `renderMarkdown`, and that is
|
|
67
|
+
* forced rather than stylistic.** The array-based renderer opens with "Basis
|
|
68
|
+
* of testing" and a "What changed" line naming how many issues are past
|
|
69
|
+
* their remediation deadline — both need to know something about *every*
|
|
70
|
+
* issue (`basis.includesManual`, `breached`) before the first line can be
|
|
71
|
+
* printed, which a forward-only stream cannot offer without buffering
|
|
72
|
+
* everything first. So this function prints what it already knows up front
|
|
73
|
+
* (title, scope, the New/Still open/Regressed/Resolved/Suppressed table,
|
|
74
|
+
* which all read straight off `RunSummary`) and moves everything that needs
|
|
75
|
+
* a full pass — the basis statement, the remediation-deadline count, what a
|
|
76
|
+
* severity floor omitted, the retest verdict counts, and what the report
|
|
77
|
+
* does not establish (B109) — into a closing `## Summary` section, written
|
|
78
|
+
* once both cursors are exhausted.
|
|
79
|
+
*
|
|
80
|
+
* **`sections` grouped by severity do not exist here**, for the reason given
|
|
81
|
+
* in {@link renderJsonStream}: `issues` and `suppressed` are trusted to
|
|
82
|
+
* already arrive in the order the document should show them. For a `pen`
|
|
83
|
+
* report that means a severity sub-heading appears whenever the incoming
|
|
84
|
+
* severity changes, without the issue count that heading carries in
|
|
85
|
+
* `renderMarkdown` — the count is not known until the section ends. A
|
|
86
|
+
* `retest` report's per-issue table has no severity floor applied to it,
|
|
87
|
+
* matching `renderMarkdown`: the whole point of that table is showing what
|
|
88
|
+
* happened to every issue carried into the retest, not a curated subset.
|
|
89
|
+
*
|
|
90
|
+
* **`attest` buffers its suppressed list; nothing else buffers issues.** An
|
|
91
|
+
* Attestation Letter states counts and names nobody's individual issue, so
|
|
92
|
+
* it folds the whole `issues` cursor for those counts without printing a
|
|
93
|
+
* row — but it also prints the suppressed appendix *after* that letter body,
|
|
94
|
+
* by which point the `suppressed` cursor would already be exhausted. Holding
|
|
95
|
+
* that one list (the accepted-risk register, ordinarily a minority of the
|
|
96
|
+
* total) is the one deliberate exception to "never hold more than a row".
|
|
97
|
+
*
|
|
98
|
+
* **"What this report does not establish" (B109) lands in the closing
|
|
99
|
+
* `## Summary` section, after the Suppressed findings table rather than
|
|
100
|
+
* before it as in `renderMarkdown`.** `describeLimitations` needs
|
|
101
|
+
* `state.suppressedCount`, complete only once the `suppressed` cursor is
|
|
102
|
+
* drained — and that drain, and the table it produces, happen earlier in
|
|
103
|
+
* this stream than the summary does. The array renderer has no such
|
|
104
|
+
* ordering constraint and keeps limitations immediately before the
|
|
105
|
+
* appendix; forcing the same document order here would mean buffering the
|
|
106
|
+
* suppressed rows a second time for no reason `renderJsonStream` needs to.
|
|
107
|
+
*
|
|
108
|
+
* @param header - The run, its baseline, and the target. Never scales with
|
|
109
|
+
* issue count.
|
|
110
|
+
* @param issues - Every issue in scope, most urgent first: open/regressed
|
|
111
|
+
* before resolved, each group by severity then most-recently-seen first —
|
|
112
|
+
* the order the document lists them in.
|
|
113
|
+
* @param suppressed - The accepted-risk register, in the order the appendix
|
|
114
|
+
* should list it.
|
|
115
|
+
* @param options - Which report, attribution, and the render time.
|
|
116
|
+
* @returns Chunks of Markdown text; concatenated, they are one document.
|
|
117
|
+
*/
|
|
118
|
+
export declare function renderMarkdownStream(header: ReportHeader, issues: AsyncIterable<SnapshotIssue>, suppressed: AsyncIterable<SuppressedIssue>, options: ReportOptions): AsyncGenerator<string>;
|
|
119
|
+
//# sourceMappingURL=stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/report/stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAG5C,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAE7E,OAAO,EASL,KAAK,aAAa,EAEnB,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;;GAUG;AACH,MAAM,WAAW,YAAY;IAC3B,qCAAqC;IACrC,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC;IAEzB,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,CAAC,EAAE,UAAU,CAAC;IAE/B,6BAA6B;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAoED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAuB,gBAAgB,CACrC,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,aAAa,CAAC,aAAa,CAAC,EACpC,UAAU,EAAE,aAAa,CAAC,eAAe,CAAC,EAC1C,OAAO,EAAE,aAAa,GACrB,cAAc,CAAC,MAAM,CAAC,CAoGxB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AACH,wBAAuB,oBAAoB,CACzC,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,aAAa,CAAC,aAAa,CAAC,EACpC,UAAU,EAAE,aAAa,CAAC,eAAe,CAAC,EAC1C,OAAO,EAAE,aAAa,GACrB,cAAc,CAAC,MAAM,CAAC,CA2UxB"}
|