depgraph-core 1.9.1 → 1.9.2

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/depgraph-mcp.js CHANGED
@@ -3263,8 +3263,8 @@ var require_utils = __commonJS({
3263
3263
  }
3264
3264
  return ind;
3265
3265
  }
3266
- function removeDotSegments(path8) {
3267
- let input = path8;
3266
+ function removeDotSegments(path9) {
3267
+ let input = path9;
3268
3268
  const output = [];
3269
3269
  let nextSlash = -1;
3270
3270
  let len = 0;
@@ -3673,8 +3673,8 @@ var require_schemes = __commonJS({
3673
3673
  }
3674
3674
  if (wsComponent.resourceName) {
3675
3675
  const queryIndex = wsComponent.resourceName.indexOf("?");
3676
- const path8 = queryIndex === -1 ? wsComponent.resourceName : wsComponent.resourceName.slice(0, queryIndex);
3677
- wsComponent.path = path8 && path8 !== "/" ? path8 : void 0;
3676
+ const path9 = queryIndex === -1 ? wsComponent.resourceName : wsComponent.resourceName.slice(0, queryIndex);
3677
+ wsComponent.path = path9 && path9 !== "/" ? path9 : void 0;
3678
3678
  wsComponent.query = queryIndex === -1 ? void 0 : wsComponent.resourceName.slice(queryIndex + 1);
3679
3679
  wsComponent.resourceName = void 0;
3680
3680
  }
@@ -7677,8 +7677,8 @@ function getErrorMap() {
7677
7677
 
7678
7678
  // node_modules/zod/v3/helpers/parseUtil.js
7679
7679
  var makeIssue = (params) => {
7680
- const { data, path: path8, errorMaps, issueData } = params;
7681
- const fullPath = [...path8, ...issueData.path || []];
7680
+ const { data, path: path9, errorMaps, issueData } = params;
7681
+ const fullPath = [...path9, ...issueData.path || []];
7682
7682
  const fullIssue = {
7683
7683
  ...issueData,
7684
7684
  path: fullPath
@@ -7794,11 +7794,11 @@ var errorUtil;
7794
7794
 
7795
7795
  // node_modules/zod/v3/types.js
7796
7796
  var ParseInputLazyPath = class {
7797
- constructor(parent, value, path8, key) {
7797
+ constructor(parent, value, path9, key) {
7798
7798
  this._cachedPath = [];
7799
7799
  this.parent = parent;
7800
7800
  this.data = value;
7801
- this._path = path8;
7801
+ this._path = path9;
7802
7802
  this._key = key;
7803
7803
  }
7804
7804
  get path() {
@@ -11435,10 +11435,10 @@ function assignProp(target, prop, value) {
11435
11435
  configurable: true
11436
11436
  });
11437
11437
  }
11438
- function getElementAtPath(obj, path8) {
11439
- if (!path8)
11438
+ function getElementAtPath(obj, path9) {
11439
+ if (!path9)
11440
11440
  return obj;
11441
- return path8.reduce((acc, key) => acc?.[key], obj);
11441
+ return path9.reduce((acc, key) => acc?.[key], obj);
11442
11442
  }
11443
11443
  function promiseAllObject(promisesObj) {
11444
11444
  const keys = Object.keys(promisesObj);
@@ -11758,11 +11758,11 @@ function aborted(x, startIndex = 0) {
11758
11758
  }
11759
11759
  return false;
11760
11760
  }
11761
- function prefixIssues(path8, issues) {
11761
+ function prefixIssues(path9, issues) {
11762
11762
  return issues.map((iss) => {
11763
11763
  var _a;
11764
11764
  (_a = iss).path ?? (_a.path = []);
11765
- iss.path.unshift(path8);
11765
+ iss.path.unshift(path9);
11766
11766
  return iss;
11767
11767
  });
11768
11768
  }
@@ -15173,11 +15173,11 @@ function normalizeObjectSchema(schema) {
15173
15173
  }
15174
15174
  return void 0;
15175
15175
  }
15176
- function getDotPath(path8) {
15177
- if (path8.length === 0) {
15176
+ function getDotPath(path9) {
15177
+ if (path9.length === 0) {
15178
15178
  return "object root";
15179
15179
  }
15180
- return path8.reduce((acc, seg, index) => {
15180
+ return path9.reduce((acc, seg, index) => {
15181
15181
  if (index === 0) {
15182
15182
  return String(seg);
15183
15183
  }
@@ -21546,7 +21546,8 @@ var SUPPORTED_EXTS = /* @__PURE__ */ new Set([
21546
21546
  ".svelte",
21547
21547
  ".dart",
21548
21548
  ".rs",
21549
- ".sql"
21549
+ ".sql",
21550
+ ".prisma"
21550
21551
  ]);
21551
21552
  var MAX_FILE_SIZE = 3e5;
21552
21553
  var MAX_BFS_DEPTH = 10;
@@ -23711,6 +23712,24 @@ function collectCteNames(text) {
23711
23712
  for (const m of text.matchAll(rx)) ctes.add(normIdent(m[1]));
23712
23713
  return ctes;
23713
23714
  }
23715
+ function findMatchingParen(text, openIdx) {
23716
+ let depth = 0;
23717
+ for (let i = openIdx; i < text.length; i++) {
23718
+ if (text[i] === "(") depth++;
23719
+ else if (text[i] === ")") {
23720
+ depth--;
23721
+ if (depth === 0) return i;
23722
+ }
23723
+ }
23724
+ return text.length;
23725
+ }
23726
+ function findStatementEnd(text, start) {
23727
+ const slice = text.slice(start);
23728
+ const match = slice.match(/(?:^|\n)\s*CREATE\s/i);
23729
+ if (!match || match.index == null) return text.length;
23730
+ const offset = match.index === 0 ? 0 : match.index + 1;
23731
+ return start + offset;
23732
+ }
23714
23733
  function collectTableRefs(masked, extraNonTables = /* @__PURE__ */ new Set()) {
23715
23734
  const skip = /* @__PURE__ */ new Set([...NON_TABLES, ...extraNonTables]);
23716
23735
  const refs = [];
@@ -23816,17 +23835,55 @@ function extractEntities12(code, filePath) {
23816
23835
  }
23817
23836
  return entities;
23818
23837
  }
23838
+ var TABLE_HEADER_RX = new RegExp(
23839
+ `\\bCREATE\\s+(?:TEMP(?:ORARY)?\\s+)?TABLE\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?(${QUAL_NAME})`,
23840
+ "gi"
23841
+ );
23842
+ var VIEW_HEADER_RX = new RegExp(
23843
+ `\\bCREATE\\s+(?:OR\\s+(?:REPLACE|ALTER)\\s+)?(?:MATERIALIZED\\s+)?VIEW\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?(${QUAL_NAME})`,
23844
+ "gi"
23845
+ );
23846
+ var ROUTINE_HEADER_RX = new RegExp(
23847
+ `\\bCREATE\\s+(?:OR\\s+(?:REPLACE|ALTER)\\s+)?(?:FUNCTION|PROC(?:EDURE)?)\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?(${QUAL_NAME})`,
23848
+ "gi"
23849
+ );
23819
23850
  function extractImports12(code) {
23820
23851
  const masked = maskSqlComments(code);
23821
- const imports = [];
23822
23852
  const fileBase = import_path3.default.basename(_currentFile, import_path3.default.extname(_currentFile));
23823
- if (!fileBase) return imports;
23824
- const ctes = collectCteNames(masked);
23825
- for (const ref of collectFkRefs(masked)) {
23826
- imports.push({ source: fileBase, names: [ref.name], isLocal: true });
23827
- }
23828
- for (const ref of collectTableRefs(masked, ctes)) {
23829
- imports.push({ source: fileBase, names: [ref.name], isLocal: true });
23853
+ if (!fileBase) return [];
23854
+ const imports = [];
23855
+ function emit(fromEntity, name, relationType) {
23856
+ if (normIdent(name) === normIdent(fromEntity)) return;
23857
+ imports.push({ source: fileBase, names: [name], isLocal: true, fromEntity, relationType });
23858
+ }
23859
+ TABLE_HEADER_RX.lastIndex = 0;
23860
+ for (const m of masked.matchAll(TABLE_HEADER_RX)) {
23861
+ const tableName = m[1].trim();
23862
+ const afterHeader = m.index + m[0].length;
23863
+ let pi = afterHeader;
23864
+ while (pi < masked.length && masked[pi] !== "(" && masked[pi] !== ";") pi++;
23865
+ if (masked[pi] !== "(") continue;
23866
+ const bodyEnd = findMatchingParen(masked, pi);
23867
+ const body = masked.slice(pi + 1, bodyEnd);
23868
+ for (const ref of collectFkRefs(body)) emit(tableName, ref.name, "references");
23869
+ }
23870
+ VIEW_HEADER_RX.lastIndex = 0;
23871
+ for (const m of masked.matchAll(VIEW_HEADER_RX)) {
23872
+ const viewName = m[1].trim();
23873
+ const afterHeader = m.index + m[0].length;
23874
+ const bodyEnd = findStatementEnd(masked, afterHeader);
23875
+ const body = masked.slice(afterHeader, bodyEnd);
23876
+ const ctes = collectCteNames(body);
23877
+ for (const ref of collectTableRefs(body, ctes)) emit(viewName, ref.name, "reads_from");
23878
+ }
23879
+ ROUTINE_HEADER_RX.lastIndex = 0;
23880
+ for (const m of masked.matchAll(ROUTINE_HEADER_RX)) {
23881
+ const routineName = m[1].trim();
23882
+ const afterHeader = m.index + m[0].length;
23883
+ const bodyEnd = findStatementEnd(masked, afterHeader);
23884
+ const body = masked.slice(afterHeader, bodyEnd);
23885
+ const ctes = collectCteNames(body);
23886
+ for (const ref of collectTableRefs(body, ctes)) emit(routineName, ref.name, "reads_from");
23830
23887
  }
23831
23888
  return imports;
23832
23889
  }
@@ -23858,9 +23915,94 @@ var SqlParser = {
23858
23915
  };
23859
23916
  registerParser(SqlParser);
23860
23917
 
23918
+ // src/languages/prisma/extractor.ts
23919
+ var import_path4 = __toESM(require("path"));
23920
+ var PRISMA_SCALARS = /* @__PURE__ */ new Set([
23921
+ "string",
23922
+ "int",
23923
+ "float",
23924
+ "boolean",
23925
+ "datetime",
23926
+ "json",
23927
+ "bytes",
23928
+ "decimal",
23929
+ "bigint",
23930
+ "unsupported"
23931
+ ]);
23932
+ function isScalar(typeName) {
23933
+ return PRISMA_SCALARS.has(typeName.toLowerCase());
23934
+ }
23935
+ function baseType(t) {
23936
+ return t.replace(/[\[\]?]/g, "").trim();
23937
+ }
23938
+ var _currentFile2 = "";
23939
+ function extractEntities13(code, filePath) {
23940
+ _currentFile2 = filePath;
23941
+ const entities = [];
23942
+ const modelRx = /^model\s+(\w+)\s*\{/gm;
23943
+ for (const m of code.matchAll(modelRx)) {
23944
+ const line = code.slice(0, m.index).split("\n").length;
23945
+ entities.push({ name: m[1], type: "model", line, complexity: "low" });
23946
+ }
23947
+ const enumRx = /^enum\s+(\w+)\s*\{/gm;
23948
+ for (const m of code.matchAll(enumRx)) {
23949
+ const line = code.slice(0, m.index).split("\n").length;
23950
+ entities.push({ name: m[1], type: "enum", line, complexity: "low" });
23951
+ }
23952
+ return entities;
23953
+ }
23954
+ function extractImports13(code) {
23955
+ const fileBase = import_path4.default.basename(_currentFile2, import_path4.default.extname(_currentFile2));
23956
+ if (!fileBase) return [];
23957
+ const imports = [];
23958
+ const modelBlockRx = /^model\s+(\w+)\s*\{([^}]*)\}/gms;
23959
+ for (const block of code.matchAll(modelBlockRx)) {
23960
+ const modelName = block[1];
23961
+ const body = block[2];
23962
+ const fieldRx = /^\s*(\w+)\s+(\w[\w[\]?]*)/gm;
23963
+ const seen = /* @__PURE__ */ new Set();
23964
+ for (const field of body.matchAll(fieldRx)) {
23965
+ const rawType = field[2];
23966
+ const typeName = baseType(rawType);
23967
+ if (isScalar(typeName)) continue;
23968
+ if (typeName === modelName) continue;
23969
+ if (seen.has(typeName)) continue;
23970
+ seen.add(typeName);
23971
+ imports.push({
23972
+ source: fileBase,
23973
+ names: [typeName],
23974
+ isLocal: true,
23975
+ fromEntity: modelName,
23976
+ relationType: "relation"
23977
+ });
23978
+ }
23979
+ }
23980
+ return imports;
23981
+ }
23982
+ function extractExports13(code) {
23983
+ const names = [];
23984
+ for (const m of code.matchAll(/^(?:model|enum)\s+(\w+)/gm)) names.push(m[1]);
23985
+ return names;
23986
+ }
23987
+
23988
+ // src/languages/prisma/index.ts
23989
+ var prismaEntityPatterns = [
23990
+ { regex: /^model\s+(\w+)\s*\{/gm, type: "model" },
23991
+ { regex: /^enum\s+(\w+)\s*\{/gm, type: "enum" }
23992
+ ];
23993
+ var PrismaParser = {
23994
+ lang: "prisma",
23995
+ extensions: [".prisma"],
23996
+ extractEntities: extractEntities13,
23997
+ extractImports: extractImports13,
23998
+ extractExports: extractExports13,
23999
+ entityPatterns: prismaEntityPatterns
24000
+ };
24001
+ registerParser(PrismaParser);
24002
+
23861
24003
  // src/stages/collector.ts
23862
24004
  var import_fs = __toESM(require("fs"));
23863
- var import_path4 = __toESM(require("path"));
24005
+ var import_path5 = __toESM(require("path"));
23864
24006
  function collectFiles(dir) {
23865
24007
  const results = [];
23866
24008
  function walk(currentDir) {
@@ -23872,7 +24014,7 @@ function collectFiles(dir) {
23872
24014
  return;
23873
24015
  }
23874
24016
  for (const entry of entries) {
23875
- const fullPath = import_path4.default.join(currentDir, entry);
24017
+ const fullPath = import_path5.default.join(currentDir, entry);
23876
24018
  let stat;
23877
24019
  try {
23878
24020
  stat = import_fs.default.statSync(fullPath);
@@ -23886,7 +24028,7 @@ function collectFiles(dir) {
23886
24028
  }
23887
24029
  continue;
23888
24030
  }
23889
- const ext = import_path4.default.extname(entry);
24031
+ const ext = import_path5.default.extname(entry);
23890
24032
  if (SUPPORTED_EXTS.has(ext) && stat.size < MAX_FILE_SIZE) {
23891
24033
  results.push(fullPath);
23892
24034
  }
@@ -23898,7 +24040,7 @@ function collectFiles(dir) {
23898
24040
 
23899
24041
  // src/stages/parser.ts
23900
24042
  var import_fs2 = __toESM(require("fs"));
23901
- var import_path5 = __toESM(require("path"));
24043
+ var import_path6 = __toESM(require("path"));
23902
24044
  function parseFile(filePath) {
23903
24045
  let code;
23904
24046
  try {
@@ -23907,7 +24049,7 @@ function parseFile(filePath) {
23907
24049
  console.warn(`\u26A0 Cannot read file: ${filePath}`);
23908
24050
  return null;
23909
24051
  }
23910
- const ext = import_path5.default.extname(filePath).toLowerCase();
24052
+ const ext = import_path6.default.extname(filePath).toLowerCase();
23911
24053
  const parser = getLanguageParser(ext);
23912
24054
  if (!parser) return null;
23913
24055
  const isHashCommentLang = [".py", ".rb", ".sh", ".bash", ".ps1"].includes(ext);
@@ -23939,12 +24081,12 @@ function parseFiles(filePaths) {
23939
24081
  }
23940
24082
 
23941
24083
  // src/stages/graph.ts
23942
- var import_path6 = __toESM(require("path"));
24084
+ var import_path7 = __toESM(require("path"));
23943
24085
  function buildGraph(parsedFiles) {
23944
24086
  const nodes = /* @__PURE__ */ new Map();
23945
24087
  const edges = [];
23946
24088
  for (const file of parsedFiles) {
23947
- const fileBase = import_path6.default.basename(file.filePath, import_path6.default.extname(file.filePath));
24089
+ const fileBase = import_path7.default.basename(file.filePath, import_path7.default.extname(file.filePath));
23948
24090
  for (const entity of file.entities) {
23949
24091
  const id = makeId(entity.name, fileBase);
23950
24092
  if (nodes.has(id)) continue;
@@ -23968,7 +24110,7 @@ function buildGraph(parsedFiles) {
23968
24110
  fileMap.set(file.filePath, file);
23969
24111
  }
23970
24112
  for (const file of parsedFiles) {
23971
- const fileBase = import_path6.default.basename(file.filePath, import_path6.default.extname(file.filePath));
24113
+ const fileBase = import_path7.default.basename(file.filePath, import_path7.default.extname(file.filePath));
23972
24114
  for (const imp of file.imports) {
23973
24115
  if (!imp.isLocal) continue;
23974
24116
  const resolvedPath = resolvePath(file.filePath, imp.source, parsedFiles);
@@ -23978,23 +24120,24 @@ function buildGraph(parsedFiles) {
23978
24120
  for (const importedName of imp.names) {
23979
24121
  const targetEntity = targetFile.entities.find((e) => e.name === importedName);
23980
24122
  if (!targetEntity) continue;
23981
- const targetBase = import_path6.default.basename(resolvedPath, import_path6.default.extname(resolvedPath));
24123
+ const targetBase = import_path7.default.basename(resolvedPath, import_path7.default.extname(resolvedPath));
23982
24124
  const toId = makeId(importedName, targetBase);
23983
24125
  if (!nodes.has(toId)) continue;
23984
- const fromEntities = file.entities.length > 0 ? file.entities : [{ name: fileBase, type: "file", line: 0, complexity: "low" }];
24126
+ const edgeType = imp.relationType ?? "imports";
24127
+ const fromEntities = imp.fromEntity ? file.entities.filter((e) => e.name === imp.fromEntity) : file.entities.length > 0 ? file.entities : [{ name: fileBase, type: "file", line: 0, complexity: "low" }];
23985
24128
  for (const fromEntity of fromEntities) {
23986
24129
  const fromId = makeId(fromEntity.name, fileBase);
23987
24130
  if (!nodes.has(fromId)) continue;
23988
24131
  if (fromId === toId) continue;
23989
24132
  const alreadyExists = edges.some(
23990
- (e) => e.from === fromId && e.to === toId && e.type === "imports"
24133
+ (e) => e.from === fromId && e.to === toId && e.type === edgeType
23991
24134
  );
23992
24135
  if (alreadyExists) continue;
23993
24136
  edges.push({
23994
24137
  from: fromId,
23995
24138
  to: toId,
23996
- type: "imports",
23997
- description: `${fromEntity.name} imports ${importedName} from ${import_path6.default.basename(resolvedPath)}`
24139
+ type: edgeType,
24140
+ description: `${fromEntity.name} ${edgeType} ${importedName}`
23998
24141
  });
23999
24142
  const fromNode = nodes.get(fromId);
24000
24143
  const toNode = nodes.get(toId);
@@ -24016,7 +24159,7 @@ function makeId(name, fileBase) {
24016
24159
  return `${cleanName}__${cleanBase}`;
24017
24160
  }
24018
24161
  function resolvePath(fromFile, importSource, allFiles) {
24019
- const fromDir = import_path6.default.dirname(fromFile);
24162
+ const fromDir = import_path7.default.dirname(fromFile);
24020
24163
  let normalizedSource = importSource;
24021
24164
  if (normalizedSource.startsWith("crate::")) {
24022
24165
  normalizedSource = normalizedSource.slice(7).replace(/::/g, "/");
@@ -24025,7 +24168,7 @@ function resolvePath(fromFile, importSource, allFiles) {
24025
24168
  } else if (normalizedSource.startsWith("self::")) {
24026
24169
  normalizedSource = "./" + normalizedSource.slice(6).replace(/::/g, "/");
24027
24170
  }
24028
- const base = import_path6.default.join(fromDir, normalizedSource);
24171
+ const base = import_path7.default.join(fromDir, normalizedSource);
24029
24172
  const candidates = [
24030
24173
  base,
24031
24174
  `${base}.ts`,
@@ -24036,14 +24179,15 @@ function resolvePath(fromFile, importSource, allFiles) {
24036
24179
  `${base}/index.js`,
24037
24180
  `${base}.dart`,
24038
24181
  `${base}.rs`,
24039
- `${base}.sql`
24182
+ `${base}.sql`,
24183
+ `${base}.prisma`
24040
24184
  ];
24041
24185
  for (const candidate of candidates) {
24042
24186
  const normalized = candidate.replace(/\\/g, "/");
24043
24187
  const found = allFiles.find((f) => f.filePath.replace(/\\/g, "/") === normalized);
24044
24188
  if (found) return found.filePath;
24045
24189
  }
24046
- const parentBase = import_path6.default.dirname(base);
24190
+ const parentBase = import_path7.default.dirname(base);
24047
24191
  if (parentBase && parentBase !== base) {
24048
24192
  const parentCandidates = [
24049
24193
  `${parentBase}.rs`,
@@ -24233,7 +24377,7 @@ function emptyReport(targetName, changeDescription, reason) {
24233
24377
 
24234
24378
  // src/stages/gitdiff.ts
24235
24379
  var import_child_process = require("child_process");
24236
- var import_path7 = __toESM(require("path"));
24380
+ var import_path8 = __toESM(require("path"));
24237
24381
  function getChangedEntities(options) {
24238
24382
  const diff = runGitDiff(options);
24239
24383
  if (!diff) return [];
@@ -24325,7 +24469,7 @@ function parseDiff(diff, projectDir) {
24325
24469
  return entities;
24326
24470
  }
24327
24471
  function extractEntityFromContext(context, file) {
24328
- const ext = import_path7.default.extname(file).toLowerCase();
24472
+ const ext = import_path8.default.extname(file).toLowerCase();
24329
24473
  const parser = getLanguageParser(ext);
24330
24474
  if (parser?.entityPatterns) {
24331
24475
  for (const { regex, type } of parser.entityPatterns) {