depgraph-core 1.9.0 → 1.9.1

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(path7) {
3267
- let input = path7;
3266
+ function removeDotSegments(path8) {
3267
+ let input = path8;
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 path7 = queryIndex === -1 ? wsComponent.resourceName : wsComponent.resourceName.slice(0, queryIndex);
3677
- wsComponent.path = path7 && path7 !== "/" ? path7 : void 0;
3676
+ const path8 = queryIndex === -1 ? wsComponent.resourceName : wsComponent.resourceName.slice(0, queryIndex);
3677
+ wsComponent.path = path8 && path8 !== "/" ? path8 : 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: path7, errorMaps, issueData } = params;
7681
- const fullPath = [...path7, ...issueData.path || []];
7680
+ const { data, path: path8, errorMaps, issueData } = params;
7681
+ const fullPath = [...path8, ...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, path7, key) {
7797
+ constructor(parent, value, path8, key) {
7798
7798
  this._cachedPath = [];
7799
7799
  this.parent = parent;
7800
7800
  this.data = value;
7801
- this._path = path7;
7801
+ this._path = path8;
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, path7) {
11439
- if (!path7)
11438
+ function getElementAtPath(obj, path8) {
11439
+ if (!path8)
11440
11440
  return obj;
11441
- return path7.reduce((acc, key) => acc?.[key], obj);
11441
+ return path8.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(path7, issues) {
11761
+ function prefixIssues(path8, issues) {
11762
11762
  return issues.map((iss) => {
11763
11763
  var _a;
11764
11764
  (_a = iss).path ?? (_a.path = []);
11765
- iss.path.unshift(path7);
11765
+ iss.path.unshift(path8);
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(path7) {
15177
- if (path7.length === 0) {
15176
+ function getDotPath(path8) {
15177
+ if (path8.length === 0) {
15178
15178
  return "object root";
15179
15179
  }
15180
- return path7.reduce((acc, seg, index) => {
15180
+ return path8.reduce((acc, seg, index) => {
15181
15181
  if (index === 0) {
15182
15182
  return String(seg);
15183
15183
  }
@@ -21545,7 +21545,8 @@ var SUPPORTED_EXTS = /* @__PURE__ */ new Set([
21545
21545
  ".vue",
21546
21546
  ".svelte",
21547
21547
  ".dart",
21548
- ".rs"
21548
+ ".rs",
21549
+ ".sql"
21549
21550
  ]);
21550
21551
  var MAX_FILE_SIZE = 3e5;
21551
21552
  var MAX_BFS_DEPTH = 10;
@@ -23592,9 +23593,274 @@ var RustParser = {
23592
23593
  };
23593
23594
  registerParser(RustParser);
23594
23595
 
23596
+ // src/languages/sql/helpers.ts
23597
+ var NAME_PART = '(?:"(?:[^"\\n]|"")*"|`(?:[^`\\n]|``)*`|\\[(?:[^\\]\\n]|\\]\\])*\\]|[\\w$]+)';
23598
+ var QUAL_NAME = `${NAME_PART}(?:\\s*\\.\\s*${NAME_PART})*`;
23599
+ var ROUTINE_RECOVERY_RX = new RegExp(
23600
+ `\\bCREATE\\s+(?:OR\\s+(?:REPLACE|ALTER)\\s+)?(?:FUNCTION|PROC(?:EDURE)?)\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?(${QUAL_NAME})`,
23601
+ "gi"
23602
+ );
23603
+ function lineOf(text, offset) {
23604
+ return text.slice(0, offset).split("\n").length;
23605
+ }
23606
+ function normIdent(name) {
23607
+ return name.split(".").map((p) => {
23608
+ const s = p.trim();
23609
+ if (s.length >= 2 && (s[0] === s[s.length - 1] && (s[0] === '"' || s[0] === "`") || s[0] === "[" && s[s.length - 1] === "]")) {
23610
+ return s.slice(1, -1).toLowerCase();
23611
+ }
23612
+ return s.toLowerCase();
23613
+ }).join(".");
23614
+ }
23615
+ function maskSqlComments(text) {
23616
+ const out = [];
23617
+ let i = 0;
23618
+ const n = text.length;
23619
+ function blank(upto) {
23620
+ for (const ch of text.slice(i, upto)) out.push(ch === "\n" ? "\n" : " ");
23621
+ return upto;
23622
+ }
23623
+ while (i < n) {
23624
+ const c = text[i];
23625
+ if (c === "'") {
23626
+ let j = i + 1;
23627
+ while (j < n && text[j] !== "\n") {
23628
+ if (text[j] === "'") {
23629
+ if (j + 1 < n && text[j + 1] === "'") {
23630
+ j += 2;
23631
+ continue;
23632
+ }
23633
+ j++;
23634
+ break;
23635
+ }
23636
+ j++;
23637
+ }
23638
+ i = blank(j);
23639
+ } else if (c === '"' || c === "`" || c === "[") {
23640
+ const closer = c === "[" ? "]" : c;
23641
+ let j = i + 1;
23642
+ let closed = false;
23643
+ while (j < n && text[j] !== "\n") {
23644
+ if (text[j] === closer) {
23645
+ if (j + 1 < n && text[j + 1] === closer) {
23646
+ j += 2;
23647
+ continue;
23648
+ }
23649
+ j++;
23650
+ closed = true;
23651
+ break;
23652
+ }
23653
+ j++;
23654
+ }
23655
+ const span = text.slice(i, j);
23656
+ if (closed && !span.includes("--") && !span.includes("/*")) {
23657
+ out.push(span);
23658
+ i = j;
23659
+ } else {
23660
+ let eol = text.indexOf("\n", i);
23661
+ if (eol === -1) eol = n;
23662
+ i = blank(eol);
23663
+ }
23664
+ } else if (c === "-" && i + 1 < n && text[i + 1] === "-") {
23665
+ let j = i;
23666
+ while (j < n && text[j] !== "\n") j++;
23667
+ i = blank(j);
23668
+ } else if (c === "/" && i + 1 < n && text[i + 1] === "*") {
23669
+ let depth = 1;
23670
+ let j = i + 2;
23671
+ while (j < n && depth > 0) {
23672
+ if (text[j] === "/" && j + 1 < n && text[j + 1] === "*") {
23673
+ depth++;
23674
+ j += 2;
23675
+ } else if (text[j] === "*" && j + 1 < n && text[j + 1] === "/") {
23676
+ depth--;
23677
+ j += 2;
23678
+ } else j++;
23679
+ }
23680
+ i = blank(j);
23681
+ } else {
23682
+ out.push(c);
23683
+ i++;
23684
+ }
23685
+ }
23686
+ return out.join("");
23687
+ }
23688
+ var NON_TABLES = /* @__PURE__ */ new Set([
23689
+ "select",
23690
+ "where",
23691
+ "set",
23692
+ "dual",
23693
+ "null",
23694
+ "true",
23695
+ "false",
23696
+ "first",
23697
+ "skip",
23698
+ "rows",
23699
+ "next",
23700
+ "only",
23701
+ "lateral",
23702
+ "values",
23703
+ "inserted",
23704
+ "deleted",
23705
+ "new",
23706
+ "old"
23707
+ ]);
23708
+ function collectCteNames(text) {
23709
+ const ctes = /* @__PURE__ */ new Set();
23710
+ const rx = /\bWITH\s+(?:RECURSIVE\s+)?([\w$]+)\s*(?:\([^()]*\))?\s+AS\s*\(/gi;
23711
+ for (const m of text.matchAll(rx)) ctes.add(normIdent(m[1]));
23712
+ return ctes;
23713
+ }
23714
+ function collectTableRefs(masked, extraNonTables = /* @__PURE__ */ new Set()) {
23715
+ const skip = /* @__PURE__ */ new Set([...NON_TABLES, ...extraNonTables]);
23716
+ const refs = [];
23717
+ const seen = /* @__PURE__ */ new Set();
23718
+ const rx = new RegExp(
23719
+ `\\b(?:FROM|JOIN|INTO|UPDATE)\\s+(${QUAL_NAME})`,
23720
+ "gi"
23721
+ );
23722
+ for (const m of masked.matchAll(rx)) {
23723
+ const raw = m[1];
23724
+ const key = normIdent(raw);
23725
+ if (skip.has(key) || seen.has(key)) continue;
23726
+ seen.add(key);
23727
+ refs.push({ name: raw, line: lineOf(masked, m.index ?? 0) });
23728
+ }
23729
+ return refs;
23730
+ }
23731
+ function collectFkRefs(masked) {
23732
+ const refs = [];
23733
+ const seen = /* @__PURE__ */ new Set();
23734
+ const rx = new RegExp(`\\bREFERENCES\\s+(${QUAL_NAME})`, "gi");
23735
+ for (const m of masked.matchAll(rx)) {
23736
+ const raw = m[1];
23737
+ const key = normIdent(raw);
23738
+ if (seen.has(key)) continue;
23739
+ seen.add(key);
23740
+ refs.push({ name: raw, line: lineOf(masked, m.index ?? 0) });
23741
+ }
23742
+ return refs;
23743
+ }
23744
+
23745
+ // src/languages/sql/patterns.ts
23746
+ var sqlEntityPatterns = [
23747
+ {
23748
+ regex: new RegExp(
23749
+ `\\bCREATE\\s+(?:TEMP(?:ORARY)?\\s+)?TABLE\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?(${QUAL_NAME})`,
23750
+ "gi"
23751
+ ),
23752
+ type: "table"
23753
+ },
23754
+ {
23755
+ regex: new RegExp(
23756
+ `\\bCREATE\\s+(?:OR\\s+(?:REPLACE|ALTER)\\s+)?(?:MATERIALIZED\\s+)?VIEW\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?(${QUAL_NAME})`,
23757
+ "gi"
23758
+ ),
23759
+ type: "view"
23760
+ },
23761
+ {
23762
+ regex: new RegExp(
23763
+ `\\bCREATE\\s+(?:OR\\s+(?:REPLACE|ALTER)\\s+)?FUNCTION\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?(${QUAL_NAME})`,
23764
+ "gi"
23765
+ ),
23766
+ type: "function"
23767
+ },
23768
+ {
23769
+ regex: new RegExp(
23770
+ `\\bCREATE\\s+(?:OR\\s+(?:REPLACE|ALTER)\\s+)?PROC(?:EDURE)?\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?(${QUAL_NAME})`,
23771
+ "gi"
23772
+ ),
23773
+ type: "procedure"
23774
+ },
23775
+ {
23776
+ regex: new RegExp(
23777
+ `\\bCREATE\\s+(?:OR\\s+(?:REPLACE|ALTER)\\s+)?TRIGGER\\s+(?:IF\\s+NOT\\s+EXISTS\\s+)?(${QUAL_NAME})`,
23778
+ "gi"
23779
+ ),
23780
+ type: "trigger"
23781
+ },
23782
+ {
23783
+ regex: new RegExp(
23784
+ `\\bCREATE\\s+(?:UNIQUE\\s+)?INDEX\\s+(?:CONCURRENTLY\\s+)?(?:IF\\s+NOT\\s+EXISTS\\s+)?(${QUAL_NAME})\\s+ON\\b`,
23785
+ "gi"
23786
+ ),
23787
+ type: "index"
23788
+ }
23789
+ ];
23790
+
23791
+ // src/languages/sql/extractor.ts
23792
+ var import_path3 = __toESM(require("path"));
23793
+ var _currentFile = "";
23794
+ function extractEntities12(code, filePath) {
23795
+ _currentFile = filePath;
23796
+ const masked = maskSqlComments(code);
23797
+ const entities = [];
23798
+ const seenNames = /* @__PURE__ */ new Set();
23799
+ for (const { regex, type } of sqlEntityPatterns) {
23800
+ regex.lastIndex = 0;
23801
+ for (const m of masked.matchAll(regex)) {
23802
+ const raw = m[1].trim();
23803
+ const key = normIdent(raw);
23804
+ if (seenNames.has(key)) continue;
23805
+ seenNames.add(key);
23806
+ entities.push({ name: raw, type, line: lineOf(code, m.index ?? 0), complexity: "low" });
23807
+ }
23808
+ }
23809
+ ROUTINE_RECOVERY_RX.lastIndex = 0;
23810
+ for (const m of masked.matchAll(ROUTINE_RECOVERY_RX)) {
23811
+ const raw = m[1].trim();
23812
+ const key = normIdent(raw);
23813
+ if (seenNames.has(key)) continue;
23814
+ seenNames.add(key);
23815
+ entities.push({ name: `${raw}()`, type: "procedure", line: lineOf(code, m.index ?? 0), complexity: "low" });
23816
+ }
23817
+ return entities;
23818
+ }
23819
+ function extractImports12(code) {
23820
+ const masked = maskSqlComments(code);
23821
+ const imports = [];
23822
+ 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 });
23830
+ }
23831
+ return imports;
23832
+ }
23833
+ function extractExports12(code) {
23834
+ const masked = maskSqlComments(code);
23835
+ const names = [];
23836
+ const seen = /* @__PURE__ */ new Set();
23837
+ for (const { regex } of sqlEntityPatterns) {
23838
+ regex.lastIndex = 0;
23839
+ for (const m of masked.matchAll(regex)) {
23840
+ const key = normIdent(m[1].trim());
23841
+ if (!seen.has(key)) {
23842
+ seen.add(key);
23843
+ names.push(m[1].trim());
23844
+ }
23845
+ }
23846
+ }
23847
+ return names;
23848
+ }
23849
+
23850
+ // src/languages/sql/index.ts
23851
+ var SqlParser = {
23852
+ lang: "sql",
23853
+ extensions: [".sql"],
23854
+ extractEntities: extractEntities12,
23855
+ extractImports: extractImports12,
23856
+ extractExports: extractExports12,
23857
+ entityPatterns: sqlEntityPatterns
23858
+ };
23859
+ registerParser(SqlParser);
23860
+
23595
23861
  // src/stages/collector.ts
23596
23862
  var import_fs = __toESM(require("fs"));
23597
- var import_path3 = __toESM(require("path"));
23863
+ var import_path4 = __toESM(require("path"));
23598
23864
  function collectFiles(dir) {
23599
23865
  const results = [];
23600
23866
  function walk(currentDir) {
@@ -23606,7 +23872,7 @@ function collectFiles(dir) {
23606
23872
  return;
23607
23873
  }
23608
23874
  for (const entry of entries) {
23609
- const fullPath = import_path3.default.join(currentDir, entry);
23875
+ const fullPath = import_path4.default.join(currentDir, entry);
23610
23876
  let stat;
23611
23877
  try {
23612
23878
  stat = import_fs.default.statSync(fullPath);
@@ -23620,7 +23886,7 @@ function collectFiles(dir) {
23620
23886
  }
23621
23887
  continue;
23622
23888
  }
23623
- const ext = import_path3.default.extname(entry);
23889
+ const ext = import_path4.default.extname(entry);
23624
23890
  if (SUPPORTED_EXTS.has(ext) && stat.size < MAX_FILE_SIZE) {
23625
23891
  results.push(fullPath);
23626
23892
  }
@@ -23632,7 +23898,7 @@ function collectFiles(dir) {
23632
23898
 
23633
23899
  // src/stages/parser.ts
23634
23900
  var import_fs2 = __toESM(require("fs"));
23635
- var import_path4 = __toESM(require("path"));
23901
+ var import_path5 = __toESM(require("path"));
23636
23902
  function parseFile(filePath) {
23637
23903
  let code;
23638
23904
  try {
@@ -23641,7 +23907,7 @@ function parseFile(filePath) {
23641
23907
  console.warn(`\u26A0 Cannot read file: ${filePath}`);
23642
23908
  return null;
23643
23909
  }
23644
- const ext = import_path4.default.extname(filePath).toLowerCase();
23910
+ const ext = import_path5.default.extname(filePath).toLowerCase();
23645
23911
  const parser = getLanguageParser(ext);
23646
23912
  if (!parser) return null;
23647
23913
  const isHashCommentLang = [".py", ".rb", ".sh", ".bash", ".ps1"].includes(ext);
@@ -23673,12 +23939,12 @@ function parseFiles(filePaths) {
23673
23939
  }
23674
23940
 
23675
23941
  // src/stages/graph.ts
23676
- var import_path5 = __toESM(require("path"));
23942
+ var import_path6 = __toESM(require("path"));
23677
23943
  function buildGraph(parsedFiles) {
23678
23944
  const nodes = /* @__PURE__ */ new Map();
23679
23945
  const edges = [];
23680
23946
  for (const file of parsedFiles) {
23681
- const fileBase = import_path5.default.basename(file.filePath, import_path5.default.extname(file.filePath));
23947
+ const fileBase = import_path6.default.basename(file.filePath, import_path6.default.extname(file.filePath));
23682
23948
  for (const entity of file.entities) {
23683
23949
  const id = makeId(entity.name, fileBase);
23684
23950
  if (nodes.has(id)) continue;
@@ -23702,7 +23968,7 @@ function buildGraph(parsedFiles) {
23702
23968
  fileMap.set(file.filePath, file);
23703
23969
  }
23704
23970
  for (const file of parsedFiles) {
23705
- const fileBase = import_path5.default.basename(file.filePath, import_path5.default.extname(file.filePath));
23971
+ const fileBase = import_path6.default.basename(file.filePath, import_path6.default.extname(file.filePath));
23706
23972
  for (const imp of file.imports) {
23707
23973
  if (!imp.isLocal) continue;
23708
23974
  const resolvedPath = resolvePath(file.filePath, imp.source, parsedFiles);
@@ -23712,7 +23978,7 @@ function buildGraph(parsedFiles) {
23712
23978
  for (const importedName of imp.names) {
23713
23979
  const targetEntity = targetFile.entities.find((e) => e.name === importedName);
23714
23980
  if (!targetEntity) continue;
23715
- const targetBase = import_path5.default.basename(resolvedPath, import_path5.default.extname(resolvedPath));
23981
+ const targetBase = import_path6.default.basename(resolvedPath, import_path6.default.extname(resolvedPath));
23716
23982
  const toId = makeId(importedName, targetBase);
23717
23983
  if (!nodes.has(toId)) continue;
23718
23984
  const fromEntities = file.entities.length > 0 ? file.entities : [{ name: fileBase, type: "file", line: 0, complexity: "low" }];
@@ -23728,7 +23994,7 @@ function buildGraph(parsedFiles) {
23728
23994
  from: fromId,
23729
23995
  to: toId,
23730
23996
  type: "imports",
23731
- description: `${fromEntity.name} imports ${importedName} from ${import_path5.default.basename(resolvedPath)}`
23997
+ description: `${fromEntity.name} imports ${importedName} from ${import_path6.default.basename(resolvedPath)}`
23732
23998
  });
23733
23999
  const fromNode = nodes.get(fromId);
23734
24000
  const toNode = nodes.get(toId);
@@ -23750,7 +24016,7 @@ function makeId(name, fileBase) {
23750
24016
  return `${cleanName}__${cleanBase}`;
23751
24017
  }
23752
24018
  function resolvePath(fromFile, importSource, allFiles) {
23753
- const fromDir = import_path5.default.dirname(fromFile);
24019
+ const fromDir = import_path6.default.dirname(fromFile);
23754
24020
  let normalizedSource = importSource;
23755
24021
  if (normalizedSource.startsWith("crate::")) {
23756
24022
  normalizedSource = normalizedSource.slice(7).replace(/::/g, "/");
@@ -23759,7 +24025,7 @@ function resolvePath(fromFile, importSource, allFiles) {
23759
24025
  } else if (normalizedSource.startsWith("self::")) {
23760
24026
  normalizedSource = "./" + normalizedSource.slice(6).replace(/::/g, "/");
23761
24027
  }
23762
- const base = import_path5.default.join(fromDir, normalizedSource);
24028
+ const base = import_path6.default.join(fromDir, normalizedSource);
23763
24029
  const candidates = [
23764
24030
  base,
23765
24031
  `${base}.ts`,
@@ -23769,14 +24035,15 @@ function resolvePath(fromFile, importSource, allFiles) {
23769
24035
  `${base}/index.ts`,
23770
24036
  `${base}/index.js`,
23771
24037
  `${base}.dart`,
23772
- `${base}.rs`
24038
+ `${base}.rs`,
24039
+ `${base}.sql`
23773
24040
  ];
23774
24041
  for (const candidate of candidates) {
23775
24042
  const normalized = candidate.replace(/\\/g, "/");
23776
24043
  const found = allFiles.find((f) => f.filePath.replace(/\\/g, "/") === normalized);
23777
24044
  if (found) return found.filePath;
23778
24045
  }
23779
- const parentBase = import_path5.default.dirname(base);
24046
+ const parentBase = import_path6.default.dirname(base);
23780
24047
  if (parentBase && parentBase !== base) {
23781
24048
  const parentCandidates = [
23782
24049
  `${parentBase}.rs`,
@@ -23966,7 +24233,7 @@ function emptyReport(targetName, changeDescription, reason) {
23966
24233
 
23967
24234
  // src/stages/gitdiff.ts
23968
24235
  var import_child_process = require("child_process");
23969
- var import_path6 = __toESM(require("path"));
24236
+ var import_path7 = __toESM(require("path"));
23970
24237
  function getChangedEntities(options) {
23971
24238
  const diff = runGitDiff(options);
23972
24239
  if (!diff) return [];
@@ -24058,7 +24325,7 @@ function parseDiff(diff, projectDir) {
24058
24325
  return entities;
24059
24326
  }
24060
24327
  function extractEntityFromContext(context, file) {
24061
- const ext = import_path6.default.extname(file).toLowerCase();
24328
+ const ext = import_path7.default.extname(file).toLowerCase();
24062
24329
  const parser = getLanguageParser(ext);
24063
24330
  if (parser?.entityPatterns) {
24064
24331
  for (const { regex, type } of parser.entityPatterns) {