@tekton-ui/mcp-server 0.3.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.
Files changed (179) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +980 -0
  3. package/dist/auth/cache.d.ts +28 -0
  4. package/dist/auth/cache.d.ts.map +1 -0
  5. package/dist/auth/cache.js +48 -0
  6. package/dist/auth/cache.js.map +1 -0
  7. package/dist/auth/guard.d.ts +13 -0
  8. package/dist/auth/guard.d.ts.map +1 -0
  9. package/dist/auth/guard.js +21 -0
  10. package/dist/auth/guard.js.map +1 -0
  11. package/dist/auth/state.d.ts +32 -0
  12. package/dist/auth/state.d.ts.map +1 -0
  13. package/dist/auth/state.js +72 -0
  14. package/dist/auth/state.js.map +1 -0
  15. package/dist/auth/theme-access.d.ts +10 -0
  16. package/dist/auth/theme-access.d.ts.map +1 -0
  17. package/dist/auth/theme-access.js +24 -0
  18. package/dist/auth/theme-access.js.map +1 -0
  19. package/dist/auth/verify.d.ts +44 -0
  20. package/dist/auth/verify.d.ts.map +1 -0
  21. package/dist/auth/verify.js +77 -0
  22. package/dist/auth/verify.js.map +1 -0
  23. package/dist/cli/credentials.d.ts +29 -0
  24. package/dist/cli/credentials.d.ts.map +1 -0
  25. package/dist/cli/credentials.js +66 -0
  26. package/dist/cli/credentials.js.map +1 -0
  27. package/dist/cli/index.d.ts +7 -0
  28. package/dist/cli/index.d.ts.map +1 -0
  29. package/dist/cli/index.js +36 -0
  30. package/dist/cli/index.js.map +1 -0
  31. package/dist/cli/login.d.ts +9 -0
  32. package/dist/cli/login.d.ts.map +1 -0
  33. package/dist/cli/login.js +120 -0
  34. package/dist/cli/login.js.map +1 -0
  35. package/dist/cli/logout.d.ts +9 -0
  36. package/dist/cli/logout.d.ts.map +1 -0
  37. package/dist/cli/logout.js +18 -0
  38. package/dist/cli/logout.js.map +1 -0
  39. package/dist/cli/status.d.ts +9 -0
  40. package/dist/cli/status.d.ts.map +1 -0
  41. package/dist/cli/status.js +31 -0
  42. package/dist/cli/status.js.map +1 -0
  43. package/dist/data/component-registry.d.ts +30 -0
  44. package/dist/data/component-registry.d.ts.map +1 -0
  45. package/dist/data/component-registry.js +320 -0
  46. package/dist/data/component-registry.js.map +1 -0
  47. package/dist/data/examples/screen-examples.d.ts +38 -0
  48. package/dist/data/examples/screen-examples.d.ts.map +1 -0
  49. package/dist/data/examples/screen-examples.js +500 -0
  50. package/dist/data/examples/screen-examples.js.map +1 -0
  51. package/dist/data/hint-generator.d.ts +16 -0
  52. package/dist/data/hint-generator.d.ts.map +1 -0
  53. package/dist/data/hint-generator.js +298 -0
  54. package/dist/data/hint-generator.js.map +1 -0
  55. package/dist/data/recipe-resolver.d.ts +48 -0
  56. package/dist/data/recipe-resolver.d.ts.map +1 -0
  57. package/dist/data/recipe-resolver.js +226 -0
  58. package/dist/data/recipe-resolver.js.map +1 -0
  59. package/dist/data/template-matcher.d.ts +50 -0
  60. package/dist/data/template-matcher.d.ts.map +1 -0
  61. package/dist/data/template-matcher.js +240 -0
  62. package/dist/data/template-matcher.js.map +1 -0
  63. package/dist/generators/core-resolver.d.ts +56 -0
  64. package/dist/generators/core-resolver.d.ts.map +1 -0
  65. package/dist/generators/core-resolver.js +490 -0
  66. package/dist/generators/core-resolver.js.map +1 -0
  67. package/dist/generators/css-generator.d.ts +49 -0
  68. package/dist/generators/css-generator.d.ts.map +1 -0
  69. package/dist/generators/css-generator.js +294 -0
  70. package/dist/generators/css-generator.js.map +1 -0
  71. package/dist/generators/index.d.ts +13 -0
  72. package/dist/generators/index.d.ts.map +1 -0
  73. package/dist/generators/index.js +16 -0
  74. package/dist/generators/index.js.map +1 -0
  75. package/dist/generators/llm-generator.d.ts +96 -0
  76. package/dist/generators/llm-generator.d.ts.map +1 -0
  77. package/dist/generators/llm-generator.js +296 -0
  78. package/dist/generators/llm-generator.js.map +1 -0
  79. package/dist/index.d.ts +3 -0
  80. package/dist/index.d.ts.map +1 -0
  81. package/dist/index.js +818 -0
  82. package/dist/index.js.map +1 -0
  83. package/dist/schemas/mcp-schemas.d.ts +4132 -0
  84. package/dist/schemas/mcp-schemas.d.ts.map +1 -0
  85. package/dist/schemas/mcp-schemas.js +946 -0
  86. package/dist/schemas/mcp-schemas.js.map +1 -0
  87. package/dist/storage/blueprint-storage.d.ts +68 -0
  88. package/dist/storage/blueprint-storage.d.ts.map +1 -0
  89. package/dist/storage/blueprint-storage.js +135 -0
  90. package/dist/storage/blueprint-storage.js.map +1 -0
  91. package/dist/storage/timestamp-manager.d.ts +32 -0
  92. package/dist/storage/timestamp-manager.d.ts.map +1 -0
  93. package/dist/storage/timestamp-manager.js +59 -0
  94. package/dist/storage/timestamp-manager.js.map +1 -0
  95. package/dist/tools/export-screen.d.ts +34 -0
  96. package/dist/tools/export-screen.d.ts.map +1 -0
  97. package/dist/tools/export-screen.js +344 -0
  98. package/dist/tools/export-screen.js.map +1 -0
  99. package/dist/tools/generate-blueprint.d.ts +15 -0
  100. package/dist/tools/generate-blueprint.d.ts.map +1 -0
  101. package/dist/tools/generate-blueprint.js +165 -0
  102. package/dist/tools/generate-blueprint.js.map +1 -0
  103. package/dist/tools/generate-screen.d.ts +13 -0
  104. package/dist/tools/generate-screen.d.ts.map +1 -0
  105. package/dist/tools/generate-screen.js +82 -0
  106. package/dist/tools/generate-screen.js.map +1 -0
  107. package/dist/tools/get-screen-generation-context.d.ts +11 -0
  108. package/dist/tools/get-screen-generation-context.d.ts.map +1 -0
  109. package/dist/tools/get-screen-generation-context.js +316 -0
  110. package/dist/tools/get-screen-generation-context.js.map +1 -0
  111. package/dist/tools/list-components.d.ts +15 -0
  112. package/dist/tools/list-components.d.ts.map +1 -0
  113. package/dist/tools/list-components.js +46 -0
  114. package/dist/tools/list-components.js.map +1 -0
  115. package/dist/tools/list-icon-libraries.d.ts +12 -0
  116. package/dist/tools/list-icon-libraries.d.ts.map +1 -0
  117. package/dist/tools/list-icon-libraries.js +48 -0
  118. package/dist/tools/list-icon-libraries.js.map +1 -0
  119. package/dist/tools/list-screen-templates.d.ts +15 -0
  120. package/dist/tools/list-screen-templates.d.ts.map +1 -0
  121. package/dist/tools/list-screen-templates.js +63 -0
  122. package/dist/tools/list-screen-templates.js.map +1 -0
  123. package/dist/tools/list-themes.d.ts +13 -0
  124. package/dist/tools/list-themes.d.ts.map +1 -0
  125. package/dist/tools/list-themes.js +42 -0
  126. package/dist/tools/list-themes.js.map +1 -0
  127. package/dist/tools/list-tokens.d.ts +13 -0
  128. package/dist/tools/list-tokens.d.ts.map +1 -0
  129. package/dist/tools/list-tokens.js +92 -0
  130. package/dist/tools/list-tokens.js.map +1 -0
  131. package/dist/tools/preview-component.d.ts +18 -0
  132. package/dist/tools/preview-component.d.ts.map +1 -0
  133. package/dist/tools/preview-component.js +178 -0
  134. package/dist/tools/preview-component.js.map +1 -0
  135. package/dist/tools/preview-icon-library.d.ts +13 -0
  136. package/dist/tools/preview-icon-library.d.ts.map +1 -0
  137. package/dist/tools/preview-icon-library.js +63 -0
  138. package/dist/tools/preview-icon-library.js.map +1 -0
  139. package/dist/tools/preview-screen-template.d.ts +18 -0
  140. package/dist/tools/preview-screen-template.d.ts.map +1 -0
  141. package/dist/tools/preview-screen-template.js +101 -0
  142. package/dist/tools/preview-screen-template.js.map +1 -0
  143. package/dist/tools/preview-theme.d.ts +15 -0
  144. package/dist/tools/preview-theme.d.ts.map +1 -0
  145. package/dist/tools/preview-theme.js +71 -0
  146. package/dist/tools/preview-theme.js.map +1 -0
  147. package/dist/tools/validate-environment.d.ts +37 -0
  148. package/dist/tools/validate-environment.d.ts.map +1 -0
  149. package/dist/tools/validate-environment.js +153 -0
  150. package/dist/tools/validate-environment.js.map +1 -0
  151. package/dist/tools/validate-screen-definition.d.ts +10 -0
  152. package/dist/tools/validate-screen-definition.d.ts.map +1 -0
  153. package/dist/tools/validate-screen-definition.js +463 -0
  154. package/dist/tools/validate-screen-definition.js.map +1 -0
  155. package/dist/tools/validate-screen.d.ts +13 -0
  156. package/dist/tools/validate-screen.d.ts.map +1 -0
  157. package/dist/tools/validate-screen.js +106 -0
  158. package/dist/tools/validate-screen.js.map +1 -0
  159. package/dist/utils/dependency-extractor.d.ts +13 -0
  160. package/dist/utils/dependency-extractor.d.ts.map +1 -0
  161. package/dist/utils/dependency-extractor.js +232 -0
  162. package/dist/utils/dependency-extractor.js.map +1 -0
  163. package/dist/utils/error-handler.d.ts +29 -0
  164. package/dist/utils/error-handler.d.ts.map +1 -0
  165. package/dist/utils/error-handler.js +48 -0
  166. package/dist/utils/error-handler.js.map +1 -0
  167. package/dist/utils/logger.d.ts +8 -0
  168. package/dist/utils/logger.d.ts.map +1 -0
  169. package/dist/utils/logger.js +14 -0
  170. package/dist/utils/logger.js.map +1 -0
  171. package/dist/utils/package-json-reader.d.ts +37 -0
  172. package/dist/utils/package-json-reader.d.ts.map +1 -0
  173. package/dist/utils/package-json-reader.js +108 -0
  174. package/dist/utils/package-json-reader.js.map +1 -0
  175. package/dist/utils/tailwind-config-reader.d.ts +23 -0
  176. package/dist/utils/tailwind-config-reader.d.ts.map +1 -0
  177. package/dist/utils/tailwind-config-reader.js +81 -0
  178. package/dist/utils/tailwind-config-reader.js.map +1 -0
  179. package/package.json +72 -0
@@ -0,0 +1,298 @@
1
+ /**
2
+ * Hint Generator Module
3
+ * SPEC-MCP-004 Phase 3.5: Generates contextual hints for coding agents
4
+ *
5
+ * Provides guidance on layout, components, styling, accessibility, and best practices
6
+ */
7
+ /**
8
+ * Keyword patterns for hint generation
9
+ */
10
+ const LAYOUT_KEYWORDS = {
11
+ dashboard: ['dashboard', 'analytics', 'metrics', 'admin', 'kpi', 'stats'],
12
+ form: ['form', 'input', 'submit', 'register', 'signup', 'contact'],
13
+ auth: ['login', 'signin', 'signup', 'auth', 'password', 'verification'],
14
+ table: ['table', 'list', 'data', 'records', 'grid', 'rows'],
15
+ landing: ['landing', 'hero', 'marketing', 'homepage', 'home'],
16
+ profile: ['profile', 'user', 'account', 'settings', 'preferences'],
17
+ };
18
+ const COMPONENT_KEYWORDS = {
19
+ Card: ['card', 'panel', 'container', 'box'],
20
+ Table: ['table', 'data', 'records', 'rows', 'columns'],
21
+ Form: ['form', 'input', 'submit', 'field'],
22
+ Avatar: ['avatar', 'profile', 'user', 'photo'],
23
+ Badge: ['badge', 'tag', 'label', 'status'],
24
+ Button: ['button', 'action', 'cta', 'submit'],
25
+ Modal: ['modal', 'dialog', 'popup', 'overlay'],
26
+ Tabs: ['tabs', 'tabbed', 'sections', 'panels'],
27
+ Chart: ['chart', 'graph', 'visualization', 'analytics'],
28
+ };
29
+ /**
30
+ * Generate layout hints based on description
31
+ */
32
+ function generateLayoutHints(description) {
33
+ const hints = [];
34
+ const lowerDesc = description.toLowerCase();
35
+ // Dashboard layout hints
36
+ if (LAYOUT_KEYWORDS.dashboard.some(kw => lowerDesc.includes(kw))) {
37
+ hints.push({
38
+ category: 'layout',
39
+ priority: 'high',
40
+ message: 'Use shell.web.dashboard with page.dashboard for admin-style layouts with sidebar navigation',
41
+ example: 'shell: "shell.web.dashboard", page: "page.dashboard"',
42
+ });
43
+ hints.push({
44
+ category: 'layout',
45
+ priority: 'medium',
46
+ message: 'Consider section.grid-4 for KPI cards at the top of the dashboard',
47
+ });
48
+ }
49
+ // Form layout hints
50
+ if (LAYOUT_KEYWORDS.form.some(kw => lowerDesc.includes(kw))) {
51
+ hints.push({
52
+ category: 'layout',
53
+ priority: 'high',
54
+ message: 'Use section.container for form content with appropriate max-width',
55
+ example: 'pattern: "section.container"',
56
+ });
57
+ hints.push({
58
+ category: 'best-practice',
59
+ priority: 'medium',
60
+ message: 'Group related form fields together and use clear labels',
61
+ });
62
+ }
63
+ // Auth layout hints
64
+ if (LAYOUT_KEYWORDS.auth.some(kw => lowerDesc.includes(kw))) {
65
+ hints.push({
66
+ category: 'layout',
67
+ priority: 'high',
68
+ message: 'Use shell.web.auth with page.wizard for centered authentication flows',
69
+ example: 'shell: "shell.web.auth", page: "page.wizard"',
70
+ });
71
+ hints.push({
72
+ category: 'layout',
73
+ priority: 'medium',
74
+ message: 'Use section.centered to center the authentication card vertically and horizontally',
75
+ });
76
+ }
77
+ // Table layout hints
78
+ if (LAYOUT_KEYWORDS.table.some(kw => lowerDesc.includes(kw))) {
79
+ hints.push({
80
+ category: 'layout',
81
+ priority: 'high',
82
+ message: 'Use shell.web.app with page.resource for data table views',
83
+ example: 'shell: "shell.web.app", page: "page.resource"',
84
+ });
85
+ hints.push({
86
+ category: 'component',
87
+ priority: 'medium',
88
+ message: 'Include a toolbar section with search and filter controls above the table',
89
+ });
90
+ }
91
+ // Landing page hints
92
+ if (LAYOUT_KEYWORDS.landing.some(kw => lowerDesc.includes(kw))) {
93
+ hints.push({
94
+ category: 'layout',
95
+ priority: 'high',
96
+ message: 'Use shell.web.marketing with page.detail for full-width marketing layouts',
97
+ example: 'shell: "shell.web.marketing", page: "page.detail"',
98
+ });
99
+ }
100
+ return hints;
101
+ }
102
+ /**
103
+ * Generate component hints based on description
104
+ */
105
+ function generateComponentHints(description) {
106
+ const hints = [];
107
+ const lowerDesc = description.toLowerCase();
108
+ const detectedComponents = [];
109
+ // Detect components from description
110
+ for (const [component, keywords] of Object.entries(COMPONENT_KEYWORDS)) {
111
+ if (keywords.some(kw => lowerDesc.includes(kw))) {
112
+ detectedComponents.push(component);
113
+ }
114
+ }
115
+ // Add hints for detected components
116
+ if (detectedComponents.includes('Card')) {
117
+ hints.push({
118
+ category: 'component',
119
+ priority: 'medium',
120
+ message: 'Use Card with variant="elevated" for prominent content or variant="outline" for subtle containers',
121
+ example: '{ type: "Card", props: { variant: "elevated" } }',
122
+ });
123
+ }
124
+ if (detectedComponents.includes('Table')) {
125
+ hints.push({
126
+ category: 'component',
127
+ priority: 'high',
128
+ message: 'Define table columns with key, header, and sortable properties for interactive tables',
129
+ example: 'columns: [{ key: "name", header: "Name", sortable: true }]',
130
+ });
131
+ hints.push({
132
+ category: 'accessibility',
133
+ priority: 'high',
134
+ message: 'Ensure tables have proper column headers for screen reader accessibility',
135
+ });
136
+ }
137
+ if (detectedComponents.includes('Form')) {
138
+ hints.push({
139
+ category: 'component',
140
+ priority: 'high',
141
+ message: 'Use Input components with proper label and type props for form fields',
142
+ example: '{ type: "Input", props: { type: "email", label: "Email", required: true } }',
143
+ });
144
+ hints.push({
145
+ category: 'accessibility',
146
+ priority: 'high',
147
+ message: 'All form inputs must have associated labels for accessibility',
148
+ });
149
+ }
150
+ if (detectedComponents.includes('Avatar')) {
151
+ hints.push({
152
+ category: 'component',
153
+ priority: 'medium',
154
+ message: 'Always provide alt text for Avatar components',
155
+ example: '{ type: "Avatar", props: { src: "...", alt: "User Name", size: "lg" } }',
156
+ });
157
+ }
158
+ if (detectedComponents.includes('Button')) {
159
+ hints.push({
160
+ category: 'component',
161
+ priority: 'medium',
162
+ message: 'Use variant="primary" for main actions and variant="secondary" or variant="outline" for secondary actions',
163
+ });
164
+ }
165
+ if (detectedComponents.includes('Modal')) {
166
+ hints.push({
167
+ category: 'accessibility',
168
+ priority: 'high',
169
+ message: 'Modals should trap focus and be dismissible with Escape key',
170
+ });
171
+ }
172
+ return hints;
173
+ }
174
+ /**
175
+ * Generate styling hints based on theme
176
+ */
177
+ function generateStylingHints(themeId) {
178
+ const hints = [];
179
+ hints.push({
180
+ category: 'styling',
181
+ priority: 'medium',
182
+ message: 'Use theme recipes for consistent component styling instead of custom classes',
183
+ example: 'Recipe classes are automatically applied based on component variant props',
184
+ });
185
+ if (themeId) {
186
+ hints.push({
187
+ category: 'styling',
188
+ priority: 'low',
189
+ message: `Theme "${themeId}" is selected - component variants will use this theme's recipe classes`,
190
+ });
191
+ }
192
+ else {
193
+ hints.push({
194
+ category: 'styling',
195
+ priority: 'medium',
196
+ message: 'Consider specifying a themeId to enable automatic recipe class application',
197
+ });
198
+ }
199
+ return hints;
200
+ }
201
+ /**
202
+ * Generate accessibility hints
203
+ */
204
+ function generateAccessibilityHints(description) {
205
+ const hints = [];
206
+ const lowerDesc = description.toLowerCase();
207
+ // Always include basic accessibility hints
208
+ hints.push({
209
+ category: 'accessibility',
210
+ priority: 'high',
211
+ message: 'Use semantic HTML elements (Heading for titles, List for lists) for proper document structure',
212
+ });
213
+ // Add context-specific accessibility hints
214
+ if (lowerDesc.includes('image') || lowerDesc.includes('photo') || lowerDesc.includes('avatar')) {
215
+ hints.push({
216
+ category: 'accessibility',
217
+ priority: 'high',
218
+ message: 'All images must have descriptive alt text',
219
+ example: 'props: { alt: "Description of the image content" }',
220
+ });
221
+ }
222
+ if (lowerDesc.includes('form') || lowerDesc.includes('input')) {
223
+ hints.push({
224
+ category: 'accessibility',
225
+ priority: 'high',
226
+ message: 'Form inputs should have clear error messages and validation feedback',
227
+ });
228
+ }
229
+ if (lowerDesc.includes('button') || lowerDesc.includes('click')) {
230
+ hints.push({
231
+ category: 'accessibility',
232
+ priority: 'medium',
233
+ message: 'Interactive elements should have clear focus states and be keyboard accessible',
234
+ });
235
+ }
236
+ return hints;
237
+ }
238
+ /**
239
+ * Generate best practice hints
240
+ */
241
+ function generateBestPracticeHints(description) {
242
+ const hints = [];
243
+ const lowerDesc = description.toLowerCase();
244
+ hints.push({
245
+ category: 'best-practice',
246
+ priority: 'medium',
247
+ message: 'Use meaningful section IDs that describe the content purpose',
248
+ example: 'id: "user-profile-header" instead of id: "section-1"',
249
+ });
250
+ hints.push({
251
+ category: 'best-practice',
252
+ priority: 'low',
253
+ message: 'Assign sections to appropriate slots (header, main, sidebar, footer) for proper layout positioning',
254
+ });
255
+ // Add context-specific best practices
256
+ if (lowerDesc.includes('list') || lowerDesc.includes('grid') || lowerDesc.includes('cards')) {
257
+ hints.push({
258
+ category: 'best-practice',
259
+ priority: 'medium',
260
+ message: 'For repeating content, define one component structure as a template pattern',
261
+ });
262
+ }
263
+ if (lowerDesc.includes('navigation') || lowerDesc.includes('menu')) {
264
+ hints.push({
265
+ category: 'best-practice',
266
+ priority: 'medium',
267
+ message: 'Use consistent navigation patterns across related screens',
268
+ });
269
+ }
270
+ return hints;
271
+ }
272
+ /**
273
+ * Generate all contextual hints based on description and theme
274
+ */
275
+ export function generateHints(description, themeId) {
276
+ const allHints = [
277
+ ...generateLayoutHints(description),
278
+ ...generateComponentHints(description),
279
+ ...generateStylingHints(themeId),
280
+ ...generateAccessibilityHints(description),
281
+ ...generateBestPracticeHints(description),
282
+ ];
283
+ // Sort by priority (high first, then medium, then low)
284
+ const priorityOrder = { high: 0, medium: 1, low: 2 };
285
+ allHints.sort((a, b) => priorityOrder[a.priority] - priorityOrder[b.priority]);
286
+ // Remove duplicates and limit total hints
287
+ const uniqueHints = allHints.filter((hint, index, self) => index === self.findIndex(h => h.message === hint.message));
288
+ // Return top 10 hints to avoid overwhelming the agent
289
+ return uniqueHints.slice(0, 10);
290
+ }
291
+ /**
292
+ * Generate hints for a specific category
293
+ */
294
+ export function generateCategoryHints(description, category, themeId) {
295
+ const allHints = generateHints(description, themeId);
296
+ return allHints.filter(hint => hint.category === category);
297
+ }
298
+ //# sourceMappingURL=hint-generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hint-generator.js","sourceRoot":"","sources":["../../src/data/hint-generator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Recipe Resolver Module
3
+ * SPEC-MCP-004 Phase 4: Theme Recipes Auto-Application
4
+ *
5
+ * 테마에서 레시피를 조회하고 컴포넌트 className에 적용합니다.
6
+ */
7
+ import type { ComponentNode } from '@tekton-ui/core';
8
+ /**
9
+ * 테마에서 레시피 조회
10
+ *
11
+ * @param themeId - 테마 ID
12
+ * @param componentType - 컴포넌트 타입 (Card, Button, Text 등)
13
+ * @param variant - 컴포넌트 variant (glass, primary, hero 등)
14
+ * @returns 레시피 className 문자열 또는 undefined
15
+ */
16
+ export declare function resolveRecipe(themeId: string, componentType: string, variant?: string): string | undefined;
17
+ /**
18
+ * ComponentNode에 레시피 적용 (재귀)
19
+ *
20
+ * @param node - 컴포넌트 노드
21
+ * @param themeId - 테마 ID
22
+ * @returns 레시피가 적용된 노드 (원본 수정하지 않음)
23
+ */
24
+ export declare function applyRecipeToNode(node: ComponentNode, themeId: string): ComponentNode;
25
+ /**
26
+ * Blueprint의 모든 컴포넌트에 레시피 적용
27
+ *
28
+ * @param components - 컴포넌트 배열
29
+ * @param themeId - 테마 ID
30
+ * @returns 레시피가 적용된 컴포넌트 배열
31
+ */
32
+ export declare function applyRecipesToBlueprint(components: ComponentNode[], themeId: string): ComponentNode[];
33
+ /**
34
+ * 레시피 통계 계산
35
+ *
36
+ * @param components - 컴포넌트 배열
37
+ * @param themeId - 테마 ID
38
+ * @returns 적용된 레시피 개수
39
+ */
40
+ export declare function countAppliedRecipes(components: ComponentNode[], themeId: string): number;
41
+ /**
42
+ * 사용 가능한 모든 레시피 조회 (디버깅용)
43
+ *
44
+ * @param themeId - 테마 ID
45
+ * @returns 레시피 경로 → className 매핑
46
+ */
47
+ export declare function getAllRecipes(themeId: string): Record<string, string>;
48
+ //# sourceMappingURL=recipe-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recipe-resolver.d.ts","sourceRoot":"","sources":["../../src/data/recipe-resolver.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAwDrD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,aAAa,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE,MAAM,GACf,MAAM,GAAG,SAAS,CA2CpB;AAyBD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,GAAG,aAAa,CA+BrF;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,aAAa,EAAE,EAC3B,OAAO,EAAE,MAAM,GACd,aAAa,EAAE,CAEjB;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,aAAa,EAAE,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAuBxF;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAiCrE"}
@@ -0,0 +1,226 @@
1
+ /**
2
+ * Recipe Resolver Module
3
+ * SPEC-MCP-004 Phase 4: Theme Recipes Auto-Application
4
+ *
5
+ * 테마에서 레시피를 조회하고 컴포넌트 className에 적용합니다.
6
+ */
7
+ import { loadTheme } from '@tekton-ui/core';
8
+ /**
9
+ * 컴포넌트 타입과 variant에서 레시피 경로 생성
10
+ *
11
+ * 규칙:
12
+ * - card + glass → recipes.card.glass
13
+ * - button + primary → recipes.button.primary
14
+ * - Text + hero → recipes.typography.hero (특수 케이스)
15
+ * - Badge + neutral → recipes.badge.neutral
16
+ */
17
+ function getRecipePath(componentType, variant) {
18
+ if (!variant) {
19
+ return [`recipes.${componentType.toLowerCase()}.default`];
20
+ }
21
+ const type = componentType.toLowerCase();
22
+ const paths = [];
23
+ // Typography 특수 처리 (Text → recipes.typography)
24
+ if (type === 'text' || type === 'heading') {
25
+ paths.push(`recipes.typography.${variant}`);
26
+ }
27
+ // 일반 컴포넌트
28
+ else {
29
+ paths.push(`recipes.${type}.${variant}`);
30
+ }
31
+ // Fallback: variant 없이 기본 레시피
32
+ paths.push(`recipes.${type}.default`);
33
+ paths.push(`recipes.${type}`);
34
+ return paths;
35
+ }
36
+ /**
37
+ * 중첩 객체에서 경로로 값 조회
38
+ *
39
+ * @example
40
+ * getNestedValue({ a: { b: { c: 'value' } } }, 'a.b.c') → 'value'
41
+ */
42
+ function getNestedValue(obj, path) {
43
+ const keys = path.split('.');
44
+ let current = obj;
45
+ for (const key of keys) {
46
+ if (current && typeof current === 'object' && key in current) {
47
+ current = current[key];
48
+ }
49
+ else {
50
+ return undefined;
51
+ }
52
+ }
53
+ return current;
54
+ }
55
+ /**
56
+ * 테마에서 레시피 조회
57
+ *
58
+ * @param themeId - 테마 ID
59
+ * @param componentType - 컴포넌트 타입 (Card, Button, Text 등)
60
+ * @param variant - 컴포넌트 variant (glass, primary, hero 등)
61
+ * @returns 레시피 className 문자열 또는 undefined
62
+ */
63
+ export function resolveRecipe(themeId, componentType, variant) {
64
+ try {
65
+ const theme = loadTheme(themeId);
66
+ if (!theme) {
67
+ return undefined;
68
+ }
69
+ // recipes는 tokens 내부가 아니라 최상위 필드
70
+ const recipes = theme.recipes || theme.tokens?.recipes;
71
+ if (!recipes) {
72
+ return undefined;
73
+ }
74
+ const paths = getRecipePath(componentType, variant);
75
+ // 우선순위대로 레시피 경로 시도
76
+ for (const path of paths) {
77
+ const recipe = getNestedValue(recipes, path.replace('recipes.', ''));
78
+ // 레시피가 문자열이면 반환
79
+ if (typeof recipe === 'string') {
80
+ return recipe;
81
+ }
82
+ // 레시피가 객체면 'base' 또는 'default' 키 확인
83
+ if (recipe && typeof recipe === 'object') {
84
+ if (typeof recipe.base === 'string') {
85
+ return recipe.base;
86
+ }
87
+ if (typeof recipe.default === 'string') {
88
+ return recipe.default;
89
+ }
90
+ }
91
+ }
92
+ return undefined;
93
+ }
94
+ catch (error) {
95
+ console.warn(`[Recipe Resolver] Failed to resolve recipe for ${componentType}.${variant}:`, error);
96
+ return undefined;
97
+ }
98
+ }
99
+ /**
100
+ * ComponentNode의 props.className에 레시피 병합
101
+ *
102
+ * 기존 className이 있으면 레시피를 앞에 추가합니다.
103
+ *
104
+ * @example
105
+ * mergeClassName("p-4", "bg-white border") → "bg-white border p-4"
106
+ */
107
+ function mergeClassName(existing, recipe) {
108
+ if (!existing) {
109
+ return recipe;
110
+ }
111
+ // 중복 제거를 위해 Set 사용
112
+ const existingClasses = existing.split(/\s+/).filter(Boolean);
113
+ const recipeClasses = recipe.split(/\s+/).filter(Boolean);
114
+ // 레시피 클래스를 앞에, 기존 클래스를 뒤에 (specificity 우선순위)
115
+ const merged = [...new Set([...recipeClasses, ...existingClasses])];
116
+ return merged.join(' ');
117
+ }
118
+ /**
119
+ * ComponentNode에 레시피 적용 (재귀)
120
+ *
121
+ * @param node - 컴포넌트 노드
122
+ * @param themeId - 테마 ID
123
+ * @returns 레시피가 적용된 노드 (원본 수정하지 않음)
124
+ */
125
+ export function applyRecipeToNode(node, themeId) {
126
+ const result = { ...node };
127
+ // variant가 있으면 레시피 조회
128
+ if (result.type) {
129
+ const variant = result.props?.variant;
130
+ const recipe = resolveRecipe(themeId, result.type, variant);
131
+ if (recipe) {
132
+ // props 복사 (immutability 보장)
133
+ const currentProps = result.props || {};
134
+ const existingClassName = currentProps.className;
135
+ result.props = {
136
+ ...currentProps,
137
+ className: mergeClassName(existingClassName, recipe),
138
+ };
139
+ }
140
+ }
141
+ // children 재귀 처리
142
+ if (Array.isArray(result.children)) {
143
+ result.children = result.children.map(child => {
144
+ if (typeof child === 'object' && child !== null && 'type' in child) {
145
+ return applyRecipeToNode(child, themeId);
146
+ }
147
+ return child;
148
+ });
149
+ }
150
+ return result;
151
+ }
152
+ /**
153
+ * Blueprint의 모든 컴포넌트에 레시피 적용
154
+ *
155
+ * @param components - 컴포넌트 배열
156
+ * @param themeId - 테마 ID
157
+ * @returns 레시피가 적용된 컴포넌트 배열
158
+ */
159
+ export function applyRecipesToBlueprint(components, themeId) {
160
+ return components.map(component => applyRecipeToNode(component, themeId));
161
+ }
162
+ /**
163
+ * 레시피 통계 계산
164
+ *
165
+ * @param components - 컴포넌트 배열
166
+ * @param themeId - 테마 ID
167
+ * @returns 적용된 레시피 개수
168
+ */
169
+ export function countAppliedRecipes(components, themeId) {
170
+ let count = 0;
171
+ function traverse(node) {
172
+ const variant = node.props?.variant;
173
+ if (node.type && resolveRecipe(themeId, node.type, variant)) {
174
+ count++;
175
+ }
176
+ if (Array.isArray(node.children)) {
177
+ for (const child of node.children) {
178
+ if (typeof child === 'object' && child !== null && 'type' in child) {
179
+ traverse(child);
180
+ }
181
+ }
182
+ }
183
+ }
184
+ for (const component of components) {
185
+ traverse(component);
186
+ }
187
+ return count;
188
+ }
189
+ /**
190
+ * 사용 가능한 모든 레시피 조회 (디버깅용)
191
+ *
192
+ * @param themeId - 테마 ID
193
+ * @returns 레시피 경로 → className 매핑
194
+ */
195
+ export function getAllRecipes(themeId) {
196
+ try {
197
+ const theme = loadTheme(themeId);
198
+ if (!theme) {
199
+ return {};
200
+ }
201
+ // recipes는 tokens 내부가 아니라 최상위 필드
202
+ const recipes = theme.recipes || theme.tokens?.recipes;
203
+ if (!recipes) {
204
+ return {};
205
+ }
206
+ const result = {};
207
+ function traverse(obj, path = 'recipes') {
208
+ for (const [key, value] of Object.entries(obj)) {
209
+ const currentPath = path ? `${path}.${key}` : key;
210
+ if (typeof value === 'string') {
211
+ result[currentPath] = value;
212
+ }
213
+ else if (typeof value === 'object' && value !== null) {
214
+ traverse(value, currentPath);
215
+ }
216
+ }
217
+ }
218
+ traverse(recipes);
219
+ return result;
220
+ }
221
+ catch (error) {
222
+ console.warn(`[Recipe Resolver] Failed to get all recipes for ${themeId}:`, error);
223
+ return {};
224
+ }
225
+ }
226
+ //# sourceMappingURL=recipe-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recipe-resolver.js","sourceRoot":"","sources":["../../src/data/recipe-resolver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Template Matcher Module
3
+ * SPEC-MCP-004 Phase 3: Blueprint Generator Enhancement
4
+ *
5
+ * 자연어 설명에서 최적의 Screen Template을 매칭합니다.
6
+ */
7
+ /**
8
+ * 템플릿 카테고리별 Shell/Page 토큰 권장 매핑
9
+ */
10
+ export declare const TEMPLATE_LAYOUT_RECOMMENDATIONS: Record<string, {
11
+ shell: string;
12
+ page: string;
13
+ description: string;
14
+ }>;
15
+ /**
16
+ * 템플릿 매칭 결과
17
+ */
18
+ export interface TemplateMatchResult {
19
+ templateId: string;
20
+ templateName: string;
21
+ category: string;
22
+ confidence: number;
23
+ matchedKeywords: string[];
24
+ layoutRecommendation: {
25
+ shell: string;
26
+ page: string;
27
+ description: string;
28
+ };
29
+ }
30
+ /**
31
+ * 자연어 설명에서 최적의 템플릿 매칭
32
+ *
33
+ * @param description - 사용자의 자연어 화면 설명
34
+ * @param topN - 반환할 상위 N개 결과 (기본: 3)
35
+ * @returns 매칭된 템플릿 결과 배열 (신뢰도순 정렬)
36
+ */
37
+ export declare function matchTemplates(description: string, topN?: number): TemplateMatchResult[];
38
+ /**
39
+ * 최적 단일 템플릿 반환
40
+ */
41
+ export declare function getBestMatch(description: string): TemplateMatchResult | null;
42
+ /**
43
+ * 템플릿 ID로 레이아웃 권장사항 조회
44
+ */
45
+ export declare function getLayoutRecommendation(templateId: string): (typeof TEMPLATE_LAYOUT_RECOMMENDATIONS)[string] | null;
46
+ /**
47
+ * 모든 템플릿 키워드 목록 조회 (디버깅용)
48
+ */
49
+ export declare function getAllKeywordMappings(): Record<string, string[]>;
50
+ //# sourceMappingURL=template-matcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-matcher.d.ts","sourceRoot":"","sources":["../../src/data/template-matcher.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAyIH;;GAEG;AACH,eAAO,MAAM,+BAA+B,EAAE,MAAM,CAClD,MAAM,EACN;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CA2BrD,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,oBAAoB,EAAE;QACpB,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;CACH;AAwBD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,GAAE,MAAU,GAAG,mBAAmB,EAAE,CA6B3F;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,mBAAmB,GAAG,IAAI,CAI5E;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,MAAM,GACjB,CAAC,OAAO,+BAA+B,CAAC,CAAC,MAAM,CAAC,GAAG,IAAI,CAMzD;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAEhE"}