edfcore 0.6.0 → 0.6.2
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/constants.d.ts +1 -1
- package/dist/constants.js +1 -1
- package/dist/diagnostics/format.d.ts +17 -0
- package/dist/diagnostics/format.d.ts.map +1 -1
- package/dist/diagnostics/format.js +46 -6
- package/dist/diagnostics/format.js.map +1 -1
- package/dist/format-annotations.d.ts.map +1 -1
- package/dist/format-annotations.js +2 -3
- package/dist/format-annotations.js.map +1 -1
- package/dist/format-report.d.ts.map +1 -1
- package/dist/format-report.js +5 -1
- package/dist/format-report.js.map +1 -1
- package/dist/options.d.ts +15 -0
- package/dist/options.d.ts.map +1 -1
- package/dist/options.js +24 -0
- package/dist/options.js.map +1 -1
- package/docs/CHANGELOG.md +46 -0
- package/package.json +1 -1
- package/src/constants.ts +1 -1
- package/src/diagnostics/format.ts +49 -6
- package/src/format-annotations.ts +2 -4
- package/src/format-report.ts +6 -1
- package/src/options.ts +26 -0
package/dist/constants.d.ts
CHANGED
|
@@ -109,5 +109,5 @@ export declare const SIGNAL_FIELD_BLOCK_OFFSETS: {
|
|
|
109
109
|
readonly reserved: 224;
|
|
110
110
|
};
|
|
111
111
|
/** Published package version. Kept in sync with package.json by a test. */
|
|
112
|
-
export declare const VERSION = "0.6.
|
|
112
|
+
export declare const VERSION = "0.6.2";
|
|
113
113
|
//# sourceMappingURL=constants.d.ts.map
|
package/dist/constants.js
CHANGED
|
@@ -33,6 +33,23 @@ export interface FormatDiagnosticsOptions {
|
|
|
33
33
|
*/
|
|
34
34
|
readonly redactFields?: readonly string[];
|
|
35
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* A name outside the vocabulary is refused rather than ignored.
|
|
38
|
+
*
|
|
39
|
+
* `redactFields` is the one option in this package whose silent failure sends a person's name
|
|
40
|
+
* somewhere it should not go, and matching is exact — `'patientID'`, `'patient'` and
|
|
41
|
+
* `'patient_id'` all withheld nothing and reported nothing, so the caller who asked for redaction
|
|
42
|
+
* got a report with the name in it and no way to tell. It is the same shape `parseArgs` refuses a
|
|
43
|
+
* misspelled `--patinet` for, and for the same reason: a flag that silently does nothing prints
|
|
44
|
+
* the output the caller was trying to avoid.
|
|
45
|
+
*
|
|
46
|
+
* Checked before anything is rendered, so an empty diagnostics array reports the typo too. A leak
|
|
47
|
+
* found on the first clean file costs nothing; found on the file that has a problem it is already
|
|
48
|
+
* on someone's screen — which is also why `formatValidationReport` calls this itself rather than
|
|
49
|
+
* relying on the `formatDiagnostics` below it: that call is inside an `if (length > 0)`, so a PASS
|
|
50
|
+
* would have said nothing and the same argument would have leaked on the next file.
|
|
51
|
+
*/
|
|
52
|
+
export declare function assertRedactableFields(fields: readonly string[] | undefined): void;
|
|
36
53
|
/**
|
|
37
54
|
* A multi-line report, one block per diagnostic. Returns `''` for an empty list so the result
|
|
38
55
|
* can be concatenated into a larger report without a stray blank line.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/diagnostics/format.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/diagnostics/format.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,OAAO,KAAK,EAAE,aAAa,EAAe,MAAM,aAAa,CAAC;AAE9D;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;;;;;;;;;OAaG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3C;AAmBD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,GAAG,IAAI,CAUlF;AAgBD;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,SAAS,aAAa,EAAE,EACrC,OAAO,CAAC,EAAE,wBAAwB,GACjC,MAAM,CAmBR"}
|
|
@@ -9,7 +9,51 @@
|
|
|
9
9
|
* no iteration over an unordered collection, and no ANSI escapes unless `color` is requested.
|
|
10
10
|
*/
|
|
11
11
|
import { trimEdfField } from '../bytes/latin1.js';
|
|
12
|
+
import { HEADER_FIELDS, SIGNAL_FIELD_WIDTHS } from '../constants.js';
|
|
13
|
+
import { requireItemLimit } from '../options.js';
|
|
12
14
|
import { printable } from '../text/printable.js';
|
|
15
|
+
/**
|
|
16
|
+
* Every value `field` can hold on a diagnostic edfcore produces.
|
|
17
|
+
*
|
|
18
|
+
* Two of the three sources are the header layout itself, so a field added there is redactable the
|
|
19
|
+
* day it exists; the other three are the diagnostics that name something the layout has no entry
|
|
20
|
+
* for — the whole header block, the data-record region, and the record size the geometry implies.
|
|
21
|
+
* `redaction-vocabulary.test.ts` builds the same set out of `src/` and refuses a difference, which
|
|
22
|
+
* is what stops this from drifting behind a diagnostic that names a new field.
|
|
23
|
+
*/
|
|
24
|
+
const REDACTABLE_FIELDS = new Set([
|
|
25
|
+
...Object.keys(HEADER_FIELDS),
|
|
26
|
+
...Object.keys(SIGNAL_FIELD_WIDTHS),
|
|
27
|
+
'dataRecords',
|
|
28
|
+
'header',
|
|
29
|
+
'recordByteLength',
|
|
30
|
+
]);
|
|
31
|
+
/**
|
|
32
|
+
* A name outside the vocabulary is refused rather than ignored.
|
|
33
|
+
*
|
|
34
|
+
* `redactFields` is the one option in this package whose silent failure sends a person's name
|
|
35
|
+
* somewhere it should not go, and matching is exact — `'patientID'`, `'patient'` and
|
|
36
|
+
* `'patient_id'` all withheld nothing and reported nothing, so the caller who asked for redaction
|
|
37
|
+
* got a report with the name in it and no way to tell. It is the same shape `parseArgs` refuses a
|
|
38
|
+
* misspelled `--patinet` for, and for the same reason: a flag that silently does nothing prints
|
|
39
|
+
* the output the caller was trying to avoid.
|
|
40
|
+
*
|
|
41
|
+
* Checked before anything is rendered, so an empty diagnostics array reports the typo too. A leak
|
|
42
|
+
* found on the first clean file costs nothing; found on the file that has a problem it is already
|
|
43
|
+
* on someone's screen — which is also why `formatValidationReport` calls this itself rather than
|
|
44
|
+
* relying on the `formatDiagnostics` below it: that call is inside an `if (length > 0)`, so a PASS
|
|
45
|
+
* would have said nothing and the same argument would have leaked on the next file.
|
|
46
|
+
*/
|
|
47
|
+
export function assertRedactableFields(fields) {
|
|
48
|
+
for (const field of fields ?? []) {
|
|
49
|
+
if (REDACTABLE_FIELDS.has(field))
|
|
50
|
+
continue;
|
|
51
|
+
throw new RangeError(`options.redactFields names ${JSON.stringify(field)}, which is not a field any edfcore ` +
|
|
52
|
+
'diagnostic reports, so nothing would have been withheld for it. Next: pass names from ' +
|
|
53
|
+
`${[...REDACTABLE_FIELDS].sort().join(', ')} — "patientId" and "recordingId" are the two ` +
|
|
54
|
+
"that carry a person's name.");
|
|
55
|
+
}
|
|
56
|
+
}
|
|
13
57
|
const INDENT = ' ';
|
|
14
58
|
/** A report is a summary, not a hex dump; longer runs are elided with a count. */
|
|
15
59
|
const MAX_RAW_BYTES_SHOWN = 24;
|
|
@@ -26,8 +70,9 @@ const SEVERITY_COLORS = {
|
|
|
26
70
|
*/
|
|
27
71
|
export function formatDiagnostics(diagnostics, options) {
|
|
28
72
|
const color = options?.color === true;
|
|
29
|
-
const shown =
|
|
73
|
+
const shown = requireItemLimit(options?.maxItems, diagnostics.length);
|
|
30
74
|
const lines = [];
|
|
75
|
+
assertRedactableFields(options?.redactFields);
|
|
31
76
|
const redact = new Set(options?.redactFields ?? []);
|
|
32
77
|
for (let i = 0; i < shown; i++) {
|
|
33
78
|
const diagnostic = diagnostics[i];
|
|
@@ -41,11 +86,6 @@ export function formatDiagnostics(diagnostics, options) {
|
|
|
41
86
|
lines.push(paint(`... and ${hidden} more`, ANSI_DIM, color));
|
|
42
87
|
return lines.join('\n');
|
|
43
88
|
}
|
|
44
|
-
function resolveLimit(maxItems, total) {
|
|
45
|
-
if (maxItems === undefined || !Number.isFinite(maxItems))
|
|
46
|
-
return total;
|
|
47
|
-
return Math.max(0, Math.min(total, Math.floor(maxItems)));
|
|
48
|
-
}
|
|
49
89
|
const REDACTED = '[redacted]';
|
|
50
90
|
/**
|
|
51
91
|
* Removes a field's content from every place `appendDiagnostic` would print it.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/diagnostics/format.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AA4BjD,MAAM,MAAM,GAAG,IAAI,CAAC;AAEpB,kFAAkF;AAClF,MAAM,mBAAmB,GAAG,EAAE,CAAC;AAE/B,MAAM,UAAU,GAAG,WAAW,CAAC;AAC/B,MAAM,QAAQ,GAAG,WAAW,CAAC;AAE7B,MAAM,eAAe,GAA0C;IAC7D,KAAK,EAAE,YAAY;IACnB,OAAO,EAAE,YAAY;IACrB,IAAI,EAAE,YAAY;CACnB,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,WAAqC,EACrC,OAAkC;IAElC,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,KAAK,IAAI,CAAC;IACtC,MAAM,KAAK,GAAG,
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/diagnostics/format.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AA4BjD;;;;;;;;GAQG;AACH,MAAM,iBAAiB,GAAwB,IAAI,GAAG,CAAC;IACrD,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC;IAC7B,GAAG,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC;IACnC,aAAa;IACb,QAAQ;IACR,kBAAkB;CACnB,CAAC,CAAC;AAEH;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAAqC;IAC1E,KAAK,MAAM,KAAK,IAAI,MAAM,IAAI,EAAE,EAAE,CAAC;QACjC,IAAI,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE,SAAS;QAC3C,MAAM,IAAI,UAAU,CAClB,8BAA8B,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,qCAAqC;YACtF,wFAAwF;YACxF,GAAG,CAAC,GAAG,iBAAiB,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,+CAA+C;YAC1F,6BAA6B,CAChC,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,MAAM,GAAG,IAAI,CAAC;AAEpB,kFAAkF;AAClF,MAAM,mBAAmB,GAAG,EAAE,CAAC;AAE/B,MAAM,UAAU,GAAG,WAAW,CAAC;AAC/B,MAAM,QAAQ,GAAG,WAAW,CAAC;AAE7B,MAAM,eAAe,GAA0C;IAC7D,KAAK,EAAE,YAAY;IACnB,OAAO,EAAE,YAAY;IACrB,IAAI,EAAE,YAAY;CACnB,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,WAAqC,EACrC,OAAkC;IAElC,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,KAAK,IAAI,CAAC;IACtC,MAAM,KAAK,GAAG,gBAAgB,CAAC,OAAO,EAAE,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACtE,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,sBAAsB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IAC9C,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,EAAE,YAAY,IAAI,EAAE,CAAC,CAAC;IAEpD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/B,MAAM,UAAU,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;QAClC,oFAAoF;QACpF,IAAI,UAAU,KAAK,SAAS;YAAE,SAAS;QACvC,gBAAgB,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IACrD,CAAC;IAED,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,GAAG,KAAK,CAAC;IAC1C,IAAI,MAAM,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,MAAM,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;IAE7E,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,QAAQ,GAAG,YAAY,CAAC;AAE9B;;;;;;;;;;GAUG;AACH,SAAS,gBAAgB,CAAC,UAAyB;IACjD,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC;IAC3B,IAAI,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC;IACjC,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB;;;;;;;;WAQG;QACH,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;QACjF,MAAM,OAAO,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;QAClC,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IACnD,CAAC;IACD;;;;;;;;OAQG;IACH,IAAI,UAAU,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QACzC,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IACjD,CAAC;IACD,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO;QACL,GAAG,UAAU;QACb,OAAO;QACP,GAAG,EAAE,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ;QAC7C,QAAQ,EAAE,SAAS;QACnB,MAAM,EAAE,UAAU,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ;KAC/D,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CACvB,KAAe,EACf,KAAoB,EACpB,KAAc,EACd,YAAiC;IAEjC,MAAM,UAAU,GACd,KAAK,CAAC,KAAK,KAAK,SAAS,IAAI,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAC/F,MAAM,MAAM,GAAG,KAAK,CAClB,GAAG,UAAU,CAAC,QAAQ,KAAK,UAAU,CAAC,IAAI,GAAG,EAC7C,eAAe,CAAC,UAAU,CAAC,QAAQ,CAAC,EACpC,KAAK,CACN,CAAC;IAEF;;;;;;;;;;;OAWG;IACH,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;IAC5D,MAAM,KAAK,GAAG,YAAY,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACpC,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI,KAAK,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;IAC3C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7C,MAAM,IAAI,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;QAC7B,IAAI,IAAI,KAAK,SAAS;YAAE,SAAS;QACjC,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACxC,CAAC;IAED,MAAM,QAAQ,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;IACxC,IAAI,QAAQ,KAAK,SAAS;QAAE,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC3D,IAAI,UAAU,CAAC,GAAG,KAAK,SAAS;QAAE,MAAM,CAAC,KAAK,EAAE,QAAQ,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IACxF,IAAI,UAAU,CAAC,QAAQ,KAAK,SAAS,IAAI,UAAU,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxE,MAAM,CAAC,KAAK,EAAE,UAAU,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IACjE,CAAC;IACD,6FAA6F;IAC7F,+FAA+F;IAC/F,6FAA6F;IAC7F,gGAAgG;IAChG,wFAAwF;IACxF,IAAI,UAAU,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QACtC,MAAM,CAAC,KAAK,EAAE,aAAa,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAC9E,CAAC;IACD,IAAI,UAAU,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QACpC,MAAM,CAAC,KAAK,EAAE,WAAW,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAC1E,CAAC;IACD,IAAI,UAAU,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;QAC3C,MAAM,CAAC,KAAK,EAAE,SAAS,UAAU,CAAC,aAAa,EAAE,EAAE,KAAK,CAAC,CAAC;IAC5D,CAAC;AACH,CAAC;AAED,SAAS,MAAM,CAAC,KAAe,EAAE,IAAY,EAAE,KAAc;IAC3D,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,GAAG,KAAK,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;AACzD,CAAC;AAED,SAAS,UAAU,CAAC,UAAyB;IAC3C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,UAAU,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;QACxC,KAAK,CAAC,IAAI,CACR,UAAU,CAAC,UAAU,KAAK,SAAS;YACjC,CAAC,CAAC,eAAe,UAAU,CAAC,UAAU,EAAE;YACxC,CAAC,CAAC,eAAe,UAAU,CAAC,UAAU,KAAK,UAAU,CAAC,UAAU,SAAS,CAC5E,CAAC;IACJ,CAAC;IACD,IAAI,UAAU,CAAC,KAAK,KAAK,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IACjE,IAAI,UAAU,CAAC,WAAW,KAAK,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,UAAU,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC;IACzF,IAAI,UAAU,CAAC,WAAW,KAAK,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,UAAU,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC;IACzF,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AACnE,CAAC;AAED,4FAA4F;AAC5F,SAAS,OAAO,CAAC,KAAiB;IAChC,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,mBAAmB,CAAC,CAAC;IACrD,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,IAAI,KAAK,GAAG,EAAE,CAAC;IACf,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;QAC7C,KAAK,IAAI,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IACpE,CAAC;IACD,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAC3C,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,KAAK,IAAI,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;AAC/E,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAY;IACpC,OAAO,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC;AACtC,CAAC;AAED,iGAAiG;AACjG,SAAS,KAAK,CAAC,KAAa;IAC1B,IAAI,GAAG,GAAG,GAAG,CAAC;IACd,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACtC,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,IAAI;YAAE,GAAG,IAAI,KAAK,IAAI,EAAE,CAAC;aACjD,IAAI,gBAAgB,CAAC,IAAI,CAAC;YAAE,GAAG,IAAI,IAAI,CAAC;aACxC,IAAI,IAAI,IAAI,IAAI;YAAE,GAAG,IAAI,MAAM,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;;YACpE,GAAG,IAAI,OAAO,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC;IAC1C,CAAC;IACD,OAAO,GAAG,GAAG,GAAG,CAAC;AACnB,CAAC;AAED,SAAS,KAAK,CAAC,IAAY,EAAE,KAAa,EAAE,OAAgB;IAC1D,OAAO,OAAO,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,IAAI,GAAG,UAAU,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACzD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format-annotations.d.ts","sourceRoot":"","sources":["../src/format-annotations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;
|
|
1
|
+
{"version":3,"file":"format-annotations.d.ts","sourceRoot":"","sources":["../src/format-annotations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAMH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,2FAA2F;IAC3F,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,kGAAkG;IAClG,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;CACnC;AA0CD;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,SAAS,aAAa,EAAE,EACrC,OAAO,CAAC,EAAE,wBAAwB,GACjC,MAAM,CA6BR"}
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
* file says. Clamping it to zero would silently move an event.
|
|
16
16
|
*/
|
|
17
17
|
import { TICKS_PER_SECOND } from './constants.js';
|
|
18
|
+
import { requireItemLimit } from './options.js';
|
|
18
19
|
import { floorDiv } from './tal/ticks.js';
|
|
19
20
|
import { printable } from './text/printable.js';
|
|
20
21
|
const TICKS_PER_MILLISECOND = TICKS_PER_SECOND / 1000n;
|
|
@@ -63,9 +64,7 @@ function duration(annotation) {
|
|
|
63
64
|
export function formatAnnotations(annotations, options) {
|
|
64
65
|
if (annotations.length === 0)
|
|
65
66
|
return '';
|
|
66
|
-
const limit = options?.maxItems
|
|
67
|
-
? annotations.length
|
|
68
|
-
: Math.max(0, Math.min(annotations.length, Math.floor(options.maxItems)));
|
|
67
|
+
const limit = requireItemLimit(options?.maxItems, annotations.length);
|
|
69
68
|
const rows = [];
|
|
70
69
|
for (let i = 0; i < limit; i += 1) {
|
|
71
70
|
const annotation = annotations[i];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format-annotations.js","sourceRoot":"","sources":["../src/format-annotations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAehD,MAAM,qBAAqB,GAAG,gBAAgB,GAAG,KAAK,CAAC;AAEvD;;;;;;GAMG;AACH,SAAS,KAAK,CAAC,KAAa;IAC1B,2FAA2F;IAC3F,gGAAgG;IAChG,gGAAgG;IAChG,6FAA6F;IAC7F,wFAAwF;IACxF,MAAM,mBAAmB,GAAG,QAAQ,CAAC,KAAK,EAAE,qBAAqB,CAAC,CAAC;IACnE,MAAM,QAAQ,GAAG,mBAAmB,GAAG,EAAE,CAAC;IAC1C,MAAM,iBAAiB,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,mBAAmB,CAAC;IAEhF,MAAM,YAAY,GAAG,iBAAiB,GAAG,KAAK,CAAC;IAC/C,MAAM,YAAY,GAAG,iBAAiB,GAAG,KAAK,CAAC;IAC/C,MAAM,OAAO,GAAG,YAAY,GAAG,GAAG,CAAC;IACnC,MAAM,YAAY,GAAG,YAAY,GAAG,GAAG,CAAC;IACxC,MAAM,OAAO,GAAG,YAAY,GAAG,GAAG,CAAC;IACnC,MAAM,KAAK,GAAG,YAAY,GAAG,GAAG,CAAC;IAEjC,MAAM,GAAG,GAAG,CAAC,KAAa,EAAE,KAAa,EAAU,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACzF,OAAO,CACL,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE;QAC9E,IAAI,GAAG,CAAC,YAAY,EAAE,CAAC,CAAC,EAAE,CAC3B,CAAC;AACJ,CAAC;AAED,6FAA6F;AAC7F,SAAS,QAAQ,CAAC,UAAyB;IACzC,MAAM,KAAK,GAAG,UAAU,CAAC,aAAa,CAAC;IACvC,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE;QAAE,OAAO,EAAE,CAAC;IACnD,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;AAC3B,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAC/B,WAAqC,EACrC,OAAkC;IAElC,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAExC,MAAM,KAAK,
|
|
1
|
+
{"version":3,"file":"format-annotations.js","sourceRoot":"","sources":["../src/format-annotations.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format-report.d.ts","sourceRoot":"","sources":["../src/format-report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AASnF;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,gBAAgB,EACxB,OAAO,CAAC,EAAE,mBAAmB,GAC5B,MAAM,
|
|
1
|
+
{"version":3,"file":"format-report.d.ts","sourceRoot":"","sources":["../src/format-report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AASnF;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,gBAAgB,EACxB,OAAO,CAAC,EAAE,mBAAmB,GAC5B,MAAM,CA6ER;AAED,qFAAqF;AACrF,YAAY,EAAE,SAAS,EAAE,CAAC"}
|
package/dist/format-report.js
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* and only then the individual entries, capped. What a reader needs first is *which kinds* of
|
|
13
13
|
* thing are wrong and how much of the file is affected.
|
|
14
14
|
*/
|
|
15
|
-
import { formatDiagnostics } from './diagnostics/format.js';
|
|
15
|
+
import { assertRedactableFields, formatDiagnostics } from './diagnostics/format.js';
|
|
16
16
|
import { summarizeDiagnostics } from './diagnostics/summary.js';
|
|
17
17
|
import { printable } from './text/printable.js';
|
|
18
18
|
/** Enough to see the pattern, few enough to read. Override with `maxItems`. */
|
|
@@ -29,6 +29,10 @@ function pluralise(count, noun) {
|
|
|
29
29
|
export function formatValidationReport(report, options) {
|
|
30
30
|
const lines = [];
|
|
31
31
|
const header = options?.header;
|
|
32
|
+
// Before anything is rendered, and outside the `diagnostics.length > 0` branch below. A report
|
|
33
|
+
// that passes still has to report a misspelled `redactFields`: the typo belongs to the call, and
|
|
34
|
+
// the clean file is the cheap place to find out about it.
|
|
35
|
+
assertRedactableFields(options?.redactFields);
|
|
32
36
|
// One counting implementation, shared with the public `summarizeDiagnostics`.
|
|
33
37
|
const summary = summarizeDiagnostics(report.diagnostics);
|
|
34
38
|
const verdict = report.ok ? 'PASS' : 'FAIL';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format-report.js","sourceRoot":"","sources":["../src/format-report.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"format-report.js","sourceRoot":"","sources":["../src/format-report.ts"],"names":[],"mappings":"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"}
|
package/dist/options.d.ts
CHANGED
|
@@ -22,6 +22,21 @@
|
|
|
22
22
|
* got nothing — treating them alike would silently apply the default to a real mistake.
|
|
23
23
|
*/
|
|
24
24
|
export declare function requireFiniteOption(value: number | undefined, name: string, fallback: number): number;
|
|
25
|
+
/**
|
|
26
|
+
* `maxItems`, resolved against the number of items there actually are.
|
|
27
|
+
*
|
|
28
|
+
* The same class as `requireFiniteOption` and a different answer for `Infinity`, which is why it
|
|
29
|
+
* is a second function rather than a call to that one. `formatValidationReport` caps at 20 by
|
|
30
|
+
* default, so `Infinity` is the only spelling of "print all of them" a caller has; clamped against
|
|
31
|
+
* `total` it is exact, and refusing it would remove the option's only way to say that.
|
|
32
|
+
*
|
|
33
|
+
* `NaN` is refused. It used to mean the same as `Infinity` — both were `!Number.isFinite`, both
|
|
34
|
+
* returned `total` — so a limit computed from an absent config key printed the whole list, which
|
|
35
|
+
* is the opposite of what the caller asked for and looks like a file with a great deal wrong with
|
|
36
|
+
* it. `parseArgs` has refused a `NaN --limit` since the flag existed, and says why in a comment;
|
|
37
|
+
* the library function underneath it did the thing that comment describes.
|
|
38
|
+
*/
|
|
39
|
+
export declare function requireItemLimit(value: number | undefined, total: number): number;
|
|
25
40
|
/**
|
|
26
41
|
* `maxMaterializeBytes`, or the 256 MiB default.
|
|
27
42
|
*
|
package/dist/options.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GACf,MAAM,CAQR;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAQ1E"}
|
|
1
|
+
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GACf,MAAM,CAQR;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAUjF;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAQ1E"}
|
package/dist/options.js
CHANGED
|
@@ -31,6 +31,30 @@ export function requireFiniteOption(value, name, fallback) {
|
|
|
31
31
|
'expression that produced it — Number() on an absent environment variable, query ' +
|
|
32
32
|
'parameter or config key yields NaN.');
|
|
33
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* `maxItems`, resolved against the number of items there actually are.
|
|
36
|
+
*
|
|
37
|
+
* The same class as `requireFiniteOption` and a different answer for `Infinity`, which is why it
|
|
38
|
+
* is a second function rather than a call to that one. `formatValidationReport` caps at 20 by
|
|
39
|
+
* default, so `Infinity` is the only spelling of "print all of them" a caller has; clamped against
|
|
40
|
+
* `total` it is exact, and refusing it would remove the option's only way to say that.
|
|
41
|
+
*
|
|
42
|
+
* `NaN` is refused. It used to mean the same as `Infinity` — both were `!Number.isFinite`, both
|
|
43
|
+
* returned `total` — so a limit computed from an absent config key printed the whole list, which
|
|
44
|
+
* is the opposite of what the caller asked for and looks like a file with a great deal wrong with
|
|
45
|
+
* it. `parseArgs` has refused a `NaN --limit` since the flag existed, and says why in a comment;
|
|
46
|
+
* the library function underneath it did the thing that comment describes.
|
|
47
|
+
*/
|
|
48
|
+
export function requireItemLimit(value, total) {
|
|
49
|
+
if (value === undefined)
|
|
50
|
+
return total;
|
|
51
|
+
if (Number.isNaN(value)) {
|
|
52
|
+
throw new RangeError('options.maxItems must be a number, but was NaN. Next: check the expression that produced ' +
|
|
53
|
+
'it — Number() on an absent environment variable, query parameter or config key yields ' +
|
|
54
|
+
'NaN. Pass Infinity for no cap.');
|
|
55
|
+
}
|
|
56
|
+
return Math.max(0, Math.min(total, Math.floor(value)));
|
|
57
|
+
}
|
|
34
58
|
/**
|
|
35
59
|
* `maxMaterializeBytes`, or the 256 MiB default.
|
|
36
60
|
*
|
package/dist/options.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"options.js","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,6BAA6B,EAAE,MAAM,gBAAgB,CAAC;AAE/D;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CACjC,KAAyB,EACzB,IAAY,EACZ,QAAgB;IAEhB,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IACzC,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACzC,MAAM,IAAI,UAAU,CAClB,WAAW,IAAI,qCAAqC,MAAM,CAAC,KAAK,CAAC,oBAAoB;QACnF,kFAAkF;QAClF,qCAAqC,CACxC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,wBAAwB,CAAC,KAAyB;IAChE,MAAM,MAAM,GAAG,mBAAmB,CAAC,KAAK,EAAE,qBAAqB,EAAE,6BAA6B,CAAC,CAAC;IAChG,IAAI,MAAM,IAAI,CAAC;QAAE,OAAO,MAAM,CAAC;IAC/B,MAAM,IAAI,UAAU,CAClB,6DAA6D,MAAM,0BAA0B;QAC3F,0DAA0D;QAC1D,GAAG,6BAA6B,gBAAgB,CACnD,CAAC;AACJ,CAAC"}
|
|
1
|
+
{"version":3,"file":"options.js","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,6BAA6B,EAAE,MAAM,gBAAgB,CAAC;AAE/D;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CACjC,KAAyB,EACzB,IAAY,EACZ,QAAgB;IAEhB,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,QAAQ,CAAC;IACzC,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACzC,MAAM,IAAI,UAAU,CAClB,WAAW,IAAI,qCAAqC,MAAM,CAAC,KAAK,CAAC,oBAAoB;QACnF,kFAAkF;QAClF,qCAAqC,CACxC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAyB,EAAE,KAAa;IACvE,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACtC,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,UAAU,CAClB,2FAA2F;YACzF,wFAAwF;YACxF,gCAAgC,CACnC,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACzD,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,wBAAwB,CAAC,KAAyB;IAChE,MAAM,MAAM,GAAG,mBAAmB,CAAC,KAAK,EAAE,qBAAqB,EAAE,6BAA6B,CAAC,CAAC;IAChG,IAAI,MAAM,IAAI,CAAC;QAAE,OAAO,MAAM,CAAC;IAC/B,MAAM,IAAI,UAAU,CAClB,6DAA6D,MAAM,0BAA0B;QAC3F,0DAA0D;QAC1D,GAAG,6BAA6B,gBAAgB,CACnD,CAAC;AACJ,CAAC"}
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,52 @@ alone does not tell you whether you were affected.
|
|
|
6
6
|
edfcore is pre-1.0. Patch releases have carried behaviour changes where the old behaviour was a
|
|
7
7
|
defect; those are called out below.
|
|
8
8
|
|
|
9
|
+
## 0.6.2
|
|
10
|
+
|
|
11
|
+
- **Fixed** a misspelled `redactFields` name being ignored. Redaction matches exactly against
|
|
12
|
+
`diagnostic.field`, so `'patientID'`, `'patient'` and `'patient_id'` each withheld nothing and
|
|
13
|
+
reported nothing: the caller had asked for the one option in this package whose failure
|
|
14
|
+
discloses a person's name, and got a report with the name in it that looked like a report with
|
|
15
|
+
the name taken out. `formatDiagnostics` and `formatValidationReport` now throw `RangeError`
|
|
16
|
+
naming the value and listing the vocabulary.
|
|
17
|
+
- A diagnostic quotes the bytes it is complaining about by design — that is what makes it
|
|
18
|
+
actionable — and for an identification field those bytes are a name and a date of birth. The
|
|
19
|
+
files that earn such a diagnostic are the ones a person runs a tool on and pastes the output of.
|
|
20
|
+
- `parseArgs` has always refused a misspelled `--patinet`, with a comment saying why: a flag that
|
|
21
|
+
silently does nothing prints the output the caller was trying to avoid. The CLI was safe either
|
|
22
|
+
way because it passes the pair as a literal. A library caller spells the name themselves.
|
|
23
|
+
- The check runs before anything is rendered, so an empty diagnostics list reports the typo too,
|
|
24
|
+
and `formatValidationReport` runs it itself rather than leaving it to the `formatDiagnostics`
|
|
25
|
+
underneath — that call sits inside `if (diagnostics.length > 0)`, so a PASS would have said
|
|
26
|
+
nothing and the same argument would have leaked on the next file.
|
|
27
|
+
- The vocabulary is the fixed header layout, the per-signal layout, and the three names no layout
|
|
28
|
+
map covers (`dataRecords`, `header`, `recordByteLength`). `redaction-vocabulary.test.ts` rebuilds
|
|
29
|
+
it out of `src/` and refuses a difference, so a diagnostic that names a new field fails there
|
|
30
|
+
rather than telling a caller a real field does not exist.
|
|
31
|
+
|
|
32
|
+
## 0.6.1
|
|
33
|
+
|
|
34
|
+
- **Fixed** `maxItems: NaN` disabling the cap instead of being refused. `formatDiagnostics`,
|
|
35
|
+
`formatAnnotations` and `formatValidationReport` all resolved the option with
|
|
36
|
+
`!Number.isFinite(maxItems)`, which is true of `NaN` and of `Infinity` alike, and all three
|
|
37
|
+
answered it with the total — so a limit computed from an absent environment variable, query
|
|
38
|
+
parameter or config key printed the whole list. It throws `RangeError` naming `options.maxItems`
|
|
39
|
+
now.
|
|
40
|
+
- The rule was already written down one layer up. `parseArgs` refuses a `NaN --limit` and the
|
|
41
|
+
comment beside that guard says why: "a NaN limit would disable the cap silently, which is the
|
|
42
|
+
opposite of what was asked for". The library functions that flag reaches did exactly that, and
|
|
43
|
+
it is the class `options.ts` exists for — an omitted option means "use the default", a `NaN`
|
|
44
|
+
means a caller computed something and got nothing, and treating them alike applies the default
|
|
45
|
+
to a real mistake.
|
|
46
|
+
- It costs most where the cap matters most: a sweep over a damaged file can produce six figures of
|
|
47
|
+
diagnostics, `TIMEKEEPING_TAL_MISSING` is one per record, and the caller who asked for twenty
|
|
48
|
+
got all of them with no sign a limit had ever been applied.
|
|
49
|
+
- **Changed**: `maxItems: -Infinity` showed everything and now shows nothing, which is what every
|
|
50
|
+
other negative value already did. `Infinity` still means "no cap" and is what the refusal
|
|
51
|
+
recommends — `formatValidationReport` caps at twenty by default, so it is the only spelling a
|
|
52
|
+
caller has for printing the lot. That is why this is a second resolver in `options.ts` rather
|
|
53
|
+
than a call to `requireFiniteOption`, which refuses `Infinity` too.
|
|
54
|
+
|
|
9
55
|
## 0.6.0
|
|
10
56
|
|
|
11
57
|
The public API is unchanged: nothing was added, removed or renamed, and no arithmetic moved. This
|
package/package.json
CHANGED
package/src/constants.ts
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import { trimEdfField } from '../bytes/latin1.js';
|
|
13
|
+
import { HEADER_FIELDS, SIGNAL_FIELD_WIDTHS } from '../constants.js';
|
|
14
|
+
import { requireItemLimit } from '../options.js';
|
|
13
15
|
import { printable } from '../text/printable.js';
|
|
14
16
|
import type { EdfDiagnostic, EdfSeverity } from '../types.js';
|
|
15
17
|
|
|
@@ -38,6 +40,51 @@ export interface FormatDiagnosticsOptions {
|
|
|
38
40
|
readonly redactFields?: readonly string[];
|
|
39
41
|
}
|
|
40
42
|
|
|
43
|
+
/**
|
|
44
|
+
* Every value `field` can hold on a diagnostic edfcore produces.
|
|
45
|
+
*
|
|
46
|
+
* Two of the three sources are the header layout itself, so a field added there is redactable the
|
|
47
|
+
* day it exists; the other three are the diagnostics that name something the layout has no entry
|
|
48
|
+
* for — the whole header block, the data-record region, and the record size the geometry implies.
|
|
49
|
+
* `redaction-vocabulary.test.ts` builds the same set out of `src/` and refuses a difference, which
|
|
50
|
+
* is what stops this from drifting behind a diagnostic that names a new field.
|
|
51
|
+
*/
|
|
52
|
+
const REDACTABLE_FIELDS: ReadonlySet<string> = new Set([
|
|
53
|
+
...Object.keys(HEADER_FIELDS),
|
|
54
|
+
...Object.keys(SIGNAL_FIELD_WIDTHS),
|
|
55
|
+
'dataRecords',
|
|
56
|
+
'header',
|
|
57
|
+
'recordByteLength',
|
|
58
|
+
]);
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* A name outside the vocabulary is refused rather than ignored.
|
|
62
|
+
*
|
|
63
|
+
* `redactFields` is the one option in this package whose silent failure sends a person's name
|
|
64
|
+
* somewhere it should not go, and matching is exact — `'patientID'`, `'patient'` and
|
|
65
|
+
* `'patient_id'` all withheld nothing and reported nothing, so the caller who asked for redaction
|
|
66
|
+
* got a report with the name in it and no way to tell. It is the same shape `parseArgs` refuses a
|
|
67
|
+
* misspelled `--patinet` for, and for the same reason: a flag that silently does nothing prints
|
|
68
|
+
* the output the caller was trying to avoid.
|
|
69
|
+
*
|
|
70
|
+
* Checked before anything is rendered, so an empty diagnostics array reports the typo too. A leak
|
|
71
|
+
* found on the first clean file costs nothing; found on the file that has a problem it is already
|
|
72
|
+
* on someone's screen — which is also why `formatValidationReport` calls this itself rather than
|
|
73
|
+
* relying on the `formatDiagnostics` below it: that call is inside an `if (length > 0)`, so a PASS
|
|
74
|
+
* would have said nothing and the same argument would have leaked on the next file.
|
|
75
|
+
*/
|
|
76
|
+
export function assertRedactableFields(fields: readonly string[] | undefined): void {
|
|
77
|
+
for (const field of fields ?? []) {
|
|
78
|
+
if (REDACTABLE_FIELDS.has(field)) continue;
|
|
79
|
+
throw new RangeError(
|
|
80
|
+
`options.redactFields names ${JSON.stringify(field)}, which is not a field any edfcore ` +
|
|
81
|
+
'diagnostic reports, so nothing would have been withheld for it. Next: pass names from ' +
|
|
82
|
+
`${[...REDACTABLE_FIELDS].sort().join(', ')} — "patientId" and "recordingId" are the two ` +
|
|
83
|
+
"that carry a person's name.",
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
41
88
|
const INDENT = ' ';
|
|
42
89
|
|
|
43
90
|
/** A report is a summary, not a hex dump; longer runs are elided with a count. */
|
|
@@ -61,9 +108,10 @@ export function formatDiagnostics(
|
|
|
61
108
|
options?: FormatDiagnosticsOptions,
|
|
62
109
|
): string {
|
|
63
110
|
const color = options?.color === true;
|
|
64
|
-
const shown =
|
|
111
|
+
const shown = requireItemLimit(options?.maxItems, diagnostics.length);
|
|
65
112
|
const lines: string[] = [];
|
|
66
113
|
|
|
114
|
+
assertRedactableFields(options?.redactFields);
|
|
67
115
|
const redact = new Set(options?.redactFields ?? []);
|
|
68
116
|
|
|
69
117
|
for (let i = 0; i < shown; i++) {
|
|
@@ -79,11 +127,6 @@ export function formatDiagnostics(
|
|
|
79
127
|
return lines.join('\n');
|
|
80
128
|
}
|
|
81
129
|
|
|
82
|
-
function resolveLimit(maxItems: number | undefined, total: number): number {
|
|
83
|
-
if (maxItems === undefined || !Number.isFinite(maxItems)) return total;
|
|
84
|
-
return Math.max(0, Math.min(total, Math.floor(maxItems)));
|
|
85
|
-
}
|
|
86
|
-
|
|
87
130
|
const REDACTED = '[redacted]';
|
|
88
131
|
|
|
89
132
|
/**
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
import { TICKS_PER_SECOND } from './constants.js';
|
|
19
|
+
import { requireItemLimit } from './options.js';
|
|
19
20
|
import { floorDiv } from './tal/ticks.js';
|
|
20
21
|
import { printable } from './text/printable.js';
|
|
21
22
|
import type { EdfAnnotation } from './types.js';
|
|
@@ -87,10 +88,7 @@ export function formatAnnotations(
|
|
|
87
88
|
): string {
|
|
88
89
|
if (annotations.length === 0) return '';
|
|
89
90
|
|
|
90
|
-
const limit =
|
|
91
|
-
options?.maxItems === undefined || !Number.isFinite(options.maxItems)
|
|
92
|
-
? annotations.length
|
|
93
|
-
: Math.max(0, Math.min(annotations.length, Math.floor(options.maxItems)));
|
|
91
|
+
const limit = requireItemLimit(options?.maxItems, annotations.length);
|
|
94
92
|
|
|
95
93
|
const rows: string[] = [];
|
|
96
94
|
for (let i = 0; i < limit; i += 1) {
|
package/src/format-report.ts
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* thing are wrong and how much of the file is affected.
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
import { formatDiagnostics } from './diagnostics/format.js';
|
|
16
|
+
import { assertRedactableFields, formatDiagnostics } from './diagnostics/format.js';
|
|
17
17
|
import { summarizeDiagnostics } from './diagnostics/summary.js';
|
|
18
18
|
import { printable } from './text/printable.js';
|
|
19
19
|
import type { EdfHeader, FormatReportOptions, ValidationReport } from './types.js';
|
|
@@ -38,6 +38,11 @@ export function formatValidationReport(
|
|
|
38
38
|
const lines: string[] = [];
|
|
39
39
|
const header = options?.header;
|
|
40
40
|
|
|
41
|
+
// Before anything is rendered, and outside the `diagnostics.length > 0` branch below. A report
|
|
42
|
+
// that passes still has to report a misspelled `redactFields`: the typo belongs to the call, and
|
|
43
|
+
// the clean file is the cheap place to find out about it.
|
|
44
|
+
assertRedactableFields(options?.redactFields);
|
|
45
|
+
|
|
41
46
|
// One counting implementation, shared with the public `summarizeDiagnostics`.
|
|
42
47
|
const summary = summarizeDiagnostics(report.diagnostics);
|
|
43
48
|
|
package/src/options.ts
CHANGED
|
@@ -38,6 +38,32 @@ export function requireFiniteOption(
|
|
|
38
38
|
);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
/**
|
|
42
|
+
* `maxItems`, resolved against the number of items there actually are.
|
|
43
|
+
*
|
|
44
|
+
* The same class as `requireFiniteOption` and a different answer for `Infinity`, which is why it
|
|
45
|
+
* is a second function rather than a call to that one. `formatValidationReport` caps at 20 by
|
|
46
|
+
* default, so `Infinity` is the only spelling of "print all of them" a caller has; clamped against
|
|
47
|
+
* `total` it is exact, and refusing it would remove the option's only way to say that.
|
|
48
|
+
*
|
|
49
|
+
* `NaN` is refused. It used to mean the same as `Infinity` — both were `!Number.isFinite`, both
|
|
50
|
+
* returned `total` — so a limit computed from an absent config key printed the whole list, which
|
|
51
|
+
* is the opposite of what the caller asked for and looks like a file with a great deal wrong with
|
|
52
|
+
* it. `parseArgs` has refused a `NaN --limit` since the flag existed, and says why in a comment;
|
|
53
|
+
* the library function underneath it did the thing that comment describes.
|
|
54
|
+
*/
|
|
55
|
+
export function requireItemLimit(value: number | undefined, total: number): number {
|
|
56
|
+
if (value === undefined) return total;
|
|
57
|
+
if (Number.isNaN(value)) {
|
|
58
|
+
throw new RangeError(
|
|
59
|
+
'options.maxItems must be a number, but was NaN. Next: check the expression that produced ' +
|
|
60
|
+
'it — Number() on an absent environment variable, query parameter or config key yields ' +
|
|
61
|
+
'NaN. Pass Infinity for no cap.',
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
return Math.max(0, Math.min(total, Math.floor(value)));
|
|
65
|
+
}
|
|
66
|
+
|
|
41
67
|
/**
|
|
42
68
|
* `maxMaterializeBytes`, or the 256 MiB default.
|
|
43
69
|
*
|