@dereekb/dbx-components-mcp 13.10.3 → 13.10.4
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/dbx-components-mcp.js +1648 -583
- package/generated/rule-catalog.generated.json +58 -0
- package/package.json +1 -1
package/dbx-components-mcp.js
CHANGED
|
@@ -5,7 +5,7 @@ const require = __createRequire(import.meta.url);
|
|
|
5
5
|
// packages/dbx-components-mcp/package.json
|
|
6
6
|
var package_default = {
|
|
7
7
|
name: "@dereekb/dbx-components-mcp",
|
|
8
|
-
version: "13.10.
|
|
8
|
+
version: "13.10.4",
|
|
9
9
|
type: "module",
|
|
10
10
|
bin: {
|
|
11
11
|
"dbx-components-mcp": "dbx-components-mcp.js"
|
|
@@ -836,10 +836,10 @@ var defaultGlobber = async (input) => {
|
|
|
836
836
|
}
|
|
837
837
|
return matches;
|
|
838
838
|
};
|
|
839
|
-
async function loadPackageName(packagePath,
|
|
839
|
+
async function loadPackageName(packagePath, readFile15) {
|
|
840
840
|
let raw = null;
|
|
841
841
|
try {
|
|
842
|
-
raw = await
|
|
842
|
+
raw = await readFile15(packagePath);
|
|
843
843
|
} catch {
|
|
844
844
|
raw = null;
|
|
845
845
|
}
|
|
@@ -899,15 +899,15 @@ function globToRegex(pattern) {
|
|
|
899
899
|
var DEFAULT_READ_FILE = defaultReadFile;
|
|
900
900
|
var DEFAULT_GLOBBER = defaultGlobber;
|
|
901
901
|
async function buildForgeFieldsManifest(input) {
|
|
902
|
-
const { projectRoot, generator, readFile:
|
|
902
|
+
const { projectRoot, generator, readFile: readFile15 = DEFAULT_READ_FILE, globber = DEFAULT_GLOBBER, now = () => /* @__PURE__ */ new Date() } = input;
|
|
903
903
|
const configPath = resolve(projectRoot, FORGE_FIELDS_SCAN_CONFIG_FILENAME);
|
|
904
904
|
const packagePath = resolve(projectRoot, "package.json");
|
|
905
|
-
const configOutcome = await loadScanConfig(configPath,
|
|
905
|
+
const configOutcome = await loadScanConfig(configPath, readFile15);
|
|
906
906
|
if (configOutcome.kind !== "ok") {
|
|
907
907
|
return configOutcome.outcome;
|
|
908
908
|
}
|
|
909
909
|
const scanSection = configOutcome.section;
|
|
910
|
-
const packageOutcome = await loadPackageName(packagePath,
|
|
910
|
+
const packageOutcome = await loadPackageName(packagePath, readFile15);
|
|
911
911
|
if (packageOutcome.kind !== "ok") {
|
|
912
912
|
return packageOutcome.outcome;
|
|
913
913
|
}
|
|
@@ -920,7 +920,7 @@ async function buildForgeFieldsManifest(input) {
|
|
|
920
920
|
const project = new Project({ useInMemoryFileSystem: true, skipAddingFilesFromTsConfig: true });
|
|
921
921
|
for (const relPath of filePaths) {
|
|
922
922
|
const absolute = resolve(projectRoot, relPath);
|
|
923
|
-
const text = await
|
|
923
|
+
const text = await readFile15(absolute);
|
|
924
924
|
project.createSourceFile(absolute, text, { overwrite: true });
|
|
925
925
|
}
|
|
926
926
|
const extractResult = extractForgeFieldEntries({ project });
|
|
@@ -951,10 +951,10 @@ async function buildForgeFieldsManifest(input) {
|
|
|
951
951
|
}
|
|
952
952
|
return outcome;
|
|
953
953
|
}
|
|
954
|
-
async function loadScanConfig(configPath,
|
|
954
|
+
async function loadScanConfig(configPath, readFile15) {
|
|
955
955
|
let raw = null;
|
|
956
956
|
try {
|
|
957
|
-
raw = await
|
|
957
|
+
raw = await readFile15(configPath);
|
|
958
958
|
} catch {
|
|
959
959
|
raw = null;
|
|
960
960
|
}
|
|
@@ -1020,7 +1020,7 @@ import { resolve as resolve2 } from "node:path";
|
|
|
1020
1020
|
var DEFAULT_READ_FILE2 = (path) => nodeReadFile2(path, "utf-8");
|
|
1021
1021
|
var DEFAULT_WRITE_FILE = (path, data) => nodeWriteFile(path, data, "utf-8");
|
|
1022
1022
|
async function runScanCliBase(input, config) {
|
|
1023
|
-
const { argv, cwd, generator, readFile:
|
|
1023
|
+
const { argv, cwd, generator, readFile: readFile15 = DEFAULT_READ_FILE2, writeFile: writeFile2 = DEFAULT_WRITE_FILE, globber, now, log = console.log, errorLog = console.error } = input;
|
|
1024
1024
|
let result;
|
|
1025
1025
|
const args = parseScanArgs(argv);
|
|
1026
1026
|
if (args.kind === "parse-error") {
|
|
@@ -1036,8 +1036,8 @@ async function runScanCliBase(input, config) {
|
|
|
1036
1036
|
result = { exitCode: 2 };
|
|
1037
1037
|
} else {
|
|
1038
1038
|
const projectRoot = resolve2(cwd, args.project);
|
|
1039
|
-
const outcome = await config.buildManifest({ projectRoot, generator, readFile:
|
|
1040
|
-
result = await handleOutcome({ outcome, args, projectArg: args.project, readFile:
|
|
1039
|
+
const outcome = await config.buildManifest({ projectRoot, generator, readFile: readFile15, globber, now });
|
|
1040
|
+
result = await handleOutcome({ outcome, args, projectArg: args.project, readFile: readFile15, writeFile: writeFile2, log, errorLog, config });
|
|
1041
1041
|
}
|
|
1042
1042
|
return result;
|
|
1043
1043
|
}
|
|
@@ -1091,7 +1091,7 @@ function parseScanArgs(argv) {
|
|
|
1091
1091
|
return result;
|
|
1092
1092
|
}
|
|
1093
1093
|
async function handleOutcome(input) {
|
|
1094
|
-
const { outcome, args, projectArg, readFile:
|
|
1094
|
+
const { outcome, args, projectArg, readFile: readFile15, writeFile: writeFile2, log, errorLog, config } = input;
|
|
1095
1095
|
let result;
|
|
1096
1096
|
if (outcome.kind === "success") {
|
|
1097
1097
|
const finalOutPath = args.out === void 0 ? outcome.outPath : resolve2(outcome.outPath, "..", args.out);
|
|
@@ -1099,7 +1099,7 @@ async function handleOutcome(input) {
|
|
|
1099
1099
|
if (args.check) {
|
|
1100
1100
|
let existing = null;
|
|
1101
1101
|
try {
|
|
1102
|
-
existing = await
|
|
1102
|
+
existing = await readFile15(finalOutPath);
|
|
1103
1103
|
} catch {
|
|
1104
1104
|
existing = null;
|
|
1105
1105
|
}
|
|
@@ -1579,15 +1579,15 @@ var SCAN_CONFIG_FILENAME = "dbx-mcp.scan.json";
|
|
|
1579
1579
|
var DEFAULT_READ_FILE3 = defaultReadFile;
|
|
1580
1580
|
var DEFAULT_GLOBBER2 = defaultGlobber;
|
|
1581
1581
|
async function buildManifest(input) {
|
|
1582
|
-
const { projectRoot, generator, readFile:
|
|
1582
|
+
const { projectRoot, generator, readFile: readFile15 = DEFAULT_READ_FILE3, globber = DEFAULT_GLOBBER2, now = () => /* @__PURE__ */ new Date() } = input;
|
|
1583
1583
|
const configPath = resolve3(projectRoot, SCAN_CONFIG_FILENAME);
|
|
1584
1584
|
const packagePath = resolve3(projectRoot, "package.json");
|
|
1585
|
-
const configOutcome = await loadScanConfig2(configPath,
|
|
1585
|
+
const configOutcome = await loadScanConfig2(configPath, readFile15);
|
|
1586
1586
|
if (configOutcome.kind !== "ok") {
|
|
1587
1587
|
return configOutcome.outcome;
|
|
1588
1588
|
}
|
|
1589
1589
|
const scanConfig = configOutcome.config;
|
|
1590
|
-
const packageOutcome = await loadPackageName(packagePath,
|
|
1590
|
+
const packageOutcome = await loadPackageName(packagePath, readFile15);
|
|
1591
1591
|
if (packageOutcome.kind !== "ok") {
|
|
1592
1592
|
return packageOutcome.outcome;
|
|
1593
1593
|
}
|
|
@@ -1600,7 +1600,7 @@ async function buildManifest(input) {
|
|
|
1600
1600
|
const project = new Project2({ useInMemoryFileSystem: true, skipAddingFilesFromTsConfig: true });
|
|
1601
1601
|
for (const relPath of filePaths) {
|
|
1602
1602
|
const absolute = resolve3(projectRoot, relPath);
|
|
1603
|
-
const text = await
|
|
1603
|
+
const text = await readFile15(absolute);
|
|
1604
1604
|
project.createSourceFile(absolute, text, { overwrite: true });
|
|
1605
1605
|
}
|
|
1606
1606
|
const extracted = extractEntries({ project });
|
|
@@ -1629,10 +1629,10 @@ async function buildManifest(input) {
|
|
|
1629
1629
|
}
|
|
1630
1630
|
return outcome;
|
|
1631
1631
|
}
|
|
1632
|
-
async function loadScanConfig2(configPath,
|
|
1632
|
+
async function loadScanConfig2(configPath, readFile15) {
|
|
1633
1633
|
let raw = null;
|
|
1634
1634
|
try {
|
|
1635
|
-
raw = await
|
|
1635
|
+
raw = await readFile15(configPath);
|
|
1636
1636
|
} catch {
|
|
1637
1637
|
raw = null;
|
|
1638
1638
|
}
|
|
@@ -1704,7 +1704,7 @@ var USAGE2 = [
|
|
|
1704
1704
|
var DEFAULT_READ_FILE4 = (path) => nodeReadFile3(path, "utf-8");
|
|
1705
1705
|
var DEFAULT_WRITE_FILE2 = (path, data) => nodeWriteFile2(path, data, "utf-8");
|
|
1706
1706
|
async function runScanCli(input) {
|
|
1707
|
-
const { argv, cwd, generator, readFile:
|
|
1707
|
+
const { argv, cwd, generator, readFile: readFile15 = DEFAULT_READ_FILE4, writeFile: writeFile2 = DEFAULT_WRITE_FILE2, globber, now, log = console.log, errorLog = console.error } = input;
|
|
1708
1708
|
let result;
|
|
1709
1709
|
const args = parseArgs(argv);
|
|
1710
1710
|
if (args.kind === "parse-error") {
|
|
@@ -1720,8 +1720,8 @@ async function runScanCli(input) {
|
|
|
1720
1720
|
result = { exitCode: 2 };
|
|
1721
1721
|
} else {
|
|
1722
1722
|
const projectRoot = resolve4(cwd, args.project);
|
|
1723
|
-
const outcome = await buildManifest({ projectRoot, generator, readFile:
|
|
1724
|
-
result = await handleOutcome2({ outcome, args, projectArg: args.project, readFile:
|
|
1723
|
+
const outcome = await buildManifest({ projectRoot, generator, readFile: readFile15, globber, now });
|
|
1724
|
+
result = await handleOutcome2({ outcome, args, projectArg: args.project, readFile: readFile15, writeFile: writeFile2, log, errorLog });
|
|
1725
1725
|
}
|
|
1726
1726
|
return result;
|
|
1727
1727
|
}
|
|
@@ -1775,12 +1775,12 @@ function parseArgs(argv) {
|
|
|
1775
1775
|
return result;
|
|
1776
1776
|
}
|
|
1777
1777
|
async function handleSuccessOutcome(input) {
|
|
1778
|
-
const { outcome, args, projectArg, readFile:
|
|
1778
|
+
const { outcome, args, projectArg, readFile: readFile15, writeFile: writeFile2, log, errorLog } = input;
|
|
1779
1779
|
const finalOutPath = args.out === void 0 ? outcome.outPath : resolve4(outcome.outPath, "..", args.out);
|
|
1780
1780
|
const serialized = serializeManifest(outcome.manifest);
|
|
1781
1781
|
let result;
|
|
1782
1782
|
if (args.check) {
|
|
1783
|
-
result = await checkManifest({ finalOutPath, serialized, outcome, projectArg, readFile:
|
|
1783
|
+
result = await checkManifest({ finalOutPath, serialized, outcome, projectArg, readFile: readFile15, log, errorLog });
|
|
1784
1784
|
} else {
|
|
1785
1785
|
await writeFile2(finalOutPath, serialized);
|
|
1786
1786
|
log(`Wrote manifest: ${finalOutPath} (${outcome.manifest.entries.length} entries, ${outcome.scannedFileCount} files scanned)`);
|
|
@@ -1789,10 +1789,10 @@ async function handleSuccessOutcome(input) {
|
|
|
1789
1789
|
return result;
|
|
1790
1790
|
}
|
|
1791
1791
|
async function checkManifest(input) {
|
|
1792
|
-
const { finalOutPath, serialized, outcome, projectArg, readFile:
|
|
1792
|
+
const { finalOutPath, serialized, outcome, projectArg, readFile: readFile15, log, errorLog } = input;
|
|
1793
1793
|
let existing;
|
|
1794
1794
|
try {
|
|
1795
|
-
existing = await
|
|
1795
|
+
existing = await readFile15(finalOutPath);
|
|
1796
1796
|
} catch {
|
|
1797
1797
|
existing = null;
|
|
1798
1798
|
}
|
|
@@ -1987,13 +1987,13 @@ function parseDecoratorInput(property) {
|
|
|
1987
1987
|
}
|
|
1988
1988
|
}
|
|
1989
1989
|
const required = requiredFromDecorator ?? !property.hasQuestionToken();
|
|
1990
|
-
const
|
|
1990
|
+
const type62 = property.getTypeNode()?.getText() ?? "unknown";
|
|
1991
1991
|
const initializer = property.getInitializer();
|
|
1992
1992
|
const defaultValue = initializer === void 0 ? void 0 : initializer.getText();
|
|
1993
1993
|
return {
|
|
1994
1994
|
propertyName,
|
|
1995
1995
|
alias: alias ?? propertyName,
|
|
1996
|
-
type:
|
|
1996
|
+
type: type62,
|
|
1997
1997
|
required,
|
|
1998
1998
|
description: readPropertyDescription(property),
|
|
1999
1999
|
...defaultValue === void 0 ? {} : { defaultValue }
|
|
@@ -2059,22 +2059,22 @@ function parseDecoratorOutput(property) {
|
|
|
2059
2059
|
alias = decoratorArg.getLiteralText();
|
|
2060
2060
|
}
|
|
2061
2061
|
const initializer = property.getInitializer();
|
|
2062
|
-
let
|
|
2062
|
+
let type62 = "unknown";
|
|
2063
2063
|
if (initializer !== void 0 && Node4.isNewExpression(initializer)) {
|
|
2064
2064
|
const typeArgs = initializer.getTypeArguments();
|
|
2065
2065
|
if (typeArgs.length > 0) {
|
|
2066
|
-
|
|
2066
|
+
type62 = typeArgs[0].getText();
|
|
2067
2067
|
}
|
|
2068
2068
|
} else {
|
|
2069
2069
|
const explicit = property.getTypeNode()?.getText();
|
|
2070
2070
|
if (explicit !== void 0) {
|
|
2071
|
-
|
|
2071
|
+
type62 = explicit;
|
|
2072
2072
|
}
|
|
2073
2073
|
}
|
|
2074
2074
|
return {
|
|
2075
2075
|
propertyName,
|
|
2076
2076
|
name: alias ?? propertyName,
|
|
2077
|
-
type:
|
|
2077
|
+
type: type62,
|
|
2078
2078
|
description: readPropertyDescription(property)
|
|
2079
2079
|
};
|
|
2080
2080
|
}
|
|
@@ -2089,7 +2089,7 @@ function parseSignalOutput(property) {
|
|
|
2089
2089
|
}
|
|
2090
2090
|
const propertyName = property.getName();
|
|
2091
2091
|
const typeArgs = initializer.getTypeArguments();
|
|
2092
|
-
const
|
|
2092
|
+
const type62 = typeArgs.length > 0 ? typeArgs[0].getText() : "void";
|
|
2093
2093
|
const args = initializer.getArguments();
|
|
2094
2094
|
let alias;
|
|
2095
2095
|
if (args.length > 0 && Node4.isObjectLiteralExpression(args[0])) {
|
|
@@ -2098,7 +2098,7 @@ function parseSignalOutput(property) {
|
|
|
2098
2098
|
return {
|
|
2099
2099
|
propertyName,
|
|
2100
2100
|
name: alias ?? propertyName,
|
|
2101
|
-
type:
|
|
2101
|
+
type: type62,
|
|
2102
2102
|
description: readPropertyDescription(property)
|
|
2103
2103
|
};
|
|
2104
2104
|
}
|
|
@@ -2485,15 +2485,15 @@ var UI_COMPONENTS_SCAN_CONFIG_FILENAME = "dbx-mcp.scan.json";
|
|
|
2485
2485
|
var DEFAULT_READ_FILE5 = defaultReadFile;
|
|
2486
2486
|
var DEFAULT_GLOBBER3 = defaultGlobber;
|
|
2487
2487
|
async function buildUiComponentsManifest(input) {
|
|
2488
|
-
const { projectRoot, generator, readFile:
|
|
2488
|
+
const { projectRoot, generator, readFile: readFile15 = DEFAULT_READ_FILE5, globber = DEFAULT_GLOBBER3, now = () => /* @__PURE__ */ new Date() } = input;
|
|
2489
2489
|
const configPath = resolve5(projectRoot, UI_COMPONENTS_SCAN_CONFIG_FILENAME);
|
|
2490
2490
|
const packagePath = resolve5(projectRoot, "package.json");
|
|
2491
|
-
const configOutcome = await loadScanConfig3(configPath,
|
|
2491
|
+
const configOutcome = await loadScanConfig3(configPath, readFile15);
|
|
2492
2492
|
if (configOutcome.kind !== "ok") {
|
|
2493
2493
|
return configOutcome.outcome;
|
|
2494
2494
|
}
|
|
2495
2495
|
const scanSection = configOutcome.section;
|
|
2496
|
-
const packageOutcome = await loadPackageName(packagePath,
|
|
2496
|
+
const packageOutcome = await loadPackageName(packagePath, readFile15);
|
|
2497
2497
|
if (packageOutcome.kind !== "ok") {
|
|
2498
2498
|
return packageOutcome.outcome;
|
|
2499
2499
|
}
|
|
@@ -2506,7 +2506,7 @@ async function buildUiComponentsManifest(input) {
|
|
|
2506
2506
|
const project = new Project3({ useInMemoryFileSystem: true, skipAddingFilesFromTsConfig: true });
|
|
2507
2507
|
for (const relPath of filePaths) {
|
|
2508
2508
|
const absolute = resolve5(projectRoot, relPath);
|
|
2509
|
-
const text = await
|
|
2509
|
+
const text = await readFile15(absolute);
|
|
2510
2510
|
project.createSourceFile(absolute, text, { overwrite: true });
|
|
2511
2511
|
}
|
|
2512
2512
|
const extractResult = extractUiEntries({ project });
|
|
@@ -2537,10 +2537,10 @@ async function buildUiComponentsManifest(input) {
|
|
|
2537
2537
|
}
|
|
2538
2538
|
return outcome;
|
|
2539
2539
|
}
|
|
2540
|
-
async function loadScanConfig3(configPath,
|
|
2540
|
+
async function loadScanConfig3(configPath, readFile15) {
|
|
2541
2541
|
let raw = null;
|
|
2542
2542
|
try {
|
|
2543
|
-
raw = await
|
|
2543
|
+
raw = await readFile15(configPath);
|
|
2544
2544
|
} catch {
|
|
2545
2545
|
raw = null;
|
|
2546
2546
|
}
|
|
@@ -2679,11 +2679,11 @@ var DbxMcpConfig = type13({
|
|
|
2679
2679
|
var CONFIG_FILENAME = "dbx-mcp.config.json";
|
|
2680
2680
|
var DEFAULT_READ_FILE6 = (path) => nodeReadFile4(path, "utf-8");
|
|
2681
2681
|
async function findAndLoadConfig(input) {
|
|
2682
|
-
const { cwd, readFile:
|
|
2682
|
+
const { cwd, readFile: readFile15 = DEFAULT_READ_FILE6 } = input;
|
|
2683
2683
|
const configPath = resolve6(cwd, CONFIG_FILENAME);
|
|
2684
2684
|
let raw = null;
|
|
2685
2685
|
try {
|
|
2686
|
-
raw = await
|
|
2686
|
+
raw = await readFile15(configPath);
|
|
2687
2687
|
} catch {
|
|
2688
2688
|
raw = null;
|
|
2689
2689
|
}
|
|
@@ -2948,10 +2948,10 @@ import { readFile as nodeReadFile5 } from "node:fs/promises";
|
|
|
2948
2948
|
import { type as type16 } from "arktype";
|
|
2949
2949
|
var DEFAULT_READ_FILE7 = (path) => nodeReadFile5(path, "utf-8");
|
|
2950
2950
|
var SUPPORTED_VERSION = 1;
|
|
2951
|
-
async function loadFromSource(source,
|
|
2951
|
+
async function loadFromSource(source, readFile15, schema) {
|
|
2952
2952
|
let raw = null;
|
|
2953
2953
|
try {
|
|
2954
|
-
raw = await
|
|
2954
|
+
raw = await readFile15(source.path);
|
|
2955
2955
|
} catch {
|
|
2956
2956
|
raw = null;
|
|
2957
2957
|
}
|
|
@@ -3008,12 +3008,12 @@ function warningSortKey(warning) {
|
|
|
3008
3008
|
return key;
|
|
3009
3009
|
}
|
|
3010
3010
|
async function loadManifestsBase(input, config) {
|
|
3011
|
-
const { sources, readFile:
|
|
3011
|
+
const { sources, readFile: readFile15 = DEFAULT_READ_FILE7 } = input;
|
|
3012
3012
|
const { name, schema, extractIndexValue, buildEntryKey } = config;
|
|
3013
3013
|
const successes = [];
|
|
3014
3014
|
const warnings = [];
|
|
3015
3015
|
for (const source of sources) {
|
|
3016
|
-
const outcome = await loadFromSource(source,
|
|
3016
|
+
const outcome = await loadFromSource(source, readFile15, schema);
|
|
3017
3017
|
if (outcome.kind === "success") {
|
|
3018
3018
|
successes.push({ source, manifest: outcome.manifest });
|
|
3019
3019
|
} else if (isStrictSource(source)) {
|
|
@@ -3117,9 +3117,9 @@ var DEFAULT_BUNDLED_PATHS = () => {
|
|
|
3117
3117
|
return DEFAULT_BUNDLED_FILENAMES.map((name) => resolve7(packageRoot, "generated", name));
|
|
3118
3118
|
};
|
|
3119
3119
|
async function loadActionRegistry(input) {
|
|
3120
|
-
const { cwd, bundledManifestPaths = DEFAULT_BUNDLED_PATHS, readFile:
|
|
3120
|
+
const { cwd, bundledManifestPaths = DEFAULT_BUNDLED_PATHS, readFile: readFile15 } = input;
|
|
3121
3121
|
const bundledSources = bundledManifestPaths().map((path) => ({ origin: "bundled", path }));
|
|
3122
|
-
const configResult = await findAndLoadConfig({ cwd, readFile:
|
|
3122
|
+
const configResult = await findAndLoadConfig({ cwd, readFile: readFile15 });
|
|
3123
3123
|
const externalSources = [];
|
|
3124
3124
|
if (configResult.config !== null && configResult.configPath !== null) {
|
|
3125
3125
|
const baseDir = dirname(configResult.configPath);
|
|
@@ -3133,7 +3133,7 @@ async function loadActionRegistry(input) {
|
|
|
3133
3133
|
let loaderWarnings = [];
|
|
3134
3134
|
const sources = [...bundledSources, ...externalSources];
|
|
3135
3135
|
if (sources.length > 0) {
|
|
3136
|
-
const loaded = await loadActionManifests({ sources, readFile:
|
|
3136
|
+
const loaded = await loadActionManifests({ sources, readFile: readFile15 });
|
|
3137
3137
|
registry = createActionRegistry(loaded);
|
|
3138
3138
|
loaderWarnings = loaded.warnings;
|
|
3139
3139
|
}
|
|
@@ -3333,9 +3333,9 @@ var DEFAULT_BUNDLED_PATHS2 = () => {
|
|
|
3333
3333
|
return DEFAULT_BUNDLED_FILENAMES2.map((name) => resolve8(packageRoot, "generated", name));
|
|
3334
3334
|
};
|
|
3335
3335
|
async function loadFilterRegistry(input) {
|
|
3336
|
-
const { cwd, bundledManifestPaths = DEFAULT_BUNDLED_PATHS2, readFile:
|
|
3336
|
+
const { cwd, bundledManifestPaths = DEFAULT_BUNDLED_PATHS2, readFile: readFile15 } = input;
|
|
3337
3337
|
const bundledSources = bundledManifestPaths().map((path) => ({ origin: "bundled", path }));
|
|
3338
|
-
const configResult = await findAndLoadConfig({ cwd, readFile:
|
|
3338
|
+
const configResult = await findAndLoadConfig({ cwd, readFile: readFile15 });
|
|
3339
3339
|
const externalSources = [];
|
|
3340
3340
|
if (configResult.config !== null && configResult.configPath !== null) {
|
|
3341
3341
|
const baseDir = dirname2(configResult.configPath);
|
|
@@ -3349,7 +3349,7 @@ async function loadFilterRegistry(input) {
|
|
|
3349
3349
|
let loaderWarnings = [];
|
|
3350
3350
|
const sources = [...bundledSources, ...externalSources];
|
|
3351
3351
|
if (sources.length > 0) {
|
|
3352
|
-
const loaded = await loadFilterManifests({ sources, readFile:
|
|
3352
|
+
const loaded = await loadFilterManifests({ sources, readFile: readFile15 });
|
|
3353
3353
|
registry = createFilterRegistry(loaded);
|
|
3354
3354
|
loaderWarnings = loaded.warnings;
|
|
3355
3355
|
}
|
|
@@ -3580,9 +3580,9 @@ var DEFAULT_BUNDLED_PATHS3 = () => {
|
|
|
3580
3580
|
return DEFAULT_BUNDLED_FILENAMES3.map((name) => resolve9(packageRoot, "generated", name));
|
|
3581
3581
|
};
|
|
3582
3582
|
async function loadForgeFieldRegistry(input) {
|
|
3583
|
-
const { cwd, bundledManifestPaths = DEFAULT_BUNDLED_PATHS3, readFile:
|
|
3583
|
+
const { cwd, bundledManifestPaths = DEFAULT_BUNDLED_PATHS3, readFile: readFile15 } = input;
|
|
3584
3584
|
const bundledSources = bundledManifestPaths().map((path) => ({ origin: "bundled", path }));
|
|
3585
|
-
const configResult = await findAndLoadConfig({ cwd, readFile:
|
|
3585
|
+
const configResult = await findAndLoadConfig({ cwd, readFile: readFile15 });
|
|
3586
3586
|
const externalSources = [];
|
|
3587
3587
|
if (configResult.config !== null && configResult.configPath !== null) {
|
|
3588
3588
|
const baseDir = dirname3(configResult.configPath);
|
|
@@ -3596,7 +3596,7 @@ async function loadForgeFieldRegistry(input) {
|
|
|
3596
3596
|
let loaderWarnings = [];
|
|
3597
3597
|
const sources = [...bundledSources, ...externalSources];
|
|
3598
3598
|
if (sources.length > 0) {
|
|
3599
|
-
const loaded = await loadForgeFieldManifests({ sources, readFile:
|
|
3599
|
+
const loaded = await loadForgeFieldManifests({ sources, readFile: readFile15 });
|
|
3600
3600
|
registry = createForgeFieldRegistry(loaded);
|
|
3601
3601
|
loaderWarnings = loaded.warnings;
|
|
3602
3602
|
}
|
|
@@ -3762,9 +3762,9 @@ var DEFAULT_BUNDLED_PATHS4 = () => {
|
|
|
3762
3762
|
return DEFAULT_BUNDLED_FILENAMES4.map((name) => resolve10(packageRoot, "generated", name));
|
|
3763
3763
|
};
|
|
3764
3764
|
async function loadPipeRegistry(input) {
|
|
3765
|
-
const { cwd, bundledManifestPaths = DEFAULT_BUNDLED_PATHS4, readFile:
|
|
3765
|
+
const { cwd, bundledManifestPaths = DEFAULT_BUNDLED_PATHS4, readFile: readFile15 } = input;
|
|
3766
3766
|
const bundledSources = bundledManifestPaths().map((path) => ({ origin: "bundled", path }));
|
|
3767
|
-
const configResult = await findAndLoadConfig({ cwd, readFile:
|
|
3767
|
+
const configResult = await findAndLoadConfig({ cwd, readFile: readFile15 });
|
|
3768
3768
|
const externalSources = [];
|
|
3769
3769
|
if (configResult.config !== null && configResult.configPath !== null) {
|
|
3770
3770
|
const baseDir = dirname4(configResult.configPath);
|
|
@@ -3778,7 +3778,7 @@ async function loadPipeRegistry(input) {
|
|
|
3778
3778
|
let loaderWarnings = [];
|
|
3779
3779
|
const sources = [...bundledSources, ...externalSources];
|
|
3780
3780
|
if (sources.length > 0) {
|
|
3781
|
-
const loaded = await loadPipeManifests({ sources, readFile:
|
|
3781
|
+
const loaded = await loadPipeManifests({ sources, readFile: readFile15 });
|
|
3782
3782
|
registry = createPipeRegistry(loaded);
|
|
3783
3783
|
loaderWarnings = loaded.warnings;
|
|
3784
3784
|
}
|
|
@@ -3882,10 +3882,10 @@ function isCoreTopic(topic) {
|
|
|
3882
3882
|
// packages/dbx-components-mcp/src/manifest/loader.ts
|
|
3883
3883
|
var DEFAULT_READ_FILE8 = (path) => nodeReadFile6(path, "utf-8");
|
|
3884
3884
|
var SUPPORTED_VERSION2 = 1;
|
|
3885
|
-
async function loadFromSource2(source,
|
|
3885
|
+
async function loadFromSource2(source, readFile15) {
|
|
3886
3886
|
let raw = null;
|
|
3887
3887
|
try {
|
|
3888
|
-
raw = await
|
|
3888
|
+
raw = await readFile15(source.path);
|
|
3889
3889
|
} catch {
|
|
3890
3890
|
}
|
|
3891
3891
|
let result;
|
|
@@ -3972,11 +3972,11 @@ function warningSortKey2(warning) {
|
|
|
3972
3972
|
return key;
|
|
3973
3973
|
}
|
|
3974
3974
|
async function loadSemanticTypeManifests(input) {
|
|
3975
|
-
const { sources, readFile:
|
|
3975
|
+
const { sources, readFile: readFile15 = DEFAULT_READ_FILE8 } = input;
|
|
3976
3976
|
const successes = [];
|
|
3977
3977
|
const warnings = [];
|
|
3978
3978
|
for (const source of sources) {
|
|
3979
|
-
const outcome = await loadFromSource2(source,
|
|
3979
|
+
const outcome = await loadFromSource2(source, readFile15);
|
|
3980
3980
|
if (outcome.kind === "success") {
|
|
3981
3981
|
successes.push({ source, manifest: outcome.manifest });
|
|
3982
3982
|
} else if (isStrictSource2(source)) {
|
|
@@ -4073,9 +4073,9 @@ var DEFAULT_BUNDLED_PATHS5 = () => {
|
|
|
4073
4073
|
return DEFAULT_BUNDLED_FILENAMES5.map((name) => resolve11(packageRoot, "generated", name));
|
|
4074
4074
|
};
|
|
4075
4075
|
async function loadSemanticTypeRegistry(input) {
|
|
4076
|
-
const { cwd, bundledManifestPaths = DEFAULT_BUNDLED_PATHS5, readFile:
|
|
4076
|
+
const { cwd, bundledManifestPaths = DEFAULT_BUNDLED_PATHS5, readFile: readFile15 } = input;
|
|
4077
4077
|
const bundledSources = bundledManifestPaths().map((path) => ({ origin: "bundled", path }));
|
|
4078
|
-
const configResult = await findAndLoadConfig({ cwd, readFile:
|
|
4078
|
+
const configResult = await findAndLoadConfig({ cwd, readFile: readFile15 });
|
|
4079
4079
|
const externalSources = [];
|
|
4080
4080
|
if (configResult.config !== null && configResult.configPath !== null) {
|
|
4081
4081
|
const baseDir = dirname5(configResult.configPath);
|
|
@@ -4089,7 +4089,7 @@ async function loadSemanticTypeRegistry(input) {
|
|
|
4089
4089
|
let loaderWarnings = [];
|
|
4090
4090
|
const sources = [...bundledSources, ...externalSources];
|
|
4091
4091
|
if (sources.length > 0) {
|
|
4092
|
-
const loaded = await loadSemanticTypeManifests({ sources, readFile:
|
|
4092
|
+
const loaded = await loadSemanticTypeManifests({ sources, readFile: readFile15 });
|
|
4093
4093
|
registry = createSemanticTypeRegistry(loaded);
|
|
4094
4094
|
loaderWarnings = loaded.warnings;
|
|
4095
4095
|
}
|
|
@@ -4234,9 +4234,9 @@ var DEFAULT_BUNDLED_PATHS6 = () => {
|
|
|
4234
4234
|
return DEFAULT_BUNDLED_FILENAMES6.map((name) => resolve12(packageRoot, "generated", name));
|
|
4235
4235
|
};
|
|
4236
4236
|
async function loadUiComponentRegistry(input) {
|
|
4237
|
-
const { cwd, bundledManifestPaths = DEFAULT_BUNDLED_PATHS6, readFile:
|
|
4237
|
+
const { cwd, bundledManifestPaths = DEFAULT_BUNDLED_PATHS6, readFile: readFile15 } = input;
|
|
4238
4238
|
const bundledSources = bundledManifestPaths().map((path) => ({ origin: "bundled", path }));
|
|
4239
|
-
const configResult = await findAndLoadConfig({ cwd, readFile:
|
|
4239
|
+
const configResult = await findAndLoadConfig({ cwd, readFile: readFile15 });
|
|
4240
4240
|
const externalSources = [];
|
|
4241
4241
|
if (configResult.config !== null && configResult.configPath !== null) {
|
|
4242
4242
|
const baseDir = dirname6(configResult.configPath);
|
|
@@ -4250,7 +4250,7 @@ async function loadUiComponentRegistry(input) {
|
|
|
4250
4250
|
let loaderWarnings = [];
|
|
4251
4251
|
const sources = [...bundledSources, ...externalSources];
|
|
4252
4252
|
if (sources.length > 0) {
|
|
4253
|
-
const loaded = await loadUiComponentManifests({ sources, readFile:
|
|
4253
|
+
const loaded = await loadUiComponentManifests({ sources, readFile: readFile15 });
|
|
4254
4254
|
registry = createUiComponentRegistry(loaded);
|
|
4255
4255
|
loaderWarnings = loaded.warnings;
|
|
4256
4256
|
}
|
|
@@ -7262,7 +7262,7 @@ function createLookupFormTool(config) {
|
|
|
7262
7262
|
}
|
|
7263
7263
|
return lines.join("\n").trimEnd();
|
|
7264
7264
|
}
|
|
7265
|
-
function
|
|
7265
|
+
function run12(rawArgs) {
|
|
7266
7266
|
let args;
|
|
7267
7267
|
try {
|
|
7268
7268
|
args = parseLookupFormArgs(rawArgs);
|
|
@@ -7291,7 +7291,7 @@ function createLookupFormTool(config) {
|
|
|
7291
7291
|
}
|
|
7292
7292
|
const tool = {
|
|
7293
7293
|
definition: DBX_FORM_LOOKUP_TOOL,
|
|
7294
|
-
run:
|
|
7294
|
+
run: run12
|
|
7295
7295
|
};
|
|
7296
7296
|
return tool;
|
|
7297
7297
|
}
|
|
@@ -7480,7 +7480,7 @@ function formatSearchResults(input) {
|
|
|
7480
7480
|
}
|
|
7481
7481
|
function createSearchFormTool(config) {
|
|
7482
7482
|
const { registry } = config;
|
|
7483
|
-
function
|
|
7483
|
+
function run12(rawArgs) {
|
|
7484
7484
|
return runSearchTool(
|
|
7485
7485
|
{
|
|
7486
7486
|
entries: registry.all,
|
|
@@ -7496,7 +7496,7 @@ function createSearchFormTool(config) {
|
|
|
7496
7496
|
}
|
|
7497
7497
|
const tool = {
|
|
7498
7498
|
definition: DBX_FORM_SEARCH_TOOL,
|
|
7499
|
-
run:
|
|
7499
|
+
run: run12
|
|
7500
7500
|
};
|
|
7501
7501
|
return tool;
|
|
7502
7502
|
}
|
|
@@ -8019,7 +8019,7 @@ function renderScaffold(specs, valueTypeName, wrapInSection) {
|
|
|
8019
8019
|
}
|
|
8020
8020
|
function createFormScaffoldTool(config) {
|
|
8021
8021
|
const { registry } = config;
|
|
8022
|
-
function
|
|
8022
|
+
function run12(rawArgs) {
|
|
8023
8023
|
let args;
|
|
8024
8024
|
try {
|
|
8025
8025
|
args = parseScaffoldArgs(rawArgs);
|
|
@@ -8053,7 +8053,7 @@ ${code11}
|
|
|
8053
8053
|
}
|
|
8054
8054
|
const tool = {
|
|
8055
8055
|
definition: DBX_FORM_SCAFFOLD_TOOL,
|
|
8056
|
-
run:
|
|
8056
|
+
run: run12
|
|
8057
8057
|
};
|
|
8058
8058
|
return tool;
|
|
8059
8059
|
}
|
|
@@ -8314,7 +8314,7 @@ function formatNotFound3(normalized, candidates) {
|
|
|
8314
8314
|
}
|
|
8315
8315
|
function createLookupUiTool(input) {
|
|
8316
8316
|
const { registry } = input;
|
|
8317
|
-
const
|
|
8317
|
+
const run12 = (rawArgs) => {
|
|
8318
8318
|
let args;
|
|
8319
8319
|
try {
|
|
8320
8320
|
args = parseLookupUiArgs(rawArgs);
|
|
@@ -8341,7 +8341,7 @@ function createLookupUiTool(input) {
|
|
|
8341
8341
|
const result = { content: [{ type: "text", text }] };
|
|
8342
8342
|
return result;
|
|
8343
8343
|
};
|
|
8344
|
-
return { definition: DBX_UI_LOOKUP_TOOL, run:
|
|
8344
|
+
return { definition: DBX_UI_LOOKUP_TOOL, run: run12 };
|
|
8345
8345
|
}
|
|
8346
8346
|
|
|
8347
8347
|
// packages/dbx-components-mcp/src/tools/search-ui.tool.ts
|
|
@@ -8523,7 +8523,7 @@ function formatSearchResults2(options) {
|
|
|
8523
8523
|
}
|
|
8524
8524
|
function createSearchUiTool(input) {
|
|
8525
8525
|
const { registry } = input;
|
|
8526
|
-
const
|
|
8526
|
+
const run12 = (rawArgs) => {
|
|
8527
8527
|
let args;
|
|
8528
8528
|
try {
|
|
8529
8529
|
args = parseSearchUiArgs(rawArgs);
|
|
@@ -8538,7 +8538,7 @@ function createSearchUiTool(input) {
|
|
|
8538
8538
|
const result = { content: [{ type: "text", text }] };
|
|
8539
8539
|
return result;
|
|
8540
8540
|
};
|
|
8541
|
-
return { definition: DBX_UI_SEARCH_TOOL, run:
|
|
8541
|
+
return { definition: DBX_UI_SEARCH_TOOL, run: run12 };
|
|
8542
8542
|
}
|
|
8543
8543
|
|
|
8544
8544
|
// packages/dbx-components-mcp/src/tools/ui-examples.tool.ts
|
|
@@ -9934,7 +9934,7 @@ var FolderValidateArgsType = type30({
|
|
|
9934
9934
|
});
|
|
9935
9935
|
function createFolderValidateTool(config) {
|
|
9936
9936
|
const { definition, inspectFolder: inspectFolder3, validate, format } = config;
|
|
9937
|
-
async function
|
|
9937
|
+
async function run12(rawArgs) {
|
|
9938
9938
|
const parsed = FolderValidateArgsType(rawArgs);
|
|
9939
9939
|
if (parsed instanceof type30.errors) {
|
|
9940
9940
|
return toolError(`Invalid arguments: ${parsed.summary}`);
|
|
@@ -9974,7 +9974,7 @@ function createFolderValidateTool(config) {
|
|
|
9974
9974
|
};
|
|
9975
9975
|
return toolResult;
|
|
9976
9976
|
}
|
|
9977
|
-
const tool = { definition, run:
|
|
9977
|
+
const tool = { definition, run: run12 };
|
|
9978
9978
|
return tool;
|
|
9979
9979
|
}
|
|
9980
9980
|
var SourceValidateArgsType = type30({
|
|
@@ -9984,7 +9984,7 @@ var SourceValidateArgsType = type30({
|
|
|
9984
9984
|
});
|
|
9985
9985
|
function createSourceValidateTool(config) {
|
|
9986
9986
|
const { definition, validate, format } = config;
|
|
9987
|
-
async function
|
|
9987
|
+
async function run12(rawArgs) {
|
|
9988
9988
|
const parsed = SourceValidateArgsType(rawArgs);
|
|
9989
9989
|
if (parsed instanceof type30.errors) {
|
|
9990
9990
|
return toolError(`Invalid arguments: ${parsed.summary}`);
|
|
@@ -10011,7 +10011,7 @@ function createSourceValidateTool(config) {
|
|
|
10011
10011
|
};
|
|
10012
10012
|
return toolResult;
|
|
10013
10013
|
}
|
|
10014
|
-
const tool = { definition, run:
|
|
10014
|
+
const tool = { definition, run: run12 };
|
|
10015
10015
|
return tool;
|
|
10016
10016
|
}
|
|
10017
10017
|
var TwoSideValidateArgsType = type30({
|
|
@@ -10038,7 +10038,7 @@ function resolveTwoSideInput(parsed) {
|
|
|
10038
10038
|
}
|
|
10039
10039
|
function createTwoSideValidateTool(config) {
|
|
10040
10040
|
const { definition, inspectAndValidate, format } = config;
|
|
10041
|
-
async function
|
|
10041
|
+
async function run12(rawArgs) {
|
|
10042
10042
|
const parsed = TwoSideValidateArgsType(rawArgs);
|
|
10043
10043
|
if (parsed instanceof type30.errors) {
|
|
10044
10044
|
return toolError(`Invalid arguments: ${parsed.summary}`);
|
|
@@ -10055,7 +10055,7 @@ function createTwoSideValidateTool(config) {
|
|
|
10055
10055
|
};
|
|
10056
10056
|
return toolResult;
|
|
10057
10057
|
}
|
|
10058
|
-
const tool = { definition, run:
|
|
10058
|
+
const tool = { definition, run: run12 };
|
|
10059
10059
|
return tool;
|
|
10060
10060
|
}
|
|
10061
10061
|
var ListAppArgsType = type30({
|
|
@@ -10065,7 +10065,7 @@ var ListAppArgsType = type30({
|
|
|
10065
10065
|
});
|
|
10066
10066
|
function createListAppTool(config) {
|
|
10067
10067
|
const { definition, inspectAndList, formatMarkdown: formatMarkdown2, formatJson: formatJson2 } = config;
|
|
10068
|
-
async function
|
|
10068
|
+
async function run12(rawArgs) {
|
|
10069
10069
|
const parsed = ListAppArgsType(rawArgs);
|
|
10070
10070
|
if (parsed instanceof type30.errors) {
|
|
10071
10071
|
return toolError(`Invalid arguments: ${parsed.summary}`);
|
|
@@ -10079,7 +10079,7 @@ function createListAppTool(config) {
|
|
|
10079
10079
|
const toolResult = { content: [{ type: "text", text }] };
|
|
10080
10080
|
return toolResult;
|
|
10081
10081
|
}
|
|
10082
|
-
const tool = { definition, run:
|
|
10082
|
+
const tool = { definition, run: run12 };
|
|
10083
10083
|
return tool;
|
|
10084
10084
|
}
|
|
10085
10085
|
|
|
@@ -10113,15 +10113,18 @@ function findDataInterfaces(sourceFile, groupInterface) {
|
|
|
10113
10113
|
continue;
|
|
10114
10114
|
}
|
|
10115
10115
|
const fields = extractInterfaceFields(iface);
|
|
10116
|
-
|
|
10116
|
+
const dbxModelTag = readDbxModelTag(iface.getJsDocs());
|
|
10117
|
+
out.push({ name, line: iface.getStartLineNumber(), dbxModelTag, fields });
|
|
10117
10118
|
}
|
|
10118
10119
|
return out;
|
|
10119
10120
|
}
|
|
10120
10121
|
function extractInterfaceFields(iface) {
|
|
10121
10122
|
const fields = [];
|
|
10122
10123
|
for (const prop of iface.getProperties()) {
|
|
10123
|
-
const
|
|
10124
|
-
const
|
|
10124
|
+
const jsDocs = prop.getJsDocs();
|
|
10125
|
+
const jsDocFirstLine = firstJsDocLine(jsDocs);
|
|
10126
|
+
const dbxModelVariableTag = readDbxModelVariableTag(jsDocs);
|
|
10127
|
+
const field = { name: prop.getName(), line: prop.getStartLineNumber(), jsDocFirstLine, dbxModelVariableTag };
|
|
10125
10128
|
fields.push(field);
|
|
10126
10129
|
}
|
|
10127
10130
|
return fields;
|
|
@@ -10154,10 +10157,46 @@ function findGroupInterface(sourceFile) {
|
|
|
10154
10157
|
name: iface.getName(),
|
|
10155
10158
|
exported: iface.isExported(),
|
|
10156
10159
|
properties,
|
|
10157
|
-
line: iface.getStartLineNumber()
|
|
10160
|
+
line: iface.getStartLineNumber(),
|
|
10161
|
+
dbxModelGroupTag: readDbxModelGroupTag2(iface.getJsDocs())
|
|
10158
10162
|
};
|
|
10159
10163
|
return result;
|
|
10160
10164
|
}
|
|
10165
|
+
function readDbxModelGroupTag2(jsDocs) {
|
|
10166
|
+
let result;
|
|
10167
|
+
for (const jsDoc of jsDocs) {
|
|
10168
|
+
for (const tag of jsDoc.getTags()) {
|
|
10169
|
+
if (tag.getTagName() !== "dbxModelGroup") continue;
|
|
10170
|
+
const text = tag.getCommentText()?.trim() ?? "";
|
|
10171
|
+
result = text.length > 0 ? text : true;
|
|
10172
|
+
}
|
|
10173
|
+
}
|
|
10174
|
+
return result;
|
|
10175
|
+
}
|
|
10176
|
+
function readDbxModelTag(jsDocs) {
|
|
10177
|
+
let result = false;
|
|
10178
|
+
for (const jsDoc of jsDocs) {
|
|
10179
|
+
for (const tag of jsDoc.getTags()) {
|
|
10180
|
+
if (tag.getTagName() === "dbxModel") {
|
|
10181
|
+
result = true;
|
|
10182
|
+
}
|
|
10183
|
+
}
|
|
10184
|
+
}
|
|
10185
|
+
return result;
|
|
10186
|
+
}
|
|
10187
|
+
function readDbxModelVariableTag(jsDocs) {
|
|
10188
|
+
let result;
|
|
10189
|
+
for (const jsDoc of jsDocs) {
|
|
10190
|
+
for (const tag of jsDoc.getTags()) {
|
|
10191
|
+
if (tag.getTagName() !== "dbxModelVariable") continue;
|
|
10192
|
+
const text = tag.getCommentText()?.trim();
|
|
10193
|
+
if (text !== void 0 && text.length > 0 && result === void 0) {
|
|
10194
|
+
result = text;
|
|
10195
|
+
}
|
|
10196
|
+
}
|
|
10197
|
+
}
|
|
10198
|
+
return result;
|
|
10199
|
+
}
|
|
10161
10200
|
function findGroupTypes(sourceFile) {
|
|
10162
10201
|
const candidate = sourceFile.getTypeAliases().find((t) => {
|
|
10163
10202
|
const name = t.getName();
|
|
@@ -10737,6 +10776,16 @@ var RULE_CATALOG = [
|
|
|
10737
10776
|
whenItDoesNotApply: "Fields whose name is unambiguously self-describing (rare with 1-4 char abbreviations).",
|
|
10738
10777
|
canonicalFix: "Add `/** <fullName> -- <description> *\\/` above the field declaration."
|
|
10739
10778
|
},
|
|
10779
|
+
{
|
|
10780
|
+
code: "MODEL_FIELD_MISSING_VARIABLE_TAG",
|
|
10781
|
+
source: "dbx_model_validate",
|
|
10782
|
+
severity: "warning",
|
|
10783
|
+
title: "A persisted field is missing its `@dbxModelVariable <name>` JSDoc tag",
|
|
10784
|
+
whatItFlags: "A persisted field is missing its `@dbxModelVariable <name>` JSDoc tag.",
|
|
10785
|
+
whenItApplies: "Every field on a `@dbxModel` interface \u2014 the tag carries the human-readable long name the catalog and decoder use when surfacing the field to operators.",
|
|
10786
|
+
whenItDoesNotApply: "Fields on embedded sub-object interfaces (no `@dbxModel` parent) and fields the project deliberately leaves untagged (rare).",
|
|
10787
|
+
canonicalFix: "Append `@dbxModelVariable <longName>` to the field's JSDoc block."
|
|
10788
|
+
},
|
|
10740
10789
|
{
|
|
10741
10790
|
code: "MODEL_FIELD_NAME_TOO_LONG",
|
|
10742
10791
|
source: "dbx_model_validate",
|
|
@@ -10747,6 +10796,22 @@ var RULE_CATALOG = [
|
|
|
10747
10796
|
whenItDoesNotApply: "Fields that compose well-known multi-character abbreviations the project intentionally allows.",
|
|
10748
10797
|
canonicalFix: "Rename the field to a 1\u20134 character abbreviation (e.g. `name` \u2192 `n`, `userId` \u2192 `uid`)."
|
|
10749
10798
|
},
|
|
10799
|
+
{
|
|
10800
|
+
code: "MODEL_GROUP_INTERFACE_MISSING_TAG",
|
|
10801
|
+
source: "dbx_model_validate",
|
|
10802
|
+
severity: "error",
|
|
10803
|
+
title: "The `<Group>FirestoreCollections` interface is missing its `@dbxModelGroup` JSDoc tag",
|
|
10804
|
+
whatItFlags: "The `<Group>FirestoreCollections` interface is missing its `@dbxModelGroup` JSDoc tag.",
|
|
10805
|
+
whenItApplies: "Every group container \u2014 the rich catalog extractor (`scan/extract-models`) requires the tag to register the group, and downstream traversal/referencing depends on that registration.",
|
|
10806
|
+
whenItDoesNotApply: "Files in `@dereekb/firebase` itself (upstream-owned sources).",
|
|
10807
|
+
canonicalFix: "Add `@dbxModelGroup <Group>` to the JSDoc above the `<Group>FirestoreCollections` declaration.",
|
|
10808
|
+
seeAlso: [
|
|
10809
|
+
{
|
|
10810
|
+
kind: "artifact",
|
|
10811
|
+
target: "firestore-model"
|
|
10812
|
+
}
|
|
10813
|
+
]
|
|
10814
|
+
},
|
|
10750
10815
|
{
|
|
10751
10816
|
code: "MODEL_IDENTITY_BAD_ARGS",
|
|
10752
10817
|
source: "dbx_model_validate",
|
|
@@ -10767,6 +10832,38 @@ var RULE_CATALOG = [
|
|
|
10767
10832
|
whenItDoesNotApply: "When intentionally module-private (rare).",
|
|
10768
10833
|
canonicalFix: "Add `export` to the identity constant declaration."
|
|
10769
10834
|
},
|
|
10835
|
+
{
|
|
10836
|
+
code: "MODEL_IDENTITY_NOT_TAGGED",
|
|
10837
|
+
source: "dbx_model_validate",
|
|
10838
|
+
severity: "error",
|
|
10839
|
+
title: "`firestoreModelIdentity(...)` was found but its corresponding model interface lacks the `@dbxModel` JSDoc tag, leaving the model invisible to the catalog and to downstream traversal/referencing code",
|
|
10840
|
+
whatItFlags: "`firestoreModelIdentity(...)` was found but its corresponding model interface lacks the `@dbxModel` JSDoc tag, leaving the model invisible to the catalog and to downstream traversal/referencing code.",
|
|
10841
|
+
whenItApplies: "Every `firestoreModelIdentity(...)` call whose `<PascalName>` interface is missing `@dbxModel`. Anchored at the identity line so the fix points at both the interface and the identity.",
|
|
10842
|
+
whenItDoesNotApply: "Files in `@dereekb/firebase` itself.",
|
|
10843
|
+
canonicalFix: "Add `@dbxModel` to the JSDoc on the `<PascalName>` interface so the catalog and decoder recognise it as a model.",
|
|
10844
|
+
seeAlso: [
|
|
10845
|
+
{
|
|
10846
|
+
kind: "artifact",
|
|
10847
|
+
target: "firestore-model"
|
|
10848
|
+
}
|
|
10849
|
+
]
|
|
10850
|
+
},
|
|
10851
|
+
{
|
|
10852
|
+
code: "MODEL_INTERFACE_MISSING_TAG",
|
|
10853
|
+
source: "dbx_model_validate",
|
|
10854
|
+
severity: "error",
|
|
10855
|
+
title: "The model's data interface is missing its `@dbxModel` JSDoc tag",
|
|
10856
|
+
whatItFlags: "The model's data interface is missing its `@dbxModel` JSDoc tag.",
|
|
10857
|
+
whenItApplies: "Every `<PascalName>` interface that anchors a `firestoreModelIdentity(...)` model \u2014 the rich catalog extractor (`scan/extract-models`) requires the tag to register the model.",
|
|
10858
|
+
whenItDoesNotApply: "Embedded sub-object interfaces (no matching identity) and files in `@dereekb/firebase` itself.",
|
|
10859
|
+
canonicalFix: "Add `@dbxModel` to the JSDoc above the `<PascalName>` interface declaration.",
|
|
10860
|
+
seeAlso: [
|
|
10861
|
+
{
|
|
10862
|
+
kind: "artifact",
|
|
10863
|
+
target: "firestore-model"
|
|
10864
|
+
}
|
|
10865
|
+
]
|
|
10866
|
+
},
|
|
10770
10867
|
{
|
|
10771
10868
|
code: "MODEL_INTERFACE_NOT_EXPORTED",
|
|
10772
10869
|
source: "dbx_model_validate",
|
|
@@ -12562,9 +12659,7 @@ function checkFieldJsDocs(file, violations) {
|
|
|
12562
12659
|
line: field.line,
|
|
12563
12660
|
model: iface.name
|
|
12564
12661
|
});
|
|
12565
|
-
|
|
12566
|
-
}
|
|
12567
|
-
if (!FULL_NAME_FIRST_LINE.test(field.jsDocFirstLine)) {
|
|
12662
|
+
} else if (!FULL_NAME_FIRST_LINE.test(field.jsDocFirstLine)) {
|
|
12568
12663
|
pushViolation(violations, {
|
|
12569
12664
|
code: "MODEL_FIELD_JSDOC_NO_FULL_NAME",
|
|
12570
12665
|
severity: "warning",
|
|
@@ -12574,6 +12669,16 @@ function checkFieldJsDocs(file, violations) {
|
|
|
12574
12669
|
model: iface.name
|
|
12575
12670
|
});
|
|
12576
12671
|
}
|
|
12672
|
+
if (iface.dbxModelTag && field.dbxModelVariableTag === void 0) {
|
|
12673
|
+
pushViolation(violations, {
|
|
12674
|
+
code: "MODEL_FIELD_MISSING_VARIABLE_TAG",
|
|
12675
|
+
severity: "warning",
|
|
12676
|
+
message: `Field \`${field.name}\` in interface \`${iface.name}\` is missing its \`@dbxModelVariable <name>\` JSDoc tag. The catalog uses the tag for the field's long name.`,
|
|
12677
|
+
file: file.name,
|
|
12678
|
+
line: field.line,
|
|
12679
|
+
model: iface.name
|
|
12680
|
+
});
|
|
12681
|
+
}
|
|
12577
12682
|
}
|
|
12578
12683
|
}
|
|
12579
12684
|
}
|
|
@@ -12598,6 +12703,15 @@ function checkFileLevel(file, violations) {
|
|
|
12598
12703
|
model: void 0
|
|
12599
12704
|
});
|
|
12600
12705
|
}
|
|
12706
|
+
if (groupInterface.dbxModelGroupTag === void 0) {
|
|
12707
|
+
pushViolation(violations, {
|
|
12708
|
+
code: "MODEL_GROUP_INTERFACE_MISSING_TAG",
|
|
12709
|
+
message: `Interface \`${groupInterface.name}\` is missing its \`@dbxModelGroup\` JSDoc tag. Add \`@dbxModelGroup <Group>\` so the catalog and downstream traversal can register the group.`,
|
|
12710
|
+
file: name,
|
|
12711
|
+
line: groupInterface.line,
|
|
12712
|
+
model: void 0
|
|
12713
|
+
});
|
|
12714
|
+
}
|
|
12601
12715
|
checkGroupInterfaceCoverage(file, violations);
|
|
12602
12716
|
} else {
|
|
12603
12717
|
pushViolation(violations, {
|
|
@@ -12747,6 +12861,23 @@ function checkInterface(file, model, violations) {
|
|
|
12747
12861
|
model: model.name
|
|
12748
12862
|
});
|
|
12749
12863
|
}
|
|
12864
|
+
const dataInterface = file.dataInterfaces.find((d) => d.name === model.name);
|
|
12865
|
+
if (dataInterface && !dataInterface.dbxModelTag) {
|
|
12866
|
+
pushViolation(violations, {
|
|
12867
|
+
code: "MODEL_INTERFACE_MISSING_TAG",
|
|
12868
|
+
message: `Interface \`${model.name}\` is missing its \`@dbxModel\` JSDoc tag. The catalog skips untagged interfaces, so downstream traversal/referencing of \`${model.name}\` is broken.`,
|
|
12869
|
+
file: file.name,
|
|
12870
|
+
line: dataInterface.line,
|
|
12871
|
+
model: model.name
|
|
12872
|
+
});
|
|
12873
|
+
pushViolation(violations, {
|
|
12874
|
+
code: "MODEL_IDENTITY_NOT_TAGGED",
|
|
12875
|
+
message: `\`firestoreModelIdentity\` was found for \`${model.identity.constName}\` but its \`${model.name}\` interface is not tagged with \`@dbxModel\`. Tag the interface so the catalog registers the model.`,
|
|
12876
|
+
file: file.name,
|
|
12877
|
+
line: model.identity.line,
|
|
12878
|
+
model: model.name
|
|
12879
|
+
});
|
|
12880
|
+
}
|
|
12750
12881
|
}
|
|
12751
12882
|
function checkRoles(file, model, violations) {
|
|
12752
12883
|
if (!model.rolesType) {
|
|
@@ -13279,7 +13410,7 @@ function validateFirebaseModelSources(sources) {
|
|
|
13279
13410
|
var DBX_MODEL_VALIDATE_TOOL = {
|
|
13280
13411
|
name: "dbx_model_validate",
|
|
13281
13412
|
description: [
|
|
13282
|
-
"Validate a @dereekb/firebase model file against the workspace model-group convention. Checks that the file exports a `<Group>FirestoreCollections` interface and `<Group>Types` union, and that every `firestoreModelIdentity(...)` has the canonical declarations in order (interface, roles, document class, converter, collection reference fn, collection type, collection fn) \u2014 plus the factory-type + collection-group triple for subcollections.
|
|
13413
|
+
"Validate a @dereekb/firebase model file against the workspace model-group convention. Checks that the file exports a `<Group>FirestoreCollections` interface and `<Group>Types` union, and that every `firestoreModelIdentity(...)` has the canonical declarations in order (interface, roles, document class, converter, collection reference fn, collection type, collection fn) \u2014 plus the factory-type + collection-group triple for subcollections. Also enforces JSDoc tagging required for catalog discovery and downstream traversal: `@dbxModelGroup <Group>` on the group container, `@dbxModel` on every model interface (with a per-identity `MODEL_IDENTITY_NOT_TAGGED` error anchored at the `firestoreModelIdentity(...)` line), and `@dbxModelVariable <name>` on every persisted field (warning).",
|
|
13283
13414
|
"",
|
|
13284
13415
|
"Provide at least one of:",
|
|
13285
13416
|
"- `sources`: array of `{ name, text }` \u2014 file contents supplied directly.",
|
|
@@ -14496,12 +14627,14 @@ function formatResult3(result) {
|
|
|
14496
14627
|
}
|
|
14497
14628
|
|
|
14498
14629
|
// packages/dbx-components-mcp/src/tools/model-validate-folder/inspect.ts
|
|
14499
|
-
import { readdir as readdir2, stat as stat4 } from "node:fs/promises";
|
|
14500
|
-
import { basename as basename4 } from "node:path";
|
|
14630
|
+
import { readdir as readdir2, readFile as readFile4, stat as stat4 } from "node:fs/promises";
|
|
14631
|
+
import { basename as basename4, join as join3 } from "node:path";
|
|
14632
|
+
var CONTENT_VALIDATION_SKIP_SUFFIXES = [".spec.ts", ".id.ts", ".query.ts", ".action.ts", ".api.ts"];
|
|
14501
14633
|
async function inspectFolder(path) {
|
|
14502
14634
|
const name = basename4(path);
|
|
14503
14635
|
let status;
|
|
14504
14636
|
let files = [];
|
|
14637
|
+
let sources = [];
|
|
14505
14638
|
try {
|
|
14506
14639
|
const stats = await stat4(path);
|
|
14507
14640
|
if (stats.isDirectory()) {
|
|
@@ -14514,6 +14647,7 @@ async function inspectFolder(path) {
|
|
|
14514
14647
|
collected.push(entry.name);
|
|
14515
14648
|
}
|
|
14516
14649
|
files = collected;
|
|
14650
|
+
sources = await readModelSources(path, collected);
|
|
14517
14651
|
} else {
|
|
14518
14652
|
status = "not-directory";
|
|
14519
14653
|
}
|
|
@@ -14525,9 +14659,19 @@ async function inspectFolder(path) {
|
|
|
14525
14659
|
throw err;
|
|
14526
14660
|
}
|
|
14527
14661
|
}
|
|
14528
|
-
const result = { name, path, status, files };
|
|
14662
|
+
const result = { name, path, status, files, sources };
|
|
14529
14663
|
return result;
|
|
14530
14664
|
}
|
|
14665
|
+
async function readModelSources(folderPath, files) {
|
|
14666
|
+
const out = [];
|
|
14667
|
+
for (const filename of files) {
|
|
14668
|
+
if (filename === "index.ts") continue;
|
|
14669
|
+
if (CONTENT_VALIDATION_SKIP_SUFFIXES.some((suffix) => filename.endsWith(suffix))) continue;
|
|
14670
|
+
const text = await readFile4(join3(folderPath, filename), "utf8");
|
|
14671
|
+
out.push({ filename, text });
|
|
14672
|
+
}
|
|
14673
|
+
return out;
|
|
14674
|
+
}
|
|
14531
14675
|
|
|
14532
14676
|
// packages/dbx-components-mcp/src/tools/model-validate-folder/rules.ts
|
|
14533
14677
|
function runRules3(inspection) {
|
|
@@ -14563,8 +14707,26 @@ function runRules3(inspection) {
|
|
|
14563
14707
|
}
|
|
14564
14708
|
checkRequiredFiles(inspection, violations);
|
|
14565
14709
|
checkStrayFiles(inspection, violations);
|
|
14710
|
+
checkSourceContents(inspection, violations);
|
|
14566
14711
|
return violations;
|
|
14567
14712
|
}
|
|
14713
|
+
function checkSourceContents(inspection, violations) {
|
|
14714
|
+
const sources = inspection.sources;
|
|
14715
|
+
if (!sources || sources.length === 0) {
|
|
14716
|
+
return;
|
|
14717
|
+
}
|
|
14718
|
+
const validatorSources = sources.map((s) => ({ name: s.filename, text: s.text }));
|
|
14719
|
+
const result = validateFirebaseModelSources(validatorSources);
|
|
14720
|
+
for (const v of result.violations) {
|
|
14721
|
+
pushViolation3(violations, {
|
|
14722
|
+
code: v.code,
|
|
14723
|
+
severity: v.severity,
|
|
14724
|
+
message: v.message,
|
|
14725
|
+
folder: inspection.path,
|
|
14726
|
+
file: v.file
|
|
14727
|
+
});
|
|
14728
|
+
}
|
|
14729
|
+
}
|
|
14568
14730
|
function checkRequiredFiles(inspection, violations) {
|
|
14569
14731
|
const presentFiles = new Set(inspection.files);
|
|
14570
14732
|
for (const required of buildRequiredFiles(inspection.name)) {
|
|
@@ -14625,6 +14787,8 @@ var DBX_MODEL_VALIDATE_FOLDER_TOOL = {
|
|
|
14625
14787
|
description: [
|
|
14626
14788
|
"Validate that one or more model folders follow the canonical layout. Each folder named `<name>/` must contain `<name>.ts`, `<name>.id.ts`, `<name>.query.ts`, `<name>.action.ts`, `<name>.api.ts`, and `index.ts`. Missing files are hard errors.",
|
|
14627
14789
|
"",
|
|
14790
|
+
"Also runs every `dbx_model_validate` rule against the contents of each model `.ts` file, so untagged models surface here too \u2014 e.g. `MODEL_IDENTITY_NOT_TAGGED` when `firestoreModelIdentity(...)` is declared without a matching `@dbxModel` interface. Sub-files (`<name>.id.ts`, `.query.ts`, `.action.ts`, `.api.ts`, `*.spec.ts`, `index.ts`) are skipped \u2014 they never declare `firestoreModelIdentity` calls.",
|
|
14791
|
+
"",
|
|
14628
14792
|
"Warnings cover: stray `.ts` files at the folder root that do not start with `<name>.` (they should be grouped under the model prefix), and reserved folder names (`system/`, `notification/`, `storagefile/`) that have dedicated validators and are skipped here.",
|
|
14629
14793
|
"",
|
|
14630
14794
|
"Provide at least one of:",
|
|
@@ -15611,13 +15775,13 @@ function collectIdentityImports(sourceFile) {
|
|
|
15611
15775
|
}
|
|
15612
15776
|
|
|
15613
15777
|
// packages/dbx-components-mcp/src/tools/model-fixture-shared/inspect.ts
|
|
15614
|
-
import { readFile as
|
|
15615
|
-
import { join as
|
|
15778
|
+
import { readFile as readFile5 } from "node:fs/promises";
|
|
15779
|
+
import { join as join4 } from "node:path";
|
|
15616
15780
|
var FIXTURE_RELATIVE_PATH = "src/test/fixture.ts";
|
|
15617
15781
|
async function inspectAppFixtures(apiAbs, apiRel) {
|
|
15618
|
-
const absolutePath =
|
|
15782
|
+
const absolutePath = join4(apiAbs, FIXTURE_RELATIVE_PATH);
|
|
15619
15783
|
const relativePath = `${apiRel}/${FIXTURE_RELATIVE_PATH}`;
|
|
15620
|
-
const text = await
|
|
15784
|
+
const text = await readFile5(absolutePath, "utf8");
|
|
15621
15785
|
return extractAppFixturesFromText({ text, fixturePath: relativePath });
|
|
15622
15786
|
}
|
|
15623
15787
|
|
|
@@ -16464,7 +16628,7 @@ var TOOL3 = {
|
|
|
16464
16628
|
}
|
|
16465
16629
|
};
|
|
16466
16630
|
function createModelFixtureValidateAppTool(config = {}) {
|
|
16467
|
-
async function
|
|
16631
|
+
async function run12(rawArgs) {
|
|
16468
16632
|
const parsed = ValidateArgsType(rawArgs);
|
|
16469
16633
|
if (parsed instanceof type34.errors) {
|
|
16470
16634
|
return toolError(`Invalid arguments: ${parsed.summary}`);
|
|
@@ -16491,12 +16655,12 @@ function createModelFixtureValidateAppTool(config = {}) {
|
|
|
16491
16655
|
};
|
|
16492
16656
|
return toolResult;
|
|
16493
16657
|
}
|
|
16494
|
-
return { definition: TOOL3, run:
|
|
16658
|
+
return { definition: TOOL3, run: run12 };
|
|
16495
16659
|
}
|
|
16496
16660
|
|
|
16497
16661
|
// packages/dbx-components-mcp/src/tools/model-fixture-scaffold.tool.ts
|
|
16498
|
-
import { readFile as
|
|
16499
|
-
import { join as
|
|
16662
|
+
import { readFile as readFile6, writeFile } from "node:fs/promises";
|
|
16663
|
+
import { join as join5, resolve as resolve20 } from "node:path";
|
|
16500
16664
|
import { type as type35 } from "arktype";
|
|
16501
16665
|
var ScaffoldArgsType3 = type35({
|
|
16502
16666
|
apiDir: "string",
|
|
@@ -16614,10 +16778,10 @@ async function run3(rawArgs) {
|
|
|
16614
16778
|
if (conflicts.length > 0) {
|
|
16615
16779
|
return toolError(["Refusing to scaffold \u2014 the following names already exist in `" + extraction.fixturePath + "`:", "", ...conflicts.map((c) => "- `" + c + "`"), "", "Rename, delete, or pick a different model name and retry."].join("\n"));
|
|
16616
16780
|
}
|
|
16617
|
-
const absolutePath =
|
|
16781
|
+
const absolutePath = join5(apiAbs, FIXTURE_RELATIVE_PATH);
|
|
16618
16782
|
let original;
|
|
16619
16783
|
try {
|
|
16620
|
-
original = await
|
|
16784
|
+
original = await readFile6(absolutePath, "utf8");
|
|
16621
16785
|
} catch (err) {
|
|
16622
16786
|
return toolError(`Failed to read fixture file: ${err instanceof Error ? err.message : String(err)}`);
|
|
16623
16787
|
}
|
|
@@ -16666,7 +16830,7 @@ function collectConflicts(extraction, rendered) {
|
|
|
16666
16830
|
var modelFixtureScaffoldTool = { definition: TOOL4, run: run3 };
|
|
16667
16831
|
|
|
16668
16832
|
// packages/dbx-components-mcp/src/tools/model-fixture-forward.tool.ts
|
|
16669
|
-
import { join as
|
|
16833
|
+
import { join as join6, resolve as resolve21 } from "node:path";
|
|
16670
16834
|
import { type as type36 } from "arktype";
|
|
16671
16835
|
import { Project as Project8 } from "ts-morph";
|
|
16672
16836
|
var ForwardArgsType = type36({
|
|
@@ -16680,110 +16844,1007 @@ var TOOL5 = {
|
|
|
16680
16844
|
inputSchema: {
|
|
16681
16845
|
type: "object",
|
|
16682
16846
|
properties: {
|
|
16683
|
-
apiDir: { type: "string", description: "Relative path to the API app." },
|
|
16684
|
-
model: { type: "string", description: "Bare model name (e.g. `StorageFile`)." },
|
|
16685
|
-
methods: {
|
|
16686
|
-
type: "array",
|
|
16687
|
-
items: { type: "string" },
|
|
16688
|
-
description: "Optional whitelist of instance method names to forward."
|
|
16689
|
-
}
|
|
16847
|
+
apiDir: { type: "string", description: "Relative path to the API app." },
|
|
16848
|
+
model: { type: "string", description: "Bare model name (e.g. `StorageFile`)." },
|
|
16849
|
+
methods: {
|
|
16850
|
+
type: "array",
|
|
16851
|
+
items: { type: "string" },
|
|
16852
|
+
description: "Optional whitelist of instance method names to forward."
|
|
16853
|
+
}
|
|
16854
|
+
},
|
|
16855
|
+
required: ["apiDir", "model"]
|
|
16856
|
+
}
|
|
16857
|
+
};
|
|
16858
|
+
async function run4(rawArgs) {
|
|
16859
|
+
const parsed = ForwardArgsType(rawArgs);
|
|
16860
|
+
if (parsed instanceof type36.errors) {
|
|
16861
|
+
return toolError(`Invalid arguments: ${parsed.summary}`);
|
|
16862
|
+
}
|
|
16863
|
+
const cwd = process.cwd();
|
|
16864
|
+
try {
|
|
16865
|
+
ensurePathInsideCwd(parsed.apiDir, cwd);
|
|
16866
|
+
} catch (err) {
|
|
16867
|
+
return toolError(toErrorMessage(err));
|
|
16868
|
+
}
|
|
16869
|
+
const apiAbs = resolve21(cwd, parsed.apiDir);
|
|
16870
|
+
let extraction;
|
|
16871
|
+
try {
|
|
16872
|
+
extraction = await inspectAppFixtures(apiAbs, parsed.apiDir);
|
|
16873
|
+
} catch (err) {
|
|
16874
|
+
return toolError(`Failed to read fixture file: ${toErrorMessage(err)}`);
|
|
16875
|
+
}
|
|
16876
|
+
const entry = extraction.entries.find((e) => e.model === parsed.model);
|
|
16877
|
+
if (!entry) {
|
|
16878
|
+
const known = extraction.entries.map((e) => e.model).join(", ") || "(none)";
|
|
16879
|
+
return toolError(`Model \`${parsed.model}\` not found in \`${extraction.fixturePath}\`. Known: ${known}.`);
|
|
16880
|
+
}
|
|
16881
|
+
const rendered = renderForwarders({ entry, methods: parsed.methods });
|
|
16882
|
+
if (rendered.added.length === 0) {
|
|
16883
|
+
return { content: [{ type: "text", text: renderNoOpReport(extraction.fixturePath, entry.fixtureClassName, rendered) }] };
|
|
16884
|
+
}
|
|
16885
|
+
const absolutePath = join6(apiAbs, FIXTURE_RELATIVE_PATH);
|
|
16886
|
+
const writeError = await applyForwardersToFile(absolutePath, entry.fixtureClassName, rendered);
|
|
16887
|
+
if (writeError) {
|
|
16888
|
+
return toolError(writeError);
|
|
16889
|
+
}
|
|
16890
|
+
return { content: [{ type: "text", text: renderSuccessReport(extraction.fixturePath, entry.fixtureClassName, rendered) }] };
|
|
16891
|
+
}
|
|
16892
|
+
function toErrorMessage(err) {
|
|
16893
|
+
return err instanceof Error ? err.message : String(err);
|
|
16894
|
+
}
|
|
16895
|
+
async function applyForwardersToFile(absolutePath, fixtureClassName, rendered) {
|
|
16896
|
+
const project = new Project8({ skipAddingFilesFromTsConfig: true });
|
|
16897
|
+
let sourceFile;
|
|
16898
|
+
try {
|
|
16899
|
+
sourceFile = project.addSourceFileAtPath(absolutePath);
|
|
16900
|
+
} catch (err) {
|
|
16901
|
+
return `Failed to load fixture file: ${toErrorMessage(err)}`;
|
|
16902
|
+
}
|
|
16903
|
+
const fixtureClass = sourceFile.getClass(fixtureClassName);
|
|
16904
|
+
if (!fixtureClass) {
|
|
16905
|
+
return `Could not locate class \`${fixtureClassName}\` for in-place edit. The fixture file may have been modified since parsing.`;
|
|
16906
|
+
}
|
|
16907
|
+
for (const forwarder of rendered.added) {
|
|
16908
|
+
fixtureClass.insertText(fixtureClass.getEnd() - 1, "\n" + forwarder.source + "\n");
|
|
16909
|
+
}
|
|
16910
|
+
sourceFile.formatText({ ensureNewLineAtEndOfFile: true });
|
|
16911
|
+
try {
|
|
16912
|
+
await sourceFile.save();
|
|
16913
|
+
} catch (err) {
|
|
16914
|
+
return `Failed to write fixture file: ${toErrorMessage(err)}`;
|
|
16915
|
+
}
|
|
16916
|
+
return void 0;
|
|
16917
|
+
}
|
|
16918
|
+
function renderNoOpReport(fixturePath, fixtureClassName, rendered) {
|
|
16919
|
+
const lines = [`# No forwarders to add for \`${fixtureClassName}\``, "", `File: \`${fixturePath}\``];
|
|
16920
|
+
appendListSection(lines, "## Already forwarded", rendered.skippedAlreadyForwarded);
|
|
16921
|
+
appendListSection(lines, "## Whitelisted methods missing from Instance", rendered.missingFromInstance);
|
|
16922
|
+
return lines.join("\n");
|
|
16923
|
+
}
|
|
16924
|
+
function renderSuccessReport(fixturePath, fixtureClassName, rendered) {
|
|
16925
|
+
const lines = [`# Forwarded ${rendered.added.length} method${rendered.added.length === 1 ? "" : "s"} to \`${fixtureClassName}\``, "", `File: \`${fixturePath}\``, "", "## Added"];
|
|
16926
|
+
for (const f of rendered.added) {
|
|
16927
|
+
lines.push(`- \`${f.method}\``);
|
|
16928
|
+
}
|
|
16929
|
+
appendListSection(lines, "## Skipped (already forwarded)", rendered.skippedAlreadyForwarded);
|
|
16930
|
+
appendListSection(lines, "## Whitelisted methods missing from Instance", rendered.missingFromInstance);
|
|
16931
|
+
return lines.join("\n");
|
|
16932
|
+
}
|
|
16933
|
+
function appendListSection(lines, heading, names) {
|
|
16934
|
+
if (names.length === 0) return;
|
|
16935
|
+
lines.push("", heading);
|
|
16936
|
+
for (const name of names) {
|
|
16937
|
+
lines.push(`- \`${name}\``);
|
|
16938
|
+
}
|
|
16939
|
+
}
|
|
16940
|
+
var modelFixtureForwardTool = { definition: TOOL5, run: run4 };
|
|
16941
|
+
|
|
16942
|
+
// packages/dbx-components-mcp/src/tools/model-test-tree.tool.ts
|
|
16943
|
+
import { resolve as resolve22 } from "node:path";
|
|
16944
|
+
import { type as type37 } from "arktype";
|
|
16945
|
+
|
|
16946
|
+
// packages/dbx-components-mcp/src/tools/model-test-shared/extract.ts
|
|
16947
|
+
import { Node as Node12, Project as Project9, SyntaxKind as SyntaxKind7 } from "ts-morph";
|
|
16948
|
+
var SPEC_FILE_VIRTUAL_PATH = "__spec__/spec.ts";
|
|
16949
|
+
var FIXTURE_CONTEXT_SUFFIX = "Context";
|
|
16950
|
+
var FIXTURE_FACTORY_SUFFIX = "ContextFactory";
|
|
16951
|
+
var HOOK_NAMES = /* @__PURE__ */ new Set(["beforeEach", "beforeAll", "afterEach", "afterAll"]);
|
|
16952
|
+
var DESCRIBE_NAMES = /* @__PURE__ */ new Set(["describe", "xdescribe", "fdescribe"]);
|
|
16953
|
+
var IT_NAMES = /* @__PURE__ */ new Set(["it", "xit", "fit", "test"]);
|
|
16954
|
+
function extractSpecTreeFromText(input) {
|
|
16955
|
+
const { text, specPath } = input;
|
|
16956
|
+
const project = new Project9({ useInMemoryFileSystem: true, skipAddingFilesFromTsConfig: true });
|
|
16957
|
+
const sourceFile = project.createSourceFile(SPEC_FILE_VIRTUAL_PATH, text, { overwrite: true });
|
|
16958
|
+
const { prefix, prefixSource, knownFixtureNames } = resolvePrefixAndFixtures(sourceFile, input);
|
|
16959
|
+
const helpers = collectHelpers(sourceFile);
|
|
16960
|
+
const helperNames = new Set(helpers.map((h) => h.name));
|
|
16961
|
+
const counts = { describe: 0, it: 0, fixture: 0 };
|
|
16962
|
+
const rootChildren = [];
|
|
16963
|
+
for (const stmt of sourceFile.getStatements()) {
|
|
16964
|
+
if (!Node12.isExpressionStatement(stmt)) continue;
|
|
16965
|
+
const expr = stmt.getExpression();
|
|
16966
|
+
if (!Node12.isCallExpression(expr)) continue;
|
|
16967
|
+
const node = walkCall(expr, { prefix, knownFixtureNames, helperNames, counts });
|
|
16968
|
+
if (node !== void 0) {
|
|
16969
|
+
rootChildren.push(node);
|
|
16970
|
+
}
|
|
16971
|
+
}
|
|
16972
|
+
const lastLine = sourceFile.getEndLineNumber();
|
|
16973
|
+
const root = {
|
|
16974
|
+
kind: "wrapper",
|
|
16975
|
+
callee: specPath,
|
|
16976
|
+
line: 1,
|
|
16977
|
+
endLine: lastLine,
|
|
16978
|
+
children: rootChildren
|
|
16979
|
+
};
|
|
16980
|
+
const result = {
|
|
16981
|
+
specPath,
|
|
16982
|
+
prefix,
|
|
16983
|
+
prefixSource,
|
|
16984
|
+
knownFixtureNames,
|
|
16985
|
+
root,
|
|
16986
|
+
helpers,
|
|
16987
|
+
fixtureCallsCount: counts.fixture,
|
|
16988
|
+
itCount: counts.it,
|
|
16989
|
+
describeCount: counts.describe
|
|
16990
|
+
};
|
|
16991
|
+
return result;
|
|
16992
|
+
}
|
|
16993
|
+
function resolvePrefixAndFixtures(sourceFile, input) {
|
|
16994
|
+
const supplied = input.knownFixtureNames ?? [];
|
|
16995
|
+
if (input.prefix !== void 0 && input.prefix !== "" && supplied.length > 0) {
|
|
16996
|
+
const result2 = {
|
|
16997
|
+
prefix: input.prefix,
|
|
16998
|
+
prefixSource: "apiDir",
|
|
16999
|
+
knownFixtureNames: dedupedSorted(supplied)
|
|
17000
|
+
};
|
|
17001
|
+
return result2;
|
|
17002
|
+
}
|
|
17003
|
+
const imported = collectFixtureImports(sourceFile);
|
|
17004
|
+
if (imported.length > 0) {
|
|
17005
|
+
const detectedPrefix = detectPrefixFromImports(imported);
|
|
17006
|
+
const result2 = {
|
|
17007
|
+
prefix: detectedPrefix,
|
|
17008
|
+
prefixSource: "imports",
|
|
17009
|
+
knownFixtureNames: dedupedSorted(imported)
|
|
17010
|
+
};
|
|
17011
|
+
return result2;
|
|
17012
|
+
}
|
|
17013
|
+
const result = { prefix: void 0, prefixSource: "unknown", knownFixtureNames: [] };
|
|
17014
|
+
return result;
|
|
17015
|
+
}
|
|
17016
|
+
function collectFixtureImports(sourceFile) {
|
|
17017
|
+
const seen = /* @__PURE__ */ new Set();
|
|
17018
|
+
for (const decl of sourceFile.getImportDeclarations()) {
|
|
17019
|
+
const spec = decl.getModuleSpecifierValue();
|
|
17020
|
+
if (!matchesFixtureModulePath(spec)) continue;
|
|
17021
|
+
for (const named of decl.getNamedImports()) {
|
|
17022
|
+
const name = named.getName();
|
|
17023
|
+
if (!name.endsWith(FIXTURE_CONTEXT_SUFFIX)) continue;
|
|
17024
|
+
if (name.endsWith(FIXTURE_FACTORY_SUFFIX)) continue;
|
|
17025
|
+
if (!/^[a-z]/.test(name)) continue;
|
|
17026
|
+
seen.add(name);
|
|
17027
|
+
}
|
|
17028
|
+
}
|
|
17029
|
+
return [...seen];
|
|
17030
|
+
}
|
|
17031
|
+
function matchesFixtureModulePath(spec) {
|
|
17032
|
+
return /(^|\/)test\/fixture(\.[a-z]+)?$/.test(spec);
|
|
17033
|
+
}
|
|
17034
|
+
function detectPrefixFromImports(names) {
|
|
17035
|
+
if (names.length === 0) return void 0;
|
|
17036
|
+
const stems = names.map((n) => n.slice(0, n.length - FIXTURE_CONTEXT_SUFFIX.length));
|
|
17037
|
+
let common = stems[0];
|
|
17038
|
+
for (let i = 1; i < stems.length; i++) {
|
|
17039
|
+
common = sharedPrefix(common, stems[i]);
|
|
17040
|
+
if (common.length === 0) return void 0;
|
|
17041
|
+
}
|
|
17042
|
+
const camelEnd = trimToCamelBoundary(common);
|
|
17043
|
+
if (camelEnd.length === 0) return void 0;
|
|
17044
|
+
return camelEnd.charAt(0).toUpperCase() + camelEnd.slice(1);
|
|
17045
|
+
}
|
|
17046
|
+
function sharedPrefix(a, b) {
|
|
17047
|
+
const max = Math.min(a.length, b.length);
|
|
17048
|
+
let i = 0;
|
|
17049
|
+
while (i < max && a.charAt(i) === b.charAt(i)) i++;
|
|
17050
|
+
return a.slice(0, i);
|
|
17051
|
+
}
|
|
17052
|
+
function trimToCamelBoundary(s) {
|
|
17053
|
+
for (let i = s.length - 1; i >= 0; i--) {
|
|
17054
|
+
if (/[A-Z]/.test(s.charAt(i))) {
|
|
17055
|
+
return s.slice(0, i);
|
|
17056
|
+
}
|
|
17057
|
+
}
|
|
17058
|
+
return s;
|
|
17059
|
+
}
|
|
17060
|
+
function dedupedSorted(names) {
|
|
17061
|
+
return [...new Set(names)].sort();
|
|
17062
|
+
}
|
|
17063
|
+
function walkCall(call, ctx) {
|
|
17064
|
+
const calleeName = getCalleeName(call);
|
|
17065
|
+
if (calleeName === void 0) return void 0;
|
|
17066
|
+
const line = call.getStartLineNumber();
|
|
17067
|
+
const endLine = call.getEndLineNumber();
|
|
17068
|
+
if (DESCRIBE_NAMES.has(calleeName)) {
|
|
17069
|
+
ctx.counts.describe += 1;
|
|
17070
|
+
return describeOrItNode("describe", call, calleeName, line, endLine, ctx);
|
|
17071
|
+
}
|
|
17072
|
+
if (IT_NAMES.has(calleeName)) {
|
|
17073
|
+
ctx.counts.it += 1;
|
|
17074
|
+
return describeOrItNode("it", call, calleeName, line, endLine, ctx);
|
|
17075
|
+
}
|
|
17076
|
+
if (HOOK_NAMES.has(calleeName)) {
|
|
17077
|
+
return hookNode(call, calleeName, line, endLine);
|
|
17078
|
+
}
|
|
17079
|
+
if (isKnownFixtureName(calleeName, ctx)) {
|
|
17080
|
+
ctx.counts.fixture += 1;
|
|
17081
|
+
return fixtureNode(call, calleeName, ctx, line, endLine);
|
|
17082
|
+
}
|
|
17083
|
+
if (ctx.helperNames.has(calleeName)) {
|
|
17084
|
+
return helperCallNode(call, calleeName, ctx, line, endLine);
|
|
17085
|
+
}
|
|
17086
|
+
const callback = findCallback(call);
|
|
17087
|
+
if (callback === void 0) return void 0;
|
|
17088
|
+
const wrapperChildren = walkCallbackBody(callback, ctx);
|
|
17089
|
+
const wrapper = { kind: "wrapper", callee: calleeName, line, endLine, children: wrapperChildren };
|
|
17090
|
+
return wrapper;
|
|
17091
|
+
}
|
|
17092
|
+
function isKnownFixtureName(name, ctx) {
|
|
17093
|
+
if (ctx.knownFixtureNames.length > 0) {
|
|
17094
|
+
return ctx.knownFixtureNames.includes(name);
|
|
17095
|
+
}
|
|
17096
|
+
if (!name.endsWith(FIXTURE_CONTEXT_SUFFIX)) return false;
|
|
17097
|
+
if (name.endsWith(FIXTURE_FACTORY_SUFFIX)) return false;
|
|
17098
|
+
if (!/^[a-z]/.test(name)) return false;
|
|
17099
|
+
if (ctx.prefix !== void 0) {
|
|
17100
|
+
const lowerPrefix = ctx.prefix.charAt(0).toLowerCase() + ctx.prefix.slice(1);
|
|
17101
|
+
if (!name.startsWith(lowerPrefix)) return false;
|
|
17102
|
+
}
|
|
17103
|
+
return true;
|
|
17104
|
+
}
|
|
17105
|
+
function describeOrItNode(kind, call, calleeName, line, endLine, ctx) {
|
|
17106
|
+
const args = call.getArguments();
|
|
17107
|
+
const titleArg = args[0];
|
|
17108
|
+
const titleInfo = readTitle(titleArg);
|
|
17109
|
+
const callback = findCallback(call);
|
|
17110
|
+
const children = kind === "describe" && callback !== void 0 ? walkCallbackBody(callback, ctx) : [];
|
|
17111
|
+
const node = {
|
|
17112
|
+
kind,
|
|
17113
|
+
title: titleInfo.title,
|
|
17114
|
+
titleIsTemplate: titleInfo.titleIsTemplate || void 0,
|
|
17115
|
+
callee: calleeName === kind ? void 0 : calleeName,
|
|
17116
|
+
line,
|
|
17117
|
+
endLine,
|
|
17118
|
+
children
|
|
17119
|
+
};
|
|
17120
|
+
return node;
|
|
17121
|
+
}
|
|
17122
|
+
function hookNode(_call, calleeName, line, endLine) {
|
|
17123
|
+
const node = { kind: "hook", title: calleeName, line, endLine, children: [] };
|
|
17124
|
+
return node;
|
|
17125
|
+
}
|
|
17126
|
+
function fixtureNode(call, calleeName, ctx, line, endLine) {
|
|
17127
|
+
const args = call.getArguments();
|
|
17128
|
+
const argsObject = args[0];
|
|
17129
|
+
const parentVars = Node12.isObjectLiteralExpression(argsObject) ? readParentVars(argsObject) : [];
|
|
17130
|
+
const callback = findCallback(call);
|
|
17131
|
+
const varName = callback !== void 0 ? readCallbackVarName(callback) : void 0;
|
|
17132
|
+
const model = stripFixturePrefix(calleeName, ctx.prefix);
|
|
17133
|
+
const children = callback !== void 0 ? walkCallbackBody(callback, ctx) : [];
|
|
17134
|
+
const node = {
|
|
17135
|
+
kind: "fixture",
|
|
17136
|
+
callee: calleeName,
|
|
17137
|
+
model,
|
|
17138
|
+
varName,
|
|
17139
|
+
parentVars: parentVars.length > 0 ? parentVars : void 0,
|
|
17140
|
+
line,
|
|
17141
|
+
endLine,
|
|
17142
|
+
children
|
|
17143
|
+
};
|
|
17144
|
+
return node;
|
|
17145
|
+
}
|
|
17146
|
+
function helperCallNode(call, calleeName, ctx, line, endLine) {
|
|
17147
|
+
const callback = findCallback(call);
|
|
17148
|
+
const children = callback !== void 0 ? walkCallbackBody(callback, ctx) : [];
|
|
17149
|
+
const node = { kind: "helperCall", callee: calleeName, line, endLine, children };
|
|
17150
|
+
return node;
|
|
17151
|
+
}
|
|
17152
|
+
function stripFixturePrefix(name, prefix) {
|
|
17153
|
+
if (!name.endsWith(FIXTURE_CONTEXT_SUFFIX)) return void 0;
|
|
17154
|
+
const stem = name.slice(0, name.length - FIXTURE_CONTEXT_SUFFIX.length);
|
|
17155
|
+
if (prefix === void 0 || prefix === "") {
|
|
17156
|
+
if (stem.length === 0) return void 0;
|
|
17157
|
+
return stem.charAt(0).toUpperCase() + stem.slice(1);
|
|
17158
|
+
}
|
|
17159
|
+
const lower = prefix.charAt(0).toLowerCase() + prefix.slice(1);
|
|
17160
|
+
if (!stem.startsWith(lower)) return void 0;
|
|
17161
|
+
const model = stem.slice(lower.length);
|
|
17162
|
+
return model.length > 0 ? model : void 0;
|
|
17163
|
+
}
|
|
17164
|
+
function readTitle(arg) {
|
|
17165
|
+
if (arg === void 0) return { title: void 0, titleIsTemplate: false };
|
|
17166
|
+
if (Node12.isStringLiteral(arg) || Node12.isNoSubstitutionTemplateLiteral(arg)) {
|
|
17167
|
+
const result2 = { title: arg.getLiteralText(), titleIsTemplate: false };
|
|
17168
|
+
return result2;
|
|
17169
|
+
}
|
|
17170
|
+
if (Node12.isTemplateExpression(arg)) {
|
|
17171
|
+
const result2 = { title: arg.getText(), titleIsTemplate: true };
|
|
17172
|
+
return result2;
|
|
17173
|
+
}
|
|
17174
|
+
const result = { title: arg.getText(), titleIsTemplate: true };
|
|
17175
|
+
return result;
|
|
17176
|
+
}
|
|
17177
|
+
function findCallback(call) {
|
|
17178
|
+
const args = call.getArguments();
|
|
17179
|
+
for (let i = args.length - 1; i >= 0; i--) {
|
|
17180
|
+
const a = args[i];
|
|
17181
|
+
if (Node12.isArrowFunction(a) || Node12.isFunctionExpression(a)) {
|
|
17182
|
+
return a;
|
|
17183
|
+
}
|
|
17184
|
+
}
|
|
17185
|
+
return void 0;
|
|
17186
|
+
}
|
|
17187
|
+
function readCallbackVarName(callback) {
|
|
17188
|
+
const params = callback.getParameters();
|
|
17189
|
+
if (params.length === 0) return void 0;
|
|
17190
|
+
const first = params[0];
|
|
17191
|
+
const nameNode = first.getNameNode();
|
|
17192
|
+
if (Node12.isIdentifier(nameNode)) {
|
|
17193
|
+
return nameNode.getText();
|
|
17194
|
+
}
|
|
17195
|
+
return void 0;
|
|
17196
|
+
}
|
|
17197
|
+
function readParentVars(obj) {
|
|
17198
|
+
const out = [];
|
|
17199
|
+
for (const prop of obj.getProperties()) {
|
|
17200
|
+
if (Node12.isShorthandPropertyAssignment(prop)) {
|
|
17201
|
+
out.push(prop.getName());
|
|
17202
|
+
continue;
|
|
17203
|
+
}
|
|
17204
|
+
if (Node12.isPropertyAssignment(prop)) {
|
|
17205
|
+
const init = prop.getInitializer();
|
|
17206
|
+
if (init !== void 0 && Node12.isIdentifier(init)) {
|
|
17207
|
+
out.push(init.getText());
|
|
17208
|
+
}
|
|
17209
|
+
}
|
|
17210
|
+
}
|
|
17211
|
+
return out;
|
|
17212
|
+
}
|
|
17213
|
+
function walkCallbackBody(callback, ctx) {
|
|
17214
|
+
const body = callback.getBody();
|
|
17215
|
+
if (Node12.isBlock(body)) {
|
|
17216
|
+
return walkBlock(body, ctx);
|
|
17217
|
+
}
|
|
17218
|
+
if (Node12.isCallExpression(body)) {
|
|
17219
|
+
const child = walkCall(body, ctx);
|
|
17220
|
+
return child === void 0 ? [] : [child];
|
|
17221
|
+
}
|
|
17222
|
+
return [];
|
|
17223
|
+
}
|
|
17224
|
+
function walkBlock(block, ctx) {
|
|
17225
|
+
const children = [];
|
|
17226
|
+
for (const stmt of block.getStatements()) {
|
|
17227
|
+
if (!Node12.isExpressionStatement(stmt)) continue;
|
|
17228
|
+
const expr = stmt.getExpression();
|
|
17229
|
+
if (!Node12.isCallExpression(expr)) continue;
|
|
17230
|
+
const child = walkCall(expr, ctx);
|
|
17231
|
+
if (child !== void 0) {
|
|
17232
|
+
children.push(child);
|
|
17233
|
+
}
|
|
17234
|
+
}
|
|
17235
|
+
return children;
|
|
17236
|
+
}
|
|
17237
|
+
function getCalleeName(call) {
|
|
17238
|
+
const expr = call.getExpression();
|
|
17239
|
+
if (Node12.isIdentifier(expr)) return expr.getText();
|
|
17240
|
+
return void 0;
|
|
17241
|
+
}
|
|
17242
|
+
function collectHelpers(sourceFile) {
|
|
17243
|
+
const out = [];
|
|
17244
|
+
for (const fn of sourceFile.getFunctions()) {
|
|
17245
|
+
const name = fn.getName();
|
|
17246
|
+
if (name === void 0) continue;
|
|
17247
|
+
const usage = scanForDescribeOrIt(fn);
|
|
17248
|
+
if (!usage.emitsDescribe && !usage.emitsIt) continue;
|
|
17249
|
+
out.push({ name, line: fn.getStartLineNumber(), endLine: fn.getEndLineNumber(), emitsDescribe: usage.emitsDescribe, emitsIt: usage.emitsIt });
|
|
17250
|
+
}
|
|
17251
|
+
for (const v of sourceFile.getVariableStatements()) {
|
|
17252
|
+
for (const decl of v.getDeclarations()) {
|
|
17253
|
+
const init = decl.getInitializer();
|
|
17254
|
+
if (init === void 0) continue;
|
|
17255
|
+
if (!Node12.isArrowFunction(init) && !Node12.isFunctionExpression(init)) continue;
|
|
17256
|
+
const usage = scanForDescribeOrIt(init);
|
|
17257
|
+
if (!usage.emitsDescribe && !usage.emitsIt) continue;
|
|
17258
|
+
out.push({ name: decl.getName(), line: decl.getStartLineNumber(), endLine: decl.getEndLineNumber(), emitsDescribe: usage.emitsDescribe, emitsIt: usage.emitsIt });
|
|
17259
|
+
}
|
|
17260
|
+
}
|
|
17261
|
+
return out;
|
|
17262
|
+
}
|
|
17263
|
+
function scanForDescribeOrIt(node) {
|
|
17264
|
+
const usage = { emitsDescribe: false, emitsIt: false };
|
|
17265
|
+
node.forEachDescendant((descendant) => {
|
|
17266
|
+
if (descendant.getKind() !== SyntaxKind7.CallExpression) return;
|
|
17267
|
+
const call = descendant;
|
|
17268
|
+
const expr = call.getExpression();
|
|
17269
|
+
if (!Node12.isIdentifier(expr)) return;
|
|
17270
|
+
const name = expr.getText();
|
|
17271
|
+
if (DESCRIBE_NAMES.has(name)) usage.emitsDescribe = true;
|
|
17272
|
+
if (IT_NAMES.has(name)) usage.emitsIt = true;
|
|
17273
|
+
});
|
|
17274
|
+
return usage;
|
|
17275
|
+
}
|
|
17276
|
+
|
|
17277
|
+
// packages/dbx-components-mcp/src/tools/model-test-shared/inspect.ts
|
|
17278
|
+
import { readFile as readFile7 } from "node:fs/promises";
|
|
17279
|
+
async function inspectSpecFile(config) {
|
|
17280
|
+
const { specAbs, specRel, apiAbs, apiRel } = config;
|
|
17281
|
+
const text = await readFile7(specAbs, "utf8");
|
|
17282
|
+
let prefix;
|
|
17283
|
+
let knownFixtureNames;
|
|
17284
|
+
if (apiAbs !== void 0 && apiRel !== void 0) {
|
|
17285
|
+
try {
|
|
17286
|
+
const fixtures = await inspectAppFixtures(apiAbs, apiRel);
|
|
17287
|
+
prefix = fixtures.prefix;
|
|
17288
|
+
const lowerPrefix = prefix !== void 0 ? prefix.charAt(0).toLowerCase() + prefix.slice(1) : "";
|
|
17289
|
+
knownFixtureNames = fixtures.entries.map((entry) => `${lowerPrefix}${entry.model}Context`);
|
|
17290
|
+
} catch {
|
|
17291
|
+
}
|
|
17292
|
+
}
|
|
17293
|
+
return extractSpecTreeFromText({ text, specPath: specRel, prefix, knownFixtureNames });
|
|
17294
|
+
}
|
|
17295
|
+
|
|
17296
|
+
// packages/dbx-components-mcp/src/tools/model-test-shared/search.ts
|
|
17297
|
+
function searchSpecTree(tree, query) {
|
|
17298
|
+
const hits = [];
|
|
17299
|
+
const describeStack = [];
|
|
17300
|
+
const fixtureStack = [];
|
|
17301
|
+
const visit = (node) => {
|
|
17302
|
+
matchNode(node, query, describeStack, fixtureStack, hits);
|
|
17303
|
+
let pushedDescribe = false;
|
|
17304
|
+
let pushedFixture = false;
|
|
17305
|
+
if (node.kind === "describe" && node.title !== void 0) {
|
|
17306
|
+
describeStack.push(node.title);
|
|
17307
|
+
pushedDescribe = true;
|
|
17308
|
+
}
|
|
17309
|
+
if (node.kind === "fixture" && node.model !== void 0) {
|
|
17310
|
+
fixtureStack.push(node.model);
|
|
17311
|
+
pushedFixture = true;
|
|
17312
|
+
}
|
|
17313
|
+
for (const child of node.children) {
|
|
17314
|
+
visit(child);
|
|
17315
|
+
}
|
|
17316
|
+
if (pushedDescribe) describeStack.pop();
|
|
17317
|
+
if (pushedFixture) fixtureStack.pop();
|
|
17318
|
+
};
|
|
17319
|
+
for (const child of tree.root.children) {
|
|
17320
|
+
visit(child);
|
|
17321
|
+
}
|
|
17322
|
+
const result = { query, hits };
|
|
17323
|
+
return result;
|
|
17324
|
+
}
|
|
17325
|
+
function matchNode(node, query, describeStack, fixtureStack, hits) {
|
|
17326
|
+
let matched = false;
|
|
17327
|
+
switch (query.mode) {
|
|
17328
|
+
case "model":
|
|
17329
|
+
matched = node.kind === "fixture" && node.model?.toLowerCase() === query.value.toLowerCase();
|
|
17330
|
+
break;
|
|
17331
|
+
case "chain":
|
|
17332
|
+
matched = node.kind === "fixture" && chainContainsSequence([...fixtureStack, node.model ?? ""], parseChainQuery(query.value));
|
|
17333
|
+
break;
|
|
17334
|
+
case "describe":
|
|
17335
|
+
matched = node.kind === "describe" && node.title !== void 0 && node.title.toLowerCase().includes(query.value.toLowerCase());
|
|
17336
|
+
break;
|
|
17337
|
+
case "it":
|
|
17338
|
+
matched = node.kind === "it" && node.title !== void 0 && node.title.toLowerCase().includes(query.value.toLowerCase());
|
|
17339
|
+
break;
|
|
17340
|
+
default: {
|
|
17341
|
+
const exhaustive = query;
|
|
17342
|
+
void exhaustive;
|
|
17343
|
+
}
|
|
17344
|
+
}
|
|
17345
|
+
if (!matched) return;
|
|
17346
|
+
const hit = {
|
|
17347
|
+
kind: node.kind,
|
|
17348
|
+
title: node.title,
|
|
17349
|
+
model: node.model,
|
|
17350
|
+
callee: node.callee,
|
|
17351
|
+
line: node.line,
|
|
17352
|
+
endLine: node.endLine,
|
|
17353
|
+
describePath: [...describeStack],
|
|
17354
|
+
fixtureChain: [...fixtureStack]
|
|
17355
|
+
};
|
|
17356
|
+
hits.push(hit);
|
|
17357
|
+
}
|
|
17358
|
+
function parseChainQuery(value) {
|
|
17359
|
+
return value.split(">").map((s) => s.trim()).filter((s) => s.length > 0).map((s) => s.toLowerCase());
|
|
17360
|
+
}
|
|
17361
|
+
function chainContainsSequence(chain, sequence) {
|
|
17362
|
+
if (sequence.length === 0) return true;
|
|
17363
|
+
if (sequence.length > chain.length) return false;
|
|
17364
|
+
const lowerChain = chain.map((s) => s.toLowerCase());
|
|
17365
|
+
outer: for (let i = 0; i <= lowerChain.length - sequence.length; i++) {
|
|
17366
|
+
for (const [j, element] of sequence.entries()) {
|
|
17367
|
+
if (lowerChain[i + j] !== element) continue outer;
|
|
17368
|
+
}
|
|
17369
|
+
return true;
|
|
17370
|
+
}
|
|
17371
|
+
return false;
|
|
17372
|
+
}
|
|
17373
|
+
|
|
17374
|
+
// packages/dbx-components-mcp/src/tools/model-test-shared/format.json.ts
|
|
17375
|
+
function formatTreeAsJson(tree, view = "all", filters = {}) {
|
|
17376
|
+
if (view === "helpers") {
|
|
17377
|
+
const result2 = { specPath: tree.specPath, prefix: tree.prefix, prefixSource: tree.prefixSource, helpers: tree.helpers };
|
|
17378
|
+
return JSON.stringify(result2, null, 2);
|
|
17379
|
+
}
|
|
17380
|
+
if (view === "its") {
|
|
17381
|
+
const its = collectIts(tree);
|
|
17382
|
+
const result2 = { specPath: tree.specPath, prefix: tree.prefix, prefixSource: tree.prefixSource, its };
|
|
17383
|
+
return JSON.stringify(result2, null, 2);
|
|
17384
|
+
}
|
|
17385
|
+
const filteredRoot = applyFilters(tree.root, view, filters);
|
|
17386
|
+
const result = { specPath: tree.specPath, prefix: tree.prefix, prefixSource: tree.prefixSource, knownFixtureNames: tree.knownFixtureNames, view, filters, counts: { describes: tree.describeCount, its: tree.itCount, fixtures: tree.fixtureCallsCount, helpers: tree.helpers.length }, root: filteredRoot };
|
|
17387
|
+
return JSON.stringify(result, null, 2);
|
|
17388
|
+
}
|
|
17389
|
+
function formatSearchAsJson(tree, result) {
|
|
17390
|
+
const payload = { specPath: tree.specPath, prefix: tree.prefix, prefixSource: tree.prefixSource, query: result.query, hits: result.hits };
|
|
17391
|
+
return JSON.stringify(payload, null, 2);
|
|
17392
|
+
}
|
|
17393
|
+
function collectIts(tree) {
|
|
17394
|
+
const out = [];
|
|
17395
|
+
const stack = [];
|
|
17396
|
+
const visit = (node) => {
|
|
17397
|
+
if (node.kind === "it") {
|
|
17398
|
+
const entry = { describePath: [...stack], title: node.title, titleIsTemplate: node.titleIsTemplate, line: node.line, endLine: node.endLine };
|
|
17399
|
+
out.push(entry);
|
|
17400
|
+
}
|
|
17401
|
+
let pushed = false;
|
|
17402
|
+
if (node.kind === "describe" && node.title !== void 0) {
|
|
17403
|
+
stack.push(node.title);
|
|
17404
|
+
pushed = true;
|
|
17405
|
+
}
|
|
17406
|
+
for (const child of node.children) visit(child);
|
|
17407
|
+
if (pushed) stack.pop();
|
|
17408
|
+
};
|
|
17409
|
+
for (const c of tree.root.children) visit(c);
|
|
17410
|
+
return out;
|
|
17411
|
+
}
|
|
17412
|
+
function applyFilters(root, view, filters) {
|
|
17413
|
+
let next = view === "describes" ? collapseTo(root, ["describe", "it", "hook", "helperCall"]) : view === "fixtures" ? collapseTo(root, ["fixture"]) : root;
|
|
17414
|
+
if (filters.filterByModel !== void 0 && filters.filterByModel !== "") {
|
|
17415
|
+
next = pruneByModel(next, filters.filterByModel.toLowerCase()) ?? { ...next, children: [] };
|
|
17416
|
+
}
|
|
17417
|
+
if (filters.filterByDescribePath !== void 0 && filters.filterByDescribePath !== "") {
|
|
17418
|
+
next = pruneByDescribePath(next, parseDescribePath(filters.filterByDescribePath)) ?? { ...next, children: [] };
|
|
17419
|
+
}
|
|
17420
|
+
return next;
|
|
17421
|
+
}
|
|
17422
|
+
function collapseTo(node, keep) {
|
|
17423
|
+
const collapsedChildren = [];
|
|
17424
|
+
for (const child of node.children) {
|
|
17425
|
+
const transformed = collapseTo(child, keep);
|
|
17426
|
+
if (keep.includes(child.kind)) {
|
|
17427
|
+
collapsedChildren.push(transformed);
|
|
17428
|
+
} else {
|
|
17429
|
+
collapsedChildren.push(...transformed.children);
|
|
17430
|
+
}
|
|
17431
|
+
}
|
|
17432
|
+
return { ...node, children: collapsedChildren };
|
|
17433
|
+
}
|
|
17434
|
+
function pruneByModel(node, model) {
|
|
17435
|
+
const matchedSelf = node.kind === "fixture" && node.model?.toLowerCase() === model;
|
|
17436
|
+
const prunedChildren = [];
|
|
17437
|
+
for (const child of node.children) {
|
|
17438
|
+
const result = pruneByModel(child, model);
|
|
17439
|
+
if (result !== void 0) prunedChildren.push(result);
|
|
17440
|
+
}
|
|
17441
|
+
if (matchedSelf || prunedChildren.length > 0) {
|
|
17442
|
+
return { ...node, children: prunedChildren };
|
|
17443
|
+
}
|
|
17444
|
+
return void 0;
|
|
17445
|
+
}
|
|
17446
|
+
function pruneByDescribePath(node, path) {
|
|
17447
|
+
if (path.length === 0) return node;
|
|
17448
|
+
const matched = [];
|
|
17449
|
+
collectDescribesMatching(node, path, [], matched);
|
|
17450
|
+
if (matched.length === 0) return void 0;
|
|
17451
|
+
return { ...node, children: matched };
|
|
17452
|
+
}
|
|
17453
|
+
function collectDescribesMatching(node, target, stack, out) {
|
|
17454
|
+
if (node.kind === "describe" && node.title !== void 0) {
|
|
17455
|
+
stack.push(node.title.toLowerCase());
|
|
17456
|
+
if (pathStartsWith(stack, target)) {
|
|
17457
|
+
out.push(node);
|
|
17458
|
+
stack.pop();
|
|
17459
|
+
return;
|
|
17460
|
+
}
|
|
17461
|
+
}
|
|
17462
|
+
for (const child of node.children) collectDescribesMatching(child, target, stack, out);
|
|
17463
|
+
if (node.kind === "describe" && node.title !== void 0) stack.pop();
|
|
17464
|
+
}
|
|
17465
|
+
function pathStartsWith(actual, expected) {
|
|
17466
|
+
if (expected.length > actual.length) return false;
|
|
17467
|
+
for (const [i, element] of expected.entries()) {
|
|
17468
|
+
if (!actual[i].includes(element)) return false;
|
|
17469
|
+
}
|
|
17470
|
+
return true;
|
|
17471
|
+
}
|
|
17472
|
+
function parseDescribePath(value) {
|
|
17473
|
+
return value.split(">").map((s) => s.trim().toLowerCase()).filter((s) => s.length > 0);
|
|
17474
|
+
}
|
|
17475
|
+
|
|
17476
|
+
// packages/dbx-components-mcp/src/tools/model-test-shared/format.markdown.ts
|
|
17477
|
+
var INDENT = " ";
|
|
17478
|
+
function formatTreeAsMarkdown(tree, view = "all", filters = {}) {
|
|
17479
|
+
const lines = [];
|
|
17480
|
+
appendHeader(lines, tree, view, filters);
|
|
17481
|
+
if (view === "helpers") {
|
|
17482
|
+
appendHelpersSection(lines, tree.helpers);
|
|
17483
|
+
return lines.join("\n");
|
|
17484
|
+
}
|
|
17485
|
+
if (view === "its") {
|
|
17486
|
+
appendItIndex(lines, tree);
|
|
17487
|
+
return lines.join("\n");
|
|
17488
|
+
}
|
|
17489
|
+
const filteredRoot = applyFilters2(tree.root, view, filters);
|
|
17490
|
+
if (filteredRoot.children.length === 0) {
|
|
17491
|
+
lines.push("", "_No matching nodes._");
|
|
17492
|
+
return lines.join("\n");
|
|
17493
|
+
}
|
|
17494
|
+
lines.push("", `## Tree (view: ${view})`);
|
|
17495
|
+
if (filters.filterByModel) lines.push(`Filter \u2014 model: \`${filters.filterByModel}\``);
|
|
17496
|
+
if (filters.filterByDescribePath) lines.push(`Filter \u2014 describePath: \`${filters.filterByDescribePath}\``);
|
|
17497
|
+
lines.push("");
|
|
17498
|
+
for (const child of filteredRoot.children) {
|
|
17499
|
+
appendNode(lines, child, 0);
|
|
17500
|
+
}
|
|
17501
|
+
return lines.join("\n");
|
|
17502
|
+
}
|
|
17503
|
+
function formatSearchAsMarkdown(tree, result) {
|
|
17504
|
+
const lines = [];
|
|
17505
|
+
lines.push(`# Spec search \u2014 ${tree.specPath}`);
|
|
17506
|
+
lines.push("");
|
|
17507
|
+
lines.push(`Query: \`${result.query.mode}\` = \`${result.query.value}\``);
|
|
17508
|
+
lines.push(`Matches: ${result.hits.length}`);
|
|
17509
|
+
if (result.hits.length === 0) {
|
|
17510
|
+
lines.push("", "_No matches._");
|
|
17511
|
+
return lines.join("\n");
|
|
17512
|
+
}
|
|
17513
|
+
lines.push("");
|
|
17514
|
+
for (const hit of result.hits) {
|
|
17515
|
+
appendHit(lines, hit);
|
|
17516
|
+
}
|
|
17517
|
+
return lines.join("\n");
|
|
17518
|
+
}
|
|
17519
|
+
function appendHeader(lines, tree, view, filters) {
|
|
17520
|
+
lines.push(`# Spec tree \u2014 ${tree.specPath}`);
|
|
17521
|
+
lines.push("");
|
|
17522
|
+
lines.push(`Detected workspace prefix: \`${tree.prefix ?? "(none)"}\` (source: ${tree.prefixSource})`);
|
|
17523
|
+
lines.push(`Counts: ${tree.describeCount} describes, ${tree.itCount} its, ${tree.fixtureCallsCount} fixture calls, ${tree.helpers.length} helper-describes`);
|
|
17524
|
+
if (view !== "helpers" && view !== "its" && (filters.filterByModel || filters.filterByDescribePath)) {
|
|
17525
|
+
lines.push(`Active filters: ${[filters.filterByModel ? `model=\`${filters.filterByModel}\`` : "", filters.filterByDescribePath ? `describePath=\`${filters.filterByDescribePath}\`` : ""].filter(Boolean).join(", ")}`);
|
|
17526
|
+
}
|
|
17527
|
+
}
|
|
17528
|
+
function appendHelpersSection(lines, helpers) {
|
|
17529
|
+
lines.push("", `## Helpers (${helpers.length})`);
|
|
17530
|
+
if (helpers.length === 0) {
|
|
17531
|
+
lines.push("", "_No helper-describes detected._");
|
|
17532
|
+
return;
|
|
17533
|
+
}
|
|
17534
|
+
lines.push("");
|
|
17535
|
+
lines.push("| Name | Emits | Lines |");
|
|
17536
|
+
lines.push("|---|---|---|");
|
|
17537
|
+
for (const h of helpers) {
|
|
17538
|
+
const emits = [];
|
|
17539
|
+
if (h.emitsDescribe) emits.push("describe");
|
|
17540
|
+
if (h.emitsIt) emits.push("it");
|
|
17541
|
+
lines.push(`| \`${h.name}\` | ${emits.join(", ")} | ${h.line}\u2013${h.endLine} |`);
|
|
17542
|
+
}
|
|
17543
|
+
}
|
|
17544
|
+
function appendItIndex(lines, tree) {
|
|
17545
|
+
const its = [];
|
|
17546
|
+
const stack = [];
|
|
17547
|
+
const collect = (node) => {
|
|
17548
|
+
if (node.kind === "it") {
|
|
17549
|
+
its.push({ describePath: [...stack], node });
|
|
17550
|
+
}
|
|
17551
|
+
let pushed = false;
|
|
17552
|
+
if (node.kind === "describe" && node.title !== void 0) {
|
|
17553
|
+
stack.push(node.title);
|
|
17554
|
+
pushed = true;
|
|
17555
|
+
}
|
|
17556
|
+
for (const child of node.children) collect(child);
|
|
17557
|
+
if (pushed) stack.pop();
|
|
17558
|
+
};
|
|
17559
|
+
for (const c of tree.root.children) collect(c);
|
|
17560
|
+
lines.push("", `## Tests (${its.length})`);
|
|
17561
|
+
if (its.length === 0) {
|
|
17562
|
+
lines.push("", "_No `it` calls detected._");
|
|
17563
|
+
return;
|
|
17564
|
+
}
|
|
17565
|
+
lines.push("");
|
|
17566
|
+
for (const { describePath, node } of its) {
|
|
17567
|
+
const path = describePath.length > 0 ? `${describePath.join(" > ")} > ` : "";
|
|
17568
|
+
const title = node.title !== void 0 ? node.titleIsTemplate ? `\`${node.title}\` _(template)_` : `\`${node.title}\`` : "_(no title)_";
|
|
17569
|
+
lines.push(`- ${path}${title} [L${node.line}]`);
|
|
17570
|
+
}
|
|
17571
|
+
}
|
|
17572
|
+
function appendHit(lines, hit) {
|
|
17573
|
+
const label = hitLabel(hit);
|
|
17574
|
+
lines.push(`- ${label} [L${hit.line}\u2013${hit.endLine}]`);
|
|
17575
|
+
if (hit.describePath.length > 0) {
|
|
17576
|
+
lines.push(`${INDENT}describes: ${hit.describePath.map((s) => `\`${s}\``).join(" > ")}`);
|
|
17577
|
+
}
|
|
17578
|
+
if (hit.fixtureChain.length > 0) {
|
|
17579
|
+
lines.push(`${INDENT}fixtures: ${hit.fixtureChain.map((s) => `\`${s}\``).join(" > ")}`);
|
|
17580
|
+
}
|
|
17581
|
+
}
|
|
17582
|
+
function hitLabel(hit) {
|
|
17583
|
+
switch (hit.kind) {
|
|
17584
|
+
case "fixture":
|
|
17585
|
+
return `**fixture** \`${hit.callee ?? "?"}\` \u2192 \`${hit.model ?? "?"}\``;
|
|
17586
|
+
case "describe":
|
|
17587
|
+
return `**describe** \`${hit.title ?? "?"}\``;
|
|
17588
|
+
case "it":
|
|
17589
|
+
return `**it** \`${hit.title ?? "?"}\``;
|
|
17590
|
+
case "helperCall":
|
|
17591
|
+
return `**helperCall** \`${hit.callee ?? "?"}\``;
|
|
17592
|
+
case "wrapper":
|
|
17593
|
+
return `**wrapper** \`${hit.callee ?? "?"}\``;
|
|
17594
|
+
case "hook":
|
|
17595
|
+
return `**${hit.title ?? "hook"}**`;
|
|
17596
|
+
default:
|
|
17597
|
+
return "**?**";
|
|
17598
|
+
}
|
|
17599
|
+
}
|
|
17600
|
+
function appendNode(lines, node, depth) {
|
|
17601
|
+
const indent = INDENT.repeat(depth);
|
|
17602
|
+
lines.push(`${indent}- ${nodeLabel(node)} [L${node.line}\u2013${node.endLine}]`);
|
|
17603
|
+
for (const child of node.children) {
|
|
17604
|
+
appendNode(lines, child, depth + 1);
|
|
17605
|
+
}
|
|
17606
|
+
}
|
|
17607
|
+
function nodeLabel(node) {
|
|
17608
|
+
switch (node.kind) {
|
|
17609
|
+
case "describe":
|
|
17610
|
+
return `**describe** ${node.title === void 0 ? "_(no title)_" : node.titleIsTemplate ? `\`${node.title}\` _(template)_` : `\`${node.title}\``}`;
|
|
17611
|
+
case "it":
|
|
17612
|
+
return `**it** ${node.title === void 0 ? "_(no title)_" : node.titleIsTemplate ? `\`${node.title}\` _(template)_` : `\`${node.title}\``}`;
|
|
17613
|
+
case "hook":
|
|
17614
|
+
return `**${node.title ?? "hook"}**`;
|
|
17615
|
+
case "fixture": {
|
|
17616
|
+
const var_ = node.varName !== void 0 ? ` _(as \`${node.varName}\`)_` : "";
|
|
17617
|
+
const parents = node.parentVars && node.parentVars.length > 0 ? ` deps: \`${node.parentVars.join(", ")}\`` : "";
|
|
17618
|
+
return `**fixture** \`${node.callee ?? "?"}\` \u2192 \`${node.model ?? "?"}\`${var_}${parents}`;
|
|
17619
|
+
}
|
|
17620
|
+
case "wrapper":
|
|
17621
|
+
return `**wrapper** \`${node.callee ?? "?"}\``;
|
|
17622
|
+
case "helperCall":
|
|
17623
|
+
return `**helperCall** \`${node.callee ?? "?"}\``;
|
|
17624
|
+
default:
|
|
17625
|
+
return "**?**";
|
|
17626
|
+
}
|
|
17627
|
+
}
|
|
17628
|
+
function applyFilters2(root, view, filters) {
|
|
17629
|
+
let next = view === "describes" ? collapseTo2(root, ["describe", "it", "hook", "helperCall"]) : view === "fixtures" ? collapseTo2(root, ["fixture"]) : root;
|
|
17630
|
+
if (filters.filterByModel !== void 0 && filters.filterByModel !== "") {
|
|
17631
|
+
next = pruneByModel2(next, filters.filterByModel.toLowerCase()) ?? { ...next, children: [] };
|
|
17632
|
+
}
|
|
17633
|
+
if (filters.filterByDescribePath !== void 0 && filters.filterByDescribePath !== "") {
|
|
17634
|
+
next = pruneByDescribePath2(next, parseDescribePath2(filters.filterByDescribePath)) ?? { ...next, children: [] };
|
|
17635
|
+
}
|
|
17636
|
+
return next;
|
|
17637
|
+
}
|
|
17638
|
+
function collapseTo2(node, keep) {
|
|
17639
|
+
const collapsedChildren = [];
|
|
17640
|
+
for (const child of node.children) {
|
|
17641
|
+
const transformed = collapseTo2(child, keep);
|
|
17642
|
+
if (keep.includes(child.kind)) {
|
|
17643
|
+
collapsedChildren.push(transformed);
|
|
17644
|
+
} else {
|
|
17645
|
+
collapsedChildren.push(...transformed.children);
|
|
17646
|
+
}
|
|
17647
|
+
}
|
|
17648
|
+
return { ...node, children: collapsedChildren };
|
|
17649
|
+
}
|
|
17650
|
+
function pruneByModel2(node, model) {
|
|
17651
|
+
const matchedSelf = node.kind === "fixture" && node.model?.toLowerCase() === model;
|
|
17652
|
+
const prunedChildren = [];
|
|
17653
|
+
for (const child of node.children) {
|
|
17654
|
+
const result = pruneByModel2(child, model);
|
|
17655
|
+
if (result !== void 0) prunedChildren.push(result);
|
|
17656
|
+
}
|
|
17657
|
+
if (matchedSelf || prunedChildren.length > 0) {
|
|
17658
|
+
return { ...node, children: prunedChildren };
|
|
17659
|
+
}
|
|
17660
|
+
return void 0;
|
|
17661
|
+
}
|
|
17662
|
+
function pruneByDescribePath2(node, path) {
|
|
17663
|
+
if (path.length === 0) return node;
|
|
17664
|
+
const matched = [];
|
|
17665
|
+
collectDescribesMatching2(node, path, [], matched);
|
|
17666
|
+
if (matched.length === 0) return void 0;
|
|
17667
|
+
return { ...node, children: matched };
|
|
17668
|
+
}
|
|
17669
|
+
function collectDescribesMatching2(node, target, stack, out) {
|
|
17670
|
+
if (node.kind === "describe" && node.title !== void 0) {
|
|
17671
|
+
stack.push(node.title.toLowerCase());
|
|
17672
|
+
if (pathStartsWith2(stack, target)) {
|
|
17673
|
+
out.push(node);
|
|
17674
|
+
stack.pop();
|
|
17675
|
+
return;
|
|
17676
|
+
}
|
|
17677
|
+
}
|
|
17678
|
+
for (const child of node.children) collectDescribesMatching2(child, target, stack, out);
|
|
17679
|
+
if (node.kind === "describe" && node.title !== void 0) stack.pop();
|
|
17680
|
+
}
|
|
17681
|
+
function pathStartsWith2(actual, expected) {
|
|
17682
|
+
if (expected.length > actual.length) return false;
|
|
17683
|
+
for (const [i, element] of expected.entries()) {
|
|
17684
|
+
if (!actual[i].includes(element)) return false;
|
|
17685
|
+
}
|
|
17686
|
+
return true;
|
|
17687
|
+
}
|
|
17688
|
+
function parseDescribePath2(value) {
|
|
17689
|
+
return value.split(">").map((s) => s.trim().toLowerCase()).filter((s) => s.length > 0);
|
|
17690
|
+
}
|
|
17691
|
+
|
|
17692
|
+
// packages/dbx-components-mcp/src/tools/model-test-tree.tool.ts
|
|
17693
|
+
var TreeArgsType = type37({
|
|
17694
|
+
specFile: "string",
|
|
17695
|
+
"apiDir?": "string",
|
|
17696
|
+
"view?": "'all' | 'describes' | 'fixtures' | 'its' | 'helpers'",
|
|
17697
|
+
"filterByModel?": "string",
|
|
17698
|
+
"filterByDescribePath?": "string",
|
|
17699
|
+
"format?": "'markdown' | 'json'"
|
|
17700
|
+
});
|
|
17701
|
+
var TOOL6 = {
|
|
17702
|
+
name: "dbx_model_test_tree",
|
|
17703
|
+
description: [
|
|
17704
|
+
"Parse one API `.spec.ts` file and return its structural skeleton \u2014 nested `describe`/`it` calls, `<prefix><Model>Context(...)` fixture chains, locally-defined helper-describe functions, and the wrapper calls between them. Each node carries its 1-based line range so callers can navigate by line offset instead of grepping.",
|
|
17705
|
+
"",
|
|
17706
|
+
"Provide:",
|
|
17707
|
+
"- `specFile`: relative path to the `.spec.ts` file (e.g. `apps/hellosubs-api/src/app/function/job/job.crud.instruction.spec.ts`).",
|
|
17708
|
+
"- `apiDir` (optional but recommended): relative path to the API app (e.g. `apps/hellosubs-api`). When supplied the tool reuses `inspectAppFixtures()` for the authoritative workspace prefix and the full set of `<prefix><Model>Context` names. When omitted the prefix is detected from the spec's own imports off `**/test/fixture`.",
|
|
17709
|
+
"- `view` (optional): `all` (default), `describes` (drop fixtures + wrappers), `fixtures` (only fixture chains, e.g. `Country > CountryState > Region > District > ...`), `its` (flat index of every `it()` with full describe path), or `helpers` (locally-defined helper-describe functions).",
|
|
17710
|
+
"- `filterByModel` (optional): keep only subtrees that contain a fixture call resolving to this model (e.g. `Job`).",
|
|
17711
|
+
"- `filterByDescribePath` (optional): keep only subtrees rooted at a describe whose `>`-separated path matches (e.g. `admin > job published`).",
|
|
17712
|
+
"- `format` (optional): `markdown` (default) or `json`.",
|
|
17713
|
+
"",
|
|
17714
|
+
"Paths escaping the server cwd are rejected."
|
|
17715
|
+
].join("\n"),
|
|
17716
|
+
inputSchema: {
|
|
17717
|
+
type: "object",
|
|
17718
|
+
properties: {
|
|
17719
|
+
specFile: { type: "string", description: "Relative path to the `.spec.ts` file." },
|
|
17720
|
+
apiDir: { type: "string", description: "Optional relative path to the API app. Enables authoritative prefix + fixture-name detection via `inspectAppFixtures()`." },
|
|
17721
|
+
view: { type: "string", enum: ["all", "describes", "fixtures", "its", "helpers"], description: "View mode. Defaults to `all`." },
|
|
17722
|
+
filterByModel: { type: "string", description: "Keep only subtrees that contain a fixture call resolving to this model (case-insensitive)." },
|
|
17723
|
+
filterByDescribePath: { type: "string", description: "`>`-separated describe path; keep only subtrees rooted there (case-insensitive substring per segment)." },
|
|
17724
|
+
format: { type: "string", enum: ["markdown", "json"], description: "Output format. Defaults to markdown." }
|
|
17725
|
+
},
|
|
17726
|
+
required: ["specFile"]
|
|
17727
|
+
}
|
|
17728
|
+
};
|
|
17729
|
+
async function run5(rawArgs) {
|
|
17730
|
+
const parsed = TreeArgsType(rawArgs);
|
|
17731
|
+
if (parsed instanceof type37.errors) {
|
|
17732
|
+
return toolError(`Invalid arguments: ${parsed.summary}`);
|
|
17733
|
+
}
|
|
17734
|
+
const cwd = process.cwd();
|
|
17735
|
+
try {
|
|
17736
|
+
ensurePathInsideCwd(parsed.specFile, cwd);
|
|
17737
|
+
if (parsed.apiDir !== void 0) ensurePathInsideCwd(parsed.apiDir, cwd);
|
|
17738
|
+
} catch (err) {
|
|
17739
|
+
return toolError(err instanceof Error ? err.message : String(err));
|
|
17740
|
+
}
|
|
17741
|
+
const specAbs = resolve22(cwd, parsed.specFile);
|
|
17742
|
+
const apiAbs = parsed.apiDir !== void 0 ? resolve22(cwd, parsed.apiDir) : void 0;
|
|
17743
|
+
let tree;
|
|
17744
|
+
try {
|
|
17745
|
+
tree = await inspectSpecFile({ specAbs, specRel: parsed.specFile, apiAbs, apiRel: parsed.apiDir });
|
|
17746
|
+
} catch (err) {
|
|
17747
|
+
return toolError(`Failed to read spec file: ${err instanceof Error ? err.message : String(err)}`);
|
|
17748
|
+
}
|
|
17749
|
+
const view = parsed.view ?? "all";
|
|
17750
|
+
const filters = { filterByModel: parsed.filterByModel, filterByDescribePath: parsed.filterByDescribePath };
|
|
17751
|
+
const text = parsed.format === "json" ? formatTreeAsJson(tree, view, filters) : formatTreeAsMarkdown(tree, view, filters);
|
|
17752
|
+
const result = { content: [{ type: "text", text }] };
|
|
17753
|
+
return result;
|
|
17754
|
+
}
|
|
17755
|
+
var modelTestTreeTool = { definition: TOOL6, run: run5 };
|
|
17756
|
+
|
|
17757
|
+
// packages/dbx-components-mcp/src/tools/model-test-search.tool.ts
|
|
17758
|
+
import { resolve as resolve23 } from "node:path";
|
|
17759
|
+
import { type as type38 } from "arktype";
|
|
17760
|
+
var SearchArgsType2 = type38({
|
|
17761
|
+
specFile: "string",
|
|
17762
|
+
"apiDir?": "string",
|
|
17763
|
+
"model?": "string",
|
|
17764
|
+
"chain?": "string",
|
|
17765
|
+
"describe?": "string",
|
|
17766
|
+
"it?": "string",
|
|
17767
|
+
"format?": "'markdown' | 'json'"
|
|
17768
|
+
});
|
|
17769
|
+
var TOOL7 = {
|
|
17770
|
+
name: "dbx_model_test_search",
|
|
17771
|
+
description: [
|
|
17772
|
+
"Search one API `.spec.ts` file for `describe`s, `it`s, or `<prefix><Model>Context(...)` fixture calls matching a single criterion. Each hit is returned with the full describe path and fixture chain leading to it, plus its line range, so callers can jump straight to the right block.",
|
|
17773
|
+
"",
|
|
17774
|
+
"Provide exactly one of:",
|
|
17775
|
+
"- `model`: bare PascalCase model name (e.g. `Job`) \u2014 matches every `<prefix>JobContext(...)` site.",
|
|
17776
|
+
"- `chain`: `>`-separated model sequence (e.g. `Country > CountryState`) \u2014 matches every fixture chain containing the consecutive subsequence.",
|
|
17777
|
+
"- `describe`: case-insensitive substring against `describe(...)` titles.",
|
|
17778
|
+
"- `it`: case-insensitive substring against `it(...)` / `test(...)` titles.",
|
|
17779
|
+
"",
|
|
17780
|
+
"Plus:",
|
|
17781
|
+
"- `specFile`: relative path to the `.spec.ts` file.",
|
|
17782
|
+
"- `apiDir` (optional but recommended): enables authoritative prefix + fixture-name detection via `inspectAppFixtures()`.",
|
|
17783
|
+
"- `format` (optional): `markdown` (default) or `json`."
|
|
17784
|
+
].join("\n"),
|
|
17785
|
+
inputSchema: {
|
|
17786
|
+
type: "object",
|
|
17787
|
+
properties: {
|
|
17788
|
+
specFile: { type: "string", description: "Relative path to the `.spec.ts` file." },
|
|
17789
|
+
apiDir: { type: "string", description: "Optional relative path to the API app." },
|
|
17790
|
+
model: { type: "string", description: "Bare PascalCase model name (e.g. `Job`)." },
|
|
17791
|
+
chain: { type: "string", description: "`>`-separated chain (e.g. `Country > CountryState`)." },
|
|
17792
|
+
describe: { type: "string", description: "Substring match against describe titles." },
|
|
17793
|
+
it: { type: "string", description: "Substring match against it/test titles." },
|
|
17794
|
+
format: { type: "string", enum: ["markdown", "json"], description: "Output format. Defaults to markdown." }
|
|
16690
17795
|
},
|
|
16691
|
-
required: ["
|
|
17796
|
+
required: ["specFile"]
|
|
16692
17797
|
}
|
|
16693
17798
|
};
|
|
16694
|
-
async function
|
|
16695
|
-
const parsed =
|
|
16696
|
-
if (parsed instanceof
|
|
17799
|
+
async function run6(rawArgs) {
|
|
17800
|
+
const parsed = SearchArgsType2(rawArgs);
|
|
17801
|
+
if (parsed instanceof type38.errors) {
|
|
16697
17802
|
return toolError(`Invalid arguments: ${parsed.summary}`);
|
|
16698
17803
|
}
|
|
16699
|
-
const
|
|
16700
|
-
|
|
16701
|
-
|
|
16702
|
-
|
|
16703
|
-
|
|
16704
|
-
|
|
16705
|
-
|
|
16706
|
-
|
|
16707
|
-
try {
|
|
16708
|
-
extraction = await inspectAppFixtures(apiAbs, parsed.apiDir);
|
|
16709
|
-
} catch (err) {
|
|
16710
|
-
return toolError(`Failed to read fixture file: ${toErrorMessage(err)}`);
|
|
16711
|
-
}
|
|
16712
|
-
const entry = extraction.entries.find((e) => e.model === parsed.model);
|
|
16713
|
-
if (!entry) {
|
|
16714
|
-
const known = extraction.entries.map((e) => e.model).join(", ") || "(none)";
|
|
16715
|
-
return toolError(`Model \`${parsed.model}\` not found in \`${extraction.fixturePath}\`. Known: ${known}.`);
|
|
16716
|
-
}
|
|
16717
|
-
const rendered = renderForwarders({ entry, methods: parsed.methods });
|
|
16718
|
-
if (rendered.added.length === 0) {
|
|
16719
|
-
return { content: [{ type: "text", text: renderNoOpReport(extraction.fixturePath, entry.fixtureClassName, rendered) }] };
|
|
17804
|
+
const queryFields = [
|
|
17805
|
+
{ mode: "model", value: parsed.model },
|
|
17806
|
+
{ mode: "chain", value: parsed.chain },
|
|
17807
|
+
{ mode: "describe", value: parsed.describe },
|
|
17808
|
+
{ mode: "it", value: parsed.it }
|
|
17809
|
+
].filter((q) => q.value !== void 0 && q.value !== "");
|
|
17810
|
+
if (queryFields.length === 0) {
|
|
17811
|
+
return toolError("Provide exactly one of `model`, `chain`, `describe`, or `it`.");
|
|
16720
17812
|
}
|
|
16721
|
-
|
|
16722
|
-
|
|
16723
|
-
if (writeError) {
|
|
16724
|
-
return toolError(writeError);
|
|
17813
|
+
if (queryFields.length > 1) {
|
|
17814
|
+
return toolError(`Provide exactly one query field. Received: ${queryFields.map((q) => q.mode).join(", ")}.`);
|
|
16725
17815
|
}
|
|
16726
|
-
|
|
16727
|
-
|
|
16728
|
-
function toErrorMessage(err) {
|
|
16729
|
-
return err instanceof Error ? err.message : String(err);
|
|
16730
|
-
}
|
|
16731
|
-
async function applyForwardersToFile(absolutePath, fixtureClassName, rendered) {
|
|
16732
|
-
const project = new Project8({ skipAddingFilesFromTsConfig: true });
|
|
16733
|
-
let sourceFile;
|
|
17816
|
+
const query = { mode: queryFields[0].mode, value: queryFields[0].value };
|
|
17817
|
+
const cwd = process.cwd();
|
|
16734
17818
|
try {
|
|
16735
|
-
|
|
17819
|
+
ensurePathInsideCwd(parsed.specFile, cwd);
|
|
17820
|
+
if (parsed.apiDir !== void 0) ensurePathInsideCwd(parsed.apiDir, cwd);
|
|
16736
17821
|
} catch (err) {
|
|
16737
|
-
return
|
|
16738
|
-
}
|
|
16739
|
-
const fixtureClass = sourceFile.getClass(fixtureClassName);
|
|
16740
|
-
if (!fixtureClass) {
|
|
16741
|
-
return `Could not locate class \`${fixtureClassName}\` for in-place edit. The fixture file may have been modified since parsing.`;
|
|
16742
|
-
}
|
|
16743
|
-
for (const forwarder of rendered.added) {
|
|
16744
|
-
fixtureClass.insertText(fixtureClass.getEnd() - 1, "\n" + forwarder.source + "\n");
|
|
17822
|
+
return toolError(err instanceof Error ? err.message : String(err));
|
|
16745
17823
|
}
|
|
16746
|
-
|
|
17824
|
+
const specAbs = resolve23(cwd, parsed.specFile);
|
|
17825
|
+
const apiAbs = parsed.apiDir !== void 0 ? resolve23(cwd, parsed.apiDir) : void 0;
|
|
17826
|
+
let tree;
|
|
16747
17827
|
try {
|
|
16748
|
-
await
|
|
17828
|
+
tree = await inspectSpecFile({ specAbs, specRel: parsed.specFile, apiAbs, apiRel: parsed.apiDir });
|
|
16749
17829
|
} catch (err) {
|
|
16750
|
-
return `Failed to
|
|
16751
|
-
}
|
|
16752
|
-
return void 0;
|
|
16753
|
-
}
|
|
16754
|
-
function renderNoOpReport(fixturePath, fixtureClassName, rendered) {
|
|
16755
|
-
const lines = [`# No forwarders to add for \`${fixtureClassName}\``, "", `File: \`${fixturePath}\``];
|
|
16756
|
-
appendListSection(lines, "## Already forwarded", rendered.skippedAlreadyForwarded);
|
|
16757
|
-
appendListSection(lines, "## Whitelisted methods missing from Instance", rendered.missingFromInstance);
|
|
16758
|
-
return lines.join("\n");
|
|
16759
|
-
}
|
|
16760
|
-
function renderSuccessReport(fixturePath, fixtureClassName, rendered) {
|
|
16761
|
-
const lines = [`# Forwarded ${rendered.added.length} method${rendered.added.length === 1 ? "" : "s"} to \`${fixtureClassName}\``, "", `File: \`${fixturePath}\``, "", "## Added"];
|
|
16762
|
-
for (const f of rendered.added) {
|
|
16763
|
-
lines.push(`- \`${f.method}\``);
|
|
16764
|
-
}
|
|
16765
|
-
appendListSection(lines, "## Skipped (already forwarded)", rendered.skippedAlreadyForwarded);
|
|
16766
|
-
appendListSection(lines, "## Whitelisted methods missing from Instance", rendered.missingFromInstance);
|
|
16767
|
-
return lines.join("\n");
|
|
16768
|
-
}
|
|
16769
|
-
function appendListSection(lines, heading, names) {
|
|
16770
|
-
if (names.length === 0) return;
|
|
16771
|
-
lines.push("", heading);
|
|
16772
|
-
for (const name of names) {
|
|
16773
|
-
lines.push(`- \`${name}\``);
|
|
17830
|
+
return toolError(`Failed to read spec file: ${err instanceof Error ? err.message : String(err)}`);
|
|
16774
17831
|
}
|
|
17832
|
+
const result = searchSpecTree(tree, query);
|
|
17833
|
+
const text = parsed.format === "json" ? formatSearchAsJson(tree, result) : formatSearchAsMarkdown(tree, result);
|
|
17834
|
+
const out = { content: [{ type: "text", text }] };
|
|
17835
|
+
return out;
|
|
16775
17836
|
}
|
|
16776
|
-
var
|
|
17837
|
+
var modelTestSearchTool = { definition: TOOL7, run: run6 };
|
|
16777
17838
|
|
|
16778
17839
|
// packages/dbx-components-mcp/src/tools/storagefile-m-validate-app/extract.ts
|
|
16779
|
-
import { Node as
|
|
17840
|
+
import { Node as Node14, SyntaxKind as SyntaxKind9 } from "ts-morph";
|
|
16780
17841
|
|
|
16781
17842
|
// packages/dbx-components-mcp/src/tools/_validate/ast.ts
|
|
16782
|
-
import { Node as
|
|
17843
|
+
import { Node as Node13, Project as Project10, SyntaxKind as SyntaxKind8 } from "ts-morph";
|
|
16783
17844
|
var COMPONENT_VIRTUAL_PREFIX = "__component__/";
|
|
16784
17845
|
var API_VIRTUAL_PREFIX = "__api__/";
|
|
16785
17846
|
function buildInMemoryProject(input) {
|
|
16786
|
-
const project = new
|
|
17847
|
+
const project = new Project10({ useInMemoryFileSystem: true, skipAddingFilesFromTsConfig: true });
|
|
16787
17848
|
const componentSources = [];
|
|
16788
17849
|
const apiSources = [];
|
|
16789
17850
|
for (const file of input.component.files) {
|
|
@@ -16803,28 +17864,28 @@ function componentRelPath(sourceFile) {
|
|
|
16803
17864
|
}
|
|
16804
17865
|
function unwrapAsExpressions(node) {
|
|
16805
17866
|
let current = node;
|
|
16806
|
-
while (current &&
|
|
17867
|
+
while (current && Node13.isAsExpression(current)) {
|
|
16807
17868
|
current = current.getExpression();
|
|
16808
17869
|
}
|
|
16809
17870
|
return current;
|
|
16810
17871
|
}
|
|
16811
17872
|
function asObjectLiteral(node) {
|
|
16812
17873
|
const inner = unwrapAsExpressions(node);
|
|
16813
|
-
if (inner &&
|
|
17874
|
+
if (inner && Node13.isObjectLiteralExpression(inner)) {
|
|
16814
17875
|
return inner;
|
|
16815
17876
|
}
|
|
16816
17877
|
return void 0;
|
|
16817
17878
|
}
|
|
16818
17879
|
function asArrayLiteral(node) {
|
|
16819
17880
|
const inner = unwrapAsExpressions(node);
|
|
16820
|
-
if (inner &&
|
|
17881
|
+
if (inner && Node13.isArrayLiteralExpression(inner)) {
|
|
16821
17882
|
return inner;
|
|
16822
17883
|
}
|
|
16823
17884
|
return void 0;
|
|
16824
17885
|
}
|
|
16825
17886
|
function readStringLiteralInitializer(decl) {
|
|
16826
17887
|
const initializer = unwrapAsExpressions(decl.getInitializer());
|
|
16827
|
-
if (initializer &&
|
|
17888
|
+
if (initializer && Node13.isStringLiteral(initializer)) {
|
|
16828
17889
|
return initializer.getLiteralText();
|
|
16829
17890
|
}
|
|
16830
17891
|
return void 0;
|
|
@@ -16836,37 +17897,37 @@ function typeAnnotationText(node) {
|
|
|
16836
17897
|
function getPropertyInitializer(obj, name) {
|
|
16837
17898
|
const prop = obj.getProperty(name);
|
|
16838
17899
|
if (!prop) return void 0;
|
|
16839
|
-
if (
|
|
17900
|
+
if (Node13.isPropertyAssignment(prop)) {
|
|
16840
17901
|
return prop.getInitializer();
|
|
16841
17902
|
}
|
|
16842
|
-
if (
|
|
17903
|
+
if (Node13.isShorthandPropertyAssignment(prop)) {
|
|
16843
17904
|
return prop.getNameNode();
|
|
16844
17905
|
}
|
|
16845
17906
|
return void 0;
|
|
16846
17907
|
}
|
|
16847
17908
|
function readStringProperty2(obj, name) {
|
|
16848
17909
|
const init = unwrapAsExpressions(getPropertyInitializer(obj, name));
|
|
16849
|
-
if (init &&
|
|
17910
|
+
if (init && Node13.isStringLiteral(init)) {
|
|
16850
17911
|
return init.getLiteralText();
|
|
16851
17912
|
}
|
|
16852
17913
|
return void 0;
|
|
16853
17914
|
}
|
|
16854
17915
|
function readIdentifierProperty(obj, name) {
|
|
16855
17916
|
const init = unwrapAsExpressions(getPropertyInitializer(obj, name));
|
|
16856
|
-
if (init &&
|
|
17917
|
+
if (init && Node13.isIdentifier(init)) {
|
|
16857
17918
|
return init.getText();
|
|
16858
17919
|
}
|
|
16859
17920
|
return void 0;
|
|
16860
17921
|
}
|
|
16861
17922
|
function findReturnExpression(fn) {
|
|
16862
|
-
if (!
|
|
17923
|
+
if (!Node13.isArrowFunction(fn) && !Node13.isFunctionDeclaration(fn) && !Node13.isFunctionExpression(fn)) {
|
|
16863
17924
|
return void 0;
|
|
16864
17925
|
}
|
|
16865
17926
|
const body = fn.getBody();
|
|
16866
17927
|
if (!body) return void 0;
|
|
16867
|
-
if (
|
|
17928
|
+
if (Node13.isBlock(body)) {
|
|
16868
17929
|
for (const stmt of body.getStatements()) {
|
|
16869
|
-
if (
|
|
17930
|
+
if (Node13.isReturnStatement(stmt)) {
|
|
16870
17931
|
return stmt.getExpression();
|
|
16871
17932
|
}
|
|
16872
17933
|
}
|
|
@@ -16880,17 +17941,17 @@ function findLocalVariable(sf, name) {
|
|
|
16880
17941
|
if (decl.getName() === name) return decl;
|
|
16881
17942
|
}
|
|
16882
17943
|
}
|
|
16883
|
-
for (const decl of sf.getDescendantsOfKind(
|
|
17944
|
+
for (const decl of sf.getDescendantsOfKind(SyntaxKind8.VariableDeclaration)) {
|
|
16884
17945
|
if (decl.getName() === name) return decl;
|
|
16885
17946
|
}
|
|
16886
17947
|
return void 0;
|
|
16887
17948
|
}
|
|
16888
17949
|
function collectTypeofReferences(node, out) {
|
|
16889
|
-
if (
|
|
17950
|
+
if (Node13.isTypeQuery(node)) {
|
|
16890
17951
|
out.push(node.getExprName().getText());
|
|
16891
17952
|
return;
|
|
16892
17953
|
}
|
|
16893
|
-
for (const tq of node.getDescendantsOfKind(
|
|
17954
|
+
for (const tq of node.getDescendantsOfKind(SyntaxKind8.TypeQuery)) {
|
|
16894
17955
|
out.push(tq.getExprName().getText());
|
|
16895
17956
|
}
|
|
16896
17957
|
}
|
|
@@ -17188,8 +18249,8 @@ function getFunctionType(x) {
|
|
|
17188
18249
|
return typeof x === "function" ? x.prototype ? Object.getOwnPropertyDescriptor(x, "prototype")?.writable ? "function" : "class" : x.constructor.name === "AsyncFunction" ? "function" : "arrow" : null;
|
|
17189
18250
|
}
|
|
17190
18251
|
function isNonClassFunction(x) {
|
|
17191
|
-
const
|
|
17192
|
-
return
|
|
18252
|
+
const type62 = getFunctionType(x);
|
|
18253
|
+
return type62 != null && type62 !== "class";
|
|
17193
18254
|
}
|
|
17194
18255
|
|
|
17195
18256
|
// packages/util/src/lib/getter/getter.ts
|
|
@@ -17266,9 +18327,9 @@ function asNumber(input) {
|
|
|
17266
18327
|
}
|
|
17267
18328
|
|
|
17268
18329
|
// packages/util/src/lib/number/round.ts
|
|
17269
|
-
function roundingFunction(
|
|
18330
|
+
function roundingFunction(type62) {
|
|
17270
18331
|
let fn;
|
|
17271
|
-
switch (
|
|
18332
|
+
switch (type62) {
|
|
17272
18333
|
case "floor":
|
|
17273
18334
|
fn = Math.floor;
|
|
17274
18335
|
break;
|
|
@@ -17521,9 +18582,9 @@ function filterKeyValueTuplesInputToFilter(input) {
|
|
|
17521
18582
|
}
|
|
17522
18583
|
function filterKeyValueTupleFunction(inputFilter) {
|
|
17523
18584
|
const filter = filterKeyValueTuplesInputToFilter(inputFilter);
|
|
17524
|
-
const { valueFilter:
|
|
18585
|
+
const { valueFilter: type62 = 1 /* UNDEFINED */, invertFilter: inverseFilter = false, keysFilter } = filter;
|
|
17525
18586
|
let filterFn;
|
|
17526
|
-
switch (
|
|
18587
|
+
switch (type62) {
|
|
17527
18588
|
case 1 /* UNDEFINED */:
|
|
17528
18589
|
filterFn = ([, x]) => x !== void 0;
|
|
17529
18590
|
break;
|
|
@@ -17782,7 +18843,7 @@ var NUMBER_STRING_DENCODER_64_DIGITS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcd
|
|
|
17782
18843
|
var NUMBER_STRING_DENCODER_64_DEFAULT_NEGATIVE_PREFIX = "!";
|
|
17783
18844
|
function numberStringDencoder(config) {
|
|
17784
18845
|
const { negativePrefix, digits } = config;
|
|
17785
|
-
const
|
|
18846
|
+
const type62 = negativePrefix ? "integer" : "positive_integer";
|
|
17786
18847
|
const log2OfDigits = Math.min(6, Math.floor(Math.log2(digits.length)));
|
|
17787
18848
|
const bitDepth = Math.pow(2, log2OfDigits);
|
|
17788
18849
|
const bitMask = bitDepth - 1;
|
|
@@ -17819,7 +18880,7 @@ function numberStringDencoder(config) {
|
|
|
17819
18880
|
return result;
|
|
17820
18881
|
}
|
|
17821
18882
|
return {
|
|
17822
|
-
type:
|
|
18883
|
+
type: type62,
|
|
17823
18884
|
digits,
|
|
17824
18885
|
bitDepth,
|
|
17825
18886
|
negativePrefix,
|
|
@@ -17890,9 +18951,9 @@ function readableStreamToStringFunction(encoding) {
|
|
|
17890
18951
|
var readableStreamToBase64 = readableStreamToStringFunction("base64");
|
|
17891
18952
|
function readableStreamToBuffer(stream) {
|
|
17892
18953
|
const chunks = [];
|
|
17893
|
-
return new Promise((
|
|
18954
|
+
return new Promise((resolve36, reject) => {
|
|
17894
18955
|
stream.on("data", (chunk) => chunks.push(Buffer.from(chunk)));
|
|
17895
|
-
stream.on("end", () =>
|
|
18956
|
+
stream.on("end", () => resolve36(Buffer.concat(chunks)));
|
|
17896
18957
|
stream.on("error", reject);
|
|
17897
18958
|
});
|
|
17898
18959
|
}
|
|
@@ -18315,7 +19376,7 @@ function extractUploadInitializerEntries(sources) {
|
|
|
18315
19376
|
const out = [];
|
|
18316
19377
|
for (const sf of sources) {
|
|
18317
19378
|
const rel = apiRelPath(sf);
|
|
18318
|
-
for (const decl of sf.getDescendantsOfKind(
|
|
19379
|
+
for (const decl of sf.getDescendantsOfKind(SyntaxKind9.VariableDeclaration)) {
|
|
18319
19380
|
const typeText = typeAnnotationText(decl);
|
|
18320
19381
|
if (typeText !== UPLOAD_SERVICE_INITIALIZER_TYPE) continue;
|
|
18321
19382
|
const obj = asObjectLiteral(decl.getInitializer());
|
|
@@ -18345,7 +19406,7 @@ function buildApiFunctionIndex(sources) {
|
|
|
18345
19406
|
for (const decl of stmt.getDeclarations()) {
|
|
18346
19407
|
const initializer = unwrapAsExpressions(decl.getInitializer());
|
|
18347
19408
|
if (!initializer) continue;
|
|
18348
|
-
if (
|
|
19409
|
+
if (Node14.isArrowFunction(initializer) || Node14.isFunctionExpression(initializer)) {
|
|
18349
19410
|
map.set(decl.getName(), { node: initializer, sourceFile: sf });
|
|
18350
19411
|
}
|
|
18351
19412
|
}
|
|
@@ -18358,34 +19419,34 @@ function collectInitializerBindingsFromValue(options) {
|
|
|
18358
19419
|
const { node, sf, index, resolved, unresolved, visited } = options;
|
|
18359
19420
|
const inner = unwrapAsExpressions(node);
|
|
18360
19421
|
if (!inner) return false;
|
|
18361
|
-
if (
|
|
19422
|
+
if (Node14.isArrayLiteralExpression(inner)) {
|
|
18362
19423
|
for (const el of inner.getElements()) {
|
|
18363
|
-
if (
|
|
19424
|
+
if (Node14.isSpreadElement(el)) {
|
|
18364
19425
|
const spreadInner = el.getExpression();
|
|
18365
|
-
if (
|
|
19426
|
+
if (Node14.isIdentifier(spreadInner)) {
|
|
18366
19427
|
collectInitializerBindingsFromIdentifier({ name: spreadInner.getText(), sf, index, resolved, unresolved, visited });
|
|
18367
|
-
} else if (
|
|
19428
|
+
} else if (Node14.isCallExpression(spreadInner)) {
|
|
18368
19429
|
const callee = spreadInner.getExpression();
|
|
18369
|
-
if (
|
|
19430
|
+
if (Node14.isIdentifier(callee)) {
|
|
18370
19431
|
collectInitializerBindingsFromIdentifier({ name: callee.getText(), sf, index, resolved, unresolved, visited });
|
|
18371
19432
|
}
|
|
18372
19433
|
}
|
|
18373
19434
|
continue;
|
|
18374
19435
|
}
|
|
18375
19436
|
const elementInner = unwrapAsExpressions(el);
|
|
18376
|
-
if (elementInner &&
|
|
19437
|
+
if (elementInner && Node14.isIdentifier(elementInner)) {
|
|
18377
19438
|
resolved.push(elementInner.getText());
|
|
18378
19439
|
}
|
|
18379
19440
|
}
|
|
18380
19441
|
return true;
|
|
18381
19442
|
}
|
|
18382
|
-
if (
|
|
19443
|
+
if (Node14.isCallExpression(inner)) {
|
|
18383
19444
|
const callee = inner.getExpression();
|
|
18384
|
-
if (
|
|
19445
|
+
if (Node14.isIdentifier(callee)) {
|
|
18385
19446
|
return collectInitializerBindingsFromIdentifier({ name: callee.getText(), sf, index, resolved, unresolved, visited });
|
|
18386
19447
|
}
|
|
18387
19448
|
}
|
|
18388
|
-
if (
|
|
19449
|
+
if (Node14.isIdentifier(inner)) {
|
|
18389
19450
|
return collectInitializerBindingsFromIdentifier({ name: inner.getText(), sf, index, resolved, unresolved, visited });
|
|
18390
19451
|
}
|
|
18391
19452
|
return false;
|
|
@@ -18424,15 +19485,15 @@ function collectUploadInitializerArray(options) {
|
|
|
18424
19485
|
const { initializerArr, sf, index, direct, spreads, resolved, unresolved } = options;
|
|
18425
19486
|
const visited = /* @__PURE__ */ new Set();
|
|
18426
19487
|
for (const el of initializerArr.getElements()) {
|
|
18427
|
-
if (
|
|
19488
|
+
if (Node14.isSpreadElement(el)) {
|
|
18428
19489
|
const inner2 = el.getExpression();
|
|
18429
|
-
if (
|
|
19490
|
+
if (Node14.isIdentifier(inner2)) {
|
|
18430
19491
|
const name = inner2.getText();
|
|
18431
19492
|
spreads.push(name);
|
|
18432
19493
|
collectInitializerBindingsFromIdentifier({ name, sf, index, resolved, unresolved, visited });
|
|
18433
|
-
} else if (
|
|
19494
|
+
} else if (Node14.isCallExpression(inner2)) {
|
|
18434
19495
|
const callee = inner2.getExpression();
|
|
18435
|
-
if (
|
|
19496
|
+
if (Node14.isIdentifier(callee)) {
|
|
18436
19497
|
const name = callee.getText();
|
|
18437
19498
|
spreads.push(name);
|
|
18438
19499
|
collectInitializerBindingsFromIdentifier({ name, sf, index, resolved, unresolved, visited });
|
|
@@ -18441,7 +19502,7 @@ function collectUploadInitializerArray(options) {
|
|
|
18441
19502
|
continue;
|
|
18442
19503
|
}
|
|
18443
19504
|
const inner = unwrapAsExpressions(el);
|
|
18444
|
-
if (inner &&
|
|
19505
|
+
if (inner && Node14.isIdentifier(inner)) {
|
|
18445
19506
|
const name = inner.getText();
|
|
18446
19507
|
direct.push(name);
|
|
18447
19508
|
resolved.push(name);
|
|
@@ -18452,9 +19513,9 @@ function extractUploadServiceCalls(sources, index) {
|
|
|
18452
19513
|
const out = [];
|
|
18453
19514
|
for (const sf of sources) {
|
|
18454
19515
|
const rel = apiRelPath(sf);
|
|
18455
|
-
for (const call of sf.getDescendantsOfKind(
|
|
19516
|
+
for (const call of sf.getDescendantsOfKind(SyntaxKind9.CallExpression)) {
|
|
18456
19517
|
const expr = call.getExpression();
|
|
18457
|
-
if (!
|
|
19518
|
+
if (!Node14.isIdentifier(expr) || expr.getText() !== UPLOAD_SERVICE_FACTORY) continue;
|
|
18458
19519
|
const args = call.getArguments();
|
|
18459
19520
|
const first = args[0] ? resolveObjectArg(args[0], sf) : void 0;
|
|
18460
19521
|
if (!first) continue;
|
|
@@ -18482,12 +19543,12 @@ function extractUploadServiceCalls(sources, index) {
|
|
|
18482
19543
|
function resolveObjectArg(node, sf) {
|
|
18483
19544
|
const inner = unwrapAsExpressions(node);
|
|
18484
19545
|
if (!inner) return void 0;
|
|
18485
|
-
if (
|
|
18486
|
-
if (
|
|
19546
|
+
if (Node14.isObjectLiteralExpression(inner)) return inner;
|
|
19547
|
+
if (Node14.isIdentifier(inner)) {
|
|
18487
19548
|
const declNode = findLocalVariable(sf, inner.getText());
|
|
18488
19549
|
if (declNode) {
|
|
18489
19550
|
const declInit = unwrapAsExpressions(declNode.getInitializer());
|
|
18490
|
-
if (declInit &&
|
|
19551
|
+
if (declInit && Node14.isObjectLiteralExpression(declInit)) {
|
|
18491
19552
|
return declInit;
|
|
18492
19553
|
}
|
|
18493
19554
|
}
|
|
@@ -18497,12 +19558,12 @@ function resolveObjectArg(node, sf) {
|
|
|
18497
19558
|
function resolveArrayFromProperty(obj, name, sf) {
|
|
18498
19559
|
const init = unwrapAsExpressions(getPropertyInitializer(obj, name));
|
|
18499
19560
|
if (!init) return void 0;
|
|
18500
|
-
if (
|
|
18501
|
-
if (
|
|
19561
|
+
if (Node14.isArrayLiteralExpression(init)) return init;
|
|
19562
|
+
if (Node14.isIdentifier(init)) {
|
|
18502
19563
|
const declNode = findLocalVariable(sf, init.getText());
|
|
18503
19564
|
if (declNode) {
|
|
18504
19565
|
const declInit = unwrapAsExpressions(declNode.getInitializer());
|
|
18505
|
-
if (declInit &&
|
|
19566
|
+
if (declInit && Node14.isArrayLiteralExpression(declInit)) {
|
|
18506
19567
|
return declInit;
|
|
18507
19568
|
}
|
|
18508
19569
|
}
|
|
@@ -18513,11 +19574,11 @@ function enclosingFactoryName(node) {
|
|
|
18513
19574
|
let current = node.getParent();
|
|
18514
19575
|
let result;
|
|
18515
19576
|
while (current) {
|
|
18516
|
-
if (
|
|
19577
|
+
if (Node14.isFunctionDeclaration(current)) {
|
|
18517
19578
|
result = current.getName() ?? void 0;
|
|
18518
19579
|
break;
|
|
18519
19580
|
}
|
|
18520
|
-
if (
|
|
19581
|
+
if (Node14.isVariableDeclaration(current)) {
|
|
18521
19582
|
result = current.getName();
|
|
18522
19583
|
break;
|
|
18523
19584
|
}
|
|
@@ -18529,7 +19590,7 @@ function extractUploadServiceWirings(sources) {
|
|
|
18529
19590
|
const out = [];
|
|
18530
19591
|
for (const sf of sources) {
|
|
18531
19592
|
const rel = apiRelPath(sf);
|
|
18532
|
-
for (const obj of sf.getDescendantsOfKind(
|
|
19593
|
+
for (const obj of sf.getDescendantsOfKind(SyntaxKind9.ObjectLiteralExpression)) {
|
|
18533
19594
|
const provideIdent = readIdentifierProperty(obj, "provide");
|
|
18534
19595
|
if (provideIdent !== UPLOAD_SERVICE_PROVIDE_TOKEN) continue;
|
|
18535
19596
|
const useFactory = readIdentifierProperty(obj, "useFactory");
|
|
@@ -18542,7 +19603,7 @@ function extractProcessingConfigs(sources) {
|
|
|
18542
19603
|
const out = [];
|
|
18543
19604
|
for (const sf of sources) {
|
|
18544
19605
|
const rel = apiRelPath(sf);
|
|
18545
|
-
for (const decl of sf.getDescendantsOfKind(
|
|
19606
|
+
for (const decl of sf.getDescendantsOfKind(SyntaxKind9.VariableDeclaration)) {
|
|
18546
19607
|
const config = extractProcessingConfigFromDecl(decl, rel);
|
|
18547
19608
|
if (config) {
|
|
18548
19609
|
out.push(config);
|
|
@@ -18571,10 +19632,10 @@ function extractProcessingConfigFromDecl(decl, rel) {
|
|
|
18571
19632
|
function readFlowSubtasks(obj) {
|
|
18572
19633
|
const flowInit = unwrapAsExpressions(getPropertyInitializer(obj, "flow"));
|
|
18573
19634
|
const subtasks = [];
|
|
18574
|
-
if (flowInit &&
|
|
19635
|
+
if (flowInit && Node14.isArrayLiteralExpression(flowInit)) {
|
|
18575
19636
|
for (const el of flowInit.getElements()) {
|
|
18576
19637
|
const inner = unwrapAsExpressions(el);
|
|
18577
|
-
if (inner &&
|
|
19638
|
+
if (inner && Node14.isObjectLiteralExpression(inner)) {
|
|
18578
19639
|
const subtask = readIdentifierProperty(inner, "subtask");
|
|
18579
19640
|
if (subtask) subtasks.push(subtask);
|
|
18580
19641
|
}
|
|
@@ -18586,9 +19647,9 @@ function extractProcessingHandlerCalls(sources) {
|
|
|
18586
19647
|
const out = [];
|
|
18587
19648
|
for (const sf of sources) {
|
|
18588
19649
|
const rel = apiRelPath(sf);
|
|
18589
|
-
for (const call of sf.getDescendantsOfKind(
|
|
19650
|
+
for (const call of sf.getDescendantsOfKind(SyntaxKind9.CallExpression)) {
|
|
18590
19651
|
const expr = call.getExpression();
|
|
18591
|
-
if (!
|
|
19652
|
+
if (!Node14.isIdentifier(expr) || expr.getText() !== PROCESSING_HANDLER_FACTORY) continue;
|
|
18592
19653
|
const args = call.getArguments();
|
|
18593
19654
|
const first = args[0] ? resolveObjectArg(args[0], sf) : void 0;
|
|
18594
19655
|
if (!first) continue;
|
|
@@ -18609,7 +19670,7 @@ function extractProcessingHandlerCalls(sources) {
|
|
|
18609
19670
|
}
|
|
18610
19671
|
function collectProcessorArrayElements(processorsArr, direct, spreads) {
|
|
18611
19672
|
for (const el of processorsArr.getElements()) {
|
|
18612
|
-
if (
|
|
19673
|
+
if (Node14.isSpreadElement(el)) {
|
|
18613
19674
|
addProcessorIdentifierName(el.getExpression(), spreads);
|
|
18614
19675
|
continue;
|
|
18615
19676
|
}
|
|
@@ -18621,13 +19682,13 @@ function collectProcessorArrayElements(processorsArr, direct, spreads) {
|
|
|
18621
19682
|
}
|
|
18622
19683
|
function addProcessorIdentifierName(node, bucket) {
|
|
18623
19684
|
if (!node) return;
|
|
18624
|
-
if (
|
|
19685
|
+
if (Node14.isIdentifier(node)) {
|
|
18625
19686
|
bucket.push(node.getText());
|
|
18626
19687
|
return;
|
|
18627
19688
|
}
|
|
18628
|
-
if (
|
|
19689
|
+
if (Node14.isCallExpression(node)) {
|
|
18629
19690
|
const callee = node.getExpression();
|
|
18630
|
-
if (
|
|
19691
|
+
if (Node14.isIdentifier(callee)) {
|
|
18631
19692
|
bucket.push(callee.getText());
|
|
18632
19693
|
}
|
|
18633
19694
|
}
|
|
@@ -18982,8 +20043,8 @@ function formatResult4(result) {
|
|
|
18982
20043
|
}
|
|
18983
20044
|
|
|
18984
20045
|
// packages/dbx-components-mcp/src/tools/_validate/inspect.ts
|
|
18985
|
-
import { readdir as readdir3, readFile as
|
|
18986
|
-
import { join as
|
|
20046
|
+
import { readdir as readdir3, readFile as readFile8, stat as stat5 } from "node:fs/promises";
|
|
20047
|
+
import { join as join7, relative as relative5, sep as sep4 } from "node:path";
|
|
18987
20048
|
async function inspectSide(rootDir, subpaths) {
|
|
18988
20049
|
const rootStatus = await readRootStatus(rootDir);
|
|
18989
20050
|
if (rootStatus !== void 0) {
|
|
@@ -18993,7 +20054,7 @@ async function inspectSide(rootDir, subpaths) {
|
|
|
18993
20054
|
const presentFolders = [];
|
|
18994
20055
|
const collectedFiles = [];
|
|
18995
20056
|
for (const sub of subpaths) {
|
|
18996
|
-
const absFolder =
|
|
20057
|
+
const absFolder = join7(rootDir, sub);
|
|
18997
20058
|
const folderPresent = await isDirectory(absFolder);
|
|
18998
20059
|
if (!folderPresent) continue;
|
|
18999
20060
|
presentFolders.push(sub);
|
|
@@ -19039,7 +20100,7 @@ async function collectTsFiles(absFolder, rootDir) {
|
|
|
19039
20100
|
continue;
|
|
19040
20101
|
}
|
|
19041
20102
|
for (const entry of entries) {
|
|
19042
|
-
const full =
|
|
20103
|
+
const full = join7(current, entry.name);
|
|
19043
20104
|
if (entry.isDirectory()) {
|
|
19044
20105
|
stack.push(full);
|
|
19045
20106
|
continue;
|
|
@@ -19048,7 +20109,7 @@ async function collectTsFiles(absFolder, rootDir) {
|
|
|
19048
20109
|
if (!entry.name.endsWith(".ts")) continue;
|
|
19049
20110
|
if (entry.name.endsWith(".spec.ts")) continue;
|
|
19050
20111
|
if (entry.name.endsWith(".d.ts")) continue;
|
|
19051
|
-
const text = await
|
|
20112
|
+
const text = await readFile8(full, "utf8");
|
|
19052
20113
|
const rel = relative5(rootDir, full).split(sep4).join("/");
|
|
19053
20114
|
out.push({ relPath: rel, text });
|
|
19054
20115
|
}
|
|
@@ -19301,8 +20362,8 @@ var storageFileMListAppTool = createListAppTool({
|
|
|
19301
20362
|
});
|
|
19302
20363
|
|
|
19303
20364
|
// packages/dbx-components-mcp/src/tools/validate-two-side-folder.ts
|
|
19304
|
-
import { readdir as readdir4, readFile as
|
|
19305
|
-
import { join as
|
|
20365
|
+
import { readdir as readdir4, readFile as readFile9, stat as stat6 } from "node:fs/promises";
|
|
20366
|
+
import { join as join8 } from "node:path";
|
|
19306
20367
|
var REEXPORT_PATTERN = /^\s*export\s+\*\s+from\s+['"]\.\/([^'"\n]+)['"]\s*;?\s*$/gm;
|
|
19307
20368
|
function createTwoSideFolderValidator(config) {
|
|
19308
20369
|
async function inspect(input) {
|
|
@@ -19346,7 +20407,7 @@ async function inspectSide2(input) {
|
|
|
19346
20407
|
let indexSource;
|
|
19347
20408
|
const rootStatOk = await isExistingDirectory(rootDir);
|
|
19348
20409
|
if (rootStatOk) {
|
|
19349
|
-
const absFolder =
|
|
20410
|
+
const absFolder = join8(rootDir, subPath);
|
|
19350
20411
|
const folderStatOk = await isExistingDirectory(absFolder);
|
|
19351
20412
|
if (folderStatOk) {
|
|
19352
20413
|
const folder = await readFolder(absFolder, indexFile);
|
|
@@ -19398,7 +20459,7 @@ async function readFolder(absFolder, indexFile) {
|
|
|
19398
20459
|
let indexSource;
|
|
19399
20460
|
if (collectedFiles.includes(indexFile)) {
|
|
19400
20461
|
try {
|
|
19401
|
-
indexSource = await
|
|
20462
|
+
indexSource = await readFile9(join8(absFolder, indexFile), "utf8");
|
|
19402
20463
|
} catch {
|
|
19403
20464
|
indexSource = void 0;
|
|
19404
20465
|
}
|
|
@@ -19618,7 +20679,7 @@ var storageFileMValidateFolderTool = createTwoSideValidateTool({
|
|
|
19618
20679
|
});
|
|
19619
20680
|
|
|
19620
20681
|
// packages/dbx-components-mcp/src/tools/notification-m-validate-app/extract.ts
|
|
19621
|
-
import { Node as
|
|
20682
|
+
import { Node as Node15, SyntaxKind as SyntaxKind10 } from "ts-morph";
|
|
19622
20683
|
var NOTIF_TEMPLATE_TYPE = "NotificationTemplateType";
|
|
19623
20684
|
var NOTIF_TEMPLATE_TYPE_INFO = "NotificationTemplateTypeInfo";
|
|
19624
20685
|
var NOTIF_TEMPLATE_TYPE_INFO_ARRAY = "NotificationTemplateTypeInfo[]";
|
|
@@ -19739,7 +20800,7 @@ function extractTemplateInfoAggregates(sources) {
|
|
|
19739
20800
|
const ids = [];
|
|
19740
20801
|
for (const el of arr.getElements()) {
|
|
19741
20802
|
const inner = unwrapAsExpressions(el);
|
|
19742
|
-
if (inner &&
|
|
20803
|
+
if (inner && Node15.isIdentifier(inner)) {
|
|
19743
20804
|
ids.push(inner.getText());
|
|
19744
20805
|
}
|
|
19745
20806
|
}
|
|
@@ -19785,7 +20846,7 @@ function extractTaskAllTypesAggregates(sources) {
|
|
|
19785
20846
|
const ids = [];
|
|
19786
20847
|
for (const el of arr.getElements()) {
|
|
19787
20848
|
const inner = unwrapAsExpressions(el);
|
|
19788
|
-
if (inner &&
|
|
20849
|
+
if (inner && Node15.isIdentifier(inner)) {
|
|
19789
20850
|
ids.push(inner.getText());
|
|
19790
20851
|
}
|
|
19791
20852
|
}
|
|
@@ -19813,14 +20874,14 @@ function extractTaskCheckpointAliases(sources) {
|
|
|
19813
20874
|
return out;
|
|
19814
20875
|
}
|
|
19815
20876
|
function collectStringLiterals(node, out) {
|
|
19816
|
-
if (
|
|
20877
|
+
if (Node15.isLiteralTypeNode(node)) {
|
|
19817
20878
|
const lit = node.getLiteral();
|
|
19818
|
-
if (
|
|
20879
|
+
if (Node15.isStringLiteral(lit)) {
|
|
19819
20880
|
out.push(lit.getLiteralText());
|
|
19820
20881
|
}
|
|
19821
20882
|
return;
|
|
19822
20883
|
}
|
|
19823
|
-
if (
|
|
20884
|
+
if (Node15.isUnionTypeNode(node)) {
|
|
19824
20885
|
for (const child of node.getTypeNodes()) {
|
|
19825
20886
|
collectStringLiterals(child, out);
|
|
19826
20887
|
}
|
|
@@ -19874,7 +20935,7 @@ function extractTemplateInfoRecord(sources, index) {
|
|
|
19874
20935
|
}
|
|
19875
20936
|
function tryReadTemplateInfoRecord(decl, rel, index) {
|
|
19876
20937
|
const initializer = unwrapAsExpressions(decl.getInitializer());
|
|
19877
|
-
if (!initializer || !
|
|
20938
|
+
if (!initializer || !Node15.isCallExpression(initializer)) return void 0;
|
|
19878
20939
|
if (initializer.getExpression().getText() !== TEMPLATE_INFO_RECORD_FACTORY) return void 0;
|
|
19879
20940
|
const args = initializer.getArguments();
|
|
19880
20941
|
const arr = args[0] ? asArrayLiteral(args[0]) : void 0;
|
|
@@ -19895,15 +20956,15 @@ function tryReadTemplateInfoRecord(decl, rel, index) {
|
|
|
19895
20956
|
}
|
|
19896
20957
|
function classifyInfoRecordArrayElements(arr, direct, spreads) {
|
|
19897
20958
|
for (const el of arr.getElements()) {
|
|
19898
|
-
if (
|
|
20959
|
+
if (Node15.isSpreadElement(el)) {
|
|
19899
20960
|
const inner2 = el.getExpression();
|
|
19900
|
-
if (
|
|
20961
|
+
if (Node15.isIdentifier(inner2)) {
|
|
19901
20962
|
spreads.push(inner2.getText());
|
|
19902
20963
|
}
|
|
19903
20964
|
continue;
|
|
19904
20965
|
}
|
|
19905
20966
|
const inner = unwrapAsExpressions(el);
|
|
19906
|
-
if (inner &&
|
|
20967
|
+
if (inner && Node15.isIdentifier(inner)) {
|
|
19907
20968
|
direct.push(inner.getText());
|
|
19908
20969
|
}
|
|
19909
20970
|
}
|
|
@@ -19924,13 +20985,13 @@ function resolveTemplateInfoSpreads(direct, spreads, index) {
|
|
|
19924
20985
|
function extractTemplateInfoRecordWiring(sources) {
|
|
19925
20986
|
for (const sf of sources) {
|
|
19926
20987
|
const rel = apiRelPath(sf);
|
|
19927
|
-
for (const call of sf.getDescendantsOfKind(
|
|
20988
|
+
for (const call of sf.getDescendantsOfKind(SyntaxKind10.CallExpression)) {
|
|
19928
20989
|
if (call.getExpression().getText() !== TEMPLATE_INFO_RECORD_SERVICE) continue;
|
|
19929
20990
|
const args = call.getArguments();
|
|
19930
20991
|
const first = args[0];
|
|
19931
20992
|
if (!first) continue;
|
|
19932
20993
|
const inner = unwrapAsExpressions(first);
|
|
19933
|
-
if (!inner || !
|
|
20994
|
+
if (!inner || !Node15.isIdentifier(inner)) continue;
|
|
19934
20995
|
const result = {
|
|
19935
20996
|
recordIdentifier: inner.getText(),
|
|
19936
20997
|
sourceFile: rel
|
|
@@ -19943,7 +21004,7 @@ function extractTemplateInfoRecordWiring(sources) {
|
|
|
19943
21004
|
function extractTemplateConfigsArrayWiring(sources) {
|
|
19944
21005
|
for (const sf of sources) {
|
|
19945
21006
|
const rel = apiRelPath(sf);
|
|
19946
|
-
for (const obj of sf.getDescendantsOfKind(
|
|
21007
|
+
for (const obj of sf.getDescendantsOfKind(SyntaxKind10.ObjectLiteralExpression)) {
|
|
19947
21008
|
const provideIdent = readIdentifierProperty(obj, "provide");
|
|
19948
21009
|
if (provideIdent !== TEMPLATE_CONFIGS_ARRAY_TOKEN) continue;
|
|
19949
21010
|
const useFactoryIdent = readIdentifierProperty(obj, "useFactory");
|
|
@@ -19968,7 +21029,7 @@ function buildApiFunctionIndex2(sources) {
|
|
|
19968
21029
|
for (const decl of stmt.getDeclarations()) {
|
|
19969
21030
|
const initializer = unwrapAsExpressions(decl.getInitializer());
|
|
19970
21031
|
if (!initializer) continue;
|
|
19971
|
-
if (
|
|
21032
|
+
if (Node15.isArrowFunction(initializer) || Node15.isFunctionExpression(initializer)) {
|
|
19972
21033
|
map.set(decl.getName(), { node: initializer, sourceFile: sf, relPath: rel });
|
|
19973
21034
|
}
|
|
19974
21035
|
}
|
|
@@ -20004,11 +21065,11 @@ function extractTemplateConfigsArrayFactory(sources, index) {
|
|
|
20004
21065
|
const arr = returnExpr ? asArrayLiteral(returnExpr) : void 0;
|
|
20005
21066
|
if (arr) {
|
|
20006
21067
|
for (const el of arr.getElements()) {
|
|
20007
|
-
if (
|
|
21068
|
+
if (Node15.isSpreadElement(el)) {
|
|
20008
21069
|
const inner2 = el.getExpression();
|
|
20009
|
-
if (
|
|
21070
|
+
if (Node15.isCallExpression(inner2)) {
|
|
20010
21071
|
const callee = inner2.getExpression();
|
|
20011
|
-
if (
|
|
21072
|
+
if (Node15.isIdentifier(callee)) {
|
|
20012
21073
|
const callName = callee.getText();
|
|
20013
21074
|
spreadCalls.push(callName);
|
|
20014
21075
|
if (!index.functionsByName.has(callName)) {
|
|
@@ -20019,9 +21080,9 @@ function extractTemplateConfigsArrayFactory(sources, index) {
|
|
|
20019
21080
|
continue;
|
|
20020
21081
|
}
|
|
20021
21082
|
const inner = unwrapAsExpressions(el);
|
|
20022
|
-
if (inner &&
|
|
21083
|
+
if (inner && Node15.isCallExpression(inner)) {
|
|
20023
21084
|
const callee = inner.getExpression();
|
|
20024
|
-
if (
|
|
21085
|
+
if (Node15.isIdentifier(callee)) {
|
|
20025
21086
|
directCalls.push(callee.getText());
|
|
20026
21087
|
}
|
|
20027
21088
|
}
|
|
@@ -20070,11 +21131,11 @@ function collectFromArrayEntryFactory(name, out, index) {
|
|
|
20070
21131
|
const arr = asArrayLiteral(returnExpr);
|
|
20071
21132
|
if (!arr) return;
|
|
20072
21133
|
for (const el of arr.getElements()) {
|
|
20073
|
-
if (
|
|
21134
|
+
if (Node15.isSpreadElement(el)) {
|
|
20074
21135
|
const inner2 = el.getExpression();
|
|
20075
|
-
if (
|
|
21136
|
+
if (Node15.isCallExpression(inner2)) {
|
|
20076
21137
|
const callee = inner2.getExpression();
|
|
20077
|
-
if (
|
|
21138
|
+
if (Node15.isIdentifier(callee)) {
|
|
20078
21139
|
collectFromArrayEntryFactory(callee.getText(), out, index);
|
|
20079
21140
|
}
|
|
20080
21141
|
}
|
|
@@ -20082,9 +21143,9 @@ function collectFromArrayEntryFactory(name, out, index) {
|
|
|
20082
21143
|
}
|
|
20083
21144
|
const inner = unwrapAsExpressions(el);
|
|
20084
21145
|
if (!inner) continue;
|
|
20085
|
-
if (
|
|
21146
|
+
if (Node15.isCallExpression(inner)) {
|
|
20086
21147
|
const callee = inner.getExpression();
|
|
20087
|
-
if (
|
|
21148
|
+
if (Node15.isIdentifier(callee)) {
|
|
20088
21149
|
collectFromSingleEntryFactory(callee.getText(), out, index);
|
|
20089
21150
|
}
|
|
20090
21151
|
continue;
|
|
@@ -20102,9 +21163,9 @@ function extractTaskServiceCalls(sources, index, trustedExternal) {
|
|
|
20102
21163
|
const out = [];
|
|
20103
21164
|
for (const sf of sources) {
|
|
20104
21165
|
const rel = apiRelPath(sf);
|
|
20105
|
-
for (const call of sf.getDescendantsOfKind(
|
|
21166
|
+
for (const call of sf.getDescendantsOfKind(SyntaxKind10.CallExpression)) {
|
|
20106
21167
|
const expr = call.getExpression();
|
|
20107
|
-
if (!
|
|
21168
|
+
if (!Node15.isIdentifier(expr) || expr.getText() !== TASK_SERVICE_FACTORY) continue;
|
|
20108
21169
|
const args = call.getArguments();
|
|
20109
21170
|
const first = args[0] ? asObjectLiteral(args[0]) : void 0;
|
|
20110
21171
|
if (!first) continue;
|
|
@@ -20130,13 +21191,13 @@ function collectValidateArrayElements(validateArr) {
|
|
|
20130
21191
|
const spreads = [];
|
|
20131
21192
|
if (!validateArr) return { ids, spreads };
|
|
20132
21193
|
for (const el of validateArr.getElements()) {
|
|
20133
|
-
if (
|
|
21194
|
+
if (Node15.isSpreadElement(el)) {
|
|
20134
21195
|
const inner2 = el.getExpression();
|
|
20135
|
-
if (
|
|
21196
|
+
if (Node15.isIdentifier(inner2)) spreads.push(inner2.getText());
|
|
20136
21197
|
continue;
|
|
20137
21198
|
}
|
|
20138
21199
|
const inner = unwrapAsExpressions(el);
|
|
20139
|
-
if (inner &&
|
|
21200
|
+
if (inner && Node15.isIdentifier(inner)) ids.push(inner.getText());
|
|
20140
21201
|
}
|
|
20141
21202
|
return { ids, spreads };
|
|
20142
21203
|
}
|
|
@@ -20149,17 +21210,17 @@ function collectHandlersArrayElements(options) {
|
|
|
20149
21210
|
if (!handlersArr) return { handlerTypes, unresolvedSpreads, resolvedBindings, unresolvedBindings };
|
|
20150
21211
|
const visited = /* @__PURE__ */ new Set();
|
|
20151
21212
|
for (const el of handlersArr.getElements()) {
|
|
20152
|
-
if (
|
|
21213
|
+
if (Node15.isSpreadElement(el)) {
|
|
20153
21214
|
consumeHandlersSpreadElement({ inner: el.getExpression(), sf, index, trustedExternal, unresolvedSpreads, resolvedBindings, unresolvedBindings, visited });
|
|
20154
21215
|
continue;
|
|
20155
21216
|
}
|
|
20156
21217
|
const inner = unwrapAsExpressions(el);
|
|
20157
21218
|
if (!inner) continue;
|
|
20158
|
-
if (
|
|
21219
|
+
if (Node15.isIdentifier(inner)) {
|
|
20159
21220
|
collectHandlerBindingsFromIdentifier({ name: inner.getText(), sf, index, trustedExternal, resolved: resolvedBindings, unresolved: unresolvedBindings, visited });
|
|
20160
|
-
} else if (
|
|
21221
|
+
} else if (Node15.isCallExpression(inner)) {
|
|
20161
21222
|
const callee = inner.getExpression();
|
|
20162
|
-
if (
|
|
21223
|
+
if (Node15.isIdentifier(callee)) {
|
|
20163
21224
|
collectHandlerBindingsFromIdentifier({ name: callee.getText(), sf, index, trustedExternal, resolved: resolvedBindings, unresolved: unresolvedBindings, visited });
|
|
20164
21225
|
}
|
|
20165
21226
|
}
|
|
@@ -20168,16 +21229,16 @@ function collectHandlersArrayElements(options) {
|
|
|
20168
21229
|
}
|
|
20169
21230
|
function consumeHandlersSpreadElement(options) {
|
|
20170
21231
|
const { inner, sf, index, trustedExternal, unresolvedSpreads, resolvedBindings, unresolvedBindings, visited } = options;
|
|
20171
|
-
if (
|
|
21232
|
+
if (Node15.isCallExpression(inner)) {
|
|
20172
21233
|
const callee = inner.getExpression();
|
|
20173
|
-
if (
|
|
21234
|
+
if (Node15.isIdentifier(callee)) {
|
|
20174
21235
|
const name = callee.getText();
|
|
20175
21236
|
unresolvedSpreads.push(name);
|
|
20176
21237
|
collectHandlerBindingsFromIdentifier({ name, sf, index, trustedExternal, resolved: resolvedBindings, unresolved: unresolvedBindings, visited });
|
|
20177
21238
|
}
|
|
20178
21239
|
return;
|
|
20179
21240
|
}
|
|
20180
|
-
if (
|
|
21241
|
+
if (Node15.isIdentifier(inner)) {
|
|
20181
21242
|
const name = inner.getText();
|
|
20182
21243
|
unresolvedSpreads.push(name);
|
|
20183
21244
|
collectHandlerBindingsFromIdentifier({ name, sf, index, trustedExternal, resolved: resolvedBindings, unresolved: unresolvedBindings, visited });
|
|
@@ -20187,13 +21248,13 @@ function collectHandlerBindingsFromValue(options) {
|
|
|
20187
21248
|
const { node, sf, index, trustedExternal, resolved, unresolved, visited } = options;
|
|
20188
21249
|
const inner = unwrapAsExpressions(node);
|
|
20189
21250
|
if (!inner) return false;
|
|
20190
|
-
if (
|
|
21251
|
+
if (Node15.isCallExpression(inner)) {
|
|
20191
21252
|
const callee = inner.getExpression();
|
|
20192
|
-
if (
|
|
21253
|
+
if (Node15.isIdentifier(callee)) {
|
|
20193
21254
|
return collectHandlerBindingsFromIdentifier({ name: callee.getText(), sf, index, trustedExternal, resolved, unresolved, visited });
|
|
20194
21255
|
}
|
|
20195
21256
|
}
|
|
20196
|
-
if (
|
|
21257
|
+
if (Node15.isIdentifier(inner)) {
|
|
20197
21258
|
return collectHandlerBindingsFromIdentifier({ name: inner.getText(), sf, index, trustedExternal, resolved, unresolved, visited });
|
|
20198
21259
|
}
|
|
20199
21260
|
return false;
|
|
@@ -20210,7 +21271,7 @@ function collectHandlerBindingsFromIdentifier(options) {
|
|
|
20210
21271
|
const typeText = typeNode ? typeNode.getText() : void 0;
|
|
20211
21272
|
const isHandlerConfigTyped = typeText !== void 0 && (typeText === NOTIF_TASK_SERVICE_HANDLER_CONFIG || typeText.startsWith(`${NOTIF_TASK_SERVICE_HANDLER_CONFIG}<`));
|
|
20212
21273
|
const declInit = unwrapAsExpressions(localDecl.getInitializer());
|
|
20213
|
-
const isObjectLit = declInit !== void 0 &&
|
|
21274
|
+
const isObjectLit = declInit !== void 0 && Node15.isObjectLiteralExpression(declInit);
|
|
20214
21275
|
if (isHandlerConfigTyped && isObjectLit) {
|
|
20215
21276
|
resolved.push(localDecl.getName());
|
|
20216
21277
|
resolvedAny = true;
|
|
@@ -20241,12 +21302,12 @@ function collectHandlerBindingsFromIdentifier(options) {
|
|
|
20241
21302
|
function resolveArrayFromProperty2(obj, name, sf) {
|
|
20242
21303
|
const init = unwrapAsExpressions(getPropertyInitializer(obj, name));
|
|
20243
21304
|
if (!init) return void 0;
|
|
20244
|
-
if (
|
|
20245
|
-
if (
|
|
21305
|
+
if (Node15.isArrayLiteralExpression(init)) return init;
|
|
21306
|
+
if (Node15.isIdentifier(init)) {
|
|
20246
21307
|
const declNode = findLocalVariable(sf, init.getText());
|
|
20247
21308
|
if (declNode) {
|
|
20248
21309
|
const declInit = unwrapAsExpressions(declNode.getInitializer());
|
|
20249
|
-
if (declInit &&
|
|
21310
|
+
if (declInit && Node15.isArrayLiteralExpression(declInit)) {
|
|
20250
21311
|
return declInit;
|
|
20251
21312
|
}
|
|
20252
21313
|
}
|
|
@@ -20267,12 +21328,12 @@ function extractTaskHandlerEntries(sources) {
|
|
|
20267
21328
|
if (!typeIdent) return;
|
|
20268
21329
|
const flowInit = unwrapAsExpressions(getPropertyInitializer(obj, "flow"));
|
|
20269
21330
|
let flowCount;
|
|
20270
|
-
if (flowInit &&
|
|
21331
|
+
if (flowInit && Node15.isArrayLiteralExpression(flowInit)) {
|
|
20271
21332
|
flowCount = flowInit.getElements().length;
|
|
20272
21333
|
}
|
|
20273
21334
|
let dataArg;
|
|
20274
21335
|
let checkpointArg;
|
|
20275
|
-
if (
|
|
21336
|
+
if (Node15.isTypeReference(typeNode)) {
|
|
20276
21337
|
const tArgs = typeNode.getTypeArguments();
|
|
20277
21338
|
if (tArgs.length >= 1) dataArg = tArgs[0].getText();
|
|
20278
21339
|
if (tArgs.length >= 2) checkpointArg = tArgs[1].getText();
|
|
@@ -20292,7 +21353,7 @@ function extractTaskHandlerEntries(sources) {
|
|
|
20292
21353
|
};
|
|
20293
21354
|
for (const sf of sources) {
|
|
20294
21355
|
const rel = apiRelPath(sf);
|
|
20295
|
-
for (const decl of sf.getDescendantsOfKind(
|
|
21356
|
+
for (const decl of sf.getDescendantsOfKind(SyntaxKind10.VariableDeclaration)) {
|
|
20296
21357
|
collectFromVariable(decl, rel);
|
|
20297
21358
|
}
|
|
20298
21359
|
}
|
|
@@ -21123,8 +22184,8 @@ function formatResult8(result) {
|
|
|
21123
22184
|
}
|
|
21124
22185
|
|
|
21125
22186
|
// packages/dbx-components-mcp/src/tools/system-m-validate-folder/inspect.ts
|
|
21126
|
-
import { readdir as readdir5, readFile as
|
|
21127
|
-
import { basename as basename5, join as
|
|
22187
|
+
import { readdir as readdir5, readFile as readFile10, stat as stat7 } from "node:fs/promises";
|
|
22188
|
+
import { basename as basename5, join as join9 } from "node:path";
|
|
21128
22189
|
async function inspectFolder2(path) {
|
|
21129
22190
|
const name = basename5(path);
|
|
21130
22191
|
let status;
|
|
@@ -21144,7 +22205,7 @@ async function inspectFolder2(path) {
|
|
|
21144
22205
|
files = collected;
|
|
21145
22206
|
if (collected.includes("system.ts")) {
|
|
21146
22207
|
try {
|
|
21147
|
-
systemSource = await
|
|
22208
|
+
systemSource = await readFile10(join9(path, "system.ts"), "utf8");
|
|
21148
22209
|
} catch {
|
|
21149
22210
|
systemSource = void 0;
|
|
21150
22211
|
}
|
|
@@ -21165,14 +22226,14 @@ async function inspectFolder2(path) {
|
|
|
21165
22226
|
}
|
|
21166
22227
|
|
|
21167
22228
|
// packages/dbx-components-mcp/src/tools/system-m-validate-folder/extract.ts
|
|
21168
|
-
import { Node as
|
|
22229
|
+
import { Node as Node16, Project as Project11 } from "ts-morph";
|
|
21169
22230
|
var TYPE_CONSTANT_SUFFIX = "_SYSTEM_STATE_TYPE";
|
|
21170
22231
|
var DATA_INTERFACE_SUFFIX = "SystemData";
|
|
21171
22232
|
var CONVERTER_CONFIG_TYPE = "SystemStateStoredDataFieldConverterConfig";
|
|
21172
22233
|
var CONVERTER_MAP_TYPE = "SystemStateStoredDataConverterMap";
|
|
21173
22234
|
var SYSTEM_STATE_STORED_DATA = "SystemStateStoredData";
|
|
21174
22235
|
function extractSystemFile(name, text) {
|
|
21175
|
-
const project = new
|
|
22236
|
+
const project = new Project11({ useInMemoryFileSystem: true, skipAddingFilesFromTsConfig: true });
|
|
21176
22237
|
const sourceFile = project.createSourceFile(name, text, { overwrite: true });
|
|
21177
22238
|
const typeConstants = findTypeConstants(sourceFile);
|
|
21178
22239
|
const dataInterfaces = findDataInterfaces2(sourceFile);
|
|
@@ -21229,7 +22290,7 @@ function findDataInterfaces2(sourceFile) {
|
|
|
21229
22290
|
return out;
|
|
21230
22291
|
}
|
|
21231
22292
|
function extendsSystemStateStoredData(iface) {
|
|
21232
|
-
if (!
|
|
22293
|
+
if (!Node16.isInterfaceDeclaration(iface)) return false;
|
|
21233
22294
|
for (const clause of iface.getExtends()) {
|
|
21234
22295
|
const text = clause.getText();
|
|
21235
22296
|
if (text === SYSTEM_STATE_STORED_DATA || text.startsWith(`${SYSTEM_STATE_STORED_DATA}<`) || text === `${SYSTEM_STATE_STORED_DATA}, ${SYSTEM_STATE_STORED_DATA}`) {
|
|
@@ -21249,14 +22310,14 @@ function findConverters2(sourceFile) {
|
|
|
21249
22310
|
for (const decl of stmt.getDeclarations()) {
|
|
21250
22311
|
const typeNode = decl.getTypeNode();
|
|
21251
22312
|
if (!typeNode) continue;
|
|
21252
|
-
if (!
|
|
22313
|
+
if (!Node16.isTypeReference(typeNode)) continue;
|
|
21253
22314
|
const typeName = typeNode.getTypeName().getText();
|
|
21254
22315
|
if (typeName !== CONVERTER_CONFIG_TYPE) continue;
|
|
21255
22316
|
const typeArgs = typeNode.getTypeArguments();
|
|
21256
22317
|
let dataTypeArgument;
|
|
21257
22318
|
if (typeArgs.length >= 1) {
|
|
21258
22319
|
const arg = typeArgs[0];
|
|
21259
|
-
if (
|
|
22320
|
+
if (Node16.isTypeReference(arg)) {
|
|
21260
22321
|
dataTypeArgument = arg.getTypeName().getText();
|
|
21261
22322
|
} else {
|
|
21262
22323
|
dataTypeArgument = arg.getText();
|
|
@@ -21303,19 +22364,19 @@ function collectConverterMapKeys(decl) {
|
|
|
21303
22364
|
if (!obj) return [];
|
|
21304
22365
|
const out = [];
|
|
21305
22366
|
for (const prop of obj.getProperties()) {
|
|
21306
|
-
if (!
|
|
22367
|
+
if (!Node16.isPropertyAssignment(prop)) continue;
|
|
21307
22368
|
const nameNode = prop.getNameNode();
|
|
21308
22369
|
const line = prop.getStartLineNumber();
|
|
21309
|
-
if (
|
|
22370
|
+
if (Node16.isComputedPropertyName(nameNode)) {
|
|
21310
22371
|
const inner = nameNode.getExpression();
|
|
21311
22372
|
out.push({ raw: inner.getText(), kind: "identifier", line });
|
|
21312
22373
|
continue;
|
|
21313
22374
|
}
|
|
21314
|
-
if (
|
|
22375
|
+
if (Node16.isStringLiteral(nameNode)) {
|
|
21315
22376
|
out.push({ raw: nameNode.getLiteralText(), kind: "string", line });
|
|
21316
22377
|
continue;
|
|
21317
22378
|
}
|
|
21318
|
-
if (
|
|
22379
|
+
if (Node16.isIdentifier(nameNode)) {
|
|
21319
22380
|
out.push({ raw: nameNode.getText(), kind: "string", line });
|
|
21320
22381
|
continue;
|
|
21321
22382
|
}
|
|
@@ -21325,10 +22386,10 @@ function collectConverterMapKeys(decl) {
|
|
|
21325
22386
|
}
|
|
21326
22387
|
function unwrapObjectLiteral(node) {
|
|
21327
22388
|
let current = node;
|
|
21328
|
-
while (current &&
|
|
22389
|
+
while (current && Node16.isAsExpression(current)) {
|
|
21329
22390
|
current = current.getExpression();
|
|
21330
22391
|
}
|
|
21331
|
-
if (current &&
|
|
22392
|
+
if (current && Node16.isObjectLiteralExpression(current)) {
|
|
21332
22393
|
return current;
|
|
21333
22394
|
}
|
|
21334
22395
|
return void 0;
|
|
@@ -21362,10 +22423,10 @@ function findLastTopLevelExportLine(sourceFile) {
|
|
|
21362
22423
|
return last;
|
|
21363
22424
|
}
|
|
21364
22425
|
function isExportedTopLevel(stmt) {
|
|
21365
|
-
if (
|
|
22426
|
+
if (Node16.isVariableStatement(stmt) || Node16.isFunctionDeclaration(stmt) || Node16.isClassDeclaration(stmt) || Node16.isInterfaceDeclaration(stmt) || Node16.isTypeAliasDeclaration(stmt) || Node16.isEnumDeclaration(stmt)) {
|
|
21366
22427
|
return stmt.isExported();
|
|
21367
22428
|
}
|
|
21368
|
-
if (
|
|
22429
|
+
if (Node16.isExportDeclaration(stmt) || Node16.isExportAssignment(stmt)) {
|
|
21369
22430
|
return true;
|
|
21370
22431
|
}
|
|
21371
22432
|
return false;
|
|
@@ -21676,7 +22737,7 @@ var systemMValidateFolderTool = createFolderValidateTool({
|
|
|
21676
22737
|
});
|
|
21677
22738
|
|
|
21678
22739
|
// packages/dbx-components-mcp/src/tools/lookup-action.tool.ts
|
|
21679
|
-
import { type as
|
|
22740
|
+
import { type as type39 } from "arktype";
|
|
21680
22741
|
var DBX_ACTION_LOOKUP_TOOL = {
|
|
21681
22742
|
name: "dbx_action_lookup",
|
|
21682
22743
|
description: [
|
|
@@ -21709,13 +22770,13 @@ var DBX_ACTION_LOOKUP_TOOL = {
|
|
|
21709
22770
|
required: ["topic"]
|
|
21710
22771
|
}
|
|
21711
22772
|
};
|
|
21712
|
-
var LookupActionArgsType =
|
|
22773
|
+
var LookupActionArgsType = type39({
|
|
21713
22774
|
topic: "string",
|
|
21714
22775
|
"depth?": "'brief' | 'full'"
|
|
21715
22776
|
});
|
|
21716
22777
|
function parseLookupActionArgs(raw) {
|
|
21717
22778
|
const parsed = LookupActionArgsType(raw);
|
|
21718
|
-
if (parsed instanceof
|
|
22779
|
+
if (parsed instanceof type39.errors) {
|
|
21719
22780
|
throw new TypeError(`Invalid arguments: ${parsed.summary}`);
|
|
21720
22781
|
}
|
|
21721
22782
|
const result = {
|
|
@@ -21982,7 +23043,7 @@ function code6(value) {
|
|
|
21982
23043
|
}
|
|
21983
23044
|
function createLookupActionTool(input) {
|
|
21984
23045
|
const { registry } = input;
|
|
21985
|
-
const
|
|
23046
|
+
const run12 = (rawArgs) => {
|
|
21986
23047
|
let args;
|
|
21987
23048
|
try {
|
|
21988
23049
|
args = parseLookupActionArgs(rawArgs);
|
|
@@ -22009,11 +23070,11 @@ function createLookupActionTool(input) {
|
|
|
22009
23070
|
const result = { content: [{ type: "text", text }] };
|
|
22010
23071
|
return result;
|
|
22011
23072
|
};
|
|
22012
|
-
return { definition: DBX_ACTION_LOOKUP_TOOL, run:
|
|
23073
|
+
return { definition: DBX_ACTION_LOOKUP_TOOL, run: run12 };
|
|
22013
23074
|
}
|
|
22014
23075
|
|
|
22015
23076
|
// packages/dbx-components-mcp/src/tools/action-examples.tool.ts
|
|
22016
|
-
import { type as
|
|
23077
|
+
import { type as type40 } from "arktype";
|
|
22017
23078
|
|
|
22018
23079
|
// packages/dbx-components-mcp/src/tools/data/patterns/actions/action.auto-trigger-on-modify.pattern.ts
|
|
22019
23080
|
var ACTION_PATTERN_AUTO_TRIGGER_ON_MODIFY = {
|
|
@@ -22373,13 +23434,13 @@ var DBX_ACTION_EXAMPLES_TOOL = {
|
|
|
22373
23434
|
required: ["pattern"]
|
|
22374
23435
|
}
|
|
22375
23436
|
};
|
|
22376
|
-
var ActionExamplesArgsType =
|
|
23437
|
+
var ActionExamplesArgsType = type40({
|
|
22377
23438
|
pattern: "string",
|
|
22378
23439
|
"depth?": "'minimal' | 'brief' | 'full'"
|
|
22379
23440
|
});
|
|
22380
23441
|
function parseActionExamplesArgs(raw) {
|
|
22381
23442
|
const parsed = ActionExamplesArgsType(raw);
|
|
22382
|
-
if (parsed instanceof
|
|
23443
|
+
if (parsed instanceof type40.errors) {
|
|
22383
23444
|
throw new TypeError(`Invalid arguments: ${parsed.summary}`);
|
|
22384
23445
|
}
|
|
22385
23446
|
const result = {
|
|
@@ -22441,7 +23502,7 @@ var actionExamplesTool = {
|
|
|
22441
23502
|
};
|
|
22442
23503
|
|
|
22443
23504
|
// packages/dbx-components-mcp/src/tools/action-scaffold.tool.ts
|
|
22444
|
-
import { type as
|
|
23505
|
+
import { type as type41 } from "arktype";
|
|
22445
23506
|
var TRIGGER_VALUES = ["button", "form", "auto-modify"];
|
|
22446
23507
|
var SUCCESS_FEEDBACK_VALUES = ["snackbar", "redirect", "none"];
|
|
22447
23508
|
var CONTEXT_PROVIDER_VALUES = ["inline", "parent", "host-component"];
|
|
@@ -22475,7 +23536,7 @@ var DBX_ACTION_SCAFFOLD_TOOL = {
|
|
|
22475
23536
|
required: ["use_case", "trigger", "value_type"]
|
|
22476
23537
|
}
|
|
22477
23538
|
};
|
|
22478
|
-
var ScaffoldArgsType4 =
|
|
23539
|
+
var ScaffoldArgsType4 = type41({
|
|
22479
23540
|
use_case: "string",
|
|
22480
23541
|
trigger: "'button' | 'form' | 'auto-modify'",
|
|
22481
23542
|
"confirm?": "boolean",
|
|
@@ -22486,7 +23547,7 @@ var ScaffoldArgsType4 = type39({
|
|
|
22486
23547
|
});
|
|
22487
23548
|
function parseScaffoldArgs2(raw) {
|
|
22488
23549
|
const parsed = ScaffoldArgsType4(raw);
|
|
22489
|
-
if (parsed instanceof
|
|
23550
|
+
if (parsed instanceof type41.errors) {
|
|
22490
23551
|
throw new TypeError(`Invalid arguments: ${parsed.summary}`);
|
|
22491
23552
|
}
|
|
22492
23553
|
const useCase = parsed.use_case.trim();
|
|
@@ -22692,16 +23753,16 @@ var actionScaffoldTool = {
|
|
|
22692
23753
|
};
|
|
22693
23754
|
|
|
22694
23755
|
// packages/dbx-components-mcp/src/tools/route-tree.tool.ts
|
|
22695
|
-
import { type as
|
|
23756
|
+
import { type as type42 } from "arktype";
|
|
22696
23757
|
|
|
22697
23758
|
// packages/dbx-components-mcp/src/tools/route/load-sources.ts
|
|
22698
|
-
import { glob as fsGlob4, readFile as
|
|
22699
|
-
import { dirname as dirname7, isAbsolute as isAbsolute7, resolve as
|
|
23759
|
+
import { glob as fsGlob4, readFile as readFile11, stat as stat8 } from "node:fs/promises";
|
|
23760
|
+
import { dirname as dirname7, isAbsolute as isAbsolute7, resolve as resolve24, sep as sep5 } from "node:path";
|
|
22700
23761
|
|
|
22701
23762
|
// packages/dbx-components-mcp/src/tools/route/extract.ts
|
|
22702
|
-
import { Node as
|
|
23763
|
+
import { Node as Node17, Project as Project12, SyntaxKind as SyntaxKind11 } from "ts-morph";
|
|
22703
23764
|
function extractFile3(source) {
|
|
22704
|
-
const project = new
|
|
23765
|
+
const project = new Project12({ useInMemoryFileSystem: true, skipAddingFilesFromTsConfig: true });
|
|
22705
23766
|
const sourceFile = project.createSourceFile(source.name, source.text, { overwrite: true });
|
|
22706
23767
|
const issues = [];
|
|
22707
23768
|
const objectLiteralsByName = collectStateConsts(sourceFile);
|
|
@@ -22714,9 +23775,9 @@ function extractFile3(source) {
|
|
|
22714
23775
|
}
|
|
22715
23776
|
for (const arrayLit of findStateArrayLiterals(sourceFile)) {
|
|
22716
23777
|
for (const element of arrayLit.getElements()) {
|
|
22717
|
-
if (
|
|
23778
|
+
if (Node17.isObjectLiteralExpression(element)) {
|
|
22718
23779
|
addNode({ file: source.name, literal: element, fallbackConstName: void 0, into: collected, issues });
|
|
22719
|
-
} else if (
|
|
23780
|
+
} else if (Node17.isIdentifier(element)) {
|
|
22720
23781
|
const ref = objectLiteralsByName.get(element.getText());
|
|
22721
23782
|
if (ref) {
|
|
22722
23783
|
addNode({ file: source.name, literal: ref.literal, fallbackConstName: element.getText(), into: collected, issues });
|
|
@@ -22737,7 +23798,7 @@ function collectStateConsts(sourceFile) {
|
|
|
22737
23798
|
for (const stmt of sourceFile.getVariableStatements()) {
|
|
22738
23799
|
for (const decl of stmt.getDeclarations()) {
|
|
22739
23800
|
const initializer = decl.getInitializer();
|
|
22740
|
-
if (!initializer || !
|
|
23801
|
+
if (!initializer || !Node17.isObjectLiteralExpression(initializer)) {
|
|
22741
23802
|
continue;
|
|
22742
23803
|
}
|
|
22743
23804
|
const typeNode = decl.getTypeNode();
|
|
@@ -22752,12 +23813,12 @@ function findStateArrayLiterals(sourceFile) {
|
|
|
22752
23813
|
for (const stmt of sourceFile.getVariableStatements()) {
|
|
22753
23814
|
for (const decl of stmt.getDeclarations()) {
|
|
22754
23815
|
const initializer = decl.getInitializer();
|
|
22755
|
-
if (initializer &&
|
|
23816
|
+
if (initializer && Node17.isArrayLiteralExpression(initializer) && declarationIsStateArray(stmt, decl.getName(), initializer)) {
|
|
22756
23817
|
arrays.push(initializer);
|
|
22757
23818
|
}
|
|
22758
23819
|
}
|
|
22759
23820
|
}
|
|
22760
|
-
for (const call of sourceFile.getDescendantsOfKind(
|
|
23821
|
+
for (const call of sourceFile.getDescendantsOfKind(SyntaxKind11.CallExpression)) {
|
|
22761
23822
|
const expr = call.getExpression();
|
|
22762
23823
|
const exprText = expr.getText();
|
|
22763
23824
|
const isProvide = exprText === "provideStates";
|
|
@@ -22766,17 +23827,17 @@ function findStateArrayLiterals(sourceFile) {
|
|
|
22766
23827
|
continue;
|
|
22767
23828
|
}
|
|
22768
23829
|
for (const arg of call.getArguments()) {
|
|
22769
|
-
if (!
|
|
23830
|
+
if (!Node17.isObjectLiteralExpression(arg)) {
|
|
22770
23831
|
continue;
|
|
22771
23832
|
}
|
|
22772
23833
|
const statesProp = arg.getProperty("states");
|
|
22773
|
-
if (!statesProp || !
|
|
23834
|
+
if (!statesProp || !Node17.isPropertyAssignment(statesProp)) {
|
|
22774
23835
|
continue;
|
|
22775
23836
|
}
|
|
22776
23837
|
const initializer = statesProp.getInitializer();
|
|
22777
|
-
if (initializer &&
|
|
23838
|
+
if (initializer && Node17.isArrayLiteralExpression(initializer)) {
|
|
22778
23839
|
arrays.push(initializer);
|
|
22779
|
-
} else if (initializer &&
|
|
23840
|
+
} else if (initializer && Node17.isIdentifier(initializer)) {
|
|
22780
23841
|
const referenced = findArrayLiteralForIdentifier(sourceFile, initializer);
|
|
22781
23842
|
if (referenced) {
|
|
22782
23843
|
arrays.push(referenced);
|
|
@@ -22793,10 +23854,10 @@ function declarationIsStateArray(stmt, name, literal) {
|
|
|
22793
23854
|
return true;
|
|
22794
23855
|
}
|
|
22795
23856
|
for (const element of literal.getElements()) {
|
|
22796
|
-
if (
|
|
23857
|
+
if (Node17.isObjectLiteralExpression(element) && hasStringNameProperty(element)) {
|
|
22797
23858
|
return true;
|
|
22798
23859
|
}
|
|
22799
|
-
if (
|
|
23860
|
+
if (Node17.isIdentifier(element)) {
|
|
22800
23861
|
return true;
|
|
22801
23862
|
}
|
|
22802
23863
|
}
|
|
@@ -22804,11 +23865,11 @@ function declarationIsStateArray(stmt, name, literal) {
|
|
|
22804
23865
|
}
|
|
22805
23866
|
function hasStringNameProperty(literal) {
|
|
22806
23867
|
const nameProp = literal.getProperty("name");
|
|
22807
|
-
if (!nameProp || !
|
|
23868
|
+
if (!nameProp || !Node17.isPropertyAssignment(nameProp)) {
|
|
22808
23869
|
return false;
|
|
22809
23870
|
}
|
|
22810
23871
|
const initializer = nameProp.getInitializer();
|
|
22811
|
-
return initializer !== void 0 && (
|
|
23872
|
+
return initializer !== void 0 && (Node17.isStringLiteral(initializer) || Node17.isNoSubstitutionTemplateLiteral(initializer));
|
|
22812
23873
|
}
|
|
22813
23874
|
function findArrayLiteralForIdentifier(sourceFile, identifier) {
|
|
22814
23875
|
const name = identifier.getText();
|
|
@@ -22818,7 +23879,7 @@ function findArrayLiteralForIdentifier(sourceFile, identifier) {
|
|
|
22818
23879
|
continue;
|
|
22819
23880
|
}
|
|
22820
23881
|
const initializer = decl.getInitializer();
|
|
22821
|
-
if (initializer &&
|
|
23882
|
+
if (initializer && Node17.isArrayLiteralExpression(initializer)) {
|
|
22822
23883
|
return initializer;
|
|
22823
23884
|
}
|
|
22824
23885
|
}
|
|
@@ -22868,64 +23929,64 @@ function addNode(options) {
|
|
|
22868
23929
|
}
|
|
22869
23930
|
function stringPropertyValue(literal, key) {
|
|
22870
23931
|
const prop = literal.getProperty(key);
|
|
22871
|
-
if (!prop || !
|
|
23932
|
+
if (!prop || !Node17.isPropertyAssignment(prop)) {
|
|
22872
23933
|
return void 0;
|
|
22873
23934
|
}
|
|
22874
23935
|
const initializer = prop.getInitializer();
|
|
22875
23936
|
if (!initializer) {
|
|
22876
23937
|
return void 0;
|
|
22877
23938
|
}
|
|
22878
|
-
if (
|
|
23939
|
+
if (Node17.isStringLiteral(initializer) || Node17.isNoSubstitutionTemplateLiteral(initializer)) {
|
|
22879
23940
|
return initializer.getLiteralText();
|
|
22880
23941
|
}
|
|
22881
23942
|
return void 0;
|
|
22882
23943
|
}
|
|
22883
23944
|
function booleanPropertyValue(literal, key) {
|
|
22884
23945
|
const prop = literal.getProperty(key);
|
|
22885
|
-
if (!prop || !
|
|
23946
|
+
if (!prop || !Node17.isPropertyAssignment(prop)) {
|
|
22886
23947
|
return void 0;
|
|
22887
23948
|
}
|
|
22888
23949
|
const initializer = prop.getInitializer();
|
|
22889
23950
|
if (!initializer) {
|
|
22890
23951
|
return void 0;
|
|
22891
23952
|
}
|
|
22892
|
-
if (initializer.getKind() ===
|
|
23953
|
+
if (initializer.getKind() === SyntaxKind11.TrueKeyword) {
|
|
22893
23954
|
return true;
|
|
22894
23955
|
}
|
|
22895
|
-
if (initializer.getKind() ===
|
|
23956
|
+
if (initializer.getKind() === SyntaxKind11.FalseKeyword) {
|
|
22896
23957
|
return false;
|
|
22897
23958
|
}
|
|
22898
23959
|
return void 0;
|
|
22899
23960
|
}
|
|
22900
23961
|
function identifierPropertyValue(literal, key) {
|
|
22901
23962
|
const prop = literal.getProperty(key);
|
|
22902
|
-
if (!prop || !
|
|
23963
|
+
if (!prop || !Node17.isPropertyAssignment(prop)) {
|
|
22903
23964
|
return void 0;
|
|
22904
23965
|
}
|
|
22905
23966
|
const initializer = prop.getInitializer();
|
|
22906
23967
|
if (!initializer) {
|
|
22907
23968
|
return void 0;
|
|
22908
23969
|
}
|
|
22909
|
-
if (
|
|
23970
|
+
if (Node17.isIdentifier(initializer)) {
|
|
22910
23971
|
return initializer.getText();
|
|
22911
23972
|
}
|
|
22912
|
-
if (
|
|
23973
|
+
if (Node17.isPropertyAccessExpression(initializer)) {
|
|
22913
23974
|
return initializer.getText();
|
|
22914
23975
|
}
|
|
22915
23976
|
return void 0;
|
|
22916
23977
|
}
|
|
22917
23978
|
function objectPropertyKeys(literal, key) {
|
|
22918
23979
|
const prop = literal.getProperty(key);
|
|
22919
|
-
if (!prop || !
|
|
23980
|
+
if (!prop || !Node17.isPropertyAssignment(prop)) {
|
|
22920
23981
|
return [];
|
|
22921
23982
|
}
|
|
22922
23983
|
const initializer = prop.getInitializer();
|
|
22923
|
-
if (!initializer || !
|
|
23984
|
+
if (!initializer || !Node17.isObjectLiteralExpression(initializer)) {
|
|
22924
23985
|
return [];
|
|
22925
23986
|
}
|
|
22926
23987
|
const out = [];
|
|
22927
23988
|
for (const member of initializer.getProperties()) {
|
|
22928
|
-
if (
|
|
23989
|
+
if (Node17.isPropertyAssignment(member) || Node17.isShorthandPropertyAssignment(member) || Node17.isMethodDeclaration(member)) {
|
|
22929
23990
|
const nameNode = member.getNameNode();
|
|
22930
23991
|
if (nameNode) {
|
|
22931
23992
|
out.push(nameNode.getText());
|
|
@@ -22936,7 +23997,7 @@ function objectPropertyKeys(literal, key) {
|
|
|
22936
23997
|
}
|
|
22937
23998
|
function collectResolveKeys(literal) {
|
|
22938
23999
|
const prop = literal.getProperty("resolve");
|
|
22939
|
-
if (!prop || !
|
|
24000
|
+
if (!prop || !Node17.isPropertyAssignment(prop)) {
|
|
22940
24001
|
return [];
|
|
22941
24002
|
}
|
|
22942
24003
|
const initializer = prop.getInitializer();
|
|
@@ -22944,22 +24005,22 @@ function collectResolveKeys(literal) {
|
|
|
22944
24005
|
return [];
|
|
22945
24006
|
}
|
|
22946
24007
|
const keys = [];
|
|
22947
|
-
if (
|
|
24008
|
+
if (Node17.isObjectLiteralExpression(initializer)) {
|
|
22948
24009
|
for (const member of initializer.getProperties()) {
|
|
22949
|
-
if (
|
|
24010
|
+
if (Node17.isPropertyAssignment(member) || Node17.isShorthandPropertyAssignment(member) || Node17.isMethodDeclaration(member)) {
|
|
22950
24011
|
const nameNode = member.getNameNode();
|
|
22951
24012
|
if (nameNode) {
|
|
22952
24013
|
keys.push(nameNode.getText());
|
|
22953
24014
|
}
|
|
22954
24015
|
}
|
|
22955
24016
|
}
|
|
22956
|
-
} else if (
|
|
24017
|
+
} else if (Node17.isArrayLiteralExpression(initializer)) {
|
|
22957
24018
|
for (const element of initializer.getElements()) {
|
|
22958
|
-
if (
|
|
24019
|
+
if (Node17.isObjectLiteralExpression(element)) {
|
|
22959
24020
|
const tokenProp = element.getProperty("token");
|
|
22960
|
-
if (tokenProp &&
|
|
24021
|
+
if (tokenProp && Node17.isPropertyAssignment(tokenProp)) {
|
|
22961
24022
|
const tokenInit = tokenProp.getInitializer();
|
|
22962
|
-
if (tokenInit && (
|
|
24023
|
+
if (tokenInit && (Node17.isStringLiteral(tokenInit) || Node17.isIdentifier(tokenInit))) {
|
|
22963
24024
|
keys.push(tokenInit.getText().replaceAll(/^['"]|['"]$/g, ""));
|
|
22964
24025
|
}
|
|
22965
24026
|
}
|
|
@@ -23011,7 +24072,7 @@ function computeRelativeSpecifiers(source) {
|
|
|
23011
24072
|
// packages/dbx-components-mcp/src/tools/route/load-sources.ts
|
|
23012
24073
|
var TRY_EXTENSIONS = [".ts", ".tsx", "/index.ts", "/index.tsx"];
|
|
23013
24074
|
async function loadRouteSources(args) {
|
|
23014
|
-
const cwdResolved = args.cwd ?
|
|
24075
|
+
const cwdResolved = args.cwd ? resolve24(process.cwd(), args.cwd) : process.cwd();
|
|
23015
24076
|
guardCwdInsideServer(args.cwd, cwdResolved);
|
|
23016
24077
|
const collected = /* @__PURE__ */ new Map();
|
|
23017
24078
|
if (args.sources) {
|
|
@@ -23083,21 +24144,21 @@ async function loadOne(relative13, cwd, into) {
|
|
|
23083
24144
|
if (into.has(relative13)) {
|
|
23084
24145
|
return;
|
|
23085
24146
|
}
|
|
23086
|
-
const absolute =
|
|
24147
|
+
const absolute = resolve24(cwd, relative13);
|
|
23087
24148
|
const cwdPrefix = cwd.endsWith(sep5) ? cwd : cwd + sep5;
|
|
23088
24149
|
if (!absolute.startsWith(cwdPrefix) && absolute !== cwd) {
|
|
23089
24150
|
throw new Error(`Path \`${relative13}\` resolves outside the server cwd and is not allowed.`);
|
|
23090
24151
|
}
|
|
23091
|
-
const text = await
|
|
24152
|
+
const text = await readFile11(absolute, "utf8");
|
|
23092
24153
|
into.set(relative13, { name: relative13, text });
|
|
23093
24154
|
}
|
|
23094
24155
|
async function resolveRelativeImport(fromFile, specifier, cwd) {
|
|
23095
24156
|
if (!specifier.startsWith(".")) {
|
|
23096
24157
|
return void 0;
|
|
23097
24158
|
}
|
|
23098
|
-
const fromAbsolute = isAbsolute7(fromFile) ? fromFile :
|
|
24159
|
+
const fromAbsolute = isAbsolute7(fromFile) ? fromFile : resolve24(cwd, fromFile);
|
|
23099
24160
|
const fromDir = dirname7(fromAbsolute);
|
|
23100
|
-
const baseAbsolute =
|
|
24161
|
+
const baseAbsolute = resolve24(fromDir, specifier);
|
|
23101
24162
|
const cwdPrefix = cwd.endsWith(sep5) ? cwd : cwd + sep5;
|
|
23102
24163
|
for (const ext of TRY_EXTENSIONS) {
|
|
23103
24164
|
const candidateAbsolute = baseAbsolute + ext;
|
|
@@ -23108,7 +24169,7 @@ async function resolveRelativeImport(fromFile, specifier, cwd) {
|
|
|
23108
24169
|
if (!exists) {
|
|
23109
24170
|
continue;
|
|
23110
24171
|
}
|
|
23111
|
-
const text = await
|
|
24172
|
+
const text = await readFile11(candidateAbsolute, "utf8");
|
|
23112
24173
|
const relativeName = candidateAbsolute.startsWith(cwdPrefix) ? candidateAbsolute.slice(cwdPrefix.length) : candidateAbsolute;
|
|
23113
24174
|
const result = { name: relativeName, text };
|
|
23114
24175
|
return result;
|
|
@@ -23476,8 +24537,8 @@ var DBX_ROUTE_TREE_TOOL = {
|
|
|
23476
24537
|
}
|
|
23477
24538
|
}
|
|
23478
24539
|
};
|
|
23479
|
-
var
|
|
23480
|
-
"sources?":
|
|
24540
|
+
var TreeArgsType2 = type42({
|
|
24541
|
+
"sources?": type42({ name: "string", text: "string" }).array(),
|
|
23481
24542
|
"paths?": "string[]",
|
|
23482
24543
|
"glob?": "string",
|
|
23483
24544
|
"format?": "'markdown' | 'json' | 'flat'",
|
|
@@ -23485,8 +24546,8 @@ var TreeArgsType = type40({
|
|
|
23485
24546
|
"cwd?": "string"
|
|
23486
24547
|
});
|
|
23487
24548
|
function parseArgs4(raw) {
|
|
23488
|
-
const parsed =
|
|
23489
|
-
if (parsed instanceof
|
|
24549
|
+
const parsed = TreeArgsType2(raw);
|
|
24550
|
+
if (parsed instanceof type42.errors) {
|
|
23490
24551
|
throw new TypeError(`Invalid arguments: ${parsed.summary}`);
|
|
23491
24552
|
}
|
|
23492
24553
|
const result = {
|
|
@@ -23536,7 +24597,7 @@ var routeTreeTool = {
|
|
|
23536
24597
|
};
|
|
23537
24598
|
|
|
23538
24599
|
// packages/dbx-components-mcp/src/tools/route-lookup.tool.ts
|
|
23539
|
-
import { type as
|
|
24600
|
+
import { type as type43 } from "arktype";
|
|
23540
24601
|
var DBX_ROUTE_LOOKUP_TOOL = {
|
|
23541
24602
|
name: "dbx_route_lookup",
|
|
23542
24603
|
description: ["Look up a single UIRouter state by name, full URL, or component class name. Returns the state's URL, component, parent chain, params, resolves, siblings, and children.", "", "Provide at least one of `sources` / `paths` / `glob` to point the tool at the source set, plus a `topic`.", "", "Resolution order: exact state name \u2192 URL path \u2192 component class name \u2192 fuzzy substring (returns up to 5 candidates)."].join("\n"),
|
|
@@ -23561,9 +24622,9 @@ var DBX_ROUTE_LOOKUP_TOOL = {
|
|
|
23561
24622
|
required: ["topic"]
|
|
23562
24623
|
}
|
|
23563
24624
|
};
|
|
23564
|
-
var LookupArgsType2 =
|
|
24625
|
+
var LookupArgsType2 = type43({
|
|
23565
24626
|
topic: "string",
|
|
23566
|
-
"sources?":
|
|
24627
|
+
"sources?": type43({ name: "string", text: "string" }).array(),
|
|
23567
24628
|
"paths?": "string[]",
|
|
23568
24629
|
"glob?": "string",
|
|
23569
24630
|
"depth?": "'brief' | 'full'",
|
|
@@ -23571,7 +24632,7 @@ var LookupArgsType2 = type41({
|
|
|
23571
24632
|
});
|
|
23572
24633
|
function parseArgs5(raw) {
|
|
23573
24634
|
const parsed = LookupArgsType2(raw);
|
|
23574
|
-
if (parsed instanceof
|
|
24635
|
+
if (parsed instanceof type43.errors) {
|
|
23575
24636
|
throw new TypeError(`Invalid arguments: ${parsed.summary}`);
|
|
23576
24637
|
}
|
|
23577
24638
|
const result = {
|
|
@@ -23764,7 +24825,7 @@ var routeLookupTool = {
|
|
|
23764
24825
|
};
|
|
23765
24826
|
|
|
23766
24827
|
// packages/dbx-components-mcp/src/tools/route-search.tool.ts
|
|
23767
|
-
import { type as
|
|
24828
|
+
import { type as type44 } from "arktype";
|
|
23768
24829
|
var DBX_ROUTE_SEARCH_TOOL = {
|
|
23769
24830
|
name: "dbx_route_search",
|
|
23770
24831
|
description: ["Search the UIRouter state tree of a dbx-components app. Matches against state names, full URLs, component class names, resolve keys, and source-file paths. Returns the top 10 results with state name, URL, component, and source location.", "", "Provide at least one of `sources` / `paths` / `glob` plus a `query`. `scope` narrows to a single axis (`name`, `url`, `component`, `resolve`)."].join("\n"),
|
|
@@ -23788,17 +24849,17 @@ var DBX_ROUTE_SEARCH_TOOL = {
|
|
|
23788
24849
|
required: ["query"]
|
|
23789
24850
|
}
|
|
23790
24851
|
};
|
|
23791
|
-
var
|
|
24852
|
+
var SearchArgsType3 = type44({
|
|
23792
24853
|
query: "string",
|
|
23793
|
-
"sources?":
|
|
24854
|
+
"sources?": type44({ name: "string", text: "string" }).array(),
|
|
23794
24855
|
"paths?": "string[]",
|
|
23795
24856
|
"glob?": "string",
|
|
23796
24857
|
"scope?": "'name' | 'url' | 'component' | 'resolve' | 'all'",
|
|
23797
24858
|
"cwd?": "string"
|
|
23798
24859
|
});
|
|
23799
24860
|
function parseArgs6(raw) {
|
|
23800
|
-
const parsed =
|
|
23801
|
-
if (parsed instanceof
|
|
24861
|
+
const parsed = SearchArgsType3(raw);
|
|
24862
|
+
if (parsed instanceof type44.errors) {
|
|
23802
24863
|
throw new TypeError(`Invalid arguments: ${parsed.summary}`);
|
|
23803
24864
|
}
|
|
23804
24865
|
const result = {
|
|
@@ -23891,14 +24952,14 @@ var routeSearchTool = {
|
|
|
23891
24952
|
};
|
|
23892
24953
|
|
|
23893
24954
|
// packages/dbx-components-mcp/src/tools/_lookup.factory.ts
|
|
23894
|
-
import { type as
|
|
23895
|
-
var LOOKUP_ARGS_TYPE =
|
|
24955
|
+
import { type as type45 } from "arktype";
|
|
24956
|
+
var LOOKUP_ARGS_TYPE = type45({
|
|
23896
24957
|
topic: "string",
|
|
23897
24958
|
"depth?": "'brief' | 'full'"
|
|
23898
24959
|
});
|
|
23899
24960
|
function parseLookupArgs(raw) {
|
|
23900
24961
|
const parsed = LOOKUP_ARGS_TYPE(raw);
|
|
23901
|
-
if (parsed instanceof
|
|
24962
|
+
if (parsed instanceof type45.errors) {
|
|
23902
24963
|
throw new TypeError(`Invalid arguments: ${parsed.summary}`);
|
|
23903
24964
|
}
|
|
23904
24965
|
const result = {
|
|
@@ -24100,7 +25161,7 @@ function createLookupFilterTool(input) {
|
|
|
24100
25161
|
}
|
|
24101
25162
|
|
|
24102
25163
|
// packages/dbx-components-mcp/src/tools/filter-scaffold.tool.ts
|
|
24103
|
-
import { type as
|
|
25164
|
+
import { type as type46 } from "arktype";
|
|
24104
25165
|
var DBX_FILTER_SCAFFOLD_TOOL = {
|
|
24105
25166
|
name: "dbx_filter_scaffold",
|
|
24106
25167
|
description: [
|
|
@@ -24125,7 +25186,7 @@ var DBX_FILTER_SCAFFOLD_TOOL = {
|
|
|
24125
25186
|
required: ["model_name", "filter_type"]
|
|
24126
25187
|
}
|
|
24127
25188
|
};
|
|
24128
|
-
var ScaffoldArgsType5 =
|
|
25189
|
+
var ScaffoldArgsType5 = type46({
|
|
24129
25190
|
model_name: "string",
|
|
24130
25191
|
filter_type: "string",
|
|
24131
25192
|
"preset_keys?": "string[]",
|
|
@@ -24133,7 +25194,7 @@ var ScaffoldArgsType5 = type44({
|
|
|
24133
25194
|
});
|
|
24134
25195
|
function parseArgs7(raw) {
|
|
24135
25196
|
const parsed = ScaffoldArgsType5(raw);
|
|
24136
|
-
if (parsed instanceof
|
|
25197
|
+
if (parsed instanceof type46.errors) {
|
|
24137
25198
|
throw new TypeError(`Invalid arguments: ${parsed.summary}`);
|
|
24138
25199
|
}
|
|
24139
25200
|
const modelName = parsed.model_name.trim();
|
|
@@ -24373,8 +25434,8 @@ function createLookupPipeTool(input) {
|
|
|
24373
25434
|
|
|
24374
25435
|
// packages/dbx-components-mcp/src/tools/artifact-scaffold.tool.ts
|
|
24375
25436
|
import { access } from "node:fs/promises";
|
|
24376
|
-
import { resolve as
|
|
24377
|
-
import { type as
|
|
25437
|
+
import { resolve as resolve25, sep as sep6 } from "node:path";
|
|
25438
|
+
import { type as type47 } from "arktype";
|
|
24378
25439
|
|
|
24379
25440
|
// packages/dbx-components-mcp/src/tools/artifact-scaffold/templates.ts
|
|
24380
25441
|
function splitWords(input) {
|
|
@@ -24922,7 +25983,7 @@ var DBX_ARTIFACT_SCAFFOLD_TOOL = {
|
|
|
24922
25983
|
required: ["artifact", "name", "componentDir", "apiDir"]
|
|
24923
25984
|
}
|
|
24924
25985
|
};
|
|
24925
|
-
var ScaffoldArtifactArgsType =
|
|
25986
|
+
var ScaffoldArtifactArgsType = type47({
|
|
24926
25987
|
artifact: ARTIFACT_KIND_LITERAL_UNION,
|
|
24927
25988
|
name: "string",
|
|
24928
25989
|
componentDir: "string",
|
|
@@ -24935,7 +25996,7 @@ var ScaffoldArtifactArgsType = type45({
|
|
|
24935
25996
|
});
|
|
24936
25997
|
function parseArgs8(raw) {
|
|
24937
25998
|
const parsed = ScaffoldArtifactArgsType(raw);
|
|
24938
|
-
if (parsed instanceof
|
|
25999
|
+
if (parsed instanceof type47.errors) {
|
|
24939
26000
|
throw new TypeError(`Invalid arguments: ${parsed.summary}`);
|
|
24940
26001
|
}
|
|
24941
26002
|
const result = {
|
|
@@ -24948,7 +26009,7 @@ function parseArgs8(raw) {
|
|
|
24948
26009
|
return result;
|
|
24949
26010
|
}
|
|
24950
26011
|
function ensureInsideCwd(relativePath, cwd) {
|
|
24951
|
-
const absolute =
|
|
26012
|
+
const absolute = resolve25(cwd, relativePath);
|
|
24952
26013
|
const cwdPrefix = cwd.endsWith(sep6) ? cwd : cwd + sep6;
|
|
24953
26014
|
if (!absolute.startsWith(cwdPrefix) && absolute !== cwd) {
|
|
24954
26015
|
throw new Error(`Path \`${relativePath}\` resolves outside the server cwd and is not allowed.`);
|
|
@@ -24988,7 +26049,7 @@ async function runArtifactScaffold(rawArgs) {
|
|
|
24988
26049
|
const message = err instanceof Error ? err.message : String(err);
|
|
24989
26050
|
return toolError(`Scaffold failed: ${message}`);
|
|
24990
26051
|
}
|
|
24991
|
-
const checked = await applyIdempotency(raw, (relativePath) => fileExists2(
|
|
26052
|
+
const checked = await applyIdempotency(raw, (relativePath) => fileExists2(resolve25(cwd, relativePath)));
|
|
24992
26053
|
const text = formatResult9(checked);
|
|
24993
26054
|
const result = {
|
|
24994
26055
|
content: [{ type: "text", text }]
|
|
@@ -25001,7 +26062,7 @@ var artifactScaffoldTool = {
|
|
|
25001
26062
|
};
|
|
25002
26063
|
|
|
25003
26064
|
// packages/dbx-components-mcp/src/tools/artifact-file-convention.tool.ts
|
|
25004
|
-
import { type as
|
|
26065
|
+
import { type as type48 } from "arktype";
|
|
25005
26066
|
|
|
25006
26067
|
// packages/dbx-components-mcp/src/tools/artifact-file-convention/spec.ts
|
|
25007
26068
|
var FIRESTORE_MODEL = {
|
|
@@ -25437,7 +26498,7 @@ var DBX_ARTIFACT_FILE_CONVENTION_TOOL = {
|
|
|
25437
26498
|
required: ["artifact"]
|
|
25438
26499
|
}
|
|
25439
26500
|
};
|
|
25440
|
-
var FileConventionArgsType =
|
|
26501
|
+
var FileConventionArgsType = type48({
|
|
25441
26502
|
artifact: ARTIFACT_KIND_LITERAL_UNION2,
|
|
25442
26503
|
"componentDir?": "string",
|
|
25443
26504
|
"apiDir?": "string",
|
|
@@ -25445,7 +26506,7 @@ var FileConventionArgsType = type46({
|
|
|
25445
26506
|
});
|
|
25446
26507
|
function parseArgs9(raw) {
|
|
25447
26508
|
const parsed = FileConventionArgsType(raw);
|
|
25448
|
-
if (parsed instanceof
|
|
26509
|
+
if (parsed instanceof type48.errors) {
|
|
25449
26510
|
throw new TypeError(`Invalid arguments: ${parsed.summary}`);
|
|
25450
26511
|
}
|
|
25451
26512
|
const result = {
|
|
@@ -25478,12 +26539,12 @@ var artifactFileConventionTool = {
|
|
|
25478
26539
|
};
|
|
25479
26540
|
|
|
25480
26541
|
// packages/dbx-components-mcp/src/tools/explain-rule.tool.ts
|
|
25481
|
-
import { type as
|
|
25482
|
-
var ExplainRuleArgsType =
|
|
26542
|
+
import { type as type49 } from "arktype";
|
|
26543
|
+
var ExplainRuleArgsType = type49({
|
|
25483
26544
|
code: "string",
|
|
25484
26545
|
"format?": "'markdown' | 'json'"
|
|
25485
26546
|
});
|
|
25486
|
-
var
|
|
26547
|
+
var TOOL8 = {
|
|
25487
26548
|
name: "dbx_explain_rule",
|
|
25488
26549
|
description: [
|
|
25489
26550
|
"Explain one validation rule by code. Returns the title, severity, source tool, what it flags, when it applies, when it does NOT apply, canonical fix, optional fix template, and any see-also references.",
|
|
@@ -25506,9 +26567,9 @@ var TOOL6 = {
|
|
|
25506
26567
|
required: ["code"]
|
|
25507
26568
|
}
|
|
25508
26569
|
};
|
|
25509
|
-
async function
|
|
26570
|
+
async function run7(rawArgs) {
|
|
25510
26571
|
const parsed = ExplainRuleArgsType(rawArgs);
|
|
25511
|
-
if (parsed instanceof
|
|
26572
|
+
if (parsed instanceof type49.errors) {
|
|
25512
26573
|
return toolError(`Invalid arguments: ${parsed.summary}`);
|
|
25513
26574
|
}
|
|
25514
26575
|
const exact = findRule(parsed.code);
|
|
@@ -25530,24 +26591,26 @@ async function run5(rawArgs) {
|
|
|
25530
26591
|
const result = { content: [{ type: "text", text }], isError: true };
|
|
25531
26592
|
return result;
|
|
25532
26593
|
}
|
|
25533
|
-
var explainRuleTool = { definition:
|
|
26594
|
+
var explainRuleTool = { definition: TOOL8, run: run7 };
|
|
25534
26595
|
|
|
25535
26596
|
// packages/dbx-components-mcp/src/tools/app-validate.tool.ts
|
|
25536
|
-
import { resolve as
|
|
26597
|
+
import { resolve as resolve26, join as join10 } from "node:path";
|
|
25537
26598
|
import { readdir as readdir6, stat as stat9 } from "node:fs/promises";
|
|
25538
|
-
import { type as
|
|
26599
|
+
import { type as type50 } from "arktype";
|
|
25539
26600
|
var Cluster = "'storagefile_m' | 'notification_m' | 'model_folder' | 'system_m' | 'fixture'";
|
|
25540
|
-
var AppValidateArgsType =
|
|
26601
|
+
var AppValidateArgsType = type50({
|
|
25541
26602
|
componentDir: "string",
|
|
25542
26603
|
apiDir: "string",
|
|
25543
26604
|
"format?": "'markdown' | 'json'",
|
|
25544
26605
|
"skip?": `(${Cluster})[]`
|
|
25545
26606
|
});
|
|
25546
|
-
var
|
|
26607
|
+
var TOOL9 = {
|
|
25547
26608
|
name: "dbx_app_validate",
|
|
25548
26609
|
description: [
|
|
25549
26610
|
"Aggregate validator for a downstream `-firebase` component + API app pair. Runs every per-domain validator (`storagefile_m`, `notification_m`, model-folder, `system_m`, fixture) and returns one severity-grouped report.",
|
|
25550
26611
|
"",
|
|
26612
|
+
"The `model_folder` cluster includes both folder-structure findings (canonical 5-file layout) and per-file content findings forwarded from `dbx_model_validate` \u2014 including the JSDoc-tag rules (`MODEL_IDENTITY_NOT_TAGGED`, `MODEL_GROUP_INTERFACE_MISSING_TAG`, `MODEL_INTERFACE_MISSING_TAG`) that flag downstream apps where `firestoreModelIdentity(...)` calls lack catalog tagging.",
|
|
26613
|
+
"",
|
|
25551
26614
|
"Replaces the six-tool dance an agent runs to validate one app end-to-end. Each finding is tagged with its source cluster, code, file/line, and canonical-fix line (when the rule catalog has an entry).",
|
|
25552
26615
|
"",
|
|
25553
26616
|
"Inputs:",
|
|
@@ -25573,9 +26636,9 @@ var TOOL7 = {
|
|
|
25573
26636
|
required: ["componentDir", "apiDir"]
|
|
25574
26637
|
}
|
|
25575
26638
|
};
|
|
25576
|
-
async function
|
|
26639
|
+
async function run8(rawArgs) {
|
|
25577
26640
|
const parsed = AppValidateArgsType(rawArgs);
|
|
25578
|
-
if (parsed instanceof
|
|
26641
|
+
if (parsed instanceof type50.errors) {
|
|
25579
26642
|
return toolError(`Invalid arguments: ${parsed.summary}`);
|
|
25580
26643
|
}
|
|
25581
26644
|
const cwd = process.cwd();
|
|
@@ -25585,8 +26648,8 @@ async function run6(rawArgs) {
|
|
|
25585
26648
|
} catch (err) {
|
|
25586
26649
|
return toolError(err instanceof Error ? err.message : String(err));
|
|
25587
26650
|
}
|
|
25588
|
-
const componentAbs =
|
|
25589
|
-
const apiAbs =
|
|
26651
|
+
const componentAbs = resolve26(cwd, parsed.componentDir);
|
|
26652
|
+
const apiAbs = resolve26(cwd, parsed.apiDir);
|
|
25590
26653
|
const skip = new Set(parsed.skip ?? []);
|
|
25591
26654
|
const findings = [];
|
|
25592
26655
|
const skipped = [];
|
|
@@ -25658,7 +26721,7 @@ async function runModelFolders(ctx) {
|
|
|
25658
26721
|
return;
|
|
25659
26722
|
}
|
|
25660
26723
|
try {
|
|
25661
|
-
const modelRoot =
|
|
26724
|
+
const modelRoot = join10(ctx.componentAbs, "src/lib/model");
|
|
25662
26725
|
const reservedNames = new Set(RESERVED_MODEL_FOLDERS.map((r) => r.name));
|
|
25663
26726
|
let entries;
|
|
25664
26727
|
try {
|
|
@@ -25675,7 +26738,7 @@ async function runModelFolders(ctx) {
|
|
|
25675
26738
|
for (const entry of entries) {
|
|
25676
26739
|
if (!entry.isDirectory()) continue;
|
|
25677
26740
|
if (reservedNames.has(entry.name)) continue;
|
|
25678
|
-
const inspection = await inspectFolder(
|
|
26741
|
+
const inspection = await inspectFolder(join10(modelRoot, entry.name));
|
|
25679
26742
|
inspections.push(inspection);
|
|
25680
26743
|
}
|
|
25681
26744
|
if (inspections.length === 0) {
|
|
@@ -25695,7 +26758,7 @@ async function runSystemFolder(ctx) {
|
|
|
25695
26758
|
ctx.skipped.push("system_m");
|
|
25696
26759
|
return;
|
|
25697
26760
|
}
|
|
25698
|
-
const systemPath =
|
|
26761
|
+
const systemPath = join10(ctx.componentAbs, "src/lib/model/system");
|
|
25699
26762
|
try {
|
|
25700
26763
|
let exists = true;
|
|
25701
26764
|
try {
|
|
@@ -25781,21 +26844,21 @@ function renderFinding(finding) {
|
|
|
25781
26844
|
function formatJson(report) {
|
|
25782
26845
|
return JSON.stringify(report, null, 2);
|
|
25783
26846
|
}
|
|
25784
|
-
var appValidateTool = { definition:
|
|
26847
|
+
var appValidateTool = { definition: TOOL9, run: run8 };
|
|
25785
26848
|
|
|
25786
26849
|
// packages/dbx-components-mcp/src/tools/model-list-component.tool.ts
|
|
25787
|
-
import { resolve as
|
|
25788
|
-
import { type as
|
|
26850
|
+
import { resolve as resolve27 } from "node:path";
|
|
26851
|
+
import { type as type51 } from "arktype";
|
|
25789
26852
|
|
|
25790
26853
|
// packages/dbx-components-mcp/src/tools/model-list-component/extract.ts
|
|
25791
|
-
import { readdir as readdir7, readFile as
|
|
25792
|
-
import { basename as basename6, join as
|
|
25793
|
-
import { Node as
|
|
26854
|
+
import { readdir as readdir7, readFile as readFile12, stat as stat10 } from "node:fs/promises";
|
|
26855
|
+
import { basename as basename6, join as join11, relative as relative6, sep as sep7 } from "node:path";
|
|
26856
|
+
import { Node as Node18, Project as Project13 } from "ts-morph";
|
|
25794
26857
|
var MODEL_SUBPATH2 = "src/lib/model";
|
|
25795
26858
|
var MODEL_SUBPATH_PREFIX = `${MODEL_SUBPATH2}/`;
|
|
25796
26859
|
var RESERVED_NAMES = RESERVED_MODEL_FOLDERS.map((r) => r.name);
|
|
25797
26860
|
async function extractComponentModels(componentAbs) {
|
|
25798
|
-
const modelRoot =
|
|
26861
|
+
const modelRoot = join11(componentAbs, MODEL_SUBPATH2);
|
|
25799
26862
|
const folders = await listFolders(modelRoot);
|
|
25800
26863
|
if (folders === void 0) {
|
|
25801
26864
|
const result2 = { modelRoot, models: [], skipped: [], unidentifiedFolders: [] };
|
|
@@ -25819,7 +26882,7 @@ async function extractComponentModels(componentAbs) {
|
|
|
25819
26882
|
skipReservedFolders: RESERVED_NAMES
|
|
25820
26883
|
});
|
|
25821
26884
|
const richByFolder = groupRichByFolder(richResult.models);
|
|
25822
|
-
const fallbackProject = new
|
|
26885
|
+
const fallbackProject = new Project13({ useInMemoryFileSystem: true });
|
|
25823
26886
|
const models = [];
|
|
25824
26887
|
const unidentified = [];
|
|
25825
26888
|
for (const folder of targetFolders) {
|
|
@@ -25885,7 +26948,7 @@ function projectRich(model, folder) {
|
|
|
25885
26948
|
}
|
|
25886
26949
|
async function fallbackForFolder(input) {
|
|
25887
26950
|
const { modelRoot, componentAbs, folder, project } = input;
|
|
25888
|
-
const folderAbs =
|
|
26951
|
+
const folderAbs = join11(modelRoot, folder);
|
|
25889
26952
|
const mainFile = await readMainFile(folderAbs, folder);
|
|
25890
26953
|
if (mainFile === void 0) return void 0;
|
|
25891
26954
|
const sourceFile = project.createSourceFile(mainFile.fileName, mainFile.text, { overwrite: true });
|
|
@@ -25919,9 +26982,9 @@ async function listFolders(modelRoot) {
|
|
|
25919
26982
|
return out;
|
|
25920
26983
|
}
|
|
25921
26984
|
async function readMainFile(folderAbs, folder) {
|
|
25922
|
-
const candidate =
|
|
26985
|
+
const candidate = join11(folderAbs, `${folder}.ts`);
|
|
25923
26986
|
try {
|
|
25924
|
-
const text = await
|
|
26987
|
+
const text = await readFile12(candidate, "utf8");
|
|
25925
26988
|
return { absPath: candidate, fileName: basename6(candidate), text };
|
|
25926
26989
|
} catch {
|
|
25927
26990
|
return void 0;
|
|
@@ -25931,7 +26994,7 @@ function findIdentityIn(sourceFile) {
|
|
|
25931
26994
|
for (const statement of sourceFile.getVariableStatements()) {
|
|
25932
26995
|
for (const decl of statement.getDeclarations()) {
|
|
25933
26996
|
const initializer = decl.getInitializer();
|
|
25934
|
-
if (!initializer || !
|
|
26997
|
+
if (!initializer || !Node18.isCallExpression(initializer)) continue;
|
|
25935
26998
|
if (initializer.getExpression().getText() !== "firestoreModelIdentity") continue;
|
|
25936
26999
|
const args = initializer.getArguments();
|
|
25937
27000
|
const parsed = parseIdentityArgs2(args);
|
|
@@ -25951,13 +27014,13 @@ function parseIdentityArgs2(args) {
|
|
|
25951
27014
|
return { parentIdentityRef: void 0, collectionName: stringLiteralValue3(args[0]), collectionPrefix: stringLiteralValue3(args[1]) };
|
|
25952
27015
|
}
|
|
25953
27016
|
if (args.length === 3) {
|
|
25954
|
-
const parent =
|
|
27017
|
+
const parent = Node18.isIdentifier(args[0]) ? args[0].getText() : void 0;
|
|
25955
27018
|
return { parentIdentityRef: parent, collectionName: stringLiteralValue3(args[1]), collectionPrefix: stringLiteralValue3(args[2]) };
|
|
25956
27019
|
}
|
|
25957
27020
|
return { parentIdentityRef: void 0, collectionName: void 0, collectionPrefix: void 0 };
|
|
25958
27021
|
}
|
|
25959
27022
|
function stringLiteralValue3(node) {
|
|
25960
|
-
if (
|
|
27023
|
+
if (Node18.isStringLiteral(node) || Node18.isNoSubstitutionTemplateLiteral(node)) {
|
|
25961
27024
|
return node.getLiteralText();
|
|
25962
27025
|
}
|
|
25963
27026
|
return void 0;
|
|
@@ -26060,12 +27123,12 @@ function stripCoverage(model) {
|
|
|
26060
27123
|
}
|
|
26061
27124
|
|
|
26062
27125
|
// packages/dbx-components-mcp/src/tools/model-list-component.tool.ts
|
|
26063
|
-
var ListArgsType2 =
|
|
27126
|
+
var ListArgsType2 = type51({
|
|
26064
27127
|
componentDir: "string",
|
|
26065
27128
|
"apiDir?": "string",
|
|
26066
27129
|
"format?": "'markdown' | 'json'"
|
|
26067
27130
|
});
|
|
26068
|
-
var
|
|
27131
|
+
var TOOL10 = {
|
|
26069
27132
|
name: "dbx_model_list_component",
|
|
26070
27133
|
description: [
|
|
26071
27134
|
"List every Firestore model declared in a downstream `-firebase` component package, with optional fixture-coverage annotation when an API app is also supplied.",
|
|
@@ -26089,9 +27152,9 @@ var TOOL8 = {
|
|
|
26089
27152
|
required: ["componentDir"]
|
|
26090
27153
|
}
|
|
26091
27154
|
};
|
|
26092
|
-
async function
|
|
27155
|
+
async function run9(rawArgs) {
|
|
26093
27156
|
const parsed = ListArgsType2(rawArgs);
|
|
26094
|
-
if (parsed instanceof
|
|
27157
|
+
if (parsed instanceof type51.errors) {
|
|
26095
27158
|
return toolError(`Invalid arguments: ${parsed.summary}`);
|
|
26096
27159
|
}
|
|
26097
27160
|
const cwd = process.cwd();
|
|
@@ -26101,8 +27164,8 @@ async function run7(rawArgs) {
|
|
|
26101
27164
|
} catch (err) {
|
|
26102
27165
|
return toolError(err instanceof Error ? err.message : String(err));
|
|
26103
27166
|
}
|
|
26104
|
-
const componentAbs =
|
|
26105
|
-
const apiAbs = parsed.apiDir ?
|
|
27167
|
+
const componentAbs = resolve27(cwd, parsed.componentDir);
|
|
27168
|
+
const apiAbs = parsed.apiDir ? resolve27(cwd, parsed.apiDir) : void 0;
|
|
26106
27169
|
let report;
|
|
26107
27170
|
try {
|
|
26108
27171
|
report = await listComponentModels(componentAbs, { componentDir: parsed.componentDir, apiDir: parsed.apiDir, apiAbs });
|
|
@@ -26113,26 +27176,26 @@ async function run7(rawArgs) {
|
|
|
26113
27176
|
const result = { content: [{ type: "text", text }] };
|
|
26114
27177
|
return result;
|
|
26115
27178
|
}
|
|
26116
|
-
var modelListComponentTool = { definition:
|
|
27179
|
+
var modelListComponentTool = { definition: TOOL10, run: run9 };
|
|
26117
27180
|
|
|
26118
27181
|
// packages/dbx-components-mcp/src/tools/server-actions-list-app.tool.ts
|
|
26119
|
-
import { resolve as
|
|
26120
|
-
import { type as
|
|
27182
|
+
import { resolve as resolve28 } from "node:path";
|
|
27183
|
+
import { type as type52 } from "arktype";
|
|
26121
27184
|
|
|
26122
27185
|
// packages/dbx-components-mcp/src/tools/server-actions-list-app/extract.ts
|
|
26123
|
-
import { readdir as readdir8, readFile as
|
|
26124
|
-
import { dirname as dirname8, join as
|
|
26125
|
-
import { Node as
|
|
27186
|
+
import { readdir as readdir8, readFile as readFile13, stat as stat11 } from "node:fs/promises";
|
|
27187
|
+
import { dirname as dirname8, join as join12, relative as relative7, sep as sep8 } from "node:path";
|
|
27188
|
+
import { Node as Node19, Project as Project14 } from "ts-morph";
|
|
26126
27189
|
var ACTION_SERVER_SUFFIX = ".action.server.ts";
|
|
26127
27190
|
var COMMON_MODEL_SUBPATH = "src/app/common/model";
|
|
26128
27191
|
var COMMON_BARREL_REL = "src/app/common/index.ts";
|
|
26129
27192
|
async function extractServerActions(apiAbs, apiRel) {
|
|
26130
|
-
const modelRoot =
|
|
27193
|
+
const modelRoot = join12(apiAbs, COMMON_MODEL_SUBPATH);
|
|
26131
27194
|
const actionFiles = await collectActionFiles(modelRoot);
|
|
26132
27195
|
if (actionFiles.length === 0) {
|
|
26133
27196
|
return { modelRoot, entries: [], fixtureStatus: "ok" };
|
|
26134
27197
|
}
|
|
26135
|
-
const project = new
|
|
27198
|
+
const project = new Project14({ useInMemoryFileSystem: true });
|
|
26136
27199
|
const commonBarrelExports = await readCommonBarrelExports(apiAbs);
|
|
26137
27200
|
const fixtureCoverageMap = /* @__PURE__ */ new Map();
|
|
26138
27201
|
let fixtureStatus = "ok";
|
|
@@ -26147,7 +27210,7 @@ async function extractServerActions(apiAbs, apiRel) {
|
|
|
26147
27210
|
}
|
|
26148
27211
|
const entries = [];
|
|
26149
27212
|
for (const filePath of actionFiles) {
|
|
26150
|
-
const text = await
|
|
27213
|
+
const text = await readFile13(filePath, "utf8");
|
|
26151
27214
|
const sourceFile = project.createSourceFile(filePath, text, { overwrite: true });
|
|
26152
27215
|
const classes = findServerActionClasses(sourceFile);
|
|
26153
27216
|
for (const className of classes) {
|
|
@@ -26187,7 +27250,7 @@ async function collectActionFiles(root) {
|
|
|
26187
27250
|
continue;
|
|
26188
27251
|
}
|
|
26189
27252
|
for (const entry of entries) {
|
|
26190
|
-
const full =
|
|
27253
|
+
const full = join12(current, entry.name);
|
|
26191
27254
|
if (entry.isDirectory()) {
|
|
26192
27255
|
stack.push(full);
|
|
26193
27256
|
continue;
|
|
@@ -26236,7 +27299,7 @@ async function findModuleCandidates(actionFilePath) {
|
|
|
26236
27299
|
for (const entry of entries) {
|
|
26237
27300
|
if (!entry.isFile()) continue;
|
|
26238
27301
|
if (!entry.name.endsWith(".module.ts")) continue;
|
|
26239
|
-
out.push(
|
|
27302
|
+
out.push(join12(dir, entry.name));
|
|
26240
27303
|
}
|
|
26241
27304
|
} catch {
|
|
26242
27305
|
}
|
|
@@ -26245,13 +27308,13 @@ async function findModuleCandidates(actionFilePath) {
|
|
|
26245
27308
|
}
|
|
26246
27309
|
async function safeRead(path) {
|
|
26247
27310
|
try {
|
|
26248
|
-
return await
|
|
27311
|
+
return await readFile13(path, "utf8");
|
|
26249
27312
|
} catch {
|
|
26250
27313
|
return void 0;
|
|
26251
27314
|
}
|
|
26252
27315
|
}
|
|
26253
27316
|
function inspectModuleText(input) {
|
|
26254
|
-
const project = new
|
|
27317
|
+
const project = new Project14({ useInMemoryFileSystem: true });
|
|
26255
27318
|
const sourceFile = project.createSourceFile("module.ts", input.text, { overwrite: true });
|
|
26256
27319
|
let providedByModule = false;
|
|
26257
27320
|
let exportedByModule = false;
|
|
@@ -26259,7 +27322,7 @@ function inspectModuleText(input) {
|
|
|
26259
27322
|
for (const decorator of cls.getDecorators()) {
|
|
26260
27323
|
if (decorator.getName() !== "Module") continue;
|
|
26261
27324
|
const args = decorator.getArguments();
|
|
26262
|
-
if (args.length === 0 || !
|
|
27325
|
+
if (args.length === 0 || !Node19.isObjectLiteralExpression(args[0])) continue;
|
|
26263
27326
|
const obj = args[0];
|
|
26264
27327
|
providedByModule ||= moduleArrayContains(obj, "providers", input.className);
|
|
26265
27328
|
exportedByModule ||= moduleArrayContains(obj, "exports", input.className);
|
|
@@ -26269,26 +27332,26 @@ function inspectModuleText(input) {
|
|
|
26269
27332
|
}
|
|
26270
27333
|
function moduleArrayContains(decoratorArg, propertyName, className) {
|
|
26271
27334
|
const property = decoratorArg.getProperty(propertyName);
|
|
26272
|
-
if (!property || !
|
|
27335
|
+
if (!property || !Node19.isPropertyAssignment(property)) return false;
|
|
26273
27336
|
const initializer = property.getInitializer();
|
|
26274
|
-
if (!initializer || !
|
|
27337
|
+
if (!initializer || !Node19.isArrayLiteralExpression(initializer)) return false;
|
|
26275
27338
|
for (const element of initializer.getElements()) {
|
|
26276
|
-
if (
|
|
26277
|
-
if (
|
|
27339
|
+
if (Node19.isIdentifier(element) && element.getText() === className) return true;
|
|
27340
|
+
if (Node19.isObjectLiteralExpression(element)) {
|
|
26278
27341
|
const provideProp = element.getProperty("provide");
|
|
26279
|
-
if (provideProp &&
|
|
27342
|
+
if (provideProp && Node19.isPropertyAssignment(provideProp)) {
|
|
26280
27343
|
const provideInit = provideProp.getInitializer();
|
|
26281
|
-
if (provideInit &&
|
|
27344
|
+
if (provideInit && Node19.isIdentifier(provideInit) && provideInit.getText() === className) return true;
|
|
26282
27345
|
}
|
|
26283
27346
|
}
|
|
26284
27347
|
}
|
|
26285
27348
|
return false;
|
|
26286
27349
|
}
|
|
26287
27350
|
async function readCommonBarrelExports(apiAbs) {
|
|
26288
|
-
const path =
|
|
27351
|
+
const path = join12(apiAbs, COMMON_BARREL_REL);
|
|
26289
27352
|
const text = await safeRead(path);
|
|
26290
27353
|
if (text === void 0) return /* @__PURE__ */ new Set();
|
|
26291
|
-
const project = new
|
|
27354
|
+
const project = new Project14({ useInMemoryFileSystem: true });
|
|
26292
27355
|
const sourceFile = project.createSourceFile(path, text, { overwrite: true });
|
|
26293
27356
|
const exported = /* @__PURE__ */ new Set();
|
|
26294
27357
|
for (const decl of sourceFile.getExportDeclarations()) {
|
|
@@ -26332,11 +27395,11 @@ function collectInterfaceGetters(sourceFile) {
|
|
|
26332
27395
|
const out = /* @__PURE__ */ new Map();
|
|
26333
27396
|
for (const iface of sourceFile.getInterfaces()) {
|
|
26334
27397
|
for (const member of iface.getMembers()) {
|
|
26335
|
-
if (
|
|
27398
|
+
if (Node19.isGetAccessorDeclaration(member)) {
|
|
26336
27399
|
out.set(member.getName(), iface.getName());
|
|
26337
27400
|
continue;
|
|
26338
27401
|
}
|
|
26339
|
-
if (
|
|
27402
|
+
if (Node19.isPropertySignature(member)) {
|
|
26340
27403
|
out.set(member.getName(), iface.getName());
|
|
26341
27404
|
}
|
|
26342
27405
|
}
|
|
@@ -26348,7 +27411,7 @@ function collectClassGetters(sourceFile) {
|
|
|
26348
27411
|
for (const cls of sourceFile.getClasses()) {
|
|
26349
27412
|
const set = /* @__PURE__ */ new Set();
|
|
26350
27413
|
for (const member of cls.getMembers()) {
|
|
26351
|
-
if (
|
|
27414
|
+
if (Node19.isGetAccessorDeclaration(member)) set.add(member.getName());
|
|
26352
27415
|
}
|
|
26353
27416
|
if (set.size > 0) out.set(cls.getName() ?? "<anon>", set);
|
|
26354
27417
|
}
|
|
@@ -26427,11 +27490,11 @@ async function listAppServerActions(apiAbs, options) {
|
|
|
26427
27490
|
}
|
|
26428
27491
|
|
|
26429
27492
|
// packages/dbx-components-mcp/src/tools/server-actions-list-app.tool.ts
|
|
26430
|
-
var ListArgsType3 =
|
|
27493
|
+
var ListArgsType3 = type52({
|
|
26431
27494
|
apiDir: "string",
|
|
26432
27495
|
"format?": "'markdown' | 'json'"
|
|
26433
27496
|
});
|
|
26434
|
-
var
|
|
27497
|
+
var TOOL11 = {
|
|
26435
27498
|
name: "dbx_server_actions_list_app",
|
|
26436
27499
|
description: [
|
|
26437
27500
|
"List every `*ServerActions` abstract class declared in an API app, with NestJS module wiring, common-barrel export status, and test-fixture coverage.",
|
|
@@ -26454,9 +27517,9 @@ var TOOL9 = {
|
|
|
26454
27517
|
required: ["apiDir"]
|
|
26455
27518
|
}
|
|
26456
27519
|
};
|
|
26457
|
-
async function
|
|
27520
|
+
async function run10(rawArgs) {
|
|
26458
27521
|
const parsed = ListArgsType3(rawArgs);
|
|
26459
|
-
if (parsed instanceof
|
|
27522
|
+
if (parsed instanceof type52.errors) {
|
|
26460
27523
|
return toolError(`Invalid arguments: ${parsed.summary}`);
|
|
26461
27524
|
}
|
|
26462
27525
|
const cwd = process.cwd();
|
|
@@ -26465,7 +27528,7 @@ async function run8(rawArgs) {
|
|
|
26465
27528
|
} catch (err) {
|
|
26466
27529
|
return toolError(err instanceof Error ? err.message : String(err));
|
|
26467
27530
|
}
|
|
26468
|
-
const apiAbs =
|
|
27531
|
+
const apiAbs = resolve28(cwd, parsed.apiDir);
|
|
26469
27532
|
let report;
|
|
26470
27533
|
try {
|
|
26471
27534
|
report = await listAppServerActions(apiAbs, { apiDir: parsed.apiDir });
|
|
@@ -26476,19 +27539,19 @@ async function run8(rawArgs) {
|
|
|
26476
27539
|
const result = { content: [{ type: "text", text }] };
|
|
26477
27540
|
return result;
|
|
26478
27541
|
}
|
|
26479
|
-
var serverActionsListAppTool = { definition:
|
|
27542
|
+
var serverActionsListAppTool = { definition: TOOL11, run: run10 };
|
|
26480
27543
|
|
|
26481
27544
|
// packages/dbx-components-mcp/src/tools/mcp-config.tool.ts
|
|
26482
|
-
import { type as
|
|
26483
|
-
import { resolve as
|
|
27545
|
+
import { type as type59 } from "arktype";
|
|
27546
|
+
import { resolve as resolve35 } from "node:path";
|
|
26484
27547
|
|
|
26485
27548
|
// packages/dbx-components-mcp/src/tools/mcp-config/snapshot.ts
|
|
26486
|
-
import { dirname as dirname9, isAbsolute as isAbsolute8, relative as relative8, resolve as
|
|
27549
|
+
import { dirname as dirname9, isAbsolute as isAbsolute8, relative as relative8, resolve as resolve30 } from "node:path";
|
|
26487
27550
|
import { stat as stat13 } from "node:fs/promises";
|
|
26488
27551
|
|
|
26489
27552
|
// packages/dbx-components-mcp/src/scan/discover-downstream-packages.ts
|
|
26490
|
-
import { glob as fsGlob5, readFile as
|
|
26491
|
-
import { basename as basename7, join as
|
|
27553
|
+
import { glob as fsGlob5, readFile as readFile14, stat as stat12 } from "node:fs/promises";
|
|
27554
|
+
import { basename as basename7, join as join13, resolve as resolve29, sep as sep9 } from "node:path";
|
|
26492
27555
|
var COMPONENT_GLOBS = ["components/*-firebase", "components/*-shared", "components/*-web", "components/*-core"];
|
|
26493
27556
|
var APPS_GLOB = "apps/*";
|
|
26494
27557
|
var SCAN_CONFIG_FILENAME2 = "dbx-mcp.scan.json";
|
|
@@ -26518,7 +27581,7 @@ async function discoverConventionalDirs(workspaceRoot) {
|
|
|
26518
27581
|
}
|
|
26519
27582
|
for await (const match of fsGlob5(APPS_GLOB, { cwd: workspaceRoot })) {
|
|
26520
27583
|
const rel = match.split(sep9).join("/");
|
|
26521
|
-
if (await fileExists3(
|
|
27584
|
+
if (await fileExists3(join13(workspaceRoot, rel, SCAN_CONFIG_FILENAME2))) {
|
|
26522
27585
|
found.add(rel);
|
|
26523
27586
|
}
|
|
26524
27587
|
}
|
|
@@ -26533,13 +27596,13 @@ function normaliseExplicitDirs(dirs) {
|
|
|
26533
27596
|
return result;
|
|
26534
27597
|
}
|
|
26535
27598
|
async function inspectPackage2(workspaceRoot, relDir) {
|
|
26536
|
-
const absDir =
|
|
27599
|
+
const absDir = resolve29(workspaceRoot, relDir);
|
|
26537
27600
|
const isDir = await isDirectory2(absDir);
|
|
26538
27601
|
if (!isDir) return void 0;
|
|
26539
27602
|
const packageName = await readPackageName2(absDir, relDir);
|
|
26540
27603
|
const slug = packageNameToSlug(packageName);
|
|
26541
|
-
const hasScanConfig = await fileExists3(
|
|
26542
|
-
const declaredScanClusters = hasScanConfig ? await readDeclaredClusters(
|
|
27604
|
+
const hasScanConfig = await fileExists3(join13(absDir, SCAN_CONFIG_FILENAME2));
|
|
27605
|
+
const declaredScanClusters = hasScanConfig ? await readDeclaredClusters(join13(absDir, SCAN_CONFIG_FILENAME2)) : [];
|
|
26543
27606
|
const heuristicClusters = await detectCandidateClusters(absDir);
|
|
26544
27607
|
const candidateClusters = mergeClusters(heuristicClusters, declaredScanClusters);
|
|
26545
27608
|
return {
|
|
@@ -26572,7 +27635,7 @@ async function readPackageName2(absDir, relDir) {
|
|
|
26572
27635
|
const fallback = basename7(relDir);
|
|
26573
27636
|
let result = fallback;
|
|
26574
27637
|
try {
|
|
26575
|
-
const text = await
|
|
27638
|
+
const text = await readFile14(join13(absDir, PACKAGE_JSON2), "utf8");
|
|
26576
27639
|
const parsed = JSON.parse(text);
|
|
26577
27640
|
if (typeof parsed.name === "string" && parsed.name.length > 0) {
|
|
26578
27641
|
result = parsed.name;
|
|
@@ -26587,7 +27650,7 @@ function packageNameToSlug(packageName) {
|
|
|
26587
27650
|
async function readDeclaredClusters(scanConfigPath) {
|
|
26588
27651
|
let parsed = null;
|
|
26589
27652
|
try {
|
|
26590
|
-
const text = await
|
|
27653
|
+
const text = await readFile14(scanConfigPath, "utf8");
|
|
26591
27654
|
parsed = JSON.parse(text);
|
|
26592
27655
|
} catch {
|
|
26593
27656
|
parsed = null;
|
|
@@ -26664,7 +27727,7 @@ async function collectRegisteredSources(config, configBaseDir, workspaceRoot) {
|
|
|
26664
27727
|
for (const cluster of DOWNSTREAM_CLUSTERS) {
|
|
26665
27728
|
const declared = config[cluster]?.sources ?? [];
|
|
26666
27729
|
for (const declaredPath of declared) {
|
|
26667
|
-
const absolutePath = isAbsolute8(declaredPath) ? declaredPath :
|
|
27730
|
+
const absolutePath = isAbsolute8(declaredPath) ? declaredPath : resolve30(configBaseDir, declaredPath);
|
|
26668
27731
|
const exists = await fileExists4(absolutePath);
|
|
26669
27732
|
const relativePath = relativeOrAbsolute(workspaceRoot, absolutePath);
|
|
26670
27733
|
out.push({ cluster, declaredPath, absolutePath, relativePath, exists });
|
|
@@ -26702,21 +27765,21 @@ function relativeOrAbsolute(from, target) {
|
|
|
26702
27765
|
|
|
26703
27766
|
// packages/dbx-components-mcp/src/tools/mcp-config/init.ts
|
|
26704
27767
|
import { writeFile as nodeWriteFile3, mkdir as nodeMkdir, readFile as nodeReadFile7 } from "node:fs/promises";
|
|
26705
|
-
import { dirname as dirname10, relative as relative9, resolve as
|
|
27768
|
+
import { dirname as dirname10, relative as relative9, resolve as resolve31 } from "node:path";
|
|
26706
27769
|
var HEURISTIC_CLUSTERS = ["uiComponents", "forgeFields", "pipes", "actions", "filters"];
|
|
26707
27770
|
var DEFAULT_INCLUDE = ["src/**/*.ts"];
|
|
26708
27771
|
var DEFAULT_EXCLUDE = ["**/*.spec.ts", "**/*.test.ts", "**/*.stories.ts"];
|
|
26709
27772
|
async function buildInitPlan(input) {
|
|
26710
27773
|
const { snapshot } = input;
|
|
26711
|
-
const
|
|
27774
|
+
const readFile15 = input.readFile ?? defaultReadFile2;
|
|
26712
27775
|
const changes = [];
|
|
26713
27776
|
const sourcesToRegister = [];
|
|
26714
27777
|
for (const ps of snapshot.packages) {
|
|
26715
|
-
const planResult = await planPackageScanConfig({ snapshot, packageSnapshot: ps, readFile:
|
|
27778
|
+
const planResult = await planPackageScanConfig({ snapshot, packageSnapshot: ps, readFile: readFile15 });
|
|
26716
27779
|
if (planResult.change !== void 0) changes.push(planResult.change);
|
|
26717
27780
|
for (const reg of planResult.sourcesToRegister) sourcesToRegister.push(reg);
|
|
26718
27781
|
}
|
|
26719
|
-
const configChange = await planRootConfig({ snapshot, sourcesToRegister, readFile:
|
|
27782
|
+
const configChange = await planRootConfig({ snapshot, sourcesToRegister, readFile: readFile15 });
|
|
26720
27783
|
if (configChange !== void 0) changes.push(configChange);
|
|
26721
27784
|
return { workspaceRoot: snapshot.workspaceRoot, changes };
|
|
26722
27785
|
}
|
|
@@ -26730,10 +27793,10 @@ async function applyInitPlan(plan, opts) {
|
|
|
26730
27793
|
}
|
|
26731
27794
|
}
|
|
26732
27795
|
async function planPackageScanConfig(input) {
|
|
26733
|
-
const { snapshot, packageSnapshot, readFile:
|
|
27796
|
+
const { snapshot, packageSnapshot, readFile: readFile15 } = input;
|
|
26734
27797
|
const { pkg } = packageSnapshot;
|
|
26735
|
-
const scanConfigPath =
|
|
26736
|
-
const before = await tryRead(scanConfigPath,
|
|
27798
|
+
const scanConfigPath = resolve31(pkg.absDir, "dbx-mcp.scan.json");
|
|
27799
|
+
const before = await tryRead(scanConfigPath, readFile15);
|
|
26737
27800
|
const parsed = parseExisting(before);
|
|
26738
27801
|
const targetClusters = HEURISTIC_CLUSTERS.filter((c) => pkg.candidateClusters.includes(c));
|
|
26739
27802
|
if (targetClusters.length === 0 && parsed === null) {
|
|
@@ -26775,9 +27838,9 @@ async function planPackageScanConfig(input) {
|
|
|
26775
27838
|
return { change, sourcesToRegister };
|
|
26776
27839
|
}
|
|
26777
27840
|
async function planRootConfig(input) {
|
|
26778
|
-
const { snapshot, sourcesToRegister, readFile:
|
|
26779
|
-
const configPath = snapshot.configPath ??
|
|
26780
|
-
const before = snapshot.configPath !== null ? await tryRead(configPath,
|
|
27841
|
+
const { snapshot, sourcesToRegister, readFile: readFile15 } = input;
|
|
27842
|
+
const configPath = snapshot.configPath ?? resolve31(snapshot.workspaceRoot, "dbx-mcp.config.json");
|
|
27843
|
+
const before = snapshot.configPath !== null ? await tryRead(configPath, readFile15) : null;
|
|
26781
27844
|
const baseConfig = snapshot.config !== null ? cloneConfig(snapshot.config) : { version: 1 };
|
|
26782
27845
|
if (baseConfig.version !== 1) baseConfig.version = 1;
|
|
26783
27846
|
let mutated = false;
|
|
@@ -26805,11 +27868,11 @@ async function planRootConfig(input) {
|
|
|
26805
27868
|
};
|
|
26806
27869
|
}
|
|
26807
27870
|
function defaultOutFor(input) {
|
|
26808
|
-
const targetAbs =
|
|
27871
|
+
const targetAbs = resolve31(input.snapshot.workspaceRoot, ".tmp/dbx-mcp", `${input.slug}.${input.cluster}.json`);
|
|
26809
27872
|
return relative9(dirname10(input.scanConfigPath), targetAbs).split("\\").join("/");
|
|
26810
27873
|
}
|
|
26811
27874
|
function resolveScanOut(scanConfigPath, out) {
|
|
26812
|
-
return
|
|
27875
|
+
return resolve31(dirname10(scanConfigPath), out);
|
|
26813
27876
|
}
|
|
26814
27877
|
function relativeFromConfig(snapshot, absolute) {
|
|
26815
27878
|
const configDir = snapshot.configPath !== null ? dirname10(snapshot.configPath) : snapshot.workspaceRoot;
|
|
@@ -26842,9 +27905,9 @@ function cloneConfig(config) {
|
|
|
26842
27905
|
}
|
|
26843
27906
|
return out;
|
|
26844
27907
|
}
|
|
26845
|
-
async function tryRead(path,
|
|
27908
|
+
async function tryRead(path, readFile15) {
|
|
26846
27909
|
try {
|
|
26847
|
-
return await
|
|
27910
|
+
return await readFile15(path);
|
|
26848
27911
|
} catch {
|
|
26849
27912
|
return null;
|
|
26850
27913
|
}
|
|
@@ -26856,12 +27919,12 @@ var defaultMkdir = async (dir) => {
|
|
|
26856
27919
|
};
|
|
26857
27920
|
|
|
26858
27921
|
// packages/dbx-components-mcp/src/scan/actions-build-manifest.ts
|
|
26859
|
-
import { relative as relative10, resolve as
|
|
26860
|
-
import { type as
|
|
26861
|
-
import { Project as
|
|
27922
|
+
import { relative as relative10, resolve as resolve32 } from "node:path";
|
|
27923
|
+
import { type as type54 } from "arktype";
|
|
27924
|
+
import { Project as Project15 } from "ts-morph";
|
|
26862
27925
|
|
|
26863
27926
|
// packages/dbx-components-mcp/src/scan/actions-extract.ts
|
|
26864
|
-
import { Node as
|
|
27927
|
+
import { Node as Node20, SyntaxKind as SyntaxKind12 } from "ts-morph";
|
|
26865
27928
|
var ACTION_MARKER = "dbxAction";
|
|
26866
27929
|
var ACTION_SLUG_TAG = "dbxActionSlug";
|
|
26867
27930
|
var ACTION_ROLE_TAG = "dbxActionRole";
|
|
@@ -27069,7 +28132,7 @@ function filterStates(values) {
|
|
|
27069
28132
|
}
|
|
27070
28133
|
function readEnumMemberLiteral(member) {
|
|
27071
28134
|
const initializer = member.getInitializer();
|
|
27072
|
-
if (initializer !== void 0 && (
|
|
28135
|
+
if (initializer !== void 0 && (Node20.isStringLiteral(initializer) || Node20.isNoSubstitutionTemplateLiteral(initializer))) {
|
|
27073
28136
|
return initializer.getLiteralText();
|
|
27074
28137
|
}
|
|
27075
28138
|
return member.getName();
|
|
@@ -27141,7 +28204,7 @@ function extractStoreObservables(decl) {
|
|
|
27141
28204
|
return out;
|
|
27142
28205
|
}
|
|
27143
28206
|
function isVisibleMethod(method) {
|
|
27144
|
-
if (method.hasModifier(
|
|
28207
|
+
if (method.hasModifier(SyntaxKind12.PrivateKeyword) || method.hasModifier(SyntaxKind12.ProtectedKeyword)) {
|
|
27145
28208
|
return false;
|
|
27146
28209
|
}
|
|
27147
28210
|
const name = method.getName();
|
|
@@ -27160,15 +28223,15 @@ function readMethodDescription(method) {
|
|
|
27160
28223
|
}
|
|
27161
28224
|
|
|
27162
28225
|
// packages/dbx-components-mcp/src/scan/actions-scan-config-schema.ts
|
|
27163
|
-
import { type as
|
|
27164
|
-
var ActionsScanSection =
|
|
28226
|
+
import { type as type53 } from "arktype";
|
|
28227
|
+
var ActionsScanSection = type53({
|
|
27165
28228
|
"source?": "string",
|
|
27166
28229
|
"module?": "string",
|
|
27167
28230
|
include: "string[] >= 1",
|
|
27168
28231
|
"exclude?": "string[]",
|
|
27169
28232
|
"out?": "string"
|
|
27170
28233
|
});
|
|
27171
|
-
var ActionsScanConfig =
|
|
28234
|
+
var ActionsScanConfig = type53({
|
|
27172
28235
|
version: "1",
|
|
27173
28236
|
actions: ActionsScanSection
|
|
27174
28237
|
});
|
|
@@ -27179,20 +28242,20 @@ var ACTIONS_SCAN_CONFIG_FILENAME = "dbx-mcp.scan.json";
|
|
|
27179
28242
|
var DEFAULT_READ_FILE9 = defaultReadFile;
|
|
27180
28243
|
var DEFAULT_GLOBBER4 = defaultGlobber;
|
|
27181
28244
|
async function buildActionsManifest(input) {
|
|
27182
|
-
const { projectRoot, generator, readFile:
|
|
27183
|
-
const configPath =
|
|
27184
|
-
const packagePath =
|
|
27185
|
-
const configOutcome = await loadScanConfig4(configPath,
|
|
28245
|
+
const { projectRoot, generator, readFile: readFile15 = DEFAULT_READ_FILE9, globber = DEFAULT_GLOBBER4, now = () => /* @__PURE__ */ new Date() } = input;
|
|
28246
|
+
const configPath = resolve32(projectRoot, ACTIONS_SCAN_CONFIG_FILENAME);
|
|
28247
|
+
const packagePath = resolve32(projectRoot, "package.json");
|
|
28248
|
+
const configOutcome = await loadScanConfig4(configPath, readFile15);
|
|
27186
28249
|
if (configOutcome.kind !== "ok") return configOutcome.outcome;
|
|
27187
28250
|
const scanSection = configOutcome.section;
|
|
27188
|
-
const packageOutcome = await loadPackageName(packagePath,
|
|
28251
|
+
const packageOutcome = await loadPackageName(packagePath, readFile15);
|
|
27189
28252
|
if (packageOutcome.kind !== "ok") return packageOutcome.outcome;
|
|
27190
28253
|
const packageName = packageOutcome.packageName;
|
|
27191
28254
|
const filePaths = await globber({ projectRoot, include: scanSection.include, exclude: scanSection.exclude ?? [] });
|
|
27192
|
-
const project = new
|
|
28255
|
+
const project = new Project15({ useInMemoryFileSystem: true, skipAddingFilesFromTsConfig: true });
|
|
27193
28256
|
for (const relPath of filePaths) {
|
|
27194
|
-
const absolute =
|
|
27195
|
-
const text = await
|
|
28257
|
+
const absolute = resolve32(projectRoot, relPath);
|
|
28258
|
+
const text = await readFile15(absolute);
|
|
27196
28259
|
project.createSourceFile(absolute, text, { overwrite: true });
|
|
27197
28260
|
}
|
|
27198
28261
|
const extractResult = extractActionEntries({ project });
|
|
@@ -27209,10 +28272,10 @@ async function buildActionsManifest(input) {
|
|
|
27209
28272
|
};
|
|
27210
28273
|
const validated = ActionManifest(manifest);
|
|
27211
28274
|
let outcome;
|
|
27212
|
-
if (validated instanceof
|
|
28275
|
+
if (validated instanceof type54.errors) {
|
|
27213
28276
|
outcome = { kind: "invalid-manifest", error: validated.summary };
|
|
27214
28277
|
} else {
|
|
27215
|
-
const outPath =
|
|
28278
|
+
const outPath = resolve32(projectRoot, scanSection.out ?? DEFAULT_ACTIONS_SCAN_OUT_PATH);
|
|
27216
28279
|
outcome = {
|
|
27217
28280
|
kind: "success",
|
|
27218
28281
|
manifest: validated,
|
|
@@ -27223,10 +28286,10 @@ async function buildActionsManifest(input) {
|
|
|
27223
28286
|
}
|
|
27224
28287
|
return outcome;
|
|
27225
28288
|
}
|
|
27226
|
-
async function loadScanConfig4(configPath,
|
|
28289
|
+
async function loadScanConfig4(configPath, readFile15) {
|
|
27227
28290
|
let raw = null;
|
|
27228
28291
|
try {
|
|
27229
|
-
raw = await
|
|
28292
|
+
raw = await readFile15(configPath);
|
|
27230
28293
|
} catch {
|
|
27231
28294
|
raw = null;
|
|
27232
28295
|
}
|
|
@@ -27243,7 +28306,7 @@ async function loadScanConfig4(configPath, readFile13) {
|
|
|
27243
28306
|
}
|
|
27244
28307
|
if (parseError === null) {
|
|
27245
28308
|
const validated = ActionsScanConfig(parsed);
|
|
27246
|
-
if (validated instanceof
|
|
28309
|
+
if (validated instanceof type54.errors) {
|
|
27247
28310
|
result = { kind: "fail", outcome: { kind: "invalid-scan-config", configPath, error: validated.summary } };
|
|
27248
28311
|
} else {
|
|
27249
28312
|
result = { kind: "ok", section: validated.actions };
|
|
@@ -27374,9 +28437,9 @@ function formatExtractWarning3(warning) {
|
|
|
27374
28437
|
}
|
|
27375
28438
|
|
|
27376
28439
|
// packages/dbx-components-mcp/src/scan/filters-build-manifest.ts
|
|
27377
|
-
import { relative as relative11, resolve as
|
|
27378
|
-
import { type as
|
|
27379
|
-
import { Project as
|
|
28440
|
+
import { relative as relative11, resolve as resolve33 } from "node:path";
|
|
28441
|
+
import { type as type56 } from "arktype";
|
|
28442
|
+
import { Project as Project16 } from "ts-morph";
|
|
27380
28443
|
|
|
27381
28444
|
// packages/dbx-components-mcp/src/scan/filters-extract.ts
|
|
27382
28445
|
var FILTER_MARKER = "dbxFilter";
|
|
@@ -27568,15 +28631,15 @@ function extractOutputs3(decl) {
|
|
|
27568
28631
|
}
|
|
27569
28632
|
|
|
27570
28633
|
// packages/dbx-components-mcp/src/scan/filters-scan-config-schema.ts
|
|
27571
|
-
import { type as
|
|
27572
|
-
var FiltersScanSection =
|
|
28634
|
+
import { type as type55 } from "arktype";
|
|
28635
|
+
var FiltersScanSection = type55({
|
|
27573
28636
|
"source?": "string",
|
|
27574
28637
|
"module?": "string",
|
|
27575
28638
|
include: "string[] >= 1",
|
|
27576
28639
|
"exclude?": "string[]",
|
|
27577
28640
|
"out?": "string"
|
|
27578
28641
|
});
|
|
27579
|
-
var FiltersScanConfig =
|
|
28642
|
+
var FiltersScanConfig = type55({
|
|
27580
28643
|
version: "1",
|
|
27581
28644
|
filters: FiltersScanSection
|
|
27582
28645
|
});
|
|
@@ -27587,15 +28650,15 @@ var FILTERS_SCAN_CONFIG_FILENAME = "dbx-mcp.scan.json";
|
|
|
27587
28650
|
var DEFAULT_READ_FILE10 = defaultReadFile;
|
|
27588
28651
|
var DEFAULT_GLOBBER5 = defaultGlobber;
|
|
27589
28652
|
async function buildFiltersManifest(input) {
|
|
27590
|
-
const { projectRoot, generator, readFile:
|
|
27591
|
-
const configPath =
|
|
27592
|
-
const packagePath =
|
|
27593
|
-
const configOutcome = await loadScanConfig5(configPath,
|
|
28653
|
+
const { projectRoot, generator, readFile: readFile15 = DEFAULT_READ_FILE10, globber = DEFAULT_GLOBBER5, now = () => /* @__PURE__ */ new Date() } = input;
|
|
28654
|
+
const configPath = resolve33(projectRoot, FILTERS_SCAN_CONFIG_FILENAME);
|
|
28655
|
+
const packagePath = resolve33(projectRoot, "package.json");
|
|
28656
|
+
const configOutcome = await loadScanConfig5(configPath, readFile15);
|
|
27594
28657
|
if (configOutcome.kind !== "ok") {
|
|
27595
28658
|
return configOutcome.outcome;
|
|
27596
28659
|
}
|
|
27597
28660
|
const scanSection = configOutcome.section;
|
|
27598
|
-
const packageOutcome = await loadPackageName(packagePath,
|
|
28661
|
+
const packageOutcome = await loadPackageName(packagePath, readFile15);
|
|
27599
28662
|
if (packageOutcome.kind !== "ok") {
|
|
27600
28663
|
return packageOutcome.outcome;
|
|
27601
28664
|
}
|
|
@@ -27605,10 +28668,10 @@ async function buildFiltersManifest(input) {
|
|
|
27605
28668
|
include: scanSection.include,
|
|
27606
28669
|
exclude: scanSection.exclude ?? []
|
|
27607
28670
|
});
|
|
27608
|
-
const project = new
|
|
28671
|
+
const project = new Project16({ useInMemoryFileSystem: true, skipAddingFilesFromTsConfig: true });
|
|
27609
28672
|
for (const relPath of filePaths) {
|
|
27610
|
-
const absolute =
|
|
27611
|
-
const text = await
|
|
28673
|
+
const absolute = resolve33(projectRoot, relPath);
|
|
28674
|
+
const text = await readFile15(absolute);
|
|
27612
28675
|
project.createSourceFile(absolute, text, { overwrite: true });
|
|
27613
28676
|
}
|
|
27614
28677
|
const extractResult = extractFilterEntries({ project });
|
|
@@ -27625,10 +28688,10 @@ async function buildFiltersManifest(input) {
|
|
|
27625
28688
|
};
|
|
27626
28689
|
const validated = FilterManifest(manifest);
|
|
27627
28690
|
let outcome;
|
|
27628
|
-
if (validated instanceof
|
|
28691
|
+
if (validated instanceof type56.errors) {
|
|
27629
28692
|
outcome = { kind: "invalid-manifest", error: validated.summary };
|
|
27630
28693
|
} else {
|
|
27631
|
-
const outPath =
|
|
28694
|
+
const outPath = resolve33(projectRoot, scanSection.out ?? DEFAULT_FILTERS_SCAN_OUT_PATH);
|
|
27632
28695
|
outcome = {
|
|
27633
28696
|
kind: "success",
|
|
27634
28697
|
manifest: validated,
|
|
@@ -27639,10 +28702,10 @@ async function buildFiltersManifest(input) {
|
|
|
27639
28702
|
}
|
|
27640
28703
|
return outcome;
|
|
27641
28704
|
}
|
|
27642
|
-
async function loadScanConfig5(configPath,
|
|
28705
|
+
async function loadScanConfig5(configPath, readFile15) {
|
|
27643
28706
|
let raw = null;
|
|
27644
28707
|
try {
|
|
27645
|
-
raw = await
|
|
28708
|
+
raw = await readFile15(configPath);
|
|
27646
28709
|
} catch {
|
|
27647
28710
|
raw = null;
|
|
27648
28711
|
}
|
|
@@ -27659,7 +28722,7 @@ async function loadScanConfig5(configPath, readFile13) {
|
|
|
27659
28722
|
}
|
|
27660
28723
|
if (parseError === null) {
|
|
27661
28724
|
const validated = FiltersScanConfig(parsed);
|
|
27662
|
-
if (validated instanceof
|
|
28725
|
+
if (validated instanceof type56.errors) {
|
|
27663
28726
|
result = { kind: "fail", outcome: { kind: "invalid-scan-config", configPath, error: validated.summary } };
|
|
27664
28727
|
} else {
|
|
27665
28728
|
result = { kind: "ok", section: validated.filters };
|
|
@@ -27752,12 +28815,12 @@ function formatExtractWarning4(warning) {
|
|
|
27752
28815
|
}
|
|
27753
28816
|
|
|
27754
28817
|
// packages/dbx-components-mcp/src/scan/pipes-build-manifest.ts
|
|
27755
|
-
import { relative as relative12, resolve as
|
|
27756
|
-
import { type as
|
|
27757
|
-
import { Project as
|
|
28818
|
+
import { relative as relative12, resolve as resolve34 } from "node:path";
|
|
28819
|
+
import { type as type58 } from "arktype";
|
|
28820
|
+
import { Project as Project17 } from "ts-morph";
|
|
27758
28821
|
|
|
27759
28822
|
// packages/dbx-components-mcp/src/scan/pipes-extract.ts
|
|
27760
|
-
import { Node as
|
|
28823
|
+
import { Node as Node21 } from "ts-morph";
|
|
27761
28824
|
var PIPE_MARKER = "dbxPipe";
|
|
27762
28825
|
var PIPE_SLUG_TAG = "dbxPipeSlug";
|
|
27763
28826
|
var PIPE_CATEGORY_TAG = "dbxPipeCategory";
|
|
@@ -27950,7 +29013,7 @@ function readPipeDecoratorConfig(decorator) {
|
|
|
27950
29013
|
return void 0;
|
|
27951
29014
|
}
|
|
27952
29015
|
const firstArg = args[0];
|
|
27953
|
-
if (!
|
|
29016
|
+
if (!Node21.isObjectLiteralExpression(firstArg)) {
|
|
27954
29017
|
return void 0;
|
|
27955
29018
|
}
|
|
27956
29019
|
const name = readStringProperty(firstArg, "name");
|
|
@@ -27963,7 +29026,7 @@ function readPipeDecoratorConfig(decorator) {
|
|
|
27963
29026
|
}
|
|
27964
29027
|
function readBooleanProperty(obj, propName) {
|
|
27965
29028
|
const prop = obj.getProperty(propName);
|
|
27966
|
-
if (prop === void 0 || !
|
|
29029
|
+
if (prop === void 0 || !Node21.isPropertyAssignment(prop)) {
|
|
27967
29030
|
return void 0;
|
|
27968
29031
|
}
|
|
27969
29032
|
const initializer = prop.getInitializer();
|
|
@@ -27989,10 +29052,10 @@ function readTransformSignature(method, fallbackParamDescriptions) {
|
|
|
27989
29052
|
for (let i = 1; i < params.length; i += 1) {
|
|
27990
29053
|
const param = params[i];
|
|
27991
29054
|
const name = param.getName();
|
|
27992
|
-
const
|
|
29055
|
+
const type62 = readParamType(param);
|
|
27993
29056
|
const description = methodParamDescriptions.get(name) ?? fallbackParamDescriptions.get(name) ?? "";
|
|
27994
29057
|
const required = !param.isOptional() && !param.hasInitializer();
|
|
27995
|
-
args.push({ name, type:
|
|
29058
|
+
args.push({ name, type: type62, description, required });
|
|
27996
29059
|
}
|
|
27997
29060
|
return { inputType, outputType, args };
|
|
27998
29061
|
}
|
|
@@ -28029,15 +29092,15 @@ function extractParamName(rawTag) {
|
|
|
28029
29092
|
}
|
|
28030
29093
|
|
|
28031
29094
|
// packages/dbx-components-mcp/src/scan/pipes-scan-config-schema.ts
|
|
28032
|
-
import { type as
|
|
28033
|
-
var PipesScanSection =
|
|
29095
|
+
import { type as type57 } from "arktype";
|
|
29096
|
+
var PipesScanSection = type57({
|
|
28034
29097
|
"source?": "string",
|
|
28035
29098
|
"module?": "string",
|
|
28036
29099
|
include: "string[] >= 1",
|
|
28037
29100
|
"exclude?": "string[]",
|
|
28038
29101
|
"out?": "string"
|
|
28039
29102
|
});
|
|
28040
|
-
var PipesScanConfig =
|
|
29103
|
+
var PipesScanConfig = type57({
|
|
28041
29104
|
version: "1",
|
|
28042
29105
|
pipes: PipesScanSection
|
|
28043
29106
|
});
|
|
@@ -28048,15 +29111,15 @@ var PIPES_SCAN_CONFIG_FILENAME = "dbx-mcp.scan.json";
|
|
|
28048
29111
|
var DEFAULT_READ_FILE11 = defaultReadFile;
|
|
28049
29112
|
var DEFAULT_GLOBBER6 = defaultGlobber;
|
|
28050
29113
|
async function buildPipesManifest(input) {
|
|
28051
|
-
const { projectRoot, generator, readFile:
|
|
28052
|
-
const configPath =
|
|
28053
|
-
const packagePath =
|
|
28054
|
-
const configOutcome = await loadScanConfig6(configPath,
|
|
29114
|
+
const { projectRoot, generator, readFile: readFile15 = DEFAULT_READ_FILE11, globber = DEFAULT_GLOBBER6, now = () => /* @__PURE__ */ new Date() } = input;
|
|
29115
|
+
const configPath = resolve34(projectRoot, PIPES_SCAN_CONFIG_FILENAME);
|
|
29116
|
+
const packagePath = resolve34(projectRoot, "package.json");
|
|
29117
|
+
const configOutcome = await loadScanConfig6(configPath, readFile15);
|
|
28055
29118
|
if (configOutcome.kind !== "ok") {
|
|
28056
29119
|
return configOutcome.outcome;
|
|
28057
29120
|
}
|
|
28058
29121
|
const scanSection = configOutcome.section;
|
|
28059
|
-
const packageOutcome = await loadPackageName(packagePath,
|
|
29122
|
+
const packageOutcome = await loadPackageName(packagePath, readFile15);
|
|
28060
29123
|
if (packageOutcome.kind !== "ok") {
|
|
28061
29124
|
return packageOutcome.outcome;
|
|
28062
29125
|
}
|
|
@@ -28066,10 +29129,10 @@ async function buildPipesManifest(input) {
|
|
|
28066
29129
|
include: scanSection.include,
|
|
28067
29130
|
exclude: scanSection.exclude ?? []
|
|
28068
29131
|
});
|
|
28069
|
-
const project = new
|
|
29132
|
+
const project = new Project17({ useInMemoryFileSystem: true, skipAddingFilesFromTsConfig: true });
|
|
28070
29133
|
for (const relPath of filePaths) {
|
|
28071
|
-
const absolute =
|
|
28072
|
-
const text = await
|
|
29134
|
+
const absolute = resolve34(projectRoot, relPath);
|
|
29135
|
+
const text = await readFile15(absolute);
|
|
28073
29136
|
project.createSourceFile(absolute, text, { overwrite: true });
|
|
28074
29137
|
}
|
|
28075
29138
|
const extractResult = extractPipeEntries({ project });
|
|
@@ -28086,10 +29149,10 @@ async function buildPipesManifest(input) {
|
|
|
28086
29149
|
};
|
|
28087
29150
|
const validated = PipeManifest(manifest);
|
|
28088
29151
|
let outcome;
|
|
28089
|
-
if (validated instanceof
|
|
29152
|
+
if (validated instanceof type58.errors) {
|
|
28090
29153
|
outcome = { kind: "invalid-manifest", error: validated.summary };
|
|
28091
29154
|
} else {
|
|
28092
|
-
const outPath =
|
|
29155
|
+
const outPath = resolve34(projectRoot, scanSection.out ?? DEFAULT_PIPES_SCAN_OUT_PATH);
|
|
28093
29156
|
outcome = {
|
|
28094
29157
|
kind: "success",
|
|
28095
29158
|
manifest: validated,
|
|
@@ -28100,10 +29163,10 @@ async function buildPipesManifest(input) {
|
|
|
28100
29163
|
}
|
|
28101
29164
|
return outcome;
|
|
28102
29165
|
}
|
|
28103
|
-
async function loadScanConfig6(configPath,
|
|
29166
|
+
async function loadScanConfig6(configPath, readFile15) {
|
|
28104
29167
|
let raw = null;
|
|
28105
29168
|
try {
|
|
28106
|
-
raw = await
|
|
29169
|
+
raw = await readFile15(configPath);
|
|
28107
29170
|
} catch {
|
|
28108
29171
|
raw = null;
|
|
28109
29172
|
}
|
|
@@ -28120,7 +29183,7 @@ async function loadScanConfig6(configPath, readFile13) {
|
|
|
28120
29183
|
}
|
|
28121
29184
|
if (parseError === null) {
|
|
28122
29185
|
const validated = PipesScanConfig(parsed);
|
|
28123
|
-
if (validated instanceof
|
|
29186
|
+
if (validated instanceof type58.errors) {
|
|
28124
29187
|
result = { kind: "fail", outcome: { kind: "invalid-scan-config", configPath, error: validated.summary } };
|
|
28125
29188
|
} else {
|
|
28126
29189
|
result = { kind: "ok", section: validated.pipes };
|
|
@@ -28468,7 +29531,7 @@ function hasUnregisteredCandidates(snapshot) {
|
|
|
28468
29531
|
}
|
|
28469
29532
|
|
|
28470
29533
|
// packages/dbx-components-mcp/src/tools/mcp-config.tool.ts
|
|
28471
|
-
var
|
|
29534
|
+
var TOOL12 = {
|
|
28472
29535
|
name: "dbx_mcp_config",
|
|
28473
29536
|
description: [
|
|
28474
29537
|
"Inspect, validate, and configure the dbx-mcp downstream-manifest pipeline for a workspace.",
|
|
@@ -28512,7 +29575,7 @@ var TOOL10 = {
|
|
|
28512
29575
|
required: ["op"]
|
|
28513
29576
|
}
|
|
28514
29577
|
};
|
|
28515
|
-
var McpConfigArgsType =
|
|
29578
|
+
var McpConfigArgsType = type59({
|
|
28516
29579
|
op: "'status' | 'validate' | 'init' | 'refresh'",
|
|
28517
29580
|
"cwd?": "string",
|
|
28518
29581
|
"dryRun?": "boolean",
|
|
@@ -28520,12 +29583,12 @@ var McpConfigArgsType = type57({
|
|
|
28520
29583
|
});
|
|
28521
29584
|
function parseArgs10(rawArgs, defaultCwd) {
|
|
28522
29585
|
const parsed = McpConfigArgsType(rawArgs);
|
|
28523
|
-
if (parsed instanceof
|
|
29586
|
+
if (parsed instanceof type59.errors) {
|
|
28524
29587
|
return `Invalid arguments: ${parsed.summary}`;
|
|
28525
29588
|
}
|
|
28526
29589
|
let workspaceRoot = defaultCwd;
|
|
28527
29590
|
if (parsed.cwd !== void 0 && parsed.cwd.length > 0) {
|
|
28528
|
-
workspaceRoot =
|
|
29591
|
+
workspaceRoot = resolve35(defaultCwd, parsed.cwd);
|
|
28529
29592
|
}
|
|
28530
29593
|
if (parsed.explicitDirs !== void 0) {
|
|
28531
29594
|
for (const dir of parsed.explicitDirs) {
|
|
@@ -28543,7 +29606,7 @@ function parseArgs10(rawArgs, defaultCwd) {
|
|
|
28543
29606
|
explicitDirs: parsed.explicitDirs
|
|
28544
29607
|
};
|
|
28545
29608
|
}
|
|
28546
|
-
async function
|
|
29609
|
+
async function run11(rawArgs) {
|
|
28547
29610
|
const parsed = parseArgs10(rawArgs, process.cwd());
|
|
28548
29611
|
if (typeof parsed === "string") return toolError(parsed);
|
|
28549
29612
|
const snapshot = await buildSnapshot({ workspaceRoot: parsed.workspaceRoot, explicitDirs: parsed.explicitDirs });
|
|
@@ -28572,12 +29635,12 @@ async function run9(rawArgs) {
|
|
|
28572
29635
|
}
|
|
28573
29636
|
}
|
|
28574
29637
|
var mcpConfigTool = {
|
|
28575
|
-
definition:
|
|
28576
|
-
run:
|
|
29638
|
+
definition: TOOL12,
|
|
29639
|
+
run: run11
|
|
28577
29640
|
};
|
|
28578
29641
|
|
|
28579
29642
|
// packages/dbx-components-mcp/src/tools/lookup-semantic-type.tool.ts
|
|
28580
|
-
import { type as
|
|
29643
|
+
import { type as type60 } from "arktype";
|
|
28581
29644
|
|
|
28582
29645
|
// packages/dbx-components-mcp/src/tools/semantic-type-lookup.formatter.ts
|
|
28583
29646
|
function formatSemanticTypeEntry(entry, depth) {
|
|
@@ -28758,13 +29821,13 @@ var DBX_SEMANTIC_TYPE_LOOKUP_TOOL = {
|
|
|
28758
29821
|
required: ["name"]
|
|
28759
29822
|
}
|
|
28760
29823
|
};
|
|
28761
|
-
var LookupSemanticTypeArgsType =
|
|
29824
|
+
var LookupSemanticTypeArgsType = type60({
|
|
28762
29825
|
name: "string",
|
|
28763
29826
|
"depth?": "'brief' | 'full'"
|
|
28764
29827
|
});
|
|
28765
29828
|
function parseLookupArgs2(raw) {
|
|
28766
29829
|
const parsed = LookupSemanticTypeArgsType(raw);
|
|
28767
|
-
if (parsed instanceof
|
|
29830
|
+
if (parsed instanceof type60.errors) {
|
|
28768
29831
|
throw new TypeError(`Invalid arguments: ${parsed.summary}`);
|
|
28769
29832
|
}
|
|
28770
29833
|
const result = {
|
|
@@ -28775,7 +29838,7 @@ function parseLookupArgs2(raw) {
|
|
|
28775
29838
|
}
|
|
28776
29839
|
function createSemanticTypeLookupTool(config) {
|
|
28777
29840
|
const { registry } = config;
|
|
28778
|
-
function
|
|
29841
|
+
function run12(rawArgs) {
|
|
28779
29842
|
let args;
|
|
28780
29843
|
let result;
|
|
28781
29844
|
try {
|
|
@@ -28811,7 +29874,7 @@ function createSemanticTypeLookupTool(config) {
|
|
|
28811
29874
|
}
|
|
28812
29875
|
const tool = {
|
|
28813
29876
|
definition: DBX_SEMANTIC_TYPE_LOOKUP_TOOL,
|
|
28814
|
-
run:
|
|
29877
|
+
run: run12
|
|
28815
29878
|
};
|
|
28816
29879
|
return tool;
|
|
28817
29880
|
}
|
|
@@ -28826,7 +29889,7 @@ function formatNotFound11(name, registry) {
|
|
|
28826
29889
|
}
|
|
28827
29890
|
|
|
28828
29891
|
// packages/dbx-components-mcp/src/tools/search-semantic-type.tool.ts
|
|
28829
|
-
import { type as
|
|
29892
|
+
import { type as type61 } from "arktype";
|
|
28830
29893
|
var DEFAULT_LIMIT4 = 25;
|
|
28831
29894
|
var MAX_LIMIT4 = 100;
|
|
28832
29895
|
var DBX_SEMANTIC_TYPE_SEARCH_TOOL = {
|
|
@@ -28859,7 +29922,7 @@ var DBX_SEMANTIC_TYPE_SEARCH_TOOL = {
|
|
|
28859
29922
|
}
|
|
28860
29923
|
}
|
|
28861
29924
|
};
|
|
28862
|
-
var SearchSemanticTypeArgsType =
|
|
29925
|
+
var SearchSemanticTypeArgsType = type61({
|
|
28863
29926
|
"topic?": "string",
|
|
28864
29927
|
"baseType?": "string",
|
|
28865
29928
|
"package?": "string",
|
|
@@ -28868,7 +29931,7 @@ var SearchSemanticTypeArgsType = type59({
|
|
|
28868
29931
|
});
|
|
28869
29932
|
function parseSearchArgs2(raw) {
|
|
28870
29933
|
const parsed = SearchSemanticTypeArgsType(raw);
|
|
28871
|
-
if (parsed instanceof
|
|
29934
|
+
if (parsed instanceof type61.errors) {
|
|
28872
29935
|
throw new TypeError(`Invalid arguments: ${parsed.summary}`);
|
|
28873
29936
|
}
|
|
28874
29937
|
const rawLimit = parsed.limit ?? DEFAULT_LIMIT4;
|
|
@@ -28894,7 +29957,7 @@ function nonEmpty(value) {
|
|
|
28894
29957
|
}
|
|
28895
29958
|
function createSemanticTypeSearchTool(config) {
|
|
28896
29959
|
const { registry } = config;
|
|
28897
|
-
function
|
|
29960
|
+
function run12(rawArgs) {
|
|
28898
29961
|
let args;
|
|
28899
29962
|
let result;
|
|
28900
29963
|
try {
|
|
@@ -28907,7 +29970,7 @@ function createSemanticTypeSearchTool(config) {
|
|
|
28907
29970
|
if (filterCount === 0) {
|
|
28908
29971
|
result = toolError("At least one filter (topic, baseType, package, query) must be supplied.");
|
|
28909
29972
|
} else {
|
|
28910
|
-
const matches =
|
|
29973
|
+
const matches = applyFilters3(registry, args);
|
|
28911
29974
|
const limited = matches.slice(0, args.limit);
|
|
28912
29975
|
const text = formatSemanticTypeSearchResults({
|
|
28913
29976
|
query: describeFilters(args),
|
|
@@ -28919,11 +29982,11 @@ function createSemanticTypeSearchTool(config) {
|
|
|
28919
29982
|
}
|
|
28920
29983
|
const tool = {
|
|
28921
29984
|
definition: DBX_SEMANTIC_TYPE_SEARCH_TOOL,
|
|
28922
|
-
run:
|
|
29985
|
+
run: run12
|
|
28923
29986
|
};
|
|
28924
29987
|
return tool;
|
|
28925
29988
|
}
|
|
28926
|
-
function
|
|
29989
|
+
function applyFilters3(registry, args) {
|
|
28927
29990
|
let candidates;
|
|
28928
29991
|
if (args.topic !== void 0) {
|
|
28929
29992
|
candidates = registry.findByTopic(args.topic);
|
|
@@ -28997,6 +30060,8 @@ var DBX_TOOLS = [
|
|
|
28997
30060
|
modelFixtureLookupTool,
|
|
28998
30061
|
modelFixtureScaffoldTool,
|
|
28999
30062
|
modelFixtureForwardTool,
|
|
30063
|
+
modelTestTreeTool,
|
|
30064
|
+
modelTestSearchTool,
|
|
29000
30065
|
// storagefile_m (model extension)
|
|
29001
30066
|
storageFileMValidateAppTool,
|
|
29002
30067
|
storageFileMListAppTool,
|