@treeui/mcp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +56 -0
- package/dist/chunk-SNF26WKA.js +6653 -0
- package/dist/cli.cjs +6692 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +32 -0
- package/dist/index.cjs +7043 -0
- package/dist/index.d.cts +160 -0
- package/dist/index.d.ts +160 -0
- package/dist/index.js +372 -0
- package/package.json +33 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
|
+
|
|
3
|
+
interface TreeuiCatalogField {
|
|
4
|
+
name: string;
|
|
5
|
+
type?: string;
|
|
6
|
+
required?: boolean;
|
|
7
|
+
default?: string;
|
|
8
|
+
values?: string[];
|
|
9
|
+
description?: string;
|
|
10
|
+
note?: string;
|
|
11
|
+
payload?: string;
|
|
12
|
+
}
|
|
13
|
+
interface TreeuiAlternative {
|
|
14
|
+
component: string;
|
|
15
|
+
when: string;
|
|
16
|
+
}
|
|
17
|
+
interface TreeuiSelectionProfile {
|
|
18
|
+
keywords: string[];
|
|
19
|
+
useWhen: string[];
|
|
20
|
+
avoidWhen: string[];
|
|
21
|
+
alternatives: TreeuiAlternative[];
|
|
22
|
+
}
|
|
23
|
+
interface TreeuiComponentSetup {
|
|
24
|
+
required: string[];
|
|
25
|
+
notes: string[];
|
|
26
|
+
}
|
|
27
|
+
interface TreeuiComponentEntry {
|
|
28
|
+
name: string;
|
|
29
|
+
legacyAlias?: string;
|
|
30
|
+
aliases: string[];
|
|
31
|
+
package: string;
|
|
32
|
+
kind?: string;
|
|
33
|
+
category?: string;
|
|
34
|
+
status?: string;
|
|
35
|
+
description?: string;
|
|
36
|
+
purpose?: string;
|
|
37
|
+
sourceFile?: string;
|
|
38
|
+
storyFile?: string;
|
|
39
|
+
storyTitle?: string;
|
|
40
|
+
manifestFile?: string;
|
|
41
|
+
props: TreeuiCatalogField[];
|
|
42
|
+
events: TreeuiCatalogField[];
|
|
43
|
+
slots: TreeuiCatalogField[];
|
|
44
|
+
a11y: string[];
|
|
45
|
+
behavior: string[];
|
|
46
|
+
selection: TreeuiSelectionProfile;
|
|
47
|
+
setup: TreeuiComponentSetup;
|
|
48
|
+
recipes: string[];
|
|
49
|
+
}
|
|
50
|
+
interface TreeuiDecisionGuideOption {
|
|
51
|
+
use: string;
|
|
52
|
+
when: string[];
|
|
53
|
+
notes: string[];
|
|
54
|
+
}
|
|
55
|
+
interface TreeuiDecisionGuide {
|
|
56
|
+
id: string;
|
|
57
|
+
question: string;
|
|
58
|
+
options: TreeuiDecisionGuideOption[];
|
|
59
|
+
}
|
|
60
|
+
interface TreeuiRecipe {
|
|
61
|
+
id: string;
|
|
62
|
+
name: string;
|
|
63
|
+
useWhen: string[];
|
|
64
|
+
compose: string[];
|
|
65
|
+
notes: string[];
|
|
66
|
+
}
|
|
67
|
+
interface TreeuiSetupEntry {
|
|
68
|
+
install: {
|
|
69
|
+
packageManagerExamples: Record<string, string>;
|
|
70
|
+
requiredImports: string[];
|
|
71
|
+
};
|
|
72
|
+
vueSetup: {
|
|
73
|
+
pluginInstall: {
|
|
74
|
+
import: string;
|
|
75
|
+
usage: string;
|
|
76
|
+
};
|
|
77
|
+
individualImports: {
|
|
78
|
+
import: string;
|
|
79
|
+
};
|
|
80
|
+
guidance: string[];
|
|
81
|
+
};
|
|
82
|
+
globalRules: string[];
|
|
83
|
+
componentSetup: Record<string, TreeuiComponentSetup>;
|
|
84
|
+
appPatterns: {
|
|
85
|
+
providers: Array<{
|
|
86
|
+
component: string;
|
|
87
|
+
placement: string;
|
|
88
|
+
reason: string;
|
|
89
|
+
}>;
|
|
90
|
+
commonCompositions: string[];
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
interface TreeuiCatalog {
|
|
94
|
+
generatedAt: string;
|
|
95
|
+
packageName: string;
|
|
96
|
+
packageVersion: string;
|
|
97
|
+
decisionGuides: TreeuiDecisionGuide[];
|
|
98
|
+
recipes: TreeuiRecipe[];
|
|
99
|
+
setup: TreeuiSetupEntry;
|
|
100
|
+
components: TreeuiComponentEntry[];
|
|
101
|
+
}
|
|
102
|
+
interface TreeuiSearchResult {
|
|
103
|
+
component: TreeuiComponentEntry;
|
|
104
|
+
score: number;
|
|
105
|
+
reasons: string[];
|
|
106
|
+
}
|
|
107
|
+
interface TreeuiRecipeSearchResult {
|
|
108
|
+
recipe: TreeuiRecipe;
|
|
109
|
+
score: number;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
declare const catalog: TreeuiCatalog;
|
|
113
|
+
declare const findComponent: (name: string) => TreeuiComponentEntry | undefined;
|
|
114
|
+
declare const searchComponents: (query: string, limit?: number) => TreeuiSearchResult[];
|
|
115
|
+
declare const recommendComponents: (task: string, limit?: number) => TreeuiSearchResult[];
|
|
116
|
+
declare const searchRecipes: (query: string, limit?: number) => TreeuiRecipeSearchResult[];
|
|
117
|
+
declare const formatComponentSummary: (component: TreeuiComponentEntry) => string;
|
|
118
|
+
declare const formatSearchResults: (results: TreeuiSearchResult[]) => string;
|
|
119
|
+
declare const formatRecipeResults: (results: TreeuiRecipeSearchResult[]) => string;
|
|
120
|
+
declare const formatSetupGuide: (componentName?: string) => string;
|
|
121
|
+
|
|
122
|
+
declare const buildCatalogFromRepo: (repoRoot: string) => TreeuiCatalog;
|
|
123
|
+
declare const getRepoRootFromPackageRoot: (packageRoot: string) => string;
|
|
124
|
+
|
|
125
|
+
declare const createTreeuiMcpServer: () => Server<{
|
|
126
|
+
method: string;
|
|
127
|
+
params?: {
|
|
128
|
+
[x: string]: unknown;
|
|
129
|
+
_meta?: {
|
|
130
|
+
[x: string]: unknown;
|
|
131
|
+
progressToken?: string | number | undefined;
|
|
132
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
133
|
+
taskId: string;
|
|
134
|
+
} | undefined;
|
|
135
|
+
} | undefined;
|
|
136
|
+
} | undefined;
|
|
137
|
+
}, {
|
|
138
|
+
method: string;
|
|
139
|
+
params?: {
|
|
140
|
+
[x: string]: unknown;
|
|
141
|
+
_meta?: {
|
|
142
|
+
[x: string]: unknown;
|
|
143
|
+
progressToken?: string | number | undefined;
|
|
144
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
145
|
+
taskId: string;
|
|
146
|
+
} | undefined;
|
|
147
|
+
} | undefined;
|
|
148
|
+
} | undefined;
|
|
149
|
+
}, {
|
|
150
|
+
[x: string]: unknown;
|
|
151
|
+
_meta?: {
|
|
152
|
+
[x: string]: unknown;
|
|
153
|
+
progressToken?: string | number | undefined;
|
|
154
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
155
|
+
taskId: string;
|
|
156
|
+
} | undefined;
|
|
157
|
+
} | undefined;
|
|
158
|
+
}>;
|
|
159
|
+
|
|
160
|
+
export { type TreeuiCatalog, type TreeuiCatalogField, type TreeuiComponentEntry, type TreeuiDecisionGuide, type TreeuiRecipe, type TreeuiSearchResult, type TreeuiSetupEntry, buildCatalogFromRepo, catalog, createTreeuiMcpServer, findComponent, formatComponentSummary, formatRecipeResults, formatSearchResults, formatSetupGuide, getRepoRootFromPackageRoot, recommendComponents, searchComponents, searchRecipes };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
|
+
|
|
3
|
+
interface TreeuiCatalogField {
|
|
4
|
+
name: string;
|
|
5
|
+
type?: string;
|
|
6
|
+
required?: boolean;
|
|
7
|
+
default?: string;
|
|
8
|
+
values?: string[];
|
|
9
|
+
description?: string;
|
|
10
|
+
note?: string;
|
|
11
|
+
payload?: string;
|
|
12
|
+
}
|
|
13
|
+
interface TreeuiAlternative {
|
|
14
|
+
component: string;
|
|
15
|
+
when: string;
|
|
16
|
+
}
|
|
17
|
+
interface TreeuiSelectionProfile {
|
|
18
|
+
keywords: string[];
|
|
19
|
+
useWhen: string[];
|
|
20
|
+
avoidWhen: string[];
|
|
21
|
+
alternatives: TreeuiAlternative[];
|
|
22
|
+
}
|
|
23
|
+
interface TreeuiComponentSetup {
|
|
24
|
+
required: string[];
|
|
25
|
+
notes: string[];
|
|
26
|
+
}
|
|
27
|
+
interface TreeuiComponentEntry {
|
|
28
|
+
name: string;
|
|
29
|
+
legacyAlias?: string;
|
|
30
|
+
aliases: string[];
|
|
31
|
+
package: string;
|
|
32
|
+
kind?: string;
|
|
33
|
+
category?: string;
|
|
34
|
+
status?: string;
|
|
35
|
+
description?: string;
|
|
36
|
+
purpose?: string;
|
|
37
|
+
sourceFile?: string;
|
|
38
|
+
storyFile?: string;
|
|
39
|
+
storyTitle?: string;
|
|
40
|
+
manifestFile?: string;
|
|
41
|
+
props: TreeuiCatalogField[];
|
|
42
|
+
events: TreeuiCatalogField[];
|
|
43
|
+
slots: TreeuiCatalogField[];
|
|
44
|
+
a11y: string[];
|
|
45
|
+
behavior: string[];
|
|
46
|
+
selection: TreeuiSelectionProfile;
|
|
47
|
+
setup: TreeuiComponentSetup;
|
|
48
|
+
recipes: string[];
|
|
49
|
+
}
|
|
50
|
+
interface TreeuiDecisionGuideOption {
|
|
51
|
+
use: string;
|
|
52
|
+
when: string[];
|
|
53
|
+
notes: string[];
|
|
54
|
+
}
|
|
55
|
+
interface TreeuiDecisionGuide {
|
|
56
|
+
id: string;
|
|
57
|
+
question: string;
|
|
58
|
+
options: TreeuiDecisionGuideOption[];
|
|
59
|
+
}
|
|
60
|
+
interface TreeuiRecipe {
|
|
61
|
+
id: string;
|
|
62
|
+
name: string;
|
|
63
|
+
useWhen: string[];
|
|
64
|
+
compose: string[];
|
|
65
|
+
notes: string[];
|
|
66
|
+
}
|
|
67
|
+
interface TreeuiSetupEntry {
|
|
68
|
+
install: {
|
|
69
|
+
packageManagerExamples: Record<string, string>;
|
|
70
|
+
requiredImports: string[];
|
|
71
|
+
};
|
|
72
|
+
vueSetup: {
|
|
73
|
+
pluginInstall: {
|
|
74
|
+
import: string;
|
|
75
|
+
usage: string;
|
|
76
|
+
};
|
|
77
|
+
individualImports: {
|
|
78
|
+
import: string;
|
|
79
|
+
};
|
|
80
|
+
guidance: string[];
|
|
81
|
+
};
|
|
82
|
+
globalRules: string[];
|
|
83
|
+
componentSetup: Record<string, TreeuiComponentSetup>;
|
|
84
|
+
appPatterns: {
|
|
85
|
+
providers: Array<{
|
|
86
|
+
component: string;
|
|
87
|
+
placement: string;
|
|
88
|
+
reason: string;
|
|
89
|
+
}>;
|
|
90
|
+
commonCompositions: string[];
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
interface TreeuiCatalog {
|
|
94
|
+
generatedAt: string;
|
|
95
|
+
packageName: string;
|
|
96
|
+
packageVersion: string;
|
|
97
|
+
decisionGuides: TreeuiDecisionGuide[];
|
|
98
|
+
recipes: TreeuiRecipe[];
|
|
99
|
+
setup: TreeuiSetupEntry;
|
|
100
|
+
components: TreeuiComponentEntry[];
|
|
101
|
+
}
|
|
102
|
+
interface TreeuiSearchResult {
|
|
103
|
+
component: TreeuiComponentEntry;
|
|
104
|
+
score: number;
|
|
105
|
+
reasons: string[];
|
|
106
|
+
}
|
|
107
|
+
interface TreeuiRecipeSearchResult {
|
|
108
|
+
recipe: TreeuiRecipe;
|
|
109
|
+
score: number;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
declare const catalog: TreeuiCatalog;
|
|
113
|
+
declare const findComponent: (name: string) => TreeuiComponentEntry | undefined;
|
|
114
|
+
declare const searchComponents: (query: string, limit?: number) => TreeuiSearchResult[];
|
|
115
|
+
declare const recommendComponents: (task: string, limit?: number) => TreeuiSearchResult[];
|
|
116
|
+
declare const searchRecipes: (query: string, limit?: number) => TreeuiRecipeSearchResult[];
|
|
117
|
+
declare const formatComponentSummary: (component: TreeuiComponentEntry) => string;
|
|
118
|
+
declare const formatSearchResults: (results: TreeuiSearchResult[]) => string;
|
|
119
|
+
declare const formatRecipeResults: (results: TreeuiRecipeSearchResult[]) => string;
|
|
120
|
+
declare const formatSetupGuide: (componentName?: string) => string;
|
|
121
|
+
|
|
122
|
+
declare const buildCatalogFromRepo: (repoRoot: string) => TreeuiCatalog;
|
|
123
|
+
declare const getRepoRootFromPackageRoot: (packageRoot: string) => string;
|
|
124
|
+
|
|
125
|
+
declare const createTreeuiMcpServer: () => Server<{
|
|
126
|
+
method: string;
|
|
127
|
+
params?: {
|
|
128
|
+
[x: string]: unknown;
|
|
129
|
+
_meta?: {
|
|
130
|
+
[x: string]: unknown;
|
|
131
|
+
progressToken?: string | number | undefined;
|
|
132
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
133
|
+
taskId: string;
|
|
134
|
+
} | undefined;
|
|
135
|
+
} | undefined;
|
|
136
|
+
} | undefined;
|
|
137
|
+
}, {
|
|
138
|
+
method: string;
|
|
139
|
+
params?: {
|
|
140
|
+
[x: string]: unknown;
|
|
141
|
+
_meta?: {
|
|
142
|
+
[x: string]: unknown;
|
|
143
|
+
progressToken?: string | number | undefined;
|
|
144
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
145
|
+
taskId: string;
|
|
146
|
+
} | undefined;
|
|
147
|
+
} | undefined;
|
|
148
|
+
} | undefined;
|
|
149
|
+
}, {
|
|
150
|
+
[x: string]: unknown;
|
|
151
|
+
_meta?: {
|
|
152
|
+
[x: string]: unknown;
|
|
153
|
+
progressToken?: string | number | undefined;
|
|
154
|
+
"io.modelcontextprotocol/related-task"?: {
|
|
155
|
+
taskId: string;
|
|
156
|
+
} | undefined;
|
|
157
|
+
} | undefined;
|
|
158
|
+
}>;
|
|
159
|
+
|
|
160
|
+
export { type TreeuiCatalog, type TreeuiCatalogField, type TreeuiComponentEntry, type TreeuiDecisionGuide, type TreeuiRecipe, type TreeuiSearchResult, type TreeuiSetupEntry, buildCatalogFromRepo, catalog, createTreeuiMcpServer, findComponent, formatComponentSummary, formatRecipeResults, formatSearchResults, formatSetupGuide, getRepoRootFromPackageRoot, recommendComponents, searchComponents, searchRecipes };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
import {
|
|
2
|
+
catalog,
|
|
3
|
+
createTreeuiMcpServer,
|
|
4
|
+
findComponent,
|
|
5
|
+
formatComponentSummary,
|
|
6
|
+
formatRecipeResults,
|
|
7
|
+
formatSearchResults,
|
|
8
|
+
formatSetupGuide,
|
|
9
|
+
recommendComponents,
|
|
10
|
+
searchComponents,
|
|
11
|
+
searchRecipes
|
|
12
|
+
} from "./chunk-SNF26WKA.js";
|
|
13
|
+
|
|
14
|
+
// src/catalog-source.ts
|
|
15
|
+
import fs from "fs";
|
|
16
|
+
import path from "path";
|
|
17
|
+
import { parseAllDocuments } from "yaml";
|
|
18
|
+
var readText = (filePath) => fs.readFileSync(filePath, "utf8");
|
|
19
|
+
var normalizeWhitespace = (value) => value.replace(/\s+/g, " ").trim();
|
|
20
|
+
var stringifyValue = (value) => {
|
|
21
|
+
if (value === void 0 || value === null) {
|
|
22
|
+
return void 0;
|
|
23
|
+
}
|
|
24
|
+
if (typeof value === "string") {
|
|
25
|
+
return value;
|
|
26
|
+
}
|
|
27
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
28
|
+
return String(value);
|
|
29
|
+
}
|
|
30
|
+
return JSON.stringify(value);
|
|
31
|
+
};
|
|
32
|
+
var normalizeStringList = (value) => {
|
|
33
|
+
if (value === void 0 || value === null) {
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
if (Array.isArray(value)) {
|
|
37
|
+
return value.flatMap((item) => normalizeStringList(item));
|
|
38
|
+
}
|
|
39
|
+
if (typeof value === "string") {
|
|
40
|
+
return [value];
|
|
41
|
+
}
|
|
42
|
+
if (typeof value === "object") {
|
|
43
|
+
return Object.entries(value).map(
|
|
44
|
+
([key, entryValue]) => normalizeWhitespace(`${key}: ${stringifyValue(entryValue) ?? ""}`)
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
return [String(value)];
|
|
48
|
+
};
|
|
49
|
+
var normalizeComponentName = (rawName) => {
|
|
50
|
+
if (typeof rawName !== "string" || !rawName.trim()) {
|
|
51
|
+
return void 0;
|
|
52
|
+
}
|
|
53
|
+
const value = rawName.trim();
|
|
54
|
+
if (value.startsWith("T")) {
|
|
55
|
+
return value;
|
|
56
|
+
}
|
|
57
|
+
if (value.startsWith("Tree")) {
|
|
58
|
+
return `T${value.slice(4)}`;
|
|
59
|
+
}
|
|
60
|
+
return `T${value}`;
|
|
61
|
+
};
|
|
62
|
+
var normalizeSourceFile = (rawValue) => {
|
|
63
|
+
if (typeof rawValue !== "string" || !rawValue.trim()) {
|
|
64
|
+
return void 0;
|
|
65
|
+
}
|
|
66
|
+
if (rawValue.startsWith("packages/")) {
|
|
67
|
+
return rawValue;
|
|
68
|
+
}
|
|
69
|
+
if (rawValue.endsWith(".vue")) {
|
|
70
|
+
return `packages/vue/src/components/${rawValue}`;
|
|
71
|
+
}
|
|
72
|
+
return rawValue;
|
|
73
|
+
};
|
|
74
|
+
var normalizeFieldMap = (value) => {
|
|
75
|
+
if (!value) {
|
|
76
|
+
return [];
|
|
77
|
+
}
|
|
78
|
+
if (Array.isArray(value)) {
|
|
79
|
+
return value.map(
|
|
80
|
+
(entry) => typeof entry === "string" ? { name: entry } : {
|
|
81
|
+
name: stringifyValue(entry.name) ?? "unnamed",
|
|
82
|
+
type: stringifyValue(entry.type),
|
|
83
|
+
description: stringifyValue(entry.description)
|
|
84
|
+
}
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
if (typeof value !== "object") {
|
|
88
|
+
return [];
|
|
89
|
+
}
|
|
90
|
+
return Object.entries(value).map(([name, entry]) => {
|
|
91
|
+
if (typeof entry === "string") {
|
|
92
|
+
return { name, description: entry };
|
|
93
|
+
}
|
|
94
|
+
if (Array.isArray(entry)) {
|
|
95
|
+
return { name, values: entry.map((item) => String(item)) };
|
|
96
|
+
}
|
|
97
|
+
const record = entry ?? {};
|
|
98
|
+
const values = Array.isArray(record.values) ? record.values.map((item) => String(item)) : void 0;
|
|
99
|
+
return {
|
|
100
|
+
name,
|
|
101
|
+
type: stringifyValue(record.type),
|
|
102
|
+
required: typeof record.required === "boolean" ? record.required : void 0,
|
|
103
|
+
default: stringifyValue(record.default),
|
|
104
|
+
values,
|
|
105
|
+
description: stringifyValue(record.description),
|
|
106
|
+
note: stringifyValue(record.note),
|
|
107
|
+
payload: stringifyValue(record.payload)
|
|
108
|
+
};
|
|
109
|
+
});
|
|
110
|
+
};
|
|
111
|
+
var normalizeEventList = (value) => {
|
|
112
|
+
if (!value) {
|
|
113
|
+
return [];
|
|
114
|
+
}
|
|
115
|
+
if (Array.isArray(value)) {
|
|
116
|
+
return value.map(
|
|
117
|
+
(entry) => typeof entry === "string" ? { name: entry } : {
|
|
118
|
+
name: stringifyValue(entry.name) ?? "unnamed",
|
|
119
|
+
description: stringifyValue(entry.description),
|
|
120
|
+
payload: stringifyValue(entry.payload)
|
|
121
|
+
}
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
if (typeof value !== "object") {
|
|
125
|
+
return [];
|
|
126
|
+
}
|
|
127
|
+
return Object.entries(value).map(([name, entry]) => {
|
|
128
|
+
if (typeof entry === "string") {
|
|
129
|
+
return { name, description: entry };
|
|
130
|
+
}
|
|
131
|
+
const record = entry ?? {};
|
|
132
|
+
return {
|
|
133
|
+
name,
|
|
134
|
+
description: stringifyValue(record.description),
|
|
135
|
+
payload: stringifyValue(record.payload)
|
|
136
|
+
};
|
|
137
|
+
});
|
|
138
|
+
};
|
|
139
|
+
var normalizeSlotList = (value) => {
|
|
140
|
+
if (!value) {
|
|
141
|
+
return [];
|
|
142
|
+
}
|
|
143
|
+
if (Array.isArray(value)) {
|
|
144
|
+
return value.map(
|
|
145
|
+
(entry) => typeof entry === "string" ? { name: entry } : {
|
|
146
|
+
name: stringifyValue(entry.name) ?? "unnamed",
|
|
147
|
+
description: stringifyValue(entry.description),
|
|
148
|
+
note: stringifyValue(entry.bindings)
|
|
149
|
+
}
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
if (typeof value !== "object") {
|
|
153
|
+
return [];
|
|
154
|
+
}
|
|
155
|
+
return Object.entries(value).map(([name, entry]) => {
|
|
156
|
+
if (typeof entry === "string") {
|
|
157
|
+
return { name, description: entry };
|
|
158
|
+
}
|
|
159
|
+
const record = entry ?? {};
|
|
160
|
+
return {
|
|
161
|
+
name,
|
|
162
|
+
description: stringifyValue(record.description),
|
|
163
|
+
note: stringifyValue(record.bindings)
|
|
164
|
+
};
|
|
165
|
+
});
|
|
166
|
+
};
|
|
167
|
+
var normalizeSelectionProfile = (value) => {
|
|
168
|
+
const record = value ?? {};
|
|
169
|
+
const alternatives = Array.isArray(record.alternatives) ? record.alternatives.map((entry) => {
|
|
170
|
+
const alternative = entry;
|
|
171
|
+
const component = stringifyValue(alternative.component);
|
|
172
|
+
const when = stringifyValue(alternative.when);
|
|
173
|
+
if (!component || !when) {
|
|
174
|
+
return void 0;
|
|
175
|
+
}
|
|
176
|
+
return { component, when };
|
|
177
|
+
}).filter((entry) => Boolean(entry)) : [];
|
|
178
|
+
return {
|
|
179
|
+
keywords: normalizeStringList(record.keywords),
|
|
180
|
+
useWhen: normalizeStringList(record.use_when),
|
|
181
|
+
avoidWhen: normalizeStringList(record.avoid_when),
|
|
182
|
+
alternatives
|
|
183
|
+
};
|
|
184
|
+
};
|
|
185
|
+
var normalizeSetupEntry = (value) => {
|
|
186
|
+
const record = value ?? {};
|
|
187
|
+
return {
|
|
188
|
+
required: normalizeStringList(record.required),
|
|
189
|
+
notes: normalizeStringList(record.notes)
|
|
190
|
+
};
|
|
191
|
+
};
|
|
192
|
+
var normalizeDecisionGuides = (value) => {
|
|
193
|
+
if (!Array.isArray(value)) {
|
|
194
|
+
return [];
|
|
195
|
+
}
|
|
196
|
+
return value.map((guide) => {
|
|
197
|
+
const record = guide;
|
|
198
|
+
const options = Array.isArray(record.options) ? record.options.map((option) => {
|
|
199
|
+
const optionRecord = option;
|
|
200
|
+
return {
|
|
201
|
+
use: String(optionRecord.use),
|
|
202
|
+
when: normalizeStringList(optionRecord.when),
|
|
203
|
+
notes: normalizeStringList(optionRecord.notes)
|
|
204
|
+
};
|
|
205
|
+
}) : [];
|
|
206
|
+
return {
|
|
207
|
+
id: String(record.id),
|
|
208
|
+
question: String(record.question),
|
|
209
|
+
options
|
|
210
|
+
};
|
|
211
|
+
});
|
|
212
|
+
};
|
|
213
|
+
var normalizeRecipes = (value) => {
|
|
214
|
+
if (!Array.isArray(value)) {
|
|
215
|
+
return [];
|
|
216
|
+
}
|
|
217
|
+
return value.map((recipe) => {
|
|
218
|
+
const record = recipe;
|
|
219
|
+
return {
|
|
220
|
+
id: String(record.id),
|
|
221
|
+
name: String(record.name),
|
|
222
|
+
useWhen: normalizeStringList(record.use_when),
|
|
223
|
+
compose: normalizeStringList(record.compose),
|
|
224
|
+
notes: normalizeStringList(record.notes)
|
|
225
|
+
};
|
|
226
|
+
});
|
|
227
|
+
};
|
|
228
|
+
var loadYamlDocuments = (filePath) => parseAllDocuments(readText(filePath)).map((document) => document.toJSON()).filter((document) => Boolean(document));
|
|
229
|
+
var buildStoryIndex = (repoRoot) => {
|
|
230
|
+
const storiesDir = path.join(repoRoot, "apps/docs/src/stories");
|
|
231
|
+
const index = /* @__PURE__ */ new Map();
|
|
232
|
+
for (const fileName of fs.readdirSync(storiesDir)) {
|
|
233
|
+
if (!fileName.endsWith(".stories.ts")) {
|
|
234
|
+
continue;
|
|
235
|
+
}
|
|
236
|
+
const filePath = path.join(storiesDir, fileName);
|
|
237
|
+
const source = readText(filePath);
|
|
238
|
+
const componentMatch = source.match(/component:\s*(T[A-Za-z0-9]+)/);
|
|
239
|
+
if (!componentMatch) {
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
const componentName = componentMatch[1];
|
|
243
|
+
const titleMatch = source.match(/title:\s*'([^']+)'/);
|
|
244
|
+
const storyTitle = titleMatch?.[1];
|
|
245
|
+
const titleParts = storyTitle?.split("/") ?? [];
|
|
246
|
+
const category = titleParts.length > 2 ? titleParts.slice(1, -1).join(" / ") : titleParts[1];
|
|
247
|
+
index.set(componentName, {
|
|
248
|
+
storyFile: path.relative(repoRoot, filePath),
|
|
249
|
+
storyTitle,
|
|
250
|
+
category
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
return index;
|
|
254
|
+
};
|
|
255
|
+
var buildCatalogFromRepo = (repoRoot) => {
|
|
256
|
+
const docsDir = path.join(repoRoot, "docs/ai");
|
|
257
|
+
const componentsDir = path.join(docsDir, "COMPONENTS");
|
|
258
|
+
const storyIndex = buildStoryIndex(repoRoot);
|
|
259
|
+
const vuePackage = JSON.parse(
|
|
260
|
+
readText(path.join(repoRoot, "packages/vue/package.json"))
|
|
261
|
+
);
|
|
262
|
+
const selectionDoc = loadYamlDocuments(path.join(docsDir, "SELECTION.yaml"))[0] ?? {};
|
|
263
|
+
const setupDoc = loadYamlDocuments(path.join(docsDir, "SETUP.yaml"))[0] ?? {};
|
|
264
|
+
const recipesDoc = loadYamlDocuments(path.join(docsDir, "RECIPES.yaml"))[0] ?? {};
|
|
265
|
+
const contractsDoc = loadYamlDocuments(path.join(docsDir, "CONTRACTS.yaml"))[0] ?? {};
|
|
266
|
+
const componentProfiles = selectionDoc.component_profiles ?? {};
|
|
267
|
+
const componentSetup = setupDoc.component_setup ?? {};
|
|
268
|
+
const aliasMap = contractsDoc.compatibility_aliases ?? {};
|
|
269
|
+
const recipes = normalizeRecipes(recipesDoc.recipes);
|
|
270
|
+
const components = fs.readdirSync(componentsDir).filter((fileName) => fileName.endsWith(".yaml")).flatMap((fileName) => {
|
|
271
|
+
const filePath = path.join(componentsDir, fileName);
|
|
272
|
+
return loadYamlDocuments(filePath).flatMap((document) => {
|
|
273
|
+
const name = normalizeComponentName(document.name ?? document.component);
|
|
274
|
+
if (!name) {
|
|
275
|
+
return [];
|
|
276
|
+
}
|
|
277
|
+
const story = storyIndex.get(name);
|
|
278
|
+
const selection = normalizeSelectionProfile(componentProfiles[name]);
|
|
279
|
+
const setup2 = normalizeSetupEntry(componentSetup[name]);
|
|
280
|
+
const aliases = Array.from(
|
|
281
|
+
new Set(
|
|
282
|
+
[
|
|
283
|
+
...normalizeStringList(document.aliases),
|
|
284
|
+
aliasMap[name],
|
|
285
|
+
name.startsWith("T") ? `Tree${name.slice(1)}` : void 0
|
|
286
|
+
].filter((value) => Boolean(value))
|
|
287
|
+
)
|
|
288
|
+
);
|
|
289
|
+
const componentRecipes = recipes.filter((recipe) => recipe.compose.includes(name)).map((recipe) => recipe.id);
|
|
290
|
+
const entry = {
|
|
291
|
+
name,
|
|
292
|
+
legacyAlias: aliasMap[name] ?? aliases.find((alias) => alias.startsWith("Tree")),
|
|
293
|
+
aliases,
|
|
294
|
+
package: stringifyValue(document.package) ?? vuePackage.name,
|
|
295
|
+
kind: stringifyValue(document.kind),
|
|
296
|
+
category: story?.category,
|
|
297
|
+
status: stringifyValue(document.status),
|
|
298
|
+
description: stringifyValue(document.description),
|
|
299
|
+
purpose: stringifyValue(document.purpose),
|
|
300
|
+
sourceFile: normalizeSourceFile(document.source_file ?? document.source ?? document.provider_source_file),
|
|
301
|
+
storyFile: story?.storyFile,
|
|
302
|
+
storyTitle: story?.storyTitle,
|
|
303
|
+
manifestFile: path.relative(repoRoot, filePath),
|
|
304
|
+
props: normalizeFieldMap(document.props),
|
|
305
|
+
events: normalizeEventList(document.events ?? document.toast_events),
|
|
306
|
+
slots: normalizeSlotList(document.slots),
|
|
307
|
+
a11y: normalizeStringList(document.a11y ?? document.accessibility),
|
|
308
|
+
behavior: normalizeStringList(document.behavior),
|
|
309
|
+
selection,
|
|
310
|
+
setup: setup2,
|
|
311
|
+
recipes: componentRecipes
|
|
312
|
+
};
|
|
313
|
+
return [entry];
|
|
314
|
+
});
|
|
315
|
+
}).sort((left, right) => left.name.localeCompare(right.name));
|
|
316
|
+
const setup = {
|
|
317
|
+
install: {
|
|
318
|
+
packageManagerExamples: (setupDoc.install ?? {}).package_manager_examples,
|
|
319
|
+
requiredImports: normalizeStringList(
|
|
320
|
+
(setupDoc.install ?? {}).required_imports
|
|
321
|
+
)
|
|
322
|
+
},
|
|
323
|
+
vueSetup: {
|
|
324
|
+
pluginInstall: {
|
|
325
|
+
import: String((setupDoc.vue_setup ?? {}).plugin_install.import),
|
|
326
|
+
usage: String((setupDoc.vue_setup ?? {}).plugin_install.usage)
|
|
327
|
+
},
|
|
328
|
+
individualImports: {
|
|
329
|
+
import: String((setupDoc.vue_setup ?? {}).individual_imports.import)
|
|
330
|
+
},
|
|
331
|
+
guidance: normalizeStringList((setupDoc.vue_setup ?? {}).guidance)
|
|
332
|
+
},
|
|
333
|
+
globalRules: normalizeStringList(setupDoc.global_rules),
|
|
334
|
+
componentSetup: Object.fromEntries(
|
|
335
|
+
Object.keys(componentSetup).map((name) => [name, normalizeSetupEntry(componentSetup[name])])
|
|
336
|
+
),
|
|
337
|
+
appPatterns: {
|
|
338
|
+
providers: Array.isArray((setupDoc.app_patterns ?? {}).providers) ? (setupDoc.app_patterns ?? {}).providers.map((entry) => ({
|
|
339
|
+
component: String(entry.component),
|
|
340
|
+
placement: String(entry.placement),
|
|
341
|
+
reason: String(entry.reason)
|
|
342
|
+
})) : [],
|
|
343
|
+
commonCompositions: normalizeStringList(
|
|
344
|
+
(setupDoc.app_patterns ?? {}).common_compositions
|
|
345
|
+
)
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
return {
|
|
349
|
+
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
350
|
+
packageName: vuePackage.name,
|
|
351
|
+
packageVersion: vuePackage.version,
|
|
352
|
+
decisionGuides: normalizeDecisionGuides(selectionDoc.decision_guides),
|
|
353
|
+
recipes,
|
|
354
|
+
setup,
|
|
355
|
+
components
|
|
356
|
+
};
|
|
357
|
+
};
|
|
358
|
+
var getRepoRootFromPackageRoot = (packageRoot) => path.resolve(packageRoot, "../..");
|
|
359
|
+
export {
|
|
360
|
+
buildCatalogFromRepo,
|
|
361
|
+
catalog,
|
|
362
|
+
createTreeuiMcpServer,
|
|
363
|
+
findComponent,
|
|
364
|
+
formatComponentSummary,
|
|
365
|
+
formatRecipeResults,
|
|
366
|
+
formatSearchResults,
|
|
367
|
+
formatSetupGuide,
|
|
368
|
+
getRepoRootFromPackageRoot,
|
|
369
|
+
recommendComponents,
|
|
370
|
+
searchComponents,
|
|
371
|
+
searchRecipes
|
|
372
|
+
};
|