@c4a/extract-go 0.7.5 → 0.7.9

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.
Files changed (2) hide show
  1. package/index.js +128 -23
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -11444,15 +11444,21 @@ function replaceWithCount(value, pattern, replacement, count) {
11444
11444
  return replacement(...args.slice(0, -2));
11445
11445
  });
11446
11446
  }
11447
+ var SECRET_TEXT_KEY = "(?:[A-Za-z0-9_.-]*(?:password|passwd|pwd|secret|token|credential|cookie)[A-Za-z0-9_.-]*|api[-_]?key|access[-_]?(?:key|token)|private[-_]?key|client[-_]?secret|authorization)";
11448
+ var SECRET_TEXT_ASSIGNMENT = `(?:=\\s*|:\\s+(?=\\S)|:\\s*(?=["']))`;
11449
+ var AUTHORIZATION_TEXT_PATTERN = new RegExp(`(\\bauthorization\\s*:\\s*(?:bearer|basic)\\s+)` + `(?!${escapeRegExp(INDEXER_OUTPUT_REDACTION_MARKER)})[^\\s,;]+`, "giu");
11450
+ var QUERY_SECRET_TEXT_PATTERN = new RegExp(`([?&](?:access_token|refresh_token|api_key|password|secret)=)` + `(?!${escapeRegExp(INDEXER_OUTPUT_REDACTION_MARKER)})[^&#\\s]+`, "giu");
11451
+ var ASSIGNMENT_SECRET_TEXT_PATTERN = new RegExp(`((?:["']?${SECRET_TEXT_KEY}["']?)\\s*${SECRET_TEXT_ASSIGNMENT})` + `(?!["']?${escapeRegExp(INDEXER_OUTPUT_REDACTION_MARKER)})` + `(?:"(?:\\\\.|[^"])*"|'(?:\\\\.|[^'])*'|[^\\s,;}\\]]+)`, "giu");
11447
11452
  function redactKnownText(value, count) {
11453
+ if (!value.includes(":") && !value.includes("=") && !value.includes("-----BEGIN ")) {
11454
+ return value;
11455
+ }
11448
11456
  let output = value;
11449
11457
  output = replaceWithCount(output, /-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |OPENSSH )?PRIVATE KEY-----/gu, INDEXER_OUTPUT_REDACTION_MARKER, count);
11450
- output = replaceWithCount(output, new RegExp(`(\\bauthorization\\s*:\\s*(?:bearer|basic)\\s+)` + `(?!${escapeRegExp(INDEXER_OUTPUT_REDACTION_MARKER)})[^\\s,;]+`, "giu"), (_match, prefix) => `${prefix}${INDEXER_OUTPUT_REDACTION_MARKER}`, count);
11458
+ output = replaceWithCount(output, AUTHORIZATION_TEXT_PATTERN, (_match, prefix) => `${prefix}${INDEXER_OUTPUT_REDACTION_MARKER}`, count);
11451
11459
  output = replaceWithCount(output, /([a-z][a-z0-9+.-]*:\/\/)[^\s/@:]+:[^\s/@]+@/giu, (_match, prefix) => `${prefix}${INDEXER_OUTPUT_REDACTION_MARKER}@`, count);
11452
- output = replaceWithCount(output, new RegExp(`([?&](?:access_token|refresh_token|api_key|password|secret)=)` + `(?!${escapeRegExp(INDEXER_OUTPUT_REDACTION_MARKER)})[^&#\\s]+`, "giu"), (_match, prefix) => `${prefix}${INDEXER_OUTPUT_REDACTION_MARKER}`, count);
11453
- const key = "(?:[A-Za-z0-9_.-]*(?:password|passwd|pwd|secret|token|credential|cookie)[A-Za-z0-9_.-]*|api[-_]?key|access[-_]?(?:key|token)|private[-_]?key|client[-_]?secret|authorization)";
11454
- const assignment = `(?:=\\s*|:\\s+(?=\\S)|:\\s*(?=["']))`;
11455
- output = replaceWithCount(output, new RegExp(`((?:["']?${key}["']?)\\s*${assignment})` + `(?!["']?${escapeRegExp(INDEXER_OUTPUT_REDACTION_MARKER)})` + `(?:"(?:\\\\.|[^"])*"|'(?:\\\\.|[^'])*'|[^\\s,;}\\]]+)`, "giu"), (_match, prefix) => `${prefix}"${INDEXER_OUTPUT_REDACTION_MARKER}"`, count);
11460
+ output = replaceWithCount(output, QUERY_SECRET_TEXT_PATTERN, (_match, prefix) => `${prefix}${INDEXER_OUTPUT_REDACTION_MARKER}`, count);
11461
+ output = replaceWithCount(output, ASSIGNMENT_SECRET_TEXT_PATTERN, (_match, prefix) => `${prefix}"${INDEXER_OUTPUT_REDACTION_MARKER}"`, count);
11456
11462
  return output;
11457
11463
  }
11458
11464
  function redactBlockedText(value, blocked, count) {
@@ -12099,6 +12105,44 @@ function functionSignature(node2) {
12099
12105
  function symbolId(filePath, kind, qualifiedName) {
12100
12106
  return `go:${filePath}#${kind}:${qualifiedName}`;
12101
12107
  }
12108
+ function declaredParameters(node2) {
12109
+ if (node2 === null)
12110
+ return [];
12111
+ if (node2.type !== "parameter_list")
12112
+ return [{ name: "", type: node2.text, optional: false, rest: false }];
12113
+ return node2.namedChildren.flatMap((parameter) => {
12114
+ const type = parameter.childForFieldName("type");
12115
+ if (type === null)
12116
+ return [];
12117
+ const names = parameter.namedChildren.filter((child) => child.type === "identifier" && child.id !== type.id);
12118
+ const rest = parameter.type === "variadic_parameter_declaration";
12119
+ return (names.length === 0 ? [""] : names.map((name) => name.text)).map((name) => ({
12120
+ name,
12121
+ type: type.text,
12122
+ optional: rest,
12123
+ rest
12124
+ }));
12125
+ });
12126
+ }
12127
+ function declaredFields(node2, filePath) {
12128
+ const list = node2.namedChildren.find((child) => child.type === "field_declaration_list");
12129
+ return (list?.namedChildren ?? []).flatMap((field) => {
12130
+ if (field.type !== "field_declaration")
12131
+ return [];
12132
+ const type = field.childForFieldName("type");
12133
+ if (type === null)
12134
+ return [];
12135
+ const names = field.namedChildren.filter((child) => child.type === "field_identifier");
12136
+ const tag = field.childForFieldName("tag")?.text;
12137
+ return (names.length === 0 ? [type.text] : names.map((name) => name.text)).map((name) => ({
12138
+ name,
12139
+ type: type.text,
12140
+ embedded: names.length === 0,
12141
+ location: locationFor(filePath, field),
12142
+ ...tag === undefined ? {} : { tag }
12143
+ }));
12144
+ });
12145
+ }
12102
12146
  function extractSymbols(root, filePath, packageName, exportedOnly) {
12103
12147
  const symbols = [];
12104
12148
  for (const node2 of root.namedChildren) {
@@ -12119,6 +12163,8 @@ function extractSymbols(root, filePath, packageName, exportedOnly) {
12119
12163
  ...receiver ? { receiver } : {},
12120
12164
  exported: isExported(name),
12121
12165
  signature: functionSignature(node2),
12166
+ parameters: declaredParameters(node2.childForFieldName("parameters")),
12167
+ results: declaredParameters(node2.childForFieldName("result")),
12122
12168
  ...doc ? { doc } : {},
12123
12169
  location: locationFor(filePath, node2)
12124
12170
  });
@@ -12140,6 +12186,7 @@ function extractSymbols(root, filePath, packageName, exportedOnly) {
12140
12186
  package: packageName,
12141
12187
  exported: isExported(name),
12142
12188
  signature: compact(`type ${name} ${typeNode.text}`),
12189
+ ...kind2 === "struct" ? { fields: declaredFields(typeNode, filePath) } : {},
12143
12190
  ...doc ? { doc } : {},
12144
12191
  location: locationFor(filePath, spec)
12145
12192
  });
@@ -12189,7 +12236,7 @@ function unquoteGoString(value) {
12189
12236
  return trimmed.slice(1, -1);
12190
12237
  }
12191
12238
  }
12192
- function extractImports(root) {
12239
+ function extractImports(root, filePath) {
12193
12240
  const imports = [];
12194
12241
  for (const spec of descendants(root, "import_spec")) {
12195
12242
  const pathNode = spec.childForFieldName("path") ?? spec.namedChildren.find((child) => child.type.endsWith("string_literal"));
@@ -12198,7 +12245,7 @@ function extractImports(root) {
12198
12245
  continue;
12199
12246
  const explicitAlias = spec.childForFieldName("name")?.text;
12200
12247
  const alias = explicitAlias && explicitAlias !== "." && explicitAlias !== "_" ? explicitAlias : importPath.split("/").at(-1) ?? importPath;
12201
- imports.push({ alias, path: importPath });
12248
+ imports.push({ alias, path: importPath, location: locationFor(filePath, spec) });
12202
12249
  }
12203
12250
  return imports.sort((left, right) => left.alias.localeCompare(right.alias) || left.path.localeCompare(right.path));
12204
12251
  }
@@ -12318,20 +12365,24 @@ function indexGoSource(source, filePath, options = {}) {
12318
12365
  const tree = parser.parse(source);
12319
12366
  if (!tree)
12320
12367
  throw new Error(`Go parser returned no syntax tree for ${filePath}`);
12321
- const root = tree.rootNode;
12322
- const packageName = descendants(root, "package_identifier")[0]?.text ?? "unknown";
12323
- const imports = extractImports(root);
12324
- const relations = extractCallsAndRoutes(root, filePath, imports);
12325
- return {
12326
- path: filePath,
12327
- package: packageName,
12328
- imports,
12329
- symbols: extractSymbols(root, filePath, packageName, options.exportedOnly ?? false),
12330
- calls: relations.calls,
12331
- routes: relations.routes,
12332
- parseErrors: countParseErrors(root),
12333
- lines: source.length === 0 ? 0 : source.split(/\r\n|\r|\n/u).length
12334
- };
12368
+ try {
12369
+ const root = tree.rootNode;
12370
+ const packageName = descendants(root, "package_identifier")[0]?.text ?? "unknown";
12371
+ const imports = extractImports(root, filePath);
12372
+ const relations = extractCallsAndRoutes(root, filePath, imports);
12373
+ return {
12374
+ path: filePath,
12375
+ package: packageName,
12376
+ imports,
12377
+ symbols: extractSymbols(root, filePath, packageName, options.exportedOnly ?? false),
12378
+ calls: relations.calls,
12379
+ routes: relations.routes,
12380
+ parseErrors: countParseErrors(root),
12381
+ lines: source.length === 0 ? 0 : source.split(/\r\n|\r|\n/u).length
12382
+ };
12383
+ } finally {
12384
+ tree.delete();
12385
+ }
12335
12386
  }
12336
12387
 
12337
12388
  // src/plugin.ts
@@ -12365,6 +12416,18 @@ function symbolInfo(filePath, symbol) {
12365
12416
  line: symbol.location.startLine,
12366
12417
  endLine: symbol.location.endLine,
12367
12418
  signature: symbol.signature,
12419
+ ...symbol.parameters === undefined ? {} : { params: symbol.parameters },
12420
+ ...symbol.results === undefined ? {} : { returnType: symbol.results.map((item) => item.type).join(", ") || null },
12421
+ ...symbol.fields === undefined ? {} : { members: symbol.fields.map((field) => ({
12422
+ name: field.name,
12423
+ kind: "prop" /* Prop */,
12424
+ visibility: /^[A-Z]/u.test(field.name) ? "exported" /* Exported */ : "internal" /* Internal */,
12425
+ file: filePath,
12426
+ line: field.location.startLine,
12427
+ endLine: field.location.endLine,
12428
+ typeAnnotation: field.type,
12429
+ ...field.tag === undefined ? {} : { doc: field.tag }
12430
+ })) },
12368
12431
  ...symbol.doc ? { doc: symbol.doc } : {}
12369
12432
  };
12370
12433
  }
@@ -12432,12 +12495,26 @@ class GoPlugin {
12432
12495
  const indexed = indexGoSource(source, entry.path, { exportedOnly: false });
12433
12496
  files.push({ path: entry.path, language: "go", lines: indexed.lines });
12434
12497
  symbols.push(...indexed.symbols.map((symbol) => symbolInfo(entry.path, symbol)));
12498
+ for (const imported of indexed.imports) {
12499
+ relations.push({
12500
+ type: "imports" /* Imports */,
12501
+ from: entry.path,
12502
+ file: entry.path,
12503
+ to: imported.path,
12504
+ isExternal: true,
12505
+ grounding: "code" /* Code */,
12506
+ confidence: 1,
12507
+ source: "ast" /* Ast */,
12508
+ ...imported.location === undefined ? {} : { line: imported.location.startLine }
12509
+ });
12510
+ }
12435
12511
  for (const call of indexed.calls) {
12436
12512
  if (!call.enclosingSymbol)
12437
12513
  continue;
12438
12514
  relations.push({
12439
12515
  type: "calls" /* Calls */,
12440
12516
  from: call.enclosingSymbol,
12517
+ file: entry.path,
12441
12518
  to: call.callee,
12442
12519
  isExternal: call.importPath !== undefined,
12443
12520
  grounding: "code" /* Code */,
@@ -12454,7 +12531,14 @@ class GoPlugin {
12454
12531
  file: entry.path,
12455
12532
  line: route.location.startLine,
12456
12533
  endLine: route.location.endLine,
12457
- signature: `${route.method} ${route.path} -> ${route.handler}`
12534
+ signature: `${route.method} ${route.path} -> ${route.handler}`,
12535
+ registration: {
12536
+ kind: "http",
12537
+ method: route.method,
12538
+ key: route.path,
12539
+ handler: route.handler,
12540
+ middleware: route.middleware
12541
+ }
12458
12542
  });
12459
12543
  }
12460
12544
  }
@@ -12595,7 +12679,17 @@ var relationSourceSchema = exports_external.enum([
12595
12679
  var packageKindSchema2 = exports_external.enum(Object.values(PackageKind));
12596
12680
  var symbolParamSchema = exports_external.object({
12597
12681
  name: exports_external.string().min(1),
12598
- type: exports_external.string().min(1).nullable()
12682
+ type: exports_external.string().min(1).nullable(),
12683
+ optional: exports_external.boolean().optional(),
12684
+ rest: exports_external.boolean().optional(),
12685
+ defaultValue: exports_external.string().optional()
12686
+ });
12687
+ var registrationSchema = exports_external.object({
12688
+ kind: exports_external.enum(["http", "schedule", "event"]),
12689
+ key: exports_external.string(),
12690
+ handler: exports_external.string(),
12691
+ method: exports_external.string().optional(),
12692
+ middleware: exports_external.array(exports_external.string())
12599
12693
  });
12600
12694
  var symbolInfoSchema = exports_external.lazy(() => exports_external.object({
12601
12695
  name: exports_external.string().min(1),
@@ -12606,6 +12700,14 @@ var symbolInfoSchema = exports_external.lazy(() => exports_external.object({
12606
12700
  endLine: exports_external.number().int().positive(),
12607
12701
  members: exports_external.array(symbolInfoSchema).optional(),
12608
12702
  params: exports_external.array(symbolParamSchema).optional(),
12703
+ optional: exports_external.boolean().optional(),
12704
+ readonly: exports_external.boolean().optional(),
12705
+ defaultValue: exports_external.string().optional(),
12706
+ typeParameters: exports_external.string().optional(),
12707
+ overloads: exports_external.array(exports_external.string()).optional(),
12708
+ publicEntrypoints: exports_external.array(exports_external.string()).optional(),
12709
+ contractResolution: exports_external.enum(["resolved", "declaration-only"]).optional(),
12710
+ registration: registrationSchema.optional(),
12609
12711
  returnType: exports_external.string().min(1).nullable().optional(),
12610
12712
  typeAnnotation: exports_external.string().min(1).nullable().optional(),
12611
12713
  extends: exports_external.string().min(1).nullable().optional(),
@@ -12620,6 +12722,7 @@ var relationInfoSchema = exports_external.object({
12620
12722
  type: relationTypeSchema,
12621
12723
  from: exports_external.string().min(1),
12622
12724
  to: exports_external.string().min(1),
12725
+ file: exports_external.string().min(1).optional(),
12623
12726
  isExternal: exports_external.boolean(),
12624
12727
  grounding: groundingSchema,
12625
12728
  confidence: exports_external.number().min(0).max(1),
@@ -12900,6 +13003,8 @@ function semanticExtractionPayload(extraction) {
12900
13003
  };
12901
13004
  }
12902
13005
  function relationSourceFile(relation, symbols, filePaths) {
13006
+ if (relation.file !== undefined)
13007
+ return filePaths.has(relation.file) ? relation.file : null;
12903
13008
  if (filePaths.has(relation.from))
12904
13009
  return relation.from;
12905
13010
  const candidates = symbols.filter((symbol) => symbol.name === relation.from);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@c4a/extract-go",
3
- "version": "0.7.5",
3
+ "version": "0.7.9",
4
4
  "type": "module",
5
5
  "description": "Go extraction plugin and structural index for Context",
6
6
  "license": "MIT",