@c4a/context-cli 0.7.73 → 0.7.81

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/cli.js CHANGED
@@ -42109,6 +42109,40 @@ var init_debugTrace = __esm(() => {
42109
42109
  SENSITIVE_OPTION = /^(--(?:auth|authorization|password|secret|token|otp|cookie|api-key))(?:=|$)/iu;
42110
42110
  });
42111
42111
 
42112
+ // src/project/derivedValueCache.ts
42113
+ class DerivedValueCache {
42114
+ values = new Map;
42115
+ bytes = 0;
42116
+ get(key, calculate) {
42117
+ const existing = this.values.get(key);
42118
+ if (existing) {
42119
+ this.values.delete(key);
42120
+ this.values.set(key, existing);
42121
+ return existing.value;
42122
+ }
42123
+ const value = calculate();
42124
+ let serialized;
42125
+ try {
42126
+ serialized = JSON.stringify(value);
42127
+ } catch {
42128
+ return value;
42129
+ }
42130
+ if (serialized === undefined)
42131
+ return value;
42132
+ const bytes = Buffer.byteLength(key) + Buffer.byteLength(serialized);
42133
+ if (bytes > 8 * 1024 * 1024)
42134
+ return value;
42135
+ while (this.values.size >= 512 || this.bytes + bytes > 8 * 1024 * 1024) {
42136
+ const oldest = this.values.keys().next().value;
42137
+ this.bytes -= this.values.get(oldest).bytes;
42138
+ this.values.delete(oldest);
42139
+ }
42140
+ this.values.set(key, { value, bytes });
42141
+ this.bytes += bytes;
42142
+ return value;
42143
+ }
42144
+ }
42145
+
42112
42146
  // src/project/commandReadCache.ts
42113
42147
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
42114
42148
  import { readdir as readdir3, stat as stat2 } from "node:fs/promises";
@@ -42122,7 +42156,7 @@ async function readCommandDirectory(path2) {
42122
42156
  return [...entries];
42123
42157
  }
42124
42158
  function withCommandReadCache(action) {
42125
- return commandReads.getStore() === undefined ? commandReads.run(new Map, action) : action();
42159
+ return commandReads.getStore() === undefined ? commandValues.run(new DerivedValueCache, () => commandReads.run(new Map, action)) : action();
42126
42160
  }
42127
42161
  async function reuseCommandFileRead(input) {
42128
42162
  const cache = commandReads.getStore();
@@ -42178,10 +42212,15 @@ async function reuseCommandFileRead(input) {
42178
42212
  throw error;
42179
42213
  }
42180
42214
  }
42181
- var commandReads, MAX_READS = 64;
42215
+ function reuseCommandValue(key, calculate) {
42216
+ const cache = commandValues.getStore();
42217
+ return cache ? cache.get(key, calculate) : calculate();
42218
+ }
42219
+ var commandReads, MAX_READS = 64, commandValues;
42182
42220
  var init_commandReadCache = __esm(() => {
42183
42221
  init_debugTrace();
42184
42222
  commandReads = new AsyncLocalStorage2;
42223
+ commandValues = new AsyncLocalStorage2;
42185
42224
  });
42186
42225
 
42187
42226
  // src/project/writeLock.ts
@@ -53416,8 +53455,11 @@ function destinationRange(raw) {
53416
53455
  function markdownInlineLinks(content3) {
53417
53456
  if (!content3.includes("["))
53418
53457
  return [];
53419
- const tree = unified().use(remarkParse).parse(content3);
53420
- return inlineLinksFromTree(content3, tree);
53458
+ const links = reuseCommandValue(`markdown-inline-links:${content3}`, () => {
53459
+ const tree = unified().use(remarkParse).parse(content3);
53460
+ return inlineLinksFromTree(content3, tree);
53461
+ });
53462
+ return links.map((link) => ({ ...link }));
53421
53463
  }
53422
53464
  function inlineLinksFromTree(content3, tree) {
53423
53465
  const links = [];
@@ -53504,6 +53546,7 @@ function replaceMarkdownInlineLinkTargets(content3, replacement) {
53504
53546
  var init_markdownLinks = __esm(() => {
53505
53547
  init_remark_parse();
53506
53548
  init_unified();
53549
+ init_commandReadCache();
53507
53550
  });
53508
53551
 
53509
53552
  // src/project/documentCaptureAssets.ts
@@ -94237,6 +94280,35 @@ function normalizeSubpath2(value) {
94237
94280
  const normalized = value.replace(/\\/g, "/").split("/").filter((part) => part.length > 0 && part !== ".").join("/");
94238
94281
  return normalized.length > 0 ? normalized : undefined;
94239
94282
  }
94283
+ function explicitSubpath(value, sourceName) {
94284
+ const parts = value.replace(/\\/g, "/").split("/");
94285
+ if (isAbsolute16(value) || /^[A-Za-z]:/.test(value) || parts.includes("..")) {
94286
+ throw new ContextError(ExitCode.UserError, `repo source subpath must stay inside the repository: ${value}`, {
94287
+ category: ErrorCategory.UserInputInvalid,
94288
+ sourceName,
94289
+ subpath: value,
94290
+ next: "Pass --subpath as a repository-relative directory such as apps/web, or . for the repository root."
94291
+ });
94292
+ }
94293
+ return normalizeSubpath2(value);
94294
+ }
94295
+ function requestedSubpath(input) {
94296
+ if (input.value === undefined)
94297
+ return input.current;
94298
+ const { value, sourceName } = input;
94299
+ const localScope = input.localScoped ? input.current : undefined;
94300
+ const requested = explicitSubpath(value, sourceName);
94301
+ if (localScope !== undefined && localScope !== requested) {
94302
+ throw new ContextError(ExitCode.UserError, `repo source subpath ${requested ?? "."} conflicts with local path scope ${localScope}`, {
94303
+ category: ErrorCategory.UserInputInvalid,
94304
+ sourceName,
94305
+ subpath: value,
94306
+ localSubpath: localScope,
94307
+ next: "Pass --local at the repository root together with --subpath, or pass only --local pointing at the module directory."
94308
+ });
94309
+ }
94310
+ return requested;
94311
+ }
94240
94312
  function scopedLocalPath(rootAbs, subpath) {
94241
94313
  return subpath === undefined ? rootAbs : resolve30(rootAbs, subpath);
94242
94314
  }
@@ -94482,6 +94554,12 @@ async function normalizeAddInput(input, existing) {
94482
94554
  }
94483
94555
  }
94484
94556
  }
94557
+ subpath = requestedSubpath({
94558
+ value: input.subpath,
94559
+ sourceName,
94560
+ current: subpath,
94561
+ localScoped: localWasResolvedFromInput && gitRootAbs !== null
94562
+ });
94485
94563
  if (input.local !== undefined && (explicitRemote === null || explicitRef === null)) {
94486
94564
  if (originalLocalAbs === null || !existsSync22(originalLocalAbs)) {
94487
94565
  throw new ContextError(ExitCode.UserError, `repo source local path does not exist: ${input.local}`, {
@@ -115697,7 +115775,7 @@ async function readSourceBatchJournalStatus(input) {
115697
115775
 
115698
115776
  // src/project/sourceBatchRegistration.ts
115699
115777
  var ITEM_KEYS = {
115700
- repo: new Set(["type", "module", "local", "remote", "ref"]),
115778
+ repo: new Set(["type", "module", "local", "remote", "ref", "subpath"]),
115701
115779
  file: new Set(["type", "module", "local", "include"]),
115702
115780
  lark: new Set(["type", "module", "url", "docToken", "wikiToken", "title"])
115703
115781
  };
@@ -115741,7 +115819,12 @@ function optionalStringArray(record6, field, path3) {
115741
115819
  function assertAllowedKeys(record6, type, path3) {
115742
115820
  const unknown2 = Object.keys(record6).filter((key) => !ITEM_KEYS[type].has(key));
115743
115821
  if (unknown2.length > 0) {
115744
- throw inputError(`${path3} has unsupported field(s): ${unknown2.join(", ")}`, { path: path3, fields: unknown2 });
115822
+ const allowed = [...ITEM_KEYS[type]].join(", ");
115823
+ throw inputError(`${path3} has unsupported field(s): ${unknown2.join(", ")}; ${type} items accept ${allowed}`, {
115824
+ path: path3,
115825
+ fields: unknown2,
115826
+ allowed: [...ITEM_KEYS[type]]
115827
+ });
115745
115828
  }
115746
115829
  }
115747
115830
  function parseBatchItem(value, index2) {
@@ -115757,12 +115840,14 @@ function parseBatchItem(value, index2) {
115757
115840
  const local = optionalString(record6, "local", path3);
115758
115841
  const remote = optionalString(record6, "remote", path3);
115759
115842
  const ref2 = optionalString(record6, "ref", path3);
115843
+ const subpath = optionalString(record6, "subpath", path3);
115760
115844
  return {
115761
115845
  type,
115762
115846
  module: module2,
115763
115847
  ...local !== undefined ? { local } : {},
115764
115848
  ...remote !== undefined ? { remote } : {},
115765
- ...ref2 !== undefined ? { ref: ref2 } : {}
115849
+ ...ref2 !== undefined ? { ref: ref2 } : {},
115850
+ ...subpath !== undefined ? { subpath } : {}
115766
115851
  };
115767
115852
  }
115768
115853
  if (type === "file") {
@@ -117593,6 +117678,9 @@ repo.local is resolved from the Context project root. A valid local Git checkout
117593
117678
  lets the CLI infer origin and the current commit; remote/ref are needed only when
117594
117679
  that local identity cannot be resolved. If local is omitted, the CLI also accepts
117595
117680
  one uniquely named Git directory at <project-root>/<module> or ../<module>.
117681
+ repo.subpath is an optional repository-relative module directory. Use it with
117682
+ remote/ref, or with local pointing at the checkout root; a local module directory
117683
+ already sets the subpath.
117596
117684
  The current source-boundary Route requires the completed, presented work-start
117597
117685
  report shown above. A direct maintenance call outside that Route may omit it.
117598
117686
  For long batches, add --checkpoint --progress. Resume with --resume <job-id>;
@@ -117635,7 +117723,7 @@ Resume performs registration only unless --configure is explicitly supplied.
117635
117723
  }
117636
117724
  writeFormatted(result, format2);
117637
117725
  });
117638
- sourceAdd.command("repo [date]").description("Add or update a repo module under a valid YYYYMMDD batch in sources/repo/index.yaml").option("--configure", "Also select this source in a simple src/index.ts; does not capture").requiredOption("--module <name>", "concrete repo/package module name").option("--remote <url>", "repo remote URL; inferred from local origin when omitted").option("--ref <sha>", "pinned commit/ref; inferred from local HEAD when omitted").option("--local <path>", "local checkout path; may point at a monorepo subdirectory").option("--format <format>", "output format: json | yaml | table", "table").action(async (namespace, ...args) => {
117726
+ sourceAdd.command("repo [date]").description("Add or update a repo module under a valid YYYYMMDD batch in sources/repo/index.yaml").option("--configure", "Also select this source in a simple src/index.ts; does not capture").requiredOption("--module <name>", "concrete repo/package module name").option("--remote <url>", "repo remote URL; inferred from local origin when omitted").option("--ref <sha>", "pinned commit/ref; inferred from local HEAD when omitted").option("--local <path>", "local checkout path; may point at a monorepo subdirectory").option("--subpath <dir>", "repo-relative module directory; use with --remote/--ref or a --local repository root").option("--format <format>", "output format: json | yaml | table", "table").action(async (namespace, ...args) => {
117639
117727
  const options = actionOptions(...args);
117640
117728
  const format2 = assertChoice(options.format, DATA_FORMATS, "--format");
117641
117729
  const projectRoot2 = requireProjectRoot3(process.cwd(), "source add repo");
@@ -117650,13 +117738,15 @@ Resume performs registration only unless --configure is explicitly supplied.
117650
117738
  const local = optionalString2(options.local);
117651
117739
  const remote = optionalString2(options.remote);
117652
117740
  const ref2 = optionalString2(options.ref);
117741
+ const subpath = optionalString2(options.subpath);
117653
117742
  const result = await addRepoSource({
117654
117743
  projectRoot: projectRoot2,
117655
117744
  namespace: sourceNamespace.name,
117656
117745
  module,
117657
117746
  ...local !== undefined ? { local } : {},
117658
117747
  ...remote !== undefined ? { remote } : {},
117659
- ...ref2 !== undefined ? { ref: ref2 } : {}
117748
+ ...ref2 !== undefined ? { ref: ref2 } : {},
117749
+ ...subpath !== undefined ? { subpath } : {}
117660
117750
  });
117661
117751
  writeFormatted(options.configure ? { ...result, configuration: await configureRegisteredSources(projectRoot2, [{ type: "repo", name: `${sourceNamespace.name}/${module}` }]) } : result, format2);
117662
117752
  });