@c4a/extract 0.5.29-beta.21 → 0.5.29-beta.29

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.
@@ -13291,6 +13291,41 @@ function createPathMatcher(rules) {
13291
13291
  const isExcluded = rules.exclude.length > 0 ? import_picomatch.default(rules.exclude, { dot: false }) : () => false;
13292
13292
  return (path) => isIncluded(path) && !isExcluded(path);
13293
13293
  }
13294
+ // ../core/src/utils/version.ts
13295
+ var VERSION_LABEL_REGEX = /^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-(alpha|beta|rc)\.(0|[1-9]\d*))?$/i;
13296
+ function encodePrerelease(channel, sequence) {
13297
+ if (!channel) {
13298
+ return 99;
13299
+ }
13300
+ const index = Number.parseInt(sequence ?? "", 10);
13301
+ if (!Number.isInteger(index) || index <= 0 || index > 29) {
13302
+ return null;
13303
+ }
13304
+ switch (channel.toLowerCase()) {
13305
+ case "alpha":
13306
+ return index;
13307
+ case "beta":
13308
+ return 30 + index;
13309
+ case "rc":
13310
+ return 60 + index;
13311
+ default:
13312
+ return null;
13313
+ }
13314
+ }
13315
+ function encodeVersionLabel(label) {
13316
+ const match = VERSION_LABEL_REGEX.exec(label.trim());
13317
+ if (!match) {
13318
+ return null;
13319
+ }
13320
+ const major = Number.parseInt(match[1] ?? "", 10);
13321
+ const minor = Number.parseInt(match[2] ?? "", 10);
13322
+ const patch = Number.parseInt(match[3] ?? "", 10);
13323
+ const prerelease = encodePrerelease(match[4], match[5]);
13324
+ if (!Number.isInteger(major) || !Number.isInteger(minor) || !Number.isInteger(patch) || prerelease === null) {
13325
+ return null;
13326
+ }
13327
+ return major * 1e6 + minor * 1e4 + patch * 100 + prerelease;
13328
+ }
13294
13329
  // ../core/src/constants.ts
13295
13330
  var SCAN_EXCLUDED_DIRS = new Set([
13296
13331
  ".git",
@@ -13494,6 +13529,7 @@ var generateSymbolDiff = (current, previous) => {
13494
13529
 
13495
13530
  // src/codeSnapshot.ts
13496
13531
  var sha256 = (value) => `sha256:${contentHash(value)}`;
13532
+ var FALLBACK_VERSION_LABEL = "0.0.1";
13497
13533
  var stableStringify = (value) => {
13498
13534
  if (value === null || typeof value !== "object")
13499
13535
  return JSON.stringify(value);
@@ -13522,6 +13558,32 @@ var jsonl = (rows) => rows.map((row) => JSON.stringify(row)).join(`
13522
13558
  var manifestText = (value) => JSON.stringify(value, null, 2) + `
13523
13559
  `;
13524
13560
  var hasOwn = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
13561
+ var canonicalizeCodeVersionLabel = (value) => {
13562
+ const trimmed = value.trim();
13563
+ if (!trimmed || encodeVersionLabel(trimmed) === null)
13564
+ return null;
13565
+ return trimmed.replace(/^v/iu, "").replace(/-(alpha|beta|rc)\./iu, (match) => match.toLowerCase());
13566
+ };
13567
+ var normalizeDoc = (value) => {
13568
+ if (typeof value !== "string")
13569
+ return;
13570
+ const normalized = value.replace(/\r\n?/gu, `
13571
+ `).replace(/[ \t]+$/gmu, "").trim();
13572
+ return normalized.length > 0 ? normalized : undefined;
13573
+ };
13574
+ var resolveVersion = (label, source2) => {
13575
+ const canonical = typeof label === "string" ? canonicalizeCodeVersionLabel(label) : null;
13576
+ if (canonical) {
13577
+ return { version_label: canonical, version_source: source2 ?? "package-json" };
13578
+ }
13579
+ return { version_label: FALLBACK_VERSION_LABEL, version_source: "fallback-0.0.1" };
13580
+ };
13581
+ var commonVersionField = (rows, field) => {
13582
+ const values = new Set(rows.map((row) => row[field]));
13583
+ if (values.size === 0)
13584
+ return;
13585
+ return values.size === 1 ? Array.from(values)[0] : "mixed";
13586
+ };
13525
13587
  var commonCommit = (rows) => {
13526
13588
  const commits = new Set(rows.digests.map((row) => row.dir_commit).filter((commit) => commit && commit !== "unknown"));
13527
13589
  return commits.size === 1 ? Array.from(commits)[0] : null;
@@ -13544,7 +13606,8 @@ var metaText = (manifest, source2, rows) => {
13544
13606
  dir_commit: digestByModule.get(row.module_path)?.dir_commit ?? "unknown",
13545
13607
  module_content_hash: digestByModule.get(row.module_path)?.module_content_hash ?? "",
13546
13608
  dirty: digestByModule.get(row.module_path)?.dirty ?? false,
13547
- version_label: row.version_label
13609
+ version_label: row.version_label,
13610
+ version_source: row.version_source
13548
13611
  })),
13549
13612
  snapshot_id: manifest.snapshot_id,
13550
13613
  source_slug: manifest.source_slug,
@@ -13552,6 +13615,8 @@ var metaText = (manifest, source2, rows) => {
13552
13615
  snapshot_content_hash: manifest.snapshot_content_hash,
13553
13616
  toolchain: manifest.toolchain,
13554
13617
  version_policy: source2.version_policy,
13618
+ ...manifest.version_label ? { version_label: manifest.version_label } : {},
13619
+ ...manifest.version_source ? { version_source: manifest.version_source } : {},
13555
13620
  head_commit: manifest.head_commit,
13556
13621
  dirty: manifest.dirty,
13557
13622
  ...manifest.worktree_content_hash ? { worktree_content_hash: manifest.worktree_content_hash } : {}
@@ -13563,7 +13628,14 @@ function flattenSymbols(symbols, packageName, modulePath) {
13563
13628
  const walk = (list) => {
13564
13629
  for (const symbol of list) {
13565
13630
  const { members, ...rest } = symbol;
13566
- out.push({ ...rest, package: packageName, modulePath });
13631
+ out.push({
13632
+ ...rest,
13633
+ package: packageName,
13634
+ package_name: packageName,
13635
+ symbol_id: symbol.name,
13636
+ modulePath,
13637
+ module_path: modulePath
13638
+ });
13567
13639
  if (members && members.length > 0)
13568
13640
  walk(members);
13569
13641
  }
@@ -13576,35 +13648,80 @@ var buildHashId = (packageName, dirCommit, moduleContentHash, dirty = false) =>
13576
13648
  return sha256(base);
13577
13649
  };
13578
13650
  var buildSourceFileHashId = (packageName, sourceCommit) => sha256(`pkg:${packageName}:${sourceCommit ?? "unknown"}`);
13651
+ var buildPackageHashId = (packageName, modulePath, version2, description) => hashStable({ packageName, modulePath, version: version2 ?? null, description: description ?? null });
13652
+ var buildEdgeHashId = (edge2, packageName, modulePath, versionLabel) => hashStable({
13653
+ packageName,
13654
+ modulePath,
13655
+ type: edge2.type,
13656
+ from: edge2.from,
13657
+ to: edge2.to,
13658
+ isExternal: edge2.isExternal,
13659
+ grounding: edge2.grounding,
13660
+ source: edge2.source,
13661
+ line: edge2.line ?? null,
13662
+ versionLabel
13663
+ });
13579
13664
  var buildDigestData = (input) => {
13580
13665
  const digest = generateDigest(input.extraction);
13581
13666
  const moduleContentHash = hashStable(digest);
13582
13667
  const dirty = input.dirty ?? false;
13668
+ const rawVersionLabel = input.versionLabel !== undefined ? input.versionLabel : input.extraction.package.version;
13669
+ const version2 = resolveVersion(rawVersionLabel, input.versionSource);
13670
+ const doc = normalizeDoc(input.moduleDoc);
13583
13671
  return {
13584
13672
  hash_id: buildHashId(input.extraction.package.name, input.dirCommit, moduleContentHash, dirty),
13585
13673
  module_name: input.moduleName,
13586
13674
  module_path: input.modulePath,
13587
13675
  package_name: input.extraction.package.name,
13588
13676
  dir_commit: input.dirCommit,
13589
- version_label: input.versionLabel !== undefined ? input.versionLabel : input.extraction.package.version ?? null,
13677
+ ...version2,
13590
13678
  module_content_hash: moduleContentHash,
13591
13679
  dirty,
13680
+ ...doc ? { doc } : {},
13592
13681
  digest
13593
13682
  };
13594
13683
  };
13595
- var packageRowFor = (result) => ({
13596
- name: result.extraction.package.name,
13597
- kind: result.extraction.package.kind,
13598
- language: result.extraction.package.language,
13599
- modulePath: result.module.path,
13600
- ...result.extraction.package.version ? { version: result.extraction.package.version } : {}
13601
- });
13602
- var edgeRowsFor = (result) => result.extraction.relations.map((edge2) => ({
13684
+ var packageDescriptionFor = (result) => {
13685
+ const packageManifest = result.sourceInfo.manifests.find((manifest) => manifest.type === "package.json");
13686
+ const content = packageManifest?.content;
13687
+ if (!content || typeof content !== "object" || Array.isArray(content))
13688
+ return;
13689
+ return normalizeDoc(content.description);
13690
+ };
13691
+ var packageRowFor = (result) => {
13692
+ const version2 = result.extraction.package.version;
13693
+ const description = packageDescriptionFor(result);
13694
+ return {
13695
+ name: result.extraction.package.name,
13696
+ kind: result.extraction.package.kind,
13697
+ language: result.extraction.package.language,
13698
+ modulePath: result.module.path,
13699
+ hash_id: buildPackageHashId(result.extraction.package.name, result.module.path, version2, description),
13700
+ ...version2 ? { version: version2 } : {},
13701
+ ...description ? { description } : {}
13702
+ };
13703
+ };
13704
+ var edgeRowsFor = (result, versionLabel) => result.extraction.relations.map((edge2) => ({
13603
13705
  ...edge2,
13604
13706
  package: result.extraction.package.name,
13605
- modulePath: result.module.path
13707
+ package_name: result.extraction.package.name,
13708
+ modulePath: result.module.path,
13709
+ module_path: result.module.path,
13710
+ version_label: versionLabel,
13711
+ hash_id: buildEdgeHashId(edge2, result.extraction.package.name, result.module.path, versionLabel)
13606
13712
  }));
13607
13713
  var byteLength = (value) => Buffer.byteLength(value, "utf-8");
13714
+ var edgeSortKey = (edge2) => [
13715
+ edge2.modulePath,
13716
+ edge2.from,
13717
+ edge2.type,
13718
+ edge2.to,
13719
+ edge2.line == null ? "" : String(edge2.line).padStart(12, "0"),
13720
+ edge2.source,
13721
+ edge2.grounding,
13722
+ String(edge2.isExternal),
13723
+ edge2.hash_id
13724
+ ].join("\x00");
13608
13725
  var buildCodeSnapshot = (input) => {
13609
13726
  const capturedAt = input.capturedAt ?? new Date().toISOString();
13610
13727
  const rows = {
@@ -13617,6 +13734,7 @@ var buildCodeSnapshot = (input) => {
13617
13734
  for (const result of input.results) {
13618
13735
  const dirCommit = input.dirCommits?.[result.module.path] ?? result.extraction.meta.commitHash ?? "unknown";
13619
13736
  const versionLabel = input.versionLabels && hasOwn(input.versionLabels, result.module.path) ? input.versionLabels[result.module.path] ?? null : result.extraction.package.version ?? null;
13737
+ const versionSource = input.versionSources && hasOwn(input.versionSources, result.module.path) ? input.versionSources[result.module.path] : undefined;
13620
13738
  const dirty2 = input.dirtyModules?.[result.module.path] ?? false;
13621
13739
  const digestRow = buildDigestData({
13622
13740
  moduleName: result.module.name,
@@ -13624,11 +13742,13 @@ var buildCodeSnapshot = (input) => {
13624
13742
  extraction: result.extraction,
13625
13743
  dirCommit,
13626
13744
  versionLabel,
13745
+ ...versionSource ? { versionSource } : {},
13746
+ ...result.moduleDoc ? { moduleDoc: result.moduleDoc } : {},
13627
13747
  dirty: dirty2
13628
13748
  });
13629
13749
  rows.packages.push(packageRowFor(result));
13630
13750
  rows.symbols.push(...flattenSymbols(result.extraction.symbols, result.extraction.package.name, result.module.path));
13631
- rows.edges.push(...edgeRowsFor(result));
13751
+ rows.edges.push(...edgeRowsFor(result, digestRow.version_label));
13632
13752
  rows.digests.push(digestRow);
13633
13753
  rows.sourceFiles.push({
13634
13754
  source_id: input.sourceId,
@@ -13636,6 +13756,7 @@ var buildCodeSnapshot = (input) => {
13636
13756
  hash_id: buildSourceFileHashId(result.extraction.package.name, input.sourceCommit),
13637
13757
  digest_hash_id: digestRow.hash_id,
13638
13758
  version_label: digestRow.version_label,
13759
+ version_source: digestRow.version_source,
13639
13760
  branch: null,
13640
13761
  package_name: result.extraction.package.name,
13641
13762
  module_path: result.module.path
@@ -13643,7 +13764,7 @@ var buildCodeSnapshot = (input) => {
13643
13764
  }
13644
13765
  rows.packages.sort((left, right) => left.modulePath.localeCompare(right.modulePath));
13645
13766
  rows.symbols.sort((left, right) => `${left.modulePath}:${left.name}:${left.file}:${left.line}`.localeCompare(`${right.modulePath}:${right.name}:${right.file}:${right.line}`));
13646
- rows.edges.sort((left, right) => `${left.modulePath}:${left.from}:${left.type}:${left.to}`.localeCompare(`${right.modulePath}:${right.from}:${right.type}:${right.to}`));
13767
+ rows.edges.sort((left, right) => edgeSortKey(left).localeCompare(edgeSortKey(right)));
13647
13768
  rows.digests.sort((left, right) => left.module_path.localeCompare(right.module_path));
13648
13769
  rows.sourceFiles.sort((left, right) => left.module_path.localeCompare(right.module_path));
13649
13770
  const sourceHashInput = {
@@ -13669,6 +13790,14 @@ var buildCodeSnapshot = (input) => {
13669
13790
  version_policy: input.versionPolicy ?? "package-version",
13670
13791
  captured_at: capturedAt
13671
13792
  };
13793
+ const commonVersionLabel = commonVersionField(rows.digests, "version_label");
13794
+ const commonVersionSource = commonVersionField(rows.digests, "version_source");
13795
+ if (commonVersionLabel && commonVersionLabel !== "mixed") {
13796
+ source2.version_label = commonVersionLabel;
13797
+ }
13798
+ if (commonVersionSource) {
13799
+ source2.version_source = commonVersionSource;
13800
+ }
13672
13801
  const files = {
13673
13802
  "source.yaml": manifestText(source2),
13674
13803
  "digests.jsonl": jsonl(rows.digests),
@@ -13689,6 +13818,8 @@ var buildCodeSnapshot = (input) => {
13689
13818
  script_hash: input.scriptHash,
13690
13819
  toolchain: input.toolchain,
13691
13820
  version_policy: source2.version_policy,
13821
+ ...source2.version_label ? { version_label: source2.version_label } : {},
13822
+ ...source2.version_source ? { version_source: source2.version_source } : {},
13692
13823
  snapshot_content_hash: snapshotContentHash,
13693
13824
  ...input.worktreeContentHash ? { worktree_content_hash: input.worktreeContentHash } : {},
13694
13825
  module_count: rows.packages.length,
@@ -14173,6 +14304,25 @@ var normalizeExtractionPaths = (extraction, entryDetection, modulePath, commitHa
14173
14304
  entryDetection: prefixEntryDetectionPaths(entryDetection, modulePath),
14174
14305
  extraction: prefixExtractionPaths(extraction, modulePath, commitHash)
14175
14306
  });
14307
+ var extractLeadingJsDoc = (source2) => {
14308
+ const match = source2.match(/^\s*\/\*\*([\s\S]*?)\*\//u);
14309
+ if (!match?.[1])
14310
+ return;
14311
+ const doc = match[1].replace(/^\s*\* ?/gmu, "").replace(/\r\n?/gu, `
14312
+ `).replace(/[ \t]+$/gmu, "").trim();
14313
+ return doc.length > 0 ? doc : undefined;
14314
+ };
14315
+ var extractModuleDoc = async (entryDetection, fs) => {
14316
+ const entries = [...entryDetection.entries].sort((left, right) => left.path.localeCompare(right.path));
14317
+ for (const entry of entries) {
14318
+ try {
14319
+ const doc = extractLeadingJsDoc(await fs.readFile(entry.path));
14320
+ if (doc)
14321
+ return doc;
14322
+ } catch {}
14323
+ }
14324
+ return;
14325
+ };
14176
14326
  var noModuleError = (modulePath, repoPath) => ({
14177
14327
  module_name: modulePath,
14178
14328
  module_path: modulePath,
@@ -14238,6 +14388,7 @@ var runRepositoryExtraction = async (input) => {
14238
14388
  });
14239
14389
  const entryDetection = await plugin.detectEntries(manifest, fs);
14240
14390
  input.onProgress?.({ phase: "parsing", progress: 20, module_name: module.name, module_path: module.path });
14391
+ const moduleDoc = await extractModuleDoc(entryDetection, fs);
14241
14392
  const rawExtraction = await plugin.extractSymbols(entryDetection.entries, fs);
14242
14393
  const commitHash = input.moduleCommits?.[module.path] ?? input.commitHash ?? rawExtraction.meta.commitHash ?? null;
14243
14394
  const normalized = normalizeExtractionPaths(rawExtraction, entryDetection, module.path, commitHash);
@@ -14246,6 +14397,7 @@ var runRepositoryExtraction = async (input) => {
14246
14397
  module,
14247
14398
  sourceInfo,
14248
14399
  entryDetection: normalized.entryDetection,
14400
+ ...moduleDoc ? { moduleDoc } : {},
14249
14401
  extraction: normalized.extraction
14250
14402
  });
14251
14403
  }
package/index.js CHANGED
@@ -15031,6 +15031,41 @@ function createPathMatcher(rules) {
15031
15031
  const isExcluded = rules.exclude.length > 0 ? import_picomatch.default(rules.exclude, { dot: false }) : () => false;
15032
15032
  return (path) => isIncluded(path) && !isExcluded(path);
15033
15033
  }
15034
+ // ../core/src/utils/version.ts
15035
+ var VERSION_LABEL_REGEX = /^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-(alpha|beta|rc)\.(0|[1-9]\d*))?$/i;
15036
+ function encodePrerelease(channel, sequence) {
15037
+ if (!channel) {
15038
+ return 99;
15039
+ }
15040
+ const index = Number.parseInt(sequence ?? "", 10);
15041
+ if (!Number.isInteger(index) || index <= 0 || index > 29) {
15042
+ return null;
15043
+ }
15044
+ switch (channel.toLowerCase()) {
15045
+ case "alpha":
15046
+ return index;
15047
+ case "beta":
15048
+ return 30 + index;
15049
+ case "rc":
15050
+ return 60 + index;
15051
+ default:
15052
+ return null;
15053
+ }
15054
+ }
15055
+ function encodeVersionLabel(label) {
15056
+ const match = VERSION_LABEL_REGEX.exec(label.trim());
15057
+ if (!match) {
15058
+ return null;
15059
+ }
15060
+ const major = Number.parseInt(match[1] ?? "", 10);
15061
+ const minor = Number.parseInt(match[2] ?? "", 10);
15062
+ const patch = Number.parseInt(match[3] ?? "", 10);
15063
+ const prerelease = encodePrerelease(match[4], match[5]);
15064
+ if (!Number.isInteger(major) || !Number.isInteger(minor) || !Number.isInteger(patch) || prerelease === null) {
15065
+ return null;
15066
+ }
15067
+ return major * 1e6 + minor * 1e4 + patch * 100 + prerelease;
15068
+ }
15034
15069
  // ../core/src/constants.ts
15035
15070
  var SCAN_EXCLUDED_DIRS = new Set([
15036
15071
  ".git",
@@ -15847,6 +15882,25 @@ var normalizeExtractionPaths = (extraction, entryDetection, modulePath, commitHa
15847
15882
  entryDetection: prefixEntryDetectionPaths(entryDetection, modulePath),
15848
15883
  extraction: prefixExtractionPaths(extraction, modulePath, commitHash)
15849
15884
  });
15885
+ var extractLeadingJsDoc = (source2) => {
15886
+ const match = source2.match(/^\s*\/\*\*([\s\S]*?)\*\//u);
15887
+ if (!match?.[1])
15888
+ return;
15889
+ const doc = match[1].replace(/^\s*\* ?/gmu, "").replace(/\r\n?/gu, `
15890
+ `).replace(/[ \t]+$/gmu, "").trim();
15891
+ return doc.length > 0 ? doc : undefined;
15892
+ };
15893
+ var extractModuleDoc = async (entryDetection, fs2) => {
15894
+ const entries = [...entryDetection.entries].sort((left, right) => left.path.localeCompare(right.path));
15895
+ for (const entry of entries) {
15896
+ try {
15897
+ const doc = extractLeadingJsDoc(await fs2.readFile(entry.path));
15898
+ if (doc)
15899
+ return doc;
15900
+ } catch {}
15901
+ }
15902
+ return;
15903
+ };
15850
15904
  var noModuleError = (modulePath, repoPath) => ({
15851
15905
  module_name: modulePath,
15852
15906
  module_path: modulePath,
@@ -15912,6 +15966,7 @@ var runRepositoryExtraction = async (input) => {
15912
15966
  });
15913
15967
  const entryDetection = await plugin.detectEntries(manifest, fs2);
15914
15968
  input.onProgress?.({ phase: "parsing", progress: 20, module_name: module2.name, module_path: module2.path });
15969
+ const moduleDoc = await extractModuleDoc(entryDetection, fs2);
15915
15970
  const rawExtraction = await plugin.extractSymbols(entryDetection.entries, fs2);
15916
15971
  const commitHash = input.moduleCommits?.[module2.path] ?? input.commitHash ?? rawExtraction.meta.commitHash ?? null;
15917
15972
  const normalized = normalizeExtractionPaths(rawExtraction, entryDetection, module2.path, commitHash);
@@ -15920,6 +15975,7 @@ var runRepositoryExtraction = async (input) => {
15920
15975
  module: module2,
15921
15976
  sourceInfo,
15922
15977
  entryDetection: normalized.entryDetection,
15978
+ ...moduleDoc ? { moduleDoc } : {},
15923
15979
  extraction: normalized.extraction
15924
15980
  });
15925
15981
  }
@@ -15927,6 +15983,7 @@ var runRepositoryExtraction = async (input) => {
15927
15983
  };
15928
15984
  // src/codeSnapshot.ts
15929
15985
  var sha256 = (value) => `sha256:${contentHash(value)}`;
15986
+ var FALLBACK_VERSION_LABEL = "0.0.1";
15930
15987
  var stableStringify = (value) => {
15931
15988
  if (value === null || typeof value !== "object")
15932
15989
  return JSON.stringify(value);
@@ -15955,6 +16012,32 @@ var jsonl = (rows) => rows.map((row) => JSON.stringify(row)).join(`
15955
16012
  var manifestText = (value) => JSON.stringify(value, null, 2) + `
15956
16013
  `;
15957
16014
  var hasOwn = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
16015
+ var canonicalizeCodeVersionLabel = (value) => {
16016
+ const trimmed = value.trim();
16017
+ if (!trimmed || encodeVersionLabel(trimmed) === null)
16018
+ return null;
16019
+ return trimmed.replace(/^v/iu, "").replace(/-(alpha|beta|rc)\./iu, (match) => match.toLowerCase());
16020
+ };
16021
+ var normalizeDoc = (value) => {
16022
+ if (typeof value !== "string")
16023
+ return;
16024
+ const normalized = value.replace(/\r\n?/gu, `
16025
+ `).replace(/[ \t]+$/gmu, "").trim();
16026
+ return normalized.length > 0 ? normalized : undefined;
16027
+ };
16028
+ var resolveVersion = (label, source2) => {
16029
+ const canonical = typeof label === "string" ? canonicalizeCodeVersionLabel(label) : null;
16030
+ if (canonical) {
16031
+ return { version_label: canonical, version_source: source2 ?? "package-json" };
16032
+ }
16033
+ return { version_label: FALLBACK_VERSION_LABEL, version_source: "fallback-0.0.1" };
16034
+ };
16035
+ var commonVersionField = (rows, field) => {
16036
+ const values = new Set(rows.map((row) => row[field]));
16037
+ if (values.size === 0)
16038
+ return;
16039
+ return values.size === 1 ? Array.from(values)[0] : "mixed";
16040
+ };
15958
16041
  var commonCommit = (rows) => {
15959
16042
  const commits = new Set(rows.digests.map((row) => row.dir_commit).filter((commit) => commit && commit !== "unknown"));
15960
16043
  return commits.size === 1 ? Array.from(commits)[0] : null;
@@ -15977,7 +16060,8 @@ var metaText = (manifest, source2, rows) => {
15977
16060
  dir_commit: digestByModule.get(row.module_path)?.dir_commit ?? "unknown",
15978
16061
  module_content_hash: digestByModule.get(row.module_path)?.module_content_hash ?? "",
15979
16062
  dirty: digestByModule.get(row.module_path)?.dirty ?? false,
15980
- version_label: row.version_label
16063
+ version_label: row.version_label,
16064
+ version_source: row.version_source
15981
16065
  })),
15982
16066
  snapshot_id: manifest.snapshot_id,
15983
16067
  source_slug: manifest.source_slug,
@@ -15985,6 +16069,8 @@ var metaText = (manifest, source2, rows) => {
15985
16069
  snapshot_content_hash: manifest.snapshot_content_hash,
15986
16070
  toolchain: manifest.toolchain,
15987
16071
  version_policy: source2.version_policy,
16072
+ ...manifest.version_label ? { version_label: manifest.version_label } : {},
16073
+ ...manifest.version_source ? { version_source: manifest.version_source } : {},
15988
16074
  head_commit: manifest.head_commit,
15989
16075
  dirty: manifest.dirty,
15990
16076
  ...manifest.worktree_content_hash ? { worktree_content_hash: manifest.worktree_content_hash } : {}
@@ -15996,7 +16082,14 @@ function flattenSymbols(symbols, packageName, modulePath) {
15996
16082
  const walk = (list) => {
15997
16083
  for (const symbol of list) {
15998
16084
  const { members, ...rest } = symbol;
15999
- out2.push({ ...rest, package: packageName, modulePath });
16085
+ out2.push({
16086
+ ...rest,
16087
+ package: packageName,
16088
+ package_name: packageName,
16089
+ symbol_id: symbol.name,
16090
+ modulePath,
16091
+ module_path: modulePath
16092
+ });
16000
16093
  if (members && members.length > 0)
16001
16094
  walk(members);
16002
16095
  }
@@ -16009,35 +16102,80 @@ var buildHashId = (packageName, dirCommit, moduleContentHash, dirty = false) =>
16009
16102
  return sha256(base);
16010
16103
  };
16011
16104
  var buildSourceFileHashId = (packageName, sourceCommit) => sha256(`pkg:${packageName}:${sourceCommit ?? "unknown"}`);
16105
+ var buildPackageHashId = (packageName, modulePath, version2, description) => hashStable({ packageName, modulePath, version: version2 ?? null, description: description ?? null });
16106
+ var buildEdgeHashId = (edge2, packageName, modulePath, versionLabel) => hashStable({
16107
+ packageName,
16108
+ modulePath,
16109
+ type: edge2.type,
16110
+ from: edge2.from,
16111
+ to: edge2.to,
16112
+ isExternal: edge2.isExternal,
16113
+ grounding: edge2.grounding,
16114
+ source: edge2.source,
16115
+ line: edge2.line ?? null,
16116
+ versionLabel
16117
+ });
16012
16118
  var buildDigestData = (input) => {
16013
16119
  const digest = generateDigest(input.extraction);
16014
16120
  const moduleContentHash = hashStable(digest);
16015
16121
  const dirty = input.dirty ?? false;
16122
+ const rawVersionLabel = input.versionLabel !== undefined ? input.versionLabel : input.extraction.package.version;
16123
+ const version2 = resolveVersion(rawVersionLabel, input.versionSource);
16124
+ const doc = normalizeDoc(input.moduleDoc);
16016
16125
  return {
16017
16126
  hash_id: buildHashId(input.extraction.package.name, input.dirCommit, moduleContentHash, dirty),
16018
16127
  module_name: input.moduleName,
16019
16128
  module_path: input.modulePath,
16020
16129
  package_name: input.extraction.package.name,
16021
16130
  dir_commit: input.dirCommit,
16022
- version_label: input.versionLabel !== undefined ? input.versionLabel : input.extraction.package.version ?? null,
16131
+ ...version2,
16023
16132
  module_content_hash: moduleContentHash,
16024
16133
  dirty,
16134
+ ...doc ? { doc } : {},
16025
16135
  digest
16026
16136
  };
16027
16137
  };
16028
- var packageRowFor = (result) => ({
16029
- name: result.extraction.package.name,
16030
- kind: result.extraction.package.kind,
16031
- language: result.extraction.package.language,
16032
- modulePath: result.module.path,
16033
- ...result.extraction.package.version ? { version: result.extraction.package.version } : {}
16034
- });
16035
- var edgeRowsFor = (result) => result.extraction.relations.map((edge2) => ({
16138
+ var packageDescriptionFor = (result) => {
16139
+ const packageManifest = result.sourceInfo.manifests.find((manifest) => manifest.type === "package.json");
16140
+ const content = packageManifest?.content;
16141
+ if (!content || typeof content !== "object" || Array.isArray(content))
16142
+ return;
16143
+ return normalizeDoc(content.description);
16144
+ };
16145
+ var packageRowFor = (result) => {
16146
+ const version2 = result.extraction.package.version;
16147
+ const description = packageDescriptionFor(result);
16148
+ return {
16149
+ name: result.extraction.package.name,
16150
+ kind: result.extraction.package.kind,
16151
+ language: result.extraction.package.language,
16152
+ modulePath: result.module.path,
16153
+ hash_id: buildPackageHashId(result.extraction.package.name, result.module.path, version2, description),
16154
+ ...version2 ? { version: version2 } : {},
16155
+ ...description ? { description } : {}
16156
+ };
16157
+ };
16158
+ var edgeRowsFor = (result, versionLabel) => result.extraction.relations.map((edge2) => ({
16036
16159
  ...edge2,
16037
16160
  package: result.extraction.package.name,
16038
- modulePath: result.module.path
16161
+ package_name: result.extraction.package.name,
16162
+ modulePath: result.module.path,
16163
+ module_path: result.module.path,
16164
+ version_label: versionLabel,
16165
+ hash_id: buildEdgeHashId(edge2, result.extraction.package.name, result.module.path, versionLabel)
16039
16166
  }));
16040
16167
  var byteLength = (value) => Buffer.byteLength(value, "utf-8");
16168
+ var edgeSortKey = (edge2) => [
16169
+ edge2.modulePath,
16170
+ edge2.from,
16171
+ edge2.type,
16172
+ edge2.to,
16173
+ edge2.line == null ? "" : String(edge2.line).padStart(12, "0"),
16174
+ edge2.source,
16175
+ edge2.grounding,
16176
+ String(edge2.isExternal),
16177
+ edge2.hash_id
16178
+ ].join("\x00");
16041
16179
  var buildCodeSnapshot = (input) => {
16042
16180
  const capturedAt = input.capturedAt ?? new Date().toISOString();
16043
16181
  const rows = {
@@ -16050,6 +16188,7 @@ var buildCodeSnapshot = (input) => {
16050
16188
  for (const result of input.results) {
16051
16189
  const dirCommit = input.dirCommits?.[result.module.path] ?? result.extraction.meta.commitHash ?? "unknown";
16052
16190
  const versionLabel = input.versionLabels && hasOwn(input.versionLabels, result.module.path) ? input.versionLabels[result.module.path] ?? null : result.extraction.package.version ?? null;
16191
+ const versionSource = input.versionSources && hasOwn(input.versionSources, result.module.path) ? input.versionSources[result.module.path] : undefined;
16053
16192
  const dirty2 = input.dirtyModules?.[result.module.path] ?? false;
16054
16193
  const digestRow = buildDigestData({
16055
16194
  moduleName: result.module.name,
@@ -16057,11 +16196,13 @@ var buildCodeSnapshot = (input) => {
16057
16196
  extraction: result.extraction,
16058
16197
  dirCommit,
16059
16198
  versionLabel,
16199
+ ...versionSource ? { versionSource } : {},
16200
+ ...result.moduleDoc ? { moduleDoc: result.moduleDoc } : {},
16060
16201
  dirty: dirty2
16061
16202
  });
16062
16203
  rows.packages.push(packageRowFor(result));
16063
16204
  rows.symbols.push(...flattenSymbols(result.extraction.symbols, result.extraction.package.name, result.module.path));
16064
- rows.edges.push(...edgeRowsFor(result));
16205
+ rows.edges.push(...edgeRowsFor(result, digestRow.version_label));
16065
16206
  rows.digests.push(digestRow);
16066
16207
  rows.sourceFiles.push({
16067
16208
  source_id: input.sourceId,
@@ -16069,6 +16210,7 @@ var buildCodeSnapshot = (input) => {
16069
16210
  hash_id: buildSourceFileHashId(result.extraction.package.name, input.sourceCommit),
16070
16211
  digest_hash_id: digestRow.hash_id,
16071
16212
  version_label: digestRow.version_label,
16213
+ version_source: digestRow.version_source,
16072
16214
  branch: null,
16073
16215
  package_name: result.extraction.package.name,
16074
16216
  module_path: result.module.path
@@ -16076,7 +16218,7 @@ var buildCodeSnapshot = (input) => {
16076
16218
  }
16077
16219
  rows.packages.sort((left, right) => left.modulePath.localeCompare(right.modulePath));
16078
16220
  rows.symbols.sort((left, right) => `${left.modulePath}:${left.name}:${left.file}:${left.line}`.localeCompare(`${right.modulePath}:${right.name}:${right.file}:${right.line}`));
16079
- rows.edges.sort((left, right) => `${left.modulePath}:${left.from}:${left.type}:${left.to}`.localeCompare(`${right.modulePath}:${right.from}:${right.type}:${right.to}`));
16221
+ rows.edges.sort((left, right) => edgeSortKey(left).localeCompare(edgeSortKey(right)));
16080
16222
  rows.digests.sort((left, right) => left.module_path.localeCompare(right.module_path));
16081
16223
  rows.sourceFiles.sort((left, right) => left.module_path.localeCompare(right.module_path));
16082
16224
  const sourceHashInput = {
@@ -16102,6 +16244,14 @@ var buildCodeSnapshot = (input) => {
16102
16244
  version_policy: input.versionPolicy ?? "package-version",
16103
16245
  captured_at: capturedAt
16104
16246
  };
16247
+ const commonVersionLabel = commonVersionField(rows.digests, "version_label");
16248
+ const commonVersionSource = commonVersionField(rows.digests, "version_source");
16249
+ if (commonVersionLabel && commonVersionLabel !== "mixed") {
16250
+ source2.version_label = commonVersionLabel;
16251
+ }
16252
+ if (commonVersionSource) {
16253
+ source2.version_source = commonVersionSource;
16254
+ }
16105
16255
  const files = {
16106
16256
  "source.yaml": manifestText(source2),
16107
16257
  "digests.jsonl": jsonl(rows.digests),
@@ -16122,6 +16272,8 @@ var buildCodeSnapshot = (input) => {
16122
16272
  script_hash: input.scriptHash,
16123
16273
  toolchain: input.toolchain,
16124
16274
  version_policy: source2.version_policy,
16275
+ ...source2.version_label ? { version_label: source2.version_label } : {},
16276
+ ...source2.version_source ? { version_source: source2.version_source } : {},
16125
16277
  snapshot_content_hash: snapshotContentHash,
16126
16278
  ...input.worktreeContentHash ? { worktree_content_hash: input.worktreeContentHash } : {},
16127
16279
  module_count: rows.packages.length,
@@ -16445,8 +16597,11 @@ export {
16445
16597
  detectModuleAt,
16446
16598
  createModuleFileSystem,
16447
16599
  codeExtractRunnerInputSchema,
16600
+ canonicalizeCodeVersionLabel,
16448
16601
  buildSourceFileHashId,
16602
+ buildPackageHashId,
16449
16603
  buildHashId,
16604
+ buildEdgeHashId,
16450
16605
  buildDigestData,
16451
16606
  buildCodeSnapshot,
16452
16607
  SCAN_EXCLUDED_DIRS,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@c4a/extract",
3
- "version": "0.5.29-beta.21",
3
+ "version": "0.5.29-beta.29",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "c4a-extract-code": "./bin/c4a-extract-code.js"