@hawkeyexl/manni 2.10.1 → 2.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/{chunk-O2V45AVG.js → chunk-BUXVMARH.js} +856 -452
- package/dist/chunk-BUXVMARH.js.map +1 -0
- package/dist/{chunk-5GVRMS6B.js → chunk-V5NTFMUD.js} +2 -2
- package/dist/{chunk-HA4CK35M.js → chunk-VYFRHPCL.js} +210 -45
- package/dist/chunk-VYFRHPCL.js.map +1 -0
- package/dist/cli.js +10 -5
- package/dist/cli.js.map +1 -1
- package/dist/docmeta.js +2 -2
- package/dist/index.d.ts +66 -2
- package/dist/index.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-HA4CK35M.js.map +0 -1
- package/dist/chunk-O2V45AVG.js.map +0 -1
- /package/dist/{chunk-5GVRMS6B.js.map → chunk-V5NTFMUD.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.0",
|
|
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,7 @@ var DocmetaError = class extends ToolError {
|
|
|
751
901
|
};
|
|
752
902
|
|
|
753
903
|
// src/meta/extractors/frontmatter-write.ts
|
|
754
|
-
import { parseDocument as
|
|
904
|
+
import { parseDocument as parseDocument3, isMap as isMap3, isCollection } from "yaml";
|
|
755
905
|
import { parse as parseToml2, stringify as stringifyToml } from "smol-toml";
|
|
756
906
|
|
|
757
907
|
// src/meta/extractors/patch-util.ts
|
|
@@ -874,13 +1024,13 @@ function mergeBlock(flavor, inner, patch, deletions = []) {
|
|
|
874
1024
|
}
|
|
875
1025
|
}
|
|
876
1026
|
function mergeYaml(inner, patch, deletions = []) {
|
|
877
|
-
const doc =
|
|
1027
|
+
const doc = parseDocument3(inner);
|
|
878
1028
|
if (doc.errors.length > 0) {
|
|
879
1029
|
throw new DocmetaError(
|
|
880
1030
|
`Cannot rewrite invalid YAML front matter: ${doc.errors[0]?.message ?? "parse error"}`
|
|
881
1031
|
);
|
|
882
1032
|
}
|
|
883
|
-
if (doc.contents != null && !
|
|
1033
|
+
if (doc.contents != null && !isMap3(doc.contents)) {
|
|
884
1034
|
throw new DocmetaError(
|
|
885
1035
|
"Cannot rewrite front matter: the root must be a mapping."
|
|
886
1036
|
);
|
|
@@ -1041,7 +1191,7 @@ function parseBlock(flavor, text2) {
|
|
|
1041
1191
|
case "toml":
|
|
1042
1192
|
return text2.trim() === "" ? {} : parseToml2(text2);
|
|
1043
1193
|
case "yaml": {
|
|
1044
|
-
const doc =
|
|
1194
|
+
const doc = parseDocument3(text2);
|
|
1045
1195
|
if (doc.errors.length > 0) {
|
|
1046
1196
|
throw new DocmetaError(
|
|
1047
1197
|
`Cannot rewrite invalid YAML front matter: ${doc.errors[0]?.message ?? "parse error"}`
|
|
@@ -1308,8 +1458,8 @@ function ditaShape(content, root, filePath) {
|
|
|
1308
1458
|
const lower = filePath?.toLowerCase() ?? "";
|
|
1309
1459
|
const byExtension2 = (lower.endsWith(".dita") || lower.endsWith(".ditamap")) && DITA_ROOTS.has(name2);
|
|
1310
1460
|
if (!byDoctype && !byClass && !byArch && !byExtension2) return void 0;
|
|
1311
|
-
const
|
|
1312
|
-
return
|
|
1461
|
+
const isMap10 = /^\s*[-+]\s+map\//.test(cls) || MAP_ROOTS.has(name2) || lower.endsWith(".ditamap");
|
|
1462
|
+
return isMap10 ? { kind: "map", container: "topicmeta", preamble: /* @__PURE__ */ new Set(["title"]) } : {
|
|
1313
1463
|
kind: "topic",
|
|
1314
1464
|
container: "metadata",
|
|
1315
1465
|
preamble: /* @__PURE__ */ new Set([
|
|
@@ -2731,8 +2881,8 @@ function listFormats() {
|
|
|
2731
2881
|
}
|
|
2732
2882
|
|
|
2733
2883
|
// 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";
|
|
2884
|
+
import { writeFile, rename, rm, stat as stat2, chmod, mkdir } from "node:fs/promises";
|
|
2885
|
+
import { dirname, join, basename, resolve as resolve2 } from "node:path";
|
|
2736
2886
|
|
|
2737
2887
|
// src/meta/core/manifest-cache.ts
|
|
2738
2888
|
import { stat } from "node:fs/promises";
|
|
@@ -2789,15 +2939,16 @@ var RENAME_ATTEMPTS = 3;
|
|
|
2789
2939
|
function errorCode(err) {
|
|
2790
2940
|
return typeof err === "object" && err !== null && "code" in err ? String(err.code) : void 0;
|
|
2791
2941
|
}
|
|
2792
|
-
var wait = (ms) => new Promise((
|
|
2793
|
-
setTimeout(
|
|
2942
|
+
var wait = (ms) => new Promise((resolve23) => {
|
|
2943
|
+
setTimeout(resolve23, ms);
|
|
2794
2944
|
});
|
|
2795
|
-
async function writeFileAtomic(path, contents) {
|
|
2945
|
+
async function writeFileAtomic(path, contents, options = {}) {
|
|
2796
2946
|
const tmp = join(
|
|
2797
2947
|
dirname(path),
|
|
2798
2948
|
`.${basename(path)}.manni-${process.pid}-${Math.random().toString(36).slice(2, 8)}.tmp`
|
|
2799
2949
|
);
|
|
2800
2950
|
try {
|
|
2951
|
+
if (options.createParents === true) await mkdir(dirname(path), { recursive: true });
|
|
2801
2952
|
await writeFile(tmp, contents);
|
|
2802
2953
|
try {
|
|
2803
2954
|
const { mode } = await stat2(path);
|
|
@@ -2827,13 +2978,13 @@ async function writeFileAtomic(path, contents) {
|
|
|
2827
2978
|
}
|
|
2828
2979
|
} finally {
|
|
2829
2980
|
await rm(tmp, { force: true });
|
|
2830
|
-
invalidateManifestCache(
|
|
2981
|
+
invalidateManifestCache(resolve2(path));
|
|
2831
2982
|
}
|
|
2832
2983
|
}
|
|
2833
2984
|
|
|
2834
2985
|
// src/meta/core/schema-cache.ts
|
|
2835
2986
|
import { createHash as createHash2 } from "node:crypto";
|
|
2836
|
-
import { mkdir, readFile, stat as stat3 } from "node:fs/promises";
|
|
2987
|
+
import { mkdir as mkdir2, readFile, stat as stat3 } from "node:fs/promises";
|
|
2837
2988
|
import { join as join2 } from "node:path";
|
|
2838
2989
|
var SCHEMA_CACHE_DIR = ".manni/meta/schema-cache";
|
|
2839
2990
|
var SCHEMA_CACHE_VERSION = 1;
|
|
@@ -2926,7 +3077,7 @@ var SchemaCache = class {
|
|
|
2926
3077
|
schema
|
|
2927
3078
|
};
|
|
2928
3079
|
try {
|
|
2929
|
-
await
|
|
3080
|
+
await mkdir2(this.dir, { recursive: true });
|
|
2930
3081
|
await writeFileAtomic(
|
|
2931
3082
|
this.entryPath(url),
|
|
2932
3083
|
`${JSON.stringify(entry, null, 2)}
|
|
@@ -5344,8 +5495,8 @@ var SCHEMA_KEYS = [
|
|
|
5344
5495
|
"multipleOf"
|
|
5345
5496
|
];
|
|
5346
5497
|
var RETRY_DELAY_MS = 500;
|
|
5347
|
-
var wait2 = (ms) => new Promise((
|
|
5348
|
-
setTimeout(
|
|
5498
|
+
var wait2 = (ms) => new Promise((resolve23) => {
|
|
5499
|
+
setTimeout(resolve23, ms);
|
|
5349
5500
|
});
|
|
5350
5501
|
var RetryableFetchError = class extends DocmetaError {
|
|
5351
5502
|
};
|
|
@@ -5598,7 +5749,7 @@ async function loadSchema(ref, options = {}) {
|
|
|
5598
5749
|
}
|
|
5599
5750
|
|
|
5600
5751
|
// src/meta/core/resolve-schema.ts
|
|
5601
|
-
import { isAbsolute, relative, resolve as
|
|
5752
|
+
import { isAbsolute as isAbsolute2, relative as relative2, resolve as resolve3 } from "node:path";
|
|
5602
5753
|
var DEFAULT_SCHEMAS = Object.freeze([
|
|
5603
5754
|
"google:okf:0.1",
|
|
5604
5755
|
"passo-uno:seven-action:1.0"
|
|
@@ -5620,8 +5771,8 @@ function collectSchemaPins(config) {
|
|
|
5620
5771
|
return pins;
|
|
5621
5772
|
}
|
|
5622
5773
|
function rebaseConfigSchemaRefs(config, configDir, cwd) {
|
|
5623
|
-
if (
|
|
5624
|
-
const rebase2 = (ref) => classifyRef(ref).kind === "file" && !
|
|
5774
|
+
if (resolve3(configDir) === resolve3(cwd)) return config;
|
|
5775
|
+
const rebase2 = (ref) => classifyRef(ref).kind === "file" && !isAbsolute2(ref) ? resolve3(configDir, ref) : ref;
|
|
5625
5776
|
const rebaseEntry = (entry) => typeof entry === "string" ? rebase2(entry) : {
|
|
5626
5777
|
...entry,
|
|
5627
5778
|
ref: rebase2(entry.ref),
|
|
@@ -5697,9 +5848,9 @@ function assertDocumentRefAllowed(ref, mode, params) {
|
|
|
5697
5848
|
}
|
|
5698
5849
|
const root = params.trustRoot;
|
|
5699
5850
|
if (!root) return;
|
|
5700
|
-
const abs =
|
|
5701
|
-
const within =
|
|
5702
|
-
if (within !== "" && !within.startsWith("..") && !
|
|
5851
|
+
const abs = resolve3(params.fileBase ?? process.cwd(), ref);
|
|
5852
|
+
const within = relative2(root.dir, abs);
|
|
5853
|
+
if (within !== "" && !within.startsWith("..") && !isAbsolute2(within)) return;
|
|
5703
5854
|
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
5855
|
const scope = root.source === "git" ? "the repository" : "the project";
|
|
5705
5856
|
throw new DocmetaError(
|
|
@@ -5849,12 +6000,12 @@ function isPlainObject(v) {
|
|
|
5849
6000
|
}
|
|
5850
6001
|
|
|
5851
6002
|
// src/meta/core/config.ts
|
|
5852
|
-
import { resolve as
|
|
6003
|
+
import { resolve as resolve7 } from "node:path";
|
|
5853
6004
|
import { parse as parseYaml2 } from "yaml";
|
|
5854
6005
|
|
|
5855
6006
|
// src/shared/config-file.ts
|
|
5856
6007
|
import { readFile as readFile3 } from "node:fs/promises";
|
|
5857
|
-
import { basename as basename2, dirname as dirname3, join as join4, relative as
|
|
6008
|
+
import { basename as basename2, dirname as dirname3, join as join4, relative as relative3, resolve as resolve6 } from "node:path";
|
|
5858
6009
|
import { parse as parseYaml } from "yaml";
|
|
5859
6010
|
|
|
5860
6011
|
// src/shared/encryption.ts
|
|
@@ -5985,9 +6136,9 @@ function keyedPin(text2, key) {
|
|
|
5985
6136
|
|
|
5986
6137
|
// src/shared/git-root.ts
|
|
5987
6138
|
import { existsSync } from "node:fs";
|
|
5988
|
-
import { dirname as dirname2, join as join3, resolve as
|
|
6139
|
+
import { dirname as dirname2, join as join3, resolve as resolve4 } from "node:path";
|
|
5989
6140
|
function findGitRoot(cwd) {
|
|
5990
|
-
let dir =
|
|
6141
|
+
let dir = resolve4(cwd);
|
|
5991
6142
|
for (; ; ) {
|
|
5992
6143
|
if (existsSync(join3(dir, ".git"))) return dir;
|
|
5993
6144
|
const parent = dirname2(dir);
|
|
@@ -5996,7 +6147,7 @@ function findGitRoot(cwd) {
|
|
|
5996
6147
|
}
|
|
5997
6148
|
}
|
|
5998
6149
|
function searchPath(cwd) {
|
|
5999
|
-
const start =
|
|
6150
|
+
const start = resolve4(cwd);
|
|
6000
6151
|
const root = findGitRoot(start);
|
|
6001
6152
|
if (root === null) return [start];
|
|
6002
6153
|
const chain = [];
|
|
@@ -6011,7 +6162,7 @@ function searchPath(cwd) {
|
|
|
6011
6162
|
}
|
|
6012
6163
|
|
|
6013
6164
|
// src/shared/tools.ts
|
|
6014
|
-
import { isAbsolute as
|
|
6165
|
+
import { isAbsolute as isAbsolute3, resolve as resolve5 } from "node:path";
|
|
6015
6166
|
var TOOL_KEYS = ["vale"];
|
|
6016
6167
|
var VALE_KEYS = ["config"];
|
|
6017
6168
|
function isMapping2(value) {
|
|
@@ -6056,7 +6207,7 @@ function parseVale(raw, source, toError) {
|
|
|
6056
6207
|
function valeConfigPath(tools, configDir) {
|
|
6057
6208
|
const config = tools.vale?.config;
|
|
6058
6209
|
if (config === void 0) return void 0;
|
|
6059
|
-
return
|
|
6210
|
+
return isAbsolute3(config) ? config : resolve5(configDir, config);
|
|
6060
6211
|
}
|
|
6061
6212
|
|
|
6062
6213
|
// src/shared/warn.ts
|
|
@@ -6161,7 +6312,7 @@ function tolerantKeysOf(document) {
|
|
|
6161
6312
|
};
|
|
6162
6313
|
}
|
|
6163
6314
|
function relativeSource(cwd, path) {
|
|
6164
|
-
return
|
|
6315
|
+
return relative3(cwd, path).replace(/\\/g, "/");
|
|
6165
6316
|
}
|
|
6166
6317
|
function mooseWarning(name2) {
|
|
6167
6318
|
return `"${name2}" is the pre-rename name of the family config file. Rename it to "${FAMILY_CONFIG_NAMES[0] ?? "manni.config.yaml"}".`;
|
|
@@ -6171,7 +6322,7 @@ var FAMILY_FILES = [
|
|
|
6171
6322
|
{ names: MOOSE_CONFIG_NAMES, kind: "moose" }
|
|
6172
6323
|
];
|
|
6173
6324
|
async function findConfigFile(cwd, opts) {
|
|
6174
|
-
const start =
|
|
6325
|
+
const start = resolve6(cwd);
|
|
6175
6326
|
for (const dir of searchPath(start)) {
|
|
6176
6327
|
for (const { names, kind } of FAMILY_FILES) {
|
|
6177
6328
|
for (const name2 of names) {
|
|
@@ -6219,7 +6370,7 @@ async function findConfigFile(cwd, opts) {
|
|
|
6219
6370
|
return null;
|
|
6220
6371
|
}
|
|
6221
6372
|
async function readConfigFile(explicitPath, cwd, opts) {
|
|
6222
|
-
const path =
|
|
6373
|
+
const path = resolve6(cwd, explicitPath);
|
|
6223
6374
|
const document = await readDocument(path, explicitPath, opts.toError);
|
|
6224
6375
|
if (document === null) {
|
|
6225
6376
|
throw opts.toError(`Config file not found: "${explicitPath}".`);
|
|
@@ -6243,7 +6394,7 @@ async function readConfigFile(explicitPath, cwd, opts) {
|
|
|
6243
6394
|
};
|
|
6244
6395
|
}
|
|
6245
6396
|
async function findFamilyConfigFile(cwd, toError) {
|
|
6246
|
-
const start =
|
|
6397
|
+
const start = resolve6(cwd);
|
|
6247
6398
|
for (const dir of searchPath(start)) {
|
|
6248
6399
|
for (const { names, kind } of FAMILY_FILES) {
|
|
6249
6400
|
for (const name2 of names) {
|
|
@@ -6270,7 +6421,7 @@ async function findFamilyConfigFile(cwd, toError) {
|
|
|
6270
6421
|
return null;
|
|
6271
6422
|
}
|
|
6272
6423
|
async function readFamilyConfigFile(explicitPath, cwd, toError) {
|
|
6273
|
-
const path =
|
|
6424
|
+
const path = resolve6(cwd, explicitPath);
|
|
6274
6425
|
const document = await readDocument(path, explicitPath, toError);
|
|
6275
6426
|
if (document === null) {
|
|
6276
6427
|
throw toError(`Config file not found: "${explicitPath}".`);
|
|
@@ -6939,8 +7090,8 @@ function parseFill(value, source) {
|
|
|
6939
7090
|
function schemaTrustRoot(cwd, configDir) {
|
|
6940
7091
|
const git2 = findGitRoot(cwd);
|
|
6941
7092
|
if (git2 !== null) return { dir: git2, source: "git" };
|
|
6942
|
-
if (configDir !== void 0) return { dir:
|
|
6943
|
-
return { dir:
|
|
7093
|
+
if (configDir !== void 0) return { dir: resolve7(configDir), source: "config" };
|
|
7094
|
+
return { dir: resolve7(cwd), source: "cwd" };
|
|
6944
7095
|
}
|
|
6945
7096
|
async function loadConfig(explicitPath, cwd = process.cwd()) {
|
|
6946
7097
|
const file = explicitPath ? await readConfigFile(explicitPath, cwd, CONFIG_FILE) : await findConfigFile(cwd, CONFIG_FILE);
|
|
@@ -7003,23 +7154,23 @@ async function resolveRunConfig(opts) {
|
|
|
7003
7154
|
}
|
|
7004
7155
|
|
|
7005
7156
|
// src/meta/reporters/sarif.ts
|
|
7006
|
-
import { isAbsolute as
|
|
7157
|
+
import { isAbsolute as isAbsolute4 } from "node:path";
|
|
7007
7158
|
|
|
7008
7159
|
// src/meta/core/baseline.ts
|
|
7009
7160
|
import { createHash as createHash3 } from "node:crypto";
|
|
7010
7161
|
import { existsSync as existsSync2 } from "node:fs";
|
|
7011
7162
|
import { readFile as readFile4 } from "node:fs/promises";
|
|
7012
|
-
import { relative as
|
|
7163
|
+
import { relative as relative6, resolve as resolve10 } from "node:path";
|
|
7013
7164
|
|
|
7014
7165
|
// src/meta/core/load-files.ts
|
|
7015
7166
|
import { stat as stat4 } from "node:fs/promises";
|
|
7016
|
-
import { extname, relative as
|
|
7017
|
-
import
|
|
7167
|
+
import { extname, relative as relative5, resolve as resolve9 } from "node:path";
|
|
7168
|
+
import fg2 from "fast-glob";
|
|
7018
7169
|
import picomatch3 from "picomatch";
|
|
7019
7170
|
|
|
7020
7171
|
// src/meta/core/gitignore.ts
|
|
7021
7172
|
import { spawn } from "node:child_process";
|
|
7022
|
-
import { dirname as dirname4, relative as
|
|
7173
|
+
import { dirname as dirname4, relative as relative4, resolve as resolve8, sep as sep2 } from "node:path";
|
|
7023
7174
|
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
7175
|
var unavailable = () => ({
|
|
7025
7176
|
ignored: /* @__PURE__ */ new Set(),
|
|
@@ -7033,7 +7184,7 @@ async function gitIgnored(paths, cwd) {
|
|
|
7033
7184
|
const byRoot = /* @__PURE__ */ new Map();
|
|
7034
7185
|
let inSomeRepo = false;
|
|
7035
7186
|
for (const spelled of paths) {
|
|
7036
|
-
const abs =
|
|
7187
|
+
const abs = resolve8(cwd, spelled);
|
|
7037
7188
|
const dir = dirname4(abs);
|
|
7038
7189
|
let root = rootOf.get(dir);
|
|
7039
7190
|
if (root === void 0) {
|
|
@@ -7042,7 +7193,7 @@ async function gitIgnored(paths, cwd) {
|
|
|
7042
7193
|
}
|
|
7043
7194
|
if (root === null) continue;
|
|
7044
7195
|
inSomeRepo = true;
|
|
7045
|
-
const rel =
|
|
7196
|
+
const rel = relative4(root, abs).split(sep2).join("/");
|
|
7046
7197
|
const bucket = byRoot.get(root);
|
|
7047
7198
|
if (bucket) bucket.push({ rel, spelled });
|
|
7048
7199
|
else byRoot.set(root, [{ rel, spelled }]);
|
|
@@ -7145,14 +7296,14 @@ async function resolveTargetSet(opts) {
|
|
|
7145
7296
|
for (const input of opts.inputs) {
|
|
7146
7297
|
if (input === STDIN_TOKEN) continue;
|
|
7147
7298
|
const posixInput = toPosix(input);
|
|
7148
|
-
const abs =
|
|
7299
|
+
const abs = resolve9(cwd, posixInput);
|
|
7149
7300
|
const st = await statOrNull(abs);
|
|
7150
7301
|
if (st?.isFile()) {
|
|
7151
|
-
named.add(toPosix(
|
|
7302
|
+
named.add(toPosix(relative5(cwd, abs)));
|
|
7152
7303
|
continue;
|
|
7153
7304
|
}
|
|
7154
7305
|
if (st?.isDirectory()) {
|
|
7155
|
-
const found2 = await
|
|
7306
|
+
const found2 = await fg2(`${posixInput}/**/*`, {
|
|
7156
7307
|
cwd,
|
|
7157
7308
|
ignore,
|
|
7158
7309
|
onlyFiles: true,
|
|
@@ -7165,7 +7316,7 @@ async function resolveTargetSet(opts) {
|
|
|
7165
7316
|
missing.push(posixInput);
|
|
7166
7317
|
continue;
|
|
7167
7318
|
}
|
|
7168
|
-
const found = await
|
|
7319
|
+
const found = await fg2(posixInput, {
|
|
7169
7320
|
cwd,
|
|
7170
7321
|
ignore,
|
|
7171
7322
|
onlyFiles: true,
|
|
@@ -7230,13 +7381,13 @@ var FINGERPRINT_RE = /^[0-9a-f]{16}$/;
|
|
|
7230
7381
|
function canonicalFilePath(file, ctx) {
|
|
7231
7382
|
if (!ctx) return file;
|
|
7232
7383
|
const from = ctx.runBase ?? ctx.base;
|
|
7233
|
-
return
|
|
7384
|
+
return relative6(ctx.base, resolve10(from, file)).replace(/\\/g, "/");
|
|
7234
7385
|
}
|
|
7235
7386
|
function canonicalSchemaRef(ref, ctx) {
|
|
7236
7387
|
if (!ctx) return ref;
|
|
7237
7388
|
if (classifyRef(ref).kind !== "file") return ref;
|
|
7238
|
-
const abs =
|
|
7239
|
-
return
|
|
7389
|
+
const abs = resolve10(ctx.cwd, ref);
|
|
7390
|
+
return relative6(ctx.base, abs).replace(/\\/g, "/");
|
|
7240
7391
|
}
|
|
7241
7392
|
function fingerprint(e, ctx) {
|
|
7242
7393
|
const parts = [
|
|
@@ -7393,17 +7544,17 @@ function countFingerprints(baseline) {
|
|
|
7393
7544
|
}
|
|
7394
7545
|
function resolveBaselineRequest(opts, configured, configDir, cwd, defaults) {
|
|
7395
7546
|
const named = (label) => ({
|
|
7396
|
-
absPath:
|
|
7547
|
+
absPath: resolve10(cwd, label),
|
|
7397
7548
|
label
|
|
7398
7549
|
});
|
|
7399
7550
|
const implied = () => {
|
|
7400
7551
|
const base = configDir ?? cwd;
|
|
7401
7552
|
if (configured !== void 0) {
|
|
7402
|
-
return { absPath:
|
|
7553
|
+
return { absPath: resolve10(base, configured), label: configured };
|
|
7403
7554
|
}
|
|
7404
|
-
const current =
|
|
7555
|
+
const current = resolve10(base, defaults.current);
|
|
7405
7556
|
if (defaults.legacy !== void 0) {
|
|
7406
|
-
const legacy =
|
|
7557
|
+
const legacy = resolve10(base, defaults.legacy);
|
|
7407
7558
|
if (!existsSync2(current) && existsSync2(legacy)) {
|
|
7408
7559
|
warn(
|
|
7409
7560
|
`"${defaults.legacy}" is the pre-rename baseline file name. Rename it to "${defaults.current}".`
|
|
@@ -7516,7 +7667,7 @@ function uriFrame(frame) {
|
|
|
7516
7667
|
}
|
|
7517
7668
|
function artifactUri(file, frame) {
|
|
7518
7669
|
const uri = canonicalFilePath(file, frame);
|
|
7519
|
-
if (uri === "" || uri.startsWith("../") ||
|
|
7670
|
+
if (uri === "" || uri.startsWith("../") || isAbsolute4(uri)) return null;
|
|
7520
7671
|
return uri;
|
|
7521
7672
|
}
|
|
7522
7673
|
function renderSarif(results, opts = {}) {
|
|
@@ -7910,22 +8061,92 @@ async function readCapped(url, res, maxBytes) {
|
|
|
7910
8061
|
|
|
7911
8062
|
// src/meta/core/external-metadata.ts
|
|
7912
8063
|
import { readFile as readFile6 } from "node:fs/promises";
|
|
7913
|
-
import { isAbsolute as
|
|
8064
|
+
import { isAbsolute as isAbsolute5, relative as relative8, resolve as resolve12, sep as sep3 } from "node:path";
|
|
7914
8065
|
import {
|
|
7915
|
-
LineCounter as
|
|
7916
|
-
isMap as
|
|
7917
|
-
isNode,
|
|
7918
|
-
isScalar as
|
|
8066
|
+
LineCounter as LineCounter3,
|
|
8067
|
+
isMap as isMap5,
|
|
8068
|
+
isNode as isNode2,
|
|
8069
|
+
isScalar as isScalar3,
|
|
7919
8070
|
isSeq as isSeq2,
|
|
7920
|
-
parseDocument as
|
|
8071
|
+
parseDocument as parseDocument5
|
|
7921
8072
|
} from "yaml";
|
|
7922
8073
|
|
|
8074
|
+
// src/shared/manifest-cas.ts
|
|
8075
|
+
import { posix as posix3 } from "node:path";
|
|
8076
|
+
var COMMIT_ATTEMPTS = 5;
|
|
8077
|
+
function conflictRefusal(file) {
|
|
8078
|
+
return `${file} changed under the command while it was being written. Nothing was written to it. Re-run the command.`;
|
|
8079
|
+
}
|
|
8080
|
+
function heldManifest(path, file, before, absent = false) {
|
|
8081
|
+
return { path, file, before, text: before, ops: [], bases: /* @__PURE__ */ new Map(), absent };
|
|
8082
|
+
}
|
|
8083
|
+
function encodeValue(value) {
|
|
8084
|
+
return value === void 0 ? "absent" : JSON.stringify(value);
|
|
8085
|
+
}
|
|
8086
|
+
function baseKey(at2) {
|
|
8087
|
+
const entry = at2.join === "path" ? posix3.normalize(at2.entry) : at2.entry;
|
|
8088
|
+
return `${entry}\0${at2.key}`;
|
|
8089
|
+
}
|
|
8090
|
+
function rebaseable(held, op, codec) {
|
|
8091
|
+
const at2 = baseKey(op);
|
|
8092
|
+
if (held.bases.has(at2)) return;
|
|
8093
|
+
held.bases.set(at2, {
|
|
8094
|
+
entry: op.entry,
|
|
8095
|
+
key: op.key,
|
|
8096
|
+
join: op.join,
|
|
8097
|
+
value: encodeValue(codec.read(held.before, op))
|
|
8098
|
+
});
|
|
8099
|
+
}
|
|
8100
|
+
function rebase(held, current, codec) {
|
|
8101
|
+
for (const base of held.bases.values()) {
|
|
8102
|
+
if (encodeValue(codec.read(current, base)) !== base.value) return void 0;
|
|
8103
|
+
}
|
|
8104
|
+
let text2 = current;
|
|
8105
|
+
for (const op of held.ops) text2 = codec.apply(text2, op);
|
|
8106
|
+
return text2;
|
|
8107
|
+
}
|
|
8108
|
+
function rebaseline(held) {
|
|
8109
|
+
held.before = held.text;
|
|
8110
|
+
held.ops = [];
|
|
8111
|
+
held.bases.clear();
|
|
8112
|
+
held.absent = false;
|
|
8113
|
+
}
|
|
8114
|
+
async function settle(held, io) {
|
|
8115
|
+
for (let attempt = 1; attempt <= COMMIT_ATTEMPTS; attempt++) {
|
|
8116
|
+
let current;
|
|
8117
|
+
try {
|
|
8118
|
+
current = await io.read(held.path);
|
|
8119
|
+
} catch (error) {
|
|
8120
|
+
if (held.absent && isMissing(error)) {
|
|
8121
|
+
await io.write(held.path, held.text);
|
|
8122
|
+
held.absent = false;
|
|
8123
|
+
return;
|
|
8124
|
+
}
|
|
8125
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
8126
|
+
throw io.toError(`Manifest ${held.file} could not be read: ${reason}`);
|
|
8127
|
+
}
|
|
8128
|
+
if (!held.absent && current === held.before) {
|
|
8129
|
+
await io.write(held.path, held.text);
|
|
8130
|
+
return;
|
|
8131
|
+
}
|
|
8132
|
+
const replayed = rebase(held, current, io.codec);
|
|
8133
|
+
if (replayed === void 0) throw io.toError(conflictRefusal(held.file));
|
|
8134
|
+
held.before = current;
|
|
8135
|
+
held.text = replayed;
|
|
8136
|
+
held.absent = false;
|
|
8137
|
+
}
|
|
8138
|
+
throw io.toError(conflictRefusal(held.file));
|
|
8139
|
+
}
|
|
8140
|
+
function isMissing(error) {
|
|
8141
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
8142
|
+
}
|
|
8143
|
+
|
|
7923
8144
|
// src/shared/encryption-key.ts
|
|
7924
8145
|
import { spawnSync } from "node:child_process";
|
|
7925
8146
|
import { readFile as readFile5 } from "node:fs/promises";
|
|
7926
|
-
import { basename as basename4, dirname as dirname6, join as join6, relative as
|
|
8147
|
+
import { basename as basename4, dirname as dirname6, join as join6, relative as relative7, resolve as resolve11 } from "node:path";
|
|
7927
8148
|
import { isDeepStrictEqual } from "node:util";
|
|
7928
|
-
import { isMap as
|
|
8149
|
+
import { isMap as isMap4, parseDocument as parseDocument4, parse as parseYaml3, stringify } from "yaml";
|
|
7929
8150
|
|
|
7930
8151
|
// src/shared/write-file.ts
|
|
7931
8152
|
import { chmod as chmod2, rename as rename2, rm as rm2, stat as stat5, writeFile as writeFile2 } from "node:fs/promises";
|
|
@@ -7935,8 +8156,8 @@ var RENAME_ATTEMPTS2 = 3;
|
|
|
7935
8156
|
function errorCode2(err) {
|
|
7936
8157
|
return typeof err === "object" && err !== null && "code" in err ? String(err.code) : void 0;
|
|
7937
8158
|
}
|
|
7938
|
-
var wait3 = (ms) => new Promise((
|
|
7939
|
-
setTimeout(
|
|
8159
|
+
var wait3 = (ms) => new Promise((resolve23) => {
|
|
8160
|
+
setTimeout(resolve23, ms);
|
|
7940
8161
|
});
|
|
7941
8162
|
async function writeTextAtomic(path, text2) {
|
|
7942
8163
|
const tmp = join5(
|
|
@@ -7985,7 +8206,7 @@ function resolveEncryptionKey(opts) {
|
|
|
7985
8206
|
return { key: void 0, source: "none" };
|
|
7986
8207
|
}
|
|
7987
8208
|
function relativeSource2(cwd, path) {
|
|
7988
|
-
return
|
|
8209
|
+
return relative7(resolve11(cwd), path).replace(/\\/g, "/");
|
|
7989
8210
|
}
|
|
7990
8211
|
function errorCode3(err) {
|
|
7991
8212
|
return typeof err === "object" && err !== null && "code" in err ? String(err.code) : void 0;
|
|
@@ -8008,7 +8229,7 @@ async function fileTarget(file, toError) {
|
|
|
8008
8229
|
return { path: file.path, source: file.source, text: text2 ?? file.text };
|
|
8009
8230
|
}
|
|
8010
8231
|
async function defaultTarget(cwd) {
|
|
8011
|
-
const root = findGitRoot(cwd) ??
|
|
8232
|
+
const root = findGitRoot(cwd) ?? resolve11(cwd);
|
|
8012
8233
|
for (const name2 of [...FAMILY_CONFIG_NAMES, ...MOOSE_CONFIG_NAMES]) {
|
|
8013
8234
|
const path2 = join6(root, name2);
|
|
8014
8235
|
const text2 = await readIfPresent(path2);
|
|
@@ -8018,12 +8239,12 @@ async function defaultTarget(cwd) {
|
|
|
8018
8239
|
return { path, source: relativeSource2(cwd, path), text: null };
|
|
8019
8240
|
}
|
|
8020
8241
|
function withKey(text2, key, previous, source, toError) {
|
|
8021
|
-
const doc =
|
|
8242
|
+
const doc = parseDocument4(text2);
|
|
8022
8243
|
const [first] = doc.errors;
|
|
8023
8244
|
if (first !== void 0) {
|
|
8024
8245
|
throw toError(`${source}: invalid YAML: ${first.message}`);
|
|
8025
8246
|
}
|
|
8026
|
-
if (doc.contents !== null && !
|
|
8247
|
+
if (doc.contents !== null && !isMap4(doc.contents)) {
|
|
8027
8248
|
throw toError(`${source}: top level must be a mapping.`);
|
|
8028
8249
|
}
|
|
8029
8250
|
doc.set(ENCRYPTION_KEY_FIELD, key);
|
|
@@ -8293,18 +8514,20 @@ function redactedDerived(f) {
|
|
|
8293
8514
|
var EXTERNAL_OWNED_SCHEMA = "external:owned";
|
|
8294
8515
|
var EXTERNAL_DUPLICATE_SCHEMA = "external:duplicate";
|
|
8295
8516
|
var EXTERNAL_KEYWORD = "external";
|
|
8296
|
-
var
|
|
8517
|
+
var PATH_JOIN2 = "path";
|
|
8297
8518
|
var parsedManifests = new ManifestCache();
|
|
8298
|
-
var
|
|
8519
|
+
var perPageRules = /* @__PURE__ */ new WeakMap();
|
|
8520
|
+
var strayEntries = /* @__PURE__ */ new WeakSet();
|
|
8521
|
+
var posix4 = (p) => p.split(sep3).join("/");
|
|
8299
8522
|
function reportedPath(abs, base) {
|
|
8300
|
-
const rel =
|
|
8301
|
-
return rel === "" ? "." :
|
|
8523
|
+
const rel = relative8(base, abs);
|
|
8524
|
+
return rel === "" ? "." : posix4(rel);
|
|
8302
8525
|
}
|
|
8303
8526
|
function reported(of, file) {
|
|
8304
8527
|
return of.file === file ? of : { ...of, file };
|
|
8305
8528
|
}
|
|
8306
8529
|
function externalMetadataJoin(manifest) {
|
|
8307
|
-
return manifest.join ??
|
|
8530
|
+
return manifest.join ?? PATH_JOIN2;
|
|
8308
8531
|
}
|
|
8309
8532
|
async function loadExternalMetadata(collections, opts) {
|
|
8310
8533
|
const configured = collections.flatMap(
|
|
@@ -8315,7 +8538,17 @@ async function loadExternalMetadata(collections, opts) {
|
|
|
8315
8538
|
const byPath = /* @__PURE__ */ new Map();
|
|
8316
8539
|
const byField = /* @__PURE__ */ new Map();
|
|
8317
8540
|
const entries = [];
|
|
8541
|
+
const resolvedBy = /* @__PURE__ */ new Map();
|
|
8542
|
+
const rules = [];
|
|
8318
8543
|
for (const { collection, manifest } of configured) {
|
|
8544
|
+
const declared = collections.find(
|
|
8545
|
+
(c) => c.name === collection && c.externalMetadata.includes(manifest)
|
|
8546
|
+
);
|
|
8547
|
+
if (declared !== void 0 && classifyRef(manifest.file).kind !== "url" && hasPagePlaceholder(manifest.file)) {
|
|
8548
|
+
await loadPerPage(declared, manifest, opts, resolvedBy, { owners, byPath, byField, entries });
|
|
8549
|
+
rules.push({ collection: declared, manifest, configDir: opts.configDir });
|
|
8550
|
+
continue;
|
|
8551
|
+
}
|
|
8319
8552
|
const join11 = externalMetadataJoin(manifest);
|
|
8320
8553
|
let parsed2;
|
|
8321
8554
|
let file;
|
|
@@ -8329,7 +8562,7 @@ async function loadExternalMetadata(collections, opts) {
|
|
|
8329
8562
|
});
|
|
8330
8563
|
parsed2 = parseManifest(manifest, collection, text2, file, opts.configDir, join11);
|
|
8331
8564
|
} else {
|
|
8332
|
-
const abs =
|
|
8565
|
+
const abs = isAbsolute5(manifest.file) ? manifest.file : resolve12(opts.configDir, manifest.file);
|
|
8333
8566
|
const label = reportedPath(abs, opts.base);
|
|
8334
8567
|
file = label;
|
|
8335
8568
|
parsed2 = await parsedManifests.parse(
|
|
@@ -8367,7 +8600,7 @@ async function loadExternalMetadata(collections, opts) {
|
|
|
8367
8600
|
else owners.set(key, [{ collection, file }]);
|
|
8368
8601
|
}
|
|
8369
8602
|
let target;
|
|
8370
|
-
if (join11 ===
|
|
8603
|
+
if (join11 === PATH_JOIN2) {
|
|
8371
8604
|
target = byPath;
|
|
8372
8605
|
} else {
|
|
8373
8606
|
const existing = byField.get(join11);
|
|
@@ -8384,23 +8617,112 @@ async function loadExternalMetadata(collections, opts) {
|
|
|
8384
8617
|
}
|
|
8385
8618
|
for (const entry of parsed2.entries) entries.push(reported(entry, file));
|
|
8386
8619
|
}
|
|
8387
|
-
|
|
8620
|
+
const index = { owners, byPath, byField, entries };
|
|
8621
|
+
if (rules.length > 0) perPageRules.set(index, rules);
|
|
8622
|
+
return index;
|
|
8623
|
+
}
|
|
8624
|
+
async function loadPerPage(declared, manifest, opts, resolvedBy, into) {
|
|
8625
|
+
const collection = declared.name;
|
|
8626
|
+
const join11 = externalMetadataJoin(manifest);
|
|
8627
|
+
for (const key of manifest.keys) {
|
|
8628
|
+
const list2 = into.owners.get(key);
|
|
8629
|
+
if (list2) list2.push({ collection, file: manifest.file });
|
|
8630
|
+
else into.owners.set(key, [{ collection, file: manifest.file }]);
|
|
8631
|
+
}
|
|
8632
|
+
const target = indexFor(join11, into);
|
|
8633
|
+
for (const pageAbs of opts.pages ?? []) {
|
|
8634
|
+
const resolved = pageManifestPath(manifest.file, opts.configDir, pageAbs);
|
|
8635
|
+
if ("outside" in resolved) {
|
|
8636
|
+
if (resolved.pageRel.startsWith("../") && matchesCollectionPaths(declared, resolved.pageRel)) {
|
|
8637
|
+
throw new DocmetaError(outsideRefusal(manifest, collection, resolved.pageRel));
|
|
8638
|
+
}
|
|
8639
|
+
continue;
|
|
8640
|
+
}
|
|
8641
|
+
const rel = posix4(relative8(opts.configDir, pageAbs));
|
|
8642
|
+
if (!isMember(declared, rel)) continue;
|
|
8643
|
+
const earlier = resolvedBy.get(resolved.abs);
|
|
8644
|
+
if (earlier !== void 0 && earlier !== pageAbs) {
|
|
8645
|
+
const [a, b] = [reportedPath(earlier, opts.base), reportedPath(pageAbs, opts.base)].sort();
|
|
8646
|
+
throw new DocmetaError(
|
|
8647
|
+
`${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.`
|
|
8648
|
+
);
|
|
8649
|
+
}
|
|
8650
|
+
resolvedBy.set(resolved.abs, pageAbs);
|
|
8651
|
+
const label = reportedPath(resolved.abs, opts.base);
|
|
8652
|
+
const parsed2 = await parsedManifests.parse(
|
|
8653
|
+
resolved.abs,
|
|
8654
|
+
JSON.stringify([collection, join11, opts.configDir, [...manifest.keys].sort()]),
|
|
8655
|
+
async () => parseManifest(
|
|
8656
|
+
manifest,
|
|
8657
|
+
collection,
|
|
8658
|
+
await readPageManifest(resolved.abs, label),
|
|
8659
|
+
label,
|
|
8660
|
+
opts.configDir,
|
|
8661
|
+
join11
|
|
8662
|
+
)
|
|
8663
|
+
);
|
|
8664
|
+
const pageLabel = reportedPath(pageAbs, opts.base);
|
|
8665
|
+
for (const entry of parsed2.entries) {
|
|
8666
|
+
if (entry.abs === void 0 || sameFile(entry.abs, pageAbs)) continue;
|
|
8667
|
+
const at2 = entry.line === void 0 ? label : `${label}:${String(entry.line)}`;
|
|
8668
|
+
throw new DocmetaError(
|
|
8669
|
+
`Manifest ${at2} names "${entry.spelled}", but ${PAGE_PLACEHOLDER} resolved this file for "${pageLabel}". A per-page manifest holds one entry, for its own page.`
|
|
8670
|
+
);
|
|
8671
|
+
}
|
|
8672
|
+
for (const [indexKey, values] of parsed2.values) {
|
|
8673
|
+
const key = join11 === PATH_JOIN2 ? pageAbs : indexKey;
|
|
8674
|
+
const merged = target.get(key) ?? /* @__PURE__ */ new Map();
|
|
8675
|
+
for (const [owned, value] of values) merged.set(owned, reported(value, label));
|
|
8676
|
+
target.set(key, merged);
|
|
8677
|
+
}
|
|
8678
|
+
for (const entry of parsed2.entries) {
|
|
8679
|
+
into.entries.push({
|
|
8680
|
+
...reported(entry, label),
|
|
8681
|
+
...entry.abs === void 0 ? {} : { abs: pageAbs }
|
|
8682
|
+
});
|
|
8683
|
+
}
|
|
8684
|
+
}
|
|
8685
|
+
}
|
|
8686
|
+
function indexFor(join11, into) {
|
|
8687
|
+
if (join11 === PATH_JOIN2) return into.byPath;
|
|
8688
|
+
const existing = into.byField.get(join11);
|
|
8689
|
+
if (existing) return existing;
|
|
8690
|
+
const created = /* @__PURE__ */ new Map();
|
|
8691
|
+
into.byField.set(join11, created);
|
|
8692
|
+
return created;
|
|
8693
|
+
}
|
|
8694
|
+
function outsideRefusal(manifest, collection, pageRel) {
|
|
8695
|
+
const tail = `for "${pageRel}". A ${PAGE_PLACEHOLDER} manifest stays under the config file.`;
|
|
8696
|
+
const origin = externalMetadataOrigin(manifest);
|
|
8697
|
+
if (origin === void 0) {
|
|
8698
|
+
return `externalMetadata file "${manifest.file}" of collection ${collection} resolves outside the config file's directory ${tail}`;
|
|
8699
|
+
}
|
|
8700
|
+
return `${origin.source}: ${origin.where}.file resolves outside ${origin.source}'s directory ${tail}`;
|
|
8701
|
+
}
|
|
8702
|
+
async function readPageManifest(abs, file) {
|
|
8703
|
+
try {
|
|
8704
|
+
return await readFile6(abs, "utf8");
|
|
8705
|
+
} catch (err) {
|
|
8706
|
+
if (isMissing(err)) return "";
|
|
8707
|
+
throw unreadable(file, err);
|
|
8708
|
+
}
|
|
8388
8709
|
}
|
|
8389
8710
|
async function readManifest(abs, file) {
|
|
8390
8711
|
try {
|
|
8391
8712
|
return await readFile6(abs, "utf8");
|
|
8392
8713
|
} catch (err) {
|
|
8393
|
-
|
|
8394
|
-
throw new DocmetaError(
|
|
8395
|
-
`Manifest ${file} could not be read: ${reason}`
|
|
8396
|
-
);
|
|
8714
|
+
throw unreadable(file, err);
|
|
8397
8715
|
}
|
|
8398
8716
|
}
|
|
8717
|
+
function unreadable(file, err) {
|
|
8718
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
8719
|
+
return new DocmetaError(`Manifest ${file} could not be read: ${reason}`);
|
|
8720
|
+
}
|
|
8399
8721
|
function parseManifest(manifest, collection, text2, file, configDir, join11) {
|
|
8400
8722
|
const target = /* @__PURE__ */ new Map();
|
|
8401
8723
|
const entries = [];
|
|
8402
|
-
const lc = new
|
|
8403
|
-
const doc =
|
|
8724
|
+
const lc = new LineCounter3();
|
|
8725
|
+
const doc = parseDocument5(text2, { lineCounter: lc, uniqueKeys: false });
|
|
8404
8726
|
const problem = doc.errors[0];
|
|
8405
8727
|
if (problem) {
|
|
8406
8728
|
throw new DocmetaError(
|
|
@@ -8408,21 +8730,21 @@ function parseManifest(manifest, collection, text2, file, configDir, join11) {
|
|
|
8408
8730
|
);
|
|
8409
8731
|
}
|
|
8410
8732
|
const root = doc.contents;
|
|
8411
|
-
if (root === null ||
|
|
8733
|
+
if (root === null || isScalar3(root) && root.value === null)
|
|
8412
8734
|
return { values: target, entries };
|
|
8413
|
-
if (!
|
|
8735
|
+
if (!isMap5(root)) {
|
|
8414
8736
|
throw new DocmetaError(
|
|
8415
|
-
`Manifest ${file}: the manifest must be a mapping from document ${join11 ===
|
|
8737
|
+
`Manifest ${file}: the manifest must be a mapping from document ${join11 === PATH_JOIN2 ? "path" : `"${join11}"`} to owned keys.`
|
|
8416
8738
|
);
|
|
8417
8739
|
}
|
|
8418
8740
|
const owned = new Set(manifest.keys);
|
|
8419
8741
|
const lineAt = (node) => {
|
|
8420
|
-
const range =
|
|
8742
|
+
const range = isNode2(node) ? node.range : void 0;
|
|
8421
8743
|
return range ? lc.linePos(range[0]).line : void 0;
|
|
8422
8744
|
};
|
|
8423
8745
|
const seen = /* @__PURE__ */ new Map();
|
|
8424
8746
|
for (const pair of root.items) {
|
|
8425
|
-
const spelled =
|
|
8747
|
+
const spelled = isScalar3(pair.key) ? String(pair.key.value) : String(pair.key);
|
|
8426
8748
|
const entryLine = lineAt(pair.key);
|
|
8427
8749
|
const where = entryLine === void 0 ? file : `${file}:${entryLine}`;
|
|
8428
8750
|
if (seen.has(spelled)) {
|
|
@@ -8432,15 +8754,15 @@ function parseManifest(manifest, collection, text2, file, configDir, join11) {
|
|
|
8432
8754
|
);
|
|
8433
8755
|
}
|
|
8434
8756
|
seen.set(spelled, entryLine);
|
|
8435
|
-
if (!
|
|
8757
|
+
if (!isMap5(pair.value)) {
|
|
8436
8758
|
throw new DocmetaError(
|
|
8437
8759
|
`Manifest ${where}: "${spelled}" must be a mapping of owned keys to values.`
|
|
8438
8760
|
);
|
|
8439
8761
|
}
|
|
8440
|
-
const indexKey = join11 ===
|
|
8762
|
+
const indexKey = join11 === PATH_JOIN2 ? resolve12(configDir, spelled) : spelled;
|
|
8441
8763
|
const values = target.get(indexKey) ?? /* @__PURE__ */ new Map();
|
|
8442
8764
|
for (const kv of pair.value.items) {
|
|
8443
|
-
const key =
|
|
8765
|
+
const key = isScalar3(kv.key) ? String(kv.key.value) : String(kv.key);
|
|
8444
8766
|
if (key === FILE_SCHEMA_KEY) {
|
|
8445
8767
|
throw new DocmetaError(
|
|
8446
8768
|
`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 +8788,7 @@ function parseManifest(manifest, collection, text2, file, configDir, join11) {
|
|
|
8466
8788
|
entries.push({
|
|
8467
8789
|
collection,
|
|
8468
8790
|
join: join11,
|
|
8469
|
-
...join11 ===
|
|
8791
|
+
...join11 === PATH_JOIN2 ? { abs: indexKey } : {},
|
|
8470
8792
|
spelled,
|
|
8471
8793
|
file,
|
|
8472
8794
|
...entryLine === void 0 ? {} : { line: entryLine }
|
|
@@ -8475,9 +8797,9 @@ function parseManifest(manifest, collection, text2, file, configDir, join11) {
|
|
|
8475
8797
|
return { values: target, entries };
|
|
8476
8798
|
}
|
|
8477
8799
|
function nodeLines(node, lineAt, prefix = "", out = /* @__PURE__ */ new Map()) {
|
|
8478
|
-
if (
|
|
8800
|
+
if (isMap5(node)) {
|
|
8479
8801
|
for (const kv of node.items) {
|
|
8480
|
-
const seg =
|
|
8802
|
+
const seg = isScalar3(kv.key) ? String(kv.key.value) : String(kv.key);
|
|
8481
8803
|
const pointer = `${prefix}/${escapePointerSegment(seg)}`;
|
|
8482
8804
|
const line = lineAt(kv.key) ?? lineAt(kv.value);
|
|
8483
8805
|
if (line !== void 0) out.set(pointer, line);
|
|
@@ -8516,7 +8838,7 @@ function mergeExternalMetadata(label, extracted, index, memberOf2, base, options
|
|
|
8516
8838
|
const sources = [];
|
|
8517
8839
|
const joins = [];
|
|
8518
8840
|
if (label !== STDIN_LABEL) {
|
|
8519
|
-
const byPath = index.byPath.get(
|
|
8841
|
+
const byPath = index.byPath.get(resolve12(base, label));
|
|
8520
8842
|
if (byPath) sources.push(byPath);
|
|
8521
8843
|
}
|
|
8522
8844
|
for (const [field, byValue] of index.byField) {
|
|
@@ -8611,10 +8933,41 @@ function externalMetadataPointer(key) {
|
|
|
8611
8933
|
}
|
|
8612
8934
|
function orphanEntries(index, loaded, base, collections) {
|
|
8613
8935
|
if (!index) return [];
|
|
8614
|
-
const have = new Set(loaded.map((l) =>
|
|
8615
|
-
|
|
8616
|
-
(e) => inCollections(e, collections) && e.join ===
|
|
8936
|
+
const have = new Set(loaded.map((l) => resolve12(base, l)));
|
|
8937
|
+
const orphans = index.entries.filter(
|
|
8938
|
+
(e) => inCollections(e, collections) && e.join === PATH_JOIN2 && e.abs !== void 0 && !have.has(e.abs)
|
|
8617
8939
|
);
|
|
8940
|
+
if (collections !== void 0) return orphans;
|
|
8941
|
+
return [...orphans, ...strayManifests(perPageRules.get(index) ?? [], have, base)];
|
|
8942
|
+
}
|
|
8943
|
+
function strayManifests(rules, loaded, base) {
|
|
8944
|
+
const strays = [];
|
|
8945
|
+
for (const { collection, manifest, configDir } of rules) {
|
|
8946
|
+
const read = /* @__PURE__ */ new Set();
|
|
8947
|
+
for (const pageAbs of loaded) {
|
|
8948
|
+
const resolved = pageManifestPath(manifest.file, configDir, pageAbs);
|
|
8949
|
+
if (!("outside" in resolved)) read.add(resolved.abs);
|
|
8950
|
+
}
|
|
8951
|
+
const found = findPageManifests(manifest.file, configDir, (rel) => isMember(collection, rel));
|
|
8952
|
+
for (const { abs, entries } of found) {
|
|
8953
|
+
if (read.has(abs)) continue;
|
|
8954
|
+
const file = reportedPath(abs, base);
|
|
8955
|
+
for (const entry of entries) {
|
|
8956
|
+
if (loaded.has(entry.pageAbs)) continue;
|
|
8957
|
+
const stray = {
|
|
8958
|
+
collection: collection.name,
|
|
8959
|
+
join: PATH_JOIN2,
|
|
8960
|
+
abs: entry.pageAbs,
|
|
8961
|
+
spelled: entry.spelled,
|
|
8962
|
+
file,
|
|
8963
|
+
...entry.line === void 0 ? {} : { line: entry.line }
|
|
8964
|
+
};
|
|
8965
|
+
strayEntries.add(stray);
|
|
8966
|
+
strays.push(stray);
|
|
8967
|
+
}
|
|
8968
|
+
}
|
|
8969
|
+
}
|
|
8970
|
+
return strays;
|
|
8618
8971
|
}
|
|
8619
8972
|
function inCollections(entry, collections) {
|
|
8620
8973
|
return collections === void 0 || collections.includes(entry.collection);
|
|
@@ -8622,7 +8975,7 @@ function inCollections(entry, collections) {
|
|
|
8622
8975
|
function orphanJoins(index, matched, collections) {
|
|
8623
8976
|
if (!index) return [];
|
|
8624
8977
|
return index.entries.filter(
|
|
8625
|
-
(e) => inCollections(e, collections) && e.join !==
|
|
8978
|
+
(e) => inCollections(e, collections) && e.join !== PATH_JOIN2 && !(matched.get(e.join)?.has(e.spelled) ?? false)
|
|
8626
8979
|
);
|
|
8627
8980
|
}
|
|
8628
8981
|
function orphanError(orphans) {
|
|
@@ -8630,9 +8983,10 @@ function orphanError(orphans) {
|
|
|
8630
8983
|
if (!first) throw new Error("orphanError called with no orphans");
|
|
8631
8984
|
const where = first.line === void 0 ? first.file : `${first.file}:${first.line}`;
|
|
8632
8985
|
const more = orphans.length > 1 ? ` (${orphans.length - 1} more)` : "";
|
|
8633
|
-
const what = first.join ===
|
|
8986
|
+
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`;
|
|
8987
|
+
const remove = strayEntries.has(first) ? "the file" : "it";
|
|
8634
8988
|
return new DocmetaError(
|
|
8635
|
-
`Manifest ${where} ${what}${more}. Fix the entry, or remove
|
|
8989
|
+
`Manifest ${where} ${what}${more}. Fix the entry, or remove ${remove}.`
|
|
8636
8990
|
);
|
|
8637
8991
|
}
|
|
8638
8992
|
|
|
@@ -8646,7 +9000,7 @@ function isFieldLocation(value) {
|
|
|
8646
9000
|
}
|
|
8647
9001
|
|
|
8648
9002
|
// src/meta/core/collections.ts
|
|
8649
|
-
import { isAbsolute as
|
|
9003
|
+
import { isAbsolute as isAbsolute6, relative as relative9, resolve as resolvePath2, sep as sep4 } from "node:path";
|
|
8650
9004
|
|
|
8651
9005
|
// src/meta/core/projection.ts
|
|
8652
9006
|
var SYSTEM_COLUMNS = ["_path", "_format", "_present", "_data"];
|
|
@@ -8867,8 +9221,8 @@ function loadSqlite() {
|
|
|
8867
9221
|
function memberOf(collections, configDir, base, label) {
|
|
8868
9222
|
if (collections.length === 0) return [];
|
|
8869
9223
|
if (label === STDIN_LABEL) return [];
|
|
8870
|
-
const rel =
|
|
8871
|
-
if (
|
|
9224
|
+
const rel = relative9(configDir, resolvePath2(base, label)).split(sep4).join("/");
|
|
9225
|
+
if (isAbsolute6(rel)) return [];
|
|
8872
9226
|
return collections.filter((c) => isMember(c, rel)).map((c) => c.name);
|
|
8873
9227
|
}
|
|
8874
9228
|
function retainMembers(files, membersFor) {
|
|
@@ -9322,7 +9676,7 @@ function toFieldError(schema, e, lineFor, colFor, locate) {
|
|
|
9322
9676
|
|
|
9323
9677
|
// src/meta/core/derive/cache.ts
|
|
9324
9678
|
import { createHash as createHash4 } from "node:crypto";
|
|
9325
|
-
import { mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
9679
|
+
import { mkdirSync, readFileSync as readFileSync2, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
9326
9680
|
import { join as join7 } from "node:path";
|
|
9327
9681
|
var REVIEW_CACHE_DIR = ".manni/meta/review-cache";
|
|
9328
9682
|
var REVIEW_CACHE_VERSION = 1;
|
|
@@ -9342,7 +9696,7 @@ var ReviewCache = class {
|
|
|
9342
9696
|
if (!this.enabled) return void 0;
|
|
9343
9697
|
let raw;
|
|
9344
9698
|
try {
|
|
9345
|
-
raw = JSON.parse(
|
|
9699
|
+
raw = JSON.parse(readFileSync2(this.entryPath(key), "utf8"));
|
|
9346
9700
|
} catch {
|
|
9347
9701
|
return void 0;
|
|
9348
9702
|
}
|
|
@@ -9906,12 +10260,12 @@ function utcDate(iso) {
|
|
|
9906
10260
|
}
|
|
9907
10261
|
|
|
9908
10262
|
// src/meta/core/derive/index.ts
|
|
9909
|
-
import { dirname as dirname9, resolve as
|
|
10263
|
+
import { dirname as dirname9, resolve as resolve14 } from "node:path";
|
|
9910
10264
|
|
|
9911
10265
|
// src/meta/core/derive/codeowners.ts
|
|
9912
10266
|
import { existsSync as existsSync3 } from "node:fs";
|
|
9913
10267
|
import { readFile as readFile7 } from "node:fs/promises";
|
|
9914
|
-
import { dirname as dirname7, relative as
|
|
10268
|
+
import { dirname as dirname7, relative as relative10, resolve as resolve13, sep as sep5 } from "node:path";
|
|
9915
10269
|
import picomatch4 from "picomatch";
|
|
9916
10270
|
var CODEOWNERS_LOCATIONS = [
|
|
9917
10271
|
".github/CODEOWNERS",
|
|
@@ -9921,11 +10275,11 @@ var CODEOWNERS_LOCATIONS = [
|
|
|
9921
10275
|
];
|
|
9922
10276
|
function findCodeowners(root, explicit) {
|
|
9923
10277
|
if (explicit !== void 0) {
|
|
9924
|
-
const path =
|
|
10278
|
+
const path = resolve13(root, explicit);
|
|
9925
10279
|
return existsSync3(path) ? path : null;
|
|
9926
10280
|
}
|
|
9927
10281
|
for (const loc of CODEOWNERS_LOCATIONS) {
|
|
9928
|
-
const path =
|
|
10282
|
+
const path = resolve13(root, ...loc.split("/"));
|
|
9929
10283
|
if (existsSync3(path)) return path;
|
|
9930
10284
|
}
|
|
9931
10285
|
return null;
|
|
@@ -10040,7 +10394,7 @@ function toGlobs(pattern) {
|
|
|
10040
10394
|
var NOT_FOUND_REASON = `no CODEOWNERS file found (looked for ${CODEOWNERS_LOCATIONS.join(", ")})`;
|
|
10041
10395
|
async function deriveFromCodeowners(inputs, opts) {
|
|
10042
10396
|
const records = /* @__PURE__ */ new Map();
|
|
10043
|
-
const explicitPath = opts.explicit === void 0 ? void 0 :
|
|
10397
|
+
const explicitPath = opts.explicit === void 0 ? void 0 : resolve13(opts.configDir ?? process.cwd(), opts.explicit);
|
|
10044
10398
|
if (explicitPath !== void 0 && !existsSync3(explicitPath)) {
|
|
10045
10399
|
return {
|
|
10046
10400
|
status: { available: false, reason: `CODEOWNERS not found at ${explicitPath}` },
|
|
@@ -10070,7 +10424,7 @@ async function deriveFromCodeowners(inputs, opts) {
|
|
|
10070
10424
|
continue;
|
|
10071
10425
|
}
|
|
10072
10426
|
found += 1;
|
|
10073
|
-
const label = toPosix2(
|
|
10427
|
+
const label = toPosix2(relative10(opts.configDir ?? root, path));
|
|
10074
10428
|
const key = `${path}\0${label}`;
|
|
10075
10429
|
let file = parsed2.get(key);
|
|
10076
10430
|
if (!file) {
|
|
@@ -10092,7 +10446,7 @@ async function deriveFromCodeowners(inputs, opts) {
|
|
|
10092
10446
|
};
|
|
10093
10447
|
}
|
|
10094
10448
|
for (const input of bucket) {
|
|
10095
|
-
const rel = toPosix2(
|
|
10449
|
+
const rel = toPosix2(relative10(root, input.absPath));
|
|
10096
10450
|
const hit = ownersFor(owners, rel);
|
|
10097
10451
|
records.set(
|
|
10098
10452
|
input.label,
|
|
@@ -10116,13 +10470,13 @@ async function deriveFromCodeowners(inputs, opts) {
|
|
|
10116
10470
|
return { status: { available: true }, records };
|
|
10117
10471
|
}
|
|
10118
10472
|
function toPosix2(p) {
|
|
10119
|
-
return p.split(
|
|
10473
|
+
return p.split(sep5).join("/");
|
|
10120
10474
|
}
|
|
10121
10475
|
|
|
10122
10476
|
// src/meta/core/derive/git.ts
|
|
10123
10477
|
import { constants as bufferConstants } from "node:buffer";
|
|
10124
10478
|
import { spawn as spawn3 } from "node:child_process";
|
|
10125
|
-
import { dirname as dirname8, extname as extname2, isAbsolute as
|
|
10479
|
+
import { dirname as dirname8, extname as extname2, isAbsolute as isAbsolute7, posix as posix5, relative as relative11, sep as sep6 } from "node:path";
|
|
10126
10480
|
import { parse as parseYaml4 } from "yaml";
|
|
10127
10481
|
|
|
10128
10482
|
// src/shared/pin.ts
|
|
@@ -10772,7 +11126,7 @@ function groupByRoot(inputs) {
|
|
|
10772
11126
|
rootOf.set(dir, root);
|
|
10773
11127
|
}
|
|
10774
11128
|
if (root === null) continue;
|
|
10775
|
-
const rel =
|
|
11129
|
+
const rel = relative11(root, input.absPath).split(sep6).join("/");
|
|
10776
11130
|
const bucket = byRoot.get(root);
|
|
10777
11131
|
if (bucket) bucket.push({ input, rel });
|
|
10778
11132
|
else byRoot.set(root, [{ input, rel }]);
|
|
@@ -11225,14 +11579,14 @@ async function commitEvidence(run2, root, entry, blame, history, blobs, manifest
|
|
|
11225
11579
|
return commits;
|
|
11226
11580
|
}
|
|
11227
11581
|
function insideRoot(root, abs) {
|
|
11228
|
-
const rel =
|
|
11229
|
-
if (rel === "" || rel.startsWith("..") ||
|
|
11230
|
-
return rel.split(
|
|
11582
|
+
const rel = relative11(root, abs);
|
|
11583
|
+
if (rel === "" || rel.startsWith("..") || isAbsolute7(rel)) return void 0;
|
|
11584
|
+
return rel.split(sep6).join("/");
|
|
11231
11585
|
}
|
|
11232
11586
|
function entryAt(entry, rel, relAtCommit) {
|
|
11233
11587
|
if (relAtCommit === rel) return entry;
|
|
11234
|
-
const fromHere =
|
|
11235
|
-
return
|
|
11588
|
+
const fromHere = posix5.relative(posix5.dirname(rel), relAtCommit);
|
|
11589
|
+
return posix5.join(posix5.dirname(entry), fromHere);
|
|
11236
11590
|
}
|
|
11237
11591
|
function manifestStamp(text2, key, join11) {
|
|
11238
11592
|
if (text2 === void 0) return [];
|
|
@@ -11244,7 +11598,7 @@ function manifestStamp(text2, key, join11) {
|
|
|
11244
11598
|
}
|
|
11245
11599
|
if (!isRecord5(data)) return [];
|
|
11246
11600
|
for (const [candidate, value] of Object.entries(data)) {
|
|
11247
|
-
const same2 = join11 === "path" ?
|
|
11601
|
+
const same2 = join11 === "path" ? posix5.normalize(candidate) === posix5.normalize(key) : candidate === key;
|
|
11248
11602
|
if (same2 && isRecord5(value)) return provenanceEntries(value[PROVENANCE_FIELD]);
|
|
11249
11603
|
}
|
|
11250
11604
|
return [];
|
|
@@ -11554,7 +11908,7 @@ async function deriveReviewsByRoot(inputs, git2, rootFor, ctx, requested) {
|
|
|
11554
11908
|
if (byRoot.size === 0) {
|
|
11555
11909
|
return unavailable3(requested, "no git repository contains the documents");
|
|
11556
11910
|
}
|
|
11557
|
-
const cacheDir =
|
|
11911
|
+
const cacheDir = resolve14(ctx.configDir ?? ctx.cwd, REVIEW_CACHE_DIR);
|
|
11558
11912
|
for (const [root, bucket] of byRoot) {
|
|
11559
11913
|
const client = ctx.reviews ?? await createReviewClient(root, { cwd: ctx.cwd, cache: ctx.cache, cacheDir, requested });
|
|
11560
11914
|
const identity = await client.detect();
|
|
@@ -11736,33 +12090,33 @@ import { readFile as readFile9 } from "node:fs/promises";
|
|
|
11736
12090
|
|
|
11737
12091
|
// src/meta/core/relocation.ts
|
|
11738
12092
|
import { access, readFile as readFile8, stat as stat6, unlink } from "node:fs/promises";
|
|
11739
|
-
import { basename as basename5, extname as extname3, isAbsolute as
|
|
12093
|
+
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
12094
|
import picomatch6 from "picomatch";
|
|
11741
12095
|
import {
|
|
11742
|
-
LineCounter as
|
|
11743
|
-
isMap as
|
|
11744
|
-
isNode as
|
|
11745
|
-
isScalar as
|
|
12096
|
+
LineCounter as LineCounter5,
|
|
12097
|
+
isMap as isMap7,
|
|
12098
|
+
isNode as isNode4,
|
|
12099
|
+
isScalar as isScalar5,
|
|
11746
12100
|
isSeq as isSeq4,
|
|
11747
12101
|
parse as parseYaml5,
|
|
11748
|
-
parseDocument as
|
|
12102
|
+
parseDocument as parseDocument7
|
|
11749
12103
|
} from "yaml";
|
|
11750
12104
|
|
|
11751
12105
|
// src/meta/core/external-metadata-write.ts
|
|
11752
|
-
import { posix as
|
|
12106
|
+
import { posix as posix6 } from "node:path";
|
|
11753
12107
|
import {
|
|
11754
|
-
LineCounter as
|
|
11755
|
-
isMap as
|
|
11756
|
-
isNode as
|
|
12108
|
+
LineCounter as LineCounter4,
|
|
12109
|
+
isMap as isMap6,
|
|
12110
|
+
isNode as isNode3,
|
|
11757
12111
|
isPair,
|
|
11758
|
-
isScalar as
|
|
12112
|
+
isScalar as isScalar4,
|
|
11759
12113
|
isSeq as isSeq3,
|
|
11760
|
-
parseDocument as
|
|
12114
|
+
parseDocument as parseDocument6,
|
|
11761
12115
|
stringify as stringify2
|
|
11762
12116
|
} from "yaml";
|
|
11763
12117
|
function spliceManifestValue(text2, options) {
|
|
11764
12118
|
const { entry, key, value, file } = options;
|
|
11765
|
-
const join11 = options.join ??
|
|
12119
|
+
const join11 = options.join ?? PATH_JOIN2;
|
|
11766
12120
|
const at2 = (line2) => {
|
|
11767
12121
|
const name2 = file === void 0 ? "Manifest" : `Manifest ${file}`;
|
|
11768
12122
|
if (line2 === void 0) return name2;
|
|
@@ -11777,8 +12131,8 @@ function spliceManifestValue(text2, options) {
|
|
|
11777
12131
|
throw new DocmetaError(`${at2()}: refusing to write "${key}" for "${entry}" with no value.`);
|
|
11778
12132
|
}
|
|
11779
12133
|
const eol = detectEol(text2);
|
|
11780
|
-
const lc = new
|
|
11781
|
-
const doc =
|
|
12134
|
+
const lc = new LineCounter4();
|
|
12135
|
+
const doc = parseDocument6(text2, { lineCounter: lc, uniqueKeys: false });
|
|
11782
12136
|
const problem = doc.errors[0];
|
|
11783
12137
|
if (problem) {
|
|
11784
12138
|
throw new DocmetaError(`${at2()} is not valid YAML: ${problem.message}`);
|
|
@@ -11787,15 +12141,15 @@ function spliceManifestValue(text2, options) {
|
|
|
11787
12141
|
const r = rangeOf(node);
|
|
11788
12142
|
return r ? lc.linePos(r[0]).line : void 0;
|
|
11789
12143
|
};
|
|
11790
|
-
const same2 = join11 ===
|
|
12144
|
+
const same2 = join11 === PATH_JOIN2 ? (a, b) => posix6.normalize(a) === posix6.normalize(b) : (a, b) => a === b;
|
|
11791
12145
|
const root = doc.contents;
|
|
11792
12146
|
let spelled = entry;
|
|
11793
12147
|
let edit;
|
|
11794
|
-
if (root === null ||
|
|
12148
|
+
if (root === null || isScalar4(root) && root.value === null && emptySource(text2, root)) {
|
|
11795
12149
|
edit = startManifest(text2, entry, key, value, eol);
|
|
11796
|
-
} else if (!
|
|
12150
|
+
} else if (!isMap6(root)) {
|
|
11797
12151
|
throw new DocmetaError(
|
|
11798
|
-
`${at2()}: the manifest must be a mapping from document ${join11 ===
|
|
12152
|
+
`${at2()}: the manifest must be a mapping from document ${join11 === PATH_JOIN2 ? "path" : `"${join11}"`} to owned keys.`
|
|
11799
12153
|
);
|
|
11800
12154
|
} else {
|
|
11801
12155
|
const style = detectStyle(text2, root, eol);
|
|
@@ -11817,7 +12171,7 @@ function spliceManifestValue(text2, options) {
|
|
|
11817
12171
|
spelled = keyString(first.key);
|
|
11818
12172
|
const where = at2(keyLine(first.key));
|
|
11819
12173
|
const v = first.value;
|
|
11820
|
-
if (!
|
|
12174
|
+
if (!isMap6(v)) {
|
|
11821
12175
|
throw new DocmetaError(`${where}: "${spelled}" must be a mapping of owned keys to values.`);
|
|
11822
12176
|
}
|
|
11823
12177
|
const hits = v.items.filter((kv) => keyString(kv.key) === key);
|
|
@@ -11860,30 +12214,30 @@ function spliceManifestValue(text2, options) {
|
|
|
11860
12214
|
return { text: out, line };
|
|
11861
12215
|
}
|
|
11862
12216
|
function readManifestValue(text2, options) {
|
|
11863
|
-
const join11 = options.join ??
|
|
11864
|
-
const doc =
|
|
12217
|
+
const join11 = options.join ?? PATH_JOIN2;
|
|
12218
|
+
const doc = parseDocument6(text2, { uniqueKeys: false });
|
|
11865
12219
|
if (doc.errors.length > 0) return void 0;
|
|
11866
12220
|
const root = doc.contents;
|
|
11867
|
-
if (!
|
|
11868
|
-
const same2 = join11 ===
|
|
12221
|
+
if (!isMap6(root)) return void 0;
|
|
12222
|
+
const same2 = join11 === PATH_JOIN2 ? (a, b) => posix6.normalize(a) === posix6.normalize(b) : (a, b) => a === b;
|
|
11869
12223
|
const pair = root.items.find((p) => same2(keyString(p.key), options.entry));
|
|
11870
12224
|
const held = pair?.value;
|
|
11871
|
-
if (!
|
|
12225
|
+
if (!isMap6(held)) return void 0;
|
|
11872
12226
|
const kv = held.items.find((p) => keyString(p.key) === options.key);
|
|
11873
12227
|
const node = kv?.value;
|
|
11874
|
-
return
|
|
12228
|
+
return isNode3(node) ? node.toJSON() : void 0;
|
|
11875
12229
|
}
|
|
11876
12230
|
function removeManifestKey(text2, options) {
|
|
11877
12231
|
const { entry, key, file } = options;
|
|
11878
|
-
const join11 = options.join ??
|
|
12232
|
+
const join11 = options.join ?? PATH_JOIN2;
|
|
11879
12233
|
const at2 = (line) => {
|
|
11880
12234
|
const name2 = file === void 0 ? "Manifest" : `Manifest ${file}`;
|
|
11881
12235
|
if (line === void 0) return name2;
|
|
11882
12236
|
return file === void 0 ? `${name2} line ${String(line)}` : `${name2}:${String(line)}`;
|
|
11883
12237
|
};
|
|
11884
12238
|
const eol = detectEol(text2);
|
|
11885
|
-
const lc = new
|
|
11886
|
-
const doc =
|
|
12239
|
+
const lc = new LineCounter4();
|
|
12240
|
+
const doc = parseDocument6(text2, { lineCounter: lc, uniqueKeys: false });
|
|
11887
12241
|
const problem = doc.errors[0];
|
|
11888
12242
|
if (problem) {
|
|
11889
12243
|
throw new DocmetaError(`${at2()} is not valid YAML: ${problem.message}`);
|
|
@@ -11893,13 +12247,13 @@ function removeManifestKey(text2, options) {
|
|
|
11893
12247
|
return r ? lc.linePos(r[0]).line : void 0;
|
|
11894
12248
|
};
|
|
11895
12249
|
const root = doc.contents;
|
|
11896
|
-
if (root === null ||
|
|
11897
|
-
if (!
|
|
12250
|
+
if (root === null || isScalar4(root) && root.value === null) return { text: text2 };
|
|
12251
|
+
if (!isMap6(root)) {
|
|
11898
12252
|
throw new DocmetaError(
|
|
11899
|
-
`${at2()}: the manifest must be a mapping from document ${join11 ===
|
|
12253
|
+
`${at2()}: the manifest must be a mapping from document ${join11 === PATH_JOIN2 ? "path" : `"${join11}"`} to owned keys.`
|
|
11900
12254
|
);
|
|
11901
12255
|
}
|
|
11902
|
-
const same2 = join11 ===
|
|
12256
|
+
const same2 = join11 === PATH_JOIN2 ? (a, b) => posix6.normalize(a) === posix6.normalize(b) : (a, b) => a === b;
|
|
11903
12257
|
const matches = root.items.filter((p) => same2(keyString(p.key), entry));
|
|
11904
12258
|
const [first, second] = matches;
|
|
11905
12259
|
if (first && second) {
|
|
@@ -11911,7 +12265,7 @@ function removeManifestKey(text2, options) {
|
|
|
11911
12265
|
const spelled = keyString(first.key);
|
|
11912
12266
|
const where = at2(keyLine(first.key));
|
|
11913
12267
|
const v = first.value;
|
|
11914
|
-
if (!
|
|
12268
|
+
if (!isMap6(v)) {
|
|
11915
12269
|
throw new DocmetaError(`${where}: "${spelled}" must be a mapping of owned keys to values.`);
|
|
11916
12270
|
}
|
|
11917
12271
|
const hits = v.items.filter((kv) => keyString(kv.key) === key);
|
|
@@ -11944,7 +12298,7 @@ function removeManifestKey(text2, options) {
|
|
|
11944
12298
|
else if (start === 0 && text2.startsWith(eol, end)) end += eol.length;
|
|
11945
12299
|
}
|
|
11946
12300
|
const out = text2.slice(0, start) + text2.slice(end);
|
|
11947
|
-
const after =
|
|
12301
|
+
const after = parseDocument6(out, { uniqueKeys: false });
|
|
11948
12302
|
const fail2 = (why) => new DocmetaError(
|
|
11949
12303
|
`${at2()}: removing "${key}" for "${entry}" did not read back as removed, so nothing was written. ${why}`
|
|
11950
12304
|
);
|
|
@@ -11964,14 +12318,14 @@ function removeManifestKey(text2, options) {
|
|
|
11964
12318
|
}
|
|
11965
12319
|
function renameManifestEntry(text2, options) {
|
|
11966
12320
|
const { entry, to, file } = options;
|
|
11967
|
-
const join11 = options.join ??
|
|
12321
|
+
const join11 = options.join ?? PATH_JOIN2;
|
|
11968
12322
|
const at2 = (line) => {
|
|
11969
12323
|
const name2 = file === void 0 ? "Manifest" : `Manifest ${file}`;
|
|
11970
12324
|
if (line === void 0) return name2;
|
|
11971
12325
|
return file === void 0 ? `${name2} line ${String(line)}` : `${name2}:${String(line)}`;
|
|
11972
12326
|
};
|
|
11973
|
-
const lc = new
|
|
11974
|
-
const doc =
|
|
12327
|
+
const lc = new LineCounter4();
|
|
12328
|
+
const doc = parseDocument6(text2, { lineCounter: lc, uniqueKeys: false });
|
|
11975
12329
|
const problem = doc.errors[0];
|
|
11976
12330
|
if (problem) {
|
|
11977
12331
|
throw new DocmetaError(`${at2()} is not valid YAML: ${problem.message}`);
|
|
@@ -11981,13 +12335,13 @@ function renameManifestEntry(text2, options) {
|
|
|
11981
12335
|
return r2 ? lc.linePos(r2[0]).line : void 0;
|
|
11982
12336
|
};
|
|
11983
12337
|
const root = doc.contents;
|
|
11984
|
-
if (root === null ||
|
|
11985
|
-
if (!
|
|
12338
|
+
if (root === null || isScalar4(root) && root.value === null) return { text: text2 };
|
|
12339
|
+
if (!isMap6(root)) {
|
|
11986
12340
|
throw new DocmetaError(
|
|
11987
|
-
`${at2()}: the manifest must be a mapping from document ${join11 ===
|
|
12341
|
+
`${at2()}: the manifest must be a mapping from document ${join11 === PATH_JOIN2 ? "path" : `"${join11}"`} to owned keys.`
|
|
11988
12342
|
);
|
|
11989
12343
|
}
|
|
11990
|
-
const same2 = join11 ===
|
|
12344
|
+
const same2 = join11 === PATH_JOIN2 ? (a, b) => posix6.normalize(a) === posix6.normalize(b) : (a, b) => a === b;
|
|
11991
12345
|
const [first, second] = root.items.filter((p) => same2(keyString(p.key), entry));
|
|
11992
12346
|
if (first && second) {
|
|
11993
12347
|
throw new DocmetaError(
|
|
@@ -12009,11 +12363,11 @@ function renameManifestEntry(text2, options) {
|
|
|
12009
12363
|
`${at2(keyLine(first.key))}: "${spelled}" is written in a form this writer does not edit. Write it as "${spelled}: \u2026".`
|
|
12010
12364
|
);
|
|
12011
12365
|
}
|
|
12012
|
-
const quoted =
|
|
12366
|
+
const quoted = isScalar4(first.key) && (first.key.type === "QUOTE_DOUBLE" || first.key.type === "QUOTE_SINGLE");
|
|
12013
12367
|
const plain = stringify2(to, { lineWidth: 0 }).replace(/\n$/, "");
|
|
12014
12368
|
const insert = quoted || plain.includes("\n") ? JSON.stringify(to) : plain;
|
|
12015
12369
|
const out = text2.slice(0, r[0]) + insert + text2.slice(end);
|
|
12016
|
-
const after =
|
|
12370
|
+
const after = parseDocument6(out, { uniqueKeys: false });
|
|
12017
12371
|
const fail2 = (why) => new DocmetaError(
|
|
12018
12372
|
`${at2()}: renaming "${spelled}" to "${to}" did not read back as renamed, so nothing was written. ${why}`
|
|
12019
12373
|
);
|
|
@@ -12047,7 +12401,7 @@ function appendEntry(text2, root, entry, key, value, style) {
|
|
|
12047
12401
|
const col = firstKey ? colOf(text2, firstKey[0]) : 0;
|
|
12048
12402
|
const pos = lineEnd(text2, contentEnd(text2, root) ?? text2.length);
|
|
12049
12403
|
const last = root.items.at(-1);
|
|
12050
|
-
const spaced = root.items.length > 1 &&
|
|
12404
|
+
const spaced = root.items.length > 1 && isNode3(last?.key) && last.key.spaceBefore === true;
|
|
12051
12405
|
return {
|
|
12052
12406
|
start: pos,
|
|
12053
12407
|
end: pos,
|
|
@@ -12087,7 +12441,7 @@ function replaceBlockValue(text2, pair, value, style) {
|
|
|
12087
12441
|
ownLine = true;
|
|
12088
12442
|
}
|
|
12089
12443
|
const old = pair.value;
|
|
12090
|
-
const oldEnd =
|
|
12444
|
+
const oldEnd = isScalar4(old) && old.value === null && emptySource(text2, old) ? start : contentEnd(text2, old) ?? start;
|
|
12091
12445
|
const end = Math.max(start, oldEnd);
|
|
12092
12446
|
let insert = afterColon(value, keyCol, style);
|
|
12093
12447
|
if (ownLine && !insert.startsWith(style.eol)) {
|
|
@@ -12102,8 +12456,8 @@ function replaceFlowValue(text2, pair, value) {
|
|
|
12102
12456
|
return { start: r[0], end, insert: flowText(value) };
|
|
12103
12457
|
}
|
|
12104
12458
|
function readBack(before, out, spelled, key, value, fail2) {
|
|
12105
|
-
const lc = new
|
|
12106
|
-
const after =
|
|
12459
|
+
const lc = new LineCounter4();
|
|
12460
|
+
const after = parseDocument6(out, { lineCounter: lc, uniqueKeys: false });
|
|
12107
12461
|
const problem = after.errors[0];
|
|
12108
12462
|
if (problem) throw fail2(`The result is not valid YAML: ${problem.message}`);
|
|
12109
12463
|
const was = before.toJS({ maxAliasCount: 100 });
|
|
@@ -12124,9 +12478,9 @@ function readBack(before, out, spelled, key, value, fail2) {
|
|
|
12124
12478
|
throw fail2("Another value in the manifest would have changed.");
|
|
12125
12479
|
}
|
|
12126
12480
|
const root = after.contents;
|
|
12127
|
-
const pair =
|
|
12481
|
+
const pair = isMap6(root) ? root.items.find((p) => keyString(p.key) === spelled) : void 0;
|
|
12128
12482
|
const entryMap = pair?.value;
|
|
12129
|
-
const kv =
|
|
12483
|
+
const kv = isMap6(entryMap) ? entryMap.items.find((p) => keyString(p.key) === key) : void 0;
|
|
12130
12484
|
const r = rangeOf(kv?.value) ?? rangeOf(kv?.key);
|
|
12131
12485
|
if (!r) throw fail2("The written value could not be found again.");
|
|
12132
12486
|
return lc.linePos(r[0]).line;
|
|
@@ -12157,7 +12511,7 @@ function detectStyle(text2, root, eol) {
|
|
|
12157
12511
|
for (const pair of root.items) {
|
|
12158
12512
|
const v = pair.value;
|
|
12159
12513
|
const entryKey = rangeOf(pair.key);
|
|
12160
|
-
const ownedKey =
|
|
12514
|
+
const ownedKey = isMap6(v) && v.flow !== true ? rangeOf(v.items[0]?.key) : void 0;
|
|
12161
12515
|
if (entryKey && ownedKey) {
|
|
12162
12516
|
const d = colOf(text2, ownedKey[0]) - colOf(text2, entryKey[0]);
|
|
12163
12517
|
if (d > 0) {
|
|
@@ -12169,7 +12523,7 @@ function detectStyle(text2, root, eol) {
|
|
|
12169
12523
|
return { step, indentSeq: seqIndented(text2, root) ?? true, eol };
|
|
12170
12524
|
}
|
|
12171
12525
|
function seqIndented(text2, node) {
|
|
12172
|
-
if (
|
|
12526
|
+
if (isMap6(node)) {
|
|
12173
12527
|
for (const pair of node.items) {
|
|
12174
12528
|
const v = pair.value;
|
|
12175
12529
|
if (isSeq3(v) && v.flow !== true && v.items.length > 0) {
|
|
@@ -12189,7 +12543,7 @@ function seqIndented(text2, node) {
|
|
|
12189
12543
|
return void 0;
|
|
12190
12544
|
}
|
|
12191
12545
|
function contentEnd(text2, node) {
|
|
12192
|
-
if (
|
|
12546
|
+
if (isMap6(node) && node.flow !== true) {
|
|
12193
12547
|
const last = node.items.at(-1);
|
|
12194
12548
|
if (last) return contentEnd(text2, last.value) ?? contentEnd(text2, last.key);
|
|
12195
12549
|
} else if (isSeq3(node) && node.flow !== true) {
|
|
@@ -12223,14 +12577,14 @@ function colOf(text2, offset) {
|
|
|
12223
12577
|
return offset - start;
|
|
12224
12578
|
}
|
|
12225
12579
|
function rangeOf(node) {
|
|
12226
|
-
return
|
|
12580
|
+
return isNode3(node) ? node.range ?? void 0 : void 0;
|
|
12227
12581
|
}
|
|
12228
12582
|
function emptySource(text2, node) {
|
|
12229
12583
|
const r = rangeOf(node);
|
|
12230
12584
|
return !r || text2.slice(r[0], r[1]).trim() === "";
|
|
12231
12585
|
}
|
|
12232
12586
|
function keyString(key) {
|
|
12233
|
-
return
|
|
12587
|
+
return isScalar4(key) ? String(key.value) : String(key);
|
|
12234
12588
|
}
|
|
12235
12589
|
function isRecord6(x) {
|
|
12236
12590
|
return typeof x === "object" && x !== null && !Array.isArray(x);
|
|
@@ -12260,13 +12614,13 @@ function relocationContext(run2, extras) {
|
|
|
12260
12614
|
...extras.onNotice !== void 0 ? { onNotice: extras.onNotice } : {}
|
|
12261
12615
|
};
|
|
12262
12616
|
}
|
|
12263
|
-
var toPosix3 = (p) => p.split(
|
|
12617
|
+
var toPosix3 = (p) => p.split(sep7).join("/");
|
|
12264
12618
|
function reported2(abs, base) {
|
|
12265
|
-
const rel =
|
|
12619
|
+
const rel = relative12(base, abs);
|
|
12266
12620
|
return rel === "" ? "." : toPosix3(rel);
|
|
12267
12621
|
}
|
|
12268
12622
|
function configSource(path, cwd) {
|
|
12269
|
-
return toPosix3(
|
|
12623
|
+
return toPosix3(relative12(cwd, path)) || basename5(path);
|
|
12270
12624
|
}
|
|
12271
12625
|
function cloneCollection(c) {
|
|
12272
12626
|
return {
|
|
@@ -12284,7 +12638,8 @@ var Model = class {
|
|
|
12284
12638
|
for (const c of this.collections) {
|
|
12285
12639
|
c.externalMetadata.forEach((m, index) => {
|
|
12286
12640
|
const url = classifyRef(m.file).kind === "url";
|
|
12287
|
-
const
|
|
12641
|
+
const perPage = !url && hasPagePlaceholder(m.file);
|
|
12642
|
+
const absPath = url || perPage ? void 0 : isAbsolute8(m.file) ? m.file : resolve15(configDir, m.file);
|
|
12288
12643
|
this.manifests.push({
|
|
12289
12644
|
collection: c.name,
|
|
12290
12645
|
index,
|
|
@@ -12293,6 +12648,7 @@ var Model = class {
|
|
|
12293
12648
|
absPath,
|
|
12294
12649
|
file: absPath === void 0 ? m.file : reported2(absPath, ctx.base),
|
|
12295
12650
|
join: externalMetadataJoin(m),
|
|
12651
|
+
perPage,
|
|
12296
12652
|
created: false,
|
|
12297
12653
|
keysBefore: [...m.keys],
|
|
12298
12654
|
keysAdded: [],
|
|
@@ -12319,6 +12675,22 @@ var Model = class {
|
|
|
12319
12675
|
manifestsOf(collection) {
|
|
12320
12676
|
return this.manifests.filter((m) => m.collection === collection);
|
|
12321
12677
|
}
|
|
12678
|
+
/**
|
|
12679
|
+
* The one file `m` keeps a page's values in, and how the run reports it:
|
|
12680
|
+
* the page's own for a `{page}` manifest (proposal 0058), the declared file
|
|
12681
|
+
* for any other. `abs` is undefined only for a URL manifest.
|
|
12682
|
+
*/
|
|
12683
|
+
fileFor(m, pageAbs) {
|
|
12684
|
+
if (!m.perPage) return { abs: m.absPath, file: m.file };
|
|
12685
|
+
const resolved = pageManifestPath(m.written, this.configDir, pageAbs);
|
|
12686
|
+
if ("outside" in resolved) {
|
|
12687
|
+
const declared = this.ctx.declaredCollections.find((c) => c.name === m.collection)?.externalMetadata[m.index];
|
|
12688
|
+
throw new DocmetaError(
|
|
12689
|
+
outsideRefusal(declared ?? { file: m.written, keys: [] }, m.collection, resolved.pageRel)
|
|
12690
|
+
);
|
|
12691
|
+
}
|
|
12692
|
+
return { abs: resolved.abs, file: reported2(resolved.abs, this.ctx.base) };
|
|
12693
|
+
}
|
|
12322
12694
|
/** The manifest of one of `members` that owns `key`, in declaration order. */
|
|
12323
12695
|
ownerOf(key, members) {
|
|
12324
12696
|
return this.manifests.find(
|
|
@@ -12404,7 +12776,8 @@ var Model = class {
|
|
|
12404
12776
|
url: false,
|
|
12405
12777
|
absPath,
|
|
12406
12778
|
file,
|
|
12407
|
-
join:
|
|
12779
|
+
join: PATH_JOIN2,
|
|
12780
|
+
perPage: false,
|
|
12408
12781
|
created: true,
|
|
12409
12782
|
keysBefore: [],
|
|
12410
12783
|
keysAdded: [],
|
|
@@ -12441,8 +12814,8 @@ var Model = class {
|
|
|
12441
12814
|
/** A label relative to the config directory, posix; undefined outside it. */
|
|
12442
12815
|
relative(label) {
|
|
12443
12816
|
if (label === "<stdin>") return void 0;
|
|
12444
|
-
const rel = toPosix3(
|
|
12445
|
-
return
|
|
12817
|
+
const rel = toPosix3(relative12(this.configDir, resolve15(this.ctx.base, label)));
|
|
12818
|
+
return isAbsolute8(rel) || rel.startsWith("../") ? void 0 : rel;
|
|
12446
12819
|
}
|
|
12447
12820
|
};
|
|
12448
12821
|
function dedupe2(xs) {
|
|
@@ -12453,17 +12826,17 @@ function bare(path) {
|
|
|
12453
12826
|
}
|
|
12454
12827
|
async function collectionPath(target, cwd, configDir) {
|
|
12455
12828
|
if (target === STDIN_TOKEN) return void 0;
|
|
12456
|
-
const
|
|
12457
|
-
const scanned = picomatch6.scan(
|
|
12829
|
+
const posix7 = target.replace(/\\/g, "/");
|
|
12830
|
+
const scanned = picomatch6.scan(posix7);
|
|
12458
12831
|
if (scanned.isGlob) {
|
|
12459
|
-
const rel2 = toPosix3(
|
|
12460
|
-
if (
|
|
12832
|
+
const rel2 = toPosix3(relative12(configDir, resolve15(cwd, scanned.base === "" ? "." : scanned.base)));
|
|
12833
|
+
if (isAbsolute8(rel2) || rel2 === ".." || rel2.startsWith("../")) return void 0;
|
|
12461
12834
|
return rel2 === "" ? scanned.glob : `${rel2}/${scanned.glob}`;
|
|
12462
12835
|
}
|
|
12463
|
-
const abs =
|
|
12464
|
-
const rel = toPosix3(
|
|
12465
|
-
if (
|
|
12466
|
-
let directory =
|
|
12836
|
+
const abs = resolve15(cwd, posix7);
|
|
12837
|
+
const rel = toPosix3(relative12(configDir, abs));
|
|
12838
|
+
if (isAbsolute8(rel) || rel.startsWith("..")) return void 0;
|
|
12839
|
+
let directory = posix7.endsWith("/");
|
|
12467
12840
|
if (!directory) {
|
|
12468
12841
|
try {
|
|
12469
12842
|
directory = (await stat6(abs)).isDirectory();
|
|
@@ -12484,28 +12857,30 @@ async function exists(absPath, file) {
|
|
|
12484
12857
|
}
|
|
12485
12858
|
}
|
|
12486
12859
|
function plannedConfigDir(ctx) {
|
|
12487
|
-
return ctx.configDir ?? findGitRoot(ctx.cwd) ??
|
|
12860
|
+
return ctx.configDir ?? findGitRoot(ctx.cwd) ?? resolve15(ctx.cwd);
|
|
12488
12861
|
}
|
|
12489
12862
|
async function keyHome(ctx, label, data, key) {
|
|
12490
12863
|
const model = new Model(ctx, plannedConfigDir(ctx));
|
|
12491
12864
|
const owner = model.ownerOf(key, model.members(label));
|
|
12492
12865
|
if (owner !== void 0) {
|
|
12493
|
-
|
|
12866
|
+
const at2 = model.fileFor(owner, resolve15(ctx.base, label));
|
|
12867
|
+
if (owner.url || at2.abs === void 0) {
|
|
12494
12868
|
return { kind: "url", collection: owner.collection, file: owner.file };
|
|
12495
12869
|
}
|
|
12496
12870
|
return {
|
|
12497
12871
|
kind: "manifest",
|
|
12498
12872
|
collection: owner.collection,
|
|
12499
|
-
file:
|
|
12500
|
-
absPath:
|
|
12873
|
+
file: at2.file,
|
|
12874
|
+
absPath: at2.abs,
|
|
12501
12875
|
join: owner.join,
|
|
12502
|
-
entry: entryFor(owner, label, data, model.configDir, ctx.base, lazyKey(ctx.configFile, ctx.env))
|
|
12876
|
+
entry: entryFor(owner, label, data, model.configDir, ctx.base, lazyKey(ctx.configFile, ctx.env)),
|
|
12877
|
+
perPage: owner.perPage
|
|
12503
12878
|
};
|
|
12504
12879
|
}
|
|
12505
12880
|
return { kind: "unowned", home: (await model.home(label, false)).proposed };
|
|
12506
12881
|
}
|
|
12507
12882
|
function entryFor(m, label, data, configDir, base, key) {
|
|
12508
|
-
if (m.join ===
|
|
12883
|
+
if (m.join === PATH_JOIN2) return toPosix3(relative12(configDir, resolve15(base, label)));
|
|
12509
12884
|
let raw = data[m.join];
|
|
12510
12885
|
if (isEncryptedValue(raw)) {
|
|
12511
12886
|
const k = key();
|
|
@@ -12522,6 +12897,27 @@ function entryFor(m, label, data, configDir, base, key) {
|
|
|
12522
12897
|
if (typeof raw === "number" || typeof raw === "boolean") return String(raw);
|
|
12523
12898
|
return void 0;
|
|
12524
12899
|
}
|
|
12900
|
+
async function relocationPages(ctx, request) {
|
|
12901
|
+
const pages2 = new Set(request.files.map((label) => resolve15(ctx.base, label)));
|
|
12902
|
+
const root = ctx.configDir ?? ctx.cwd;
|
|
12903
|
+
for (const collection of ctx.declaredCollections) {
|
|
12904
|
+
const perPage = collection.externalMetadata.some(
|
|
12905
|
+
(m) => classifyRef(m.file).kind !== "url" && hasPagePlaceholder(m.file)
|
|
12906
|
+
);
|
|
12907
|
+
if (!perPage) continue;
|
|
12908
|
+
const walked = await resolveTargetSet({
|
|
12909
|
+
inputs: [...collection.paths],
|
|
12910
|
+
cwd: root,
|
|
12911
|
+
allowEmpty: true,
|
|
12912
|
+
...gitignoreOptions({
|
|
12913
|
+
...ctx.respectGitignore !== void 0 ? { flag: ctx.respectGitignore } : {},
|
|
12914
|
+
...ctx.config?.respectGitignore !== void 0 ? { configured: ctx.config.respectGitignore } : {}
|
|
12915
|
+
})
|
|
12916
|
+
});
|
|
12917
|
+
for (const file of walked.files) pages2.add(resolve15(root, file));
|
|
12918
|
+
}
|
|
12919
|
+
return [...pages2];
|
|
12920
|
+
}
|
|
12525
12921
|
async function planRelocation(ctx, request) {
|
|
12526
12922
|
const configDir = plannedConfigDir(ctx);
|
|
12527
12923
|
const model = new Model(ctx, configDir);
|
|
@@ -12529,7 +12925,8 @@ async function planRelocation(ctx, request) {
|
|
|
12529
12925
|
const index = await loadExternalMetadata(ctx.declaredCollections, {
|
|
12530
12926
|
configDir: ctx.configDir ?? ctx.cwd,
|
|
12531
12927
|
base: ctx.base,
|
|
12532
|
-
offline: ctx.config?.offline ?? false
|
|
12928
|
+
offline: ctx.config?.offline ?? false,
|
|
12929
|
+
pages: await relocationPages(ctx, request)
|
|
12533
12930
|
});
|
|
12534
12931
|
const trustRoot = schemaTrustRoot(ctx.cwd, ctx.configDir);
|
|
12535
12932
|
const forced = ctx.as !== void 0 ? extractorByName(ctx.as) : void 0;
|
|
@@ -12546,17 +12943,17 @@ async function planRelocation(ctx, request) {
|
|
|
12546
12943
|
if (beyond) return void 0;
|
|
12547
12944
|
throw new DocmetaError(`Unsupported file type "${extname3(label)}" for "${label}". Use --as to override.`);
|
|
12548
12945
|
}
|
|
12549
|
-
const absPath =
|
|
12946
|
+
const absPath = resolve15(ctx.base, label);
|
|
12550
12947
|
const elements = resolveElements(label, ctx.config, currentMembers(label));
|
|
12551
12948
|
let content = "";
|
|
12552
12949
|
let own2 = {};
|
|
12553
|
-
let
|
|
12950
|
+
let unreadable2;
|
|
12554
12951
|
if (beyond) {
|
|
12555
12952
|
try {
|
|
12556
12953
|
content = await readFile8(absPath, "utf8");
|
|
12557
12954
|
own2 = extractor.extract(content, label, { elements }).data;
|
|
12558
12955
|
} catch (err) {
|
|
12559
|
-
|
|
12956
|
+
unreadable2 = (errorMessage(err).split("\n")[0] ?? "").replace(/:\s*$/, "");
|
|
12560
12957
|
}
|
|
12561
12958
|
} else {
|
|
12562
12959
|
content = await readFile8(absPath, "utf8");
|
|
@@ -12575,7 +12972,7 @@ async function planRelocation(ctx, request) {
|
|
|
12575
12972
|
extractor,
|
|
12576
12973
|
own: own2,
|
|
12577
12974
|
beyond,
|
|
12578
|
-
...
|
|
12975
|
+
...unreadable2 !== void 0 ? { unreadable: unreadable2 } : {},
|
|
12579
12976
|
intents: /* @__PURE__ */ new Map()
|
|
12580
12977
|
};
|
|
12581
12978
|
pages2.set(label, page);
|
|
@@ -12584,13 +12981,13 @@ async function planRelocation(ctx, request) {
|
|
|
12584
12981
|
const supplied = (m, page, key) => {
|
|
12585
12982
|
if (m.created || index === null) return void 0;
|
|
12586
12983
|
let sv;
|
|
12587
|
-
if (m.join ===
|
|
12984
|
+
if (m.join === PATH_JOIN2) {
|
|
12588
12985
|
sv = index.byPath.get(page.absPath)?.get(key);
|
|
12589
12986
|
} else {
|
|
12590
12987
|
const entry = entryFor(m, page.label, page.own, configDir, ctx.base, encryptionKey);
|
|
12591
12988
|
sv = entry === void 0 ? void 0 : index.byField.get(m.join)?.get(entry)?.get(key);
|
|
12592
12989
|
}
|
|
12593
|
-
return sv !== void 0 && sv.collection === m.collection && sv.file === m.file ? sv : void 0;
|
|
12990
|
+
return sv !== void 0 && sv.collection === m.collection && sv.file === model.fileFor(m, page.absPath).file ? sv : void 0;
|
|
12594
12991
|
};
|
|
12595
12992
|
const stay = (page, key, reason, detail, links = {}) => {
|
|
12596
12993
|
page.intents.set(key, { kind: "stay", reason, detail, ...links });
|
|
@@ -12610,7 +13007,7 @@ async function planRelocation(ctx, request) {
|
|
|
12610
13007
|
}
|
|
12611
13008
|
const held = supplied(m, page, key);
|
|
12612
13009
|
if (held !== void 0 && !deepEqual(held.value, page.own[key])) {
|
|
12613
|
-
stay(page, key, "values-differ", `the page and ${
|
|
13010
|
+
stay(page, key, "values-differ", `the page and ${held.file} hold different values`, { toward: m });
|
|
12614
13011
|
return;
|
|
12615
13012
|
}
|
|
12616
13013
|
page.intents.set(key, { kind: "out", manifest: m, reason, drop: held !== void 0, entry });
|
|
@@ -12623,7 +13020,7 @@ async function planRelocation(ctx, request) {
|
|
|
12623
13020
|
if (entry === void 0) return;
|
|
12624
13021
|
if (Object.hasOwn(page.own, key)) {
|
|
12625
13022
|
if (!deepEqual(held.value, page.own[key])) {
|
|
12626
|
-
stay(page, key, "values-differ", `the page and ${
|
|
13023
|
+
stay(page, key, "values-differ", `the page and ${held.file} hold different values`, { blocks: m });
|
|
12627
13024
|
return;
|
|
12628
13025
|
}
|
|
12629
13026
|
page.intents.set(key, { kind: "in", manifest: m, drop: true, entry, value: held.value });
|
|
@@ -12669,7 +13066,7 @@ async function planRelocation(ctx, request) {
|
|
|
12669
13066
|
preferencesOf.set(label, prefs);
|
|
12670
13067
|
const planned = model.members(label);
|
|
12671
13068
|
const joins = new Set(
|
|
12672
|
-
model.manifests.filter((m) => planned.includes(m.collection) && m.join !==
|
|
13069
|
+
model.manifests.filter((m) => planned.includes(m.collection) && m.join !== PATH_JOIN2).map((m) => m.join)
|
|
12673
13070
|
);
|
|
12674
13071
|
for (const m of model.manifests) {
|
|
12675
13072
|
if (planned.includes(m.collection)) for (const k of [...m.keysBefore, ...m.keysAdded]) marked.add(k);
|
|
@@ -12759,7 +13156,7 @@ async function planRelocation(ctx, request) {
|
|
|
12759
13156
|
});
|
|
12760
13157
|
const labels = dedupe2([
|
|
12761
13158
|
...request.files,
|
|
12762
|
-
...walked.files.map((f) => reported2(
|
|
13159
|
+
...walked.files.map((f) => reported2(resolve15(configDir, f), ctx.base))
|
|
12763
13160
|
]).filter((label) => model.members(label).includes(name2));
|
|
12764
13161
|
for (const label of labels) {
|
|
12765
13162
|
const page = await load(label, !runSet.has(label));
|
|
@@ -12776,7 +13173,7 @@ async function planRelocation(ctx, request) {
|
|
|
12776
13173
|
const changing = covered ? out : out.filter((k) => m.keysAdded.includes(k));
|
|
12777
13174
|
for (const key of changing) if (!page.intents.has(key)) stay(page, key, "unreadable", detail);
|
|
12778
13175
|
for (const key of m.keysRemoved) {
|
|
12779
|
-
const held = m.join !==
|
|
13176
|
+
const held = m.join !== PATH_JOIN2 || !m.created && index?.byPath.get(page.absPath)?.get(key)?.file === model.fileFor(m, page.absPath).file;
|
|
12780
13177
|
if (held && !page.intents.has(key)) stay(page, key, "unreadable", detail, { blocks: m });
|
|
12781
13178
|
}
|
|
12782
13179
|
continue;
|
|
@@ -12827,35 +13224,50 @@ async function planRelocation(ctx, request) {
|
|
|
12827
13224
|
const writes = [];
|
|
12828
13225
|
const lines = /* @__PURE__ */ new Map();
|
|
12829
13226
|
for (const m of model.manifests) {
|
|
12830
|
-
if (m.url
|
|
13227
|
+
if (m.url) continue;
|
|
12831
13228
|
const undeclared = model.finalKeys(m).length === 0 && !m.created;
|
|
12832
|
-
const
|
|
12833
|
-
const
|
|
13229
|
+
const files = /* @__PURE__ */ new Map();
|
|
13230
|
+
const group = (at2) => {
|
|
13231
|
+
if (at2.abs === void 0) return void 0;
|
|
13232
|
+
const have = files.get(at2.abs);
|
|
13233
|
+
if (have !== void 0) return have;
|
|
13234
|
+
const made = { file: at2.file, outs: [], ins: [] };
|
|
13235
|
+
files.set(at2.abs, made);
|
|
13236
|
+
return made;
|
|
13237
|
+
};
|
|
13238
|
+
if (m.created) group({ abs: m.absPath, file: m.file });
|
|
12834
13239
|
for (const page of orderedPages()) {
|
|
12835
13240
|
for (const [key, intent] of orderedIntents(page)) {
|
|
12836
|
-
if (intent.kind === "out" && intent.manifest === m) {
|
|
12837
|
-
|
|
12838
|
-
|
|
12839
|
-
|
|
13241
|
+
if ((intent.kind === "out" || intent.kind === "in") && intent.manifest === m) {
|
|
13242
|
+
const into = group(model.fileFor(m, page.absPath));
|
|
13243
|
+
if (intent.kind === "out") {
|
|
13244
|
+
into?.outs.push({ page: page.label, entry: intent.entry, key, value: page.own[key], drop: intent.drop });
|
|
13245
|
+
} else {
|
|
13246
|
+
into?.ins.push({ entry: intent.entry, key });
|
|
13247
|
+
}
|
|
12840
13248
|
}
|
|
12841
13249
|
}
|
|
12842
13250
|
}
|
|
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
|
-
|
|
13251
|
+
if (!undeclared) assertNoStrandedEntries(m, index, pages2, configDir, (abs) => model.fileFor(m, abs).file);
|
|
13252
|
+
if (undeclared) continue;
|
|
13253
|
+
for (const [path, { file, outs, ins }] of files) {
|
|
13254
|
+
if (!m.created && outs.length === 0 && ins.length === 0) continue;
|
|
13255
|
+
const disk = m.created ? null : await readManifestText(path, file, m.perPage);
|
|
13256
|
+
let text2 = disk ?? "";
|
|
13257
|
+
const before = text2;
|
|
13258
|
+
const where = { join: m.join, file };
|
|
13259
|
+
for (const o of outs) {
|
|
13260
|
+
if (!o.drop) text2 = spliceManifestValue(text2, { ...where, entry: o.entry, key: o.key, value: o.value }).text;
|
|
13261
|
+
}
|
|
13262
|
+
for (const i of ins) text2 = removeManifestKey(text2, { ...where, entry: i.entry, key: i.key }).text;
|
|
13263
|
+
const found = keyLines(text2, m.join);
|
|
13264
|
+
for (const o of outs) {
|
|
13265
|
+
const line = found.get(entryId(o.entry, m.join))?.get(o.key);
|
|
13266
|
+
if (line !== void 0) lines.set(lineId(o.page, file, o.key), line);
|
|
13267
|
+
}
|
|
13268
|
+
if (m.created || text2 !== before) {
|
|
13269
|
+
writes.push({ path, text: text2, kind: "manifest", before: disk });
|
|
13270
|
+
}
|
|
12859
13271
|
}
|
|
12860
13272
|
}
|
|
12861
13273
|
const finalCollections = model.final();
|
|
@@ -12954,7 +13366,7 @@ function planPageText(page) {
|
|
|
12954
13366
|
refuse();
|
|
12955
13367
|
}
|
|
12956
13368
|
}
|
|
12957
|
-
function assertNoStrandedEntries(m, index, pages2, configDir) {
|
|
13369
|
+
function assertNoStrandedEntries(m, index, pages2, configDir, fileOf) {
|
|
12958
13370
|
if (index === null || m.keysRemoved.length === 0) return;
|
|
12959
13371
|
for (const key of m.keysRemoved) {
|
|
12960
13372
|
const moved = /* @__PURE__ */ new Set();
|
|
@@ -12962,10 +13374,10 @@ function assertNoStrandedEntries(m, index, pages2, configDir) {
|
|
|
12962
13374
|
const i = page.intents.get(key);
|
|
12963
13375
|
if (i?.kind === "in" && i.manifest === m) moved.add(entryId(i.entry, m.join));
|
|
12964
13376
|
}
|
|
12965
|
-
const stranded = m.join ===
|
|
13377
|
+
const stranded = m.join === PATH_JOIN2 ? [...index.byPath].filter(([abs, values]) => {
|
|
12966
13378
|
const sv = values.get(key);
|
|
12967
|
-
return sv !== void 0 && sv.
|
|
12968
|
-
}).map(([abs]) => toPosix3(
|
|
13379
|
+
return sv !== void 0 && sv.collection === m.collection && sv.file === fileOf(abs);
|
|
13380
|
+
}).map(([abs]) => toPosix3(relative12(configDir, abs))) : [...index.byField.get(m.join) ?? /* @__PURE__ */ new Map()].filter(([, values]) => {
|
|
12969
13381
|
const sv = values.get(key);
|
|
12970
13382
|
return sv !== void 0 && sv.file === m.file && sv.collection === m.collection;
|
|
12971
13383
|
}).map(([value]) => value);
|
|
@@ -12977,29 +13389,29 @@ function assertNoStrandedEntries(m, index, pages2, configDir) {
|
|
|
12977
13389
|
}
|
|
12978
13390
|
}
|
|
12979
13391
|
}
|
|
12980
|
-
async function readManifestText(
|
|
12981
|
-
if (m.absPath === void 0) return "";
|
|
13392
|
+
async function readManifestText(path, file, perPage) {
|
|
12982
13393
|
try {
|
|
12983
|
-
return await readFile8(
|
|
13394
|
+
return await readFile8(path, "utf8");
|
|
12984
13395
|
} catch (err) {
|
|
12985
|
-
|
|
13396
|
+
if (perPage && isMissing(err)) return null;
|
|
13397
|
+
throw new DocmetaError(`Manifest ${file} could not be read: ${errorMessage(err)}`);
|
|
12986
13398
|
}
|
|
12987
13399
|
}
|
|
12988
|
-
var entryId = (entry, join11) => join11 ===
|
|
13400
|
+
var entryId = (entry, join11) => join11 === PATH_JOIN2 ? toPosix3(entry).replace(/^\.\//, "").replace(/\/+/g, "/") : entry;
|
|
12989
13401
|
var lineId = (page, manifest, key) => `${page}\0${manifest}\0${key}`;
|
|
12990
13402
|
function keyLines(text2, join11) {
|
|
12991
13403
|
const out = /* @__PURE__ */ new Map();
|
|
12992
|
-
const lc = new
|
|
12993
|
-
const doc =
|
|
13404
|
+
const lc = new LineCounter5();
|
|
13405
|
+
const doc = parseDocument7(text2, { lineCounter: lc, uniqueKeys: false });
|
|
12994
13406
|
const root = doc.contents;
|
|
12995
|
-
if (!
|
|
13407
|
+
if (!isMap7(root)) return out;
|
|
12996
13408
|
for (const pair of root.items) {
|
|
12997
|
-
const spelled =
|
|
12998
|
-
if (!
|
|
13409
|
+
const spelled = isScalar5(pair.key) ? String(pair.key.value) : String(pair.key);
|
|
13410
|
+
if (!isMap7(pair.value)) continue;
|
|
12999
13411
|
const keys = /* @__PURE__ */ new Map();
|
|
13000
13412
|
for (const kv of pair.value.items) {
|
|
13001
|
-
const name2 =
|
|
13002
|
-
const range =
|
|
13413
|
+
const name2 = isScalar5(kv.key) ? String(kv.key.value) : String(kv.key);
|
|
13414
|
+
const range = isNode4(kv.key) ? kv.key.range : void 0;
|
|
13003
13415
|
if (range) keys.set(name2, lc.linePos(range[0]).line);
|
|
13004
13416
|
}
|
|
13005
13417
|
out.set(entryId(spelled, join11), keys);
|
|
@@ -13031,10 +13443,10 @@ async function configTarget(ctx, configDir) {
|
|
|
13031
13443
|
return { path: join8(configDir, FAMILY_CONFIG_NAMES[0] ?? "manni.config.yaml"), text: null, disk: null };
|
|
13032
13444
|
}
|
|
13033
13445
|
function editConfig(text2, model, source) {
|
|
13034
|
-
const doc =
|
|
13446
|
+
const doc = parseDocument7(text2 ?? "");
|
|
13035
13447
|
const [problem] = doc.errors;
|
|
13036
13448
|
if (problem !== void 0) throw new DocmetaError(`${source}: invalid YAML: ${problem.message}`);
|
|
13037
|
-
if (doc.contents !== null && !
|
|
13449
|
+
if (doc.contents !== null && !isMap7(doc.contents)) {
|
|
13038
13450
|
throw new DocmetaError(`${source}: top level must be a mapping.`);
|
|
13039
13451
|
}
|
|
13040
13452
|
const fail2 = () => {
|
|
@@ -13044,7 +13456,7 @@ function editConfig(text2, model, source) {
|
|
|
13044
13456
|
if (!isSeq4(node)) return;
|
|
13045
13457
|
node.flow = true;
|
|
13046
13458
|
if (quoted) {
|
|
13047
|
-
for (const item of node.items) if (
|
|
13459
|
+
for (const item of node.items) if (isScalar5(item)) item.type = "QUOTE_DOUBLE";
|
|
13048
13460
|
}
|
|
13049
13461
|
};
|
|
13050
13462
|
const manifestNode = (d, file, keys) => {
|
|
@@ -13058,13 +13470,13 @@ function editConfig(text2, model, source) {
|
|
|
13058
13470
|
for (let i = 0; i < declared; i++) {
|
|
13059
13471
|
const c = model.collections[i];
|
|
13060
13472
|
const node = isSeq4(existing) ? existing.items[i] : void 0;
|
|
13061
|
-
if (c === void 0 || !
|
|
13473
|
+
if (c === void 0 || !isMap7(node)) return fail2();
|
|
13062
13474
|
for (const added of model.pathsAdded.filter((p) => p.collection === c.name)) {
|
|
13063
13475
|
const paths = node.get("paths", true);
|
|
13064
13476
|
if (!isSeq4(paths)) return fail2();
|
|
13065
13477
|
const scalar = doc.createNode(added.path);
|
|
13066
13478
|
const first = paths.items[0];
|
|
13067
|
-
if (
|
|
13479
|
+
if (isScalar5(first) && first.type !== void 0) scalar.type = first.type;
|
|
13068
13480
|
paths.add(scalar);
|
|
13069
13481
|
}
|
|
13070
13482
|
const refs = model.manifestsOf(c.name);
|
|
@@ -13081,7 +13493,7 @@ function editConfig(text2, model, source) {
|
|
|
13081
13493
|
}
|
|
13082
13494
|
if (m.keysAdded.length === 0) continue;
|
|
13083
13495
|
const entry = node.getIn(["externalMetadata", m.index], true);
|
|
13084
|
-
const keys =
|
|
13496
|
+
const keys = isMap7(entry) ? entry.get("keys", true) : void 0;
|
|
13085
13497
|
if (!isSeq4(keys)) return fail2();
|
|
13086
13498
|
for (const key of m.keysAdded) keys.add(doc.createNode(key));
|
|
13087
13499
|
}
|
|
@@ -13090,10 +13502,10 @@ function editConfig(text2, model, source) {
|
|
|
13090
13502
|
if (m.keysRemoved.length === 0) continue;
|
|
13091
13503
|
if (!isSeq4(list2)) return fail2();
|
|
13092
13504
|
const entry = list2.items[m.index];
|
|
13093
|
-
const keys =
|
|
13505
|
+
const keys = isMap7(entry) ? entry.get("keys", true) : void 0;
|
|
13094
13506
|
if (!isSeq4(keys)) return fail2();
|
|
13095
13507
|
for (const key of m.keysRemoved) {
|
|
13096
|
-
const at2 = keys.items.findIndex((item) => (
|
|
13508
|
+
const at2 = keys.items.findIndex((item) => (isScalar5(item) ? String(item.value) : String(item)) === key);
|
|
13097
13509
|
if (at2 >= 0) keys.delete(at2);
|
|
13098
13510
|
}
|
|
13099
13511
|
if (keys.items.length === 0) list2.delete(m.index);
|
|
@@ -13112,7 +13524,7 @@ function editConfig(text2, model, source) {
|
|
|
13112
13524
|
flowSeq(node.get("paths", true), true);
|
|
13113
13525
|
const made = node.get("externalMetadata", true);
|
|
13114
13526
|
if (isSeq4(made)) {
|
|
13115
|
-
for (const item of made.items) if (
|
|
13527
|
+
for (const item of made.items) if (isMap7(item)) flowSeq(item.get("keys", true), false);
|
|
13116
13528
|
}
|
|
13117
13529
|
const seq = doc.get("collections", true);
|
|
13118
13530
|
if (isSeq4(seq)) seq.add(node);
|
|
@@ -13147,16 +13559,18 @@ function buildResult(input) {
|
|
|
13147
13559
|
const moved = [];
|
|
13148
13560
|
const stayed = [];
|
|
13149
13561
|
const intents = orderedIntents(page);
|
|
13562
|
+
const fileOf = (m) => model.fileFor(m, page.absPath).file;
|
|
13150
13563
|
for (const [key, intent] of intents) {
|
|
13151
|
-
if (intent.kind === "in") moved.push({ key, to: "page", from: intent.manifest
|
|
13564
|
+
if (intent.kind === "in") moved.push({ key, to: "page", from: fileOf(intent.manifest), reason: "preferred" });
|
|
13152
13565
|
}
|
|
13153
13566
|
for (const [key, intent] of intents) {
|
|
13154
13567
|
if (intent.kind !== "out") continue;
|
|
13155
|
-
const
|
|
13568
|
+
const manifest = fileOf(intent.manifest);
|
|
13569
|
+
const line = dryRun ? void 0 : lines.get(lineId(page.label, manifest, key));
|
|
13156
13570
|
moved.push({
|
|
13157
13571
|
key,
|
|
13158
13572
|
to: "manifest",
|
|
13159
|
-
manifest
|
|
13573
|
+
manifest,
|
|
13160
13574
|
...line !== void 0 ? { line } : {},
|
|
13161
13575
|
reason: intent.reason
|
|
13162
13576
|
});
|
|
@@ -13201,7 +13615,7 @@ function buildResult(input) {
|
|
|
13201
13615
|
};
|
|
13202
13616
|
}
|
|
13203
13617
|
async function applyRelocation(ctx, plan, io = {}) {
|
|
13204
|
-
const write = io.write ?? ((path, text2) => writeFileAtomic(path, text2));
|
|
13618
|
+
const write = io.write ?? ((path, text2) => writeFileAtomic(path, text2, { createParents: true }));
|
|
13205
13619
|
const remove = io.remove ?? ((path) => unlink(path));
|
|
13206
13620
|
const label = (w) => w.kind === "config" ? configSource(w.path, ctx.cwd) : reported2(w.path, ctx.base);
|
|
13207
13621
|
for (const w of plan.writes) {
|
|
@@ -13374,7 +13788,7 @@ function relocationOffers(plan) {
|
|
|
13374
13788
|
}
|
|
13375
13789
|
|
|
13376
13790
|
// src/meta/commands/validate.ts
|
|
13377
|
-
import { resolve as
|
|
13791
|
+
import { resolve as resolve17, extname as extname4 } from "node:path";
|
|
13378
13792
|
|
|
13379
13793
|
// src/meta/core/checks.ts
|
|
13380
13794
|
var CHECK_KEYWORD = "check";
|
|
@@ -13512,8 +13926,8 @@ async function runChecks(checks, entries, ctx = {}) {
|
|
|
13512
13926
|
}
|
|
13513
13927
|
|
|
13514
13928
|
// src/meta/core/derive/provenance-place.ts
|
|
13515
|
-
import { isAbsolute as
|
|
13516
|
-
var toPosix4 = (p) => p.split(
|
|
13929
|
+
import { isAbsolute as isAbsolute9, relative as relative13, resolve as resolve16, sep as sep8 } from "node:path";
|
|
13930
|
+
var toPosix4 = (p) => p.split(sep8).join("/");
|
|
13517
13931
|
function provenanceManifests(collections, configDir, base) {
|
|
13518
13932
|
const out = [];
|
|
13519
13933
|
for (const collection of collections) {
|
|
@@ -13524,13 +13938,15 @@ function provenanceManifests(collections, configDir, base) {
|
|
|
13524
13938
|
`collection ${collection.name}: ${PROVENANCE_FIELD} cannot come from a URL manifest, because manni meta derive writes it.`
|
|
13525
13939
|
);
|
|
13526
13940
|
}
|
|
13527
|
-
const absPath =
|
|
13528
|
-
const
|
|
13941
|
+
const absPath = isAbsolute9(manifest.file) ? manifest.file : resolve16(configDir, manifest.file);
|
|
13942
|
+
const perPage = hasPagePlaceholder(manifest.file);
|
|
13529
13943
|
out.push({
|
|
13530
13944
|
collection: collection.name,
|
|
13531
13945
|
absPath,
|
|
13532
|
-
file:
|
|
13533
|
-
join: externalMetadataJoin(manifest)
|
|
13946
|
+
file: perPage ? manifest.file : reportedPath(absPath, base),
|
|
13947
|
+
join: externalMetadataJoin(manifest),
|
|
13948
|
+
perPage,
|
|
13949
|
+
written: manifest.file
|
|
13534
13950
|
});
|
|
13535
13951
|
}
|
|
13536
13952
|
}
|
|
@@ -13540,15 +13956,16 @@ function provenancePlace(label, data, manifests, collections, configDir, base) {
|
|
|
13540
13956
|
if (manifests.length === 0) return void 0;
|
|
13541
13957
|
const members = new Set(memberOf(collections, configDir, base, label));
|
|
13542
13958
|
const owning = manifests.filter((m) => members.has(m.collection));
|
|
13543
|
-
const [
|
|
13544
|
-
if (
|
|
13959
|
+
const [declared, second] = owning;
|
|
13960
|
+
if (declared === void 0) return void 0;
|
|
13545
13961
|
if (second !== void 0) {
|
|
13546
13962
|
throw new DocmetaError(
|
|
13547
|
-
`${label} is in collections ${
|
|
13963
|
+
`${label} is in collections ${declared.collection} and ${second.collection}, and both keep ${PROVENANCE_FIELD} in a manifest.`
|
|
13548
13964
|
);
|
|
13549
13965
|
}
|
|
13550
|
-
|
|
13551
|
-
|
|
13966
|
+
const manifest = declared.perPage ? ownManifest(declared, label, collections, configDir, base) : declared;
|
|
13967
|
+
if (manifest.join === PATH_JOIN2) {
|
|
13968
|
+
const entry = toPosix4(relative13(configDir, resolve16(base, label)));
|
|
13552
13969
|
return { manifest, absPath: manifest.absPath, entry, join: manifest.join };
|
|
13553
13970
|
}
|
|
13554
13971
|
const value = data[manifest.join];
|
|
@@ -13559,6 +13976,16 @@ function provenancePlace(label, data, manifests, collections, configDir, base) {
|
|
|
13559
13976
|
}
|
|
13560
13977
|
return { manifest, absPath: manifest.absPath, entry: String(value), join: manifest.join };
|
|
13561
13978
|
}
|
|
13979
|
+
function ownManifest(manifest, label, collections, configDir, base) {
|
|
13980
|
+
const resolved = pageManifestPath(manifest.written, configDir, resolve16(base, label));
|
|
13981
|
+
if ("outside" in resolved) {
|
|
13982
|
+
const declared = collections.find((c) => c.name === manifest.collection)?.externalMetadata.find((m) => m.file === manifest.written);
|
|
13983
|
+
throw new DocmetaError(
|
|
13984
|
+
outsideRefusal(declared ?? { file: manifest.written, keys: [] }, manifest.collection, resolved.pageRel)
|
|
13985
|
+
);
|
|
13986
|
+
}
|
|
13987
|
+
return { ...manifest, absPath: resolved.abs, file: reportedPath(resolved.abs, base) };
|
|
13988
|
+
}
|
|
13562
13989
|
function readerManifests(collections, configDir, base) {
|
|
13563
13990
|
const local = collections.map((c) => ({
|
|
13564
13991
|
...c,
|
|
@@ -13657,7 +14084,9 @@ async function runValidate(opts) {
|
|
|
13657
14084
|
const externalMetadata = await loadExternalMetadata(collections, {
|
|
13658
14085
|
configDir: configDir ?? cwd,
|
|
13659
14086
|
base,
|
|
13660
|
-
offline: opts.offline ?? config?.offline ?? false
|
|
14087
|
+
offline: opts.offline ?? config?.offline ?? false,
|
|
14088
|
+
// A `{page}` manifest (0058) is read for exactly the pages this run reads.
|
|
14089
|
+
pages: files.map((file) => resolve17(base, file))
|
|
13661
14090
|
});
|
|
13662
14091
|
const validator = new Validator(
|
|
13663
14092
|
schemaLoadOptions({
|
|
@@ -13688,7 +14117,7 @@ async function runValidate(opts) {
|
|
|
13688
14117
|
const owned = new Set(merged.collisions.map((c) => c.key));
|
|
13689
14118
|
const declaredMembers = declaredCollections === collections ? members : memberOf(declaredCollections, configDir ?? cwd, base, label);
|
|
13690
14119
|
const joins = new Set(
|
|
13691
|
-
declaredCollections.filter((c) => declaredMembers.includes(c.name)).flatMap((c) => c.externalMetadata.map(externalMetadataJoin)).filter((join11) => join11 !==
|
|
14120
|
+
declaredCollections.filter((c) => declaredMembers.includes(c.name)).flatMap((c) => c.externalMetadata.map(externalMetadataJoin)).filter((join11) => join11 !== PATH_JOIN2)
|
|
13692
14121
|
);
|
|
13693
14122
|
const findings = [];
|
|
13694
14123
|
for (const key of Object.keys(data)) {
|
|
@@ -13812,7 +14241,7 @@ async function runValidate(opts) {
|
|
|
13812
14241
|
const place = provenanceManifests2.length === 0 ? void 0 : readerPlace(label, extracted.data, provenanceManifests2, declaredCollections, configDir ?? cwd, base);
|
|
13813
14242
|
deriveInputs.push({
|
|
13814
14243
|
label,
|
|
13815
|
-
absPath:
|
|
14244
|
+
absPath: resolve17(base, label),
|
|
13816
14245
|
content,
|
|
13817
14246
|
extracted,
|
|
13818
14247
|
...place !== void 0 ? { provenanceManifest: place } : {}
|
|
@@ -13943,7 +14372,7 @@ async function runValidate(opts) {
|
|
|
13943
14372
|
await processOne(STDIN_LABEL, content, forcedExtractor.extensions[0] ?? "");
|
|
13944
14373
|
}
|
|
13945
14374
|
for (const file of files) {
|
|
13946
|
-
const content = await readFile9(
|
|
14375
|
+
const content = await readFile9(resolve17(base, file), "utf8");
|
|
13947
14376
|
await processOne(file, content, extname4(file));
|
|
13948
14377
|
}
|
|
13949
14378
|
if (unverified > 0) opts.onNotice?.(unverifiedWarning(unverified));
|
|
@@ -14089,7 +14518,7 @@ async function runValidate(opts) {
|
|
|
14089
14518
|
|
|
14090
14519
|
// src/meta/commands/get.ts
|
|
14091
14520
|
import { readFile as readFile10 } from "node:fs/promises";
|
|
14092
|
-
import { resolve as
|
|
14521
|
+
import { resolve as resolve18, extname as extname5 } from "node:path";
|
|
14093
14522
|
async function runGet(opts) {
|
|
14094
14523
|
const cwd = opts.cwd ?? process.cwd();
|
|
14095
14524
|
if (opts.fields.length === 0) {
|
|
@@ -14148,7 +14577,9 @@ async function runGet(opts) {
|
|
|
14148
14577
|
const externalMetadata = await loadExternalMetadata(collections, {
|
|
14149
14578
|
configDir: configDir ?? cwd,
|
|
14150
14579
|
base,
|
|
14151
|
-
offline: opts.offline ?? config?.offline ?? false
|
|
14580
|
+
offline: opts.offline ?? config?.offline ?? false,
|
|
14581
|
+
// A `{page}` manifest (0058) is read for exactly the pages this run reads.
|
|
14582
|
+
pages: files.map((file) => resolve18(base, file))
|
|
14152
14583
|
});
|
|
14153
14584
|
const commands = commandsOf(config?.derive) ?? {};
|
|
14154
14585
|
const deriving = opts.derived !== false;
|
|
@@ -14175,7 +14606,7 @@ async function runGet(opts) {
|
|
|
14175
14606
|
const place = provenanceManifests2.length === 0 ? void 0 : readerPlace(label, own2.data, provenanceManifests2, declaredCollections, configDir ?? cwd, base);
|
|
14176
14607
|
deriveInputs.push({
|
|
14177
14608
|
label,
|
|
14178
|
-
absPath:
|
|
14609
|
+
absPath: resolve18(base, label),
|
|
14179
14610
|
content,
|
|
14180
14611
|
extracted: own2,
|
|
14181
14612
|
...place !== void 0 ? { provenanceManifest: place } : {}
|
|
@@ -14217,7 +14648,7 @@ async function runGet(opts) {
|
|
|
14217
14648
|
readOne(STDIN_LABEL, opts.stdinContent ?? "", forced.extensions[0] ?? "");
|
|
14218
14649
|
}
|
|
14219
14650
|
for (const file of files) {
|
|
14220
|
-
const content = await readFile10(
|
|
14651
|
+
const content = await readFile10(resolve18(base, file), "utf8");
|
|
14221
14652
|
readOne(file, content, extname5(file));
|
|
14222
14653
|
}
|
|
14223
14654
|
if (deriving) {
|
|
@@ -14343,16 +14774,16 @@ function parseJsonPointer(pointer) {
|
|
|
14343
14774
|
|
|
14344
14775
|
// src/meta/commands/schemas.ts
|
|
14345
14776
|
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
|
|
14777
|
+
import { mkdir as mkdir3, readFile as readFile11 } from "node:fs/promises";
|
|
14778
|
+
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";
|
|
14779
|
+
import { parseDocument as parseDocument8, parse as parseYaml6, stringify as stringify3 } from "yaml";
|
|
14349
14780
|
function getSchemasInfo() {
|
|
14350
14781
|
return { builtins: listBuiltins(), formats: listFormats() };
|
|
14351
14782
|
}
|
|
14352
14783
|
var DEFAULT_VENDOR_DIR = "./schema";
|
|
14353
14784
|
var DEFAULT_CONFIG_NAME = "manni.config.yaml";
|
|
14354
14785
|
function posixRelative(from, to) {
|
|
14355
|
-
return
|
|
14786
|
+
return relative14(from, to).split(sep9).join("/");
|
|
14356
14787
|
}
|
|
14357
14788
|
function vendorFileName(url) {
|
|
14358
14789
|
let parsed2;
|
|
@@ -14417,7 +14848,7 @@ function renderConfig(existing, entries, section) {
|
|
|
14417
14848
|
if (existing === null) {
|
|
14418
14849
|
return stringify3({ [META_SECTION]: { schemas: entries } });
|
|
14419
14850
|
}
|
|
14420
|
-
const doc =
|
|
14851
|
+
const doc = parseDocument8(existing);
|
|
14421
14852
|
doc.setIn(section === void 0 ? ["schemas"] : [section, "schemas"], entries);
|
|
14422
14853
|
return doc.toString();
|
|
14423
14854
|
}
|
|
@@ -14438,13 +14869,13 @@ async function runVendorSchema(opts) {
|
|
|
14438
14869
|
);
|
|
14439
14870
|
}
|
|
14440
14871
|
const loaded = await loadConfig(opts.configPath, cwd);
|
|
14441
|
-
const configPath = loaded?.path ??
|
|
14872
|
+
const configPath = loaded?.path ?? resolve19(cwd, DEFAULT_CONFIG_NAME);
|
|
14442
14873
|
const configDir = loaded?.dir ?? cwd;
|
|
14443
|
-
const absDir =
|
|
14874
|
+
const absDir = resolve19(cwd, opts.dir ?? DEFAULT_VENDOR_DIR);
|
|
14444
14875
|
const absFile = join9(absDir, vendorFileName(url));
|
|
14445
14876
|
await assertNotIgnored(absFile, absDir, cwd, opts.onNotice);
|
|
14446
14877
|
const fromConfig = posixRelative(configDir, absFile);
|
|
14447
|
-
const ref =
|
|
14878
|
+
const ref = isAbsolute10(fromConfig) || fromConfig === "" ? absFile : fromConfig.startsWith(".") ? fromConfig : `./${fromConfig}`;
|
|
14448
14879
|
const { bytes } = await fetchSchemaBytes(url, {
|
|
14449
14880
|
...opts.timeoutMs !== void 0 ? { timeoutMs: opts.timeoutMs } : {},
|
|
14450
14881
|
...opts.maxBytes !== void 0 ? { maxBytes: opts.maxBytes } : {}
|
|
@@ -14467,7 +14898,7 @@ async function runVendorSchema(opts) {
|
|
|
14467
14898
|
);
|
|
14468
14899
|
}
|
|
14469
14900
|
}
|
|
14470
|
-
await
|
|
14901
|
+
await mkdir3(absDir, { recursive: true });
|
|
14471
14902
|
await writeFileAtomic(absFile, bytes);
|
|
14472
14903
|
const existing = loaded ? await readFile11(configPath, "utf8") : null;
|
|
14473
14904
|
const section = loaded ? loaded.section : META_SECTION;
|
|
@@ -14598,11 +15029,6 @@ async function runInferSchema(opts) {
|
|
|
14598
15029
|
});
|
|
14599
15030
|
const joinKey = lazyKey(configFile, void 0);
|
|
14600
15031
|
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
15032
|
if (inputs.length === 0) {
|
|
14607
15033
|
throw new DocmetaError(
|
|
14608
15034
|
"No files to scan. Pass paths/globs, or declare a collection under `collections:` in manni.config.yaml."
|
|
@@ -14621,7 +15047,7 @@ async function runInferSchema(opts) {
|
|
|
14621
15047
|
}
|
|
14622
15048
|
let absOut;
|
|
14623
15049
|
if (opts.out !== void 0) {
|
|
14624
|
-
absOut =
|
|
15050
|
+
absOut = resolve19(cwd, opts.out);
|
|
14625
15051
|
await assertNotIgnored(
|
|
14626
15052
|
absOut,
|
|
14627
15053
|
dirname10(absOut),
|
|
@@ -14663,8 +15089,14 @@ async function runInferSchema(opts) {
|
|
|
14663
15089
|
gitignoreSkipped,
|
|
14664
15090
|
action: "scanned"
|
|
14665
15091
|
});
|
|
15092
|
+
const externalMetadata = await loadExternalMetadata(collections, {
|
|
15093
|
+
configDir: configDir ?? cwd,
|
|
15094
|
+
base,
|
|
15095
|
+
offline: opts.offline ?? config?.offline ?? false,
|
|
15096
|
+
pages: files.map((file) => resolve19(base, file))
|
|
15097
|
+
});
|
|
14666
15098
|
const stats = /* @__PURE__ */ new Map();
|
|
14667
|
-
const
|
|
15099
|
+
const unreadable2 = [];
|
|
14668
15100
|
let filesScanned = 0;
|
|
14669
15101
|
let filesWithoutMetadata = 0;
|
|
14670
15102
|
const scanOne = (label, content, extension) => {
|
|
@@ -14689,7 +15121,7 @@ async function runInferSchema(opts) {
|
|
|
14689
15121
|
{ encryptionKey: joinKey }
|
|
14690
15122
|
).extracted;
|
|
14691
15123
|
} catch (err) {
|
|
14692
|
-
|
|
15124
|
+
unreadable2.push({
|
|
14693
15125
|
file: label,
|
|
14694
15126
|
message: err instanceof Error ? err.message : String(err)
|
|
14695
15127
|
});
|
|
@@ -14709,10 +15141,10 @@ async function runInferSchema(opts) {
|
|
|
14709
15141
|
scanOne(STDIN_LABEL, opts.stdinContent ?? "", forced.extensions[0] ?? "");
|
|
14710
15142
|
}
|
|
14711
15143
|
for (const file of files) {
|
|
14712
|
-
const content = await readFile11(
|
|
15144
|
+
const content = await readFile11(resolve19(base, file), "utf8");
|
|
14713
15145
|
scanOne(file, content, extname6(file));
|
|
14714
15146
|
}
|
|
14715
|
-
for (const u of
|
|
15147
|
+
for (const u of unreadable2) {
|
|
14716
15148
|
opts.onNotice?.(`could not read metadata from "${u.file}": ${u.message}`);
|
|
14717
15149
|
}
|
|
14718
15150
|
const all = [...stats.entries()].map(([key, stat7]) => {
|
|
@@ -14751,14 +15183,14 @@ async function runInferSchema(opts) {
|
|
|
14751
15183
|
};
|
|
14752
15184
|
const keys = kept.map(({ sawEmptyString: _drop, ...rest }) => rest);
|
|
14753
15185
|
if (absOut !== void 0) {
|
|
14754
|
-
await
|
|
15186
|
+
await mkdir3(dirname10(absOut), { recursive: true });
|
|
14755
15187
|
await writeFileAtomic(absOut, `${JSON.stringify(draft, null, 2)}
|
|
14756
15188
|
`);
|
|
14757
15189
|
}
|
|
14758
15190
|
return {
|
|
14759
15191
|
filesScanned,
|
|
14760
15192
|
filesWithoutMetadata,
|
|
14761
|
-
unreadable,
|
|
15193
|
+
unreadable: unreadable2,
|
|
14762
15194
|
keys,
|
|
14763
15195
|
hiddenByMinCoverage: all.length - kept.length,
|
|
14764
15196
|
draft,
|
|
@@ -14770,8 +15202,8 @@ async function runInferSchema(opts) {
|
|
|
14770
15202
|
// src/meta/commands/query.ts
|
|
14771
15203
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
14772
15204
|
import { existsSync as existsSync5 } from "node:fs";
|
|
14773
|
-
import { mkdir as
|
|
14774
|
-
import { dirname as dirname11, isAbsolute as
|
|
15205
|
+
import { mkdir as mkdir4, open as open2, readFile as readFile12, rename as rename3, rm as rm3 } from "node:fs/promises";
|
|
15206
|
+
import { dirname as dirname11, isAbsolute as isAbsolute11, resolve as resolve20, extname as extname7, sep as sep10 } from "node:path";
|
|
14775
15207
|
|
|
14776
15208
|
// src/shared/prompt.ts
|
|
14777
15209
|
import { createInterface } from "node:readline";
|
|
@@ -14829,10 +15261,10 @@ async function ensureEncryptionKey(opts) {
|
|
|
14829
15261
|
}
|
|
14830
15262
|
|
|
14831
15263
|
// src/meta/commands/query.ts
|
|
14832
|
-
import { parseDocument as
|
|
15264
|
+
import { parseDocument as parseDocument10, isMap as isMap9, isSeq as isSeq5, isScalar as isScalar7 } from "yaml";
|
|
14833
15265
|
|
|
14834
15266
|
// src/meta/core/location-writes.ts
|
|
14835
|
-
import { LineCounter as
|
|
15267
|
+
import { LineCounter as LineCounter6, isMap as isMap8, isNode as isNode5, isScalar as isScalar6, parseDocument as parseDocument9 } from "yaml";
|
|
14836
15268
|
var dedupe3 = (xs) => [...new Set(xs)];
|
|
14837
15269
|
var pages = (n) => `${String(n)} page${n === 1 ? "" : "s"}`;
|
|
14838
15270
|
async function offerExternalHomes(ctx, writes, hooks) {
|
|
@@ -14915,17 +15347,17 @@ function externalWriteWarning(line) {
|
|
|
14915
15347
|
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
15348
|
}
|
|
14917
15349
|
function manifestKeyLine(text2, entry, key, join11) {
|
|
14918
|
-
const norm = (e) => join11 ===
|
|
14919
|
-
const lc = new
|
|
14920
|
-
const doc =
|
|
15350
|
+
const norm = (e) => join11 === PATH_JOIN2 ? e.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/+/g, "/") : e;
|
|
15351
|
+
const lc = new LineCounter6();
|
|
15352
|
+
const doc = parseDocument9(text2, { lineCounter: lc, uniqueKeys: false });
|
|
14921
15353
|
const root = doc.contents;
|
|
14922
|
-
if (!
|
|
15354
|
+
if (!isMap8(root)) return void 0;
|
|
14923
15355
|
for (const pair of root.items) {
|
|
14924
|
-
const spelled =
|
|
14925
|
-
if (norm(spelled) !== norm(entry) || !
|
|
15356
|
+
const spelled = isScalar6(pair.key) ? String(pair.key.value) : String(pair.key);
|
|
15357
|
+
if (norm(spelled) !== norm(entry) || !isMap8(pair.value)) continue;
|
|
14926
15358
|
for (const kv of pair.value.items) {
|
|
14927
|
-
const name2 =
|
|
14928
|
-
const range =
|
|
15359
|
+
const name2 = isScalar6(kv.key) ? String(kv.key.value) : String(kv.key);
|
|
15360
|
+
const range = isNode5(kv.key) ? kv.key.range : void 0;
|
|
14929
15361
|
if (name2 === key && range) return lc.linePos(range[0]).line;
|
|
14930
15362
|
}
|
|
14931
15363
|
}
|
|
@@ -15028,7 +15460,9 @@ async function runQuery(opts) {
|
|
|
15028
15460
|
const externalMetadata = await loadExternalMetadata(collections, {
|
|
15029
15461
|
configDir: configDir ?? cwd,
|
|
15030
15462
|
base,
|
|
15031
|
-
offline: opts.offline ?? config?.offline ?? false
|
|
15463
|
+
offline: opts.offline ?? config?.offline ?? false,
|
|
15464
|
+
// A `{page}` manifest (0058) is read for exactly the pages this run reads.
|
|
15465
|
+
pages: files.map((file) => resolve20(base, file))
|
|
15032
15466
|
});
|
|
15033
15467
|
const configuredKey = lazyKey(configFile, opts.env);
|
|
15034
15468
|
let ensuredKey;
|
|
@@ -15110,10 +15544,10 @@ async function runQuery(opts) {
|
|
|
15110
15544
|
readOne(STDIN_LABEL, opts.stdinContent ?? "", ext);
|
|
15111
15545
|
}
|
|
15112
15546
|
for (const file of files) {
|
|
15113
|
-
const content = await readFile12(
|
|
15547
|
+
const content = await readFile12(resolve20(base, file), "utf8");
|
|
15114
15548
|
readOne(file, content, extname7(file));
|
|
15115
15549
|
}
|
|
15116
|
-
const db = opts.db === void 0 ? void 0 : { resolved:
|
|
15550
|
+
const db = opts.db === void 0 ? void 0 : { resolved: resolve20(cwd, opts.db), display: opts.db };
|
|
15117
15551
|
const run2 = await runSql(sql, entries, {
|
|
15118
15552
|
target: db,
|
|
15119
15553
|
params: boundParams,
|
|
@@ -15210,7 +15644,7 @@ async function runSql(sql, entries, ctx) {
|
|
|
15210
15644
|
);
|
|
15211
15645
|
const { DatabaseSync } = await loadSqlite();
|
|
15212
15646
|
if (target) {
|
|
15213
|
-
await
|
|
15647
|
+
await mkdir4(dirname11(target.resolved), { recursive: true });
|
|
15214
15648
|
await prepareDbTarget(target.resolved, target.display);
|
|
15215
15649
|
}
|
|
15216
15650
|
let db;
|
|
@@ -15254,7 +15688,7 @@ async function runSql(sql, entries, ctx) {
|
|
|
15254
15688
|
const place = manifests.length === 0 ? void 0 : readerPlace(e.label, e.own.data, manifests, ctx.declaredCollections, manifestRoot, ctx.base);
|
|
15255
15689
|
return {
|
|
15256
15690
|
label: e.label,
|
|
15257
|
-
absPath:
|
|
15691
|
+
absPath: resolve20(ctx.base, e.label),
|
|
15258
15692
|
content: e.content,
|
|
15259
15693
|
extracted: e.own,
|
|
15260
15694
|
...place !== void 0 ? { provenanceManifest: place } : {}
|
|
@@ -15719,20 +16153,20 @@ function displayPath(ctx, abs) {
|
|
|
15719
16153
|
}
|
|
15720
16154
|
function assertSchemaWriteWithin(ctx, abs) {
|
|
15721
16155
|
const within = posixRelative(ctx.trustRoot.dir, abs);
|
|
15722
|
-
if (within !== "" && !within.startsWith("..") && !
|
|
16156
|
+
if (within !== "" && !within.startsWith("..") && !isAbsolute11(within)) return;
|
|
15723
16157
|
throw new DocmetaError(
|
|
15724
16158
|
`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
16159
|
);
|
|
15726
16160
|
}
|
|
15727
16161
|
function foldPath(p) {
|
|
15728
|
-
const abs =
|
|
16162
|
+
const abs = resolve20(p);
|
|
15729
16163
|
return process.platform === "win32" ? abs.toLowerCase() : abs;
|
|
15730
16164
|
}
|
|
15731
16165
|
function filePinsByPath(ctx) {
|
|
15732
16166
|
const byPath = /* @__PURE__ */ new Map();
|
|
15733
16167
|
for (const [ref, pin] of collectSchemaPins(ctx.config)) {
|
|
15734
16168
|
if (classifyRef(ref).kind !== "file") continue;
|
|
15735
|
-
byPath.set(foldPath(
|
|
16169
|
+
byPath.set(foldPath(resolve20(ctx.cwd, ref)), pin);
|
|
15736
16170
|
}
|
|
15737
16171
|
return byPath;
|
|
15738
16172
|
}
|
|
@@ -15760,7 +16194,7 @@ async function loadSetMembers(refs, ctx) {
|
|
|
15760
16194
|
});
|
|
15761
16195
|
continue;
|
|
15762
16196
|
}
|
|
15763
|
-
const abs =
|
|
16197
|
+
const abs = resolve20(ctx.cwd, ref);
|
|
15764
16198
|
const canon = foldPath(abs);
|
|
15765
16199
|
if (seenFiles.has(canon)) continue;
|
|
15766
16200
|
seenFiles.add(canon);
|
|
@@ -15965,7 +16399,7 @@ async function planSchemaMutation(ops, entries, ctx) {
|
|
|
15965
16399
|
const [, name2, ver] = target.builtinId.split(":");
|
|
15966
16400
|
const safe = (s) => s.replace(/[^A-Za-z0-9._-]/g, "-");
|
|
15967
16401
|
const forkName = `${safe(name2 ?? "schema")}-${safe(ver ?? "0")}.local.json`;
|
|
15968
|
-
schemaAbs =
|
|
16402
|
+
schemaAbs = resolve20(ctx.configDir ?? ctx.cwd, "schemas", forkName);
|
|
15969
16403
|
assertSchemaWriteWithin(ctx, schemaAbs);
|
|
15970
16404
|
if (existsSync5(schemaAbs)) {
|
|
15971
16405
|
throw new DocmetaError(
|
|
@@ -16122,17 +16556,17 @@ async function planConfigEdit(ctx, edit, runRefs) {
|
|
|
16122
16556
|
return { changes: [], repointed: false };
|
|
16123
16557
|
}
|
|
16124
16558
|
const text2 = await readFile12(configPath, "utf8");
|
|
16125
|
-
const doc =
|
|
16559
|
+
const doc = parseDocument10(stripBom2(text2));
|
|
16126
16560
|
const display = displayPath(ctx, configPath);
|
|
16127
16561
|
const rawRefOf = (item) => {
|
|
16128
|
-
if (
|
|
16129
|
-
if (
|
|
16562
|
+
if (isScalar7(item) && typeof item.value === "string") return item.value;
|
|
16563
|
+
if (isMap9(item)) {
|
|
16130
16564
|
const ref = item.get("ref");
|
|
16131
16565
|
if (typeof ref === "string") return ref;
|
|
16132
16566
|
}
|
|
16133
16567
|
return void 0;
|
|
16134
16568
|
};
|
|
16135
|
-
const rebaseRaw = (raw) => classifyRef(raw).kind === "file" && !
|
|
16569
|
+
const rebaseRaw = (raw) => classifyRef(raw).kind === "file" && !isAbsolute11(raw) ? resolve20(configDir, raw) : raw;
|
|
16136
16570
|
const wantSet = runRefs.map(rebaseRaw).sort().join("\n");
|
|
16137
16571
|
const seqResolvesToRunSet = (node) => {
|
|
16138
16572
|
if (!isSeq5(node)) return false;
|
|
@@ -16148,10 +16582,10 @@ async function planConfigEdit(ctx, edit, runRefs) {
|
|
|
16148
16582
|
for (const item of node.items) {
|
|
16149
16583
|
const raw = rawRefOf(item);
|
|
16150
16584
|
if (raw === void 0 || !wants(raw)) continue;
|
|
16151
|
-
if (
|
|
16585
|
+
if (isScalar7(item)) {
|
|
16152
16586
|
item.value = spec.newRef;
|
|
16153
16587
|
n += 1;
|
|
16154
|
-
} else if (
|
|
16588
|
+
} else if (isMap9(item)) {
|
|
16155
16589
|
item.set("ref", spec.newRef);
|
|
16156
16590
|
n += 1;
|
|
16157
16591
|
}
|
|
@@ -16159,13 +16593,13 @@ async function planConfigEdit(ctx, edit, runRefs) {
|
|
|
16159
16593
|
return n;
|
|
16160
16594
|
};
|
|
16161
16595
|
const root = ctx.configSection === void 0 ? doc : doc.get(ctx.configSection, true);
|
|
16162
|
-
const keyOf2 = (key) => root === doc ? doc.get(key, true) :
|
|
16596
|
+
const keyOf2 = (key) => root === doc ? doc.get(key, true) : isMap9(root) ? root.get(key, true) : void 0;
|
|
16163
16597
|
const topSeq = keyOf2("schemas");
|
|
16164
16598
|
let repointCount = repoint(topSeq);
|
|
16165
16599
|
const overrides = keyOf2("overrides");
|
|
16166
16600
|
if (isSeq5(overrides)) {
|
|
16167
16601
|
for (const entry of overrides.items) {
|
|
16168
|
-
if (
|
|
16602
|
+
if (isMap9(entry)) repointCount += repoint(entry.get("schemas", true));
|
|
16169
16603
|
}
|
|
16170
16604
|
}
|
|
16171
16605
|
const repointed = repointCount > 0;
|
|
@@ -16174,10 +16608,10 @@ async function planConfigEdit(ctx, edit, runRefs) {
|
|
|
16174
16608
|
if (edit.integrity && isSeq5(topSeq)) {
|
|
16175
16609
|
const wantPath = foldPath(edit.integrity.path);
|
|
16176
16610
|
for (const item of topSeq.items) {
|
|
16177
|
-
if (!
|
|
16611
|
+
if (!isMap9(item)) continue;
|
|
16178
16612
|
const raw = rawRefOf(item);
|
|
16179
16613
|
if (raw === void 0 || classifyRef(raw).kind !== "file") continue;
|
|
16180
|
-
const abs =
|
|
16614
|
+
const abs = isAbsolute11(raw) ? raw : resolve20(configDir, raw);
|
|
16181
16615
|
if (foldPath(abs) !== wantPath) continue;
|
|
16182
16616
|
pinFrom = item.get("integrity");
|
|
16183
16617
|
item.set("integrity", edit.integrity.value);
|
|
@@ -16406,7 +16840,7 @@ function buildChanges(diff, entries, sentinel, ctx, renameHints = [], booleanAdd
|
|
|
16406
16840
|
`"${file}": no writable format for that extension.`
|
|
16407
16841
|
);
|
|
16408
16842
|
}
|
|
16409
|
-
if (existsSync5(
|
|
16843
|
+
if (existsSync5(resolve20(ctx.base, file))) {
|
|
16410
16844
|
throw new DocmetaError(
|
|
16411
16845
|
`"${file}" already exists; INSERT creates new files only.`
|
|
16412
16846
|
);
|
|
@@ -16425,7 +16859,7 @@ function buildChanges(diff, entries, sentinel, ctx, renameHints = [], booleanAdd
|
|
|
16425
16859
|
`"${from}" -> "${to}": a rename may not change the extension.`
|
|
16426
16860
|
);
|
|
16427
16861
|
}
|
|
16428
|
-
if (existsSync5(
|
|
16862
|
+
if (existsSync5(resolve20(ctx.base, to))) {
|
|
16429
16863
|
throw new DocmetaError(
|
|
16430
16864
|
`"${to}" already exists; the rename would overwrite it.`
|
|
16431
16865
|
);
|
|
@@ -16454,13 +16888,13 @@ function validateNewPath(p, base) {
|
|
|
16454
16888
|
const refuse = (why) => {
|
|
16455
16889
|
throw new DocmetaError(`"${p}" is not a usable path: ${why}.`);
|
|
16456
16890
|
};
|
|
16457
|
-
if (
|
|
16891
|
+
if (isAbsolute11(p)) refuse("it is absolute");
|
|
16458
16892
|
if (p.split(/[\\/]/).some((segment) => segment === "..")) {
|
|
16459
16893
|
refuse("it traverses upward");
|
|
16460
16894
|
}
|
|
16461
|
-
const abs =
|
|
16462
|
-
if (abs ===
|
|
16463
|
-
if (!abs.startsWith(
|
|
16895
|
+
const abs = resolve20(base, p);
|
|
16896
|
+
if (abs === resolve20(base)) refuse("it points at the corpus root, not a file");
|
|
16897
|
+
if (!abs.startsWith(resolve20(base) + sep10)) refuse("it escapes the corpus");
|
|
16464
16898
|
}
|
|
16465
16899
|
function refuseJoinFieldChanges(changes, entries, ctx) {
|
|
16466
16900
|
const index = ctx.externalMetadata;
|
|
@@ -16531,6 +16965,12 @@ function postChangeData(changes, entries) {
|
|
|
16531
16965
|
}
|
|
16532
16966
|
return out;
|
|
16533
16967
|
}
|
|
16968
|
+
function runPages(changes, entries, base) {
|
|
16969
|
+
const labels = new Set(entries.map((e) => e.label));
|
|
16970
|
+
for (const c of changes) if (!("schema" in c) && !("config" in c)) labels.add(c.file);
|
|
16971
|
+
labels.delete(STDIN_LABEL);
|
|
16972
|
+
return [...labels].map((label) => resolve20(base, label));
|
|
16973
|
+
}
|
|
16534
16974
|
async function planManifestEdits(changes, entries, ctx, renameHints) {
|
|
16535
16975
|
for (const c of changes) {
|
|
16536
16976
|
delete c.manifest;
|
|
@@ -16579,12 +17019,18 @@ async function planManifestEdits(changes, entries, ctx, renameHints) {
|
|
|
16579
17019
|
let write = texts.get(home.absPath);
|
|
16580
17020
|
if (write === void 0) {
|
|
16581
17021
|
let text2;
|
|
17022
|
+
let expected;
|
|
16582
17023
|
try {
|
|
16583
17024
|
text2 = await readFile12(home.absPath, "utf8");
|
|
17025
|
+
expected = text2;
|
|
16584
17026
|
} catch (err) {
|
|
16585
|
-
|
|
17027
|
+
if (!home.perPage || !isMissing(err)) {
|
|
17028
|
+
throw new DocmetaError(`Manifest ${home.file} could not be read: ${errorMessage(err)}`);
|
|
17029
|
+
}
|
|
17030
|
+
text2 = "";
|
|
17031
|
+
expected = null;
|
|
16586
17032
|
}
|
|
16587
|
-
write = { path: home.absPath, display: home.file, text: text2, expected
|
|
17033
|
+
write = { path: home.absPath, display: home.file, text: text2, expected };
|
|
16588
17034
|
texts.set(home.absPath, write);
|
|
16589
17035
|
}
|
|
16590
17036
|
write.text = change(write.text);
|
|
@@ -16607,13 +17053,13 @@ async function planManifestEdits(changes, entries, ctx, renameHints) {
|
|
|
16607
17053
|
...col,
|
|
16608
17054
|
externalMetadata: col.externalMetadata.filter((m) => classifyRef(m.file).kind !== "url")
|
|
16609
17055
|
})),
|
|
16610
|
-
{ configDir: ctx.configDir ?? ctx.cwd, base: ctx.base }
|
|
17056
|
+
{ configDir: ctx.configDir ?? ctx.cwd, base: ctx.base, pages: runPages(changes, entries, ctx.base) }
|
|
16611
17057
|
);
|
|
16612
17058
|
const index = await leftOut;
|
|
16613
17059
|
if (index === null) return void 0;
|
|
16614
|
-
const abs =
|
|
17060
|
+
const abs = resolve20(ctx.base, file);
|
|
16615
17061
|
const named = index.entries.find(
|
|
16616
|
-
(e) => e.join ===
|
|
17062
|
+
(e) => e.join === PATH_JOIN2 && e.abs === abs && excluded.includes(e.collection)
|
|
16617
17063
|
);
|
|
16618
17064
|
if (named !== void 0) return named;
|
|
16619
17065
|
if (!joins || own2 === void 0) return void 0;
|
|
@@ -16658,7 +17104,7 @@ async function planManifestEdits(changes, entries, ctx, renameHints) {
|
|
|
16658
17104
|
continue;
|
|
16659
17105
|
}
|
|
16660
17106
|
if ("renamed" in c) {
|
|
16661
|
-
const supplied = ctx.externalMetadata?.byPath.get(
|
|
17107
|
+
const supplied = ctx.externalMetadata?.byPath.get(resolve20(ctx.base, c.file));
|
|
16662
17108
|
const seen = /* @__PURE__ */ new Set();
|
|
16663
17109
|
for (const [key, sv] of supplied ?? []) {
|
|
16664
17110
|
if (seen.has(sv.file) || !ctx.memberships(c.file).includes(sv.collection)) continue;
|
|
@@ -16669,7 +17115,12 @@ async function planManifestEdits(changes, entries, ctx, renameHints) {
|
|
|
16669
17115
|
`"${c.file}": manifest ${home.file} names it, which is fetched and cannot be written; rename the entry in that repository.`
|
|
16670
17116
|
);
|
|
16671
17117
|
}
|
|
16672
|
-
if (home.kind
|
|
17118
|
+
if (home.kind === "manifest" && home.perPage) {
|
|
17119
|
+
throw new DocmetaError(
|
|
17120
|
+
`${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.`
|
|
17121
|
+
);
|
|
17122
|
+
}
|
|
17123
|
+
if (home.kind !== "manifest" || home.join !== PATH_JOIN2 || home.entry === void 0) continue;
|
|
16673
17124
|
const moved = await keyHome(loc, c.renamed, own2, key);
|
|
16674
17125
|
if (moved.kind !== "manifest" || moved.absPath !== home.absPath || moved.entry === void 0) {
|
|
16675
17126
|
throw new DocmetaError(
|
|
@@ -16733,7 +17184,7 @@ async function planManifestEdits(changes, entries, ctx, renameHints) {
|
|
|
16733
17184
|
}
|
|
16734
17185
|
pageRoutes.set(c, ops);
|
|
16735
17186
|
}
|
|
16736
|
-
return [...texts.values()].filter((w) => w.text !== w.expected);
|
|
17187
|
+
return [...texts.values()].filter((w) => w.text !== (w.expected ?? ""));
|
|
16737
17188
|
}
|
|
16738
17189
|
async function unhomedWrites(changes, entries, ctx) {
|
|
16739
17190
|
const written = /* @__PURE__ */ new Map();
|
|
@@ -16765,7 +17216,7 @@ async function unhomedWrites(changes, entries, ctx) {
|
|
|
16765
17216
|
const prefs = await validator.locationPreferences(data, refs);
|
|
16766
17217
|
const joins = new Set(
|
|
16767
17218
|
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 !==
|
|
17219
|
+
(name2) => (loc.declaredCollections.find((col) => col.name === name2)?.externalMetadata ?? []).map((m) => externalMetadataJoin(m)).filter((j) => j !== PATH_JOIN2)
|
|
16769
17220
|
)
|
|
16770
17221
|
);
|
|
16771
17222
|
for (const key of new Set(w.keys)) {
|
|
@@ -16816,7 +17267,8 @@ async function offerRelocation(changes, entries, ctx) {
|
|
|
16816
17267
|
ctx.externalMetadata = await loadExternalMetadata(loc.collections, {
|
|
16817
17268
|
configDir: loc.configDir ?? ctx.cwd,
|
|
16818
17269
|
base: ctx.base,
|
|
16819
|
-
offline: ctx.location.offline
|
|
17270
|
+
offline: ctx.location.offline,
|
|
17271
|
+
pages: runPages(changes, entries, ctx.base)
|
|
16820
17272
|
});
|
|
16821
17273
|
ctx.memberships = (label) => memberOf(loc.collections, loc.configDir ?? ctx.cwd, ctx.base, label);
|
|
16822
17274
|
unhomed = await unhomedWrites(changes, entries, ctx);
|
|
@@ -16960,14 +17412,14 @@ async function applyChanges(changes, entries, ctx, schemaPlan, manifestWrites =
|
|
|
16960
17412
|
const pendingWrites = [];
|
|
16961
17413
|
const pendingRenames = [];
|
|
16962
17414
|
for (const [label, ops] of grouped) {
|
|
16963
|
-
const path =
|
|
17415
|
+
const path = resolve20(ctx.base, label);
|
|
16964
17416
|
if (ops.renamedTo !== void 0) {
|
|
16965
17417
|
if (!existsSync5(path)) {
|
|
16966
17418
|
throw new DocmetaError(
|
|
16967
17419
|
`"${label}" is gone from disk since it was read; re-run the query.`
|
|
16968
17420
|
);
|
|
16969
17421
|
}
|
|
16970
|
-
const toDisk =
|
|
17422
|
+
const toDisk = resolve20(ctx.base, ops.renamedTo);
|
|
16971
17423
|
if (existsSync5(toDisk)) {
|
|
16972
17424
|
throw new DocmetaError(
|
|
16973
17425
|
`"${ops.renamedTo}" appeared on disk since the plan; re-run the query.`
|
|
@@ -17092,7 +17544,7 @@ async function applyChanges(changes, entries, ctx, schemaPlan, manifestWrites =
|
|
|
17092
17544
|
try {
|
|
17093
17545
|
now = await readFile12(m.path, "utf8");
|
|
17094
17546
|
} catch {
|
|
17095
|
-
now =
|
|
17547
|
+
now = null;
|
|
17096
17548
|
}
|
|
17097
17549
|
if (now !== m.expected) {
|
|
17098
17550
|
throw new DocmetaError(
|
|
@@ -17106,7 +17558,10 @@ async function applyChanges(changes, entries, ctx, schemaPlan, manifestWrites =
|
|
|
17106
17558
|
for (const p of pendingWrites) {
|
|
17107
17559
|
if (p.ensureDir) dirs.add(dirname11(p.path));
|
|
17108
17560
|
}
|
|
17109
|
-
for (const
|
|
17561
|
+
for (const m of manifestWrites) {
|
|
17562
|
+
if (m.expected === null) dirs.add(dirname11(m.path));
|
|
17563
|
+
}
|
|
17564
|
+
for (const d of dirs) await mkdir4(d, { recursive: true });
|
|
17110
17565
|
const writeSchema = async () => {
|
|
17111
17566
|
for (const w of schemaWrites) await writeFileAtomic(w.path, w.content);
|
|
17112
17567
|
};
|
|
@@ -17221,7 +17676,7 @@ function skipExpression(sql, from) {
|
|
|
17221
17676
|
|
|
17222
17677
|
// src/meta/commands/fill.ts
|
|
17223
17678
|
import { readFile as readFile14 } from "node:fs/promises";
|
|
17224
|
-
import { resolve as
|
|
17679
|
+
import { resolve as resolve21, extname as extname8, join as join10 } from "node:path";
|
|
17225
17680
|
import {
|
|
17226
17681
|
completeValidatedJSON,
|
|
17227
17682
|
makeProvider,
|
|
@@ -17237,68 +17692,6 @@ import {
|
|
|
17237
17692
|
|
|
17238
17693
|
// src/meta/core/manifest-writes.ts
|
|
17239
17694
|
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
17695
|
var manifestCodec = {
|
|
17303
17696
|
apply(text2, op) {
|
|
17304
17697
|
const where = { entry: op.entry, key: op.key, join: op.join, file: op.file };
|
|
@@ -17311,11 +17704,12 @@ var manifestCodec = {
|
|
|
17311
17704
|
function applyManifestOp(text2, op) {
|
|
17312
17705
|
return manifestCodec.apply(text2, op);
|
|
17313
17706
|
}
|
|
17314
|
-
async function holdManifestFile(path, file) {
|
|
17707
|
+
async function holdManifestFile(path, file, perPage = false) {
|
|
17315
17708
|
let before;
|
|
17316
17709
|
try {
|
|
17317
17710
|
before = await readFile13(path, "utf8");
|
|
17318
17711
|
} catch (err) {
|
|
17712
|
+
if (perPage && isMissing(err)) return heldManifest(path, file, "", true);
|
|
17319
17713
|
throw new DocmetaError(`Manifest ${file} could not be read: ${errorMessage(err)}`);
|
|
17320
17714
|
}
|
|
17321
17715
|
return heldManifest(path, file, before);
|
|
@@ -17328,7 +17722,8 @@ async function settleManifest(held, io = {}) {
|
|
|
17328
17722
|
if (held.text === held.before) return false;
|
|
17329
17723
|
await settle(held, {
|
|
17330
17724
|
codec: manifestCodec,
|
|
17331
|
-
|
|
17725
|
+
// A per-page manifest (proposal 0058) may be the first file in its directory.
|
|
17726
|
+
write: io.write ?? ((at2, text2) => writeFileAtomic(at2, text2, { createParents: true })),
|
|
17332
17727
|
read: io.read ?? ((at2) => readFile13(at2, "utf8")),
|
|
17333
17728
|
toError: (message) => new DocmetaError(message)
|
|
17334
17729
|
});
|
|
@@ -17612,7 +18007,9 @@ async function runFill(opts) {
|
|
|
17612
18007
|
const loadManifests = () => loadExternalMetadata(mergedCollections(), {
|
|
17613
18008
|
configDir: configDir ?? cwd,
|
|
17614
18009
|
base,
|
|
17615
|
-
offline: opts.offline ?? config?.offline ?? false
|
|
18010
|
+
offline: opts.offline ?? config?.offline ?? false,
|
|
18011
|
+
// A `{page}` manifest (0058) is read for exactly the pages this run fills.
|
|
18012
|
+
pages: files.map((file) => resolve21(base, file))
|
|
17616
18013
|
});
|
|
17617
18014
|
const mergeMembersFor = (label) => memberOf(runConfig.declaredCollections, configDir ?? cwd, base, label);
|
|
17618
18015
|
let externalMetadata = await loadManifests();
|
|
@@ -17649,7 +18046,7 @@ async function runFill(opts) {
|
|
|
17649
18046
|
};
|
|
17650
18047
|
const restorePage = async (label, before) => {
|
|
17651
18048
|
try {
|
|
17652
|
-
await writeFileAtomic(
|
|
18049
|
+
await writeFileAtomic(resolve21(base, label), before);
|
|
17653
18050
|
return `${label} was restored.`;
|
|
17654
18051
|
} catch (err) {
|
|
17655
18052
|
return `${label} could not be restored: ${errorMessage(err)}. Restore it from version control.`;
|
|
@@ -17658,7 +18055,7 @@ async function runFill(opts) {
|
|
|
17658
18055
|
const holdManifest = (home) => {
|
|
17659
18056
|
let held = holding.get(home.absPath);
|
|
17660
18057
|
if (held === void 0) {
|
|
17661
|
-
held = holdManifestFile(home.absPath, home.file).then((m) => {
|
|
18058
|
+
held = holdManifestFile(home.absPath, home.file, home.perPage).then((m) => {
|
|
17662
18059
|
const h = { held: m, saving: Promise.resolve() };
|
|
17663
18060
|
heldManifests.set(home.absPath, h);
|
|
17664
18061
|
return h;
|
|
@@ -18194,7 +18591,7 @@ async function runFill(opts) {
|
|
|
18194
18591
|
const changed = next !== content || manifestChanged;
|
|
18195
18592
|
const pageWritten = next !== content && !dryRun && label !== "<stdin>";
|
|
18196
18593
|
if (pageWritten) {
|
|
18197
|
-
await writeFileAtomic(
|
|
18594
|
+
await writeFileAtomic(resolve21(base, label), next);
|
|
18198
18595
|
}
|
|
18199
18596
|
if (manifestChanged) {
|
|
18200
18597
|
const perManifest = /* @__PURE__ */ new Map();
|
|
@@ -18226,7 +18623,7 @@ async function runFill(opts) {
|
|
|
18226
18623
|
const prepareAll = async () => ({
|
|
18227
18624
|
stdin: usingStdin ? await prepareOne("<stdin>", opts.stdinContent ?? "", forcedExtractor?.extensions[0] ?? "") : void 0,
|
|
18228
18625
|
files: await mapConcurrent(files, concurrency, async (file) => {
|
|
18229
|
-
const content = await readFile14(
|
|
18626
|
+
const content = await readFile14(resolve21(base, file), "utf8");
|
|
18230
18627
|
return prepareOne(file, content, extname8(file));
|
|
18231
18628
|
})
|
|
18232
18629
|
});
|
|
@@ -18656,7 +19053,7 @@ async function mapConcurrent(items2, limit, fn) {
|
|
|
18656
19053
|
|
|
18657
19054
|
// src/meta/commands/derive.ts
|
|
18658
19055
|
import { readFile as readFile15 } from "node:fs/promises";
|
|
18659
|
-
import { extname as extname9, relative as
|
|
19056
|
+
import { extname as extname9, relative as relative15, resolve as resolve22, sep as sep11 } from "node:path";
|
|
18660
19057
|
var GENERATED_BY_ENV = "MANNI_GENERATED_BY";
|
|
18661
19058
|
var SOURCE_HINT = "narrow --sources or --fields";
|
|
18662
19059
|
async function runDerive(opts) {
|
|
@@ -18767,7 +19164,7 @@ async function runDerive(opts) {
|
|
|
18767
19164
|
const files = fromCollections ? retainMembers(walked, membersFor) : walked;
|
|
18768
19165
|
const rangesByPage = /* @__PURE__ */ new Map();
|
|
18769
19166
|
for (const t of targets) {
|
|
18770
|
-
const label =
|
|
19167
|
+
const label = relative15(base, resolve22(base, t.page)).split(sep11).join("/");
|
|
18771
19168
|
if (!files.includes(label)) {
|
|
18772
19169
|
throw new DocmetaError(
|
|
18773
19170
|
`${t.target} does not name one file that derive reads; a range names lines of one file.`
|
|
@@ -18792,7 +19189,7 @@ async function runDerive(opts) {
|
|
|
18792
19189
|
const loaded2 = /* @__PURE__ */ new Map();
|
|
18793
19190
|
const errors2 = /* @__PURE__ */ new Map();
|
|
18794
19191
|
for (const label of files) {
|
|
18795
|
-
const absPath =
|
|
19192
|
+
const absPath = resolve22(base, label);
|
|
18796
19193
|
const extractor = forcedExtractor ?? extractorForExtension(extname9(label));
|
|
18797
19194
|
if (!extractor) {
|
|
18798
19195
|
errors2.set(label, {
|
|
@@ -18818,12 +19215,13 @@ async function runDerive(opts) {
|
|
|
18818
19215
|
}
|
|
18819
19216
|
}
|
|
18820
19217
|
const provenanceRoot = configDir ?? cwd;
|
|
19218
|
+
const pages2 = files.map((label) => resolve22(base, label));
|
|
18821
19219
|
const manifests = wantsProvenance ? provenanceManifests(declaredCollections, provenanceRoot, base) : [];
|
|
18822
19220
|
const provenanceCollections = declaredCollections.map((c) => ({
|
|
18823
19221
|
...c,
|
|
18824
19222
|
externalMetadata: c.externalMetadata.filter((m) => m.keys.includes(PROVENANCE_FIELD))
|
|
18825
19223
|
})).filter((c) => c.externalMetadata.length > 0);
|
|
18826
|
-
const provenanceIndex = manifests.length === 0 ? null : await loadExternalMetadata(provenanceCollections, { configDir: provenanceRoot, base });
|
|
19224
|
+
const provenanceIndex = manifests.length === 0 ? null : await loadExternalMetadata(provenanceCollections, { configDir: provenanceRoot, base, pages: pages2 });
|
|
18827
19225
|
const places2 = /* @__PURE__ */ new Map();
|
|
18828
19226
|
for (const doc of loaded2.values()) {
|
|
18829
19227
|
if (!wantsProvenance) break;
|
|
@@ -18850,7 +19248,7 @@ async function runDerive(opts) {
|
|
|
18850
19248
|
(m) => classifyRef(m.file).kind !== "url" && m.keys.some((k) => k !== PROVENANCE_FIELD && fields.includes(k))
|
|
18851
19249
|
)
|
|
18852
19250
|
})).filter((c) => c.externalMetadata.length > 0);
|
|
18853
|
-
const ownedIndex = ownedCollections.length === 0 ? null : await loadExternalMetadata(ownedCollections, { configDir: provenanceRoot, base });
|
|
19251
|
+
const ownedIndex = ownedCollections.length === 0 ? null : await loadExternalMetadata(ownedCollections, { configDir: provenanceRoot, base, pages: pages2 });
|
|
18854
19252
|
const derived2 = await deriveMetadata([...loaded2.values()], {
|
|
18855
19253
|
cwd,
|
|
18856
19254
|
base,
|
|
@@ -18945,8 +19343,8 @@ async function runDerive(opts) {
|
|
|
18945
19343
|
error: `${at2} is encrypted, and no encryption key is available to compare it. Set ${ENCRYPTION_KEY_ENV}, or run \`manni key set\`.`
|
|
18946
19344
|
};
|
|
18947
19345
|
}
|
|
18948
|
-
const
|
|
18949
|
-
if (
|
|
19346
|
+
const unreadable2 = view.unreadable.find((p) => isAtOrUnder(p, at2));
|
|
19347
|
+
if (unreadable2 !== void 0) return { error: unreadableMessage(unreadable2) };
|
|
18950
19348
|
}
|
|
18951
19349
|
const stamped = { ...view.data };
|
|
18952
19350
|
for (const field of fields) {
|
|
@@ -19022,7 +19420,7 @@ async function runDerive(opts) {
|
|
|
19022
19420
|
const holdManifest = async (manifest) => {
|
|
19023
19421
|
const already = heldManifests.get(manifest.absPath);
|
|
19024
19422
|
if (already !== void 0) return already;
|
|
19025
|
-
const held = await holdManifestFile(manifest.absPath, manifest.file);
|
|
19423
|
+
const held = await holdManifestFile(manifest.absPath, manifest.file, manifest.perPage);
|
|
19026
19424
|
heldManifests.set(manifest.absPath, held);
|
|
19027
19425
|
return held;
|
|
19028
19426
|
};
|
|
@@ -19953,6 +20351,9 @@ export {
|
|
|
19953
20351
|
palette,
|
|
19954
20352
|
shouldColor,
|
|
19955
20353
|
matchesFileGlob,
|
|
20354
|
+
hasPagePlaceholder,
|
|
20355
|
+
pageManifestPath,
|
|
20356
|
+
findPageManifests,
|
|
19956
20357
|
externalMetadataUrlProblem,
|
|
19957
20358
|
parseCollections,
|
|
19958
20359
|
selectCollections,
|
|
@@ -19965,6 +20366,7 @@ export {
|
|
|
19965
20366
|
findGitRoot,
|
|
19966
20367
|
valeConfigPath,
|
|
19967
20368
|
programName,
|
|
20369
|
+
warn,
|
|
19968
20370
|
notice,
|
|
19969
20371
|
ToolError,
|
|
19970
20372
|
errorMessage,
|
|
@@ -20005,6 +20407,7 @@ export {
|
|
|
20005
20407
|
committedKeyWarning,
|
|
20006
20408
|
terminalConfirm,
|
|
20007
20409
|
ensureEncryptionKey,
|
|
20410
|
+
gitIgnored,
|
|
20008
20411
|
escapePointerSegment,
|
|
20009
20412
|
hasFrontmatterFence,
|
|
20010
20413
|
locateFrontmatter,
|
|
@@ -20068,6 +20471,10 @@ export {
|
|
|
20068
20471
|
isMachineFormat,
|
|
20069
20472
|
OMITTED_WHEN_CLEAN,
|
|
20070
20473
|
render,
|
|
20474
|
+
heldManifest,
|
|
20475
|
+
rebaseable,
|
|
20476
|
+
settle,
|
|
20477
|
+
isMissing,
|
|
20071
20478
|
EXTERNAL_METADATA_FETCH_TIMEOUT_MS,
|
|
20072
20479
|
EXTERNAL_METADATA_FETCH_MAX_BYTES,
|
|
20073
20480
|
fetchExternalMetadata,
|
|
@@ -20076,7 +20483,7 @@ export {
|
|
|
20076
20483
|
EXTERNAL_OWNED_SCHEMA,
|
|
20077
20484
|
EXTERNAL_DUPLICATE_SCHEMA,
|
|
20078
20485
|
EXTERNAL_KEYWORD,
|
|
20079
|
-
PATH_JOIN,
|
|
20486
|
+
PATH_JOIN2 as PATH_JOIN,
|
|
20080
20487
|
externalMetadataJoin,
|
|
20081
20488
|
loadExternalMetadata,
|
|
20082
20489
|
mergeExternalMetadata,
|
|
@@ -20134,9 +20541,6 @@ export {
|
|
|
20134
20541
|
runVendorSchema,
|
|
20135
20542
|
runInferSchema,
|
|
20136
20543
|
runQuery,
|
|
20137
|
-
heldManifest,
|
|
20138
|
-
rebaseable,
|
|
20139
|
-
settle,
|
|
20140
20544
|
runFill,
|
|
20141
20545
|
runDerive,
|
|
20142
20546
|
deriveFailed,
|
|
@@ -20155,4 +20559,4 @@ export {
|
|
|
20155
20559
|
renderQuery,
|
|
20156
20560
|
renderQueryCsv
|
|
20157
20561
|
};
|
|
20158
|
-
//# sourceMappingURL=chunk-
|
|
20562
|
+
//# sourceMappingURL=chunk-BUXVMARH.js.map
|