@c4a/extract 0.6.4 → 0.6.6

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
@@ -25,6 +25,7 @@ interface ExtractionPlugin {
25
25
  id: string;
26
26
  languages: string[];
27
27
  packageManagers: string[];
28
+ manifestTypes?: ManifestInfo["type"][];
28
29
  canHandle(source: SourceInfo): boolean;
29
30
  detectEntries(manifest: ManifestInfo, fs: FileSystem): Promise<EntryDetectionResult>;
30
31
  extractSymbols(entries: EntryFile[], fs: FileSystem): Promise<ExtractionResult>;
@@ -35,6 +36,9 @@ interface ExtractionPlugin {
35
36
  Important constraints:
36
37
 
37
38
  - Plugins read through `FileSystem`; they should not access `node:fs` directly.
39
+ - `manifestTypes` declares which manifest is passed to `detectEntries()`. It is
40
+ optional for a single-manifest module and required when a plugin accepts a
41
+ module containing multiple manifest types.
38
42
  - `detectEntries()` must return package identity, package kind, language, optional version, and entry files.
39
43
  - `extractSymbols()` must return `ExtractionResult` v2 with stable symbols and relations.
40
44
  - `detectEntries()` is called before `extractSymbols()`; plugins may keep per-detection package context between those calls.
@@ -171,6 +175,7 @@ export class PythonPlugin implements ExtractionPlugin {
171
175
  readonly id = "c4a-extract-python";
172
176
  readonly languages = ["python"];
173
177
  readonly packageManagers = ["pip"];
178
+ readonly manifestTypes: ManifestInfo["type"][] = ["pyproject.toml"];
174
179
 
175
180
  canHandle(source: SourceInfo): boolean {
176
181
  return source.manifests.some((manifest) => manifest.type === "pyproject.toml");
@@ -14284,12 +14284,22 @@ var loadSourceInfo = async (modulePath, fs) => {
14284
14284
  content: { raw: await fs.readFile(GO_MOD) }
14285
14285
  });
14286
14286
  }
14287
+ const detectedLanguages = [
14288
+ ...manifests.some((manifest) => manifest.type === GO_MOD) ? ["go"] : [],
14289
+ ...manifests.some((manifest) => manifest.type === PACKAGE_JSON) ? ["typescript"] : []
14290
+ ];
14287
14291
  return {
14288
14292
  path: normalizeRelativePath(modulePath),
14289
14293
  manifests,
14290
- ...manifests.some((manifest) => manifest.type === GO_MOD) ? { language: "go" } : manifests.some((manifest) => manifest.type === PACKAGE_JSON) ? { language: "typescript" } : {}
14294
+ ...detectedLanguages.length === 1 ? { language: detectedLanguages[0] } : {}
14291
14295
  };
14292
14296
  };
14297
+ function manifestForPlugin(source, plugin) {
14298
+ if (plugin.manifestTypes !== undefined) {
14299
+ return source.manifests.find((manifest) => plugin.manifestTypes?.includes(manifest.type));
14300
+ }
14301
+ return source.manifests.length === 1 ? source.manifests[0] : undefined;
14302
+ }
14293
14303
  var prefixSymbolPaths = (symbol, modulePath) => ({
14294
14304
  ...symbol,
14295
14305
  ...symbol.file.trim() ? { file: resolveRepoRelativePath(modulePath, symbol.file) } : {},
@@ -14386,12 +14396,12 @@ var runRepositoryExtraction = async (input) => {
14386
14396
  });
14387
14397
  continue;
14388
14398
  }
14389
- const manifest = sourceInfo.manifests.find((candidate) => candidate.type === PACKAGE_JSON) ?? sourceInfo.manifests[0];
14399
+ const manifest = manifestForPlugin(sourceInfo, plugin);
14390
14400
  if (!manifest) {
14391
14401
  moduleErrors.push({
14392
14402
  module_name: module.name,
14393
14403
  module_path: module.path,
14394
- error: `Module "${module.name}" has no supported manifest for extraction`
14404
+ error: plugin.manifestTypes === undefined && sourceInfo.manifests.length > 1 ? `Extraction plugin "${plugin.id}" must declare manifestTypes for mixed-manifest module "${module.name}"` : `Module "${module.name}" has no manifest supported by extraction plugin "${plugin.id}"`
14395
14405
  });
14396
14406
  continue;
14397
14407
  }
package/index.js CHANGED
@@ -14891,12 +14891,22 @@ var loadSourceInfo = async (modulePath, fs) => {
14891
14891
  content: { raw: await fs.readFile(GO_MOD) }
14892
14892
  });
14893
14893
  }
14894
+ const detectedLanguages = [
14895
+ ...manifests.some((manifest) => manifest.type === GO_MOD) ? ["go"] : [],
14896
+ ...manifests.some((manifest) => manifest.type === PACKAGE_JSON) ? ["typescript"] : []
14897
+ ];
14894
14898
  return {
14895
14899
  path: normalizeRelativePath(modulePath),
14896
14900
  manifests,
14897
- ...manifests.some((manifest) => manifest.type === GO_MOD) ? { language: "go" } : manifests.some((manifest) => manifest.type === PACKAGE_JSON) ? { language: "typescript" } : {}
14901
+ ...detectedLanguages.length === 1 ? { language: detectedLanguages[0] } : {}
14898
14902
  };
14899
14903
  };
14904
+ function manifestForPlugin(source, plugin) {
14905
+ if (plugin.manifestTypes !== undefined) {
14906
+ return source.manifests.find((manifest) => plugin.manifestTypes?.includes(manifest.type));
14907
+ }
14908
+ return source.manifests.length === 1 ? source.manifests[0] : undefined;
14909
+ }
14900
14910
  var prefixSymbolPaths = (symbol, modulePath) => ({
14901
14911
  ...symbol,
14902
14912
  ...symbol.file.trim() ? { file: resolveRepoRelativePath(modulePath, symbol.file) } : {},
@@ -14993,12 +15003,12 @@ var runRepositoryExtraction = async (input) => {
14993
15003
  });
14994
15004
  continue;
14995
15005
  }
14996
- const manifest = sourceInfo.manifests.find((candidate) => candidate.type === PACKAGE_JSON) ?? sourceInfo.manifests[0];
15006
+ const manifest = manifestForPlugin(sourceInfo, plugin);
14997
15007
  if (!manifest) {
14998
15008
  moduleErrors.push({
14999
15009
  module_name: module.name,
15000
15010
  module_path: module.path,
15001
- error: `Module "${module.name}" has no supported manifest for extraction`
15011
+ error: plugin.manifestTypes === undefined && sourceInfo.manifests.length > 1 ? `Extraction plugin "${plugin.id}" must declare manifestTypes for mixed-manifest module "${module.name}"` : `Module "${module.name}" has no manifest supported by extraction plugin "${plugin.id}"`
15002
15012
  });
15003
15013
  continue;
15004
15014
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@c4a/extract",
3
- "version": "0.6.4",
3
+ "version": "0.6.6",
4
4
  "type": "module",
5
5
  "description": "Code extraction engine — Tree-sitter AST parsing and structural analysis",
6
6
  "license": "MIT",