@hawkeyexl/manni 2.0.1 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -98,7 +98,7 @@ actually reads rather than hand-written:
98
98
  ```yaml
99
99
  repos:
100
100
  - repo: https://github.com/hawkeyexl/manni
101
- rev: v2.0.1
101
+ rev: v2.2.0
102
102
  hooks:
103
103
  - id: manni-meta
104
104
  ```
@@ -8,13 +8,20 @@ import {
8
8
  DocmetaError,
9
9
  FILL_FORMATS,
10
10
  FILL_FORMAT_LIST,
11
+ LOCATION_EXTERNAL_SCHEMA,
12
+ LOCATION_PAGE_SCHEMA,
11
13
  OMITTED_WHEN_CLEAN,
12
14
  QUERY_FORMATS,
13
15
  QUERY_FORMAT_LIST,
14
16
  REPORT_FORMATS,
15
17
  REPORT_FORMAT_LIST,
16
- ToolError,
17
- errorMessage,
18
+ STDIN_LABEL,
19
+ Validator,
20
+ applyRelocation,
21
+ collectSchemaPins,
22
+ deriveFailed,
23
+ fail,
24
+ formatList,
18
25
  getSchemasInfo,
19
26
  isCommonFormat,
20
27
  isDeriveFormat,
@@ -24,74 +31,37 @@ import {
24
31
  isQueryFindingsFormat,
25
32
  isQueryFormat,
26
33
  isReportFormat,
34
+ keyHome,
27
35
  notice,
36
+ offerPrompt,
28
37
  package_default,
29
38
  palette,
39
+ planRelocation,
30
40
  programName,
41
+ relocateFailed,
42
+ relocationContext,
31
43
  render,
32
44
  renderDerive,
33
45
  renderFill,
34
46
  renderGet,
35
47
  renderQuery,
36
48
  renderQueryCsv,
49
+ resolveRunConfig,
37
50
  rowsToFindings,
38
51
  runDerive,
39
52
  runFill,
40
53
  runGet,
41
54
  runInferSchema,
42
55
  runQuery,
56
+ runRelocate,
43
57
  runValidate,
44
58
  runVendorSchema,
45
- setProgramName,
59
+ schemaLoadOptions,
46
60
  shouldColor,
47
61
  supportedExtensions,
48
62
  terminalConfirm,
49
63
  toJsonText
50
- } from "./chunk-PDNSN5UJ.js";
51
-
52
- // src/shared/run.ts
53
- import { realpathSync } from "node:fs";
54
- import { fileURLToPath } from "node:url";
55
- import { CommanderError } from "commander";
56
- function fail(err) {
57
- const msg = err instanceof ToolError ? err.message : `Unexpected error: ${errorMessage(err)}`;
58
- process.stderr.write(`${programName()}: ${msg}
59
- `);
60
- process.exit(2);
61
- }
62
- var STDIN_LINES_MARKER = "\0";
63
- var STDIN_WITH_LINES = /^-(:[1-9][0-9]*(?:-[1-9][0-9]*)?)$/;
64
- function normalizeStdinArgv(argv) {
65
- return argv.map((arg) => {
66
- const lines = STDIN_WITH_LINES.exec(arg)?.[1];
67
- return lines === void 0 ? arg : `${STDIN_LINES_MARKER}${lines}`;
68
- });
69
- }
70
- async function runProgram(program, argv = process.argv) {
71
- setProgramName(program.name());
72
- try {
73
- await program.parseAsync(normalizeStdinArgv(argv));
74
- } catch (err) {
75
- if (err instanceof CommanderError) {
76
- process.exitCode = err.exitCode === 0 ? 0 : 2;
77
- return;
78
- }
79
- throw err;
80
- }
81
- }
82
- function isMainModule(moduleUrl) {
83
- const entry = process.argv[1];
84
- if (!entry) return false;
85
- try {
86
- return realpathSync(entry) === fileURLToPath(moduleUrl);
87
- } catch {
88
- return false;
89
- }
90
- }
91
- function runIfMain(moduleUrl, build) {
92
- if (!isMainModule(moduleUrl)) return;
93
- runProgram(build()).catch(fail);
94
- }
64
+ } from "./chunk-5O4FIGDJ.js";
95
65
 
96
66
  // src/meta/cli.ts
97
67
  import { existsSync } from "node:fs";
@@ -128,6 +98,238 @@ function reportConfig(toStdout, cwd) {
128
98
  };
129
99
  }
130
100
 
101
+ // src/meta/reporters/relocate.ts
102
+ var RELOCATE_FORMATS = ["pretty", "json"];
103
+ var RELOCATE_FORMAT_LIST = formatList(RELOCATE_FORMATS);
104
+ function isRelocateFormat(value) {
105
+ return RELOCATE_FORMATS.includes(value);
106
+ }
107
+ function renderRelocate(result, format, opts = {}) {
108
+ switch (format) {
109
+ case "json":
110
+ return JSON.stringify(relocateJson(result), null, 2);
111
+ case "pretty":
112
+ return renderRelocatePretty(result, opts);
113
+ default: {
114
+ const unreachable = format;
115
+ throw new DocmetaError(
116
+ `relocate --format must be pretty or json; got ${JSON.stringify(unreachable)}.`
117
+ );
118
+ }
119
+ }
120
+ }
121
+ function relocateJson(result) {
122
+ return {
123
+ dryRun: result.dryRun,
124
+ config: {
125
+ file: result.config.file,
126
+ created: result.config.created,
127
+ collectionsCreated: result.config.collectionsCreated,
128
+ pathsAdded: result.config.pathsAdded
129
+ },
130
+ manifests: result.manifests.map((m) => ({
131
+ file: m.file,
132
+ collection: m.collection,
133
+ created: m.created,
134
+ keysAdded: m.keysAdded,
135
+ keysRemoved: m.keysRemoved,
136
+ undeclared: m.undeclared
137
+ })),
138
+ files: result.files.map((f) => ({
139
+ file: f.file,
140
+ moved: f.moved,
141
+ stayed: f.stayed.map((s) => ({ key: s.key, reason: s.reason }))
142
+ })),
143
+ summary: result.summary
144
+ };
145
+ }
146
+ var plural = (n, noun) => `${n} ${noun}${n === 1 ? "" : "s"}`;
147
+ var list = (xs) => xs.join(", ");
148
+ function renderRelocatePretty(result, opts = {}) {
149
+ const c = palette(opts.color ?? false);
150
+ const dry = result.dryRun;
151
+ const lines = [];
152
+ if (result.config.created && result.config.file !== null) {
153
+ lines.push(dry ? `Would create ${result.config.file}.` : `Created ${result.config.file}.`);
154
+ }
155
+ const pathsOf = (collection) => result.config.pathsAdded.filter((p) => p.collection === collection).map((p) => p.path);
156
+ const said = /* @__PURE__ */ new Set();
157
+ for (const created of result.config.collectionsCreated) {
158
+ said.add(created.name);
159
+ const made = result.manifests.filter((m) => m.collection === created.name && m.created);
160
+ const head = `${dry ? "Would create" : "Created"} collection ${created.name} (paths: ${list(created.paths)})`;
161
+ if (made.length === 0) {
162
+ lines.push(`${head}.`);
163
+ continue;
164
+ }
165
+ const owns = list(made.flatMap((m) => m.keys));
166
+ lines.push(`${head} and ${list(made.map((m) => m.file))}; it ${dry ? "would own" : "owns"} ${owns}.`);
167
+ }
168
+ for (const m of result.manifests) {
169
+ if (said.has(m.collection) && m.created) continue;
170
+ const added = said.has(m.collection) ? [] : pathsOf(m.collection);
171
+ if (added.length > 0) said.add(m.collection);
172
+ const keys = list(m.keys);
173
+ if (m.created) {
174
+ if (added.length > 0) {
175
+ lines.push(
176
+ dry ? `Would add ${list(added)} to collection ${m.collection}'s paths and create ${m.file}; it would own ${keys}.` : `Added ${list(added)} to collection ${m.collection}'s paths and created ${m.file}; it owns ${keys}.`
177
+ );
178
+ } else {
179
+ lines.push(
180
+ dry ? `Would create ${m.file}; collections[${m.collection}].externalMetadata[${m.index}] would own ${keys}.` : `Created ${m.file}; collections[${m.collection}].externalMetadata[${m.index}] owns ${keys}.`
181
+ );
182
+ }
183
+ continue;
184
+ }
185
+ const beyond = m.beyond > 0 ? `, ${m.beyond} beyond the paths you named` : "";
186
+ const pronoun = (n) => n === 1 ? "it" : "them";
187
+ if (m.keysRemoved.length > 0) {
188
+ const what = `${list(m.keysRemoved)} from ${m.file}'s keys`;
189
+ const it = pronoun(m.keysRemoved.length);
190
+ const where = `into every page in collection ${m.collection}${beyond}`;
191
+ lines.push(dry ? `Would remove ${what}, moving ${it} ${where}.` : `Removing ${what} moves ${it} ${where}.`);
192
+ }
193
+ if (added.length > 0) {
194
+ lines.push(
195
+ dry ? `Would add ${list(added)} to collection ${m.collection}'s paths; ${m.file} would own ${keys}.` : `Added ${list(added)} to collection ${m.collection}'s paths; ${m.file} now owns ${keys}.`
196
+ );
197
+ } else if (m.keysAdded.length > 0) {
198
+ const what = `${list(m.keysAdded)} to ${m.file}'s keys`;
199
+ const it = pronoun(m.keysAdded.length);
200
+ const where = `out of every page in collection ${m.collection}${beyond}`;
201
+ lines.push(dry ? `Would add ${what}, moving ${it} ${where}.` : `Adding ${what} moves ${it} ${where}.`);
202
+ }
203
+ if (m.undeclared) {
204
+ lines.push(
205
+ dry ? `${m.file} would no longer own any keys and would no longer be declared; delete it when you are ready.` : `${m.file} no longer owns any keys and is no longer declared; delete it when you are ready.`
206
+ );
207
+ }
208
+ }
209
+ for (const p of result.config.pathsAdded) {
210
+ if (said.has(p.collection)) continue;
211
+ said.add(p.collection);
212
+ lines.push(`${dry ? "Would add" : "Added"} ${list(pathsOf(p.collection))} to collection ${p.collection}'s paths.`);
213
+ }
214
+ const width = Math.max(
215
+ 7,
216
+ ...result.files.flatMap((f) => [...f.moved, ...f.stayed].map((v) => v.key.length))
217
+ );
218
+ const shown = result.files.filter((f) => !f.beyond || f.stayed.length > 0);
219
+ for (const f of shown) {
220
+ lines.push(f.file);
221
+ for (const mv of f.moved) {
222
+ const name = c.cyan(mv.key.padEnd(width));
223
+ if (mv.to === "page") {
224
+ lines.push(` ${name} \u2190 ${mv.from}`);
225
+ } else {
226
+ lines.push(` ${name} \u2192 ${mv.manifest}${mv.line !== void 0 ? `:${mv.line}` : ""}`);
227
+ }
228
+ }
229
+ for (const st of f.stayed) {
230
+ lines.push(` ${c.cyan(st.key.padEnd(width))} ${c.yellow(`stays: ${st.detail ?? st.reason}`)}`);
231
+ }
232
+ }
233
+ const hidden = result.files.length - shown.length;
234
+ if (hidden > 0) lines.push(`\u2026 (${plural(hidden, "more file")})`);
235
+ const s = result.summary;
236
+ if (s.files === 0) {
237
+ lines.push("0 files, nothing to move");
238
+ return lines.join("\n");
239
+ }
240
+ const moves = result.files.flatMap((f) => f.moved);
241
+ const toPage = moves.filter((m) => m.to === "page").length;
242
+ const toManifest = moves.flatMap((m) => m.to === "manifest" ? [m.manifest] : []);
243
+ const manifests = plural(new Set(toManifest).size, "manifest");
244
+ let footer = `${plural(s.files, "file")}, ${plural(s.moved, "value")} ${dry ? "would move" : "moved"}`;
245
+ if (toPage > 0 && toManifest.length > 0) {
246
+ footer += `: ${toPage} into pages, ${toManifest.length} into ${manifests}`;
247
+ } else if (toManifest.length > 0) {
248
+ footer += ` to ${manifests}`;
249
+ } else if (toPage > 0) {
250
+ footer += " into pages";
251
+ }
252
+ if (s.stayed > 0) footer += `, ${s.stayed} stayed`;
253
+ lines.push(s.stayed > 0 ? c.yellow(footer) : footer);
254
+ return lines.join("\n");
255
+ }
256
+
257
+ // src/meta/commands/validate-offer.ts
258
+ async function offerRelocation(opts) {
259
+ const { confirm, output } = opts;
260
+ if (confirm === void 0 || opts.noConfig === true) return [];
261
+ const findings = opts.results.flatMap(
262
+ (r) => r.file === STDIN_LABEL ? [] : r.errors.filter((e) => e.schema === LOCATION_EXTERNAL_SCHEMA || e.schema === LOCATION_PAGE_SCHEMA).flatMap((e) => e.subject === void 0 ? [] : [{ file: r.file, key: e.subject, schema: e.schema }])
263
+ );
264
+ if (findings.length === 0) return [];
265
+ const cwd = opts.cwd ?? process.cwd();
266
+ const run = await resolveRunConfig({
267
+ cwd,
268
+ ...opts.configPath !== void 0 ? { configPath: opts.configPath } : {},
269
+ inputs: opts.inputs,
270
+ ...opts.collections !== void 0 ? { collections: opts.collections } : {}
271
+ });
272
+ const validator = new Validator(
273
+ schemaLoadOptions({
274
+ root: run.configDir ?? cwd,
275
+ fileBase: cwd,
276
+ ttlHours: run.config?.schemaCache?.ttlHours,
277
+ offline: opts.offline ?? run.config?.offline,
278
+ pins: collectSchemaPins(run.config)
279
+ })
280
+ );
281
+ const ctx = relocationContext(run, {
282
+ cwd,
283
+ targets: run.fromCollections ? [] : opts.inputs,
284
+ validator,
285
+ ...opts.cliSchemas !== void 0 && opts.cliSchemas.length > 0 ? { cliSchemas: opts.cliSchemas } : {},
286
+ ...opts.as !== void 0 ? { as: opts.as } : {},
287
+ ...opts.respectGitignore !== void 0 ? { respectGitignore: opts.respectGitignore } : {},
288
+ ...opts.env !== void 0 ? { env: opts.env } : {}
289
+ });
290
+ const groups = /* @__PURE__ */ new Map();
291
+ for (const f of findings) {
292
+ const home = await keyHome(ctx, f.file, {}, f.key);
293
+ let collection;
294
+ if (f.schema === LOCATION_PAGE_SCHEMA) {
295
+ if (home.kind === "manifest") collection = home.collection;
296
+ } else if (home.kind === "unowned" && home.home.kind === "collection") {
297
+ collection = home.home.collection;
298
+ }
299
+ if (collection === void 0) continue;
300
+ const group = groups.get(collection) ?? { files: /* @__PURE__ */ new Set(), keys: /* @__PURE__ */ new Set() };
301
+ group.files.add(f.file);
302
+ group.keys.add(f.key);
303
+ groups.set(collection, group);
304
+ }
305
+ const applied = [];
306
+ const say = (message) => {
307
+ output.write(`${programName()}: ${message}
308
+ `);
309
+ };
310
+ for (const [collection, group] of groups) {
311
+ let plan;
312
+ try {
313
+ plan = await planRelocation(ctx, { files: [...group.files], fields: [...group.keys] });
314
+ } catch (err) {
315
+ if (!(err instanceof DocmetaError)) throw err;
316
+ say(err.message);
317
+ continue;
318
+ }
319
+ if (plan.writes.length === 0) continue;
320
+ const offer = plan.offers.find((o) => o.collection === collection);
321
+ if (offer === void 0) continue;
322
+ const { notice: notice2, question } = offerPrompt(offer, "validate");
323
+ say(notice2);
324
+ if (!await confirm(question)) continue;
325
+ const result = await applyRelocation(ctx, plan);
326
+ output.write(`${renderRelocatePretty(result, { color: opts.color ?? false })}
327
+ `);
328
+ applied.push(result);
329
+ }
330
+ return applied;
331
+ }
332
+
131
333
  // src/meta/reporters/infer.ts
132
334
  var OUTLIERS_SHOWN = 5;
133
335
  var ENUM_SHOWN = 3;
@@ -542,6 +744,22 @@ function buildProgram() {
542
744
  `);
543
745
  }
544
746
  process.exitCode = summary.failed > 0 ? 1 : 0;
747
+ await offerRelocation({
748
+ results,
749
+ inputs: paths,
750
+ cliSchemas: options.schema,
751
+ as: options.as,
752
+ collections: options.collection,
753
+ ...configOption(options.config),
754
+ respectGitignore: explicitFalse(options.gitignore),
755
+ offline: options.offline ? true : void 0,
756
+ confirm: paths.includes(STDIN) ? void 0 : terminalConfirm(),
757
+ output: process.stderr,
758
+ color: shouldColor({
759
+ noColor: (command.parent ?? command).opts().color === false,
760
+ isTTY: process.stderr.isTTY
761
+ })
762
+ });
545
763
  } catch (err) {
546
764
  fail(err);
547
765
  }
@@ -762,7 +980,17 @@ function buildProgram() {
762
980
  onNotice: notice,
763
981
  // A write to a column marked x-manni-encrypt with no key asks
764
982
  // for one on a terminal, and refuses off one (proposal 0045).
765
- confirm: terminalConfirm()
983
+ // The same Confirm asks P1 (proposal 0047).
984
+ confirm: terminalConfirm(),
985
+ // An accepted P1 offer prints relocate's report: on stdout
986
+ // beside a pretty report, on stderr when stdout must parse.
987
+ onRelocated: (result) => {
988
+ const text = renderRelocate(result, "pretty", {
989
+ color: format === "pretty" && resolveColor(command.parent ?? command)
990
+ });
991
+ (format === "pretty" ? process.stdout : process.stderr).write(`${text}
992
+ `);
993
+ }
766
994
  });
767
995
  if (run.db && sql === "") {
768
996
  process.stdout.write(
@@ -926,8 +1154,18 @@ function buildProgram() {
926
1154
  includeContent: usingStdin,
927
1155
  // A field marked x-manni-encrypt with no key asks for one on a
928
1156
  // terminal, and refuses off one (proposal 0045). Reading the page
929
- // from stdin leaves no terminal to ask on.
930
- confirm: usingStdin ? void 0 : terminalConfirm()
1157
+ // from stdin leaves no terminal to ask on. The same Confirm asks
1158
+ // P1 (proposal 0047).
1159
+ confirm: usingStdin ? void 0 : terminalConfirm(),
1160
+ // An accepted P1 offer prints relocate's report: on stdout beside a
1161
+ // pretty report, on stderr when stdout must parse.
1162
+ onRelocated: (result) => {
1163
+ const text = renderRelocate(result, "pretty", {
1164
+ color: format === "pretty" && resolveColor(command.parent ?? command)
1165
+ });
1166
+ (format === "pretty" ? process.stdout : process.stderr).write(`${text}
1167
+ `);
1168
+ }
931
1169
  });
932
1170
  const color = resolveColor(command.parent ?? command);
933
1171
  const report = renderFill(format, run, {
@@ -950,9 +1188,15 @@ function buildProgram() {
950
1188
  });
951
1189
  program.command("derive").description(
952
1190
  "Stamp the managed stewardship fields from git history, CODEOWNERS and GitHub or GitLab reviews"
953
- ).argument("[paths...]", "files, directories, or globs to stamp").option(
1191
+ ).argument(
1192
+ "[paths...]",
1193
+ "files, directories, or globs to stamp; <path>:L1-L2 names lines for --generated-by"
1194
+ ).option(
954
1195
  "--fields <list>",
955
1196
  "comma-separated managed fields to stamp; config derive.fields otherwise"
1197
+ ).option(
1198
+ "--generated-by <name>",
1199
+ "attribute uncommitted body lines, or a <path>:L1-L2 range, to this machine in provenance; MANNI_GENERATED_BY otherwise"
956
1200
  ).option(
957
1201
  "--sources <list>",
958
1202
  "comma-separated sources to consult: git, codeowners, github, gitlab, command (default all)"
@@ -978,7 +1222,9 @@ function buildProgram() {
978
1222
  " manni meta derive --dry-run docs/install.md # what would change, nothing written",
979
1223
  " manni meta derive --check -f github # CI: a stale stamp is an annotation, exit 1",
980
1224
  " manni meta derive --fields reviewed-by,last-reviewed",
981
- " manni meta derive --sources git,codeowners # no gh on this machine"
1225
+ " manni meta derive --sources git,codeowners # no gh on this machine",
1226
+ " MANNI_GENERATED_BY=claude-fable-5 manni meta derive --fields provenance",
1227
+ " manni meta derive docs/limits.md:12-31 --generated-by claude-fable-5"
982
1228
  ].join("\n")
983
1229
  ).action(async (paths, options, command) => {
984
1230
  try {
@@ -998,6 +1244,7 @@ function buildProgram() {
998
1244
  inputs: paths,
999
1245
  fields: options.fields ? splitList(options.fields) : void 0,
1000
1246
  sources: options.sources ? splitList(options.sources) : void 0,
1247
+ ...options.generatedBy !== void 0 ? { generatedBy: options.generatedBy } : {},
1001
1248
  dryRun: Boolean(options.dryRun),
1002
1249
  check: Boolean(options.check),
1003
1250
  cache: options.cache,
@@ -1011,8 +1258,18 @@ function buildProgram() {
1011
1258
  respectGitignore: explicitFalse(options.gitignore),
1012
1259
  onNotice: notice,
1013
1260
  // A field its schema marks x-manni-encrypt (proposal 0045) with no
1014
- // key yet: asked on a terminal, refused off one.
1015
- confirm: terminalConfirm()
1261
+ // key yet: asked on a terminal, refused off one. The same Confirm
1262
+ // asks P1 (proposal 0047).
1263
+ confirm: terminalConfirm(),
1264
+ // An accepted P1 offer prints relocate's report: on stdout beside a
1265
+ // pretty report, on stderr when stdout must parse.
1266
+ onRelocated: (result) => {
1267
+ const text2 = renderRelocate(result, "pretty", {
1268
+ color: format === "pretty" && resolveColor(command.parent ?? command)
1269
+ });
1270
+ (format === "pretty" ? process.stdout : process.stderr).write(`${text2}
1271
+ `);
1272
+ }
1016
1273
  });
1017
1274
  const text = renderDerive(run, format, {
1018
1275
  color: resolveColor(command.parent ?? command),
@@ -1023,9 +1280,73 @@ function buildProgram() {
1023
1280
  process.stdout.write(`${text}
1024
1281
  `);
1025
1282
  }
1026
- const { stale, unset, errors } = run.summary;
1027
- const failed = errors > 0 || options.check && stale + unset > 0;
1028
- process.exitCode = failed ? 1 : 0;
1283
+ process.exitCode = deriveFailed(run) ? 1 : 0;
1284
+ } catch (err) {
1285
+ fail(err);
1286
+ }
1287
+ });
1288
+ program.command("relocate").description(
1289
+ "Move each value to where its schema's x-manni-location and the config's manifests say it belongs"
1290
+ ).argument(
1291
+ "[paths...]",
1292
+ "files, directories, or globs to relocate (stdin is refused)"
1293
+ ).option(
1294
+ "--fields <list>",
1295
+ "comma-separated fields to move; each must be marked x-manni-location or manifest-owned"
1296
+ ).option(
1297
+ "--collection <name>",
1298
+ "configured collection to run over; repeatable",
1299
+ collect,
1300
+ []
1301
+ ).option(
1302
+ "-s, --schema <ref>",
1303
+ "schema to judge preferences against; repeatable; overrides $schema/config",
1304
+ collect,
1305
+ []
1306
+ ).option("--dry-run", "report what would move and be created, and write nothing").option(
1307
+ "-f, --format <format>",
1308
+ `output: ${RELOCATE_FORMATS.join(" | ")}`,
1309
+ "pretty"
1310
+ ).option("--ext <list>", "comma-separated extensions for directory walks").option("--exclude <glob>", "glob to exclude; repeatable", collect, []).option("--as <format>", "force an input format (e.g. markdown, mdx)").option("-c, --config <path>", "path to a manni config file").option("--no-config", "ignore any discovered config file (refused: relocate writes the config)").option("--allow-empty", "treat zero matched files as success").option("--no-gitignore", "relocate files .gitignore covers").addHelpText(
1311
+ "after",
1312
+ [
1313
+ "",
1314
+ "Examples:",
1315
+ " manni meta relocate # every collection, as config declares it",
1316
+ " manni meta relocate --dry-run # what would move and be created",
1317
+ " manni meta relocate docs/install.md --fields owner",
1318
+ " manni meta relocate docs/ guides/intro.md # no collections yet: creates collection default",
1319
+ " manni meta relocate -f json --dry-run # the scripting form"
1320
+ ].join("\n")
1321
+ ).action(async (paths, options, command) => {
1322
+ try {
1323
+ const format = options.format;
1324
+ if (!isRelocateFormat(format)) {
1325
+ throw new DocmetaError(
1326
+ `relocate --format must be pretty or json; got "${format}".`
1327
+ );
1328
+ }
1329
+ const result = await runRelocate({
1330
+ inputs: paths,
1331
+ fields: options.fields ? splitList(options.fields) : void 0,
1332
+ collections: options.collection,
1333
+ cliSchemas: options.schema,
1334
+ dryRun: Boolean(options.dryRun),
1335
+ exts: options.ext ? splitList(options.ext) : void 0,
1336
+ exclude: options.exclude,
1337
+ as: options.as,
1338
+ ...configOption(options.config),
1339
+ onConfigLoaded: reportConfig(format === "pretty", process.cwd()),
1340
+ allowEmpty: options.allowEmpty ? true : void 0,
1341
+ respectGitignore: explicitFalse(options.gitignore),
1342
+ onNotice: notice
1343
+ });
1344
+ const text = renderRelocate(result, format, {
1345
+ color: resolveColor(command.parent ?? command)
1346
+ });
1347
+ process.stdout.write(`${text}
1348
+ `);
1349
+ process.exitCode = relocateFailed(result) ? 1 : 0;
1029
1350
  } catch (err) {
1030
1351
  fail(err);
1031
1352
  }
@@ -1195,9 +1516,6 @@ function buildProgram() {
1195
1516
  }
1196
1517
 
1197
1518
  export {
1198
- fail,
1199
- STDIN_LINES_MARKER,
1200
- runIfMain,
1201
1519
  collect,
1202
1520
  splitList,
1203
1521
  readStdin,
@@ -1206,4 +1524,4 @@ export {
1206
1524
  reportConfig,
1207
1525
  buildProgram
1208
1526
  };
1209
- //# sourceMappingURL=chunk-MV2T7XAW.js.map
1527
+ //# sourceMappingURL=chunk-2Q5JUEIO.js.map