@hawkeyexl/manni 2.0.1 → 2.2.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/README.md +1 -1
- package/dist/{chunk-MV2T7XAW.js → chunk-2Q5JUEIO.js} +380 -62
- package/dist/chunk-2Q5JUEIO.js.map +1 -0
- package/dist/{chunk-PDNSN5UJ.js → chunk-5O4FIGDJ.js} +4952 -758
- package/dist/chunk-5O4FIGDJ.js.map +1 -0
- package/dist/{chunk-QLVNSAHR.js → chunk-6JWX6JM2.js} +160 -550
- package/dist/chunk-6JWX6JM2.js.map +1 -0
- package/dist/cli.js +10 -18
- package/dist/cli.js.map +1 -1
- package/dist/docmeta.js +4 -3
- package/dist/docmeta.js.map +1 -1
- package/dist/index.d.ts +965 -565
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-MV2T7XAW.js.map +0 -1
- package/dist/chunk-PDNSN5UJ.js.map +0 -1
- package/dist/chunk-QLVNSAHR.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -402,6 +402,126 @@ interface ConfigFile {
|
|
|
402
402
|
encryptionKeyPrevious?: string;
|
|
403
403
|
}
|
|
404
404
|
|
|
405
|
+
/** Lines as an entry writes them: an integer for one line, `"L1-L2"` for several. */
|
|
406
|
+
type LineSpec = number | string;
|
|
407
|
+
/** Page lines as an editor numbers them, 1-based and inclusive. */
|
|
408
|
+
interface PageLines {
|
|
409
|
+
start: number;
|
|
410
|
+
end: number;
|
|
411
|
+
}
|
|
412
|
+
/** A 1-based inclusive range, either end optional: no `start` is the whole text, no `end` one line. */
|
|
413
|
+
interface LineRange {
|
|
414
|
+
start?: number;
|
|
415
|
+
end?: number;
|
|
416
|
+
}
|
|
417
|
+
/** BOM stripped, CRLF folded to LF. */
|
|
418
|
+
declare function normalizeText(text: string): string;
|
|
419
|
+
/** The normalized lines, without the empty element a trailing LF leaves. */
|
|
420
|
+
declare function splitLines(text: string): string[];
|
|
421
|
+
/**
|
|
422
|
+
* The pin of already-joined lines: `sha256-<hex>`, or with `key` the
|
|
423
|
+
* `hmac-sha256-<hex>` keyed pin an encrypted value carries. A plain pin
|
|
424
|
+
* passes `undefined`.
|
|
425
|
+
*/
|
|
426
|
+
declare function hashLines(joined: string, key?: string): string;
|
|
427
|
+
/** Whether a pin is keyed (`hmac-sha256-`), the form an encrypted value carries. */
|
|
428
|
+
declare function isKeyedPin(pin: string): boolean;
|
|
429
|
+
/** The plain pin of a range of lines; undefined when the range falls outside them or ends before it starts. */
|
|
430
|
+
declare function pinOfLines(lines: readonly string[], range: PageLines): string | undefined;
|
|
431
|
+
/** Half-width of the band around the original position the blind move search tries first. */
|
|
432
|
+
declare const MOVE_WINDOW_LINES = 2000;
|
|
433
|
+
/** Default hashing budget for the blind move search, in bytes. */
|
|
434
|
+
declare const MOVE_BUDGET_BYTES: number;
|
|
435
|
+
/** The widest range a move search is attempted for. */
|
|
436
|
+
declare const MAX_RANGE_LINES = 5000;
|
|
437
|
+
interface FindWindowsOptions {
|
|
438
|
+
/** The 1-based start line the range was pinned at: the blind search begins around it. */
|
|
439
|
+
around?: number;
|
|
440
|
+
/** The pinned lines as they were, when known: enables the first-line filter. */
|
|
441
|
+
original?: readonly string[];
|
|
442
|
+
/** Hashing budget for the blind search, in bytes. Default `MOVE_BUDGET_BYTES`. */
|
|
443
|
+
budget?: number;
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* Pure move search over normalized lines: the 1-based start lines where a
|
|
447
|
+
* window of `length` lines hashes to `pin`. `original` (the pinned lines as
|
|
448
|
+
* they were, when known) enables the first-line filter. `key` keys the hash
|
|
449
|
+
* for a keyed pin and is `undefined` for a plain one.
|
|
450
|
+
*/
|
|
451
|
+
declare function findWindows(lines: readonly string[], length: number, pin: string, key: string | undefined, opts?: FindWindowsOptions): {
|
|
452
|
+
starts: number[];
|
|
453
|
+
truncated: boolean;
|
|
454
|
+
};
|
|
455
|
+
/**
|
|
456
|
+
* The lines a `LineSpec` names. Undefined for a value that is neither a
|
|
457
|
+
* positive integer nor `"L1-L2"` with `L1 <= L2`.
|
|
458
|
+
*/
|
|
459
|
+
declare function parseLines(spec: LineSpec): PageLines | undefined;
|
|
460
|
+
/** Lines as an entry writes them: the integer for one line, `"L1-L2"` otherwise. */
|
|
461
|
+
declare function lineSpec(lines: PageLines): LineSpec;
|
|
462
|
+
/** Lines as a report spells them: `"9"` or `"9-12"`. */
|
|
463
|
+
declare function spellLines(lines: PageLines): string;
|
|
464
|
+
/** Body lines as file lines: body line 1 is the file line `bodyLine`, the first after the frontmatter. */
|
|
465
|
+
declare function toFileLines(lines: PageLines, bodyLine: number): PageLines;
|
|
466
|
+
/** File lines as body lines. */
|
|
467
|
+
declare function toBodyLines(lines: PageLines, bodyLine: number): PageLines;
|
|
468
|
+
|
|
469
|
+
/** One `provenance` entry as stored: body lines, and the pin over them. */
|
|
470
|
+
interface ProvenanceEntry {
|
|
471
|
+
"generated-by": string;
|
|
472
|
+
lines: LineSpec;
|
|
473
|
+
integrity: string;
|
|
474
|
+
}
|
|
475
|
+
/** A page read for provenance. */
|
|
476
|
+
interface ProvenancePage {
|
|
477
|
+
/** Every normalized line of the file. */
|
|
478
|
+
lines: string[];
|
|
479
|
+
/** The file line body line 1 sits on. */
|
|
480
|
+
bodyLine: number;
|
|
481
|
+
/** The body's lines: `lines` from `bodyLine` on. */
|
|
482
|
+
body: string[];
|
|
483
|
+
/** The well-formed `provenance` entries the frontmatter carries. */
|
|
484
|
+
stamp: ProvenanceEntry[];
|
|
485
|
+
}
|
|
486
|
+
/** Which of 0046's five evidence rules answered for a line. */
|
|
487
|
+
type EvidenceRule = 1 | 2 | 3 | 4 | 5;
|
|
488
|
+
/** A line's evidence: the machine, or none under rule 5, and the blamed sha. */
|
|
489
|
+
interface LineEvidence {
|
|
490
|
+
machine?: string;
|
|
491
|
+
rule: EvidenceRule;
|
|
492
|
+
sha: string;
|
|
493
|
+
}
|
|
494
|
+
/** One derived range: its entry, its body lines, and its first line's evidence. */
|
|
495
|
+
interface DerivedRange {
|
|
496
|
+
entry: ProvenanceEntry;
|
|
497
|
+
span: PageLines;
|
|
498
|
+
evidence: LineEvidence;
|
|
499
|
+
}
|
|
500
|
+
/** A page's derivation: the page, each body line's evidence, and the ranges. */
|
|
501
|
+
interface ProvenanceDerivation {
|
|
502
|
+
page: ProvenancePage;
|
|
503
|
+
evidenceByLine: ReadonlyMap<number, LineEvidence>;
|
|
504
|
+
derived: DerivedRange[];
|
|
505
|
+
}
|
|
506
|
+
/** 0046's comparison verdicts. */
|
|
507
|
+
type ProvenanceStatus = "current" | "moved" | "changed" | "stale" | "unset";
|
|
508
|
+
/** One range of `DerivedField.ranges`, in file lines. */
|
|
509
|
+
interface RangeResult {
|
|
510
|
+
lines: string;
|
|
511
|
+
"generated-by": string;
|
|
512
|
+
integrity: string;
|
|
513
|
+
status: ProvenanceStatus;
|
|
514
|
+
/** `uncommitted`, `blame <sha7>`, or `pin` when only the pin speaks for the range. */
|
|
515
|
+
evidence: string;
|
|
516
|
+
/** What the record said before: on `moved` and `stale` only. */
|
|
517
|
+
from?: {
|
|
518
|
+
lines: string;
|
|
519
|
+
"generated-by": string;
|
|
520
|
+
};
|
|
521
|
+
/** Whether `derive` wrote this range; always false until it does. */
|
|
522
|
+
written: boolean;
|
|
523
|
+
}
|
|
524
|
+
|
|
405
525
|
/**
|
|
406
526
|
* The derived metadata channel: values computed from git history, CODEOWNERS
|
|
407
527
|
* and the review record on GitHub or GitLab rather than written by hand.
|
|
@@ -415,11 +535,11 @@ interface ConfigFile {
|
|
|
415
535
|
* one, and turning the stale comparisons into findings.
|
|
416
536
|
*/
|
|
417
537
|
|
|
418
|
-
/** The
|
|
419
|
-
declare const DERIVABLE_FIELDS: readonly ["created", "last-updated", "authors", "owner", "reviewed-by", "last-reviewed"];
|
|
538
|
+
/** The seven built-in fields, in the order messages list them. */
|
|
539
|
+
declare const DERIVABLE_FIELDS: readonly ["created", "last-updated", "authors", "owner", "reviewed-by", "last-reviewed", "provenance"];
|
|
420
540
|
type BuiltinDerivableField = (typeof DERIVABLE_FIELDS)[number];
|
|
421
541
|
/**
|
|
422
|
-
* A managed field name: one of the
|
|
542
|
+
* A managed field name: one of the seven built-ins, or a key with an entry in
|
|
423
543
|
* `derive.commands`. The config parser guarantees one or the other.
|
|
424
544
|
*/
|
|
425
545
|
type DerivableField = string;
|
|
@@ -500,6 +620,32 @@ interface DeriveInput {
|
|
|
500
620
|
absPath: string;
|
|
501
621
|
content: string;
|
|
502
622
|
extracted: ExtractedMetadata;
|
|
623
|
+
/**
|
|
624
|
+
* Where the page's `provenance` record lives when a manifest owns it
|
|
625
|
+
* (proposal 0046), so evidence rule 2 reads the manifest's blob at each
|
|
626
|
+
* commit rather than the page's frontmatter. Absent: the page's own.
|
|
627
|
+
*/
|
|
628
|
+
provenanceManifest?: ProvenanceManifestRef;
|
|
629
|
+
/**
|
|
630
|
+
* `manni meta derive <path>:L1-L2 --generated-by <name>`: the file lines
|
|
631
|
+
* each target names go to `generatedBy`, committed or not, unless evidence
|
|
632
|
+
* names another machine, and no other uncommitted line does. Ranges that
|
|
633
|
+
* overlap attribute their union. Each target is a positional as typed,
|
|
634
|
+
* which every refusal quotes.
|
|
635
|
+
*/
|
|
636
|
+
attribution?: {
|
|
637
|
+
targets: string[];
|
|
638
|
+
generatedBy: string;
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
/** A manifest that holds one page's `provenance`, as the git source reads it at a commit. */
|
|
642
|
+
interface ProvenanceManifestRef {
|
|
643
|
+
/** The manifest file, absolute. */
|
|
644
|
+
absPath: string;
|
|
645
|
+
/** The page's key there: its path relative to the config directory, or its join value. */
|
|
646
|
+
entry: string;
|
|
647
|
+
/** `path`, or the page field the manifest joins on. */
|
|
648
|
+
join: string;
|
|
503
649
|
}
|
|
504
650
|
/** What a derive run holds constant across every document it visits. */
|
|
505
651
|
interface DeriveContext {
|
|
@@ -518,6 +664,10 @@ interface DeriveContext {
|
|
|
518
664
|
now: () => Date;
|
|
519
665
|
/** The review client for every repository in the run; the built-in `gh` / `glab` clients when absent. */
|
|
520
666
|
reviews?: ReviewClient;
|
|
667
|
+
/** `--generated-by` or `MANNI_GENERATED_BY` (proposal 0046): who uncommitted body lines go to. */
|
|
668
|
+
generatedBy?: string;
|
|
669
|
+
/** `derive.machines`: trailer identities that are machines; `["*[bot]"]` when absent. */
|
|
670
|
+
machines?: readonly string[];
|
|
521
671
|
}
|
|
522
672
|
/**
|
|
523
673
|
* How an asserted value stands against the derived one.
|
|
@@ -542,6 +692,25 @@ interface DerivedField {
|
|
|
542
692
|
status: DerivedStatus;
|
|
543
693
|
/** Whether `derive` wrote the value into the document. */
|
|
544
694
|
written: boolean;
|
|
695
|
+
/**
|
|
696
|
+
* `provenance` only (proposal 0046): one verdict per range, in file lines.
|
|
697
|
+
* The field's own `status` is `current` when every range is, and
|
|
698
|
+
* otherwise `stale`, or `unset` when the page carries no record at all.
|
|
699
|
+
*/
|
|
700
|
+
ranges?: RangeResult[];
|
|
701
|
+
/**
|
|
702
|
+
* `provenance` only: the manifest that holds the page's record, as the run
|
|
703
|
+
* reports it, when one does. `derive` writes there, never into the page.
|
|
704
|
+
*/
|
|
705
|
+
manifest?: string;
|
|
706
|
+
/**
|
|
707
|
+
* Proposal 0047: the manifest a field other than `provenance` is written
|
|
708
|
+
* into, as the run reports it, when a manifest of the page's collections
|
|
709
|
+
* owns the key. Absent when the value goes to the page.
|
|
710
|
+
*/
|
|
711
|
+
destination?: string;
|
|
712
|
+
/** The 1-based line of the key in `destination` after the write. Absent under `dryRun` and `check`. */
|
|
713
|
+
destinationLine?: number;
|
|
545
714
|
}
|
|
546
715
|
/**
|
|
547
716
|
* The `schema` ref a stale-field finding carries, and so its baseline and
|
|
@@ -567,9 +736,14 @@ declare function compareDerived(field: DerivableField, asserted: unknown, derive
|
|
|
567
736
|
* field that is `stale` or `unset`. Current and unknown fields file nothing.
|
|
568
737
|
*
|
|
569
738
|
* `lineFor` is the document's own pointer lookup, so a finding lands on the
|
|
570
|
-
* line the asserted key sits on; an unset field has no line.
|
|
739
|
+
* line the asserted key sits on; an unset field has no line. `locate` answers
|
|
740
|
+
* for a value a manifest supplied (proposal 0047): the finding then names the
|
|
741
|
+
* manifest and its line, as every other manifest finding does.
|
|
571
742
|
*/
|
|
572
|
-
declare function staleFindings(fields: readonly DerivedField[], lineFor: (pointer: string) => number | undefined
|
|
743
|
+
declare function staleFindings(fields: readonly DerivedField[], lineFor: (pointer: string) => number | undefined, locate?: (pointer: string) => {
|
|
744
|
+
file: string;
|
|
745
|
+
line?: number;
|
|
746
|
+
} | undefined): FieldError[];
|
|
573
747
|
|
|
574
748
|
interface SchemaOverride {
|
|
575
749
|
/**
|
|
@@ -708,6 +882,14 @@ interface DeriveConfig {
|
|
|
708
882
|
* is never a built-in field, `$schema`, or a key a manifest owns.
|
|
709
883
|
*/
|
|
710
884
|
commands?: Record<string, DeriveCommandConfig>;
|
|
885
|
+
/**
|
|
886
|
+
* Trailer identities that are machines (proposal 0046), as globs matched
|
|
887
|
+
* case-sensitively against a trailer's name and its email, with literal
|
|
888
|
+
* brackets. A match names a machine for `provenance` and is left out of
|
|
889
|
+
* `authors`. Absent means `["*[bot]"]`, which is 0040's rule; read it
|
|
890
|
+
* through `machinesOf`.
|
|
891
|
+
*/
|
|
892
|
+
machines?: string[];
|
|
711
893
|
}
|
|
712
894
|
/** Defaults for the `fill` command; every key is overridable by a CLI flag. */
|
|
713
895
|
interface FillConfig {
|
|
@@ -1181,189 +1363,222 @@ interface GetFileResult {
|
|
|
1181
1363
|
* one. A run carrying any `error` exits 1.
|
|
1182
1364
|
*/
|
|
1183
1365
|
error?: string;
|
|
1366
|
+
/**
|
|
1367
|
+
* `provenance` only (proposal 0046), present when it was requested and the
|
|
1368
|
+
* file parsed. `bodyLine` is the file line body line 1 sits on, which the
|
|
1369
|
+
* record's body lines are shown against. `current` is whether the record
|
|
1370
|
+
* agrees with git as `validate` judges it, range by range; absent when
|
|
1371
|
+
* nothing was derived.
|
|
1372
|
+
*/
|
|
1373
|
+
provenance?: {
|
|
1374
|
+
bodyLine: number;
|
|
1375
|
+
current?: boolean;
|
|
1376
|
+
};
|
|
1184
1377
|
}
|
|
1185
1378
|
declare function runGet(opts: GetOptions): Promise<GetFileResult[]>;
|
|
1186
1379
|
|
|
1187
1380
|
/** Ask a yes/no question; `true` only for a yes. */
|
|
1188
1381
|
type Confirm = (question: string) => Promise<boolean>;
|
|
1189
1382
|
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
/**
|
|
1218
|
-
|
|
1219
|
-
/** Permit an input set that resolves to zero files (see `assertNonEmpty`). */
|
|
1220
|
-
allowEmpty?: boolean;
|
|
1383
|
+
/**
|
|
1384
|
+
* The `schema` ref a collision finding carries, and so its baseline and rule
|
|
1385
|
+
* identity: `external:owned/external`. Shaped like `check:<name>` so
|
|
1386
|
+
* `classifyRef` passes it through as a built-in id rather than resolving it
|
|
1387
|
+
* as a cwd-relative file path, and reserved in the registry for the same
|
|
1388
|
+
* reason `check` is.
|
|
1389
|
+
*/
|
|
1390
|
+
declare const EXTERNAL_OWNED_SCHEMA = "external:owned";
|
|
1391
|
+
/**
|
|
1392
|
+
* The `schema` ref of a duplicate-join finding (0039): two documents carry
|
|
1393
|
+
* the same value of a join field, so one manifest entry matched both.
|
|
1394
|
+
*/
|
|
1395
|
+
declare const EXTERNAL_DUPLICATE_SCHEMA = "external:duplicate";
|
|
1396
|
+
/**
|
|
1397
|
+
* The `keyword` every external-metadata finding carries: no Ajv keyword
|
|
1398
|
+
* produced it.
|
|
1399
|
+
*/
|
|
1400
|
+
declare const EXTERNAL_KEYWORD = "external";
|
|
1401
|
+
/** The join that names documents by path, and the default. */
|
|
1402
|
+
declare const PATH_JOIN = "path";
|
|
1403
|
+
/** One value a manifest supplied, and where it was written. */
|
|
1404
|
+
interface ExternalMetadataValue {
|
|
1405
|
+
value: unknown;
|
|
1406
|
+
/** The collection whose manifest supplied it (proposal 0041). */
|
|
1407
|
+
collection: string;
|
|
1408
|
+
/** Manifest path as the run reports it: relative to the run's base, posix — or the URL. */
|
|
1409
|
+
file: string;
|
|
1410
|
+
/** 1-based line of the key in the manifest, when known. */
|
|
1411
|
+
line?: number;
|
|
1221
1412
|
/**
|
|
1222
|
-
*
|
|
1223
|
-
*
|
|
1413
|
+
* 1-based manifest line of every node inside `value`, keyed by the JSON
|
|
1414
|
+
* Pointer relative to `value` (`/2/source/file`). A mapping member sits on
|
|
1415
|
+
* its key's line, and a list item on the line its node starts. Present only
|
|
1416
|
+
* when `value` is a mapping or a list with members; `line` answers for the
|
|
1417
|
+
* value itself.
|
|
1224
1418
|
*/
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1419
|
+
lines?: ReadonlyMap<string, number>;
|
|
1420
|
+
}
|
|
1421
|
+
/** One manifest entry, for the orphan checks. */
|
|
1422
|
+
interface ExternalMetadataEntry {
|
|
1423
|
+
/** The collection whose manifest declared it (proposal 0041). */
|
|
1424
|
+
collection: string;
|
|
1425
|
+
/** `path`, or the frontmatter field this entry is keyed by. */
|
|
1426
|
+
join: string;
|
|
1427
|
+
/** Absolute document path, for a path entry. */
|
|
1428
|
+
abs?: string;
|
|
1429
|
+
/** The key exactly as written in the manifest. */
|
|
1430
|
+
spelled: string;
|
|
1431
|
+
/** Manifest path as the run reports it. */
|
|
1432
|
+
file: string;
|
|
1433
|
+
/** 1-based line of the entry in the manifest, when known. */
|
|
1434
|
+
line?: number;
|
|
1435
|
+
}
|
|
1436
|
+
/** Every manifest of a run, loaded once and consulted per document. */
|
|
1437
|
+
interface ExternalMetadataIndex {
|
|
1230
1438
|
/**
|
|
1231
|
-
*
|
|
1232
|
-
*
|
|
1233
|
-
*
|
|
1234
|
-
*
|
|
1235
|
-
*
|
|
1439
|
+
* Owned key -> every collection that owns it, with the manifest that does.
|
|
1440
|
+
*
|
|
1441
|
+
* A list rather than one entry, because two collections may legitimately
|
|
1442
|
+
* each own the same key (0041 rule 5): `guides` and `blog` can both supply
|
|
1443
|
+
* `owner`. Ambiguity only exists for a file that is a member of both, which
|
|
1444
|
+
* is decided per file in `mergeExternalMetadata`.
|
|
1236
1445
|
*/
|
|
1446
|
+
owners: ReadonlyMap<string, readonly {
|
|
1447
|
+
collection: string;
|
|
1448
|
+
file: string;
|
|
1449
|
+
}[]>;
|
|
1450
|
+
/** Path-joined manifests: absolute document path -> owned key -> value. */
|
|
1451
|
+
byPath: ReadonlyMap<string, ReadonlyMap<string, ExternalMetadataValue>>;
|
|
1452
|
+
/** Field-joined manifests: field -> value -> owned key -> value. */
|
|
1453
|
+
byField: ReadonlyMap<string, ReadonlyMap<string, ReadonlyMap<string, ExternalMetadataValue>>>;
|
|
1454
|
+
/** Every manifest entry, in manifest order. */
|
|
1455
|
+
entries: readonly ExternalMetadataEntry[];
|
|
1456
|
+
}
|
|
1457
|
+
interface LoadExternalMetadataOptions {
|
|
1458
|
+
/** Directory `externalMetadata[].file` and every manifest key resolve from. */
|
|
1459
|
+
configDir: string;
|
|
1460
|
+
/** Directory the run's file labels are relative to; manifests are reported the same way. */
|
|
1461
|
+
base: string;
|
|
1462
|
+
/** `--offline` / `offline:`: a URL manifest is refused rather than fetched (0038). */
|
|
1237
1463
|
offline?: boolean;
|
|
1464
|
+
/** Network timeout for a URL manifest; the schema fetch's default otherwise. */
|
|
1465
|
+
timeoutMs?: number;
|
|
1466
|
+
/** For tests: the environment `tokenEnv` is read from. */
|
|
1467
|
+
env?: Record<string, string | undefined>;
|
|
1468
|
+
}
|
|
1469
|
+
/** A place a merged value lives, for a finding that must name it. */
|
|
1470
|
+
interface SourceLocation {
|
|
1471
|
+
file: string;
|
|
1472
|
+
line?: number;
|
|
1473
|
+
col?: number;
|
|
1474
|
+
}
|
|
1475
|
+
/** A key the document carries that a manifest owns. */
|
|
1476
|
+
interface ExternalMetadataCollision {
|
|
1477
|
+
key: string;
|
|
1478
|
+
/** The owning manifest, as the run reports it. */
|
|
1479
|
+
file: string;
|
|
1480
|
+
/** The collection that manifest belongs to (proposal 0041). */
|
|
1481
|
+
collection: string;
|
|
1482
|
+
}
|
|
1483
|
+
/** A field-joined entry a document matched (0039). */
|
|
1484
|
+
interface ExternalMetadataJoin {
|
|
1485
|
+
field: string;
|
|
1486
|
+
/** The value matched: the field's plaintext, decrypted first when the page holds it encrypted. */
|
|
1487
|
+
value: string;
|
|
1238
1488
|
/**
|
|
1239
|
-
*
|
|
1240
|
-
*
|
|
1241
|
-
*
|
|
1489
|
+
* The field as the page holds it, when that differs from `value`: the
|
|
1490
|
+
* ciphertext of an encrypted join field (proposal 0045). A finding about
|
|
1491
|
+
* the join names this, never the plaintext.
|
|
1242
1492
|
*/
|
|
1243
|
-
|
|
1493
|
+
pageValue?: string;
|
|
1494
|
+
/** The manifest, as the run reports it. */
|
|
1495
|
+
file: string;
|
|
1496
|
+
/** The collection that manifest belongs to (proposal 0041). */
|
|
1497
|
+
collection: string;
|
|
1498
|
+
}
|
|
1499
|
+
/** What `mergeExternalMetadata` hands back. */
|
|
1500
|
+
interface MergedMetadata {
|
|
1501
|
+
/** The document's metadata with every owned key the manifest supplied. */
|
|
1502
|
+
extracted: ExtractedMetadata;
|
|
1244
1503
|
/**
|
|
1245
|
-
*
|
|
1246
|
-
*
|
|
1247
|
-
*
|
|
1248
|
-
* preview-by-default surface this revises).
|
|
1504
|
+
* Owned keys the document itself also carried, in document order, each
|
|
1505
|
+
* with the manifest that owns it — so the finding names it without a
|
|
1506
|
+
* second lookup, and without a fallback for an index that is not there.
|
|
1249
1507
|
*/
|
|
1250
|
-
|
|
1508
|
+
collisions: ExternalMetadataCollision[];
|
|
1509
|
+
/** Field-joined entries this document matched, one per manifest at most. */
|
|
1510
|
+
joins: ExternalMetadataJoin[];
|
|
1251
1511
|
/**
|
|
1252
|
-
*
|
|
1253
|
-
*
|
|
1254
|
-
*
|
|
1255
|
-
*
|
|
1256
|
-
*
|
|
1257
|
-
*
|
|
1258
|
-
*
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
/**
|
|
1262
|
-
* `-s/--schema`, repeatable: the schema set the run's DDL evolves — CLI
|
|
1263
|
-
* precedence for the DDL planner *only* (proposal 0030). The per-file
|
|
1264
|
-
* resolution walk is skipped and the deduped refs are the set; every guard
|
|
1265
|
-
* inside the set (single local file for ADD, sole declarer for
|
|
1266
|
-
* DROP/RENAME, builtin fork, URL refusal, the trust boundary) runs
|
|
1267
|
-
* unchanged. Collection views keep following the config's resolution. A
|
|
1268
|
-
* run whose statement produces no DDL effect refuses before anything is
|
|
1269
|
-
* applied — a flag that would silently mean nothing must refuse.
|
|
1270
|
-
*/
|
|
1271
|
-
schemas?: string[];
|
|
1272
|
-
/**
|
|
1273
|
-
* How to ask for a new encryption key when an `UPDATE` or `INSERT` writes
|
|
1274
|
-
* a column its schema marks `x-manni-encrypt` and no key is available
|
|
1275
|
-
* (proposal 0045). The CLI passes `terminalConfirm()`, which is
|
|
1276
|
-
* `undefined` off a terminal; absent, such a write refuses (exit 2). A dry
|
|
1277
|
-
* run never asks: it writes nothing.
|
|
1278
|
-
*/
|
|
1279
|
-
confirm?: Confirm;
|
|
1280
|
-
/**
|
|
1281
|
-
* The environment `MANNI_ENCRYPTION_KEY` is read from. Defaults to
|
|
1282
|
-
* `process.env`; tests pass their own.
|
|
1512
|
+
* Where a merged pointer's value lives. Answers only for a value the
|
|
1513
|
+
* manifest supplied — a bare key or its `/key` pointer, and anything
|
|
1514
|
+
* beneath it — and `undefined` for everything the document owns, which is
|
|
1515
|
+
* what `lineFor` is for.
|
|
1516
|
+
*
|
|
1517
|
+
* The line is the deepest manifest node the pointer reaches, so
|
|
1518
|
+
* `/citations/2` is the third item's line and `/citations/2/source/file`
|
|
1519
|
+
* that member's. A pointer past what the manifest holds falls back to the
|
|
1520
|
+
* nearest ancestor that exists, and at worst to the owned key's line.
|
|
1283
1521
|
*/
|
|
1284
|
-
|
|
1285
|
-
/** The clock an uncommitted body change is dated by. Test seam; default `new Date()`. */
|
|
1286
|
-
now?: () => Date;
|
|
1522
|
+
locate: (pointer: string) => SourceLocation | undefined;
|
|
1287
1523
|
}
|
|
1524
|
+
/** The join an external-metadata config asks for: `path` unless it names a field. */
|
|
1525
|
+
declare function externalMetadataJoin(manifest: Pick<ExternalMetadataConfig, "join">): string;
|
|
1288
1526
|
/**
|
|
1289
|
-
*
|
|
1290
|
-
*
|
|
1291
|
-
*
|
|
1292
|
-
*
|
|
1293
|
-
*
|
|
1527
|
+
* Load every manifest of every collection the run covers. Resolves to `null`
|
|
1528
|
+
* when none of them declares one, which is every setup that existed before
|
|
1529
|
+
* this feature.
|
|
1530
|
+
*
|
|
1531
|
+
* Every refusal is a `DocmetaError`: the manifest is a config-supplied input,
|
|
1532
|
+
* and one that is missing or misshapen is the run's problem, not a
|
|
1533
|
+
* document's (0014).
|
|
1294
1534
|
*/
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
interface QueryRun {
|
|
1343
|
-
/** Result column names, in SELECT order — present even for zero rows. */
|
|
1344
|
-
columns: string[];
|
|
1345
|
-
rows: Record<string, unknown>[];
|
|
1346
|
-
/** Set when `db` was written: where, and how big the table is. */
|
|
1347
|
-
db?: {
|
|
1348
|
-
path: string;
|
|
1349
|
-
files: number;
|
|
1350
|
-
columns: number;
|
|
1351
|
-
};
|
|
1352
|
-
/**
|
|
1353
|
-
* Present when the statement was a metadata edit: every cell it changed
|
|
1354
|
-
* (empty when a mutating statement matched nothing). Absent on reads.
|
|
1355
|
-
*/
|
|
1356
|
-
changes?: QueryChange[];
|
|
1357
|
-
/**
|
|
1358
|
-
* Where the run stood, in the same shape `ValidateRun.frame` carries — the
|
|
1359
|
-
* path-normalization frame SARIF and JUnit need before they can name a file
|
|
1360
|
-
* the way the repository does (proposal 0026). Constructed from the run's
|
|
1361
|
-
* `cwd`, its config directory, and the directory file labels resolve
|
|
1362
|
-
* against; absent only when a caller built a `QueryRun` by hand.
|
|
1363
|
-
*/
|
|
1364
|
-
frame?: FingerprintContext;
|
|
1365
|
-
}
|
|
1366
|
-
declare function runQuery(opts: QueryOptions): Promise<QueryRun>;
|
|
1535
|
+
declare function loadExternalMetadata(collections: readonly CollectionConfig[], opts: LoadExternalMetadataOptions): Promise<ExternalMetadataIndex | null>;
|
|
1536
|
+
/**
|
|
1537
|
+
* Merge the external metadata for one document into its extracted metadata.
|
|
1538
|
+
*
|
|
1539
|
+
* `label` is the document as the run spells it, relative to `base`; a path
|
|
1540
|
+
* entry matches on the resolved absolute path, never on the spelling, so a
|
|
1541
|
+
* positional run from a subdirectory finds the same entry a config-corpus
|
|
1542
|
+
* run does. A field entry matches on the document's own value of the join
|
|
1543
|
+
* field, wherever the document lives. Stdin never matches a path entry:
|
|
1544
|
+
* there is no file behind it.
|
|
1545
|
+
*
|
|
1546
|
+
* `memberOf` names the collections this document belongs to, and only their
|
|
1547
|
+
* manifests are consulted (0041 rule 4). It is the caller's `memberOf(...)`
|
|
1548
|
+
* result, computed once per file.
|
|
1549
|
+
*
|
|
1550
|
+
* `present`, `format` and the document's own positions are untouched. A
|
|
1551
|
+
* manifest key is not in the document, so `lineFor` keeps answering
|
|
1552
|
+
* `undefined` for it, and `locate` answers instead.
|
|
1553
|
+
*
|
|
1554
|
+
* A join field the page holds encrypted (proposal 0045) is decrypted with
|
|
1555
|
+
* `options.encryptionKey` before it is matched. With no key, and a manifest
|
|
1556
|
+
* of this document's collections joining on that field, the run cannot match
|
|
1557
|
+
* and refuses. A ciphertext that does not decrypt matches nothing.
|
|
1558
|
+
*/
|
|
1559
|
+
declare function mergeExternalMetadata(label: string, extracted: ExtractedMetadata, index: ExternalMetadataIndex | null, memberOf: readonly string[], base: string, options?: {
|
|
1560
|
+
encryptionKey?: () => string | undefined;
|
|
1561
|
+
}): MergedMetadata;
|
|
1562
|
+
/** The `/key` pointer for an external-metadata finding, RFC 6901 escaped. */
|
|
1563
|
+
declare function externalMetadataPointer(key: string): string;
|
|
1564
|
+
/**
|
|
1565
|
+
* Path entries naming no loaded document.
|
|
1566
|
+
*
|
|
1567
|
+
* `loaded` are the run's file labels, relative to `base`. Checked only when
|
|
1568
|
+
* the run is the config corpus (the same invariant corpus checks use): a
|
|
1569
|
+
* positional path means the operator chose to look at part of the corpus,
|
|
1570
|
+
* and an entry for the rest is expected, not orphaned.
|
|
1571
|
+
*/
|
|
1572
|
+
declare function orphanEntries(index: ExternalMetadataIndex | null, loaded: readonly string[], base: string, collections?: readonly string[]): ExternalMetadataEntry[];
|
|
1573
|
+
/**
|
|
1574
|
+
* Field entries no loaded document matched (0039). `matched` is field -> the
|
|
1575
|
+
* values documents in the run carried, which the caller collects from each
|
|
1576
|
+
* document's `joins` — so this runs after the per-file loop, under the same
|
|
1577
|
+
* corpus invariant as `orphanEntries`.
|
|
1578
|
+
*/
|
|
1579
|
+
declare function orphanJoins(index: ExternalMetadataIndex | null, matched: ReadonlyMap<string, ReadonlySet<string>>, collections?: readonly string[]): ExternalMetadataEntry[];
|
|
1580
|
+
/** The operational error an orphan check raises, naming the first entry. */
|
|
1581
|
+
declare function orphanError(orphans: readonly ExternalMetadataEntry[]): DocmetaError;
|
|
1367
1582
|
|
|
1368
1583
|
interface BuiltinInfo {
|
|
1369
1584
|
id: string;
|
|
@@ -1477,21 +1692,400 @@ declare function fetchSchemaBytes(ref: string, options?: LoadSchemaOptions): Pro
|
|
|
1477
1692
|
declare function schemaLoadOptions(args: {
|
|
1478
1693
|
root: string;
|
|
1479
1694
|
/**
|
|
1480
|
-
* Where a relative local-file schema ref is measured from — the run's `cwd`,
|
|
1481
|
-
* not `root`. The two differ when a config was discovered in an ancestor, and
|
|
1482
|
-
* a `--schema ./x.json` typed on the command line belongs to the directory
|
|
1483
|
-
* the user was standing in, not to the config's.
|
|
1695
|
+
* Where a relative local-file schema ref is measured from — the run's `cwd`,
|
|
1696
|
+
* not `root`. The two differ when a config was discovered in an ancestor, and
|
|
1697
|
+
* a `--schema ./x.json` typed on the command line belongs to the directory
|
|
1698
|
+
* the user was standing in, not to the config's.
|
|
1699
|
+
*/
|
|
1700
|
+
fileBase?: string;
|
|
1701
|
+
/** Config `schemaCache.ttlHours`. */
|
|
1702
|
+
ttlHours?: number;
|
|
1703
|
+
/** `--offline`, else config `offline:`. */
|
|
1704
|
+
offline?: boolean;
|
|
1705
|
+
/** From `collectSchemaPins(config)`; omitted when the config pins nothing. */
|
|
1706
|
+
pins?: ReadonlyMap<string, SchemaPin>;
|
|
1707
|
+
}): LoadSchemaOptions;
|
|
1708
|
+
/** Load and return the JSON Schema object for a reference. */
|
|
1709
|
+
declare function loadSchema(ref: string, options?: LoadSchemaOptions): Promise<Record<string, unknown>>;
|
|
1710
|
+
|
|
1711
|
+
/**
|
|
1712
|
+
* `x-manni-location` (proposal 0047): where a schema would like a top-level
|
|
1713
|
+
* key's value stored, on the page or in external metadata.
|
|
1714
|
+
*
|
|
1715
|
+
* The keyword is registered on every Ajv meta builds (validator.ts), next to
|
|
1716
|
+
* `x-manni-encrypt`, and like it records where it was evaluated. Ajv's own
|
|
1717
|
+
* resolution is the walker, so a mark counts through `$ref`, `allOf` and a
|
|
1718
|
+
* referenced built-in, and inside the `anyOf`, `oneOf` and `if`/`then`
|
|
1719
|
+
* branches Ajv takes. Only top-level properties carry a preference; a nested
|
|
1720
|
+
* mark is accepted and ignored. `Validator.locationPreferences` is the one
|
|
1721
|
+
* question commands ask of it.
|
|
1722
|
+
*
|
|
1723
|
+
* One schema marking one key both ways is judged twice. Through `properties`,
|
|
1724
|
+
* `allOf` and local `$ref` alone, it is refused when the schema compiles.
|
|
1725
|
+
* Across conditional branches it is not an error: Ajv evaluates failing
|
|
1726
|
+
* branches too, so that schema gives the key no preference.
|
|
1727
|
+
*/
|
|
1728
|
+
/** The schema keyword. */
|
|
1729
|
+
declare const LOCATION_KEYWORD = "x-manni-location";
|
|
1730
|
+
/** Where a top-level key prefers to live. */
|
|
1731
|
+
type FieldLocation = "page" | "external";
|
|
1732
|
+
/** A key's preferred location, and the schema ref whose mark decided it. */
|
|
1733
|
+
interface LocationPreference {
|
|
1734
|
+
location: FieldLocation;
|
|
1735
|
+
/** The ref, as given to `locationPreferences`, whose mark won. */
|
|
1736
|
+
schema: string;
|
|
1737
|
+
}
|
|
1738
|
+
|
|
1739
|
+
declare class Validator {
|
|
1740
|
+
private readonly schemaOptions;
|
|
1741
|
+
/**
|
|
1742
|
+
* How this validator's schemas are loaded: the disk cache location, its TTL,
|
|
1743
|
+
* and `--offline`. Held per instance rather than read from module state, so
|
|
1744
|
+
* two differently-configured validations in one process each get their own
|
|
1745
|
+
* settings.
|
|
1746
|
+
*
|
|
1747
|
+
* That is not full isolation, and the difference matters to a library
|
|
1748
|
+
* caller: `schema-registry` keeps a process-wide memo of fetched schemas, so
|
|
1749
|
+
* one validator's successful fetch is visible to another. `offline` is
|
|
1750
|
+
* excluded from that sharing on purpose — an offline validator will not be
|
|
1751
|
+
* served something this process pulled over the network — but the memo is
|
|
1752
|
+
* still shared, so a URL fetched once is not re-fetched per instance.
|
|
1753
|
+
*/
|
|
1754
|
+
constructor(schemaOptions?: LoadSchemaOptions);
|
|
1755
|
+
private ajvByDialect;
|
|
1756
|
+
/**
|
|
1757
|
+
* Keyed on the in-flight *promise*, not the resolved validator. Caching the
|
|
1758
|
+
* result made this a check-then-act race: `fill` walks files through a worker
|
|
1759
|
+
* pool, so every worker missed the cache while the first `loadSchema` was
|
|
1760
|
+
* still pending and they all then compiled the same schema into the one
|
|
1761
|
+
* shared per-dialect Ajv. Ajv registers a schema's `$id` on the first compile
|
|
1762
|
+
* and rejects the second with "schema with key or id ... already exists",
|
|
1763
|
+
* which took down any multi-file run against an $id-bearing schema. Storing
|
|
1764
|
+
* the promise before the first await lets the losers await the one compile.
|
|
1765
|
+
*/
|
|
1766
|
+
private cache;
|
|
1767
|
+
private ajvFor;
|
|
1768
|
+
/**
|
|
1769
|
+
* Synchronous by design: the `cache.set` has to happen in the same tick as
|
|
1770
|
+
* the miss, or a second caller can slip in before the entry exists.
|
|
1771
|
+
*/
|
|
1772
|
+
private compile;
|
|
1773
|
+
private compileUncached;
|
|
1774
|
+
/**
|
|
1775
|
+
* The instance pointers of `data` that carry `x-manni-encrypt: true` under
|
|
1776
|
+
* any schema in `refs`, in the order the validator evaluated them.
|
|
1777
|
+
*
|
|
1778
|
+
* A first pass with the recording keyword, so a mark counts exactly where
|
|
1779
|
+
* validation would evaluate it. Only present values are marked: Ajv applies
|
|
1780
|
+
* a property's subschema to a property that exists. A branch Ajv does not
|
|
1781
|
+
* take (`then` behind a failing `if`, an `anyOf` branch after a passing
|
|
1782
|
+
* one) contributes nothing; a branch it takes contributes its marks
|
|
1783
|
+
* whether or not the branch passes, because a ciphertext routinely fails
|
|
1784
|
+
* the rest of its own subschema until it is decrypted.
|
|
1785
|
+
*/
|
|
1786
|
+
markedPointers(data: Record<string, unknown>, refs: string[]): Promise<Set<string>>;
|
|
1787
|
+
/**
|
|
1788
|
+
* The location each top-level key of `data` prefers under `refs`: `page` or
|
|
1789
|
+
* `external`, and the ref whose `x-manni-location` mark decided it. A key no
|
|
1790
|
+
* schema marks has no entry.
|
|
1791
|
+
*
|
|
1792
|
+
* A first pass with the recording keyword, as `markedPointers` runs, so a
|
|
1793
|
+
* mark counts exactly where validation would evaluate it, and a nested mark
|
|
1794
|
+
* is ignored. Only present values are marked: Ajv applies a property's
|
|
1795
|
+
* subschema to a property that exists. A caller asking where a key it is
|
|
1796
|
+
* about to write belongs passes `data` that already holds the candidate
|
|
1797
|
+
* value. `$schema` is stripped first, as validation does.
|
|
1798
|
+
*
|
|
1799
|
+
* Refs are evaluated in order and a later ref's mark wins. A ref that says
|
|
1800
|
+
* both values for one key unconditionally is refused when it compiles; one
|
|
1801
|
+
* whose evaluated branches say both gives that key no preference.
|
|
1802
|
+
*/
|
|
1803
|
+
locationPreferences(data: Record<string, unknown>, refs: string[]): Promise<Map<string, LocationPreference>>;
|
|
1804
|
+
/**
|
|
1805
|
+
* Validate `data` against every schema in `refs`. Returns all violations,
|
|
1806
|
+
* each tagged with the schema that produced it and a source line via
|
|
1807
|
+
* `lineFor`.
|
|
1808
|
+
*
|
|
1809
|
+
* `colFor` is optional and additive: this signature is public, so a fourth
|
|
1810
|
+
* *required* parameter — or a widened third one — would be a consumer break.
|
|
1811
|
+
* Callers with an extractor that supplies no column pass nothing and get the
|
|
1812
|
+
* previous behavior exactly.
|
|
1813
|
+
*/
|
|
1814
|
+
validate(data: Record<string, unknown>, refs: string[], lineFor: (pointer: string) => number | undefined, colFor?: (pointer: string) => number | undefined,
|
|
1815
|
+
/**
|
|
1816
|
+
* Where a merged value lives when it is not in the document (proposal
|
|
1817
|
+
* 0037): a manifest's file and line. Consulted before `lineFor`,
|
|
1818
|
+
* and additive in the way `colFor` was.
|
|
1819
|
+
*/
|
|
1820
|
+
locate?: (pointer: string) => SourceLocation | undefined): Promise<FieldError[]>;
|
|
1821
|
+
}
|
|
1822
|
+
|
|
1823
|
+
/** Why a value was moved: its schema's mark, or a manifest that already owns the key. */
|
|
1824
|
+
type RelocateMoveReason = "preferred" | "owned";
|
|
1825
|
+
/** Why a value stayed on the side it is on. */
|
|
1826
|
+
type RelocateStayReason = "no-home" | "read-only-format" | "no-join-value" | "values-differ" | "url-manifest" | "unreadable";
|
|
1827
|
+
/** One value that moved, or would under `dryRun`. */
|
|
1828
|
+
type RelocateMove = {
|
|
1829
|
+
key: string;
|
|
1830
|
+
to: "page";
|
|
1831
|
+
from: string;
|
|
1832
|
+
reason: RelocateMoveReason;
|
|
1833
|
+
} | {
|
|
1834
|
+
key: string;
|
|
1835
|
+
to: "manifest";
|
|
1836
|
+
manifest: string;
|
|
1837
|
+
/** 1-based line of the key in the manifest afterwards. Absent under `dryRun`. */
|
|
1838
|
+
line?: number;
|
|
1839
|
+
reason: RelocateMoveReason;
|
|
1840
|
+
};
|
|
1841
|
+
/** One value that stayed on the wrong side. */
|
|
1842
|
+
interface RelocateStay {
|
|
1843
|
+
key: string;
|
|
1844
|
+
reason: RelocateStayReason;
|
|
1845
|
+
/** The sentence the pretty reporter prints after `stays: `. Not part of the JSON shape. */
|
|
1846
|
+
detail?: string;
|
|
1847
|
+
}
|
|
1848
|
+
interface RelocateFileResult {
|
|
1849
|
+
/** The page, as the run labels it. */
|
|
1850
|
+
file: string;
|
|
1851
|
+
moved: RelocateMove[];
|
|
1852
|
+
stayed: RelocateStay[];
|
|
1853
|
+
/** A member page outside the paths the run named, reached through a `keys:` or `paths:` change. */
|
|
1854
|
+
beyond: boolean;
|
|
1855
|
+
}
|
|
1856
|
+
interface RelocateManifestResult {
|
|
1857
|
+
/** The manifest as the run reports it: relative to the run's base, or the URL. */
|
|
1858
|
+
file: string;
|
|
1859
|
+
collection: string;
|
|
1860
|
+
/** Its index in the collection's `externalMetadata:` before the run. */
|
|
1861
|
+
index: number;
|
|
1862
|
+
created: boolean;
|
|
1863
|
+
keysAdded: string[];
|
|
1864
|
+
keysRemoved: string[];
|
|
1865
|
+
/** The keys it owns afterwards. */
|
|
1866
|
+
keys: string[];
|
|
1867
|
+
/** Whether its last key went, so the config no longer declares it (R3). */
|
|
1868
|
+
undeclared: boolean;
|
|
1869
|
+
/** Pages beyond the named paths whose values a `keys:` change moves, or leaves. */
|
|
1870
|
+
beyond: number;
|
|
1871
|
+
}
|
|
1872
|
+
interface RelocateConfigResult {
|
|
1873
|
+
/** The config file relative to the working directory, or null when there is none and none was needed. */
|
|
1874
|
+
file: string | null;
|
|
1875
|
+
created: boolean;
|
|
1876
|
+
collectionsCreated: {
|
|
1877
|
+
name: string;
|
|
1878
|
+
paths: string[];
|
|
1879
|
+
}[];
|
|
1880
|
+
pathsAdded: {
|
|
1881
|
+
collection: string;
|
|
1882
|
+
path: string;
|
|
1883
|
+
}[];
|
|
1884
|
+
}
|
|
1885
|
+
interface RelocateSummary {
|
|
1886
|
+
/** Pages with a value moved or stayed. */
|
|
1887
|
+
files: number;
|
|
1888
|
+
moved: number;
|
|
1889
|
+
stayed: number;
|
|
1890
|
+
manifestsCreated: number;
|
|
1891
|
+
}
|
|
1892
|
+
interface RelocateResult {
|
|
1893
|
+
dryRun: boolean;
|
|
1894
|
+
config: RelocateConfigResult;
|
|
1895
|
+
/** Every manifest the run creates, changes the keys of, or moves a value into or out of. */
|
|
1896
|
+
manifests: RelocateManifestResult[];
|
|
1897
|
+
files: RelocateFileResult[];
|
|
1898
|
+
summary: RelocateSummary;
|
|
1899
|
+
}
|
|
1900
|
+
|
|
1901
|
+
interface QueryOptions {
|
|
1902
|
+
/**
|
|
1903
|
+
* One SQL statement. The table is `docs`; see the system columns below.
|
|
1904
|
+
* May be empty when `db` is set — export without querying.
|
|
1905
|
+
*/
|
|
1906
|
+
sql: string;
|
|
1907
|
+
/**
|
|
1908
|
+
* `--db`: also write the built database to this file, for any SQLite
|
|
1909
|
+
* front-end (sqlite3, Datasette, duckdb) to open afterwards. The file is a
|
|
1910
|
+
* regenerated artifact: an existing SQLite file at the path is overwritten,
|
|
1911
|
+
* anything else is refused.
|
|
1912
|
+
*/
|
|
1913
|
+
db?: string;
|
|
1914
|
+
inputs: string[];
|
|
1915
|
+
as?: string;
|
|
1916
|
+
exclude?: string[];
|
|
1917
|
+
exts?: string[];
|
|
1918
|
+
configPath?: string;
|
|
1919
|
+
/** `--no-config`: skip config discovery and use the built-in defaults. */
|
|
1920
|
+
noConfig?: boolean;
|
|
1921
|
+
/**
|
|
1922
|
+
* `--collection <name>`, repeatable: run over the named configured
|
|
1923
|
+
* collections instead of every declared one (proposal 0041). Cannot be
|
|
1924
|
+
* combined with positional paths; `-` is allowed beside it.
|
|
1925
|
+
*/
|
|
1926
|
+
collections?: string[];
|
|
1927
|
+
cwd?: string;
|
|
1928
|
+
/** Content for the `-` (stdin) input, injected by the CLI/tests. */
|
|
1929
|
+
stdinContent?: string;
|
|
1930
|
+
/** Permit an input set that resolves to zero files (see `assertNonEmpty`). */
|
|
1931
|
+
allowEmpty?: boolean;
|
|
1932
|
+
/**
|
|
1933
|
+
* `--no-gitignore` (false). Absent leaves config `respectGitignore:` in
|
|
1934
|
+
* charge, which itself defaults to on.
|
|
1935
|
+
*/
|
|
1936
|
+
respectGitignore?: boolean;
|
|
1937
|
+
/** Diagnostics for the user; the CLI writes these to stderr. */
|
|
1938
|
+
onNotice?: (message: string) => void;
|
|
1939
|
+
/** Called once when a config governs the run, so the CLI can report it. */
|
|
1940
|
+
onConfigLoaded?: (info: ConfigNotice) => void;
|
|
1941
|
+
/**
|
|
1942
|
+
* `--offline`, accepted for surface parity with the other commands. DDL
|
|
1943
|
+
* statements do resolve the corpus's schema set (0024), but only from disk
|
|
1944
|
+
* and the bundled built-ins — a URL ref refuses with "vendor it first"
|
|
1945
|
+
* before anything could fetch — so there is still no network dependency to
|
|
1946
|
+
* suppress.
|
|
1947
|
+
*/
|
|
1948
|
+
offline?: boolean;
|
|
1949
|
+
/**
|
|
1950
|
+
* `--no-cache` (false): ask GitHub or GitLab again rather than reading the
|
|
1951
|
+
* review cache. Only a statement naming the `derived` table consults it,
|
|
1952
|
+
* and only for `reviewed-by` and `last-reviewed`; absent leaves it on.
|
|
1953
|
+
*/
|
|
1954
|
+
cache?: boolean;
|
|
1955
|
+
/**
|
|
1956
|
+
* `--dry-run`: preview the statement's per-file changes — the diff it
|
|
1957
|
+
* would make, files untouched. Without it a mutating statement applies,
|
|
1958
|
+
* matching `fill`'s convention (proposal 0025; 0022 recorded the original
|
|
1959
|
+
* preview-by-default surface this revises).
|
|
1960
|
+
*/
|
|
1961
|
+
dryRun?: boolean;
|
|
1962
|
+
/**
|
|
1963
|
+
* Values for the statement's named parameters (`$name`, `:name`, `@name`),
|
|
1964
|
+
* keyed by bare name (a `$`/`:`/`@` prefix on a key is tolerated). Each
|
|
1965
|
+
* value passes through the same `bindValue` the projection loader uses —
|
|
1966
|
+
* booleans become 1/0, arrays and objects JSON text — so a bound parameter
|
|
1967
|
+
* compares against a stored cell under exactly the encoding the cell got
|
|
1968
|
+
* (proposal 0029). A parameter the SQL references with no entry here
|
|
1969
|
+
* refuses: unbound would silently bind NULL and match nothing.
|
|
1970
|
+
*/
|
|
1971
|
+
params?: Record<string, unknown>;
|
|
1972
|
+
/**
|
|
1973
|
+
* `-s/--schema`, repeatable: the schema set the run's DDL evolves — CLI
|
|
1974
|
+
* precedence for the DDL planner *only* (proposal 0030). The per-file
|
|
1975
|
+
* resolution walk is skipped and the deduped refs are the set; every guard
|
|
1976
|
+
* inside the set (single local file for ADD, sole declarer for
|
|
1977
|
+
* DROP/RENAME, builtin fork, URL refusal, the trust boundary) runs
|
|
1978
|
+
* unchanged. Collection views keep following the config's resolution. A
|
|
1979
|
+
* run whose statement produces no DDL effect refuses before anything is
|
|
1980
|
+
* applied — a flag that would silently mean nothing must refuse.
|
|
1981
|
+
*/
|
|
1982
|
+
schemas?: string[];
|
|
1983
|
+
/**
|
|
1984
|
+
* How to ask for a new encryption key when an `UPDATE` or `INSERT` writes
|
|
1985
|
+
* a column its schema marks `x-manni-encrypt` and no key is available
|
|
1986
|
+
* (proposal 0045). The CLI passes `terminalConfirm()`, which is
|
|
1987
|
+
* `undefined` off a terminal; absent, such a write refuses (exit 2). A dry
|
|
1988
|
+
* run never asks: it writes nothing.
|
|
1989
|
+
*/
|
|
1990
|
+
confirm?: Confirm;
|
|
1991
|
+
/**
|
|
1992
|
+
* Called with relocate's result when a write's P1 offer was accepted and
|
|
1993
|
+
* the values moved (proposal 0047), so the CLI can print relocate's report.
|
|
1994
|
+
*/
|
|
1995
|
+
onRelocated?: (result: RelocateResult) => void;
|
|
1996
|
+
/**
|
|
1997
|
+
* The environment `MANNI_ENCRYPTION_KEY` is read from. Defaults to
|
|
1998
|
+
* `process.env`; tests pass their own.
|
|
1999
|
+
*/
|
|
2000
|
+
env?: NodeJS.ProcessEnv;
|
|
2001
|
+
/** The clock an uncommitted body change is dated by. Test seam; default `new Date()`. */
|
|
2002
|
+
now?: () => Date;
|
|
2003
|
+
}
|
|
2004
|
+
/**
|
|
2005
|
+
* One thing a statement changed, in file-space terms. Cell-level kinds carry
|
|
2006
|
+
* a `key` (a set, a deletion via `SET k = NULL` / `ALTER DROP COLUMN`, or a
|
|
2007
|
+
* key rename); file-level kinds carry the whole event (`cleared` — the block
|
|
2008
|
+
* stripped by DELETE; `created` — a file INSERT made; `renamed` — a `_path`
|
|
2009
|
+
* move). Exactly one kind per object.
|
|
2010
|
+
*
|
|
2011
|
+
* `manifest` (proposal 0047) names the external-metadata manifest the change
|
|
2012
|
+
* lands in, as the run reports it, when it lands in one: an owned key's set,
|
|
2013
|
+
* removal or rename, a created file's owned keys, a stripped document's
|
|
2014
|
+
* entry, or a moved document's entry.
|
|
2015
|
+
*/
|
|
2016
|
+
type QueryChange = {
|
|
2017
|
+
file: string;
|
|
2018
|
+
written: boolean;
|
|
2019
|
+
manifest?: string;
|
|
2020
|
+
} & ({
|
|
2021
|
+
key: string;
|
|
2022
|
+
from: unknown;
|
|
2023
|
+
to: unknown;
|
|
2024
|
+
} | {
|
|
2025
|
+
key: string;
|
|
2026
|
+
from: unknown;
|
|
2027
|
+
deleted: true;
|
|
2028
|
+
} | {
|
|
2029
|
+
key: string;
|
|
2030
|
+
renamedFrom: string;
|
|
2031
|
+
to: unknown;
|
|
2032
|
+
} | {
|
|
2033
|
+
cleared: true;
|
|
2034
|
+
from: Record<string, unknown>;
|
|
2035
|
+
} | {
|
|
2036
|
+
created: true;
|
|
2037
|
+
to: Record<string, unknown>;
|
|
2038
|
+
} | {
|
|
2039
|
+
renamed: string;
|
|
2040
|
+
} | {
|
|
2041
|
+
/** A DDL statement edited the schema itself (0024): `file` is the
|
|
2042
|
+
* schema written — an in-place edit, or the fork of a builtin. */
|
|
2043
|
+
schema: true;
|
|
2044
|
+
op: "add" | "drop" | "rename";
|
|
2045
|
+
key: string;
|
|
2046
|
+
renamedTo?: string;
|
|
2047
|
+
type?: string;
|
|
2048
|
+
/** 0028: a declared type equal to a format name carries the format. */
|
|
2049
|
+
format?: string;
|
|
2050
|
+
/** 0028: a `CHECK (k IN (…))` on the added column carries the enum. */
|
|
2051
|
+
enum?: (string | number)[];
|
|
2052
|
+
required?: boolean;
|
|
2053
|
+
forkedFrom?: string;
|
|
2054
|
+
} | {
|
|
2055
|
+
/** A DDL side effect on the governing config file: a fork repoints the
|
|
2056
|
+
* `schemas:` entry (`key: "schemas"`), an in-place edit of a pinned
|
|
2057
|
+
* schema refreshes its pin (`key: "integrity"`). Disclosed as a change
|
|
2058
|
+
* because the preview must name every file `--write` will touch. */
|
|
2059
|
+
config: true;
|
|
2060
|
+
key: string;
|
|
2061
|
+
from: unknown;
|
|
2062
|
+
to: unknown;
|
|
2063
|
+
});
|
|
2064
|
+
interface QueryRun {
|
|
2065
|
+
/** Result column names, in SELECT order — present even for zero rows. */
|
|
2066
|
+
columns: string[];
|
|
2067
|
+
rows: Record<string, unknown>[];
|
|
2068
|
+
/** Set when `db` was written: where, and how big the table is. */
|
|
2069
|
+
db?: {
|
|
2070
|
+
path: string;
|
|
2071
|
+
files: number;
|
|
2072
|
+
columns: number;
|
|
2073
|
+
};
|
|
2074
|
+
/**
|
|
2075
|
+
* Present when the statement was a metadata edit: every cell it changed
|
|
2076
|
+
* (empty when a mutating statement matched nothing). Absent on reads.
|
|
1484
2077
|
*/
|
|
1485
|
-
|
|
1486
|
-
/**
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
2078
|
+
changes?: QueryChange[];
|
|
2079
|
+
/**
|
|
2080
|
+
* Where the run stood, in the same shape `ValidateRun.frame` carries — the
|
|
2081
|
+
* path-normalization frame SARIF and JUnit need before they can name a file
|
|
2082
|
+
* the way the repository does (proposal 0026). Constructed from the run's
|
|
2083
|
+
* `cwd`, its config directory, and the directory file labels resolve
|
|
2084
|
+
* against; absent only when a caller built a `QueryRun` by hand.
|
|
2085
|
+
*/
|
|
2086
|
+
frame?: FingerprintContext;
|
|
2087
|
+
}
|
|
2088
|
+
declare function runQuery(opts: QueryOptions): Promise<QueryRun>;
|
|
1495
2089
|
|
|
1496
2090
|
interface SchemasInfo {
|
|
1497
2091
|
builtins: BuiltinInfo[];
|
|
@@ -1598,7 +2192,55 @@ interface FilledField {
|
|
|
1598
2192
|
* `x-manni-encrypt`. Absent otherwise.
|
|
1599
2193
|
*/
|
|
1600
2194
|
encrypted?: boolean;
|
|
2195
|
+
/**
|
|
2196
|
+
* Proposal 0047: the manifest the value was written into, as the run
|
|
2197
|
+
* reports it, when a manifest of the page's collections owns the key.
|
|
2198
|
+
* Absent when the value went to the page.
|
|
2199
|
+
*/
|
|
2200
|
+
destination?: string;
|
|
2201
|
+
}
|
|
2202
|
+
/**
|
|
2203
|
+
* One `meta-provenance` entry as `fill` writes it (proposal 0046): the model,
|
|
2204
|
+
* the JSON Pointers of the fields it proposed, escaped per RFC 6901, and the
|
|
2205
|
+
* confidence each was written at. Keys are the page's own spelling, so the
|
|
2206
|
+
* JSON report shows exactly what landed in the document. An entry `fill`
|
|
2207
|
+
* merged into keeps whatever else it held.
|
|
2208
|
+
*/
|
|
2209
|
+
interface MetaProvenanceEntry {
|
|
2210
|
+
"generated-by": string;
|
|
2211
|
+
fields: string[];
|
|
2212
|
+
confidence: Record<string, number>;
|
|
2213
|
+
[other: string]: unknown;
|
|
2214
|
+
}
|
|
2215
|
+
/**
|
|
2216
|
+
* What became of this file's `meta-provenance` entry. It is never a failure:
|
|
2217
|
+
* neither outcome changes the summary or the exit code.
|
|
2218
|
+
*/
|
|
2219
|
+
type MetaProvenanceReport = {
|
|
2220
|
+
written: true;
|
|
2221
|
+
entry: MetaProvenanceEntry;
|
|
2222
|
+
/** The manifest the entry was written into, when one owns `meta-provenance` (0047). */
|
|
2223
|
+
destination?: string;
|
|
2224
|
+
}
|
|
2225
|
+
/** The page's schemas, checked with the entry in place, reject it. */
|
|
2226
|
+
| {
|
|
2227
|
+
written: false;
|
|
2228
|
+
skipReason: "schema-mismatch";
|
|
2229
|
+
}
|
|
2230
|
+
/** A URL manifest in one of the page's collections owns the key, and cannot be written (0047). */
|
|
2231
|
+
| {
|
|
2232
|
+
written: false;
|
|
2233
|
+
skipReason: "manifest-owned";
|
|
2234
|
+
manifest: string;
|
|
1601
2235
|
}
|
|
2236
|
+
/**
|
|
2237
|
+
* The format's writer cannot hold a list of entries (an HTML or XML
|
|
2238
|
+
* attribute holds one line), so the fields were written without it.
|
|
2239
|
+
*/
|
|
2240
|
+
| {
|
|
2241
|
+
written: false;
|
|
2242
|
+
skipReason: "unwritable";
|
|
2243
|
+
};
|
|
1602
2244
|
interface FillFileResult {
|
|
1603
2245
|
file: string;
|
|
1604
2246
|
format: string;
|
|
@@ -1610,6 +2252,12 @@ interface FillFileResult {
|
|
|
1610
2252
|
error?: string;
|
|
1611
2253
|
/** The filled document. Populated only when the caller asks for it. */
|
|
1612
2254
|
content?: string;
|
|
2255
|
+
/**
|
|
2256
|
+
* The `meta-provenance` entry recording the fields this run wrote
|
|
2257
|
+
* (proposal 0046). Absent when no field was written; reported, not written,
|
|
2258
|
+
* under `--dry-run`.
|
|
2259
|
+
*/
|
|
2260
|
+
metaProvenance?: MetaProvenanceReport;
|
|
1613
2261
|
}
|
|
1614
2262
|
interface FillSummary {
|
|
1615
2263
|
files: number;
|
|
@@ -1707,6 +2355,11 @@ interface FillOptions {
|
|
|
1707
2355
|
* `process.env`; tests pass their own.
|
|
1708
2356
|
*/
|
|
1709
2357
|
env?: NodeJS.ProcessEnv;
|
|
2358
|
+
/**
|
|
2359
|
+
* Called with relocate's result after the user accepts a P1 offer
|
|
2360
|
+
* (proposal 0047), so the CLI can print what moved before the report.
|
|
2361
|
+
*/
|
|
2362
|
+
onRelocated?: (result: RelocateResult) => void;
|
|
1710
2363
|
}
|
|
1711
2364
|
|
|
1712
2365
|
declare function runFill(opts: FillOptions): Promise<FillRun>;
|
|
@@ -1744,337 +2397,133 @@ interface DeriveOptions {
|
|
|
1744
2397
|
* charge, which itself defaults to on.
|
|
1745
2398
|
*/
|
|
1746
2399
|
respectGitignore?: boolean;
|
|
1747
|
-
/** Diagnostics for the user; the CLI writes these to stderr. */
|
|
1748
|
-
onNotice?: (message: string) => void;
|
|
1749
|
-
/** Called once when a config governs the run, so the CLI can report it. */
|
|
1750
|
-
onConfigLoaded?: (info: ConfigNotice) => void;
|
|
1751
|
-
/** The clock an uncommitted body change is dated by. Test seam; default `new Date()`. */
|
|
1752
|
-
now?: () => Date;
|
|
1753
|
-
/** The review client, for every repository in the run. Test seam; default `gh` / `glab`. */
|
|
1754
|
-
reviews?: ReviewClient;
|
|
1755
|
-
/**
|
|
1756
|
-
* How to ask for a new encryption key when a field its schema marks
|
|
1757
|
-
* `x-manni-encrypt` is about to be stamped and no key is available
|
|
1758
|
-
* (proposal 0045). The CLI passes `terminalConfirm()`, which is `undefined`
|
|
1759
|
-
* off a terminal; absent, such a stamp refuses (exit 2). A dry run never
|
|
1760
|
-
* asks: it writes nothing.
|
|
1761
|
-
*/
|
|
1762
|
-
confirm?: Confirm;
|
|
1763
|
-
/**
|
|
1764
|
-
* The environment `MANNI_ENCRYPTION_KEY` is read from. Defaults to
|
|
1765
|
-
* `process.env`; tests pass their own.
|
|
1766
|
-
*/
|
|
1767
|
-
env?: NodeJS.ProcessEnv;
|
|
1768
|
-
}
|
|
1769
|
-
interface DeriveFileResult {
|
|
1770
|
-
file: string;
|
|
1771
|
-
/** Extractor/format used; `unknown` when none matched the file. */
|
|
1772
|
-
format: string;
|
|
1773
|
-
/** One entry per requested field, in the requested order. Empty on `error`. */
|
|
1774
|
-
fields: DerivedField[];
|
|
1775
|
-
/**
|
|
1776
|
-
* Whether writing the stale and unset fields changed the document, or
|
|
1777
|
-
* would have but for `dryRun`. Computed from the writer's output, so a
|
|
1778
|
-
* patch the format serializes to the same bytes is not a change.
|
|
1779
|
-
*/
|
|
1780
|
-
changed: boolean;
|
|
1781
|
-
/** Why the file could not be derived or written; the run goes on without it. */
|
|
1782
|
-
error?: string;
|
|
1783
|
-
/**
|
|
1784
|
-
* Under `check`, the findings for this file: one per stale or unset field,
|
|
1785
|
-
* at the field's line, plus one for an `error`. Absent otherwise.
|
|
1786
|
-
*/
|
|
1787
|
-
findings?: FieldError[];
|
|
1788
|
-
}
|
|
1789
|
-
interface DeriveSummary {
|
|
1790
|
-
files: number;
|
|
1791
|
-
/** Files whose document changed, or would have under `dryRun`. */
|
|
1792
|
-
changed: number;
|
|
1793
|
-
/** Fields whose write reached the disk: always 0 under `dryRun` and `check`. */
|
|
1794
|
-
written: number;
|
|
1795
|
-
stale: number;
|
|
1796
|
-
unset: number;
|
|
1797
|
-
unknown: number;
|
|
1798
|
-
errors: number;
|
|
1799
|
-
}
|
|
1800
|
-
interface DeriveRun {
|
|
1801
|
-
results: DeriveFileResult[];
|
|
1802
|
-
summary: DeriveSummary;
|
|
1803
|
-
dryRun: boolean;
|
|
1804
|
-
check: boolean;
|
|
1805
|
-
/** One status per source the run consulted; a source nobody asked for is absent. */
|
|
1806
|
-
sources: Partial<Record<DeriveSource, SourceStatus$1>>;
|
|
1807
|
-
/** Where the run stood, for the SARIF reporter under `check`. See `ValidateRun.frame`. */
|
|
1808
|
-
frame: FingerprintContext;
|
|
1809
|
-
}
|
|
1810
|
-
declare function runDerive(opts: DeriveOptions): Promise<DeriveRun>;
|
|
1811
|
-
|
|
1812
|
-
/**
|
|
1813
|
-
* The `schema` ref a collision finding carries, and so its baseline and rule
|
|
1814
|
-
* identity: `external:owned/external`. Shaped like `check:<name>` so
|
|
1815
|
-
* `classifyRef` passes it through as a built-in id rather than resolving it
|
|
1816
|
-
* as a cwd-relative file path, and reserved in the registry for the same
|
|
1817
|
-
* reason `check` is.
|
|
1818
|
-
*/
|
|
1819
|
-
declare const EXTERNAL_OWNED_SCHEMA = "external:owned";
|
|
1820
|
-
/**
|
|
1821
|
-
* The `schema` ref of a duplicate-join finding (0039): two documents carry
|
|
1822
|
-
* the same value of a join field, so one manifest entry matched both.
|
|
1823
|
-
*/
|
|
1824
|
-
declare const EXTERNAL_DUPLICATE_SCHEMA = "external:duplicate";
|
|
1825
|
-
/**
|
|
1826
|
-
* The `keyword` every external-metadata finding carries: no Ajv keyword
|
|
1827
|
-
* produced it.
|
|
1828
|
-
*/
|
|
1829
|
-
declare const EXTERNAL_KEYWORD = "external";
|
|
1830
|
-
/** The join that names documents by path, and the default. */
|
|
1831
|
-
declare const PATH_JOIN = "path";
|
|
1832
|
-
/** One value a manifest supplied, and where it was written. */
|
|
1833
|
-
interface ExternalMetadataValue {
|
|
1834
|
-
value: unknown;
|
|
1835
|
-
/** The collection whose manifest supplied it (proposal 0041). */
|
|
1836
|
-
collection: string;
|
|
1837
|
-
/** Manifest path as the run reports it: relative to the run's base, posix — or the URL. */
|
|
1838
|
-
file: string;
|
|
1839
|
-
/** 1-based line of the key in the manifest, when known. */
|
|
1840
|
-
line?: number;
|
|
1841
|
-
/**
|
|
1842
|
-
* 1-based manifest line of every node inside `value`, keyed by the JSON
|
|
1843
|
-
* Pointer relative to `value` (`/2/source/file`). A mapping member sits on
|
|
1844
|
-
* its key's line, and a list item on the line its node starts. Present only
|
|
1845
|
-
* when `value` is a mapping or a list with members; `line` answers for the
|
|
1846
|
-
* value itself.
|
|
1847
|
-
*/
|
|
1848
|
-
lines?: ReadonlyMap<string, number>;
|
|
1849
|
-
}
|
|
1850
|
-
/** One manifest entry, for the orphan checks. */
|
|
1851
|
-
interface ExternalMetadataEntry {
|
|
1852
|
-
/** The collection whose manifest declared it (proposal 0041). */
|
|
1853
|
-
collection: string;
|
|
1854
|
-
/** `path`, or the frontmatter field this entry is keyed by. */
|
|
1855
|
-
join: string;
|
|
1856
|
-
/** Absolute document path, for a path entry. */
|
|
1857
|
-
abs?: string;
|
|
1858
|
-
/** The key exactly as written in the manifest. */
|
|
1859
|
-
spelled: string;
|
|
1860
|
-
/** Manifest path as the run reports it. */
|
|
1861
|
-
file: string;
|
|
1862
|
-
/** 1-based line of the entry in the manifest, when known. */
|
|
1863
|
-
line?: number;
|
|
1864
|
-
}
|
|
1865
|
-
/** Every manifest of a run, loaded once and consulted per document. */
|
|
1866
|
-
interface ExternalMetadataIndex {
|
|
1867
|
-
/**
|
|
1868
|
-
* Owned key -> every collection that owns it, with the manifest that does.
|
|
1869
|
-
*
|
|
1870
|
-
* A list rather than one entry, because two collections may legitimately
|
|
1871
|
-
* each own the same key (0041 rule 5): `guides` and `blog` can both supply
|
|
1872
|
-
* `owner`. Ambiguity only exists for a file that is a member of both, which
|
|
1873
|
-
* is decided per file in `mergeExternalMetadata`.
|
|
1874
|
-
*/
|
|
1875
|
-
owners: ReadonlyMap<string, readonly {
|
|
1876
|
-
collection: string;
|
|
1877
|
-
file: string;
|
|
1878
|
-
}[]>;
|
|
1879
|
-
/** Path-joined manifests: absolute document path -> owned key -> value. */
|
|
1880
|
-
byPath: ReadonlyMap<string, ReadonlyMap<string, ExternalMetadataValue>>;
|
|
1881
|
-
/** Field-joined manifests: field -> value -> owned key -> value. */
|
|
1882
|
-
byField: ReadonlyMap<string, ReadonlyMap<string, ReadonlyMap<string, ExternalMetadataValue>>>;
|
|
1883
|
-
/** Every manifest entry, in manifest order. */
|
|
1884
|
-
entries: readonly ExternalMetadataEntry[];
|
|
1885
|
-
}
|
|
1886
|
-
interface LoadExternalMetadataOptions {
|
|
1887
|
-
/** Directory `externalMetadata[].file` and every manifest key resolve from. */
|
|
1888
|
-
configDir: string;
|
|
1889
|
-
/** Directory the run's file labels are relative to; manifests are reported the same way. */
|
|
1890
|
-
base: string;
|
|
1891
|
-
/** `--offline` / `offline:`: a URL manifest is refused rather than fetched (0038). */
|
|
1892
|
-
offline?: boolean;
|
|
1893
|
-
/** Network timeout for a URL manifest; the schema fetch's default otherwise. */
|
|
1894
|
-
timeoutMs?: number;
|
|
1895
|
-
/** For tests: the environment `tokenEnv` is read from. */
|
|
1896
|
-
env?: Record<string, string | undefined>;
|
|
1897
|
-
}
|
|
1898
|
-
/** A place a merged value lives, for a finding that must name it. */
|
|
1899
|
-
interface SourceLocation {
|
|
1900
|
-
file: string;
|
|
1901
|
-
line?: number;
|
|
1902
|
-
col?: number;
|
|
1903
|
-
}
|
|
1904
|
-
/** A key the document carries that a manifest owns. */
|
|
1905
|
-
interface ExternalMetadataCollision {
|
|
1906
|
-
key: string;
|
|
1907
|
-
/** The owning manifest, as the run reports it. */
|
|
1908
|
-
file: string;
|
|
1909
|
-
/** The collection that manifest belongs to (proposal 0041). */
|
|
1910
|
-
collection: string;
|
|
1911
|
-
}
|
|
1912
|
-
/** A field-joined entry a document matched (0039). */
|
|
1913
|
-
interface ExternalMetadataJoin {
|
|
1914
|
-
field: string;
|
|
1915
|
-
/** The value matched: the field's plaintext, decrypted first when the page holds it encrypted. */
|
|
1916
|
-
value: string;
|
|
1917
|
-
/**
|
|
1918
|
-
* The field as the page holds it, when that differs from `value`: the
|
|
1919
|
-
* ciphertext of an encrypted join field (proposal 0045). A finding about
|
|
1920
|
-
* the join names this, never the plaintext.
|
|
1921
|
-
*/
|
|
1922
|
-
pageValue?: string;
|
|
1923
|
-
/** The manifest, as the run reports it. */
|
|
1924
|
-
file: string;
|
|
1925
|
-
/** The collection that manifest belongs to (proposal 0041). */
|
|
1926
|
-
collection: string;
|
|
1927
|
-
}
|
|
1928
|
-
/** What `mergeExternalMetadata` hands back. */
|
|
1929
|
-
interface MergedMetadata {
|
|
1930
|
-
/** The document's metadata with every owned key the manifest supplied. */
|
|
1931
|
-
extracted: ExtractedMetadata;
|
|
1932
|
-
/**
|
|
1933
|
-
* Owned keys the document itself also carried, in document order, each
|
|
1934
|
-
* with the manifest that owns it — so the finding names it without a
|
|
1935
|
-
* second lookup, and without a fallback for an index that is not there.
|
|
1936
|
-
*/
|
|
1937
|
-
collisions: ExternalMetadataCollision[];
|
|
1938
|
-
/** Field-joined entries this document matched, one per manifest at most. */
|
|
1939
|
-
joins: ExternalMetadataJoin[];
|
|
2400
|
+
/** Diagnostics for the user; the CLI writes these to stderr. */
|
|
2401
|
+
onNotice?: (message: string) => void;
|
|
2402
|
+
/** Called once when a config governs the run, so the CLI can report it. */
|
|
2403
|
+
onConfigLoaded?: (info: ConfigNotice) => void;
|
|
2404
|
+
/** The clock an uncommitted body change is dated by. Test seam; default `new Date()`. */
|
|
2405
|
+
now?: () => Date;
|
|
2406
|
+
/** The review client, for every repository in the run. Test seam; default `gh` / `glab`. */
|
|
2407
|
+
reviews?: ReviewClient;
|
|
1940
2408
|
/**
|
|
1941
|
-
*
|
|
1942
|
-
*
|
|
1943
|
-
*
|
|
1944
|
-
*
|
|
1945
|
-
*
|
|
1946
|
-
* The line is the deepest manifest node the pointer reaches, so
|
|
1947
|
-
* `/citations/2` is the third item's line and `/citations/2/source/file`
|
|
1948
|
-
* that member's. A pointer past what the manifest holds falls back to the
|
|
1949
|
-
* nearest ancestor that exists, and at worst to the owned key's line.
|
|
2409
|
+
* How to ask for a new encryption key when a field its schema marks
|
|
2410
|
+
* `x-manni-encrypt` is about to be stamped and no key is available
|
|
2411
|
+
* (proposal 0045). The CLI passes `terminalConfirm()`, which is `undefined`
|
|
2412
|
+
* off a terminal; absent, such a stamp refuses (exit 2). A dry run never
|
|
2413
|
+
* asks: it writes nothing.
|
|
1950
2414
|
*/
|
|
1951
|
-
|
|
1952
|
-
}
|
|
1953
|
-
/** The join an external-metadata config asks for: `path` unless it names a field. */
|
|
1954
|
-
declare function externalMetadataJoin(manifest: Pick<ExternalMetadataConfig, "join">): string;
|
|
1955
|
-
/**
|
|
1956
|
-
* Load every manifest of every collection the run covers. Resolves to `null`
|
|
1957
|
-
* when none of them declares one, which is every setup that existed before
|
|
1958
|
-
* this feature.
|
|
1959
|
-
*
|
|
1960
|
-
* Every refusal is a `DocmetaError`: the manifest is a config-supplied input,
|
|
1961
|
-
* and one that is missing or misshapen is the run's problem, not a
|
|
1962
|
-
* document's (0014).
|
|
1963
|
-
*/
|
|
1964
|
-
declare function loadExternalMetadata(collections: readonly CollectionConfig[], opts: LoadExternalMetadataOptions): Promise<ExternalMetadataIndex | null>;
|
|
1965
|
-
/**
|
|
1966
|
-
* Merge the external metadata for one document into its extracted metadata.
|
|
1967
|
-
*
|
|
1968
|
-
* `label` is the document as the run spells it, relative to `base`; a path
|
|
1969
|
-
* entry matches on the resolved absolute path, never on the spelling, so a
|
|
1970
|
-
* positional run from a subdirectory finds the same entry a config-corpus
|
|
1971
|
-
* run does. A field entry matches on the document's own value of the join
|
|
1972
|
-
* field, wherever the document lives. Stdin never matches a path entry:
|
|
1973
|
-
* there is no file behind it.
|
|
1974
|
-
*
|
|
1975
|
-
* `memberOf` names the collections this document belongs to, and only their
|
|
1976
|
-
* manifests are consulted (0041 rule 4). It is the caller's `memberOf(...)`
|
|
1977
|
-
* result, computed once per file.
|
|
1978
|
-
*
|
|
1979
|
-
* `present`, `format` and the document's own positions are untouched. A
|
|
1980
|
-
* manifest key is not in the document, so `lineFor` keeps answering
|
|
1981
|
-
* `undefined` for it, and `locate` answers instead.
|
|
1982
|
-
*
|
|
1983
|
-
* A join field the page holds encrypted (proposal 0045) is decrypted with
|
|
1984
|
-
* `options.encryptionKey` before it is matched. With no key, and a manifest
|
|
1985
|
-
* of this document's collections joining on that field, the run cannot match
|
|
1986
|
-
* and refuses. A ciphertext that does not decrypt matches nothing.
|
|
1987
|
-
*/
|
|
1988
|
-
declare function mergeExternalMetadata(label: string, extracted: ExtractedMetadata, index: ExternalMetadataIndex | null, memberOf: readonly string[], base: string, options?: {
|
|
1989
|
-
encryptionKey?: () => string | undefined;
|
|
1990
|
-
}): MergedMetadata;
|
|
1991
|
-
/** The `/key` pointer for an external-metadata finding, RFC 6901 escaped. */
|
|
1992
|
-
declare function externalMetadataPointer(key: string): string;
|
|
1993
|
-
/**
|
|
1994
|
-
* Path entries naming no loaded document.
|
|
1995
|
-
*
|
|
1996
|
-
* `loaded` are the run's file labels, relative to `base`. Checked only when
|
|
1997
|
-
* the run is the config corpus (the same invariant corpus checks use): a
|
|
1998
|
-
* positional path means the operator chose to look at part of the corpus,
|
|
1999
|
-
* and an entry for the rest is expected, not orphaned.
|
|
2000
|
-
*/
|
|
2001
|
-
declare function orphanEntries(index: ExternalMetadataIndex | null, loaded: readonly string[], base: string, collections?: readonly string[]): ExternalMetadataEntry[];
|
|
2002
|
-
/**
|
|
2003
|
-
* Field entries no loaded document matched (0039). `matched` is field -> the
|
|
2004
|
-
* values documents in the run carried, which the caller collects from each
|
|
2005
|
-
* document's `joins` — so this runs after the per-file loop, under the same
|
|
2006
|
-
* corpus invariant as `orphanEntries`.
|
|
2007
|
-
*/
|
|
2008
|
-
declare function orphanJoins(index: ExternalMetadataIndex | null, matched: ReadonlyMap<string, ReadonlySet<string>>, collections?: readonly string[]): ExternalMetadataEntry[];
|
|
2009
|
-
/** The operational error an orphan check raises, naming the first entry. */
|
|
2010
|
-
declare function orphanError(orphans: readonly ExternalMetadataEntry[]): DocmetaError;
|
|
2011
|
-
|
|
2012
|
-
declare class Validator {
|
|
2013
|
-
private readonly schemaOptions;
|
|
2415
|
+
confirm?: Confirm;
|
|
2014
2416
|
/**
|
|
2015
|
-
*
|
|
2016
|
-
*
|
|
2017
|
-
* two differently-configured validations in one process each get their own
|
|
2018
|
-
* settings.
|
|
2019
|
-
*
|
|
2020
|
-
* That is not full isolation, and the difference matters to a library
|
|
2021
|
-
* caller: `schema-registry` keeps a process-wide memo of fetched schemas, so
|
|
2022
|
-
* one validator's successful fetch is visible to another. `offline` is
|
|
2023
|
-
* excluded from that sharing on purpose — an offline validator will not be
|
|
2024
|
-
* served something this process pulled over the network — but the memo is
|
|
2025
|
-
* still shared, so a URL fetched once is not re-fetched per instance.
|
|
2417
|
+
* The environment `MANNI_ENCRYPTION_KEY` is read from. Defaults to
|
|
2418
|
+
* `process.env`; tests pass their own.
|
|
2026
2419
|
*/
|
|
2027
|
-
|
|
2028
|
-
private ajvByDialect;
|
|
2420
|
+
env?: NodeJS.ProcessEnv;
|
|
2029
2421
|
/**
|
|
2030
|
-
*
|
|
2031
|
-
*
|
|
2032
|
-
*
|
|
2033
|
-
* still pending and they all then compiled the same schema into the one
|
|
2034
|
-
* shared per-dialect Ajv. Ajv registers a schema's `$id` on the first compile
|
|
2035
|
-
* and rejects the second with "schema with key or id ... already exists",
|
|
2036
|
-
* which took down any multi-file run against an $id-bearing schema. Storing
|
|
2037
|
-
* the promise before the first await lets the losers await the one compile.
|
|
2422
|
+
* `--generated-by <name>` (proposal 0046): the machine uncommitted body
|
|
2423
|
+
* lines go to, or the lines a `<path>:L1-L2` positional names. Absent reads
|
|
2424
|
+
* `MANNI_GENERATED_BY` from `env`; an empty value is unset either way.
|
|
2038
2425
|
*/
|
|
2039
|
-
|
|
2040
|
-
private ajvFor;
|
|
2426
|
+
generatedBy?: string;
|
|
2041
2427
|
/**
|
|
2042
|
-
*
|
|
2043
|
-
*
|
|
2428
|
+
* Called with relocate's result after the user accepts a P1 offer
|
|
2429
|
+
* (proposal 0047), so the CLI can print what moved before the report.
|
|
2044
2430
|
*/
|
|
2045
|
-
|
|
2046
|
-
|
|
2431
|
+
onRelocated?: (result: RelocateResult) => void;
|
|
2432
|
+
}
|
|
2433
|
+
interface DeriveFileResult {
|
|
2434
|
+
file: string;
|
|
2435
|
+
/** Extractor/format used; `unknown` when none matched the file. */
|
|
2436
|
+
format: string;
|
|
2437
|
+
/** One entry per requested field, in the requested order. Empty on `error`. */
|
|
2438
|
+
fields: DerivedField[];
|
|
2047
2439
|
/**
|
|
2048
|
-
*
|
|
2049
|
-
*
|
|
2050
|
-
*
|
|
2051
|
-
* A first pass with the recording keyword, so a mark counts exactly where
|
|
2052
|
-
* validation would evaluate it. Only present values are marked: Ajv applies
|
|
2053
|
-
* a property's subschema to a property that exists. A branch Ajv does not
|
|
2054
|
-
* take (`then` behind a failing `if`, an `anyOf` branch after a passing
|
|
2055
|
-
* one) contributes nothing; a branch it takes contributes its marks
|
|
2056
|
-
* whether or not the branch passes, because a ciphertext routinely fails
|
|
2057
|
-
* the rest of its own subschema until it is decrypted.
|
|
2440
|
+
* Whether writing the stale and unset fields changed the document, or
|
|
2441
|
+
* would have but for `dryRun`. Computed from the writer's output, so a
|
|
2442
|
+
* patch the format serializes to the same bytes is not a change.
|
|
2058
2443
|
*/
|
|
2059
|
-
|
|
2444
|
+
changed: boolean;
|
|
2445
|
+
/** Why the file could not be derived or written; the run goes on without it. */
|
|
2446
|
+
error?: string;
|
|
2060
2447
|
/**
|
|
2061
|
-
*
|
|
2062
|
-
*
|
|
2063
|
-
* `lineFor`.
|
|
2064
|
-
*
|
|
2065
|
-
* `colFor` is optional and additive: this signature is public, so a fourth
|
|
2066
|
-
* *required* parameter — or a widened third one — would be a consumer break.
|
|
2067
|
-
* Callers with an extractor that supplies no column pass nothing and get the
|
|
2068
|
-
* previous behavior exactly.
|
|
2448
|
+
* Under `check`, the findings for this file: one per stale or unset field,
|
|
2449
|
+
* at the field's line, plus one for an `error`. Absent otherwise.
|
|
2069
2450
|
*/
|
|
2070
|
-
|
|
2451
|
+
findings?: FieldError[];
|
|
2452
|
+
}
|
|
2453
|
+
interface DeriveSummary {
|
|
2454
|
+
files: number;
|
|
2455
|
+
/** Files whose document changed, or would have under `dryRun`. */
|
|
2456
|
+
changed: number;
|
|
2457
|
+
/** Fields whose write reached the disk: always 0 under `dryRun` and `check`. */
|
|
2458
|
+
written: number;
|
|
2071
2459
|
/**
|
|
2072
|
-
*
|
|
2073
|
-
*
|
|
2074
|
-
*
|
|
2460
|
+
* `provenance` ranges whose write reached the disk (proposal 0046): always
|
|
2461
|
+
* 0 under `dryRun` and `check`. Present only when the run derives
|
|
2462
|
+
* `provenance`.
|
|
2075
2463
|
*/
|
|
2076
|
-
|
|
2464
|
+
ranges?: number;
|
|
2465
|
+
stale: number;
|
|
2466
|
+
unset: number;
|
|
2467
|
+
unknown: number;
|
|
2468
|
+
errors: number;
|
|
2469
|
+
}
|
|
2470
|
+
interface DeriveRun {
|
|
2471
|
+
results: DeriveFileResult[];
|
|
2472
|
+
summary: DeriveSummary;
|
|
2473
|
+
dryRun: boolean;
|
|
2474
|
+
check: boolean;
|
|
2475
|
+
/** One status per source the run consulted; a source nobody asked for is absent. */
|
|
2476
|
+
sources: Partial<Record<DeriveSource, SourceStatus$1>>;
|
|
2477
|
+
/** Where the run stood, for the SARIF reporter under `check`. See `ValidateRun.frame`. */
|
|
2478
|
+
frame: FingerprintContext;
|
|
2479
|
+
}
|
|
2480
|
+
declare function runDerive(opts: DeriveOptions): Promise<DeriveRun>;
|
|
2481
|
+
|
|
2482
|
+
/**
|
|
2483
|
+
* `relocate` (proposal 0047): move every value to where its schema's
|
|
2484
|
+
* `x-manni-location` mark and the config's manifests say it belongs.
|
|
2485
|
+
*
|
|
2486
|
+
* Out of the page and into a manifest go the values a schema prefers in
|
|
2487
|
+
* external metadata and the values a manifest already owns. Out of a manifest
|
|
2488
|
+
* and into the page go the values a schema prefers on the page. The
|
|
2489
|
+
* collection, manifest file and config entry a value needs are created on the
|
|
2490
|
+
* way, and a change to a manifest's `keys:` covers every member page of its
|
|
2491
|
+
* collection. The planning and writing live in `core/relocation.ts`, which the
|
|
2492
|
+
* writers' and validate's offers share; this is the command around it.
|
|
2493
|
+
*
|
|
2494
|
+
* Two refusals come before the config is read, because each rules out the
|
|
2495
|
+
* whole run: stdin, which is not a document a manifest can name, and
|
|
2496
|
+
* `--no-config`, which leaves nowhere to declare a manifest.
|
|
2497
|
+
*/
|
|
2498
|
+
|
|
2499
|
+
interface RelocateOptions {
|
|
2500
|
+
/** Files, directories and globs. Empty falls back to the configured collections. `-` is refused. */
|
|
2501
|
+
inputs: string[];
|
|
2502
|
+
/** `--fields`: only these keys. Each must carry a mark, or be manifest-owned, for some file. */
|
|
2503
|
+
fields?: string[];
|
|
2504
|
+
/** `--collection <name>`, repeatable: run over these configured collections. */
|
|
2505
|
+
collections?: string[];
|
|
2506
|
+
/** `-s/--schema`, repeatable: the schema set every page is judged by. */
|
|
2507
|
+
cliSchemas?: string[];
|
|
2508
|
+
/** `--dry-run`: report what would move and be created; write nothing. */
|
|
2509
|
+
dryRun?: boolean;
|
|
2510
|
+
/** `--as`: force an extractor. */
|
|
2511
|
+
as?: string;
|
|
2512
|
+
exts?: string[];
|
|
2513
|
+
exclude?: string[];
|
|
2514
|
+
configPath?: string;
|
|
2515
|
+
/** `--no-config`: refused, since relocate writes the config. */
|
|
2516
|
+
noConfig?: boolean;
|
|
2517
|
+
cwd?: string;
|
|
2518
|
+
allowEmpty?: boolean;
|
|
2519
|
+
/** `--no-gitignore` (false). Absent leaves config `respectGitignore:` in charge. */
|
|
2520
|
+
respectGitignore?: boolean;
|
|
2521
|
+
onNotice?: (message: string) => void;
|
|
2522
|
+
onConfigLoaded?: (info: ConfigNotice) => void;
|
|
2523
|
+
/** Where `MANNI_ENCRYPTION_KEY` is read, for an encrypted join field. Defaults to `process.env`. */
|
|
2524
|
+
env?: NodeJS.ProcessEnv;
|
|
2077
2525
|
}
|
|
2526
|
+
declare function runRelocate(opts: RelocateOptions): Promise<RelocateResult>;
|
|
2078
2527
|
|
|
2079
2528
|
/** One value re-encrypted: where, and the ciphertext before and after. */
|
|
2080
2529
|
interface ReencryptedValue {
|
|
@@ -2297,6 +2746,12 @@ interface DeriveResult {
|
|
|
2297
2746
|
* not point at. Absent means not applicable here, never unavailable.
|
|
2298
2747
|
*/
|
|
2299
2748
|
sources: Partial<Record<DeriveSource, SourceStatus$1>>;
|
|
2749
|
+
/**
|
|
2750
|
+
* The provenance derivation per input label (proposal 0046), for the
|
|
2751
|
+
* comparison with a page's stamp: present only when `provenance` was
|
|
2752
|
+
* requested and the git source answered.
|
|
2753
|
+
*/
|
|
2754
|
+
provenance?: ReadonlyMap<string, ProvenanceDerivation>;
|
|
2300
2755
|
}
|
|
2301
2756
|
/**
|
|
2302
2757
|
* Which sources can state a field, in precedence order: the built-in table
|
|
@@ -3008,8 +3463,7 @@ interface SourceRange {
|
|
|
3008
3463
|
start?: number;
|
|
3009
3464
|
end?: number;
|
|
3010
3465
|
}
|
|
3011
|
-
|
|
3012
|
-
type LineSpec = number | string;
|
|
3466
|
+
|
|
3013
3467
|
/** The page text a citation supports. */
|
|
3014
3468
|
interface CitationClaim {
|
|
3015
3469
|
/** Body lines: counted from the first line after the frontmatter. Absent when a marker anchors the entry. */
|
|
@@ -3028,7 +3482,7 @@ interface CitationSource {
|
|
|
3028
3482
|
/** The git commit hash the pin was taken at: 7 to 64 lowercase hex. */
|
|
3029
3483
|
"commit-sha"?: string;
|
|
3030
3484
|
}
|
|
3031
|
-
/** One entry of `citations`, as the schema (`manni:citations:1.0.0-proposal.
|
|
3485
|
+
/** One entry of `citations`, as the schema (`manni:citations:1.0.0-proposal.4`) spells it. */
|
|
3032
3486
|
interface Citation {
|
|
3033
3487
|
id?: string;
|
|
3034
3488
|
claim?: CitationClaim;
|
|
@@ -3344,11 +3798,6 @@ interface CheckRun {
|
|
|
3344
3798
|
warnings: number;
|
|
3345
3799
|
notices: number;
|
|
3346
3800
|
}
|
|
3347
|
-
/** Page lines as an editor numbers them, 1-based and inclusive. */
|
|
3348
|
-
interface PageLines {
|
|
3349
|
-
start: number;
|
|
3350
|
-
end: number;
|
|
3351
|
-
}
|
|
3352
3801
|
interface AddOptions {
|
|
3353
3802
|
page: string;
|
|
3354
3803
|
/** The claim's lines as an editor numbers them (`page:L`, `page:L1-L2`). Absent: a bare pin. */
|
|
@@ -3596,16 +4045,6 @@ declare const SRC_PATTERN: RegExp;
|
|
|
3596
4045
|
declare function parseSrc(src: string): SourceRange;
|
|
3597
4046
|
/** The canonical spelling: `path:L` for one line, `path:L1-L2` otherwise. */
|
|
3598
4047
|
declare function formatSrc(range: SourceRange): string;
|
|
3599
|
-
/**
|
|
3600
|
-
* The lines an entry's `lines` names. Undefined for a value that is neither
|
|
3601
|
-
* a positive integer nor `"L1-L2"` with `L1 <= L2`: the schema refuses the
|
|
3602
|
-
* first, and `readPage` reports the second.
|
|
3603
|
-
*/
|
|
3604
|
-
declare function parseLines(spec: LineSpec): PageLines | undefined;
|
|
3605
|
-
/** Lines as an entry writes them: the integer for one line, `"L1-L2"` otherwise. */
|
|
3606
|
-
declare function lineSpec(lines: PageLines): LineSpec;
|
|
3607
|
-
/** Lines as a report spells them: `"9"` or `"9-12"`. */
|
|
3608
|
-
declare function spellLines(lines: PageLines): string;
|
|
3609
4048
|
/** An entry's source as a range. Its lines must already be valid (see `parseLines`). */
|
|
3610
4049
|
declare function sourceRange(source: CitationSource): SourceRange;
|
|
3611
4050
|
/** An entry's source spelled as one string, `path:L1-L2`, the way the command line takes it. */
|
|
@@ -3613,31 +4052,19 @@ declare function spellSource(source: CitationSource): string;
|
|
|
3613
4052
|
/** A range's lines as an entry writes them; undefined for a whole file. */
|
|
3614
4053
|
declare function rangeLines(range: SourceRange): LineSpec | undefined;
|
|
3615
4054
|
|
|
3616
|
-
/** BOM stripped, CRLF folded to LF. */
|
|
3617
|
-
declare function normalizeText(text: string): string;
|
|
3618
|
-
/** The normalized lines, without the empty element a trailing LF leaves. */
|
|
3619
|
-
declare function splitLines(text: string): string[];
|
|
3620
4055
|
/**
|
|
3621
|
-
* The
|
|
3622
|
-
*
|
|
4056
|
+
* The hashing rule, as cite uses it. The engine is `src/shared/pin.ts`, shared
|
|
4057
|
+
* with meta; this module keeps cite's import path and its error contract: a
|
|
4058
|
+
* range past the end of the text throws `CiteError`.
|
|
3623
4059
|
*/
|
|
3624
|
-
|
|
3625
|
-
start?: number;
|
|
3626
|
-
end?: number;
|
|
3627
|
-
}, label?: string): string;
|
|
3628
|
-
/** The pin of the cited lines: plain, or the keyed pin under `key` when one is given. */
|
|
3629
|
-
declare function hashRange(text: string, range?: {
|
|
3630
|
-
start?: number;
|
|
3631
|
-
end?: number;
|
|
3632
|
-
}, key?: string): string;
|
|
4060
|
+
|
|
3633
4061
|
/**
|
|
3634
|
-
* The
|
|
3635
|
-
*
|
|
3636
|
-
* passes `undefined`.
|
|
4062
|
+
* The cited lines joined by LF. Throws `CiteError` when the range runs past
|
|
4063
|
+
* the end of the text (`<path> has N lines; line M is out of range`).
|
|
3637
4064
|
*/
|
|
3638
|
-
declare function
|
|
3639
|
-
/**
|
|
3640
|
-
declare function
|
|
4065
|
+
declare function sliceLines(lines: readonly string[], range?: LineRange, label?: string): string;
|
|
4066
|
+
/** The pin of the cited lines: plain, or the keyed pin under `key` when one is given. Throws `CiteError` past the end. */
|
|
4067
|
+
declare function hashRange(text: string, range?: LineRange, key?: string): string;
|
|
3641
4068
|
|
|
3642
4069
|
/**
|
|
3643
4070
|
* How a citation reads on a terminal. A pin is sixty-four hex digits and a
|
|
@@ -3801,12 +4228,6 @@ declare function offsetOfLine(content: string, line: number): number;
|
|
|
3801
4228
|
declare function normalizeWhitespace(text: string): string;
|
|
3802
4229
|
/** `true` when the block's normalized text equals the cited lines under the hashing rule. */
|
|
3803
4230
|
declare function blockMatches(blockText: string, citedJoined: string): boolean;
|
|
3804
|
-
/** Body lines as file lines: body line 1 is the first line after the frontmatter. */
|
|
3805
|
-
declare function toFileLines(lines: PageLines, bodyLine: number): PageLines;
|
|
3806
|
-
/** File lines as body lines. */
|
|
3807
|
-
declare function toBodyLines(lines: PageLines, bodyLine: number): PageLines;
|
|
3808
|
-
/** The pin of a page range, under the claim rule: always plain. */
|
|
3809
|
-
declare function pinOfLines(lines: readonly string[], range: PageLines): string | undefined;
|
|
3810
4231
|
/** The first file line of a classified claim: where its findings sit. */
|
|
3811
4232
|
declare function claimLine(claim: ClaimEnd): number | undefined;
|
|
3812
4233
|
/**
|
|
@@ -3877,9 +4298,6 @@ declare function noGit(): GitClient;
|
|
|
3877
4298
|
* `moved`, not `never-true`; the search sees the file as it is.
|
|
3878
4299
|
*/
|
|
3879
4300
|
|
|
3880
|
-
declare const MOVE_WINDOW_LINES = 2000;
|
|
3881
|
-
declare const MOVE_BUDGET_BYTES: number;
|
|
3882
|
-
declare const MAX_RANGE_LINES = 5000;
|
|
3883
4301
|
interface ClassifyOptions {
|
|
3884
4302
|
root: string;
|
|
3885
4303
|
index: SourceIndex;
|
|
@@ -3890,24 +4308,6 @@ interface ClassifyOptions {
|
|
|
3890
4308
|
/** Hashing budget for the blind move search, in bytes. Default `MOVE_BUDGET_BYTES`. */
|
|
3891
4309
|
budget?: number;
|
|
3892
4310
|
}
|
|
3893
|
-
interface FindWindowsOptions {
|
|
3894
|
-
/** The 1-based start line the range was pinned at: the blind search begins around it. */
|
|
3895
|
-
around?: number;
|
|
3896
|
-
/** The cited lines at the commit, when git could show them: enables the first-line filter. */
|
|
3897
|
-
original?: readonly string[];
|
|
3898
|
-
/** Hashing budget for the blind search, in bytes. Default `MOVE_BUDGET_BYTES`. */
|
|
3899
|
-
budget?: number;
|
|
3900
|
-
}
|
|
3901
|
-
/**
|
|
3902
|
-
* Pure move search over normalized lines: the 1-based start lines where a
|
|
3903
|
-
* window of `length` lines hashes to `pin`. `original` (the cited lines at the
|
|
3904
|
-
* commit, when known) enables the first-line filter. `key` keys the hash for
|
|
3905
|
-
* an encrypted source's pin and is `undefined` for a plain one.
|
|
3906
|
-
*/
|
|
3907
|
-
declare function findWindows(lines: readonly string[], length: number, pin: string, key: string | undefined, opts?: FindWindowsOptions): {
|
|
3908
|
-
starts: number[];
|
|
3909
|
-
truncated: boolean;
|
|
3910
|
-
};
|
|
3911
4311
|
/**
|
|
3912
4312
|
* What git could say about the pin at the recorded commit. `unknown` is a
|
|
3913
4313
|
* file at the commit too large to search under the budget with the pin found
|
|
@@ -4804,4 +5204,4 @@ declare namespace index {
|
|
|
4804
5204
|
export { type index_EncryptionContext as EncryptionContext, index_KeyError as KeyError, type index_KeyRotateOptions as KeyRotateOptions, type index_KeyRotateResult as KeyRotateResult, type index_KeySetOptions as KeySetOptions, type index_KeySetResult as KeySetResult, type index_KeySource as KeySource, type index_ResolvedKey as ResolvedKey, type index_RotateManifest as RotateManifest, type index_RotateOutcome as RotateOutcome, type index_RotatePage as RotatePage, type index_RotatedCitation as RotatedCitation, type index_RotatedManifestValue as RotatedManifestValue, type index_RotatedMetadata as RotatedMetadata, type index_RotatedValue as RotatedValue, type index_SkippedCitation as SkippedCitation, type index_SkippedManifestValue as SkippedManifestValue, type index_SkippedMetadata as SkippedMetadata, type index_SkippedValue as SkippedValue, index_decryptValue as decryptValue, index_encryptValue as encryptValue, index_isEncryptedValue as isEncryptedValue, index_resolveEncryptionKey as resolveEncryptionKey, index_runKeyRotate as runKeyRotate, index_runKeySet as runKeySet };
|
|
4805
5205
|
}
|
|
4806
5206
|
|
|
4807
|
-
export { type ApplyOptions, type Approval, type BaselineSummary, BinMissing, type BuiltinDerivableField, COMMON_FORMATS, type CheckConfig, type CollectionConfig, type CommandSourceOptions, type CommandSourceResult, type CommonFormat, type ConfigNotice, DEFAULT_SCHEMAS, DEFAULT_TTL_HOURS, DEFAULT_VENDOR_DIR, DERIVABLE_FIELDS, DERIVED_KEYWORD, DERIVED_STALE_SCHEMA, DERIVE_FORMATS, DERIVE_SOURCES, type DerivableField, type DeriveCommand, type DeriveCommandConfig, type DeriveConfig, type DeriveContext, type DeriveFileResult, type DeriveInput, type DeriveOptions, type DeriveReportFormat, type DeriveReportOptions, type DeriveResult, type DeriveRun, type DeriveSource, type DeriveSummary, type DerivedField, type DerivedRecord, type DerivedStatus, type DerivedValue, type DocmetaConfig, DocmetaError, type DocumentRefTrust, EXTERNAL_DUPLICATE_SCHEMA, EXTERNAL_KEYWORD, EXTERNAL_METADATA_FETCH_MAX_BYTES, EXTERNAL_METADATA_FETCH_TIMEOUT_MS, EXTERNAL_OWNED_SCHEMA, type ExternalMetadataCollision, type ExternalMetadataConfig, type ExternalMetadataEntry, type ExternalMetadataFetchOptions, type ExternalMetadataIndex, type ExternalMetadataJoin, type ExternalMetadataValue, type ExtractOptions, type ExtractedMetadata, FIELD_SOURCES, FILL_FORMATS, type FetchedSchema, type FieldError, type FillConfig, type FillFileResult, type FillOptions, type FillReportFormat, type FillReportOptions, type FillRun, type FillSummary, type FilledField, type FingerprintContext, type FrontmatterFlavor, type FrontmatterLocation, type GetFileResult, type GetOptions, type GetReportOptions, GitHubClient, GitLabClient, INTEGRITY_SHAPE, type JunitOptions, type LoadExternalMetadataOptions, type LoadSchemaOptions, type LoadedConfig, type MergedChange, type MergedMetadata, type MetadataExtractor, type MetadataPatch, PATH_JOIN, PATH_PLACEHOLDER, QUERY_FORMATS, type QueryChange, type QueryFormat, type QueryOptions, type QueryReportOptions, type QueryRun, REPORT_FORMATS, RESOLVED_VIEW, REVIEW_CACHE_DIR, REVIEW_CACHE_VERSION, type ReadOptions, type ReencryptMetadataResult, type ReencryptedValue, type RemoteIdentity, type ReportFormat, type ReportOptions, ReviewCache, type ReviewClient, type ReviewFacts, type ReviewSourceInput, type ReviewSourceResult, type Run, type RunConfig, type RunConfigOptions, type RunSummary, SCHEMA_CACHE_DIR, SCHEMA_CACHE_VERSION, type SarifOptions, SchemaCache, type SchemaCacheConfig, type SchemaCacheEntry, type SchemaEntry, type SchemaPin, type SchemaRefEntry, type SchemaTrustConfig, type SkipReason, type SourceLocation, type SourceStatus$1 as SourceStatus, type SpawnOptions, type ValidateOptions, type ValidateRun, type ValidationResult, Validator, type VendorOptions, type VendorResult, applyFrontmatter, argvFor, assertSourcesAvailable, cachedClient, index$1 as cite, classifyRef, collectSchemaPins, compareDerived, consultedSources, createResolvedView, createReviewClient, deriveFromCommands, deriveFromReviews, deriveMetadata, externalMetadataJoin, externalMetadataPointer, externalMetadataUrlProblem, extractFrontmatter, extractorForExtension, fetchExternalMetadata, fetchSchemaBytes, frontmatterInnerText, getSchemasInfo, identityFromOrigin, integrityOf, isBuiltinField, isCommonFormat, isDeriveFormat, isDeriveSource, isErrorSeverity, isFillFormat, isIntegrity, isMember, isPerFile, isQueryFormat, isReportFormat, index as key, listBuiltins, loadConfig, loadExternalMetadata, loadSchema, locateFrontmatter, memberOf, mentionsResolved, mergeExternalMetadata, orphanEntries, orphanError, orphanJoins, parseCollections, parseConfig, parseOriginUrl, rebaseConfigSchemaRefs, reencryptMetadata, render, renderDerive, renderFill, renderFillGithub, renderGet, renderJunit, renderQuery, renderQueryCsv, renderSarif, resolveRunConfig, resolveSchemaSet, resolvedColumns, run, runDerive, runFill, runGet, runQuery, runValidate, runVendorSchema, schemaCacheDir, schemaEntryRef, schemaLoadOptions, selectCollections, sourcesFor, staleFindings, stringifyValue, supportedExtensions, valueOf, vendorFileName, writeFileAtomic };
|
|
5207
|
+
export { type ApplyOptions, type Approval, type BaselineSummary, BinMissing, type BuiltinDerivableField, COMMON_FORMATS, type CheckConfig, type CollectionConfig, type CommandSourceOptions, type CommandSourceResult, type CommonFormat, type ConfigNotice, DEFAULT_SCHEMAS, DEFAULT_TTL_HOURS, DEFAULT_VENDOR_DIR, DERIVABLE_FIELDS, DERIVED_KEYWORD, DERIVED_STALE_SCHEMA, DERIVE_FORMATS, DERIVE_SOURCES, type DerivableField, type DeriveCommand, type DeriveCommandConfig, type DeriveConfig, type DeriveContext, type DeriveFileResult, type DeriveInput, type DeriveOptions, type DeriveReportFormat, type DeriveReportOptions, type DeriveResult, type DeriveRun, type DeriveSource, type DeriveSummary, type DerivedField, type DerivedRecord, type DerivedStatus, type DerivedValue, type DocmetaConfig, DocmetaError, type DocumentRefTrust, EXTERNAL_DUPLICATE_SCHEMA, EXTERNAL_KEYWORD, EXTERNAL_METADATA_FETCH_MAX_BYTES, EXTERNAL_METADATA_FETCH_TIMEOUT_MS, EXTERNAL_OWNED_SCHEMA, type ExternalMetadataCollision, type ExternalMetadataConfig, type ExternalMetadataEntry, type ExternalMetadataFetchOptions, type ExternalMetadataIndex, type ExternalMetadataJoin, type ExternalMetadataValue, type ExtractOptions, type ExtractedMetadata, FIELD_SOURCES, FILL_FORMATS, type FetchedSchema, type FieldError, type FieldLocation, type FillConfig, type FillFileResult, type FillOptions, type FillReportFormat, type FillReportOptions, type FillRun, type FillSummary, type FilledField, type FingerprintContext, type FrontmatterFlavor, type FrontmatterLocation, type GetFileResult, type GetOptions, type GetReportOptions, GitHubClient, GitLabClient, INTEGRITY_SHAPE, type JunitOptions, LOCATION_KEYWORD, type LoadExternalMetadataOptions, type LoadSchemaOptions, type LoadedConfig, type LocationPreference, type MergedChange, type MergedMetadata, type MetadataExtractor, type MetadataPatch, PATH_JOIN, PATH_PLACEHOLDER, QUERY_FORMATS, type QueryChange, type QueryFormat, type QueryOptions, type QueryReportOptions, type QueryRun, REPORT_FORMATS, RESOLVED_VIEW, REVIEW_CACHE_DIR, REVIEW_CACHE_VERSION, type ReadOptions, type ReencryptMetadataResult, type ReencryptedValue, type RelocateOptions, type RelocateResult, type RemoteIdentity, type ReportFormat, type ReportOptions, ReviewCache, type ReviewClient, type ReviewFacts, type ReviewSourceInput, type ReviewSourceResult, type Run, type RunConfig, type RunConfigOptions, type RunSummary, SCHEMA_CACHE_DIR, SCHEMA_CACHE_VERSION, type SarifOptions, SchemaCache, type SchemaCacheConfig, type SchemaCacheEntry, type SchemaEntry, type SchemaPin, type SchemaRefEntry, type SchemaTrustConfig, type SkipReason, type SourceLocation, type SourceStatus$1 as SourceStatus, type SpawnOptions, type ValidateOptions, type ValidateRun, type ValidationResult, Validator, type VendorOptions, type VendorResult, applyFrontmatter, argvFor, assertSourcesAvailable, cachedClient, index$1 as cite, classifyRef, collectSchemaPins, compareDerived, consultedSources, createResolvedView, createReviewClient, deriveFromCommands, deriveFromReviews, deriveMetadata, externalMetadataJoin, externalMetadataPointer, externalMetadataUrlProblem, extractFrontmatter, extractorForExtension, fetchExternalMetadata, fetchSchemaBytes, frontmatterInnerText, getSchemasInfo, identityFromOrigin, integrityOf, isBuiltinField, isCommonFormat, isDeriveFormat, isDeriveSource, isErrorSeverity, isFillFormat, isIntegrity, isMember, isPerFile, isQueryFormat, isReportFormat, index as key, listBuiltins, loadConfig, loadExternalMetadata, loadSchema, locateFrontmatter, memberOf, mentionsResolved, mergeExternalMetadata, orphanEntries, orphanError, orphanJoins, parseCollections, parseConfig, parseOriginUrl, rebaseConfigSchemaRefs, reencryptMetadata, render, renderDerive, renderFill, renderFillGithub, renderGet, renderJunit, renderQuery, renderQueryCsv, renderSarif, resolveRunConfig, resolveSchemaSet, resolvedColumns, run, runDerive, runFill, runGet, runQuery, runRelocate, runValidate, runVendorSchema, schemaCacheDir, schemaEntryRef, schemaLoadOptions, selectCollections, sourcesFor, staleFindings, stringifyValue, supportedExtensions, valueOf, vendorFileName, writeFileAtomic };
|