@hawkeyexl/manni 2.10.2 → 2.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/{chunk-KJLPOY2I.js → chunk-7ODP2AB3.js} +1109 -603
- package/dist/chunk-7ODP2AB3.js.map +1 -0
- package/dist/{chunk-4HKOQIJL.js → chunk-CZGAZGDN.js} +135 -43
- package/dist/chunk-CZGAZGDN.js.map +1 -0
- package/dist/{chunk-H5ZFSHG2.js → chunk-FMXJ4Z3V.js} +2 -2
- package/dist/cli.js +3 -3
- package/dist/docmeta.js +2 -2
- package/dist/index.d.ts +57 -1
- package/dist/index.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-4HKOQIJL.js.map +0 -1
- package/dist/chunk-KJLPOY2I.js.map +0 -1
- /package/dist/{chunk-H5ZFSHG2.js.map → chunk-FMXJ4Z3V.js.map} +0 -0
|
@@ -8,7 +8,7 @@ var __export = (target, all) => {
|
|
|
8
8
|
// package.json
|
|
9
9
|
var package_default = {
|
|
10
10
|
name: "@hawkeyexl/manni",
|
|
11
|
-
version: "2.
|
|
11
|
+
version: "2.11.1",
|
|
12
12
|
description: "One command line for documentation that is meant to be checked. `manni meta` validates the presence and format of document metadata (Markdown frontmatter and more) against JSON Schema, built for CI. Formerly docmeta.",
|
|
13
13
|
type: "module",
|
|
14
14
|
bin: {
|
|
@@ -141,6 +141,99 @@ function matchesFileGlob(relPath, glob) {
|
|
|
141
141
|
return m(relPath.replace(/\\/g, "/"));
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
+
// src/shared/collections.ts
|
|
145
|
+
import { posix as posix2, win32 } from "node:path";
|
|
146
|
+
|
|
147
|
+
// src/shared/page-manifest.ts
|
|
148
|
+
import { readFileSync, realpathSync } from "node:fs";
|
|
149
|
+
import { isAbsolute, posix, relative, resolve, sep } from "node:path";
|
|
150
|
+
import fg from "fast-glob";
|
|
151
|
+
import { LineCounter, isMap, isNode, isScalar, parseDocument } from "yaml";
|
|
152
|
+
var PAGE_PLACEHOLDER = "{page}";
|
|
153
|
+
function hasPagePlaceholder(file) {
|
|
154
|
+
return file.includes(PAGE_PLACEHOLDER);
|
|
155
|
+
}
|
|
156
|
+
function slashes(path) {
|
|
157
|
+
return path.split(sep).join("/").replace(/\\/g, "/");
|
|
158
|
+
}
|
|
159
|
+
function normalizeManifestPattern(file) {
|
|
160
|
+
const forward = file.replace(/\\/g, "/");
|
|
161
|
+
return forward.startsWith("./") ? forward.slice(2) : forward;
|
|
162
|
+
}
|
|
163
|
+
function pageManifestPath(file, configDir, pageAbs) {
|
|
164
|
+
const between = relative(configDir, pageAbs);
|
|
165
|
+
const pageRel = slashes(between);
|
|
166
|
+
if (isAbsolute(between) || pageRel === ".." || pageRel.startsWith("../")) {
|
|
167
|
+
return { outside: true, pageRel };
|
|
168
|
+
}
|
|
169
|
+
const ext = posix.extname(pageRel);
|
|
170
|
+
const page = ext === "" ? pageRel : pageRel.slice(0, -ext.length);
|
|
171
|
+
const named = normalizeManifestPattern(file).replace(PAGE_PLACEHOLDER, () => page);
|
|
172
|
+
const abs = resolve(configDir, named);
|
|
173
|
+
return { abs, rel: slashes(relative(configDir, abs)) };
|
|
174
|
+
}
|
|
175
|
+
function strayManifestGlob(file) {
|
|
176
|
+
const normalized = normalizeManifestPattern(file);
|
|
177
|
+
const at2 = normalized.indexOf(PAGE_PLACEHOLDER);
|
|
178
|
+
if (at2 < 0) return literal(normalized);
|
|
179
|
+
const prefix = literal(normalized.slice(0, at2));
|
|
180
|
+
const suffix = literal(normalized.slice(at2 + PAGE_PLACEHOLDER.length));
|
|
181
|
+
return `${prefix}**/*${suffix}`;
|
|
182
|
+
}
|
|
183
|
+
function literal(text2) {
|
|
184
|
+
return text2 === "" ? "" : fg.escapePath(text2);
|
|
185
|
+
}
|
|
186
|
+
function findPageManifests(file, configDir, isMember2) {
|
|
187
|
+
const matched = fg.sync(strayManifestGlob(file), {
|
|
188
|
+
cwd: configDir,
|
|
189
|
+
absolute: true,
|
|
190
|
+
onlyFiles: true,
|
|
191
|
+
dot: false,
|
|
192
|
+
ignore: ["**/node_modules/**", "**/.git/**"]
|
|
193
|
+
}).map((path) => resolve(path)).sort();
|
|
194
|
+
const found = [];
|
|
195
|
+
for (const abs of matched) {
|
|
196
|
+
const entries = ownEntries(abs, file, configDir, isMember2);
|
|
197
|
+
if (entries.length > 0) found.push({ abs, entries });
|
|
198
|
+
}
|
|
199
|
+
return found;
|
|
200
|
+
}
|
|
201
|
+
function ownEntries(abs, file, configDir, isMember2) {
|
|
202
|
+
let text2;
|
|
203
|
+
try {
|
|
204
|
+
text2 = readFileSync(abs, "utf8");
|
|
205
|
+
} catch {
|
|
206
|
+
return [];
|
|
207
|
+
}
|
|
208
|
+
const lc = new LineCounter();
|
|
209
|
+
const doc = parseDocument(text2, { lineCounter: lc, uniqueKeys: false });
|
|
210
|
+
const root = doc.contents;
|
|
211
|
+
if (doc.errors.length > 0 || !isMap(root)) return [];
|
|
212
|
+
const entries = [];
|
|
213
|
+
for (const pair of root.items) {
|
|
214
|
+
const spelled = isScalar(pair.key) ? String(pair.key.value) : String(pair.key);
|
|
215
|
+
const pageAbs = resolve(configDir, spelled);
|
|
216
|
+
if (!isMember2(slashes(relative(configDir, pageAbs)))) continue;
|
|
217
|
+
const resolved = pageManifestPath(file, configDir, pageAbs);
|
|
218
|
+
if ("outside" in resolved || !sameFile(resolved.abs, abs)) continue;
|
|
219
|
+
const range = isNode(pair.key) ? pair.key.range : void 0;
|
|
220
|
+
entries.push({
|
|
221
|
+
spelled,
|
|
222
|
+
pageAbs,
|
|
223
|
+
...range ? { line: lc.linePos(range[0]).line } : {}
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
return entries;
|
|
227
|
+
}
|
|
228
|
+
function sameFile(a, b) {
|
|
229
|
+
if (a === b) return true;
|
|
230
|
+
try {
|
|
231
|
+
return realpathSync(a) === realpathSync(b);
|
|
232
|
+
} catch {
|
|
233
|
+
return false;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
144
237
|
// src/shared/collections.ts
|
|
145
238
|
var COLLECTION_KEYS = [
|
|
146
239
|
"name",
|
|
@@ -150,6 +243,7 @@ var COLLECTION_KEYS = [
|
|
|
150
243
|
"externalMetadata"
|
|
151
244
|
];
|
|
152
245
|
var EXTERNAL_METADATA_KEYS = ["file", "keys", "tokenEnv", "join"];
|
|
246
|
+
var PATH_JOIN = "path";
|
|
153
247
|
var SCHEMA_KEY = "$schema";
|
|
154
248
|
var STDIN = "<stdin>";
|
|
155
249
|
function isUrlRef(ref) {
|
|
@@ -285,6 +379,7 @@ function isHttpUrl(value) {
|
|
|
285
379
|
}
|
|
286
380
|
function parseExternalMetadata(raw, collectionWhere, source, toError) {
|
|
287
381
|
const owners = /* @__PURE__ */ new Map();
|
|
382
|
+
const patterns = /* @__PURE__ */ new Map();
|
|
288
383
|
return raw.map((entry, i) => {
|
|
289
384
|
const where = `${collectionWhere}.externalMetadata[${i}]`;
|
|
290
385
|
if (!isMapping(entry)) {
|
|
@@ -296,6 +391,16 @@ function parseExternalMetadata(raw, collectionWhere, source, toError) {
|
|
|
296
391
|
`${source}: ${where}.file must be a non-empty string naming the manifest, relative to the config file.`
|
|
297
392
|
);
|
|
298
393
|
}
|
|
394
|
+
const placeholderProblem = pagePlaceholderProblem(entry.file);
|
|
395
|
+
if (placeholderProblem !== null) {
|
|
396
|
+
throw toError(`${source}: ${where}.file ${placeholderProblem}`);
|
|
397
|
+
}
|
|
398
|
+
const perPage = hasPagePlaceholder(entry.file);
|
|
399
|
+
if (perPage && (posix2.isAbsolute(entry.file) || win32.isAbsolute(entry.file))) {
|
|
400
|
+
throw toError(
|
|
401
|
+
`${source}: ${where}.file uses ${PAGE_PLACEHOLDER} in an absolute path, so every manifest would sit outside the repository. Make it relative to the config file.`
|
|
402
|
+
);
|
|
403
|
+
}
|
|
299
404
|
if (!Array.isArray(entry.keys) || entry.keys.length === 0 || entry.keys.some((k) => !isNonEmptyString(k))) {
|
|
300
405
|
throw toError(
|
|
301
406
|
`${source}: ${where}.keys must be a non-empty list of key names.`
|
|
@@ -307,6 +412,11 @@ function parseExternalMetadata(raw, collectionWhere, source, toError) {
|
|
|
307
412
|
if (problem !== null) {
|
|
308
413
|
throw toError(`${source}: ${where}.file ${problem}.`);
|
|
309
414
|
}
|
|
415
|
+
if (perPage) {
|
|
416
|
+
throw toError(
|
|
417
|
+
`${source}: ${where}.file uses ${PAGE_PLACEHOLDER} in a URL. A placeholder names a file this run can write, and a URL is not one.`
|
|
418
|
+
);
|
|
419
|
+
}
|
|
310
420
|
}
|
|
311
421
|
if (entry.tokenEnv !== void 0) {
|
|
312
422
|
if (!isNonEmptyString(entry.tokenEnv)) {
|
|
@@ -336,6 +446,11 @@ function parseExternalMetadata(raw, collectionWhere, source, toError) {
|
|
|
336
446
|
);
|
|
337
447
|
}
|
|
338
448
|
}
|
|
449
|
+
if (perPage && typeof entry.join === "string" && entry.join !== PATH_JOIN) {
|
|
450
|
+
throw toError(
|
|
451
|
+
`${source}: ${where}.file uses ${PAGE_PLACEHOLDER}, and join is "${entry.join}". A per-page manifest is found by path, so it cannot be keyed by a field. Remove ${PAGE_PLACEHOLDER}, or remove join.`
|
|
452
|
+
);
|
|
453
|
+
}
|
|
339
454
|
const seen = /* @__PURE__ */ new Set();
|
|
340
455
|
for (const key of keys) {
|
|
341
456
|
if (key === SCHEMA_KEY) {
|
|
@@ -355,14 +470,46 @@ function parseExternalMetadata(raw, collectionWhere, source, toError) {
|
|
|
355
470
|
}
|
|
356
471
|
owners.set(key, i);
|
|
357
472
|
}
|
|
358
|
-
|
|
473
|
+
if (perPage) {
|
|
474
|
+
const pattern = normalizeManifestPattern(entry.file);
|
|
475
|
+
const first = patterns.get(pattern);
|
|
476
|
+
if (first !== void 0) {
|
|
477
|
+
throw toError(
|
|
478
|
+
`${source}: ${where}.file resolves to the same manifest as externalMetadata[${String(first)}].file for every page. Give each entry its own file name.`
|
|
479
|
+
);
|
|
480
|
+
}
|
|
481
|
+
patterns.set(pattern, i);
|
|
482
|
+
}
|
|
483
|
+
const parsed2 = {
|
|
359
484
|
file: entry.file,
|
|
360
485
|
keys,
|
|
361
486
|
...typeof entry.tokenEnv === "string" ? { tokenEnv: entry.tokenEnv } : {},
|
|
362
487
|
...typeof entry.join === "string" ? { join: entry.join } : {}
|
|
363
488
|
};
|
|
489
|
+
origins.set(parsed2, { source, where });
|
|
490
|
+
return parsed2;
|
|
364
491
|
});
|
|
365
492
|
}
|
|
493
|
+
function pagePlaceholderProblem(file) {
|
|
494
|
+
for (const match of file.matchAll(/\{[^{}]*\}/g)) {
|
|
495
|
+
if (match[0] !== PAGE_PLACEHOLDER) {
|
|
496
|
+
return `uses "${match[0]}", which is not a placeholder. The only placeholder is ${PAGE_PLACEHOLDER}.`;
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
const tokens2 = file.split(PAGE_PLACEHOLDER);
|
|
500
|
+
const stray = /[{}]/.exec(tokens2.join(""));
|
|
501
|
+
if (stray !== null) {
|
|
502
|
+
return `contains "${stray[0]}" outside a ${PAGE_PLACEHOLDER} placeholder. Remove it, or write ${PAGE_PLACEHOLDER}.`;
|
|
503
|
+
}
|
|
504
|
+
if (tokens2.length > 2) {
|
|
505
|
+
return `uses ${PAGE_PLACEHOLDER} twice. One manifest names one page.`;
|
|
506
|
+
}
|
|
507
|
+
return null;
|
|
508
|
+
}
|
|
509
|
+
var origins = /* @__PURE__ */ new WeakMap();
|
|
510
|
+
function externalMetadataOrigin(entry) {
|
|
511
|
+
return origins.get(entry);
|
|
512
|
+
}
|
|
366
513
|
function selectCollections(collections, names, source, toError) {
|
|
367
514
|
if (names === void 0 || names.length === 0) return [...collections];
|
|
368
515
|
const wanted = new Set(names);
|
|
@@ -383,6 +530,9 @@ function selectCollections(collections, names, source, toError) {
|
|
|
383
530
|
function isMember(collection, relPath) {
|
|
384
531
|
if (relPath === STDIN) return false;
|
|
385
532
|
if (relPath.startsWith("../")) return false;
|
|
533
|
+
return matchesCollectionPaths(collection, relPath);
|
|
534
|
+
}
|
|
535
|
+
function matchesCollectionPaths(collection, relPath) {
|
|
386
536
|
const matched = collection.paths.some((entry) => {
|
|
387
537
|
const normalized = normalizeEntry(entry);
|
|
388
538
|
if (normalized === "") return false;
|
|
@@ -393,15 +543,15 @@ function isMember(collection, relPath) {
|
|
|
393
543
|
return !collection.exclude.some((glob) => matchesFileGlob(relPath, glob));
|
|
394
544
|
}
|
|
395
545
|
function normalizeEntry(entry) {
|
|
396
|
-
const
|
|
397
|
-
return
|
|
546
|
+
const posix7 = entry.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
547
|
+
return posix7.endsWith("/") ? posix7.slice(0, -1) : posix7;
|
|
398
548
|
}
|
|
399
549
|
function isGlob(entry) {
|
|
400
550
|
return picomatch2.scan(entry).isGlob;
|
|
401
551
|
}
|
|
402
552
|
|
|
403
553
|
// src/shared/run.ts
|
|
404
|
-
import { realpathSync } from "node:fs";
|
|
554
|
+
import { realpathSync as realpathSync2 } from "node:fs";
|
|
405
555
|
import { fileURLToPath } from "node:url";
|
|
406
556
|
import { CommanderError } from "commander";
|
|
407
557
|
|
|
@@ -472,7 +622,7 @@ function isMainModule(moduleUrl) {
|
|
|
472
622
|
const entry = process.argv[1];
|
|
473
623
|
if (!entry) return false;
|
|
474
624
|
try {
|
|
475
|
-
return
|
|
625
|
+
return realpathSync2(entry) === fileURLToPath(moduleUrl);
|
|
476
626
|
} catch {
|
|
477
627
|
return false;
|
|
478
628
|
}
|
|
@@ -532,7 +682,7 @@ function diagnoseIntegrity(bytes, expected) {
|
|
|
532
682
|
}
|
|
533
683
|
|
|
534
684
|
// src/meta/extractors/frontmatter.ts
|
|
535
|
-
import { parseDocument, LineCounter, isMap, isSeq, isScalar } from "yaml";
|
|
685
|
+
import { parseDocument as parseDocument2, LineCounter as LineCounter2, isMap as isMap2, isSeq, isScalar as isScalar2 } from "yaml";
|
|
536
686
|
import { parse as parseToml } from "smol-toml";
|
|
537
687
|
|
|
538
688
|
// src/meta/extractors/date-value.ts
|
|
@@ -612,9 +762,9 @@ function buildLineMap(doc, lc, prefixLines) {
|
|
|
612
762
|
map.set("", 1);
|
|
613
763
|
const lineAt = (offset) => offset == null ? void 0 : lc.linePos(offset).line + prefixLines;
|
|
614
764
|
const walk = (node, pointer) => {
|
|
615
|
-
if (
|
|
765
|
+
if (isMap2(node)) {
|
|
616
766
|
for (const pair of node.items) {
|
|
617
|
-
const key =
|
|
767
|
+
const key = isScalar2(pair.key) ? String(pair.key.value) : String(pair.key);
|
|
618
768
|
const ptr = `${pointer}/${escapePointerSegment(key)}`;
|
|
619
769
|
const line = lineAt(
|
|
620
770
|
pair.key?.range?.[0]
|
|
@@ -668,8 +818,8 @@ function rootObject(parsed2, label) {
|
|
|
668
818
|
throw new Error(`Invalid ${label} frontmatter: root must be an object`);
|
|
669
819
|
}
|
|
670
820
|
function parseYamlBlock(raw, prefixLines, format) {
|
|
671
|
-
const lc = new
|
|
672
|
-
const doc =
|
|
821
|
+
const lc = new LineCounter2();
|
|
822
|
+
const doc = parseDocument2(raw, { lineCounter: lc });
|
|
673
823
|
if (doc.errors.length > 0) {
|
|
674
824
|
const e = doc.errors[0];
|
|
675
825
|
throw new Error(`Invalid YAML frontmatter: ${e?.message ?? "parse error"}`);
|
|
@@ -693,8 +843,8 @@ function parseJsonBlock(raw, prefixLines, format) {
|
|
|
693
843
|
);
|
|
694
844
|
}
|
|
695
845
|
const data = rootObject(parsed2, "JSON");
|
|
696
|
-
const lc = new
|
|
697
|
-
const doc =
|
|
846
|
+
const lc = new LineCounter2();
|
|
847
|
+
const doc = parseDocument2(raw, { lineCounter: lc });
|
|
698
848
|
const map = buildLineMap(doc, lc, prefixLines);
|
|
699
849
|
return { data, present: true, format, lineFor: positionForFactory(map) };
|
|
700
850
|
}
|
|
@@ -751,7 +901,12 @@ var DocmetaError = class extends ToolError {
|
|
|
751
901
|
};
|
|
752
902
|
|
|
753
903
|
// src/meta/extractors/frontmatter-write.ts
|
|
754
|
-
import {
|
|
904
|
+
import {
|
|
905
|
+
parseDocument as parseDocument3,
|
|
906
|
+
isMap as isMap4,
|
|
907
|
+
isCollection,
|
|
908
|
+
isScalar as isScalar4
|
|
909
|
+
} from "yaml";
|
|
755
910
|
import { parse as parseToml2, stringify as stringifyToml } from "smol-toml";
|
|
756
911
|
|
|
757
912
|
// src/meta/extractors/patch-util.ts
|
|
@@ -797,6 +952,174 @@ function toJsonText(value) {
|
|
|
797
952
|
return JSON.stringify(value);
|
|
798
953
|
}
|
|
799
954
|
|
|
955
|
+
// src/meta/core/yaml-splice.ts
|
|
956
|
+
import {
|
|
957
|
+
isMap as isMap3,
|
|
958
|
+
isNode as isNode2,
|
|
959
|
+
isPair,
|
|
960
|
+
isScalar as isScalar3,
|
|
961
|
+
isSeq as isSeq2,
|
|
962
|
+
stringify
|
|
963
|
+
} from "yaml";
|
|
964
|
+
function insertKey(text2, entryMap, key, value, style) {
|
|
965
|
+
const firstKey = rangeOf(entryMap.items[0]?.key);
|
|
966
|
+
const end = contentEnd(text2, entryMap);
|
|
967
|
+
if (!firstKey || end === void 0) return void 0;
|
|
968
|
+
const pos = lineEnd(text2, end);
|
|
969
|
+
return {
|
|
970
|
+
start: pos,
|
|
971
|
+
end: pos,
|
|
972
|
+
insert: style.eol + blockLines({ [key]: value }, colOf(text2, firstKey[0]), style)
|
|
973
|
+
};
|
|
974
|
+
}
|
|
975
|
+
function replaceBlockValue(text2, pair, value, style) {
|
|
976
|
+
const colon = colonEnd(text2, pair);
|
|
977
|
+
const keyRange = rangeOf(pair.key);
|
|
978
|
+
if (colon === void 0 || !keyRange) return void 0;
|
|
979
|
+
const keyCol = colOf(text2, keyRange[0]);
|
|
980
|
+
let start = colon;
|
|
981
|
+
let ownLine = false;
|
|
982
|
+
let i = colon;
|
|
983
|
+
while (text2.charAt(i) === " " || text2.charAt(i) === " ") i++;
|
|
984
|
+
if (text2.charAt(i) === "#") {
|
|
985
|
+
start = lineEnd(text2, i);
|
|
986
|
+
ownLine = true;
|
|
987
|
+
}
|
|
988
|
+
const old = pair.value;
|
|
989
|
+
const oldEnd = isScalar3(old) && old.value === null && emptySource(text2, old) ? start : contentEnd(text2, old) ?? start;
|
|
990
|
+
const end = Math.max(start, oldEnd);
|
|
991
|
+
let insert = afterColon(value, keyCol, style);
|
|
992
|
+
if (ownLine && !insert.startsWith(style.eol)) {
|
|
993
|
+
insert = style.eol + " ".repeat(keyCol + style.step) + insert.trimStart();
|
|
994
|
+
}
|
|
995
|
+
return { start, end, insert };
|
|
996
|
+
}
|
|
997
|
+
function replaceFlowValue(text2, pair, value, padded) {
|
|
998
|
+
const r = rangeOf(pair.value);
|
|
999
|
+
if (!r || emptySource(text2, pair.value)) return void 0;
|
|
1000
|
+
const end = contentEnd(text2, pair.value) ?? r[1];
|
|
1001
|
+
return { start: r[0], end, insert: flowText(value, padded) };
|
|
1002
|
+
}
|
|
1003
|
+
function keyLines(text2, from, to, eol) {
|
|
1004
|
+
let start = text2.lastIndexOf("\n", from - 1) + 1;
|
|
1005
|
+
let end = lineEnd(text2, to);
|
|
1006
|
+
if (text2.startsWith(eol, end)) end += eol.length;
|
|
1007
|
+
else if (start >= eol.length) start -= eol.length;
|
|
1008
|
+
return { start, end };
|
|
1009
|
+
}
|
|
1010
|
+
function removeKey(text2, pair, eol) {
|
|
1011
|
+
const from = rangeOf(pair.key);
|
|
1012
|
+
const to = contentEnd(text2, pair.value) ?? contentEnd(text2, pair.key);
|
|
1013
|
+
if (!from || to === void 0) return void 0;
|
|
1014
|
+
const { start, end } = keyLines(text2, from[0], to, eol);
|
|
1015
|
+
return { start, end, insert: "" };
|
|
1016
|
+
}
|
|
1017
|
+
function blockLines(pair, col, style) {
|
|
1018
|
+
const s = stringify(pair, { lineWidth: 0, indent: style.step, indentSeq: style.indentSeq });
|
|
1019
|
+
return indentLines(s.replace(/\n$/, "").split("\n"), col, 0).join(style.eol);
|
|
1020
|
+
}
|
|
1021
|
+
function afterColon(value, col, style) {
|
|
1022
|
+
const s = stringify({ k: value }, { lineWidth: 0, indent: style.step, indentSeq: style.indentSeq });
|
|
1023
|
+
const lines = s.replace(/\n$/, "").slice("k:".length).split("\n");
|
|
1024
|
+
return indentLines(lines, col, 1).join(style.eol);
|
|
1025
|
+
}
|
|
1026
|
+
function indentLines(lines, col, from) {
|
|
1027
|
+
const pad2 = " ".repeat(col);
|
|
1028
|
+
return lines.map((l, i) => i < from || l === "" ? l : pad2 + l);
|
|
1029
|
+
}
|
|
1030
|
+
function flowText(value, padded) {
|
|
1031
|
+
const s = stringify(value, {
|
|
1032
|
+
lineWidth: 0,
|
|
1033
|
+
collectionStyle: "flow",
|
|
1034
|
+
...padded === void 0 ? {} : { flowCollectionPadding: padded }
|
|
1035
|
+
}).replace(/\n$/, "");
|
|
1036
|
+
return s.includes("\n") ? JSON.stringify(value) : s;
|
|
1037
|
+
}
|
|
1038
|
+
function detectEol(text2) {
|
|
1039
|
+
const i = text2.indexOf("\n");
|
|
1040
|
+
return i > 0 && text2.charAt(i - 1) === "\r" ? "\r\n" : "\n";
|
|
1041
|
+
}
|
|
1042
|
+
function detectStyle(text2, root, eol) {
|
|
1043
|
+
let step = 2;
|
|
1044
|
+
for (const pair of root.items) {
|
|
1045
|
+
const v = pair.value;
|
|
1046
|
+
const entryKey = rangeOf(pair.key);
|
|
1047
|
+
const ownedKey = isMap3(v) && v.flow !== true ? rangeOf(v.items[0]?.key) : void 0;
|
|
1048
|
+
if (entryKey && ownedKey) {
|
|
1049
|
+
const d = colOf(text2, ownedKey[0]) - colOf(text2, entryKey[0]);
|
|
1050
|
+
if (d > 0) {
|
|
1051
|
+
step = d;
|
|
1052
|
+
break;
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
return { step, indentSeq: seqIndented(text2, root) ?? true, eol };
|
|
1057
|
+
}
|
|
1058
|
+
function seqIndented(text2, node) {
|
|
1059
|
+
if (isMap3(node)) {
|
|
1060
|
+
for (const pair of node.items) {
|
|
1061
|
+
const v = pair.value;
|
|
1062
|
+
if (isSeq2(v) && v.flow !== true && v.items.length > 0) {
|
|
1063
|
+
const k = rangeOf(pair.key);
|
|
1064
|
+
const s = rangeOf(v);
|
|
1065
|
+
if (k && s) return colOf(text2, s[0]) > colOf(text2, k[0]);
|
|
1066
|
+
}
|
|
1067
|
+
const inner = seqIndented(text2, v);
|
|
1068
|
+
if (inner !== void 0) return inner;
|
|
1069
|
+
}
|
|
1070
|
+
} else if (isSeq2(node)) {
|
|
1071
|
+
for (const item of node.items) {
|
|
1072
|
+
const inner = seqIndented(text2, item);
|
|
1073
|
+
if (inner !== void 0) return inner;
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
return void 0;
|
|
1077
|
+
}
|
|
1078
|
+
function contentEnd(text2, node) {
|
|
1079
|
+
if (isMap3(node) && node.flow !== true) {
|
|
1080
|
+
const last = node.items.at(-1);
|
|
1081
|
+
if (last) return contentEnd(text2, last.value) ?? contentEnd(text2, last.key);
|
|
1082
|
+
} else if (isSeq2(node) && node.flow !== true) {
|
|
1083
|
+
const last = node.items.at(-1);
|
|
1084
|
+
if (last !== void 0) {
|
|
1085
|
+
return isPair(last) ? contentEnd(text2, last.value) ?? contentEnd(text2, last.key) : contentEnd(text2, last);
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
const r = rangeOf(node);
|
|
1089
|
+
if (!r) return void 0;
|
|
1090
|
+
let end = r[1];
|
|
1091
|
+
while (end > r[0] && /\s/.test(text2.charAt(end - 1))) end--;
|
|
1092
|
+
return end;
|
|
1093
|
+
}
|
|
1094
|
+
function colonEnd(text2, pair) {
|
|
1095
|
+
const r = rangeOf(pair.key);
|
|
1096
|
+
if (!r) return void 0;
|
|
1097
|
+
let i = r[1];
|
|
1098
|
+
while (text2.charAt(i) === " " || text2.charAt(i) === " ") i++;
|
|
1099
|
+
return text2.charAt(i) === ":" ? i + 1 : void 0;
|
|
1100
|
+
}
|
|
1101
|
+
function lineEnd(text2, i) {
|
|
1102
|
+
const j = text2.indexOf("\n", i);
|
|
1103
|
+
if (j < 0) return text2.length;
|
|
1104
|
+
return j > 0 && text2.charAt(j - 1) === "\r" ? j - 1 : j;
|
|
1105
|
+
}
|
|
1106
|
+
function colOf(text2, offset) {
|
|
1107
|
+
if (offset === 0) return 0;
|
|
1108
|
+
let start = text2.lastIndexOf("\n", offset - 1) + 1;
|
|
1109
|
+
if (start === 0 && text2.startsWith("\uFEFF")) start = 1;
|
|
1110
|
+
return offset - start;
|
|
1111
|
+
}
|
|
1112
|
+
function rangeOf(node) {
|
|
1113
|
+
return isNode2(node) ? node.range ?? void 0 : void 0;
|
|
1114
|
+
}
|
|
1115
|
+
function emptySource(text2, node) {
|
|
1116
|
+
const r = rangeOf(node);
|
|
1117
|
+
return !r || text2.slice(r[0], r[1]).trim() === "";
|
|
1118
|
+
}
|
|
1119
|
+
function keyString(key) {
|
|
1120
|
+
return isScalar3(key) ? String(key.value) : String(key);
|
|
1121
|
+
}
|
|
1122
|
+
|
|
800
1123
|
// src/meta/extractors/frontmatter-write.ts
|
|
801
1124
|
var FENCE = {
|
|
802
1125
|
yaml: "---",
|
|
@@ -874,17 +1197,91 @@ function mergeBlock(flavor, inner, patch, deletions = []) {
|
|
|
874
1197
|
}
|
|
875
1198
|
}
|
|
876
1199
|
function mergeYaml(inner, patch, deletions = []) {
|
|
877
|
-
const
|
|
878
|
-
|
|
1200
|
+
const parsed2 = parseYamlBlock2(inner);
|
|
1201
|
+
const root = parsed2.contents;
|
|
1202
|
+
if (root != null && !isMap4(root)) {
|
|
879
1203
|
throw new DocmetaError(
|
|
880
|
-
|
|
1204
|
+
"Cannot rewrite front matter: the root must be a mapping."
|
|
881
1205
|
);
|
|
882
1206
|
}
|
|
883
|
-
if (
|
|
1207
|
+
if (isMap4(root) && root.flow === true) {
|
|
1208
|
+
return reemitYaml(inner, patch, deletions);
|
|
1209
|
+
}
|
|
1210
|
+
let text2 = inner;
|
|
1211
|
+
let first = parsed2;
|
|
1212
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
1213
|
+
const next = spliceYamlKey(text2, key, value, first);
|
|
1214
|
+
first = void 0;
|
|
1215
|
+
if (next === void 0) return reemitYaml(inner, patch, deletions);
|
|
1216
|
+
text2 = next;
|
|
1217
|
+
}
|
|
1218
|
+
for (const key of deletions) {
|
|
1219
|
+
const next = removeYamlKey(text2, key);
|
|
1220
|
+
if (next === void 0) return reemitYaml(inner, patch, deletions);
|
|
1221
|
+
text2 = next;
|
|
1222
|
+
}
|
|
1223
|
+
return text2;
|
|
1224
|
+
}
|
|
1225
|
+
function parseYamlBlock2(text2) {
|
|
1226
|
+
const doc = parseDocument3(text2);
|
|
1227
|
+
if (doc.errors.length > 0) {
|
|
884
1228
|
throw new DocmetaError(
|
|
885
|
-
|
|
1229
|
+
`Cannot rewrite invalid YAML front matter: ${doc.errors[0]?.message ?? "parse error"}`
|
|
886
1230
|
);
|
|
887
1231
|
}
|
|
1232
|
+
return doc;
|
|
1233
|
+
}
|
|
1234
|
+
function rootPair(root, key) {
|
|
1235
|
+
return root.items.find((p) => keyString(p.key) === key);
|
|
1236
|
+
}
|
|
1237
|
+
function spliceYamlKey(text2, key, value, parsed2 = parseYamlBlock2(text2)) {
|
|
1238
|
+
const root = parsed2.contents;
|
|
1239
|
+
const eol = detectEol(text2);
|
|
1240
|
+
if (root == null) {
|
|
1241
|
+
const lines = blockLines({ [key]: value }, 0, { step: 2, indentSeq: true, eol });
|
|
1242
|
+
if (text2 === "") return lines;
|
|
1243
|
+
return text2.endsWith("\n") ? text2 + lines : text2 + eol + lines;
|
|
1244
|
+
}
|
|
1245
|
+
if (!isMap4(root) || root.flow === true) return void 0;
|
|
1246
|
+
const style = detectStyle(text2, root, eol);
|
|
1247
|
+
const pair = rootPair(root, key);
|
|
1248
|
+
let edit;
|
|
1249
|
+
if (pair === void 0) {
|
|
1250
|
+
edit = insertKey(text2, root, key, value, style);
|
|
1251
|
+
} else {
|
|
1252
|
+
const old = pair.value;
|
|
1253
|
+
const isCollectionValue = value !== null && typeof value === "object";
|
|
1254
|
+
if (isCollectionValue && isCollection(old) && old.flow === true) {
|
|
1255
|
+
const r = rangeOf(old);
|
|
1256
|
+
const padded = r !== void 0 && /^[[{][ \t]/.test(text2.slice(r[0], r[0] + 2));
|
|
1257
|
+
edit = replaceFlowValue(text2, pair, value, padded);
|
|
1258
|
+
} else if (!isCollectionValue && isScalar4(old)) {
|
|
1259
|
+
const node = old.clone();
|
|
1260
|
+
if (!isScalar4(node)) return void 0;
|
|
1261
|
+
node.value = value;
|
|
1262
|
+
node.comment = void 0;
|
|
1263
|
+
node.commentBefore = void 0;
|
|
1264
|
+
node.spaceBefore = void 0;
|
|
1265
|
+
edit = replaceBlockValue(text2, pair, node, style);
|
|
1266
|
+
} else {
|
|
1267
|
+
edit = replaceBlockValue(text2, pair, value, style);
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
if (edit === void 0) return void 0;
|
|
1271
|
+
return text2.slice(0, edit.start) + edit.insert + text2.slice(edit.end);
|
|
1272
|
+
}
|
|
1273
|
+
function removeYamlKey(text2, key) {
|
|
1274
|
+
const root = parseYamlBlock2(text2).contents;
|
|
1275
|
+
if (!isMap4(root)) return text2;
|
|
1276
|
+
if (root.flow === true) return void 0;
|
|
1277
|
+
const pair = rootPair(root, key);
|
|
1278
|
+
if (pair === void 0) return text2;
|
|
1279
|
+
const edit = removeKey(text2, pair, detectEol(text2));
|
|
1280
|
+
if (edit === void 0) return void 0;
|
|
1281
|
+
return text2.slice(0, edit.start) + text2.slice(edit.end);
|
|
1282
|
+
}
|
|
1283
|
+
function reemitYaml(inner, patch, deletions) {
|
|
1284
|
+
const doc = parseYamlBlock2(inner);
|
|
888
1285
|
for (const [key, value] of Object.entries(patch)) {
|
|
889
1286
|
if (value !== null && typeof value === "object") {
|
|
890
1287
|
const prev = doc.get(key, true);
|
|
@@ -1041,7 +1438,7 @@ function parseBlock(flavor, text2) {
|
|
|
1041
1438
|
case "toml":
|
|
1042
1439
|
return text2.trim() === "" ? {} : parseToml2(text2);
|
|
1043
1440
|
case "yaml": {
|
|
1044
|
-
const doc =
|
|
1441
|
+
const doc = parseDocument3(text2);
|
|
1045
1442
|
if (doc.errors.length > 0) {
|
|
1046
1443
|
throw new DocmetaError(
|
|
1047
1444
|
`Cannot rewrite invalid YAML front matter: ${doc.errors[0]?.message ?? "parse error"}`
|
|
@@ -1308,8 +1705,8 @@ function ditaShape(content, root, filePath) {
|
|
|
1308
1705
|
const lower = filePath?.toLowerCase() ?? "";
|
|
1309
1706
|
const byExtension2 = (lower.endsWith(".dita") || lower.endsWith(".ditamap")) && DITA_ROOTS.has(name2);
|
|
1310
1707
|
if (!byDoctype && !byClass && !byArch && !byExtension2) return void 0;
|
|
1311
|
-
const
|
|
1312
|
-
return
|
|
1708
|
+
const isMap11 = /^\s*[-+]\s+map\//.test(cls) || MAP_ROOTS.has(name2) || lower.endsWith(".ditamap");
|
|
1709
|
+
return isMap11 ? { kind: "map", container: "topicmeta", preamble: /* @__PURE__ */ new Set(["title"]) } : {
|
|
1313
1710
|
kind: "topic",
|
|
1314
1711
|
container: "metadata",
|
|
1315
1712
|
preamble: /* @__PURE__ */ new Set([
|
|
@@ -2731,8 +3128,8 @@ function listFormats() {
|
|
|
2731
3128
|
}
|
|
2732
3129
|
|
|
2733
3130
|
// src/meta/core/write-file.ts
|
|
2734
|
-
import { writeFile, rename, rm, stat as stat2, chmod } from "node:fs/promises";
|
|
2735
|
-
import { dirname, join, basename, resolve } from "node:path";
|
|
3131
|
+
import { writeFile, rename, rm, stat as stat2, chmod, mkdir } from "node:fs/promises";
|
|
3132
|
+
import { dirname, join, basename, resolve as resolve2 } from "node:path";
|
|
2736
3133
|
|
|
2737
3134
|
// src/meta/core/manifest-cache.ts
|
|
2738
3135
|
import { stat } from "node:fs/promises";
|
|
@@ -2789,15 +3186,16 @@ var RENAME_ATTEMPTS = 3;
|
|
|
2789
3186
|
function errorCode(err) {
|
|
2790
3187
|
return typeof err === "object" && err !== null && "code" in err ? String(err.code) : void 0;
|
|
2791
3188
|
}
|
|
2792
|
-
var wait = (ms) => new Promise((
|
|
2793
|
-
setTimeout(
|
|
3189
|
+
var wait = (ms) => new Promise((resolve23) => {
|
|
3190
|
+
setTimeout(resolve23, ms);
|
|
2794
3191
|
});
|
|
2795
|
-
async function writeFileAtomic(path, contents) {
|
|
3192
|
+
async function writeFileAtomic(path, contents, options = {}) {
|
|
2796
3193
|
const tmp = join(
|
|
2797
3194
|
dirname(path),
|
|
2798
3195
|
`.${basename(path)}.manni-${process.pid}-${Math.random().toString(36).slice(2, 8)}.tmp`
|
|
2799
3196
|
);
|
|
2800
3197
|
try {
|
|
3198
|
+
if (options.createParents === true) await mkdir(dirname(path), { recursive: true });
|
|
2801
3199
|
await writeFile(tmp, contents);
|
|
2802
3200
|
try {
|
|
2803
3201
|
const { mode } = await stat2(path);
|
|
@@ -2827,13 +3225,13 @@ async function writeFileAtomic(path, contents) {
|
|
|
2827
3225
|
}
|
|
2828
3226
|
} finally {
|
|
2829
3227
|
await rm(tmp, { force: true });
|
|
2830
|
-
invalidateManifestCache(
|
|
3228
|
+
invalidateManifestCache(resolve2(path));
|
|
2831
3229
|
}
|
|
2832
3230
|
}
|
|
2833
3231
|
|
|
2834
3232
|
// src/meta/core/schema-cache.ts
|
|
2835
3233
|
import { createHash as createHash2 } from "node:crypto";
|
|
2836
|
-
import { mkdir, readFile, stat as stat3 } from "node:fs/promises";
|
|
3234
|
+
import { mkdir as mkdir2, readFile, stat as stat3 } from "node:fs/promises";
|
|
2837
3235
|
import { join as join2 } from "node:path";
|
|
2838
3236
|
var SCHEMA_CACHE_DIR = ".manni/meta/schema-cache";
|
|
2839
3237
|
var SCHEMA_CACHE_VERSION = 1;
|
|
@@ -2926,7 +3324,7 @@ var SchemaCache = class {
|
|
|
2926
3324
|
schema
|
|
2927
3325
|
};
|
|
2928
3326
|
try {
|
|
2929
|
-
await
|
|
3327
|
+
await mkdir2(this.dir, { recursive: true });
|
|
2930
3328
|
await writeFileAtomic(
|
|
2931
3329
|
this.entryPath(url),
|
|
2932
3330
|
`${JSON.stringify(entry, null, 2)}
|
|
@@ -5344,8 +5742,8 @@ var SCHEMA_KEYS = [
|
|
|
5344
5742
|
"multipleOf"
|
|
5345
5743
|
];
|
|
5346
5744
|
var RETRY_DELAY_MS = 500;
|
|
5347
|
-
var wait2 = (ms) => new Promise((
|
|
5348
|
-
setTimeout(
|
|
5745
|
+
var wait2 = (ms) => new Promise((resolve23) => {
|
|
5746
|
+
setTimeout(resolve23, ms);
|
|
5349
5747
|
});
|
|
5350
5748
|
var RetryableFetchError = class extends DocmetaError {
|
|
5351
5749
|
};
|
|
@@ -5598,7 +5996,7 @@ async function loadSchema(ref, options = {}) {
|
|
|
5598
5996
|
}
|
|
5599
5997
|
|
|
5600
5998
|
// src/meta/core/resolve-schema.ts
|
|
5601
|
-
import { isAbsolute, relative, resolve as
|
|
5999
|
+
import { isAbsolute as isAbsolute2, relative as relative2, resolve as resolve3 } from "node:path";
|
|
5602
6000
|
var DEFAULT_SCHEMAS = Object.freeze([
|
|
5603
6001
|
"google:okf:0.1",
|
|
5604
6002
|
"passo-uno:seven-action:1.0"
|
|
@@ -5620,8 +6018,8 @@ function collectSchemaPins(config) {
|
|
|
5620
6018
|
return pins;
|
|
5621
6019
|
}
|
|
5622
6020
|
function rebaseConfigSchemaRefs(config, configDir, cwd) {
|
|
5623
|
-
if (
|
|
5624
|
-
const rebase2 = (ref) => classifyRef(ref).kind === "file" && !
|
|
6021
|
+
if (resolve3(configDir) === resolve3(cwd)) return config;
|
|
6022
|
+
const rebase2 = (ref) => classifyRef(ref).kind === "file" && !isAbsolute2(ref) ? resolve3(configDir, ref) : ref;
|
|
5625
6023
|
const rebaseEntry = (entry) => typeof entry === "string" ? rebase2(entry) : {
|
|
5626
6024
|
...entry,
|
|
5627
6025
|
ref: rebase2(entry.ref),
|
|
@@ -5697,9 +6095,9 @@ function assertDocumentRefAllowed(ref, mode, params) {
|
|
|
5697
6095
|
}
|
|
5698
6096
|
const root = params.trustRoot;
|
|
5699
6097
|
if (!root) return;
|
|
5700
|
-
const abs =
|
|
5701
|
-
const within =
|
|
5702
|
-
if (within !== "" && !within.startsWith("..") && !
|
|
6098
|
+
const abs = resolve3(params.fileBase ?? process.cwd(), ref);
|
|
6099
|
+
const within = relative2(root.dir, abs);
|
|
6100
|
+
if (within !== "" && !within.startsWith("..") && !isAbsolute2(within)) return;
|
|
5703
6101
|
const boundary = root.source === "git" ? `the repository root (${root.dir})` : root.source === "config" ? `${root.dir} \u2014 no git repository was found, so the config file's own directory is the boundary` : `${root.dir} \u2014 no git repository and no config file were found, so the directory the command was run from is the boundary`;
|
|
5704
6102
|
const scope = root.source === "git" ? "the repository" : "the project";
|
|
5705
6103
|
throw new DocmetaError(
|
|
@@ -5849,12 +6247,12 @@ function isPlainObject(v) {
|
|
|
5849
6247
|
}
|
|
5850
6248
|
|
|
5851
6249
|
// src/meta/core/config.ts
|
|
5852
|
-
import { resolve as
|
|
6250
|
+
import { resolve as resolve7 } from "node:path";
|
|
5853
6251
|
import { parse as parseYaml2 } from "yaml";
|
|
5854
6252
|
|
|
5855
6253
|
// src/shared/config-file.ts
|
|
5856
6254
|
import { readFile as readFile3 } from "node:fs/promises";
|
|
5857
|
-
import { basename as basename2, dirname as dirname3, join as join4, relative as
|
|
6255
|
+
import { basename as basename2, dirname as dirname3, join as join4, relative as relative3, resolve as resolve6 } from "node:path";
|
|
5858
6256
|
import { parse as parseYaml } from "yaml";
|
|
5859
6257
|
|
|
5860
6258
|
// src/shared/encryption.ts
|
|
@@ -5985,9 +6383,9 @@ function keyedPin(text2, key) {
|
|
|
5985
6383
|
|
|
5986
6384
|
// src/shared/git-root.ts
|
|
5987
6385
|
import { existsSync } from "node:fs";
|
|
5988
|
-
import { dirname as dirname2, join as join3, resolve as
|
|
6386
|
+
import { dirname as dirname2, join as join3, resolve as resolve4 } from "node:path";
|
|
5989
6387
|
function findGitRoot(cwd) {
|
|
5990
|
-
let dir =
|
|
6388
|
+
let dir = resolve4(cwd);
|
|
5991
6389
|
for (; ; ) {
|
|
5992
6390
|
if (existsSync(join3(dir, ".git"))) return dir;
|
|
5993
6391
|
const parent = dirname2(dir);
|
|
@@ -5996,7 +6394,7 @@ function findGitRoot(cwd) {
|
|
|
5996
6394
|
}
|
|
5997
6395
|
}
|
|
5998
6396
|
function searchPath(cwd) {
|
|
5999
|
-
const start =
|
|
6397
|
+
const start = resolve4(cwd);
|
|
6000
6398
|
const root = findGitRoot(start);
|
|
6001
6399
|
if (root === null) return [start];
|
|
6002
6400
|
const chain = [];
|
|
@@ -6011,7 +6409,7 @@ function searchPath(cwd) {
|
|
|
6011
6409
|
}
|
|
6012
6410
|
|
|
6013
6411
|
// src/shared/tools.ts
|
|
6014
|
-
import { isAbsolute as
|
|
6412
|
+
import { isAbsolute as isAbsolute3, resolve as resolve5 } from "node:path";
|
|
6015
6413
|
var TOOL_KEYS = ["vale"];
|
|
6016
6414
|
var VALE_KEYS = ["config"];
|
|
6017
6415
|
function isMapping2(value) {
|
|
@@ -6056,7 +6454,7 @@ function parseVale(raw, source, toError) {
|
|
|
6056
6454
|
function valeConfigPath(tools, configDir) {
|
|
6057
6455
|
const config = tools.vale?.config;
|
|
6058
6456
|
if (config === void 0) return void 0;
|
|
6059
|
-
return
|
|
6457
|
+
return isAbsolute3(config) ? config : resolve5(configDir, config);
|
|
6060
6458
|
}
|
|
6061
6459
|
|
|
6062
6460
|
// src/shared/warn.ts
|
|
@@ -6161,7 +6559,7 @@ function tolerantKeysOf(document) {
|
|
|
6161
6559
|
};
|
|
6162
6560
|
}
|
|
6163
6561
|
function relativeSource(cwd, path) {
|
|
6164
|
-
return
|
|
6562
|
+
return relative3(cwd, path).replace(/\\/g, "/");
|
|
6165
6563
|
}
|
|
6166
6564
|
function mooseWarning(name2) {
|
|
6167
6565
|
return `"${name2}" is the pre-rename name of the family config file. Rename it to "${FAMILY_CONFIG_NAMES[0] ?? "manni.config.yaml"}".`;
|
|
@@ -6171,7 +6569,7 @@ var FAMILY_FILES = [
|
|
|
6171
6569
|
{ names: MOOSE_CONFIG_NAMES, kind: "moose" }
|
|
6172
6570
|
];
|
|
6173
6571
|
async function findConfigFile(cwd, opts) {
|
|
6174
|
-
const start =
|
|
6572
|
+
const start = resolve6(cwd);
|
|
6175
6573
|
for (const dir of searchPath(start)) {
|
|
6176
6574
|
for (const { names, kind } of FAMILY_FILES) {
|
|
6177
6575
|
for (const name2 of names) {
|
|
@@ -6219,7 +6617,7 @@ async function findConfigFile(cwd, opts) {
|
|
|
6219
6617
|
return null;
|
|
6220
6618
|
}
|
|
6221
6619
|
async function readConfigFile(explicitPath, cwd, opts) {
|
|
6222
|
-
const path =
|
|
6620
|
+
const path = resolve6(cwd, explicitPath);
|
|
6223
6621
|
const document = await readDocument(path, explicitPath, opts.toError);
|
|
6224
6622
|
if (document === null) {
|
|
6225
6623
|
throw opts.toError(`Config file not found: "${explicitPath}".`);
|
|
@@ -6243,7 +6641,7 @@ async function readConfigFile(explicitPath, cwd, opts) {
|
|
|
6243
6641
|
};
|
|
6244
6642
|
}
|
|
6245
6643
|
async function findFamilyConfigFile(cwd, toError) {
|
|
6246
|
-
const start =
|
|
6644
|
+
const start = resolve6(cwd);
|
|
6247
6645
|
for (const dir of searchPath(start)) {
|
|
6248
6646
|
for (const { names, kind } of FAMILY_FILES) {
|
|
6249
6647
|
for (const name2 of names) {
|
|
@@ -6270,7 +6668,7 @@ async function findFamilyConfigFile(cwd, toError) {
|
|
|
6270
6668
|
return null;
|
|
6271
6669
|
}
|
|
6272
6670
|
async function readFamilyConfigFile(explicitPath, cwd, toError) {
|
|
6273
|
-
const path =
|
|
6671
|
+
const path = resolve6(cwd, explicitPath);
|
|
6274
6672
|
const document = await readDocument(path, explicitPath, toError);
|
|
6275
6673
|
if (document === null) {
|
|
6276
6674
|
throw toError(`Config file not found: "${explicitPath}".`);
|
|
@@ -6939,8 +7337,8 @@ function parseFill(value, source) {
|
|
|
6939
7337
|
function schemaTrustRoot(cwd, configDir) {
|
|
6940
7338
|
const git2 = findGitRoot(cwd);
|
|
6941
7339
|
if (git2 !== null) return { dir: git2, source: "git" };
|
|
6942
|
-
if (configDir !== void 0) return { dir:
|
|
6943
|
-
return { dir:
|
|
7340
|
+
if (configDir !== void 0) return { dir: resolve7(configDir), source: "config" };
|
|
7341
|
+
return { dir: resolve7(cwd), source: "cwd" };
|
|
6944
7342
|
}
|
|
6945
7343
|
async function loadConfig(explicitPath, cwd = process.cwd()) {
|
|
6946
7344
|
const file = explicitPath ? await readConfigFile(explicitPath, cwd, CONFIG_FILE) : await findConfigFile(cwd, CONFIG_FILE);
|
|
@@ -7003,23 +7401,23 @@ async function resolveRunConfig(opts) {
|
|
|
7003
7401
|
}
|
|
7004
7402
|
|
|
7005
7403
|
// src/meta/reporters/sarif.ts
|
|
7006
|
-
import { isAbsolute as
|
|
7404
|
+
import { isAbsolute as isAbsolute4 } from "node:path";
|
|
7007
7405
|
|
|
7008
7406
|
// src/meta/core/baseline.ts
|
|
7009
7407
|
import { createHash as createHash3 } from "node:crypto";
|
|
7010
7408
|
import { existsSync as existsSync2 } from "node:fs";
|
|
7011
7409
|
import { readFile as readFile4 } from "node:fs/promises";
|
|
7012
|
-
import { relative as
|
|
7410
|
+
import { relative as relative6, resolve as resolve10 } from "node:path";
|
|
7013
7411
|
|
|
7014
7412
|
// src/meta/core/load-files.ts
|
|
7015
7413
|
import { stat as stat4 } from "node:fs/promises";
|
|
7016
|
-
import { extname, relative as
|
|
7017
|
-
import
|
|
7414
|
+
import { extname, relative as relative5, resolve as resolve9 } from "node:path";
|
|
7415
|
+
import fg2 from "fast-glob";
|
|
7018
7416
|
import picomatch3 from "picomatch";
|
|
7019
7417
|
|
|
7020
7418
|
// src/meta/core/gitignore.ts
|
|
7021
7419
|
import { spawn } from "node:child_process";
|
|
7022
|
-
import { dirname as dirname4, relative as
|
|
7420
|
+
import { dirname as dirname4, relative as relative4, resolve as resolve8, sep as sep2 } from "node:path";
|
|
7023
7421
|
var GITIGNORE_UNAVAILABLE = ".gitignore filtering was requested but git could not answer here (no repository, or no git on PATH); no files were skipped.";
|
|
7024
7422
|
var unavailable = () => ({
|
|
7025
7423
|
ignored: /* @__PURE__ */ new Set(),
|
|
@@ -7033,7 +7431,7 @@ async function gitIgnored(paths, cwd) {
|
|
|
7033
7431
|
const byRoot = /* @__PURE__ */ new Map();
|
|
7034
7432
|
let inSomeRepo = false;
|
|
7035
7433
|
for (const spelled of paths) {
|
|
7036
|
-
const abs =
|
|
7434
|
+
const abs = resolve8(cwd, spelled);
|
|
7037
7435
|
const dir = dirname4(abs);
|
|
7038
7436
|
let root = rootOf.get(dir);
|
|
7039
7437
|
if (root === void 0) {
|
|
@@ -7042,7 +7440,7 @@ async function gitIgnored(paths, cwd) {
|
|
|
7042
7440
|
}
|
|
7043
7441
|
if (root === null) continue;
|
|
7044
7442
|
inSomeRepo = true;
|
|
7045
|
-
const rel =
|
|
7443
|
+
const rel = relative4(root, abs).split(sep2).join("/");
|
|
7046
7444
|
const bucket = byRoot.get(root);
|
|
7047
7445
|
if (bucket) bucket.push({ rel, spelled });
|
|
7048
7446
|
else byRoot.set(root, [{ rel, spelled }]);
|
|
@@ -7145,14 +7543,14 @@ async function resolveTargetSet(opts) {
|
|
|
7145
7543
|
for (const input of opts.inputs) {
|
|
7146
7544
|
if (input === STDIN_TOKEN) continue;
|
|
7147
7545
|
const posixInput = toPosix(input);
|
|
7148
|
-
const abs =
|
|
7546
|
+
const abs = resolve9(cwd, posixInput);
|
|
7149
7547
|
const st = await statOrNull(abs);
|
|
7150
7548
|
if (st?.isFile()) {
|
|
7151
|
-
named.add(toPosix(
|
|
7549
|
+
named.add(toPosix(relative5(cwd, abs)));
|
|
7152
7550
|
continue;
|
|
7153
7551
|
}
|
|
7154
7552
|
if (st?.isDirectory()) {
|
|
7155
|
-
const found2 = await
|
|
7553
|
+
const found2 = await fg2(`${posixInput}/**/*`, {
|
|
7156
7554
|
cwd,
|
|
7157
7555
|
ignore,
|
|
7158
7556
|
onlyFiles: true,
|
|
@@ -7165,7 +7563,7 @@ async function resolveTargetSet(opts) {
|
|
|
7165
7563
|
missing.push(posixInput);
|
|
7166
7564
|
continue;
|
|
7167
7565
|
}
|
|
7168
|
-
const found = await
|
|
7566
|
+
const found = await fg2(posixInput, {
|
|
7169
7567
|
cwd,
|
|
7170
7568
|
ignore,
|
|
7171
7569
|
onlyFiles: true,
|
|
@@ -7230,13 +7628,13 @@ var FINGERPRINT_RE = /^[0-9a-f]{16}$/;
|
|
|
7230
7628
|
function canonicalFilePath(file, ctx) {
|
|
7231
7629
|
if (!ctx) return file;
|
|
7232
7630
|
const from = ctx.runBase ?? ctx.base;
|
|
7233
|
-
return
|
|
7631
|
+
return relative6(ctx.base, resolve10(from, file)).replace(/\\/g, "/");
|
|
7234
7632
|
}
|
|
7235
7633
|
function canonicalSchemaRef(ref, ctx) {
|
|
7236
7634
|
if (!ctx) return ref;
|
|
7237
7635
|
if (classifyRef(ref).kind !== "file") return ref;
|
|
7238
|
-
const abs =
|
|
7239
|
-
return
|
|
7636
|
+
const abs = resolve10(ctx.cwd, ref);
|
|
7637
|
+
return relative6(ctx.base, abs).replace(/\\/g, "/");
|
|
7240
7638
|
}
|
|
7241
7639
|
function fingerprint(e, ctx) {
|
|
7242
7640
|
const parts = [
|
|
@@ -7393,17 +7791,17 @@ function countFingerprints(baseline) {
|
|
|
7393
7791
|
}
|
|
7394
7792
|
function resolveBaselineRequest(opts, configured, configDir, cwd, defaults) {
|
|
7395
7793
|
const named = (label) => ({
|
|
7396
|
-
absPath:
|
|
7794
|
+
absPath: resolve10(cwd, label),
|
|
7397
7795
|
label
|
|
7398
7796
|
});
|
|
7399
7797
|
const implied = () => {
|
|
7400
7798
|
const base = configDir ?? cwd;
|
|
7401
7799
|
if (configured !== void 0) {
|
|
7402
|
-
return { absPath:
|
|
7800
|
+
return { absPath: resolve10(base, configured), label: configured };
|
|
7403
7801
|
}
|
|
7404
|
-
const current =
|
|
7802
|
+
const current = resolve10(base, defaults.current);
|
|
7405
7803
|
if (defaults.legacy !== void 0) {
|
|
7406
|
-
const legacy =
|
|
7804
|
+
const legacy = resolve10(base, defaults.legacy);
|
|
7407
7805
|
if (!existsSync2(current) && existsSync2(legacy)) {
|
|
7408
7806
|
warn(
|
|
7409
7807
|
`"${defaults.legacy}" is the pre-rename baseline file name. Rename it to "${defaults.current}".`
|
|
@@ -7516,7 +7914,7 @@ function uriFrame(frame) {
|
|
|
7516
7914
|
}
|
|
7517
7915
|
function artifactUri(file, frame) {
|
|
7518
7916
|
const uri = canonicalFilePath(file, frame);
|
|
7519
|
-
if (uri === "" || uri.startsWith("../") ||
|
|
7917
|
+
if (uri === "" || uri.startsWith("../") || isAbsolute4(uri)) return null;
|
|
7520
7918
|
return uri;
|
|
7521
7919
|
}
|
|
7522
7920
|
function renderSarif(results, opts = {}) {
|
|
@@ -7910,22 +8308,92 @@ async function readCapped(url, res, maxBytes) {
|
|
|
7910
8308
|
|
|
7911
8309
|
// src/meta/core/external-metadata.ts
|
|
7912
8310
|
import { readFile as readFile6 } from "node:fs/promises";
|
|
7913
|
-
import { isAbsolute as
|
|
8311
|
+
import { isAbsolute as isAbsolute5, relative as relative8, resolve as resolve12, sep as sep3 } from "node:path";
|
|
7914
8312
|
import {
|
|
7915
|
-
LineCounter as
|
|
7916
|
-
isMap as
|
|
7917
|
-
isNode,
|
|
7918
|
-
isScalar as
|
|
7919
|
-
isSeq as
|
|
7920
|
-
parseDocument as
|
|
8313
|
+
LineCounter as LineCounter3,
|
|
8314
|
+
isMap as isMap6,
|
|
8315
|
+
isNode as isNode3,
|
|
8316
|
+
isScalar as isScalar5,
|
|
8317
|
+
isSeq as isSeq3,
|
|
8318
|
+
parseDocument as parseDocument5
|
|
7921
8319
|
} from "yaml";
|
|
7922
8320
|
|
|
8321
|
+
// src/shared/manifest-cas.ts
|
|
8322
|
+
import { posix as posix3 } from "node:path";
|
|
8323
|
+
var COMMIT_ATTEMPTS = 5;
|
|
8324
|
+
function conflictRefusal(file) {
|
|
8325
|
+
return `${file} changed under the command while it was being written. Nothing was written to it. Re-run the command.`;
|
|
8326
|
+
}
|
|
8327
|
+
function heldManifest(path, file, before, absent = false) {
|
|
8328
|
+
return { path, file, before, text: before, ops: [], bases: /* @__PURE__ */ new Map(), absent };
|
|
8329
|
+
}
|
|
8330
|
+
function encodeValue(value) {
|
|
8331
|
+
return value === void 0 ? "absent" : JSON.stringify(value);
|
|
8332
|
+
}
|
|
8333
|
+
function baseKey(at2) {
|
|
8334
|
+
const entry = at2.join === "path" ? posix3.normalize(at2.entry) : at2.entry;
|
|
8335
|
+
return `${entry}\0${at2.key}`;
|
|
8336
|
+
}
|
|
8337
|
+
function rebaseable(held, op, codec) {
|
|
8338
|
+
const at2 = baseKey(op);
|
|
8339
|
+
if (held.bases.has(at2)) return;
|
|
8340
|
+
held.bases.set(at2, {
|
|
8341
|
+
entry: op.entry,
|
|
8342
|
+
key: op.key,
|
|
8343
|
+
join: op.join,
|
|
8344
|
+
value: encodeValue(codec.read(held.before, op))
|
|
8345
|
+
});
|
|
8346
|
+
}
|
|
8347
|
+
function rebase(held, current, codec) {
|
|
8348
|
+
for (const base of held.bases.values()) {
|
|
8349
|
+
if (encodeValue(codec.read(current, base)) !== base.value) return void 0;
|
|
8350
|
+
}
|
|
8351
|
+
let text2 = current;
|
|
8352
|
+
for (const op of held.ops) text2 = codec.apply(text2, op);
|
|
8353
|
+
return text2;
|
|
8354
|
+
}
|
|
8355
|
+
function rebaseline(held) {
|
|
8356
|
+
held.before = held.text;
|
|
8357
|
+
held.ops = [];
|
|
8358
|
+
held.bases.clear();
|
|
8359
|
+
held.absent = false;
|
|
8360
|
+
}
|
|
8361
|
+
async function settle(held, io) {
|
|
8362
|
+
for (let attempt = 1; attempt <= COMMIT_ATTEMPTS; attempt++) {
|
|
8363
|
+
let current;
|
|
8364
|
+
try {
|
|
8365
|
+
current = await io.read(held.path);
|
|
8366
|
+
} catch (error) {
|
|
8367
|
+
if (held.absent && isMissing(error)) {
|
|
8368
|
+
await io.write(held.path, held.text);
|
|
8369
|
+
held.absent = false;
|
|
8370
|
+
return;
|
|
8371
|
+
}
|
|
8372
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
8373
|
+
throw io.toError(`Manifest ${held.file} could not be read: ${reason}`);
|
|
8374
|
+
}
|
|
8375
|
+
if (!held.absent && current === held.before) {
|
|
8376
|
+
await io.write(held.path, held.text);
|
|
8377
|
+
return;
|
|
8378
|
+
}
|
|
8379
|
+
const replayed = rebase(held, current, io.codec);
|
|
8380
|
+
if (replayed === void 0) throw io.toError(conflictRefusal(held.file));
|
|
8381
|
+
held.before = current;
|
|
8382
|
+
held.text = replayed;
|
|
8383
|
+
held.absent = false;
|
|
8384
|
+
}
|
|
8385
|
+
throw io.toError(conflictRefusal(held.file));
|
|
8386
|
+
}
|
|
8387
|
+
function isMissing(error) {
|
|
8388
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
8389
|
+
}
|
|
8390
|
+
|
|
7923
8391
|
// src/shared/encryption-key.ts
|
|
7924
8392
|
import { spawnSync } from "node:child_process";
|
|
7925
8393
|
import { readFile as readFile5 } from "node:fs/promises";
|
|
7926
|
-
import { basename as basename4, dirname as dirname6, join as join6, relative as
|
|
8394
|
+
import { basename as basename4, dirname as dirname6, join as join6, relative as relative7, resolve as resolve11 } from "node:path";
|
|
7927
8395
|
import { isDeepStrictEqual } from "node:util";
|
|
7928
|
-
import { isMap as
|
|
8396
|
+
import { isMap as isMap5, parseDocument as parseDocument4, parse as parseYaml3, stringify as stringify2 } from "yaml";
|
|
7929
8397
|
|
|
7930
8398
|
// src/shared/write-file.ts
|
|
7931
8399
|
import { chmod as chmod2, rename as rename2, rm as rm2, stat as stat5, writeFile as writeFile2 } from "node:fs/promises";
|
|
@@ -7935,8 +8403,8 @@ var RENAME_ATTEMPTS2 = 3;
|
|
|
7935
8403
|
function errorCode2(err) {
|
|
7936
8404
|
return typeof err === "object" && err !== null && "code" in err ? String(err.code) : void 0;
|
|
7937
8405
|
}
|
|
7938
|
-
var wait3 = (ms) => new Promise((
|
|
7939
|
-
setTimeout(
|
|
8406
|
+
var wait3 = (ms) => new Promise((resolve23) => {
|
|
8407
|
+
setTimeout(resolve23, ms);
|
|
7940
8408
|
});
|
|
7941
8409
|
async function writeTextAtomic(path, text2) {
|
|
7942
8410
|
const tmp = join5(
|
|
@@ -7985,7 +8453,7 @@ function resolveEncryptionKey(opts) {
|
|
|
7985
8453
|
return { key: void 0, source: "none" };
|
|
7986
8454
|
}
|
|
7987
8455
|
function relativeSource2(cwd, path) {
|
|
7988
|
-
return
|
|
8456
|
+
return relative7(resolve11(cwd), path).replace(/\\/g, "/");
|
|
7989
8457
|
}
|
|
7990
8458
|
function errorCode3(err) {
|
|
7991
8459
|
return typeof err === "object" && err !== null && "code" in err ? String(err.code) : void 0;
|
|
@@ -8008,7 +8476,7 @@ async function fileTarget(file, toError) {
|
|
|
8008
8476
|
return { path: file.path, source: file.source, text: text2 ?? file.text };
|
|
8009
8477
|
}
|
|
8010
8478
|
async function defaultTarget(cwd) {
|
|
8011
|
-
const root = findGitRoot(cwd) ??
|
|
8479
|
+
const root = findGitRoot(cwd) ?? resolve11(cwd);
|
|
8012
8480
|
for (const name2 of [...FAMILY_CONFIG_NAMES, ...MOOSE_CONFIG_NAMES]) {
|
|
8013
8481
|
const path2 = join6(root, name2);
|
|
8014
8482
|
const text2 = await readIfPresent(path2);
|
|
@@ -8018,12 +8486,12 @@ async function defaultTarget(cwd) {
|
|
|
8018
8486
|
return { path, source: relativeSource2(cwd, path), text: null };
|
|
8019
8487
|
}
|
|
8020
8488
|
function withKey(text2, key, previous, source, toError) {
|
|
8021
|
-
const doc =
|
|
8489
|
+
const doc = parseDocument4(text2);
|
|
8022
8490
|
const [first] = doc.errors;
|
|
8023
8491
|
if (first !== void 0) {
|
|
8024
8492
|
throw toError(`${source}: invalid YAML: ${first.message}`);
|
|
8025
8493
|
}
|
|
8026
|
-
if (doc.contents !== null && !
|
|
8494
|
+
if (doc.contents !== null && !isMap5(doc.contents)) {
|
|
8027
8495
|
throw toError(`${source}: top level must be a mapping.`);
|
|
8028
8496
|
}
|
|
8029
8497
|
doc.set(ENCRYPTION_KEY_FIELD, key);
|
|
@@ -8063,7 +8531,7 @@ async function writeEncryptionKey(opts) {
|
|
|
8063
8531
|
);
|
|
8064
8532
|
}
|
|
8065
8533
|
const target = file === null ? await defaultTarget(opts.cwd) : await fileTarget(file, toError);
|
|
8066
|
-
const text2 = target.text === null ?
|
|
8534
|
+
const text2 = target.text === null ? stringify2({
|
|
8067
8535
|
[ENCRYPTION_KEY_FIELD]: key,
|
|
8068
8536
|
...typeof previous === "string" ? { [ENCRYPTION_KEY_PREVIOUS_FIELD]: previous } : {}
|
|
8069
8537
|
}) : withKey(target.text, key, previous, target.source, toError);
|
|
@@ -8293,18 +8761,20 @@ function redactedDerived(f) {
|
|
|
8293
8761
|
var EXTERNAL_OWNED_SCHEMA = "external:owned";
|
|
8294
8762
|
var EXTERNAL_DUPLICATE_SCHEMA = "external:duplicate";
|
|
8295
8763
|
var EXTERNAL_KEYWORD = "external";
|
|
8296
|
-
var
|
|
8764
|
+
var PATH_JOIN2 = "path";
|
|
8297
8765
|
var parsedManifests = new ManifestCache();
|
|
8298
|
-
var
|
|
8766
|
+
var perPageRules = /* @__PURE__ */ new WeakMap();
|
|
8767
|
+
var strayEntries = /* @__PURE__ */ new WeakSet();
|
|
8768
|
+
var posix4 = (p) => p.split(sep3).join("/");
|
|
8299
8769
|
function reportedPath(abs, base) {
|
|
8300
|
-
const rel =
|
|
8301
|
-
return rel === "" ? "." :
|
|
8770
|
+
const rel = relative8(base, abs);
|
|
8771
|
+
return rel === "" ? "." : posix4(rel);
|
|
8302
8772
|
}
|
|
8303
8773
|
function reported(of, file) {
|
|
8304
8774
|
return of.file === file ? of : { ...of, file };
|
|
8305
8775
|
}
|
|
8306
8776
|
function externalMetadataJoin(manifest) {
|
|
8307
|
-
return manifest.join ??
|
|
8777
|
+
return manifest.join ?? PATH_JOIN2;
|
|
8308
8778
|
}
|
|
8309
8779
|
async function loadExternalMetadata(collections, opts) {
|
|
8310
8780
|
const configured = collections.flatMap(
|
|
@@ -8315,7 +8785,17 @@ async function loadExternalMetadata(collections, opts) {
|
|
|
8315
8785
|
const byPath = /* @__PURE__ */ new Map();
|
|
8316
8786
|
const byField = /* @__PURE__ */ new Map();
|
|
8317
8787
|
const entries = [];
|
|
8788
|
+
const resolvedBy = /* @__PURE__ */ new Map();
|
|
8789
|
+
const rules = [];
|
|
8318
8790
|
for (const { collection, manifest } of configured) {
|
|
8791
|
+
const declared = collections.find(
|
|
8792
|
+
(c) => c.name === collection && c.externalMetadata.includes(manifest)
|
|
8793
|
+
);
|
|
8794
|
+
if (declared !== void 0 && classifyRef(manifest.file).kind !== "url" && hasPagePlaceholder(manifest.file)) {
|
|
8795
|
+
await loadPerPage(declared, manifest, opts, resolvedBy, { owners, byPath, byField, entries });
|
|
8796
|
+
rules.push({ collection: declared, manifest, configDir: opts.configDir });
|
|
8797
|
+
continue;
|
|
8798
|
+
}
|
|
8319
8799
|
const join11 = externalMetadataJoin(manifest);
|
|
8320
8800
|
let parsed2;
|
|
8321
8801
|
let file;
|
|
@@ -8329,7 +8809,7 @@ async function loadExternalMetadata(collections, opts) {
|
|
|
8329
8809
|
});
|
|
8330
8810
|
parsed2 = parseManifest(manifest, collection, text2, file, opts.configDir, join11);
|
|
8331
8811
|
} else {
|
|
8332
|
-
const abs =
|
|
8812
|
+
const abs = isAbsolute5(manifest.file) ? manifest.file : resolve12(opts.configDir, manifest.file);
|
|
8333
8813
|
const label = reportedPath(abs, opts.base);
|
|
8334
8814
|
file = label;
|
|
8335
8815
|
parsed2 = await parsedManifests.parse(
|
|
@@ -8367,7 +8847,7 @@ async function loadExternalMetadata(collections, opts) {
|
|
|
8367
8847
|
else owners.set(key, [{ collection, file }]);
|
|
8368
8848
|
}
|
|
8369
8849
|
let target;
|
|
8370
|
-
if (join11 ===
|
|
8850
|
+
if (join11 === PATH_JOIN2) {
|
|
8371
8851
|
target = byPath;
|
|
8372
8852
|
} else {
|
|
8373
8853
|
const existing = byField.get(join11);
|
|
@@ -8384,23 +8864,112 @@ async function loadExternalMetadata(collections, opts) {
|
|
|
8384
8864
|
}
|
|
8385
8865
|
for (const entry of parsed2.entries) entries.push(reported(entry, file));
|
|
8386
8866
|
}
|
|
8387
|
-
|
|
8867
|
+
const index = { owners, byPath, byField, entries };
|
|
8868
|
+
if (rules.length > 0) perPageRules.set(index, rules);
|
|
8869
|
+
return index;
|
|
8870
|
+
}
|
|
8871
|
+
async function loadPerPage(declared, manifest, opts, resolvedBy, into) {
|
|
8872
|
+
const collection = declared.name;
|
|
8873
|
+
const join11 = externalMetadataJoin(manifest);
|
|
8874
|
+
for (const key of manifest.keys) {
|
|
8875
|
+
const list2 = into.owners.get(key);
|
|
8876
|
+
if (list2) list2.push({ collection, file: manifest.file });
|
|
8877
|
+
else into.owners.set(key, [{ collection, file: manifest.file }]);
|
|
8878
|
+
}
|
|
8879
|
+
const target = indexFor(join11, into);
|
|
8880
|
+
for (const pageAbs of opts.pages ?? []) {
|
|
8881
|
+
const resolved = pageManifestPath(manifest.file, opts.configDir, pageAbs);
|
|
8882
|
+
if ("outside" in resolved) {
|
|
8883
|
+
if (resolved.pageRel.startsWith("../") && matchesCollectionPaths(declared, resolved.pageRel)) {
|
|
8884
|
+
throw new DocmetaError(outsideRefusal(manifest, collection, resolved.pageRel));
|
|
8885
|
+
}
|
|
8886
|
+
continue;
|
|
8887
|
+
}
|
|
8888
|
+
const rel = posix4(relative8(opts.configDir, pageAbs));
|
|
8889
|
+
if (!isMember(declared, rel)) continue;
|
|
8890
|
+
const earlier = resolvedBy.get(resolved.abs);
|
|
8891
|
+
if (earlier !== void 0 && earlier !== pageAbs) {
|
|
8892
|
+
const [a, b] = [reportedPath(earlier, opts.base), reportedPath(pageAbs, opts.base)].sort();
|
|
8893
|
+
throw new DocmetaError(
|
|
8894
|
+
`${a ?? ""} and ${b ?? ""} both resolve ${PAGE_PLACEHOLDER} to ${reportedPath(resolved.abs, opts.base)}. A ${PAGE_PLACEHOLDER} manifest names one page, so rename one of them.`
|
|
8895
|
+
);
|
|
8896
|
+
}
|
|
8897
|
+
resolvedBy.set(resolved.abs, pageAbs);
|
|
8898
|
+
const label = reportedPath(resolved.abs, opts.base);
|
|
8899
|
+
const parsed2 = await parsedManifests.parse(
|
|
8900
|
+
resolved.abs,
|
|
8901
|
+
JSON.stringify([collection, join11, opts.configDir, [...manifest.keys].sort()]),
|
|
8902
|
+
async () => parseManifest(
|
|
8903
|
+
manifest,
|
|
8904
|
+
collection,
|
|
8905
|
+
await readPageManifest(resolved.abs, label),
|
|
8906
|
+
label,
|
|
8907
|
+
opts.configDir,
|
|
8908
|
+
join11
|
|
8909
|
+
)
|
|
8910
|
+
);
|
|
8911
|
+
const pageLabel = reportedPath(pageAbs, opts.base);
|
|
8912
|
+
for (const entry of parsed2.entries) {
|
|
8913
|
+
if (entry.abs === void 0 || sameFile(entry.abs, pageAbs)) continue;
|
|
8914
|
+
const at2 = entry.line === void 0 ? label : `${label}:${String(entry.line)}`;
|
|
8915
|
+
throw new DocmetaError(
|
|
8916
|
+
`Manifest ${at2} names "${entry.spelled}", but ${PAGE_PLACEHOLDER} resolved this file for "${pageLabel}". A per-page manifest holds one entry, for its own page.`
|
|
8917
|
+
);
|
|
8918
|
+
}
|
|
8919
|
+
for (const [indexKey, values] of parsed2.values) {
|
|
8920
|
+
const key = join11 === PATH_JOIN2 ? pageAbs : indexKey;
|
|
8921
|
+
const merged = target.get(key) ?? /* @__PURE__ */ new Map();
|
|
8922
|
+
for (const [owned, value] of values) merged.set(owned, reported(value, label));
|
|
8923
|
+
target.set(key, merged);
|
|
8924
|
+
}
|
|
8925
|
+
for (const entry of parsed2.entries) {
|
|
8926
|
+
into.entries.push({
|
|
8927
|
+
...reported(entry, label),
|
|
8928
|
+
...entry.abs === void 0 ? {} : { abs: pageAbs }
|
|
8929
|
+
});
|
|
8930
|
+
}
|
|
8931
|
+
}
|
|
8932
|
+
}
|
|
8933
|
+
function indexFor(join11, into) {
|
|
8934
|
+
if (join11 === PATH_JOIN2) return into.byPath;
|
|
8935
|
+
const existing = into.byField.get(join11);
|
|
8936
|
+
if (existing) return existing;
|
|
8937
|
+
const created = /* @__PURE__ */ new Map();
|
|
8938
|
+
into.byField.set(join11, created);
|
|
8939
|
+
return created;
|
|
8940
|
+
}
|
|
8941
|
+
function outsideRefusal(manifest, collection, pageRel) {
|
|
8942
|
+
const tail = `for "${pageRel}". A ${PAGE_PLACEHOLDER} manifest stays under the config file.`;
|
|
8943
|
+
const origin = externalMetadataOrigin(manifest);
|
|
8944
|
+
if (origin === void 0) {
|
|
8945
|
+
return `externalMetadata file "${manifest.file}" of collection ${collection} resolves outside the config file's directory ${tail}`;
|
|
8946
|
+
}
|
|
8947
|
+
return `${origin.source}: ${origin.where}.file resolves outside ${origin.source}'s directory ${tail}`;
|
|
8948
|
+
}
|
|
8949
|
+
async function readPageManifest(abs, file) {
|
|
8950
|
+
try {
|
|
8951
|
+
return await readFile6(abs, "utf8");
|
|
8952
|
+
} catch (err) {
|
|
8953
|
+
if (isMissing(err)) return "";
|
|
8954
|
+
throw unreadable(file, err);
|
|
8955
|
+
}
|
|
8388
8956
|
}
|
|
8389
8957
|
async function readManifest(abs, file) {
|
|
8390
8958
|
try {
|
|
8391
8959
|
return await readFile6(abs, "utf8");
|
|
8392
8960
|
} catch (err) {
|
|
8393
|
-
|
|
8394
|
-
throw new DocmetaError(
|
|
8395
|
-
`Manifest ${file} could not be read: ${reason}`
|
|
8396
|
-
);
|
|
8961
|
+
throw unreadable(file, err);
|
|
8397
8962
|
}
|
|
8398
8963
|
}
|
|
8964
|
+
function unreadable(file, err) {
|
|
8965
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
8966
|
+
return new DocmetaError(`Manifest ${file} could not be read: ${reason}`);
|
|
8967
|
+
}
|
|
8399
8968
|
function parseManifest(manifest, collection, text2, file, configDir, join11) {
|
|
8400
8969
|
const target = /* @__PURE__ */ new Map();
|
|
8401
8970
|
const entries = [];
|
|
8402
|
-
const lc = new
|
|
8403
|
-
const doc =
|
|
8971
|
+
const lc = new LineCounter3();
|
|
8972
|
+
const doc = parseDocument5(text2, { lineCounter: lc, uniqueKeys: false });
|
|
8404
8973
|
const problem = doc.errors[0];
|
|
8405
8974
|
if (problem) {
|
|
8406
8975
|
throw new DocmetaError(
|
|
@@ -8408,21 +8977,21 @@ function parseManifest(manifest, collection, text2, file, configDir, join11) {
|
|
|
8408
8977
|
);
|
|
8409
8978
|
}
|
|
8410
8979
|
const root = doc.contents;
|
|
8411
|
-
if (root === null ||
|
|
8980
|
+
if (root === null || isScalar5(root) && root.value === null)
|
|
8412
8981
|
return { values: target, entries };
|
|
8413
|
-
if (!
|
|
8982
|
+
if (!isMap6(root)) {
|
|
8414
8983
|
throw new DocmetaError(
|
|
8415
|
-
`Manifest ${file}: the manifest must be a mapping from document ${join11 ===
|
|
8984
|
+
`Manifest ${file}: the manifest must be a mapping from document ${join11 === PATH_JOIN2 ? "path" : `"${join11}"`} to owned keys.`
|
|
8416
8985
|
);
|
|
8417
8986
|
}
|
|
8418
8987
|
const owned = new Set(manifest.keys);
|
|
8419
8988
|
const lineAt = (node) => {
|
|
8420
|
-
const range =
|
|
8989
|
+
const range = isNode3(node) ? node.range : void 0;
|
|
8421
8990
|
return range ? lc.linePos(range[0]).line : void 0;
|
|
8422
8991
|
};
|
|
8423
8992
|
const seen = /* @__PURE__ */ new Map();
|
|
8424
8993
|
for (const pair of root.items) {
|
|
8425
|
-
const spelled =
|
|
8994
|
+
const spelled = isScalar5(pair.key) ? String(pair.key.value) : String(pair.key);
|
|
8426
8995
|
const entryLine = lineAt(pair.key);
|
|
8427
8996
|
const where = entryLine === void 0 ? file : `${file}:${entryLine}`;
|
|
8428
8997
|
if (seen.has(spelled)) {
|
|
@@ -8432,15 +9001,15 @@ function parseManifest(manifest, collection, text2, file, configDir, join11) {
|
|
|
8432
9001
|
);
|
|
8433
9002
|
}
|
|
8434
9003
|
seen.set(spelled, entryLine);
|
|
8435
|
-
if (!
|
|
9004
|
+
if (!isMap6(pair.value)) {
|
|
8436
9005
|
throw new DocmetaError(
|
|
8437
9006
|
`Manifest ${where}: "${spelled}" must be a mapping of owned keys to values.`
|
|
8438
9007
|
);
|
|
8439
9008
|
}
|
|
8440
|
-
const indexKey = join11 ===
|
|
9009
|
+
const indexKey = join11 === PATH_JOIN2 ? resolve12(configDir, spelled) : spelled;
|
|
8441
9010
|
const values = target.get(indexKey) ?? /* @__PURE__ */ new Map();
|
|
8442
9011
|
for (const kv of pair.value.items) {
|
|
8443
|
-
const key =
|
|
9012
|
+
const key = isScalar5(kv.key) ? String(kv.key.value) : String(kv.key);
|
|
8444
9013
|
if (key === FILE_SCHEMA_KEY) {
|
|
8445
9014
|
throw new DocmetaError(
|
|
8446
9015
|
`Manifest ${where}: "${spelled}" sets "${FILE_SCHEMA_KEY}" \u2014 a manifest never chooses the schema a document is judged by; use "overrides" in the config.`
|
|
@@ -8466,7 +9035,7 @@ function parseManifest(manifest, collection, text2, file, configDir, join11) {
|
|
|
8466
9035
|
entries.push({
|
|
8467
9036
|
collection,
|
|
8468
9037
|
join: join11,
|
|
8469
|
-
...join11 ===
|
|
9038
|
+
...join11 === PATH_JOIN2 ? { abs: indexKey } : {},
|
|
8470
9039
|
spelled,
|
|
8471
9040
|
file,
|
|
8472
9041
|
...entryLine === void 0 ? {} : { line: entryLine }
|
|
@@ -8475,15 +9044,15 @@ function parseManifest(manifest, collection, text2, file, configDir, join11) {
|
|
|
8475
9044
|
return { values: target, entries };
|
|
8476
9045
|
}
|
|
8477
9046
|
function nodeLines(node, lineAt, prefix = "", out = /* @__PURE__ */ new Map()) {
|
|
8478
|
-
if (
|
|
9047
|
+
if (isMap6(node)) {
|
|
8479
9048
|
for (const kv of node.items) {
|
|
8480
|
-
const seg =
|
|
9049
|
+
const seg = isScalar5(kv.key) ? String(kv.key.value) : String(kv.key);
|
|
8481
9050
|
const pointer = `${prefix}/${escapePointerSegment(seg)}`;
|
|
8482
9051
|
const line = lineAt(kv.key) ?? lineAt(kv.value);
|
|
8483
9052
|
if (line !== void 0) out.set(pointer, line);
|
|
8484
9053
|
nodeLines(kv.value, lineAt, pointer, out);
|
|
8485
9054
|
}
|
|
8486
|
-
} else if (
|
|
9055
|
+
} else if (isSeq3(node)) {
|
|
8487
9056
|
node.items.forEach((item, i) => {
|
|
8488
9057
|
const pointer = `${prefix}/${String(i)}`;
|
|
8489
9058
|
const line = lineAt(item);
|
|
@@ -8516,7 +9085,7 @@ function mergeExternalMetadata(label, extracted, index, memberOf2, base, options
|
|
|
8516
9085
|
const sources = [];
|
|
8517
9086
|
const joins = [];
|
|
8518
9087
|
if (label !== STDIN_LABEL) {
|
|
8519
|
-
const byPath = index.byPath.get(
|
|
9088
|
+
const byPath = index.byPath.get(resolve12(base, label));
|
|
8520
9089
|
if (byPath) sources.push(byPath);
|
|
8521
9090
|
}
|
|
8522
9091
|
for (const [field, byValue] of index.byField) {
|
|
@@ -8611,10 +9180,41 @@ function externalMetadataPointer(key) {
|
|
|
8611
9180
|
}
|
|
8612
9181
|
function orphanEntries(index, loaded, base, collections) {
|
|
8613
9182
|
if (!index) return [];
|
|
8614
|
-
const have = new Set(loaded.map((l) =>
|
|
8615
|
-
|
|
8616
|
-
(e) => inCollections(e, collections) && e.join ===
|
|
9183
|
+
const have = new Set(loaded.map((l) => resolve12(base, l)));
|
|
9184
|
+
const orphans = index.entries.filter(
|
|
9185
|
+
(e) => inCollections(e, collections) && e.join === PATH_JOIN2 && e.abs !== void 0 && !have.has(e.abs)
|
|
8617
9186
|
);
|
|
9187
|
+
if (collections !== void 0) return orphans;
|
|
9188
|
+
return [...orphans, ...strayManifests(perPageRules.get(index) ?? [], have, base)];
|
|
9189
|
+
}
|
|
9190
|
+
function strayManifests(rules, loaded, base) {
|
|
9191
|
+
const strays = [];
|
|
9192
|
+
for (const { collection, manifest, configDir } of rules) {
|
|
9193
|
+
const read = /* @__PURE__ */ new Set();
|
|
9194
|
+
for (const pageAbs of loaded) {
|
|
9195
|
+
const resolved = pageManifestPath(manifest.file, configDir, pageAbs);
|
|
9196
|
+
if (!("outside" in resolved)) read.add(resolved.abs);
|
|
9197
|
+
}
|
|
9198
|
+
const found = findPageManifests(manifest.file, configDir, (rel) => isMember(collection, rel));
|
|
9199
|
+
for (const { abs, entries } of found) {
|
|
9200
|
+
if (read.has(abs)) continue;
|
|
9201
|
+
const file = reportedPath(abs, base);
|
|
9202
|
+
for (const entry of entries) {
|
|
9203
|
+
if (loaded.has(entry.pageAbs)) continue;
|
|
9204
|
+
const stray = {
|
|
9205
|
+
collection: collection.name,
|
|
9206
|
+
join: PATH_JOIN2,
|
|
9207
|
+
abs: entry.pageAbs,
|
|
9208
|
+
spelled: entry.spelled,
|
|
9209
|
+
file,
|
|
9210
|
+
...entry.line === void 0 ? {} : { line: entry.line }
|
|
9211
|
+
};
|
|
9212
|
+
strayEntries.add(stray);
|
|
9213
|
+
strays.push(stray);
|
|
9214
|
+
}
|
|
9215
|
+
}
|
|
9216
|
+
}
|
|
9217
|
+
return strays;
|
|
8618
9218
|
}
|
|
8619
9219
|
function inCollections(entry, collections) {
|
|
8620
9220
|
return collections === void 0 || collections.includes(entry.collection);
|
|
@@ -8622,7 +9222,7 @@ function inCollections(entry, collections) {
|
|
|
8622
9222
|
function orphanJoins(index, matched, collections) {
|
|
8623
9223
|
if (!index) return [];
|
|
8624
9224
|
return index.entries.filter(
|
|
8625
|
-
(e) => inCollections(e, collections) && e.join !==
|
|
9225
|
+
(e) => inCollections(e, collections) && e.join !== PATH_JOIN2 && !(matched.get(e.join)?.has(e.spelled) ?? false)
|
|
8626
9226
|
);
|
|
8627
9227
|
}
|
|
8628
9228
|
function orphanError(orphans) {
|
|
@@ -8630,9 +9230,10 @@ function orphanError(orphans) {
|
|
|
8630
9230
|
if (!first) throw new Error("orphanError called with no orphans");
|
|
8631
9231
|
const where = first.line === void 0 ? first.file : `${first.file}:${first.line}`;
|
|
8632
9232
|
const more = orphans.length > 1 ? ` (${orphans.length - 1} more)` : "";
|
|
8633
|
-
const what = first.join ===
|
|
9233
|
+
const what = first.join === PATH_JOIN2 ? `names "${first.spelled}", which this run did not load` : `names ${first.join} "${first.spelled}", which no loaded document carries`;
|
|
9234
|
+
const remove = strayEntries.has(first) ? "the file" : "it";
|
|
8634
9235
|
return new DocmetaError(
|
|
8635
|
-
`Manifest ${where} ${what}${more}. Fix the entry, or remove
|
|
9236
|
+
`Manifest ${where} ${what}${more}. Fix the entry, or remove ${remove}.`
|
|
8636
9237
|
);
|
|
8637
9238
|
}
|
|
8638
9239
|
|
|
@@ -8646,7 +9247,7 @@ function isFieldLocation(value) {
|
|
|
8646
9247
|
}
|
|
8647
9248
|
|
|
8648
9249
|
// src/meta/core/collections.ts
|
|
8649
|
-
import { isAbsolute as
|
|
9250
|
+
import { isAbsolute as isAbsolute6, relative as relative9, resolve as resolvePath2, sep as sep4 } from "node:path";
|
|
8650
9251
|
|
|
8651
9252
|
// src/meta/core/projection.ts
|
|
8652
9253
|
var SYSTEM_COLUMNS = ["_path", "_format", "_present", "_data"];
|
|
@@ -8867,8 +9468,8 @@ function loadSqlite() {
|
|
|
8867
9468
|
function memberOf(collections, configDir, base, label) {
|
|
8868
9469
|
if (collections.length === 0) return [];
|
|
8869
9470
|
if (label === STDIN_LABEL) return [];
|
|
8870
|
-
const rel =
|
|
8871
|
-
if (
|
|
9471
|
+
const rel = relative9(configDir, resolvePath2(base, label)).split(sep4).join("/");
|
|
9472
|
+
if (isAbsolute6(rel)) return [];
|
|
8872
9473
|
return collections.filter((c) => isMember(c, rel)).map((c) => c.name);
|
|
8873
9474
|
}
|
|
8874
9475
|
function retainMembers(files, membersFor) {
|
|
@@ -9322,7 +9923,7 @@ function toFieldError(schema, e, lineFor, colFor, locate) {
|
|
|
9322
9923
|
|
|
9323
9924
|
// src/meta/core/derive/cache.ts
|
|
9324
9925
|
import { createHash as createHash4 } from "node:crypto";
|
|
9325
|
-
import { mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
9926
|
+
import { mkdirSync, readFileSync as readFileSync2, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
9326
9927
|
import { join as join7 } from "node:path";
|
|
9327
9928
|
var REVIEW_CACHE_DIR = ".manni/meta/review-cache";
|
|
9328
9929
|
var REVIEW_CACHE_VERSION = 1;
|
|
@@ -9342,7 +9943,7 @@ var ReviewCache = class {
|
|
|
9342
9943
|
if (!this.enabled) return void 0;
|
|
9343
9944
|
let raw;
|
|
9344
9945
|
try {
|
|
9345
|
-
raw = JSON.parse(
|
|
9946
|
+
raw = JSON.parse(readFileSync2(this.entryPath(key), "utf8"));
|
|
9346
9947
|
} catch {
|
|
9347
9948
|
return void 0;
|
|
9348
9949
|
}
|
|
@@ -9906,12 +10507,12 @@ function utcDate(iso) {
|
|
|
9906
10507
|
}
|
|
9907
10508
|
|
|
9908
10509
|
// src/meta/core/derive/index.ts
|
|
9909
|
-
import { dirname as dirname9, resolve as
|
|
10510
|
+
import { dirname as dirname9, resolve as resolve14 } from "node:path";
|
|
9910
10511
|
|
|
9911
10512
|
// src/meta/core/derive/codeowners.ts
|
|
9912
10513
|
import { existsSync as existsSync3 } from "node:fs";
|
|
9913
10514
|
import { readFile as readFile7 } from "node:fs/promises";
|
|
9914
|
-
import { dirname as dirname7, relative as
|
|
10515
|
+
import { dirname as dirname7, relative as relative10, resolve as resolve13, sep as sep5 } from "node:path";
|
|
9915
10516
|
import picomatch4 from "picomatch";
|
|
9916
10517
|
var CODEOWNERS_LOCATIONS = [
|
|
9917
10518
|
".github/CODEOWNERS",
|
|
@@ -9921,11 +10522,11 @@ var CODEOWNERS_LOCATIONS = [
|
|
|
9921
10522
|
];
|
|
9922
10523
|
function findCodeowners(root, explicit) {
|
|
9923
10524
|
if (explicit !== void 0) {
|
|
9924
|
-
const path =
|
|
10525
|
+
const path = resolve13(root, explicit);
|
|
9925
10526
|
return existsSync3(path) ? path : null;
|
|
9926
10527
|
}
|
|
9927
10528
|
for (const loc of CODEOWNERS_LOCATIONS) {
|
|
9928
|
-
const path =
|
|
10529
|
+
const path = resolve13(root, ...loc.split("/"));
|
|
9929
10530
|
if (existsSync3(path)) return path;
|
|
9930
10531
|
}
|
|
9931
10532
|
return null;
|
|
@@ -10040,7 +10641,7 @@ function toGlobs(pattern) {
|
|
|
10040
10641
|
var NOT_FOUND_REASON = `no CODEOWNERS file found (looked for ${CODEOWNERS_LOCATIONS.join(", ")})`;
|
|
10041
10642
|
async function deriveFromCodeowners(inputs, opts) {
|
|
10042
10643
|
const records = /* @__PURE__ */ new Map();
|
|
10043
|
-
const explicitPath = opts.explicit === void 0 ? void 0 :
|
|
10644
|
+
const explicitPath = opts.explicit === void 0 ? void 0 : resolve13(opts.configDir ?? process.cwd(), opts.explicit);
|
|
10044
10645
|
if (explicitPath !== void 0 && !existsSync3(explicitPath)) {
|
|
10045
10646
|
return {
|
|
10046
10647
|
status: { available: false, reason: `CODEOWNERS not found at ${explicitPath}` },
|
|
@@ -10070,7 +10671,7 @@ async function deriveFromCodeowners(inputs, opts) {
|
|
|
10070
10671
|
continue;
|
|
10071
10672
|
}
|
|
10072
10673
|
found += 1;
|
|
10073
|
-
const label = toPosix2(
|
|
10674
|
+
const label = toPosix2(relative10(opts.configDir ?? root, path));
|
|
10074
10675
|
const key = `${path}\0${label}`;
|
|
10075
10676
|
let file = parsed2.get(key);
|
|
10076
10677
|
if (!file) {
|
|
@@ -10092,7 +10693,7 @@ async function deriveFromCodeowners(inputs, opts) {
|
|
|
10092
10693
|
};
|
|
10093
10694
|
}
|
|
10094
10695
|
for (const input of bucket) {
|
|
10095
|
-
const rel = toPosix2(
|
|
10696
|
+
const rel = toPosix2(relative10(root, input.absPath));
|
|
10096
10697
|
const hit = ownersFor(owners, rel);
|
|
10097
10698
|
records.set(
|
|
10098
10699
|
input.label,
|
|
@@ -10116,13 +10717,13 @@ async function deriveFromCodeowners(inputs, opts) {
|
|
|
10116
10717
|
return { status: { available: true }, records };
|
|
10117
10718
|
}
|
|
10118
10719
|
function toPosix2(p) {
|
|
10119
|
-
return p.split(
|
|
10720
|
+
return p.split(sep5).join("/");
|
|
10120
10721
|
}
|
|
10121
10722
|
|
|
10122
10723
|
// src/meta/core/derive/git.ts
|
|
10123
10724
|
import { constants as bufferConstants } from "node:buffer";
|
|
10124
10725
|
import { spawn as spawn3 } from "node:child_process";
|
|
10125
|
-
import { dirname as dirname8, extname as extname2, isAbsolute as
|
|
10726
|
+
import { dirname as dirname8, extname as extname2, isAbsolute as isAbsolute7, posix as posix5, relative as relative11, sep as sep6 } from "node:path";
|
|
10126
10727
|
import { parse as parseYaml4 } from "yaml";
|
|
10127
10728
|
|
|
10128
10729
|
// src/shared/pin.ts
|
|
@@ -10772,7 +11373,7 @@ function groupByRoot(inputs) {
|
|
|
10772
11373
|
rootOf.set(dir, root);
|
|
10773
11374
|
}
|
|
10774
11375
|
if (root === null) continue;
|
|
10775
|
-
const rel =
|
|
11376
|
+
const rel = relative11(root, input.absPath).split(sep6).join("/");
|
|
10776
11377
|
const bucket = byRoot.get(root);
|
|
10777
11378
|
if (bucket) bucket.push({ input, rel });
|
|
10778
11379
|
else byRoot.set(root, [{ input, rel }]);
|
|
@@ -11225,14 +11826,14 @@ async function commitEvidence(run2, root, entry, blame, history, blobs, manifest
|
|
|
11225
11826
|
return commits;
|
|
11226
11827
|
}
|
|
11227
11828
|
function insideRoot(root, abs) {
|
|
11228
|
-
const rel =
|
|
11229
|
-
if (rel === "" || rel.startsWith("..") ||
|
|
11230
|
-
return rel.split(
|
|
11829
|
+
const rel = relative11(root, abs);
|
|
11830
|
+
if (rel === "" || rel.startsWith("..") || isAbsolute7(rel)) return void 0;
|
|
11831
|
+
return rel.split(sep6).join("/");
|
|
11231
11832
|
}
|
|
11232
11833
|
function entryAt(entry, rel, relAtCommit) {
|
|
11233
11834
|
if (relAtCommit === rel) return entry;
|
|
11234
|
-
const fromHere =
|
|
11235
|
-
return
|
|
11835
|
+
const fromHere = posix5.relative(posix5.dirname(rel), relAtCommit);
|
|
11836
|
+
return posix5.join(posix5.dirname(entry), fromHere);
|
|
11236
11837
|
}
|
|
11237
11838
|
function manifestStamp(text2, key, join11) {
|
|
11238
11839
|
if (text2 === void 0) return [];
|
|
@@ -11244,7 +11845,7 @@ function manifestStamp(text2, key, join11) {
|
|
|
11244
11845
|
}
|
|
11245
11846
|
if (!isRecord5(data)) return [];
|
|
11246
11847
|
for (const [candidate, value] of Object.entries(data)) {
|
|
11247
|
-
const same2 = join11 === "path" ?
|
|
11848
|
+
const same2 = join11 === "path" ? posix5.normalize(candidate) === posix5.normalize(key) : candidate === key;
|
|
11248
11849
|
if (same2 && isRecord5(value)) return provenanceEntries(value[PROVENANCE_FIELD]);
|
|
11249
11850
|
}
|
|
11250
11851
|
return [];
|
|
@@ -11554,7 +12155,7 @@ async function deriveReviewsByRoot(inputs, git2, rootFor, ctx, requested) {
|
|
|
11554
12155
|
if (byRoot.size === 0) {
|
|
11555
12156
|
return unavailable3(requested, "no git repository contains the documents");
|
|
11556
12157
|
}
|
|
11557
|
-
const cacheDir =
|
|
12158
|
+
const cacheDir = resolve14(ctx.configDir ?? ctx.cwd, REVIEW_CACHE_DIR);
|
|
11558
12159
|
for (const [root, bucket] of byRoot) {
|
|
11559
12160
|
const client = ctx.reviews ?? await createReviewClient(root, { cwd: ctx.cwd, cache: ctx.cache, cacheDir, requested });
|
|
11560
12161
|
const identity = await client.detect();
|
|
@@ -11736,33 +12337,31 @@ import { readFile as readFile9 } from "node:fs/promises";
|
|
|
11736
12337
|
|
|
11737
12338
|
// src/meta/core/relocation.ts
|
|
11738
12339
|
import { access, readFile as readFile8, stat as stat6, unlink } from "node:fs/promises";
|
|
11739
|
-
import { basename as basename5, extname as extname3, isAbsolute as
|
|
12340
|
+
import { basename as basename5, extname as extname3, isAbsolute as isAbsolute8, join as join8, relative as relative12, resolve as resolve15, sep as sep7 } from "node:path";
|
|
11740
12341
|
import picomatch6 from "picomatch";
|
|
11741
12342
|
import {
|
|
11742
|
-
LineCounter as
|
|
11743
|
-
isMap as
|
|
11744
|
-
isNode as
|
|
11745
|
-
isScalar as
|
|
12343
|
+
LineCounter as LineCounter5,
|
|
12344
|
+
isMap as isMap8,
|
|
12345
|
+
isNode as isNode5,
|
|
12346
|
+
isScalar as isScalar7,
|
|
11746
12347
|
isSeq as isSeq4,
|
|
11747
12348
|
parse as parseYaml5,
|
|
11748
|
-
parseDocument as
|
|
12349
|
+
parseDocument as parseDocument7
|
|
11749
12350
|
} from "yaml";
|
|
11750
12351
|
|
|
11751
12352
|
// src/meta/core/external-metadata-write.ts
|
|
11752
|
-
import { posix as
|
|
12353
|
+
import { posix as posix6 } from "node:path";
|
|
11753
12354
|
import {
|
|
11754
|
-
LineCounter as
|
|
11755
|
-
isMap as
|
|
11756
|
-
isNode as
|
|
11757
|
-
|
|
11758
|
-
|
|
11759
|
-
|
|
11760
|
-
parseDocument as parseDocument5,
|
|
11761
|
-
stringify as stringify2
|
|
12355
|
+
LineCounter as LineCounter4,
|
|
12356
|
+
isMap as isMap7,
|
|
12357
|
+
isNode as isNode4,
|
|
12358
|
+
isScalar as isScalar6,
|
|
12359
|
+
parseDocument as parseDocument6,
|
|
12360
|
+
stringify as stringify3
|
|
11762
12361
|
} from "yaml";
|
|
11763
12362
|
function spliceManifestValue(text2, options) {
|
|
11764
12363
|
const { entry, key, value, file } = options;
|
|
11765
|
-
const join11 = options.join ??
|
|
12364
|
+
const join11 = options.join ?? PATH_JOIN2;
|
|
11766
12365
|
const at2 = (line2) => {
|
|
11767
12366
|
const name2 = file === void 0 ? "Manifest" : `Manifest ${file}`;
|
|
11768
12367
|
if (line2 === void 0) return name2;
|
|
@@ -11777,8 +12376,8 @@ function spliceManifestValue(text2, options) {
|
|
|
11777
12376
|
throw new DocmetaError(`${at2()}: refusing to write "${key}" for "${entry}" with no value.`);
|
|
11778
12377
|
}
|
|
11779
12378
|
const eol = detectEol(text2);
|
|
11780
|
-
const lc = new
|
|
11781
|
-
const doc =
|
|
12379
|
+
const lc = new LineCounter4();
|
|
12380
|
+
const doc = parseDocument6(text2, { lineCounter: lc, uniqueKeys: false });
|
|
11782
12381
|
const problem = doc.errors[0];
|
|
11783
12382
|
if (problem) {
|
|
11784
12383
|
throw new DocmetaError(`${at2()} is not valid YAML: ${problem.message}`);
|
|
@@ -11787,15 +12386,15 @@ function spliceManifestValue(text2, options) {
|
|
|
11787
12386
|
const r = rangeOf(node);
|
|
11788
12387
|
return r ? lc.linePos(r[0]).line : void 0;
|
|
11789
12388
|
};
|
|
11790
|
-
const same2 = join11 ===
|
|
12389
|
+
const same2 = join11 === PATH_JOIN2 ? (a, b) => posix6.normalize(a) === posix6.normalize(b) : (a, b) => a === b;
|
|
11791
12390
|
const root = doc.contents;
|
|
11792
12391
|
let spelled = entry;
|
|
11793
12392
|
let edit;
|
|
11794
|
-
if (root === null ||
|
|
12393
|
+
if (root === null || isScalar6(root) && root.value === null && emptySource(text2, root)) {
|
|
11795
12394
|
edit = startManifest(text2, entry, key, value, eol);
|
|
11796
|
-
} else if (!
|
|
12395
|
+
} else if (!isMap7(root)) {
|
|
11797
12396
|
throw new DocmetaError(
|
|
11798
|
-
`${at2()}: the manifest must be a mapping from document ${join11 ===
|
|
12397
|
+
`${at2()}: the manifest must be a mapping from document ${join11 === PATH_JOIN2 ? "path" : `"${join11}"`} to owned keys.`
|
|
11799
12398
|
);
|
|
11800
12399
|
} else {
|
|
11801
12400
|
const style = detectStyle(text2, root, eol);
|
|
@@ -11817,7 +12416,7 @@ function spliceManifestValue(text2, options) {
|
|
|
11817
12416
|
spelled = keyString(first.key);
|
|
11818
12417
|
const where = at2(keyLine(first.key));
|
|
11819
12418
|
const v = first.value;
|
|
11820
|
-
if (!
|
|
12419
|
+
if (!isMap7(v)) {
|
|
11821
12420
|
throw new DocmetaError(`${where}: "${spelled}" must be a mapping of owned keys to values.`);
|
|
11822
12421
|
}
|
|
11823
12422
|
const hits = v.items.filter((kv) => keyString(kv.key) === key);
|
|
@@ -11860,30 +12459,30 @@ function spliceManifestValue(text2, options) {
|
|
|
11860
12459
|
return { text: out, line };
|
|
11861
12460
|
}
|
|
11862
12461
|
function readManifestValue(text2, options) {
|
|
11863
|
-
const join11 = options.join ??
|
|
11864
|
-
const doc =
|
|
12462
|
+
const join11 = options.join ?? PATH_JOIN2;
|
|
12463
|
+
const doc = parseDocument6(text2, { uniqueKeys: false });
|
|
11865
12464
|
if (doc.errors.length > 0) return void 0;
|
|
11866
12465
|
const root = doc.contents;
|
|
11867
|
-
if (!
|
|
11868
|
-
const same2 = join11 ===
|
|
12466
|
+
if (!isMap7(root)) return void 0;
|
|
12467
|
+
const same2 = join11 === PATH_JOIN2 ? (a, b) => posix6.normalize(a) === posix6.normalize(b) : (a, b) => a === b;
|
|
11869
12468
|
const pair = root.items.find((p) => same2(keyString(p.key), options.entry));
|
|
11870
12469
|
const held = pair?.value;
|
|
11871
|
-
if (!
|
|
12470
|
+
if (!isMap7(held)) return void 0;
|
|
11872
12471
|
const kv = held.items.find((p) => keyString(p.key) === options.key);
|
|
11873
12472
|
const node = kv?.value;
|
|
11874
|
-
return
|
|
12473
|
+
return isNode4(node) ? node.toJSON() : void 0;
|
|
11875
12474
|
}
|
|
11876
12475
|
function removeManifestKey(text2, options) {
|
|
11877
12476
|
const { entry, key, file } = options;
|
|
11878
|
-
const join11 = options.join ??
|
|
12477
|
+
const join11 = options.join ?? PATH_JOIN2;
|
|
11879
12478
|
const at2 = (line) => {
|
|
11880
12479
|
const name2 = file === void 0 ? "Manifest" : `Manifest ${file}`;
|
|
11881
12480
|
if (line === void 0) return name2;
|
|
11882
12481
|
return file === void 0 ? `${name2} line ${String(line)}` : `${name2}:${String(line)}`;
|
|
11883
12482
|
};
|
|
11884
12483
|
const eol = detectEol(text2);
|
|
11885
|
-
const lc = new
|
|
11886
|
-
const doc =
|
|
12484
|
+
const lc = new LineCounter4();
|
|
12485
|
+
const doc = parseDocument6(text2, { lineCounter: lc, uniqueKeys: false });
|
|
11887
12486
|
const problem = doc.errors[0];
|
|
11888
12487
|
if (problem) {
|
|
11889
12488
|
throw new DocmetaError(`${at2()} is not valid YAML: ${problem.message}`);
|
|
@@ -11893,13 +12492,13 @@ function removeManifestKey(text2, options) {
|
|
|
11893
12492
|
return r ? lc.linePos(r[0]).line : void 0;
|
|
11894
12493
|
};
|
|
11895
12494
|
const root = doc.contents;
|
|
11896
|
-
if (root === null ||
|
|
11897
|
-
if (!
|
|
12495
|
+
if (root === null || isScalar6(root) && root.value === null) return { text: text2 };
|
|
12496
|
+
if (!isMap7(root)) {
|
|
11898
12497
|
throw new DocmetaError(
|
|
11899
|
-
`${at2()}: the manifest must be a mapping from document ${join11 ===
|
|
12498
|
+
`${at2()}: the manifest must be a mapping from document ${join11 === PATH_JOIN2 ? "path" : `"${join11}"`} to owned keys.`
|
|
11900
12499
|
);
|
|
11901
12500
|
}
|
|
11902
|
-
const same2 = join11 ===
|
|
12501
|
+
const same2 = join11 === PATH_JOIN2 ? (a, b) => posix6.normalize(a) === posix6.normalize(b) : (a, b) => a === b;
|
|
11903
12502
|
const matches = root.items.filter((p) => same2(keyString(p.key), entry));
|
|
11904
12503
|
const [first, second] = matches;
|
|
11905
12504
|
if (first && second) {
|
|
@@ -11911,7 +12510,7 @@ function removeManifestKey(text2, options) {
|
|
|
11911
12510
|
const spelled = keyString(first.key);
|
|
11912
12511
|
const where = at2(keyLine(first.key));
|
|
11913
12512
|
const v = first.value;
|
|
11914
|
-
if (!
|
|
12513
|
+
if (!isMap7(v)) {
|
|
11915
12514
|
throw new DocmetaError(`${where}: "${spelled}" must be a mapping of owned keys to values.`);
|
|
11916
12515
|
}
|
|
11917
12516
|
const hits = v.items.filter((kv) => keyString(kv.key) === key);
|
|
@@ -11935,16 +12534,13 @@ function removeManifestKey(text2, options) {
|
|
|
11935
12534
|
`${where}: "${spelled}" writes a key in a form this writer does not edit. Write it as "${key}: \u2026".`
|
|
11936
12535
|
);
|
|
11937
12536
|
}
|
|
11938
|
-
let start = text2
|
|
11939
|
-
let end = lineEnd(text2, to);
|
|
11940
|
-
if (text2.startsWith(eol, end)) end += eol.length;
|
|
11941
|
-
else if (start >= eol.length) start -= eol.length;
|
|
12537
|
+
let { start, end } = keyLines(text2, from[0], to, eol);
|
|
11942
12538
|
if (whole) {
|
|
11943
12539
|
if (text2.slice(start - 2 * eol.length, start) === eol + eol) start -= eol.length;
|
|
11944
12540
|
else if (start === 0 && text2.startsWith(eol, end)) end += eol.length;
|
|
11945
12541
|
}
|
|
11946
12542
|
const out = text2.slice(0, start) + text2.slice(end);
|
|
11947
|
-
const after =
|
|
12543
|
+
const after = parseDocument6(out, { uniqueKeys: false });
|
|
11948
12544
|
const fail2 = (why) => new DocmetaError(
|
|
11949
12545
|
`${at2()}: removing "${key}" for "${entry}" did not read back as removed, so nothing was written. ${why}`
|
|
11950
12546
|
);
|
|
@@ -11964,14 +12560,14 @@ function removeManifestKey(text2, options) {
|
|
|
11964
12560
|
}
|
|
11965
12561
|
function renameManifestEntry(text2, options) {
|
|
11966
12562
|
const { entry, to, file } = options;
|
|
11967
|
-
const join11 = options.join ??
|
|
12563
|
+
const join11 = options.join ?? PATH_JOIN2;
|
|
11968
12564
|
const at2 = (line) => {
|
|
11969
12565
|
const name2 = file === void 0 ? "Manifest" : `Manifest ${file}`;
|
|
11970
12566
|
if (line === void 0) return name2;
|
|
11971
12567
|
return file === void 0 ? `${name2} line ${String(line)}` : `${name2}:${String(line)}`;
|
|
11972
|
-
};
|
|
11973
|
-
const lc = new
|
|
11974
|
-
const doc =
|
|
12568
|
+
};
|
|
12569
|
+
const lc = new LineCounter4();
|
|
12570
|
+
const doc = parseDocument6(text2, { lineCounter: lc, uniqueKeys: false });
|
|
11975
12571
|
const problem = doc.errors[0];
|
|
11976
12572
|
if (problem) {
|
|
11977
12573
|
throw new DocmetaError(`${at2()} is not valid YAML: ${problem.message}`);
|
|
@@ -11981,13 +12577,13 @@ function renameManifestEntry(text2, options) {
|
|
|
11981
12577
|
return r2 ? lc.linePos(r2[0]).line : void 0;
|
|
11982
12578
|
};
|
|
11983
12579
|
const root = doc.contents;
|
|
11984
|
-
if (root === null ||
|
|
11985
|
-
if (!
|
|
12580
|
+
if (root === null || isScalar6(root) && root.value === null) return { text: text2 };
|
|
12581
|
+
if (!isMap7(root)) {
|
|
11986
12582
|
throw new DocmetaError(
|
|
11987
|
-
`${at2()}: the manifest must be a mapping from document ${join11 ===
|
|
12583
|
+
`${at2()}: the manifest must be a mapping from document ${join11 === PATH_JOIN2 ? "path" : `"${join11}"`} to owned keys.`
|
|
11988
12584
|
);
|
|
11989
12585
|
}
|
|
11990
|
-
const same2 = join11 ===
|
|
12586
|
+
const same2 = join11 === PATH_JOIN2 ? (a, b) => posix6.normalize(a) === posix6.normalize(b) : (a, b) => a === b;
|
|
11991
12587
|
const [first, second] = root.items.filter((p) => same2(keyString(p.key), entry));
|
|
11992
12588
|
if (first && second) {
|
|
11993
12589
|
throw new DocmetaError(
|
|
@@ -12009,11 +12605,11 @@ function renameManifestEntry(text2, options) {
|
|
|
12009
12605
|
`${at2(keyLine(first.key))}: "${spelled}" is written in a form this writer does not edit. Write it as "${spelled}: \u2026".`
|
|
12010
12606
|
);
|
|
12011
12607
|
}
|
|
12012
|
-
const quoted =
|
|
12013
|
-
const plain =
|
|
12608
|
+
const quoted = isScalar6(first.key) && (first.key.type === "QUOTE_DOUBLE" || first.key.type === "QUOTE_SINGLE");
|
|
12609
|
+
const plain = stringify3(to, { lineWidth: 0 }).replace(/\n$/, "");
|
|
12014
12610
|
const insert = quoted || plain.includes("\n") ? JSON.stringify(to) : plain;
|
|
12015
12611
|
const out = text2.slice(0, r[0]) + insert + text2.slice(end);
|
|
12016
|
-
const after =
|
|
12612
|
+
const after = parseDocument6(out, { uniqueKeys: false });
|
|
12017
12613
|
const fail2 = (why) => new DocmetaError(
|
|
12018
12614
|
`${at2()}: renaming "${spelled}" to "${to}" did not read back as renamed, so nothing was written. ${why}`
|
|
12019
12615
|
);
|
|
@@ -12047,24 +12643,13 @@ function appendEntry(text2, root, entry, key, value, style) {
|
|
|
12047
12643
|
const col = firstKey ? colOf(text2, firstKey[0]) : 0;
|
|
12048
12644
|
const pos = lineEnd(text2, contentEnd(text2, root) ?? text2.length);
|
|
12049
12645
|
const last = root.items.at(-1);
|
|
12050
|
-
const spaced = root.items.length > 1 &&
|
|
12646
|
+
const spaced = root.items.length > 1 && isNode4(last?.key) && last.key.spaceBefore === true;
|
|
12051
12647
|
return {
|
|
12052
12648
|
start: pos,
|
|
12053
12649
|
end: pos,
|
|
12054
12650
|
insert: style.eol + (spaced ? style.eol : "") + blockLines(body, col, style)
|
|
12055
12651
|
};
|
|
12056
12652
|
}
|
|
12057
|
-
function insertKey(text2, entryMap, key, value, style) {
|
|
12058
|
-
const firstKey = rangeOf(entryMap.items[0]?.key);
|
|
12059
|
-
const end = contentEnd(text2, entryMap);
|
|
12060
|
-
if (!firstKey || end === void 0) return void 0;
|
|
12061
|
-
const pos = lineEnd(text2, end);
|
|
12062
|
-
return {
|
|
12063
|
-
start: pos,
|
|
12064
|
-
end: pos,
|
|
12065
|
-
insert: style.eol + blockLines({ [key]: value }, colOf(text2, firstKey[0]), style)
|
|
12066
|
-
};
|
|
12067
|
-
}
|
|
12068
12653
|
function fillEmptyEntry(text2, entryPair, key, value, style) {
|
|
12069
12654
|
const start = colonEnd(text2, entryPair);
|
|
12070
12655
|
const keyRange = rangeOf(entryPair.key);
|
|
@@ -12073,37 +12658,9 @@ function fillEmptyEntry(text2, entryPair, key, value, style) {
|
|
|
12073
12658
|
const col = colOf(text2, keyRange[0]) + style.step;
|
|
12074
12659
|
return { start, end, insert: style.eol + blockLines({ [key]: value }, col, style) };
|
|
12075
12660
|
}
|
|
12076
|
-
function replaceBlockValue(text2, pair, value, style) {
|
|
12077
|
-
const colon = colonEnd(text2, pair);
|
|
12078
|
-
const keyRange = rangeOf(pair.key);
|
|
12079
|
-
if (colon === void 0 || !keyRange) return void 0;
|
|
12080
|
-
const keyCol = colOf(text2, keyRange[0]);
|
|
12081
|
-
let start = colon;
|
|
12082
|
-
let ownLine = false;
|
|
12083
|
-
let i = colon;
|
|
12084
|
-
while (text2.charAt(i) === " " || text2.charAt(i) === " ") i++;
|
|
12085
|
-
if (text2.charAt(i) === "#") {
|
|
12086
|
-
start = lineEnd(text2, i);
|
|
12087
|
-
ownLine = true;
|
|
12088
|
-
}
|
|
12089
|
-
const old = pair.value;
|
|
12090
|
-
const oldEnd = isScalar3(old) && old.value === null && emptySource(text2, old) ? start : contentEnd(text2, old) ?? start;
|
|
12091
|
-
const end = Math.max(start, oldEnd);
|
|
12092
|
-
let insert = afterColon(value, keyCol, style);
|
|
12093
|
-
if (ownLine && !insert.startsWith(style.eol)) {
|
|
12094
|
-
insert = style.eol + " ".repeat(keyCol + style.step) + insert.trimStart();
|
|
12095
|
-
}
|
|
12096
|
-
return { start, end, insert };
|
|
12097
|
-
}
|
|
12098
|
-
function replaceFlowValue(text2, pair, value) {
|
|
12099
|
-
const r = rangeOf(pair.value);
|
|
12100
|
-
if (!r || emptySource(text2, pair.value)) return void 0;
|
|
12101
|
-
const end = contentEnd(text2, pair.value) ?? r[1];
|
|
12102
|
-
return { start: r[0], end, insert: flowText(value) };
|
|
12103
|
-
}
|
|
12104
12661
|
function readBack(before, out, spelled, key, value, fail2) {
|
|
12105
|
-
const lc = new
|
|
12106
|
-
const after =
|
|
12662
|
+
const lc = new LineCounter4();
|
|
12663
|
+
const after = parseDocument6(out, { lineCounter: lc, uniqueKeys: false });
|
|
12107
12664
|
const problem = after.errors[0];
|
|
12108
12665
|
if (problem) throw fail2(`The result is not valid YAML: ${problem.message}`);
|
|
12109
12666
|
const was = before.toJS({ maxAliasCount: 100 });
|
|
@@ -12124,114 +12681,13 @@ function readBack(before, out, spelled, key, value, fail2) {
|
|
|
12124
12681
|
throw fail2("Another value in the manifest would have changed.");
|
|
12125
12682
|
}
|
|
12126
12683
|
const root = after.contents;
|
|
12127
|
-
const pair =
|
|
12684
|
+
const pair = isMap7(root) ? root.items.find((p) => keyString(p.key) === spelled) : void 0;
|
|
12128
12685
|
const entryMap = pair?.value;
|
|
12129
|
-
const kv =
|
|
12686
|
+
const kv = isMap7(entryMap) ? entryMap.items.find((p) => keyString(p.key) === key) : void 0;
|
|
12130
12687
|
const r = rangeOf(kv?.value) ?? rangeOf(kv?.key);
|
|
12131
12688
|
if (!r) throw fail2("The written value could not be found again.");
|
|
12132
12689
|
return lc.linePos(r[0]).line;
|
|
12133
12690
|
}
|
|
12134
|
-
function blockLines(pair, col, style) {
|
|
12135
|
-
const s = stringify2(pair, { lineWidth: 0, indent: style.step, indentSeq: style.indentSeq });
|
|
12136
|
-
return indentLines(s.replace(/\n$/, "").split("\n"), col, 0).join(style.eol);
|
|
12137
|
-
}
|
|
12138
|
-
function afterColon(value, col, style) {
|
|
12139
|
-
const s = stringify2({ k: value }, { lineWidth: 0, indent: style.step, indentSeq: style.indentSeq });
|
|
12140
|
-
const lines = s.replace(/\n$/, "").slice("k:".length).split("\n");
|
|
12141
|
-
return indentLines(lines, col, 1).join(style.eol);
|
|
12142
|
-
}
|
|
12143
|
-
function indentLines(lines, col, from) {
|
|
12144
|
-
const pad2 = " ".repeat(col);
|
|
12145
|
-
return lines.map((l, i) => i < from || l === "" ? l : pad2 + l);
|
|
12146
|
-
}
|
|
12147
|
-
function flowText(value) {
|
|
12148
|
-
const s = stringify2(value, { lineWidth: 0, collectionStyle: "flow" }).replace(/\n$/, "");
|
|
12149
|
-
return s.includes("\n") ? JSON.stringify(value) : s;
|
|
12150
|
-
}
|
|
12151
|
-
function detectEol(text2) {
|
|
12152
|
-
const i = text2.indexOf("\n");
|
|
12153
|
-
return i > 0 && text2.charAt(i - 1) === "\r" ? "\r\n" : "\n";
|
|
12154
|
-
}
|
|
12155
|
-
function detectStyle(text2, root, eol) {
|
|
12156
|
-
let step = 2;
|
|
12157
|
-
for (const pair of root.items) {
|
|
12158
|
-
const v = pair.value;
|
|
12159
|
-
const entryKey = rangeOf(pair.key);
|
|
12160
|
-
const ownedKey = isMap5(v) && v.flow !== true ? rangeOf(v.items[0]?.key) : void 0;
|
|
12161
|
-
if (entryKey && ownedKey) {
|
|
12162
|
-
const d = colOf(text2, ownedKey[0]) - colOf(text2, entryKey[0]);
|
|
12163
|
-
if (d > 0) {
|
|
12164
|
-
step = d;
|
|
12165
|
-
break;
|
|
12166
|
-
}
|
|
12167
|
-
}
|
|
12168
|
-
}
|
|
12169
|
-
return { step, indentSeq: seqIndented(text2, root) ?? true, eol };
|
|
12170
|
-
}
|
|
12171
|
-
function seqIndented(text2, node) {
|
|
12172
|
-
if (isMap5(node)) {
|
|
12173
|
-
for (const pair of node.items) {
|
|
12174
|
-
const v = pair.value;
|
|
12175
|
-
if (isSeq3(v) && v.flow !== true && v.items.length > 0) {
|
|
12176
|
-
const k = rangeOf(pair.key);
|
|
12177
|
-
const s = rangeOf(v);
|
|
12178
|
-
if (k && s) return colOf(text2, s[0]) > colOf(text2, k[0]);
|
|
12179
|
-
}
|
|
12180
|
-
const inner = seqIndented(text2, v);
|
|
12181
|
-
if (inner !== void 0) return inner;
|
|
12182
|
-
}
|
|
12183
|
-
} else if (isSeq3(node)) {
|
|
12184
|
-
for (const item of node.items) {
|
|
12185
|
-
const inner = seqIndented(text2, item);
|
|
12186
|
-
if (inner !== void 0) return inner;
|
|
12187
|
-
}
|
|
12188
|
-
}
|
|
12189
|
-
return void 0;
|
|
12190
|
-
}
|
|
12191
|
-
function contentEnd(text2, node) {
|
|
12192
|
-
if (isMap5(node) && node.flow !== true) {
|
|
12193
|
-
const last = node.items.at(-1);
|
|
12194
|
-
if (last) return contentEnd(text2, last.value) ?? contentEnd(text2, last.key);
|
|
12195
|
-
} else if (isSeq3(node) && node.flow !== true) {
|
|
12196
|
-
const last = node.items.at(-1);
|
|
12197
|
-
if (last !== void 0) {
|
|
12198
|
-
return isPair(last) ? contentEnd(text2, last.value) ?? contentEnd(text2, last.key) : contentEnd(text2, last);
|
|
12199
|
-
}
|
|
12200
|
-
}
|
|
12201
|
-
const r = rangeOf(node);
|
|
12202
|
-
if (!r) return void 0;
|
|
12203
|
-
let end = r[1];
|
|
12204
|
-
while (end > r[0] && /\s/.test(text2.charAt(end - 1))) end--;
|
|
12205
|
-
return end;
|
|
12206
|
-
}
|
|
12207
|
-
function colonEnd(text2, pair) {
|
|
12208
|
-
const r = rangeOf(pair.key);
|
|
12209
|
-
if (!r) return void 0;
|
|
12210
|
-
let i = r[1];
|
|
12211
|
-
while (text2.charAt(i) === " " || text2.charAt(i) === " ") i++;
|
|
12212
|
-
return text2.charAt(i) === ":" ? i + 1 : void 0;
|
|
12213
|
-
}
|
|
12214
|
-
function lineEnd(text2, i) {
|
|
12215
|
-
const j = text2.indexOf("\n", i);
|
|
12216
|
-
if (j < 0) return text2.length;
|
|
12217
|
-
return j > 0 && text2.charAt(j - 1) === "\r" ? j - 1 : j;
|
|
12218
|
-
}
|
|
12219
|
-
function colOf(text2, offset) {
|
|
12220
|
-
if (offset === 0) return 0;
|
|
12221
|
-
let start = text2.lastIndexOf("\n", offset - 1) + 1;
|
|
12222
|
-
if (start === 0 && text2.startsWith("\uFEFF")) start = 1;
|
|
12223
|
-
return offset - start;
|
|
12224
|
-
}
|
|
12225
|
-
function rangeOf(node) {
|
|
12226
|
-
return isNode2(node) ? node.range ?? void 0 : void 0;
|
|
12227
|
-
}
|
|
12228
|
-
function emptySource(text2, node) {
|
|
12229
|
-
const r = rangeOf(node);
|
|
12230
|
-
return !r || text2.slice(r[0], r[1]).trim() === "";
|
|
12231
|
-
}
|
|
12232
|
-
function keyString(key) {
|
|
12233
|
-
return isScalar3(key) ? String(key.value) : String(key);
|
|
12234
|
-
}
|
|
12235
12691
|
function isRecord6(x) {
|
|
12236
12692
|
return typeof x === "object" && x !== null && !Array.isArray(x);
|
|
12237
12693
|
}
|
|
@@ -12260,13 +12716,13 @@ function relocationContext(run2, extras) {
|
|
|
12260
12716
|
...extras.onNotice !== void 0 ? { onNotice: extras.onNotice } : {}
|
|
12261
12717
|
};
|
|
12262
12718
|
}
|
|
12263
|
-
var toPosix3 = (p) => p.split(
|
|
12719
|
+
var toPosix3 = (p) => p.split(sep7).join("/");
|
|
12264
12720
|
function reported2(abs, base) {
|
|
12265
|
-
const rel =
|
|
12721
|
+
const rel = relative12(base, abs);
|
|
12266
12722
|
return rel === "" ? "." : toPosix3(rel);
|
|
12267
12723
|
}
|
|
12268
12724
|
function configSource(path, cwd) {
|
|
12269
|
-
return toPosix3(
|
|
12725
|
+
return toPosix3(relative12(cwd, path)) || basename5(path);
|
|
12270
12726
|
}
|
|
12271
12727
|
function cloneCollection(c) {
|
|
12272
12728
|
return {
|
|
@@ -12284,7 +12740,8 @@ var Model = class {
|
|
|
12284
12740
|
for (const c of this.collections) {
|
|
12285
12741
|
c.externalMetadata.forEach((m, index) => {
|
|
12286
12742
|
const url = classifyRef(m.file).kind === "url";
|
|
12287
|
-
const
|
|
12743
|
+
const perPage = !url && hasPagePlaceholder(m.file);
|
|
12744
|
+
const absPath = url || perPage ? void 0 : isAbsolute8(m.file) ? m.file : resolve15(configDir, m.file);
|
|
12288
12745
|
this.manifests.push({
|
|
12289
12746
|
collection: c.name,
|
|
12290
12747
|
index,
|
|
@@ -12293,6 +12750,7 @@ var Model = class {
|
|
|
12293
12750
|
absPath,
|
|
12294
12751
|
file: absPath === void 0 ? m.file : reported2(absPath, ctx.base),
|
|
12295
12752
|
join: externalMetadataJoin(m),
|
|
12753
|
+
perPage,
|
|
12296
12754
|
created: false,
|
|
12297
12755
|
keysBefore: [...m.keys],
|
|
12298
12756
|
keysAdded: [],
|
|
@@ -12319,6 +12777,22 @@ var Model = class {
|
|
|
12319
12777
|
manifestsOf(collection) {
|
|
12320
12778
|
return this.manifests.filter((m) => m.collection === collection);
|
|
12321
12779
|
}
|
|
12780
|
+
/**
|
|
12781
|
+
* The one file `m` keeps a page's values in, and how the run reports it:
|
|
12782
|
+
* the page's own for a `{page}` manifest (proposal 0058), the declared file
|
|
12783
|
+
* for any other. `abs` is undefined only for a URL manifest.
|
|
12784
|
+
*/
|
|
12785
|
+
fileFor(m, pageAbs) {
|
|
12786
|
+
if (!m.perPage) return { abs: m.absPath, file: m.file };
|
|
12787
|
+
const resolved = pageManifestPath(m.written, this.configDir, pageAbs);
|
|
12788
|
+
if ("outside" in resolved) {
|
|
12789
|
+
const declared = this.ctx.declaredCollections.find((c) => c.name === m.collection)?.externalMetadata[m.index];
|
|
12790
|
+
throw new DocmetaError(
|
|
12791
|
+
outsideRefusal(declared ?? { file: m.written, keys: [] }, m.collection, resolved.pageRel)
|
|
12792
|
+
);
|
|
12793
|
+
}
|
|
12794
|
+
return { abs: resolved.abs, file: reported2(resolved.abs, this.ctx.base) };
|
|
12795
|
+
}
|
|
12322
12796
|
/** The manifest of one of `members` that owns `key`, in declaration order. */
|
|
12323
12797
|
ownerOf(key, members) {
|
|
12324
12798
|
return this.manifests.find(
|
|
@@ -12404,7 +12878,8 @@ var Model = class {
|
|
|
12404
12878
|
url: false,
|
|
12405
12879
|
absPath,
|
|
12406
12880
|
file,
|
|
12407
|
-
join:
|
|
12881
|
+
join: PATH_JOIN2,
|
|
12882
|
+
perPage: false,
|
|
12408
12883
|
created: true,
|
|
12409
12884
|
keysBefore: [],
|
|
12410
12885
|
keysAdded: [],
|
|
@@ -12441,8 +12916,8 @@ var Model = class {
|
|
|
12441
12916
|
/** A label relative to the config directory, posix; undefined outside it. */
|
|
12442
12917
|
relative(label) {
|
|
12443
12918
|
if (label === "<stdin>") return void 0;
|
|
12444
|
-
const rel = toPosix3(
|
|
12445
|
-
return
|
|
12919
|
+
const rel = toPosix3(relative12(this.configDir, resolve15(this.ctx.base, label)));
|
|
12920
|
+
return isAbsolute8(rel) || rel.startsWith("../") ? void 0 : rel;
|
|
12446
12921
|
}
|
|
12447
12922
|
};
|
|
12448
12923
|
function dedupe2(xs) {
|
|
@@ -12453,17 +12928,17 @@ function bare(path) {
|
|
|
12453
12928
|
}
|
|
12454
12929
|
async function collectionPath(target, cwd, configDir) {
|
|
12455
12930
|
if (target === STDIN_TOKEN) return void 0;
|
|
12456
|
-
const
|
|
12457
|
-
const scanned = picomatch6.scan(
|
|
12931
|
+
const posix7 = target.replace(/\\/g, "/");
|
|
12932
|
+
const scanned = picomatch6.scan(posix7);
|
|
12458
12933
|
if (scanned.isGlob) {
|
|
12459
|
-
const rel2 = toPosix3(
|
|
12460
|
-
if (
|
|
12934
|
+
const rel2 = toPosix3(relative12(configDir, resolve15(cwd, scanned.base === "" ? "." : scanned.base)));
|
|
12935
|
+
if (isAbsolute8(rel2) || rel2 === ".." || rel2.startsWith("../")) return void 0;
|
|
12461
12936
|
return rel2 === "" ? scanned.glob : `${rel2}/${scanned.glob}`;
|
|
12462
12937
|
}
|
|
12463
|
-
const abs =
|
|
12464
|
-
const rel = toPosix3(
|
|
12465
|
-
if (
|
|
12466
|
-
let directory =
|
|
12938
|
+
const abs = resolve15(cwd, posix7);
|
|
12939
|
+
const rel = toPosix3(relative12(configDir, abs));
|
|
12940
|
+
if (isAbsolute8(rel) || rel.startsWith("..")) return void 0;
|
|
12941
|
+
let directory = posix7.endsWith("/");
|
|
12467
12942
|
if (!directory) {
|
|
12468
12943
|
try {
|
|
12469
12944
|
directory = (await stat6(abs)).isDirectory();
|
|
@@ -12484,28 +12959,30 @@ async function exists(absPath, file) {
|
|
|
12484
12959
|
}
|
|
12485
12960
|
}
|
|
12486
12961
|
function plannedConfigDir(ctx) {
|
|
12487
|
-
return ctx.configDir ?? findGitRoot(ctx.cwd) ??
|
|
12962
|
+
return ctx.configDir ?? findGitRoot(ctx.cwd) ?? resolve15(ctx.cwd);
|
|
12488
12963
|
}
|
|
12489
12964
|
async function keyHome(ctx, label, data, key) {
|
|
12490
12965
|
const model = new Model(ctx, plannedConfigDir(ctx));
|
|
12491
12966
|
const owner = model.ownerOf(key, model.members(label));
|
|
12492
12967
|
if (owner !== void 0) {
|
|
12493
|
-
|
|
12968
|
+
const at2 = model.fileFor(owner, resolve15(ctx.base, label));
|
|
12969
|
+
if (owner.url || at2.abs === void 0) {
|
|
12494
12970
|
return { kind: "url", collection: owner.collection, file: owner.file };
|
|
12495
12971
|
}
|
|
12496
12972
|
return {
|
|
12497
12973
|
kind: "manifest",
|
|
12498
12974
|
collection: owner.collection,
|
|
12499
|
-
file:
|
|
12500
|
-
absPath:
|
|
12975
|
+
file: at2.file,
|
|
12976
|
+
absPath: at2.abs,
|
|
12501
12977
|
join: owner.join,
|
|
12502
|
-
entry: entryFor(owner, label, data, model.configDir, ctx.base, lazyKey(ctx.configFile, ctx.env))
|
|
12978
|
+
entry: entryFor(owner, label, data, model.configDir, ctx.base, lazyKey(ctx.configFile, ctx.env)),
|
|
12979
|
+
perPage: owner.perPage
|
|
12503
12980
|
};
|
|
12504
12981
|
}
|
|
12505
12982
|
return { kind: "unowned", home: (await model.home(label, false)).proposed };
|
|
12506
12983
|
}
|
|
12507
12984
|
function entryFor(m, label, data, configDir, base, key) {
|
|
12508
|
-
if (m.join ===
|
|
12985
|
+
if (m.join === PATH_JOIN2) return toPosix3(relative12(configDir, resolve15(base, label)));
|
|
12509
12986
|
let raw = data[m.join];
|
|
12510
12987
|
if (isEncryptedValue(raw)) {
|
|
12511
12988
|
const k = key();
|
|
@@ -12522,6 +12999,27 @@ function entryFor(m, label, data, configDir, base, key) {
|
|
|
12522
12999
|
if (typeof raw === "number" || typeof raw === "boolean") return String(raw);
|
|
12523
13000
|
return void 0;
|
|
12524
13001
|
}
|
|
13002
|
+
async function relocationPages(ctx, request) {
|
|
13003
|
+
const pages2 = new Set(request.files.map((label) => resolve15(ctx.base, label)));
|
|
13004
|
+
const root = ctx.configDir ?? ctx.cwd;
|
|
13005
|
+
for (const collection of ctx.declaredCollections) {
|
|
13006
|
+
const perPage = collection.externalMetadata.some(
|
|
13007
|
+
(m) => classifyRef(m.file).kind !== "url" && hasPagePlaceholder(m.file)
|
|
13008
|
+
);
|
|
13009
|
+
if (!perPage) continue;
|
|
13010
|
+
const walked = await resolveTargetSet({
|
|
13011
|
+
inputs: [...collection.paths],
|
|
13012
|
+
cwd: root,
|
|
13013
|
+
allowEmpty: true,
|
|
13014
|
+
...gitignoreOptions({
|
|
13015
|
+
...ctx.respectGitignore !== void 0 ? { flag: ctx.respectGitignore } : {},
|
|
13016
|
+
...ctx.config?.respectGitignore !== void 0 ? { configured: ctx.config.respectGitignore } : {}
|
|
13017
|
+
})
|
|
13018
|
+
});
|
|
13019
|
+
for (const file of walked.files) pages2.add(resolve15(root, file));
|
|
13020
|
+
}
|
|
13021
|
+
return [...pages2];
|
|
13022
|
+
}
|
|
12525
13023
|
async function planRelocation(ctx, request) {
|
|
12526
13024
|
const configDir = plannedConfigDir(ctx);
|
|
12527
13025
|
const model = new Model(ctx, configDir);
|
|
@@ -12529,7 +13027,8 @@ async function planRelocation(ctx, request) {
|
|
|
12529
13027
|
const index = await loadExternalMetadata(ctx.declaredCollections, {
|
|
12530
13028
|
configDir: ctx.configDir ?? ctx.cwd,
|
|
12531
13029
|
base: ctx.base,
|
|
12532
|
-
offline: ctx.config?.offline ?? false
|
|
13030
|
+
offline: ctx.config?.offline ?? false,
|
|
13031
|
+
pages: await relocationPages(ctx, request)
|
|
12533
13032
|
});
|
|
12534
13033
|
const trustRoot = schemaTrustRoot(ctx.cwd, ctx.configDir);
|
|
12535
13034
|
const forced = ctx.as !== void 0 ? extractorByName(ctx.as) : void 0;
|
|
@@ -12546,17 +13045,17 @@ async function planRelocation(ctx, request) {
|
|
|
12546
13045
|
if (beyond) return void 0;
|
|
12547
13046
|
throw new DocmetaError(`Unsupported file type "${extname3(label)}" for "${label}". Use --as to override.`);
|
|
12548
13047
|
}
|
|
12549
|
-
const absPath =
|
|
13048
|
+
const absPath = resolve15(ctx.base, label);
|
|
12550
13049
|
const elements = resolveElements(label, ctx.config, currentMembers(label));
|
|
12551
13050
|
let content = "";
|
|
12552
13051
|
let own2 = {};
|
|
12553
|
-
let
|
|
13052
|
+
let unreadable2;
|
|
12554
13053
|
if (beyond) {
|
|
12555
13054
|
try {
|
|
12556
13055
|
content = await readFile8(absPath, "utf8");
|
|
12557
13056
|
own2 = extractor.extract(content, label, { elements }).data;
|
|
12558
13057
|
} catch (err) {
|
|
12559
|
-
|
|
13058
|
+
unreadable2 = (errorMessage(err).split("\n")[0] ?? "").replace(/:\s*$/, "");
|
|
12560
13059
|
}
|
|
12561
13060
|
} else {
|
|
12562
13061
|
content = await readFile8(absPath, "utf8");
|
|
@@ -12575,7 +13074,7 @@ async function planRelocation(ctx, request) {
|
|
|
12575
13074
|
extractor,
|
|
12576
13075
|
own: own2,
|
|
12577
13076
|
beyond,
|
|
12578
|
-
...
|
|
13077
|
+
...unreadable2 !== void 0 ? { unreadable: unreadable2 } : {},
|
|
12579
13078
|
intents: /* @__PURE__ */ new Map()
|
|
12580
13079
|
};
|
|
12581
13080
|
pages2.set(label, page);
|
|
@@ -12584,13 +13083,13 @@ async function planRelocation(ctx, request) {
|
|
|
12584
13083
|
const supplied = (m, page, key) => {
|
|
12585
13084
|
if (m.created || index === null) return void 0;
|
|
12586
13085
|
let sv;
|
|
12587
|
-
if (m.join ===
|
|
13086
|
+
if (m.join === PATH_JOIN2) {
|
|
12588
13087
|
sv = index.byPath.get(page.absPath)?.get(key);
|
|
12589
13088
|
} else {
|
|
12590
13089
|
const entry = entryFor(m, page.label, page.own, configDir, ctx.base, encryptionKey);
|
|
12591
13090
|
sv = entry === void 0 ? void 0 : index.byField.get(m.join)?.get(entry)?.get(key);
|
|
12592
13091
|
}
|
|
12593
|
-
return sv !== void 0 && sv.collection === m.collection && sv.file === m.file ? sv : void 0;
|
|
13092
|
+
return sv !== void 0 && sv.collection === m.collection && sv.file === model.fileFor(m, page.absPath).file ? sv : void 0;
|
|
12594
13093
|
};
|
|
12595
13094
|
const stay = (page, key, reason, detail, links = {}) => {
|
|
12596
13095
|
page.intents.set(key, { kind: "stay", reason, detail, ...links });
|
|
@@ -12610,7 +13109,7 @@ async function planRelocation(ctx, request) {
|
|
|
12610
13109
|
}
|
|
12611
13110
|
const held = supplied(m, page, key);
|
|
12612
13111
|
if (held !== void 0 && !deepEqual(held.value, page.own[key])) {
|
|
12613
|
-
stay(page, key, "values-differ", `the page and ${
|
|
13112
|
+
stay(page, key, "values-differ", `the page and ${held.file} hold different values`, { toward: m });
|
|
12614
13113
|
return;
|
|
12615
13114
|
}
|
|
12616
13115
|
page.intents.set(key, { kind: "out", manifest: m, reason, drop: held !== void 0, entry });
|
|
@@ -12623,7 +13122,7 @@ async function planRelocation(ctx, request) {
|
|
|
12623
13122
|
if (entry === void 0) return;
|
|
12624
13123
|
if (Object.hasOwn(page.own, key)) {
|
|
12625
13124
|
if (!deepEqual(held.value, page.own[key])) {
|
|
12626
|
-
stay(page, key, "values-differ", `the page and ${
|
|
13125
|
+
stay(page, key, "values-differ", `the page and ${held.file} hold different values`, { blocks: m });
|
|
12627
13126
|
return;
|
|
12628
13127
|
}
|
|
12629
13128
|
page.intents.set(key, { kind: "in", manifest: m, drop: true, entry, value: held.value });
|
|
@@ -12669,7 +13168,7 @@ async function planRelocation(ctx, request) {
|
|
|
12669
13168
|
preferencesOf.set(label, prefs);
|
|
12670
13169
|
const planned = model.members(label);
|
|
12671
13170
|
const joins = new Set(
|
|
12672
|
-
model.manifests.filter((m) => planned.includes(m.collection) && m.join !==
|
|
13171
|
+
model.manifests.filter((m) => planned.includes(m.collection) && m.join !== PATH_JOIN2).map((m) => m.join)
|
|
12673
13172
|
);
|
|
12674
13173
|
for (const m of model.manifests) {
|
|
12675
13174
|
if (planned.includes(m.collection)) for (const k of [...m.keysBefore, ...m.keysAdded]) marked.add(k);
|
|
@@ -12759,7 +13258,7 @@ async function planRelocation(ctx, request) {
|
|
|
12759
13258
|
});
|
|
12760
13259
|
const labels = dedupe2([
|
|
12761
13260
|
...request.files,
|
|
12762
|
-
...walked.files.map((f) => reported2(
|
|
13261
|
+
...walked.files.map((f) => reported2(resolve15(configDir, f), ctx.base))
|
|
12763
13262
|
]).filter((label) => model.members(label).includes(name2));
|
|
12764
13263
|
for (const label of labels) {
|
|
12765
13264
|
const page = await load(label, !runSet.has(label));
|
|
@@ -12776,7 +13275,7 @@ async function planRelocation(ctx, request) {
|
|
|
12776
13275
|
const changing = covered ? out : out.filter((k) => m.keysAdded.includes(k));
|
|
12777
13276
|
for (const key of changing) if (!page.intents.has(key)) stay(page, key, "unreadable", detail);
|
|
12778
13277
|
for (const key of m.keysRemoved) {
|
|
12779
|
-
const held = m.join !==
|
|
13278
|
+
const held = m.join !== PATH_JOIN2 || !m.created && index?.byPath.get(page.absPath)?.get(key)?.file === model.fileFor(m, page.absPath).file;
|
|
12780
13279
|
if (held && !page.intents.has(key)) stay(page, key, "unreadable", detail, { blocks: m });
|
|
12781
13280
|
}
|
|
12782
13281
|
continue;
|
|
@@ -12827,35 +13326,50 @@ async function planRelocation(ctx, request) {
|
|
|
12827
13326
|
const writes = [];
|
|
12828
13327
|
const lines = /* @__PURE__ */ new Map();
|
|
12829
13328
|
for (const m of model.manifests) {
|
|
12830
|
-
if (m.url
|
|
13329
|
+
if (m.url) continue;
|
|
12831
13330
|
const undeclared = model.finalKeys(m).length === 0 && !m.created;
|
|
12832
|
-
const
|
|
12833
|
-
const
|
|
13331
|
+
const files = /* @__PURE__ */ new Map();
|
|
13332
|
+
const group = (at2) => {
|
|
13333
|
+
if (at2.abs === void 0) return void 0;
|
|
13334
|
+
const have = files.get(at2.abs);
|
|
13335
|
+
if (have !== void 0) return have;
|
|
13336
|
+
const made = { file: at2.file, outs: [], ins: [] };
|
|
13337
|
+
files.set(at2.abs, made);
|
|
13338
|
+
return made;
|
|
13339
|
+
};
|
|
13340
|
+
if (m.created) group({ abs: m.absPath, file: m.file });
|
|
12834
13341
|
for (const page of orderedPages()) {
|
|
12835
13342
|
for (const [key, intent] of orderedIntents(page)) {
|
|
12836
|
-
if (intent.kind === "out" && intent.manifest === m) {
|
|
12837
|
-
|
|
12838
|
-
|
|
12839
|
-
|
|
13343
|
+
if ((intent.kind === "out" || intent.kind === "in") && intent.manifest === m) {
|
|
13344
|
+
const into = group(model.fileFor(m, page.absPath));
|
|
13345
|
+
if (intent.kind === "out") {
|
|
13346
|
+
into?.outs.push({ page: page.label, entry: intent.entry, key, value: page.own[key], drop: intent.drop });
|
|
13347
|
+
} else {
|
|
13348
|
+
into?.ins.push({ entry: intent.entry, key });
|
|
13349
|
+
}
|
|
12840
13350
|
}
|
|
12841
13351
|
}
|
|
12842
13352
|
}
|
|
12843
|
-
if (!undeclared) assertNoStrandedEntries(m, index, pages2, configDir);
|
|
12844
|
-
if (undeclared
|
|
12845
|
-
|
|
12846
|
-
|
|
12847
|
-
|
|
12848
|
-
|
|
12849
|
-
|
|
12850
|
-
|
|
12851
|
-
|
|
12852
|
-
|
|
12853
|
-
|
|
12854
|
-
const
|
|
12855
|
-
|
|
12856
|
-
|
|
12857
|
-
|
|
12858
|
-
|
|
13353
|
+
if (!undeclared) assertNoStrandedEntries(m, index, pages2, configDir, (abs) => model.fileFor(m, abs).file);
|
|
13354
|
+
if (undeclared) continue;
|
|
13355
|
+
for (const [path, { file, outs, ins }] of files) {
|
|
13356
|
+
if (!m.created && outs.length === 0 && ins.length === 0) continue;
|
|
13357
|
+
const disk = m.created ? null : await readManifestText(path, file, m.perPage);
|
|
13358
|
+
let text2 = disk ?? "";
|
|
13359
|
+
const before = text2;
|
|
13360
|
+
const where = { join: m.join, file };
|
|
13361
|
+
for (const o of outs) {
|
|
13362
|
+
if (!o.drop) text2 = spliceManifestValue(text2, { ...where, entry: o.entry, key: o.key, value: o.value }).text;
|
|
13363
|
+
}
|
|
13364
|
+
for (const i of ins) text2 = removeManifestKey(text2, { ...where, entry: i.entry, key: i.key }).text;
|
|
13365
|
+
const found = keyLines2(text2, m.join);
|
|
13366
|
+
for (const o of outs) {
|
|
13367
|
+
const line = found.get(entryId(o.entry, m.join))?.get(o.key);
|
|
13368
|
+
if (line !== void 0) lines.set(lineId(o.page, file, o.key), line);
|
|
13369
|
+
}
|
|
13370
|
+
if (m.created || text2 !== before) {
|
|
13371
|
+
writes.push({ path, text: text2, kind: "manifest", before: disk });
|
|
13372
|
+
}
|
|
12859
13373
|
}
|
|
12860
13374
|
}
|
|
12861
13375
|
const finalCollections = model.final();
|
|
@@ -12954,7 +13468,7 @@ function planPageText(page) {
|
|
|
12954
13468
|
refuse();
|
|
12955
13469
|
}
|
|
12956
13470
|
}
|
|
12957
|
-
function assertNoStrandedEntries(m, index, pages2, configDir) {
|
|
13471
|
+
function assertNoStrandedEntries(m, index, pages2, configDir, fileOf) {
|
|
12958
13472
|
if (index === null || m.keysRemoved.length === 0) return;
|
|
12959
13473
|
for (const key of m.keysRemoved) {
|
|
12960
13474
|
const moved = /* @__PURE__ */ new Set();
|
|
@@ -12962,10 +13476,10 @@ function assertNoStrandedEntries(m, index, pages2, configDir) {
|
|
|
12962
13476
|
const i = page.intents.get(key);
|
|
12963
13477
|
if (i?.kind === "in" && i.manifest === m) moved.add(entryId(i.entry, m.join));
|
|
12964
13478
|
}
|
|
12965
|
-
const stranded = m.join ===
|
|
13479
|
+
const stranded = m.join === PATH_JOIN2 ? [...index.byPath].filter(([abs, values]) => {
|
|
12966
13480
|
const sv = values.get(key);
|
|
12967
|
-
return sv !== void 0 && sv.
|
|
12968
|
-
}).map(([abs]) => toPosix3(
|
|
13481
|
+
return sv !== void 0 && sv.collection === m.collection && sv.file === fileOf(abs);
|
|
13482
|
+
}).map(([abs]) => toPosix3(relative12(configDir, abs))) : [...index.byField.get(m.join) ?? /* @__PURE__ */ new Map()].filter(([, values]) => {
|
|
12969
13483
|
const sv = values.get(key);
|
|
12970
13484
|
return sv !== void 0 && sv.file === m.file && sv.collection === m.collection;
|
|
12971
13485
|
}).map(([value]) => value);
|
|
@@ -12977,29 +13491,29 @@ function assertNoStrandedEntries(m, index, pages2, configDir) {
|
|
|
12977
13491
|
}
|
|
12978
13492
|
}
|
|
12979
13493
|
}
|
|
12980
|
-
async function readManifestText(
|
|
12981
|
-
if (m.absPath === void 0) return "";
|
|
13494
|
+
async function readManifestText(path, file, perPage) {
|
|
12982
13495
|
try {
|
|
12983
|
-
return await readFile8(
|
|
13496
|
+
return await readFile8(path, "utf8");
|
|
12984
13497
|
} catch (err) {
|
|
12985
|
-
|
|
13498
|
+
if (perPage && isMissing(err)) return null;
|
|
13499
|
+
throw new DocmetaError(`Manifest ${file} could not be read: ${errorMessage(err)}`);
|
|
12986
13500
|
}
|
|
12987
13501
|
}
|
|
12988
|
-
var entryId = (entry, join11) => join11 ===
|
|
13502
|
+
var entryId = (entry, join11) => join11 === PATH_JOIN2 ? toPosix3(entry).replace(/^\.\//, "").replace(/\/+/g, "/") : entry;
|
|
12989
13503
|
var lineId = (page, manifest, key) => `${page}\0${manifest}\0${key}`;
|
|
12990
|
-
function
|
|
13504
|
+
function keyLines2(text2, join11) {
|
|
12991
13505
|
const out = /* @__PURE__ */ new Map();
|
|
12992
|
-
const lc = new
|
|
12993
|
-
const doc =
|
|
13506
|
+
const lc = new LineCounter5();
|
|
13507
|
+
const doc = parseDocument7(text2, { lineCounter: lc, uniqueKeys: false });
|
|
12994
13508
|
const root = doc.contents;
|
|
12995
|
-
if (!
|
|
13509
|
+
if (!isMap8(root)) return out;
|
|
12996
13510
|
for (const pair of root.items) {
|
|
12997
|
-
const spelled =
|
|
12998
|
-
if (!
|
|
13511
|
+
const spelled = isScalar7(pair.key) ? String(pair.key.value) : String(pair.key);
|
|
13512
|
+
if (!isMap8(pair.value)) continue;
|
|
12999
13513
|
const keys = /* @__PURE__ */ new Map();
|
|
13000
13514
|
for (const kv of pair.value.items) {
|
|
13001
|
-
const name2 =
|
|
13002
|
-
const range =
|
|
13515
|
+
const name2 = isScalar7(kv.key) ? String(kv.key.value) : String(kv.key);
|
|
13516
|
+
const range = isNode5(kv.key) ? kv.key.range : void 0;
|
|
13003
13517
|
if (range) keys.set(name2, lc.linePos(range[0]).line);
|
|
13004
13518
|
}
|
|
13005
13519
|
out.set(entryId(spelled, join11), keys);
|
|
@@ -13031,10 +13545,10 @@ async function configTarget(ctx, configDir) {
|
|
|
13031
13545
|
return { path: join8(configDir, FAMILY_CONFIG_NAMES[0] ?? "manni.config.yaml"), text: null, disk: null };
|
|
13032
13546
|
}
|
|
13033
13547
|
function editConfig(text2, model, source) {
|
|
13034
|
-
const doc =
|
|
13548
|
+
const doc = parseDocument7(text2 ?? "");
|
|
13035
13549
|
const [problem] = doc.errors;
|
|
13036
13550
|
if (problem !== void 0) throw new DocmetaError(`${source}: invalid YAML: ${problem.message}`);
|
|
13037
|
-
if (doc.contents !== null && !
|
|
13551
|
+
if (doc.contents !== null && !isMap8(doc.contents)) {
|
|
13038
13552
|
throw new DocmetaError(`${source}: top level must be a mapping.`);
|
|
13039
13553
|
}
|
|
13040
13554
|
const fail2 = () => {
|
|
@@ -13044,7 +13558,7 @@ function editConfig(text2, model, source) {
|
|
|
13044
13558
|
if (!isSeq4(node)) return;
|
|
13045
13559
|
node.flow = true;
|
|
13046
13560
|
if (quoted) {
|
|
13047
|
-
for (const item of node.items) if (
|
|
13561
|
+
for (const item of node.items) if (isScalar7(item)) item.type = "QUOTE_DOUBLE";
|
|
13048
13562
|
}
|
|
13049
13563
|
};
|
|
13050
13564
|
const manifestNode = (d, file, keys) => {
|
|
@@ -13058,13 +13572,13 @@ function editConfig(text2, model, source) {
|
|
|
13058
13572
|
for (let i = 0; i < declared; i++) {
|
|
13059
13573
|
const c = model.collections[i];
|
|
13060
13574
|
const node = isSeq4(existing) ? existing.items[i] : void 0;
|
|
13061
|
-
if (c === void 0 || !
|
|
13575
|
+
if (c === void 0 || !isMap8(node)) return fail2();
|
|
13062
13576
|
for (const added of model.pathsAdded.filter((p) => p.collection === c.name)) {
|
|
13063
13577
|
const paths = node.get("paths", true);
|
|
13064
13578
|
if (!isSeq4(paths)) return fail2();
|
|
13065
13579
|
const scalar = doc.createNode(added.path);
|
|
13066
13580
|
const first = paths.items[0];
|
|
13067
|
-
if (
|
|
13581
|
+
if (isScalar7(first) && first.type !== void 0) scalar.type = first.type;
|
|
13068
13582
|
paths.add(scalar);
|
|
13069
13583
|
}
|
|
13070
13584
|
const refs = model.manifestsOf(c.name);
|
|
@@ -13081,7 +13595,7 @@ function editConfig(text2, model, source) {
|
|
|
13081
13595
|
}
|
|
13082
13596
|
if (m.keysAdded.length === 0) continue;
|
|
13083
13597
|
const entry = node.getIn(["externalMetadata", m.index], true);
|
|
13084
|
-
const keys =
|
|
13598
|
+
const keys = isMap8(entry) ? entry.get("keys", true) : void 0;
|
|
13085
13599
|
if (!isSeq4(keys)) return fail2();
|
|
13086
13600
|
for (const key of m.keysAdded) keys.add(doc.createNode(key));
|
|
13087
13601
|
}
|
|
@@ -13090,10 +13604,10 @@ function editConfig(text2, model, source) {
|
|
|
13090
13604
|
if (m.keysRemoved.length === 0) continue;
|
|
13091
13605
|
if (!isSeq4(list2)) return fail2();
|
|
13092
13606
|
const entry = list2.items[m.index];
|
|
13093
|
-
const keys =
|
|
13607
|
+
const keys = isMap8(entry) ? entry.get("keys", true) : void 0;
|
|
13094
13608
|
if (!isSeq4(keys)) return fail2();
|
|
13095
13609
|
for (const key of m.keysRemoved) {
|
|
13096
|
-
const at2 = keys.items.findIndex((item) => (
|
|
13610
|
+
const at2 = keys.items.findIndex((item) => (isScalar7(item) ? String(item.value) : String(item)) === key);
|
|
13097
13611
|
if (at2 >= 0) keys.delete(at2);
|
|
13098
13612
|
}
|
|
13099
13613
|
if (keys.items.length === 0) list2.delete(m.index);
|
|
@@ -13112,7 +13626,7 @@ function editConfig(text2, model, source) {
|
|
|
13112
13626
|
flowSeq(node.get("paths", true), true);
|
|
13113
13627
|
const made = node.get("externalMetadata", true);
|
|
13114
13628
|
if (isSeq4(made)) {
|
|
13115
|
-
for (const item of made.items) if (
|
|
13629
|
+
for (const item of made.items) if (isMap8(item)) flowSeq(item.get("keys", true), false);
|
|
13116
13630
|
}
|
|
13117
13631
|
const seq = doc.get("collections", true);
|
|
13118
13632
|
if (isSeq4(seq)) seq.add(node);
|
|
@@ -13147,16 +13661,18 @@ function buildResult(input) {
|
|
|
13147
13661
|
const moved = [];
|
|
13148
13662
|
const stayed = [];
|
|
13149
13663
|
const intents = orderedIntents(page);
|
|
13664
|
+
const fileOf = (m) => model.fileFor(m, page.absPath).file;
|
|
13150
13665
|
for (const [key, intent] of intents) {
|
|
13151
|
-
if (intent.kind === "in") moved.push({ key, to: "page", from: intent.manifest
|
|
13666
|
+
if (intent.kind === "in") moved.push({ key, to: "page", from: fileOf(intent.manifest), reason: "preferred" });
|
|
13152
13667
|
}
|
|
13153
13668
|
for (const [key, intent] of intents) {
|
|
13154
13669
|
if (intent.kind !== "out") continue;
|
|
13155
|
-
const
|
|
13670
|
+
const manifest = fileOf(intent.manifest);
|
|
13671
|
+
const line = dryRun ? void 0 : lines.get(lineId(page.label, manifest, key));
|
|
13156
13672
|
moved.push({
|
|
13157
13673
|
key,
|
|
13158
13674
|
to: "manifest",
|
|
13159
|
-
manifest
|
|
13675
|
+
manifest,
|
|
13160
13676
|
...line !== void 0 ? { line } : {},
|
|
13161
13677
|
reason: intent.reason
|
|
13162
13678
|
});
|
|
@@ -13201,7 +13717,7 @@ function buildResult(input) {
|
|
|
13201
13717
|
};
|
|
13202
13718
|
}
|
|
13203
13719
|
async function applyRelocation(ctx, plan, io = {}) {
|
|
13204
|
-
const write = io.write ?? ((path, text2) => writeFileAtomic(path, text2));
|
|
13720
|
+
const write = io.write ?? ((path, text2) => writeFileAtomic(path, text2, { createParents: true }));
|
|
13205
13721
|
const remove = io.remove ?? ((path) => unlink(path));
|
|
13206
13722
|
const label = (w) => w.kind === "config" ? configSource(w.path, ctx.cwd) : reported2(w.path, ctx.base);
|
|
13207
13723
|
for (const w of plan.writes) {
|
|
@@ -13374,7 +13890,7 @@ function relocationOffers(plan) {
|
|
|
13374
13890
|
}
|
|
13375
13891
|
|
|
13376
13892
|
// src/meta/commands/validate.ts
|
|
13377
|
-
import { resolve as
|
|
13893
|
+
import { resolve as resolve17, extname as extname4 } from "node:path";
|
|
13378
13894
|
|
|
13379
13895
|
// src/meta/core/checks.ts
|
|
13380
13896
|
var CHECK_KEYWORD = "check";
|
|
@@ -13512,8 +14028,8 @@ async function runChecks(checks, entries, ctx = {}) {
|
|
|
13512
14028
|
}
|
|
13513
14029
|
|
|
13514
14030
|
// src/meta/core/derive/provenance-place.ts
|
|
13515
|
-
import { isAbsolute as
|
|
13516
|
-
var toPosix4 = (p) => p.split(
|
|
14031
|
+
import { isAbsolute as isAbsolute9, relative as relative13, resolve as resolve16, sep as sep8 } from "node:path";
|
|
14032
|
+
var toPosix4 = (p) => p.split(sep8).join("/");
|
|
13517
14033
|
function provenanceManifests(collections, configDir, base) {
|
|
13518
14034
|
const out = [];
|
|
13519
14035
|
for (const collection of collections) {
|
|
@@ -13524,13 +14040,15 @@ function provenanceManifests(collections, configDir, base) {
|
|
|
13524
14040
|
`collection ${collection.name}: ${PROVENANCE_FIELD} cannot come from a URL manifest, because manni meta derive writes it.`
|
|
13525
14041
|
);
|
|
13526
14042
|
}
|
|
13527
|
-
const absPath =
|
|
13528
|
-
const
|
|
14043
|
+
const absPath = isAbsolute9(manifest.file) ? manifest.file : resolve16(configDir, manifest.file);
|
|
14044
|
+
const perPage = hasPagePlaceholder(manifest.file);
|
|
13529
14045
|
out.push({
|
|
13530
14046
|
collection: collection.name,
|
|
13531
14047
|
absPath,
|
|
13532
|
-
file:
|
|
13533
|
-
join: externalMetadataJoin(manifest)
|
|
14048
|
+
file: perPage ? manifest.file : reportedPath(absPath, base),
|
|
14049
|
+
join: externalMetadataJoin(manifest),
|
|
14050
|
+
perPage,
|
|
14051
|
+
written: manifest.file
|
|
13534
14052
|
});
|
|
13535
14053
|
}
|
|
13536
14054
|
}
|
|
@@ -13540,15 +14058,16 @@ function provenancePlace(label, data, manifests, collections, configDir, base) {
|
|
|
13540
14058
|
if (manifests.length === 0) return void 0;
|
|
13541
14059
|
const members = new Set(memberOf(collections, configDir, base, label));
|
|
13542
14060
|
const owning = manifests.filter((m) => members.has(m.collection));
|
|
13543
|
-
const [
|
|
13544
|
-
if (
|
|
14061
|
+
const [declared, second] = owning;
|
|
14062
|
+
if (declared === void 0) return void 0;
|
|
13545
14063
|
if (second !== void 0) {
|
|
13546
14064
|
throw new DocmetaError(
|
|
13547
|
-
`${label} is in collections ${
|
|
14065
|
+
`${label} is in collections ${declared.collection} and ${second.collection}, and both keep ${PROVENANCE_FIELD} in a manifest.`
|
|
13548
14066
|
);
|
|
13549
14067
|
}
|
|
13550
|
-
|
|
13551
|
-
|
|
14068
|
+
const manifest = declared.perPage ? ownManifest(declared, label, collections, configDir, base) : declared;
|
|
14069
|
+
if (manifest.join === PATH_JOIN2) {
|
|
14070
|
+
const entry = toPosix4(relative13(configDir, resolve16(base, label)));
|
|
13552
14071
|
return { manifest, absPath: manifest.absPath, entry, join: manifest.join };
|
|
13553
14072
|
}
|
|
13554
14073
|
const value = data[manifest.join];
|
|
@@ -13559,6 +14078,16 @@ function provenancePlace(label, data, manifests, collections, configDir, base) {
|
|
|
13559
14078
|
}
|
|
13560
14079
|
return { manifest, absPath: manifest.absPath, entry: String(value), join: manifest.join };
|
|
13561
14080
|
}
|
|
14081
|
+
function ownManifest(manifest, label, collections, configDir, base) {
|
|
14082
|
+
const resolved = pageManifestPath(manifest.written, configDir, resolve16(base, label));
|
|
14083
|
+
if ("outside" in resolved) {
|
|
14084
|
+
const declared = collections.find((c) => c.name === manifest.collection)?.externalMetadata.find((m) => m.file === manifest.written);
|
|
14085
|
+
throw new DocmetaError(
|
|
14086
|
+
outsideRefusal(declared ?? { file: manifest.written, keys: [] }, manifest.collection, resolved.pageRel)
|
|
14087
|
+
);
|
|
14088
|
+
}
|
|
14089
|
+
return { ...manifest, absPath: resolved.abs, file: reportedPath(resolved.abs, base) };
|
|
14090
|
+
}
|
|
13562
14091
|
function readerManifests(collections, configDir, base) {
|
|
13563
14092
|
const local = collections.map((c) => ({
|
|
13564
14093
|
...c,
|
|
@@ -13657,7 +14186,9 @@ async function runValidate(opts) {
|
|
|
13657
14186
|
const externalMetadata = await loadExternalMetadata(collections, {
|
|
13658
14187
|
configDir: configDir ?? cwd,
|
|
13659
14188
|
base,
|
|
13660
|
-
offline: opts.offline ?? config?.offline ?? false
|
|
14189
|
+
offline: opts.offline ?? config?.offline ?? false,
|
|
14190
|
+
// A `{page}` manifest (0058) is read for exactly the pages this run reads.
|
|
14191
|
+
pages: files.map((file) => resolve17(base, file))
|
|
13661
14192
|
});
|
|
13662
14193
|
const validator = new Validator(
|
|
13663
14194
|
schemaLoadOptions({
|
|
@@ -13688,7 +14219,7 @@ async function runValidate(opts) {
|
|
|
13688
14219
|
const owned = new Set(merged.collisions.map((c) => c.key));
|
|
13689
14220
|
const declaredMembers = declaredCollections === collections ? members : memberOf(declaredCollections, configDir ?? cwd, base, label);
|
|
13690
14221
|
const joins = new Set(
|
|
13691
|
-
declaredCollections.filter((c) => declaredMembers.includes(c.name)).flatMap((c) => c.externalMetadata.map(externalMetadataJoin)).filter((join11) => join11 !==
|
|
14222
|
+
declaredCollections.filter((c) => declaredMembers.includes(c.name)).flatMap((c) => c.externalMetadata.map(externalMetadataJoin)).filter((join11) => join11 !== PATH_JOIN2)
|
|
13692
14223
|
);
|
|
13693
14224
|
const findings = [];
|
|
13694
14225
|
for (const key of Object.keys(data)) {
|
|
@@ -13812,7 +14343,7 @@ async function runValidate(opts) {
|
|
|
13812
14343
|
const place = provenanceManifests2.length === 0 ? void 0 : readerPlace(label, extracted.data, provenanceManifests2, declaredCollections, configDir ?? cwd, base);
|
|
13813
14344
|
deriveInputs.push({
|
|
13814
14345
|
label,
|
|
13815
|
-
absPath:
|
|
14346
|
+
absPath: resolve17(base, label),
|
|
13816
14347
|
content,
|
|
13817
14348
|
extracted,
|
|
13818
14349
|
...place !== void 0 ? { provenanceManifest: place } : {}
|
|
@@ -13943,7 +14474,7 @@ async function runValidate(opts) {
|
|
|
13943
14474
|
await processOne(STDIN_LABEL, content, forcedExtractor.extensions[0] ?? "");
|
|
13944
14475
|
}
|
|
13945
14476
|
for (const file of files) {
|
|
13946
|
-
const content = await readFile9(
|
|
14477
|
+
const content = await readFile9(resolve17(base, file), "utf8");
|
|
13947
14478
|
await processOne(file, content, extname4(file));
|
|
13948
14479
|
}
|
|
13949
14480
|
if (unverified > 0) opts.onNotice?.(unverifiedWarning(unverified));
|
|
@@ -14089,7 +14620,7 @@ async function runValidate(opts) {
|
|
|
14089
14620
|
|
|
14090
14621
|
// src/meta/commands/get.ts
|
|
14091
14622
|
import { readFile as readFile10 } from "node:fs/promises";
|
|
14092
|
-
import { resolve as
|
|
14623
|
+
import { resolve as resolve18, extname as extname5 } from "node:path";
|
|
14093
14624
|
async function runGet(opts) {
|
|
14094
14625
|
const cwd = opts.cwd ?? process.cwd();
|
|
14095
14626
|
if (opts.fields.length === 0) {
|
|
@@ -14148,7 +14679,9 @@ async function runGet(opts) {
|
|
|
14148
14679
|
const externalMetadata = await loadExternalMetadata(collections, {
|
|
14149
14680
|
configDir: configDir ?? cwd,
|
|
14150
14681
|
base,
|
|
14151
|
-
offline: opts.offline ?? config?.offline ?? false
|
|
14682
|
+
offline: opts.offline ?? config?.offline ?? false,
|
|
14683
|
+
// A `{page}` manifest (0058) is read for exactly the pages this run reads.
|
|
14684
|
+
pages: files.map((file) => resolve18(base, file))
|
|
14152
14685
|
});
|
|
14153
14686
|
const commands = commandsOf(config?.derive) ?? {};
|
|
14154
14687
|
const deriving = opts.derived !== false;
|
|
@@ -14175,7 +14708,7 @@ async function runGet(opts) {
|
|
|
14175
14708
|
const place = provenanceManifests2.length === 0 ? void 0 : readerPlace(label, own2.data, provenanceManifests2, declaredCollections, configDir ?? cwd, base);
|
|
14176
14709
|
deriveInputs.push({
|
|
14177
14710
|
label,
|
|
14178
|
-
absPath:
|
|
14711
|
+
absPath: resolve18(base, label),
|
|
14179
14712
|
content,
|
|
14180
14713
|
extracted: own2,
|
|
14181
14714
|
...place !== void 0 ? { provenanceManifest: place } : {}
|
|
@@ -14217,7 +14750,7 @@ async function runGet(opts) {
|
|
|
14217
14750
|
readOne(STDIN_LABEL, opts.stdinContent ?? "", forced.extensions[0] ?? "");
|
|
14218
14751
|
}
|
|
14219
14752
|
for (const file of files) {
|
|
14220
|
-
const content = await readFile10(
|
|
14753
|
+
const content = await readFile10(resolve18(base, file), "utf8");
|
|
14221
14754
|
readOne(file, content, extname5(file));
|
|
14222
14755
|
}
|
|
14223
14756
|
if (deriving) {
|
|
@@ -14343,16 +14876,16 @@ function parseJsonPointer(pointer) {
|
|
|
14343
14876
|
|
|
14344
14877
|
// src/meta/commands/schemas.ts
|
|
14345
14878
|
import { existsSync as existsSync4 } from "node:fs";
|
|
14346
|
-
import { mkdir as
|
|
14347
|
-
import { dirname as dirname10, extname as extname6, isAbsolute as
|
|
14348
|
-
import { parseDocument as
|
|
14879
|
+
import { mkdir as mkdir3, readFile as readFile11 } from "node:fs/promises";
|
|
14880
|
+
import { dirname as dirname10, extname as extname6, isAbsolute as isAbsolute10, join as join9, relative as relative14, resolve as resolve19, sep as sep9 } from "node:path";
|
|
14881
|
+
import { parseDocument as parseDocument8, parse as parseYaml6, stringify as stringify4 } from "yaml";
|
|
14349
14882
|
function getSchemasInfo() {
|
|
14350
14883
|
return { builtins: listBuiltins(), formats: listFormats() };
|
|
14351
14884
|
}
|
|
14352
14885
|
var DEFAULT_VENDOR_DIR = "./schema";
|
|
14353
14886
|
var DEFAULT_CONFIG_NAME = "manni.config.yaml";
|
|
14354
14887
|
function posixRelative(from, to) {
|
|
14355
|
-
return
|
|
14888
|
+
return relative14(from, to).split(sep9).join("/");
|
|
14356
14889
|
}
|
|
14357
14890
|
function vendorFileName(url) {
|
|
14358
14891
|
let parsed2;
|
|
@@ -14415,9 +14948,9 @@ function foldEntry(entries, next) {
|
|
|
14415
14948
|
}
|
|
14416
14949
|
function renderConfig(existing, entries, section) {
|
|
14417
14950
|
if (existing === null) {
|
|
14418
|
-
return
|
|
14951
|
+
return stringify4({ [META_SECTION]: { schemas: entries } });
|
|
14419
14952
|
}
|
|
14420
|
-
const doc =
|
|
14953
|
+
const doc = parseDocument8(existing);
|
|
14421
14954
|
doc.setIn(section === void 0 ? ["schemas"] : [section, "schemas"], entries);
|
|
14422
14955
|
return doc.toString();
|
|
14423
14956
|
}
|
|
@@ -14438,13 +14971,13 @@ async function runVendorSchema(opts) {
|
|
|
14438
14971
|
);
|
|
14439
14972
|
}
|
|
14440
14973
|
const loaded = await loadConfig(opts.configPath, cwd);
|
|
14441
|
-
const configPath = loaded?.path ??
|
|
14974
|
+
const configPath = loaded?.path ?? resolve19(cwd, DEFAULT_CONFIG_NAME);
|
|
14442
14975
|
const configDir = loaded?.dir ?? cwd;
|
|
14443
|
-
const absDir =
|
|
14976
|
+
const absDir = resolve19(cwd, opts.dir ?? DEFAULT_VENDOR_DIR);
|
|
14444
14977
|
const absFile = join9(absDir, vendorFileName(url));
|
|
14445
14978
|
await assertNotIgnored(absFile, absDir, cwd, opts.onNotice);
|
|
14446
14979
|
const fromConfig = posixRelative(configDir, absFile);
|
|
14447
|
-
const ref =
|
|
14980
|
+
const ref = isAbsolute10(fromConfig) || fromConfig === "" ? absFile : fromConfig.startsWith(".") ? fromConfig : `./${fromConfig}`;
|
|
14448
14981
|
const { bytes } = await fetchSchemaBytes(url, {
|
|
14449
14982
|
...opts.timeoutMs !== void 0 ? { timeoutMs: opts.timeoutMs } : {},
|
|
14450
14983
|
...opts.maxBytes !== void 0 ? { maxBytes: opts.maxBytes } : {}
|
|
@@ -14467,7 +15000,7 @@ async function runVendorSchema(opts) {
|
|
|
14467
15000
|
);
|
|
14468
15001
|
}
|
|
14469
15002
|
}
|
|
14470
|
-
await
|
|
15003
|
+
await mkdir3(absDir, { recursive: true });
|
|
14471
15004
|
await writeFileAtomic(absFile, bytes);
|
|
14472
15005
|
const existing = loaded ? await readFile11(configPath, "utf8") : null;
|
|
14473
15006
|
const section = loaded ? loaded.section : META_SECTION;
|
|
@@ -14598,11 +15131,6 @@ async function runInferSchema(opts) {
|
|
|
14598
15131
|
});
|
|
14599
15132
|
const joinKey = lazyKey(configFile, void 0);
|
|
14600
15133
|
const usingStdin = inputs.includes(STDIN_TOKEN);
|
|
14601
|
-
const externalMetadata = await loadExternalMetadata(collections, {
|
|
14602
|
-
configDir: configDir ?? cwd,
|
|
14603
|
-
base,
|
|
14604
|
-
offline: opts.offline ?? config?.offline ?? false
|
|
14605
|
-
});
|
|
14606
15134
|
if (inputs.length === 0) {
|
|
14607
15135
|
throw new DocmetaError(
|
|
14608
15136
|
"No files to scan. Pass paths/globs, or declare a collection under `collections:` in manni.config.yaml."
|
|
@@ -14621,7 +15149,7 @@ async function runInferSchema(opts) {
|
|
|
14621
15149
|
}
|
|
14622
15150
|
let absOut;
|
|
14623
15151
|
if (opts.out !== void 0) {
|
|
14624
|
-
absOut =
|
|
15152
|
+
absOut = resolve19(cwd, opts.out);
|
|
14625
15153
|
await assertNotIgnored(
|
|
14626
15154
|
absOut,
|
|
14627
15155
|
dirname10(absOut),
|
|
@@ -14663,8 +15191,14 @@ async function runInferSchema(opts) {
|
|
|
14663
15191
|
gitignoreSkipped,
|
|
14664
15192
|
action: "scanned"
|
|
14665
15193
|
});
|
|
15194
|
+
const externalMetadata = await loadExternalMetadata(collections, {
|
|
15195
|
+
configDir: configDir ?? cwd,
|
|
15196
|
+
base,
|
|
15197
|
+
offline: opts.offline ?? config?.offline ?? false,
|
|
15198
|
+
pages: files.map((file) => resolve19(base, file))
|
|
15199
|
+
});
|
|
14666
15200
|
const stats = /* @__PURE__ */ new Map();
|
|
14667
|
-
const
|
|
15201
|
+
const unreadable2 = [];
|
|
14668
15202
|
let filesScanned = 0;
|
|
14669
15203
|
let filesWithoutMetadata = 0;
|
|
14670
15204
|
const scanOne = (label, content, extension) => {
|
|
@@ -14689,7 +15223,7 @@ async function runInferSchema(opts) {
|
|
|
14689
15223
|
{ encryptionKey: joinKey }
|
|
14690
15224
|
).extracted;
|
|
14691
15225
|
} catch (err) {
|
|
14692
|
-
|
|
15226
|
+
unreadable2.push({
|
|
14693
15227
|
file: label,
|
|
14694
15228
|
message: err instanceof Error ? err.message : String(err)
|
|
14695
15229
|
});
|
|
@@ -14709,10 +15243,10 @@ async function runInferSchema(opts) {
|
|
|
14709
15243
|
scanOne(STDIN_LABEL, opts.stdinContent ?? "", forced.extensions[0] ?? "");
|
|
14710
15244
|
}
|
|
14711
15245
|
for (const file of files) {
|
|
14712
|
-
const content = await readFile11(
|
|
15246
|
+
const content = await readFile11(resolve19(base, file), "utf8");
|
|
14713
15247
|
scanOne(file, content, extname6(file));
|
|
14714
15248
|
}
|
|
14715
|
-
for (const u of
|
|
15249
|
+
for (const u of unreadable2) {
|
|
14716
15250
|
opts.onNotice?.(`could not read metadata from "${u.file}": ${u.message}`);
|
|
14717
15251
|
}
|
|
14718
15252
|
const all = [...stats.entries()].map(([key, stat7]) => {
|
|
@@ -14751,14 +15285,14 @@ async function runInferSchema(opts) {
|
|
|
14751
15285
|
};
|
|
14752
15286
|
const keys = kept.map(({ sawEmptyString: _drop, ...rest }) => rest);
|
|
14753
15287
|
if (absOut !== void 0) {
|
|
14754
|
-
await
|
|
15288
|
+
await mkdir3(dirname10(absOut), { recursive: true });
|
|
14755
15289
|
await writeFileAtomic(absOut, `${JSON.stringify(draft, null, 2)}
|
|
14756
15290
|
`);
|
|
14757
15291
|
}
|
|
14758
15292
|
return {
|
|
14759
15293
|
filesScanned,
|
|
14760
15294
|
filesWithoutMetadata,
|
|
14761
|
-
unreadable,
|
|
15295
|
+
unreadable: unreadable2,
|
|
14762
15296
|
keys,
|
|
14763
15297
|
hiddenByMinCoverage: all.length - kept.length,
|
|
14764
15298
|
draft,
|
|
@@ -14770,8 +15304,8 @@ async function runInferSchema(opts) {
|
|
|
14770
15304
|
// src/meta/commands/query.ts
|
|
14771
15305
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
14772
15306
|
import { existsSync as existsSync5 } from "node:fs";
|
|
14773
|
-
import { mkdir as
|
|
14774
|
-
import { dirname as dirname11, isAbsolute as
|
|
15307
|
+
import { mkdir as mkdir4, open as open2, readFile as readFile12, rename as rename3, rm as rm3 } from "node:fs/promises";
|
|
15308
|
+
import { dirname as dirname11, isAbsolute as isAbsolute11, resolve as resolve20, extname as extname7, sep as sep10 } from "node:path";
|
|
14775
15309
|
|
|
14776
15310
|
// src/shared/prompt.ts
|
|
14777
15311
|
import { createInterface } from "node:readline";
|
|
@@ -14829,10 +15363,10 @@ async function ensureEncryptionKey(opts) {
|
|
|
14829
15363
|
}
|
|
14830
15364
|
|
|
14831
15365
|
// src/meta/commands/query.ts
|
|
14832
|
-
import { parseDocument as
|
|
15366
|
+
import { parseDocument as parseDocument10, isMap as isMap10, isSeq as isSeq5, isScalar as isScalar9 } from "yaml";
|
|
14833
15367
|
|
|
14834
15368
|
// src/meta/core/location-writes.ts
|
|
14835
|
-
import { LineCounter as
|
|
15369
|
+
import { LineCounter as LineCounter6, isMap as isMap9, isNode as isNode6, isScalar as isScalar8, parseDocument as parseDocument9 } from "yaml";
|
|
14836
15370
|
var dedupe3 = (xs) => [...new Set(xs)];
|
|
14837
15371
|
var pages = (n) => `${String(n)} page${n === 1 ? "" : "s"}`;
|
|
14838
15372
|
async function offerExternalHomes(ctx, writes, hooks) {
|
|
@@ -14915,17 +15449,17 @@ function externalWriteWarning(line) {
|
|
|
14915
15449
|
return home.reason === "no-config" ? `${head}; ${prefer}, and --no-config leaves ${them} no manifest.` : `${head} that ${line.pages === 1 ? "is" : "are"} in none of the ${String(home.collections)} collections; ${prefer}, and only a collection has a manifest.`;
|
|
14916
15450
|
}
|
|
14917
15451
|
function manifestKeyLine(text2, entry, key, join11) {
|
|
14918
|
-
const norm = (e) => join11 ===
|
|
14919
|
-
const lc = new
|
|
14920
|
-
const doc =
|
|
15452
|
+
const norm = (e) => join11 === PATH_JOIN2 ? e.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/+/g, "/") : e;
|
|
15453
|
+
const lc = new LineCounter6();
|
|
15454
|
+
const doc = parseDocument9(text2, { lineCounter: lc, uniqueKeys: false });
|
|
14921
15455
|
const root = doc.contents;
|
|
14922
|
-
if (!
|
|
15456
|
+
if (!isMap9(root)) return void 0;
|
|
14923
15457
|
for (const pair of root.items) {
|
|
14924
|
-
const spelled =
|
|
14925
|
-
if (norm(spelled) !== norm(entry) || !
|
|
15458
|
+
const spelled = isScalar8(pair.key) ? String(pair.key.value) : String(pair.key);
|
|
15459
|
+
if (norm(spelled) !== norm(entry) || !isMap9(pair.value)) continue;
|
|
14926
15460
|
for (const kv of pair.value.items) {
|
|
14927
|
-
const name2 =
|
|
14928
|
-
const range =
|
|
15461
|
+
const name2 = isScalar8(kv.key) ? String(kv.key.value) : String(kv.key);
|
|
15462
|
+
const range = isNode6(kv.key) ? kv.key.range : void 0;
|
|
14929
15463
|
if (name2 === key && range) return lc.linePos(range[0]).line;
|
|
14930
15464
|
}
|
|
14931
15465
|
}
|
|
@@ -15028,7 +15562,9 @@ async function runQuery(opts) {
|
|
|
15028
15562
|
const externalMetadata = await loadExternalMetadata(collections, {
|
|
15029
15563
|
configDir: configDir ?? cwd,
|
|
15030
15564
|
base,
|
|
15031
|
-
offline: opts.offline ?? config?.offline ?? false
|
|
15565
|
+
offline: opts.offline ?? config?.offline ?? false,
|
|
15566
|
+
// A `{page}` manifest (0058) is read for exactly the pages this run reads.
|
|
15567
|
+
pages: files.map((file) => resolve20(base, file))
|
|
15032
15568
|
});
|
|
15033
15569
|
const configuredKey = lazyKey(configFile, opts.env);
|
|
15034
15570
|
let ensuredKey;
|
|
@@ -15110,10 +15646,10 @@ async function runQuery(opts) {
|
|
|
15110
15646
|
readOne(STDIN_LABEL, opts.stdinContent ?? "", ext);
|
|
15111
15647
|
}
|
|
15112
15648
|
for (const file of files) {
|
|
15113
|
-
const content = await readFile12(
|
|
15649
|
+
const content = await readFile12(resolve20(base, file), "utf8");
|
|
15114
15650
|
readOne(file, content, extname7(file));
|
|
15115
15651
|
}
|
|
15116
|
-
const db = opts.db === void 0 ? void 0 : { resolved:
|
|
15652
|
+
const db = opts.db === void 0 ? void 0 : { resolved: resolve20(cwd, opts.db), display: opts.db };
|
|
15117
15653
|
const run2 = await runSql(sql, entries, {
|
|
15118
15654
|
target: db,
|
|
15119
15655
|
params: boundParams,
|
|
@@ -15210,7 +15746,7 @@ async function runSql(sql, entries, ctx) {
|
|
|
15210
15746
|
);
|
|
15211
15747
|
const { DatabaseSync } = await loadSqlite();
|
|
15212
15748
|
if (target) {
|
|
15213
|
-
await
|
|
15749
|
+
await mkdir4(dirname11(target.resolved), { recursive: true });
|
|
15214
15750
|
await prepareDbTarget(target.resolved, target.display);
|
|
15215
15751
|
}
|
|
15216
15752
|
let db;
|
|
@@ -15254,7 +15790,7 @@ async function runSql(sql, entries, ctx) {
|
|
|
15254
15790
|
const place = manifests.length === 0 ? void 0 : readerPlace(e.label, e.own.data, manifests, ctx.declaredCollections, manifestRoot, ctx.base);
|
|
15255
15791
|
return {
|
|
15256
15792
|
label: e.label,
|
|
15257
|
-
absPath:
|
|
15793
|
+
absPath: resolve20(ctx.base, e.label),
|
|
15258
15794
|
content: e.content,
|
|
15259
15795
|
extracted: e.own,
|
|
15260
15796
|
...place !== void 0 ? { provenanceManifest: place } : {}
|
|
@@ -15719,20 +16255,20 @@ function displayPath(ctx, abs) {
|
|
|
15719
16255
|
}
|
|
15720
16256
|
function assertSchemaWriteWithin(ctx, abs) {
|
|
15721
16257
|
const within = posixRelative(ctx.trustRoot.dir, abs);
|
|
15722
|
-
if (within !== "" && !within.startsWith("..") && !
|
|
16258
|
+
if (within !== "" && !within.startsWith("..") && !isAbsolute11(within)) return;
|
|
15723
16259
|
throw new DocmetaError(
|
|
15724
16260
|
`The resolved schema "${abs}" lives outside ${ctx.trustRoot.dir}; DDL edits schemas inside the repository. Evolve it where it lives, or vendor a copy in.`
|
|
15725
16261
|
);
|
|
15726
16262
|
}
|
|
15727
16263
|
function foldPath(p) {
|
|
15728
|
-
const abs =
|
|
16264
|
+
const abs = resolve20(p);
|
|
15729
16265
|
return process.platform === "win32" ? abs.toLowerCase() : abs;
|
|
15730
16266
|
}
|
|
15731
16267
|
function filePinsByPath(ctx) {
|
|
15732
16268
|
const byPath = /* @__PURE__ */ new Map();
|
|
15733
16269
|
for (const [ref, pin] of collectSchemaPins(ctx.config)) {
|
|
15734
16270
|
if (classifyRef(ref).kind !== "file") continue;
|
|
15735
|
-
byPath.set(foldPath(
|
|
16271
|
+
byPath.set(foldPath(resolve20(ctx.cwd, ref)), pin);
|
|
15736
16272
|
}
|
|
15737
16273
|
return byPath;
|
|
15738
16274
|
}
|
|
@@ -15760,7 +16296,7 @@ async function loadSetMembers(refs, ctx) {
|
|
|
15760
16296
|
});
|
|
15761
16297
|
continue;
|
|
15762
16298
|
}
|
|
15763
|
-
const abs =
|
|
16299
|
+
const abs = resolve20(ctx.cwd, ref);
|
|
15764
16300
|
const canon = foldPath(abs);
|
|
15765
16301
|
if (seenFiles.has(canon)) continue;
|
|
15766
16302
|
seenFiles.add(canon);
|
|
@@ -15965,7 +16501,7 @@ async function planSchemaMutation(ops, entries, ctx) {
|
|
|
15965
16501
|
const [, name2, ver] = target.builtinId.split(":");
|
|
15966
16502
|
const safe = (s) => s.replace(/[^A-Za-z0-9._-]/g, "-");
|
|
15967
16503
|
const forkName = `${safe(name2 ?? "schema")}-${safe(ver ?? "0")}.local.json`;
|
|
15968
|
-
schemaAbs =
|
|
16504
|
+
schemaAbs = resolve20(ctx.configDir ?? ctx.cwd, "schemas", forkName);
|
|
15969
16505
|
assertSchemaWriteWithin(ctx, schemaAbs);
|
|
15970
16506
|
if (existsSync5(schemaAbs)) {
|
|
15971
16507
|
throw new DocmetaError(
|
|
@@ -16122,17 +16658,17 @@ async function planConfigEdit(ctx, edit, runRefs) {
|
|
|
16122
16658
|
return { changes: [], repointed: false };
|
|
16123
16659
|
}
|
|
16124
16660
|
const text2 = await readFile12(configPath, "utf8");
|
|
16125
|
-
const doc =
|
|
16661
|
+
const doc = parseDocument10(stripBom2(text2));
|
|
16126
16662
|
const display = displayPath(ctx, configPath);
|
|
16127
16663
|
const rawRefOf = (item) => {
|
|
16128
|
-
if (
|
|
16129
|
-
if (
|
|
16664
|
+
if (isScalar9(item) && typeof item.value === "string") return item.value;
|
|
16665
|
+
if (isMap10(item)) {
|
|
16130
16666
|
const ref = item.get("ref");
|
|
16131
16667
|
if (typeof ref === "string") return ref;
|
|
16132
16668
|
}
|
|
16133
16669
|
return void 0;
|
|
16134
16670
|
};
|
|
16135
|
-
const rebaseRaw = (raw) => classifyRef(raw).kind === "file" && !
|
|
16671
|
+
const rebaseRaw = (raw) => classifyRef(raw).kind === "file" && !isAbsolute11(raw) ? resolve20(configDir, raw) : raw;
|
|
16136
16672
|
const wantSet = runRefs.map(rebaseRaw).sort().join("\n");
|
|
16137
16673
|
const seqResolvesToRunSet = (node) => {
|
|
16138
16674
|
if (!isSeq5(node)) return false;
|
|
@@ -16148,10 +16684,10 @@ async function planConfigEdit(ctx, edit, runRefs) {
|
|
|
16148
16684
|
for (const item of node.items) {
|
|
16149
16685
|
const raw = rawRefOf(item);
|
|
16150
16686
|
if (raw === void 0 || !wants(raw)) continue;
|
|
16151
|
-
if (
|
|
16687
|
+
if (isScalar9(item)) {
|
|
16152
16688
|
item.value = spec.newRef;
|
|
16153
16689
|
n += 1;
|
|
16154
|
-
} else if (
|
|
16690
|
+
} else if (isMap10(item)) {
|
|
16155
16691
|
item.set("ref", spec.newRef);
|
|
16156
16692
|
n += 1;
|
|
16157
16693
|
}
|
|
@@ -16159,13 +16695,13 @@ async function planConfigEdit(ctx, edit, runRefs) {
|
|
|
16159
16695
|
return n;
|
|
16160
16696
|
};
|
|
16161
16697
|
const root = ctx.configSection === void 0 ? doc : doc.get(ctx.configSection, true);
|
|
16162
|
-
const keyOf2 = (key) => root === doc ? doc.get(key, true) :
|
|
16698
|
+
const keyOf2 = (key) => root === doc ? doc.get(key, true) : isMap10(root) ? root.get(key, true) : void 0;
|
|
16163
16699
|
const topSeq = keyOf2("schemas");
|
|
16164
16700
|
let repointCount = repoint(topSeq);
|
|
16165
16701
|
const overrides = keyOf2("overrides");
|
|
16166
16702
|
if (isSeq5(overrides)) {
|
|
16167
16703
|
for (const entry of overrides.items) {
|
|
16168
|
-
if (
|
|
16704
|
+
if (isMap10(entry)) repointCount += repoint(entry.get("schemas", true));
|
|
16169
16705
|
}
|
|
16170
16706
|
}
|
|
16171
16707
|
const repointed = repointCount > 0;
|
|
@@ -16174,10 +16710,10 @@ async function planConfigEdit(ctx, edit, runRefs) {
|
|
|
16174
16710
|
if (edit.integrity && isSeq5(topSeq)) {
|
|
16175
16711
|
const wantPath = foldPath(edit.integrity.path);
|
|
16176
16712
|
for (const item of topSeq.items) {
|
|
16177
|
-
if (!
|
|
16713
|
+
if (!isMap10(item)) continue;
|
|
16178
16714
|
const raw = rawRefOf(item);
|
|
16179
16715
|
if (raw === void 0 || classifyRef(raw).kind !== "file") continue;
|
|
16180
|
-
const abs =
|
|
16716
|
+
const abs = isAbsolute11(raw) ? raw : resolve20(configDir, raw);
|
|
16181
16717
|
if (foldPath(abs) !== wantPath) continue;
|
|
16182
16718
|
pinFrom = item.get("integrity");
|
|
16183
16719
|
item.set("integrity", edit.integrity.value);
|
|
@@ -16406,7 +16942,7 @@ function buildChanges(diff, entries, sentinel, ctx, renameHints = [], booleanAdd
|
|
|
16406
16942
|
`"${file}": no writable format for that extension.`
|
|
16407
16943
|
);
|
|
16408
16944
|
}
|
|
16409
|
-
if (existsSync5(
|
|
16945
|
+
if (existsSync5(resolve20(ctx.base, file))) {
|
|
16410
16946
|
throw new DocmetaError(
|
|
16411
16947
|
`"${file}" already exists; INSERT creates new files only.`
|
|
16412
16948
|
);
|
|
@@ -16425,7 +16961,7 @@ function buildChanges(diff, entries, sentinel, ctx, renameHints = [], booleanAdd
|
|
|
16425
16961
|
`"${from}" -> "${to}": a rename may not change the extension.`
|
|
16426
16962
|
);
|
|
16427
16963
|
}
|
|
16428
|
-
if (existsSync5(
|
|
16964
|
+
if (existsSync5(resolve20(ctx.base, to))) {
|
|
16429
16965
|
throw new DocmetaError(
|
|
16430
16966
|
`"${to}" already exists; the rename would overwrite it.`
|
|
16431
16967
|
);
|
|
@@ -16454,13 +16990,13 @@ function validateNewPath(p, base) {
|
|
|
16454
16990
|
const refuse = (why) => {
|
|
16455
16991
|
throw new DocmetaError(`"${p}" is not a usable path: ${why}.`);
|
|
16456
16992
|
};
|
|
16457
|
-
if (
|
|
16993
|
+
if (isAbsolute11(p)) refuse("it is absolute");
|
|
16458
16994
|
if (p.split(/[\\/]/).some((segment) => segment === "..")) {
|
|
16459
16995
|
refuse("it traverses upward");
|
|
16460
16996
|
}
|
|
16461
|
-
const abs =
|
|
16462
|
-
if (abs ===
|
|
16463
|
-
if (!abs.startsWith(
|
|
16997
|
+
const abs = resolve20(base, p);
|
|
16998
|
+
if (abs === resolve20(base)) refuse("it points at the corpus root, not a file");
|
|
16999
|
+
if (!abs.startsWith(resolve20(base) + sep10)) refuse("it escapes the corpus");
|
|
16464
17000
|
}
|
|
16465
17001
|
function refuseJoinFieldChanges(changes, entries, ctx) {
|
|
16466
17002
|
const index = ctx.externalMetadata;
|
|
@@ -16531,6 +17067,12 @@ function postChangeData(changes, entries) {
|
|
|
16531
17067
|
}
|
|
16532
17068
|
return out;
|
|
16533
17069
|
}
|
|
17070
|
+
function runPages(changes, entries, base) {
|
|
17071
|
+
const labels = new Set(entries.map((e) => e.label));
|
|
17072
|
+
for (const c of changes) if (!("schema" in c) && !("config" in c)) labels.add(c.file);
|
|
17073
|
+
labels.delete(STDIN_LABEL);
|
|
17074
|
+
return [...labels].map((label) => resolve20(base, label));
|
|
17075
|
+
}
|
|
16534
17076
|
async function planManifestEdits(changes, entries, ctx, renameHints) {
|
|
16535
17077
|
for (const c of changes) {
|
|
16536
17078
|
delete c.manifest;
|
|
@@ -16579,12 +17121,18 @@ async function planManifestEdits(changes, entries, ctx, renameHints) {
|
|
|
16579
17121
|
let write = texts.get(home.absPath);
|
|
16580
17122
|
if (write === void 0) {
|
|
16581
17123
|
let text2;
|
|
17124
|
+
let expected;
|
|
16582
17125
|
try {
|
|
16583
17126
|
text2 = await readFile12(home.absPath, "utf8");
|
|
17127
|
+
expected = text2;
|
|
16584
17128
|
} catch (err) {
|
|
16585
|
-
|
|
17129
|
+
if (!home.perPage || !isMissing(err)) {
|
|
17130
|
+
throw new DocmetaError(`Manifest ${home.file} could not be read: ${errorMessage(err)}`);
|
|
17131
|
+
}
|
|
17132
|
+
text2 = "";
|
|
17133
|
+
expected = null;
|
|
16586
17134
|
}
|
|
16587
|
-
write = { path: home.absPath, display: home.file, text: text2, expected
|
|
17135
|
+
write = { path: home.absPath, display: home.file, text: text2, expected };
|
|
16588
17136
|
texts.set(home.absPath, write);
|
|
16589
17137
|
}
|
|
16590
17138
|
write.text = change(write.text);
|
|
@@ -16607,13 +17155,13 @@ async function planManifestEdits(changes, entries, ctx, renameHints) {
|
|
|
16607
17155
|
...col,
|
|
16608
17156
|
externalMetadata: col.externalMetadata.filter((m) => classifyRef(m.file).kind !== "url")
|
|
16609
17157
|
})),
|
|
16610
|
-
{ configDir: ctx.configDir ?? ctx.cwd, base: ctx.base }
|
|
17158
|
+
{ configDir: ctx.configDir ?? ctx.cwd, base: ctx.base, pages: runPages(changes, entries, ctx.base) }
|
|
16611
17159
|
);
|
|
16612
17160
|
const index = await leftOut;
|
|
16613
17161
|
if (index === null) return void 0;
|
|
16614
|
-
const abs =
|
|
17162
|
+
const abs = resolve20(ctx.base, file);
|
|
16615
17163
|
const named = index.entries.find(
|
|
16616
|
-
(e) => e.join ===
|
|
17164
|
+
(e) => e.join === PATH_JOIN2 && e.abs === abs && excluded.includes(e.collection)
|
|
16617
17165
|
);
|
|
16618
17166
|
if (named !== void 0) return named;
|
|
16619
17167
|
if (!joins || own2 === void 0) return void 0;
|
|
@@ -16658,7 +17206,7 @@ async function planManifestEdits(changes, entries, ctx, renameHints) {
|
|
|
16658
17206
|
continue;
|
|
16659
17207
|
}
|
|
16660
17208
|
if ("renamed" in c) {
|
|
16661
|
-
const supplied = ctx.externalMetadata?.byPath.get(
|
|
17209
|
+
const supplied = ctx.externalMetadata?.byPath.get(resolve20(ctx.base, c.file));
|
|
16662
17210
|
const seen = /* @__PURE__ */ new Set();
|
|
16663
17211
|
for (const [key, sv] of supplied ?? []) {
|
|
16664
17212
|
if (seen.has(sv.file) || !ctx.memberships(c.file).includes(sv.collection)) continue;
|
|
@@ -16669,7 +17217,12 @@ async function planManifestEdits(changes, entries, ctx, renameHints) {
|
|
|
16669
17217
|
`"${c.file}": manifest ${home.file} names it, which is fetched and cannot be written; rename the entry in that repository.`
|
|
16670
17218
|
);
|
|
16671
17219
|
}
|
|
16672
|
-
if (home.kind
|
|
17220
|
+
if (home.kind === "manifest" && home.perPage) {
|
|
17221
|
+
throw new DocmetaError(
|
|
17222
|
+
`${c.file} cannot move to ${c.renamed}, because its "${key}" lives in ${home.file}, a {page} manifest named after the page's path. Move the page and its manifest together, then rename the entry's key.`
|
|
17223
|
+
);
|
|
17224
|
+
}
|
|
17225
|
+
if (home.kind !== "manifest" || home.join !== PATH_JOIN2 || home.entry === void 0) continue;
|
|
16673
17226
|
const moved = await keyHome(loc, c.renamed, own2, key);
|
|
16674
17227
|
if (moved.kind !== "manifest" || moved.absPath !== home.absPath || moved.entry === void 0) {
|
|
16675
17228
|
throw new DocmetaError(
|
|
@@ -16733,7 +17286,7 @@ async function planManifestEdits(changes, entries, ctx, renameHints) {
|
|
|
16733
17286
|
}
|
|
16734
17287
|
pageRoutes.set(c, ops);
|
|
16735
17288
|
}
|
|
16736
|
-
return [...texts.values()].filter((w) => w.text !== w.expected);
|
|
17289
|
+
return [...texts.values()].filter((w) => w.text !== (w.expected ?? ""));
|
|
16737
17290
|
}
|
|
16738
17291
|
async function unhomedWrites(changes, entries, ctx) {
|
|
16739
17292
|
const written = /* @__PURE__ */ new Map();
|
|
@@ -16765,7 +17318,7 @@ async function unhomedWrites(changes, entries, ctx) {
|
|
|
16765
17318
|
const prefs = await validator.locationPreferences(data, refs);
|
|
16766
17319
|
const joins = new Set(
|
|
16767
17320
|
memberOf(loc.declaredCollections, loc.configDir ?? ctx.cwd, ctx.base, file).flatMap(
|
|
16768
|
-
(name2) => (loc.declaredCollections.find((col) => col.name === name2)?.externalMetadata ?? []).map((m) => externalMetadataJoin(m)).filter((j) => j !==
|
|
17321
|
+
(name2) => (loc.declaredCollections.find((col) => col.name === name2)?.externalMetadata ?? []).map((m) => externalMetadataJoin(m)).filter((j) => j !== PATH_JOIN2)
|
|
16769
17322
|
)
|
|
16770
17323
|
);
|
|
16771
17324
|
for (const key of new Set(w.keys)) {
|
|
@@ -16816,7 +17369,8 @@ async function offerRelocation(changes, entries, ctx) {
|
|
|
16816
17369
|
ctx.externalMetadata = await loadExternalMetadata(loc.collections, {
|
|
16817
17370
|
configDir: loc.configDir ?? ctx.cwd,
|
|
16818
17371
|
base: ctx.base,
|
|
16819
|
-
offline: ctx.location.offline
|
|
17372
|
+
offline: ctx.location.offline,
|
|
17373
|
+
pages: runPages(changes, entries, ctx.base)
|
|
16820
17374
|
});
|
|
16821
17375
|
ctx.memberships = (label) => memberOf(loc.collections, loc.configDir ?? ctx.cwd, ctx.base, label);
|
|
16822
17376
|
unhomed = await unhomedWrites(changes, entries, ctx);
|
|
@@ -16960,14 +17514,14 @@ async function applyChanges(changes, entries, ctx, schemaPlan, manifestWrites =
|
|
|
16960
17514
|
const pendingWrites = [];
|
|
16961
17515
|
const pendingRenames = [];
|
|
16962
17516
|
for (const [label, ops] of grouped) {
|
|
16963
|
-
const path =
|
|
17517
|
+
const path = resolve20(ctx.base, label);
|
|
16964
17518
|
if (ops.renamedTo !== void 0) {
|
|
16965
17519
|
if (!existsSync5(path)) {
|
|
16966
17520
|
throw new DocmetaError(
|
|
16967
17521
|
`"${label}" is gone from disk since it was read; re-run the query.`
|
|
16968
17522
|
);
|
|
16969
17523
|
}
|
|
16970
|
-
const toDisk =
|
|
17524
|
+
const toDisk = resolve20(ctx.base, ops.renamedTo);
|
|
16971
17525
|
if (existsSync5(toDisk)) {
|
|
16972
17526
|
throw new DocmetaError(
|
|
16973
17527
|
`"${ops.renamedTo}" appeared on disk since the plan; re-run the query.`
|
|
@@ -17092,7 +17646,7 @@ async function applyChanges(changes, entries, ctx, schemaPlan, manifestWrites =
|
|
|
17092
17646
|
try {
|
|
17093
17647
|
now = await readFile12(m.path, "utf8");
|
|
17094
17648
|
} catch {
|
|
17095
|
-
now =
|
|
17649
|
+
now = null;
|
|
17096
17650
|
}
|
|
17097
17651
|
if (now !== m.expected) {
|
|
17098
17652
|
throw new DocmetaError(
|
|
@@ -17106,7 +17660,10 @@ async function applyChanges(changes, entries, ctx, schemaPlan, manifestWrites =
|
|
|
17106
17660
|
for (const p of pendingWrites) {
|
|
17107
17661
|
if (p.ensureDir) dirs.add(dirname11(p.path));
|
|
17108
17662
|
}
|
|
17109
|
-
for (const
|
|
17663
|
+
for (const m of manifestWrites) {
|
|
17664
|
+
if (m.expected === null) dirs.add(dirname11(m.path));
|
|
17665
|
+
}
|
|
17666
|
+
for (const d of dirs) await mkdir4(d, { recursive: true });
|
|
17110
17667
|
const writeSchema = async () => {
|
|
17111
17668
|
for (const w of schemaWrites) await writeFileAtomic(w.path, w.content);
|
|
17112
17669
|
};
|
|
@@ -17221,7 +17778,7 @@ function skipExpression(sql, from) {
|
|
|
17221
17778
|
|
|
17222
17779
|
// src/meta/commands/fill.ts
|
|
17223
17780
|
import { readFile as readFile14 } from "node:fs/promises";
|
|
17224
|
-
import { resolve as
|
|
17781
|
+
import { resolve as resolve21, extname as extname8, join as join10 } from "node:path";
|
|
17225
17782
|
import {
|
|
17226
17783
|
completeValidatedJSON,
|
|
17227
17784
|
makeProvider,
|
|
@@ -17237,68 +17794,6 @@ import {
|
|
|
17237
17794
|
|
|
17238
17795
|
// src/meta/core/manifest-writes.ts
|
|
17239
17796
|
import { readFile as readFile13 } from "node:fs/promises";
|
|
17240
|
-
|
|
17241
|
-
// src/shared/manifest-cas.ts
|
|
17242
|
-
import { posix as posix4 } from "node:path";
|
|
17243
|
-
var COMMIT_ATTEMPTS = 5;
|
|
17244
|
-
function conflictRefusal(file) {
|
|
17245
|
-
return `${file} changed under the command while it was being written. Nothing was written to it. Re-run the command.`;
|
|
17246
|
-
}
|
|
17247
|
-
function heldManifest(path, file, before) {
|
|
17248
|
-
return { path, file, before, text: before, ops: [], bases: /* @__PURE__ */ new Map() };
|
|
17249
|
-
}
|
|
17250
|
-
function encodeValue(value) {
|
|
17251
|
-
return value === void 0 ? "absent" : JSON.stringify(value);
|
|
17252
|
-
}
|
|
17253
|
-
function baseKey(at2) {
|
|
17254
|
-
const entry = at2.join === "path" ? posix4.normalize(at2.entry) : at2.entry;
|
|
17255
|
-
return `${entry}\0${at2.key}`;
|
|
17256
|
-
}
|
|
17257
|
-
function rebaseable(held, op, codec) {
|
|
17258
|
-
const at2 = baseKey(op);
|
|
17259
|
-
if (held.bases.has(at2)) return;
|
|
17260
|
-
held.bases.set(at2, {
|
|
17261
|
-
entry: op.entry,
|
|
17262
|
-
key: op.key,
|
|
17263
|
-
join: op.join,
|
|
17264
|
-
value: encodeValue(codec.read(held.before, op))
|
|
17265
|
-
});
|
|
17266
|
-
}
|
|
17267
|
-
function rebase(held, current, codec) {
|
|
17268
|
-
for (const base of held.bases.values()) {
|
|
17269
|
-
if (encodeValue(codec.read(current, base)) !== base.value) return void 0;
|
|
17270
|
-
}
|
|
17271
|
-
let text2 = current;
|
|
17272
|
-
for (const op of held.ops) text2 = codec.apply(text2, op);
|
|
17273
|
-
return text2;
|
|
17274
|
-
}
|
|
17275
|
-
function rebaseline(held) {
|
|
17276
|
-
held.before = held.text;
|
|
17277
|
-
held.ops = [];
|
|
17278
|
-
held.bases.clear();
|
|
17279
|
-
}
|
|
17280
|
-
async function settle(held, io) {
|
|
17281
|
-
for (let attempt = 1; attempt <= COMMIT_ATTEMPTS; attempt++) {
|
|
17282
|
-
let current;
|
|
17283
|
-
try {
|
|
17284
|
-
current = await io.read(held.path);
|
|
17285
|
-
} catch (error) {
|
|
17286
|
-
const reason = error instanceof Error ? error.message : String(error);
|
|
17287
|
-
throw io.toError(`Manifest ${held.file} could not be read: ${reason}`);
|
|
17288
|
-
}
|
|
17289
|
-
if (current === held.before) {
|
|
17290
|
-
await io.write(held.path, held.text);
|
|
17291
|
-
return;
|
|
17292
|
-
}
|
|
17293
|
-
const replayed = rebase(held, current, io.codec);
|
|
17294
|
-
if (replayed === void 0) throw io.toError(conflictRefusal(held.file));
|
|
17295
|
-
held.before = current;
|
|
17296
|
-
held.text = replayed;
|
|
17297
|
-
}
|
|
17298
|
-
throw io.toError(conflictRefusal(held.file));
|
|
17299
|
-
}
|
|
17300
|
-
|
|
17301
|
-
// src/meta/core/manifest-writes.ts
|
|
17302
17797
|
var manifestCodec = {
|
|
17303
17798
|
apply(text2, op) {
|
|
17304
17799
|
const where = { entry: op.entry, key: op.key, join: op.join, file: op.file };
|
|
@@ -17311,11 +17806,12 @@ var manifestCodec = {
|
|
|
17311
17806
|
function applyManifestOp(text2, op) {
|
|
17312
17807
|
return manifestCodec.apply(text2, op);
|
|
17313
17808
|
}
|
|
17314
|
-
async function holdManifestFile(path, file) {
|
|
17809
|
+
async function holdManifestFile(path, file, perPage = false) {
|
|
17315
17810
|
let before;
|
|
17316
17811
|
try {
|
|
17317
17812
|
before = await readFile13(path, "utf8");
|
|
17318
17813
|
} catch (err) {
|
|
17814
|
+
if (perPage && isMissing(err)) return heldManifest(path, file, "", true);
|
|
17319
17815
|
throw new DocmetaError(`Manifest ${file} could not be read: ${errorMessage(err)}`);
|
|
17320
17816
|
}
|
|
17321
17817
|
return heldManifest(path, file, before);
|
|
@@ -17328,7 +17824,8 @@ async function settleManifest(held, io = {}) {
|
|
|
17328
17824
|
if (held.text === held.before) return false;
|
|
17329
17825
|
await settle(held, {
|
|
17330
17826
|
codec: manifestCodec,
|
|
17331
|
-
|
|
17827
|
+
// A per-page manifest (proposal 0058) may be the first file in its directory.
|
|
17828
|
+
write: io.write ?? ((at2, text2) => writeFileAtomic(at2, text2, { createParents: true })),
|
|
17332
17829
|
read: io.read ?? ((at2) => readFile13(at2, "utf8")),
|
|
17333
17830
|
toError: (message) => new DocmetaError(message)
|
|
17334
17831
|
});
|
|
@@ -17612,7 +18109,9 @@ async function runFill(opts) {
|
|
|
17612
18109
|
const loadManifests = () => loadExternalMetadata(mergedCollections(), {
|
|
17613
18110
|
configDir: configDir ?? cwd,
|
|
17614
18111
|
base,
|
|
17615
|
-
offline: opts.offline ?? config?.offline ?? false
|
|
18112
|
+
offline: opts.offline ?? config?.offline ?? false,
|
|
18113
|
+
// A `{page}` manifest (0058) is read for exactly the pages this run fills.
|
|
18114
|
+
pages: files.map((file) => resolve21(base, file))
|
|
17616
18115
|
});
|
|
17617
18116
|
const mergeMembersFor = (label) => memberOf(runConfig.declaredCollections, configDir ?? cwd, base, label);
|
|
17618
18117
|
let externalMetadata = await loadManifests();
|
|
@@ -17649,7 +18148,7 @@ async function runFill(opts) {
|
|
|
17649
18148
|
};
|
|
17650
18149
|
const restorePage = async (label, before) => {
|
|
17651
18150
|
try {
|
|
17652
|
-
await writeFileAtomic(
|
|
18151
|
+
await writeFileAtomic(resolve21(base, label), before);
|
|
17653
18152
|
return `${label} was restored.`;
|
|
17654
18153
|
} catch (err) {
|
|
17655
18154
|
return `${label} could not be restored: ${errorMessage(err)}. Restore it from version control.`;
|
|
@@ -17658,7 +18157,7 @@ async function runFill(opts) {
|
|
|
17658
18157
|
const holdManifest = (home) => {
|
|
17659
18158
|
let held = holding.get(home.absPath);
|
|
17660
18159
|
if (held === void 0) {
|
|
17661
|
-
held = holdManifestFile(home.absPath, home.file).then((m) => {
|
|
18160
|
+
held = holdManifestFile(home.absPath, home.file, home.perPage).then((m) => {
|
|
17662
18161
|
const h = { held: m, saving: Promise.resolve() };
|
|
17663
18162
|
heldManifests.set(home.absPath, h);
|
|
17664
18163
|
return h;
|
|
@@ -18194,7 +18693,7 @@ async function runFill(opts) {
|
|
|
18194
18693
|
const changed = next !== content || manifestChanged;
|
|
18195
18694
|
const pageWritten = next !== content && !dryRun && label !== "<stdin>";
|
|
18196
18695
|
if (pageWritten) {
|
|
18197
|
-
await writeFileAtomic(
|
|
18696
|
+
await writeFileAtomic(resolve21(base, label), next);
|
|
18198
18697
|
}
|
|
18199
18698
|
if (manifestChanged) {
|
|
18200
18699
|
const perManifest = /* @__PURE__ */ new Map();
|
|
@@ -18226,7 +18725,7 @@ async function runFill(opts) {
|
|
|
18226
18725
|
const prepareAll = async () => ({
|
|
18227
18726
|
stdin: usingStdin ? await prepareOne("<stdin>", opts.stdinContent ?? "", forcedExtractor?.extensions[0] ?? "") : void 0,
|
|
18228
18727
|
files: await mapConcurrent(files, concurrency, async (file) => {
|
|
18229
|
-
const content = await readFile14(
|
|
18728
|
+
const content = await readFile14(resolve21(base, file), "utf8");
|
|
18230
18729
|
return prepareOne(file, content, extname8(file));
|
|
18231
18730
|
})
|
|
18232
18731
|
});
|
|
@@ -18656,7 +19155,7 @@ async function mapConcurrent(items2, limit, fn) {
|
|
|
18656
19155
|
|
|
18657
19156
|
// src/meta/commands/derive.ts
|
|
18658
19157
|
import { readFile as readFile15 } from "node:fs/promises";
|
|
18659
|
-
import { extname as extname9, relative as
|
|
19158
|
+
import { extname as extname9, relative as relative15, resolve as resolve22, sep as sep11 } from "node:path";
|
|
18660
19159
|
var GENERATED_BY_ENV = "MANNI_GENERATED_BY";
|
|
18661
19160
|
var SOURCE_HINT = "narrow --sources or --fields";
|
|
18662
19161
|
async function runDerive(opts) {
|
|
@@ -18767,7 +19266,7 @@ async function runDerive(opts) {
|
|
|
18767
19266
|
const files = fromCollections ? retainMembers(walked, membersFor) : walked;
|
|
18768
19267
|
const rangesByPage = /* @__PURE__ */ new Map();
|
|
18769
19268
|
for (const t of targets) {
|
|
18770
|
-
const label =
|
|
19269
|
+
const label = relative15(base, resolve22(base, t.page)).split(sep11).join("/");
|
|
18771
19270
|
if (!files.includes(label)) {
|
|
18772
19271
|
throw new DocmetaError(
|
|
18773
19272
|
`${t.target} does not name one file that derive reads; a range names lines of one file.`
|
|
@@ -18792,7 +19291,7 @@ async function runDerive(opts) {
|
|
|
18792
19291
|
const loaded2 = /* @__PURE__ */ new Map();
|
|
18793
19292
|
const errors2 = /* @__PURE__ */ new Map();
|
|
18794
19293
|
for (const label of files) {
|
|
18795
|
-
const absPath =
|
|
19294
|
+
const absPath = resolve22(base, label);
|
|
18796
19295
|
const extractor = forcedExtractor ?? extractorForExtension(extname9(label));
|
|
18797
19296
|
if (!extractor) {
|
|
18798
19297
|
errors2.set(label, {
|
|
@@ -18818,12 +19317,13 @@ async function runDerive(opts) {
|
|
|
18818
19317
|
}
|
|
18819
19318
|
}
|
|
18820
19319
|
const provenanceRoot = configDir ?? cwd;
|
|
19320
|
+
const pages2 = files.map((label) => resolve22(base, label));
|
|
18821
19321
|
const manifests = wantsProvenance ? provenanceManifests(declaredCollections, provenanceRoot, base) : [];
|
|
18822
19322
|
const provenanceCollections = declaredCollections.map((c) => ({
|
|
18823
19323
|
...c,
|
|
18824
19324
|
externalMetadata: c.externalMetadata.filter((m) => m.keys.includes(PROVENANCE_FIELD))
|
|
18825
19325
|
})).filter((c) => c.externalMetadata.length > 0);
|
|
18826
|
-
const provenanceIndex = manifests.length === 0 ? null : await loadExternalMetadata(provenanceCollections, { configDir: provenanceRoot, base });
|
|
19326
|
+
const provenanceIndex = manifests.length === 0 ? null : await loadExternalMetadata(provenanceCollections, { configDir: provenanceRoot, base, pages: pages2 });
|
|
18827
19327
|
const places2 = /* @__PURE__ */ new Map();
|
|
18828
19328
|
for (const doc of loaded2.values()) {
|
|
18829
19329
|
if (!wantsProvenance) break;
|
|
@@ -18850,7 +19350,7 @@ async function runDerive(opts) {
|
|
|
18850
19350
|
(m) => classifyRef(m.file).kind !== "url" && m.keys.some((k) => k !== PROVENANCE_FIELD && fields.includes(k))
|
|
18851
19351
|
)
|
|
18852
19352
|
})).filter((c) => c.externalMetadata.length > 0);
|
|
18853
|
-
const ownedIndex = ownedCollections.length === 0 ? null : await loadExternalMetadata(ownedCollections, { configDir: provenanceRoot, base });
|
|
19353
|
+
const ownedIndex = ownedCollections.length === 0 ? null : await loadExternalMetadata(ownedCollections, { configDir: provenanceRoot, base, pages: pages2 });
|
|
18854
19354
|
const derived2 = await deriveMetadata([...loaded2.values()], {
|
|
18855
19355
|
cwd,
|
|
18856
19356
|
base,
|
|
@@ -18945,8 +19445,8 @@ async function runDerive(opts) {
|
|
|
18945
19445
|
error: `${at2} is encrypted, and no encryption key is available to compare it. Set ${ENCRYPTION_KEY_ENV}, or run \`manni key set\`.`
|
|
18946
19446
|
};
|
|
18947
19447
|
}
|
|
18948
|
-
const
|
|
18949
|
-
if (
|
|
19448
|
+
const unreadable2 = view.unreadable.find((p) => isAtOrUnder(p, at2));
|
|
19449
|
+
if (unreadable2 !== void 0) return { error: unreadableMessage(unreadable2) };
|
|
18950
19450
|
}
|
|
18951
19451
|
const stamped = { ...view.data };
|
|
18952
19452
|
for (const field of fields) {
|
|
@@ -19022,7 +19522,7 @@ async function runDerive(opts) {
|
|
|
19022
19522
|
const holdManifest = async (manifest) => {
|
|
19023
19523
|
const already = heldManifests.get(manifest.absPath);
|
|
19024
19524
|
if (already !== void 0) return already;
|
|
19025
|
-
const held = await holdManifestFile(manifest.absPath, manifest.file);
|
|
19525
|
+
const held = await holdManifestFile(manifest.absPath, manifest.file, manifest.perPage);
|
|
19026
19526
|
heldManifests.set(manifest.absPath, held);
|
|
19027
19527
|
return held;
|
|
19028
19528
|
};
|
|
@@ -19953,6 +20453,9 @@ export {
|
|
|
19953
20453
|
palette,
|
|
19954
20454
|
shouldColor,
|
|
19955
20455
|
matchesFileGlob,
|
|
20456
|
+
hasPagePlaceholder,
|
|
20457
|
+
pageManifestPath,
|
|
20458
|
+
findPageManifests,
|
|
19956
20459
|
externalMetadataUrlProblem,
|
|
19957
20460
|
parseCollections,
|
|
19958
20461
|
selectCollections,
|
|
@@ -19965,6 +20468,7 @@ export {
|
|
|
19965
20468
|
findGitRoot,
|
|
19966
20469
|
valeConfigPath,
|
|
19967
20470
|
programName,
|
|
20471
|
+
warn,
|
|
19968
20472
|
notice,
|
|
19969
20473
|
ToolError,
|
|
19970
20474
|
errorMessage,
|
|
@@ -20005,6 +20509,7 @@ export {
|
|
|
20005
20509
|
committedKeyWarning,
|
|
20006
20510
|
terminalConfirm,
|
|
20007
20511
|
ensureEncryptionKey,
|
|
20512
|
+
gitIgnored,
|
|
20008
20513
|
escapePointerSegment,
|
|
20009
20514
|
hasFrontmatterFence,
|
|
20010
20515
|
locateFrontmatter,
|
|
@@ -20068,6 +20573,10 @@ export {
|
|
|
20068
20573
|
isMachineFormat,
|
|
20069
20574
|
OMITTED_WHEN_CLEAN,
|
|
20070
20575
|
render,
|
|
20576
|
+
heldManifest,
|
|
20577
|
+
rebaseable,
|
|
20578
|
+
settle,
|
|
20579
|
+
isMissing,
|
|
20071
20580
|
EXTERNAL_METADATA_FETCH_TIMEOUT_MS,
|
|
20072
20581
|
EXTERNAL_METADATA_FETCH_MAX_BYTES,
|
|
20073
20582
|
fetchExternalMetadata,
|
|
@@ -20076,7 +20585,7 @@ export {
|
|
|
20076
20585
|
EXTERNAL_OWNED_SCHEMA,
|
|
20077
20586
|
EXTERNAL_DUPLICATE_SCHEMA,
|
|
20078
20587
|
EXTERNAL_KEYWORD,
|
|
20079
|
-
PATH_JOIN,
|
|
20588
|
+
PATH_JOIN2 as PATH_JOIN,
|
|
20080
20589
|
externalMetadataJoin,
|
|
20081
20590
|
loadExternalMetadata,
|
|
20082
20591
|
mergeExternalMetadata,
|
|
@@ -20134,9 +20643,6 @@ export {
|
|
|
20134
20643
|
runVendorSchema,
|
|
20135
20644
|
runInferSchema,
|
|
20136
20645
|
runQuery,
|
|
20137
|
-
heldManifest,
|
|
20138
|
-
rebaseable,
|
|
20139
|
-
settle,
|
|
20140
20646
|
runFill,
|
|
20141
20647
|
runDerive,
|
|
20142
20648
|
deriveFailed,
|
|
@@ -20155,4 +20661,4 @@ export {
|
|
|
20155
20661
|
renderQuery,
|
|
20156
20662
|
renderQueryCsv
|
|
20157
20663
|
};
|
|
20158
|
-
//# sourceMappingURL=chunk-
|
|
20664
|
+
//# sourceMappingURL=chunk-7ODP2AB3.js.map
|