@vertesia/fusion-ux 1.0.0-dev.20260128.144200

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 (91) hide show
  1. package/LICENSE +13 -0
  2. package/README.md +160 -0
  3. package/lib/esm/fusion-fragment/ChartRenderer.js +70 -0
  4. package/lib/esm/fusion-fragment/ChartRenderer.js.map +1 -0
  5. package/lib/esm/fusion-fragment/FieldRenderer.js +153 -0
  6. package/lib/esm/fusion-fragment/FieldRenderer.js.map +1 -0
  7. package/lib/esm/fusion-fragment/FusionFragmentContext.js +53 -0
  8. package/lib/esm/fusion-fragment/FusionFragmentContext.js.map +1 -0
  9. package/lib/esm/fusion-fragment/FusionFragmentHandler.js +233 -0
  10. package/lib/esm/fusion-fragment/FusionFragmentHandler.js.map +1 -0
  11. package/lib/esm/fusion-fragment/FusionFragmentRenderer.js +108 -0
  12. package/lib/esm/fusion-fragment/FusionFragmentRenderer.js.map +1 -0
  13. package/lib/esm/fusion-fragment/SectionRenderer.js +134 -0
  14. package/lib/esm/fusion-fragment/SectionRenderer.js.map +1 -0
  15. package/lib/esm/fusion-fragment/TableRenderer.js +137 -0
  16. package/lib/esm/fusion-fragment/TableRenderer.js.map +1 -0
  17. package/lib/esm/fusion-fragment/index.js +11 -0
  18. package/lib/esm/fusion-fragment/index.js.map +1 -0
  19. package/lib/esm/index.js +44 -0
  20. package/lib/esm/index.js.map +1 -0
  21. package/lib/esm/render/index.js +12 -0
  22. package/lib/esm/render/index.js.map +1 -0
  23. package/lib/esm/render/textPreview.js +194 -0
  24. package/lib/esm/render/textPreview.js.map +1 -0
  25. package/lib/esm/types.js +8 -0
  26. package/lib/esm/types.js.map +1 -0
  27. package/lib/esm/validation/formatErrors.js +105 -0
  28. package/lib/esm/validation/formatErrors.js.map +1 -0
  29. package/lib/esm/validation/fuzzyMatch.js +87 -0
  30. package/lib/esm/validation/fuzzyMatch.js.map +1 -0
  31. package/lib/esm/validation/index.js +8 -0
  32. package/lib/esm/validation/index.js.map +1 -0
  33. package/lib/esm/validation/schemas.js +166 -0
  34. package/lib/esm/validation/schemas.js.map +1 -0
  35. package/lib/esm/validation/validateTemplate.js +247 -0
  36. package/lib/esm/validation/validateTemplate.js.map +1 -0
  37. package/lib/tsconfig.tsbuildinfo +1 -0
  38. package/lib/types/fusion-fragment/ChartRenderer.d.ts +23 -0
  39. package/lib/types/fusion-fragment/ChartRenderer.d.ts.map +1 -0
  40. package/lib/types/fusion-fragment/FieldRenderer.d.ts +12 -0
  41. package/lib/types/fusion-fragment/FieldRenderer.d.ts.map +1 -0
  42. package/lib/types/fusion-fragment/FusionFragmentContext.d.ts +48 -0
  43. package/lib/types/fusion-fragment/FusionFragmentContext.d.ts.map +1 -0
  44. package/lib/types/fusion-fragment/FusionFragmentHandler.d.ts +38 -0
  45. package/lib/types/fusion-fragment/FusionFragmentHandler.d.ts.map +1 -0
  46. package/lib/types/fusion-fragment/FusionFragmentRenderer.d.ts +32 -0
  47. package/lib/types/fusion-fragment/FusionFragmentRenderer.d.ts.map +1 -0
  48. package/lib/types/fusion-fragment/SectionRenderer.d.ts +12 -0
  49. package/lib/types/fusion-fragment/SectionRenderer.d.ts.map +1 -0
  50. package/lib/types/fusion-fragment/TableRenderer.d.ts +15 -0
  51. package/lib/types/fusion-fragment/TableRenderer.d.ts.map +1 -0
  52. package/lib/types/fusion-fragment/index.d.ts +11 -0
  53. package/lib/types/fusion-fragment/index.d.ts.map +1 -0
  54. package/lib/types/index.d.ts +42 -0
  55. package/lib/types/index.d.ts.map +1 -0
  56. package/lib/types/render/index.d.ts +12 -0
  57. package/lib/types/render/index.d.ts.map +1 -0
  58. package/lib/types/render/textPreview.d.ts +20 -0
  59. package/lib/types/render/textPreview.d.ts.map +1 -0
  60. package/lib/types/types.d.ts +262 -0
  61. package/lib/types/types.d.ts.map +1 -0
  62. package/lib/types/validation/formatErrors.d.ts +35 -0
  63. package/lib/types/validation/formatErrors.d.ts.map +1 -0
  64. package/lib/types/validation/fuzzyMatch.d.ts +25 -0
  65. package/lib/types/validation/fuzzyMatch.d.ts.map +1 -0
  66. package/lib/types/validation/index.d.ts +8 -0
  67. package/lib/types/validation/index.d.ts.map +1 -0
  68. package/lib/types/validation/schemas.d.ts +67 -0
  69. package/lib/types/validation/schemas.d.ts.map +1 -0
  70. package/lib/types/validation/validateTemplate.d.ts +22 -0
  71. package/lib/types/validation/validateTemplate.d.ts.map +1 -0
  72. package/lib/vertesia-fusion-ux.js +2 -0
  73. package/lib/vertesia-fusion-ux.js.map +1 -0
  74. package/package.json +68 -0
  75. package/src/fusion-fragment/ChartRenderer.tsx +136 -0
  76. package/src/fusion-fragment/FieldRenderer.tsx +199 -0
  77. package/src/fusion-fragment/FusionFragmentContext.tsx +92 -0
  78. package/src/fusion-fragment/FusionFragmentHandler.tsx +313 -0
  79. package/src/fusion-fragment/FusionFragmentRenderer.tsx +156 -0
  80. package/src/fusion-fragment/SectionRenderer.tsx +196 -0
  81. package/src/fusion-fragment/TableRenderer.tsx +204 -0
  82. package/src/fusion-fragment/index.ts +20 -0
  83. package/src/index.ts +89 -0
  84. package/src/render/index.ts +16 -0
  85. package/src/render/textPreview.ts +231 -0
  86. package/src/types.ts +278 -0
  87. package/src/validation/formatErrors.ts +128 -0
  88. package/src/validation/fuzzyMatch.ts +109 -0
  89. package/src/validation/index.ts +8 -0
  90. package/src/validation/schemas.ts +175 -0
  91. package/src/validation/validateTemplate.ts +282 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/fusion-fragment/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,aAAa,EAA2B,MAAM,oBAAoB,CAAC;AAC5E,OAAO,EAAE,aAAa,EAA2B,MAAM,oBAAoB,CAAC;AAC5E,OAAO,EACL,sBAAsB,EACtB,wBAAwB,EACxB,4BAA4B,GAE7B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,qBAAqB,EACrB,qCAAqC,GAEtC,MAAM,4BAA4B,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * @vertesia/fusion-ux
3
+ *
4
+ * Dynamic model-generated UI components for Vertesia.
5
+ *
6
+ * This package provides components that render model-generated templates
7
+ * with actual data. The model generates structure (template), the system
8
+ * provides values (data).
9
+ *
10
+ * @example
11
+ * ```tsx
12
+ * import {
13
+ * FusionFragmentRenderer,
14
+ * FusionFragmentProvider,
15
+ * FusionFragmentHandler,
16
+ * } from '@vertesia/fusion-ux';
17
+ *
18
+ * // Option 1: Direct rendering with template and data
19
+ * <FusionFragmentRenderer
20
+ * template={templateFromModel}
21
+ * data={actualData}
22
+ * onUpdate={handleUpdate}
23
+ * />
24
+ *
25
+ * // Option 2: Context-based rendering (for markdown code blocks)
26
+ * <FusionFragmentProvider data={fund.parameters} onUpdate={handleUpdate}>
27
+ * <MarkdownRenderer content={agentResponse} />
28
+ * </FusionFragmentProvider>
29
+ *
30
+ * // Option 3: Code block handler for markdown renderers
31
+ * const codeBlockRenderers = {
32
+ * 'fusion-fragment': ({ code }) => <FusionFragmentHandler code={code} />
33
+ * };
34
+ * ```
35
+ *
36
+ * @packageDocumentation
37
+ */
38
+ // Components
39
+ export { FusionFragmentRenderer, SectionRenderer, FieldRenderer, FusionFragmentProvider, FusionFragmentHandler, useFusionFragmentContext, useFusionFragmentContextSafe, createFusionFragmentCodeBlockRenderer, } from './fusion-fragment/index.js';
40
+ // Validation utilities
41
+ export { validateTemplate, parseAndValidateTemplate, FragmentTemplateSchema, SectionTemplateSchema, FieldTemplateSchema, findClosestKey, findSimilarKeys, formatValidationErrors, formatValidationSuccess, formatAvailableKeys, } from './validation/index.js';
42
+ // Render utilities (text preview only - image rendering is in apps/tools)
43
+ export { generateTextPreview, generateSampleData, generateCompactPreview, } from './render/index.js';
44
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAmBH,aAAa;AACb,OAAO,EACL,sBAAsB,EACtB,eAAe,EACf,aAAa,EACb,sBAAsB,EACtB,qBAAqB,EACrB,wBAAwB,EACxB,4BAA4B,EAC5B,qCAAqC,GAGtC,MAAM,4BAA4B,CAAC;AAEpC,uBAAuB;AACvB,OAAO,EACL,gBAAgB,EAChB,wBAAwB,EACxB,sBAAsB,EACtB,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,sBAAsB,EACtB,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,uBAAuB,CAAC;AAE/B,0EAA0E;AAC1E,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Render module exports
3
+ *
4
+ * NOTE: All image rendering (renderToBuffer, renderToBase64, renderToDataUrl, renderToImage)
5
+ * has been moved to apps/tools/src/tools/fusion-ux/_shared/renderFragment.ts
6
+ * because it requires Node.js-only modules (@napi-rs/canvas) or DOM APIs that
7
+ * cannot be bundled for browser use.
8
+ *
9
+ * This module only exports text-based preview utilities that work in any environment.
10
+ */
11
+ export { generateTextPreview, generateSampleData, generateCompactPreview, } from './textPreview.js';
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/render/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,194 @@
1
+ /**
2
+ * Text preview generation for non-vision models
3
+ * Generates a text description of what the fragment will look like
4
+ */
5
+ /**
6
+ * Generate sample data for preview rendering
7
+ * Creates placeholder values based on field definitions
8
+ */
9
+ export function generateSampleData(template, dataKeys) {
10
+ const data = {};
11
+ // Add provided data keys with placeholder values
12
+ for (const key of dataKeys) {
13
+ data[key] = `<${key}>`;
14
+ }
15
+ // Override with more specific placeholders based on field format
16
+ for (const section of template.sections) {
17
+ if (section.fields) {
18
+ for (const field of section.fields) {
19
+ if (field.key in data) {
20
+ data[field.key] = getSampleValue(field);
21
+ }
22
+ }
23
+ }
24
+ }
25
+ return data;
26
+ }
27
+ /**
28
+ * Get a sample value for a field based on its format
29
+ */
30
+ function getSampleValue(field) {
31
+ switch (field.format) {
32
+ case 'number':
33
+ return 1234;
34
+ case 'currency':
35
+ return 1000000;
36
+ case 'percent':
37
+ return 25;
38
+ case 'date':
39
+ return new Date().toISOString().split('T')[0];
40
+ case 'boolean':
41
+ return true;
42
+ case 'text':
43
+ default:
44
+ return `Sample ${field.label}`;
45
+ }
46
+ }
47
+ /**
48
+ * Generate a text description of the template for preview
49
+ * Used for non-vision models
50
+ */
51
+ export function generateTextPreview(template, dataKeys) {
52
+ const lines = [];
53
+ lines.push('Template structure preview:');
54
+ lines.push('');
55
+ if (template.title) {
56
+ lines.push(`## ${template.title}`);
57
+ lines.push('');
58
+ }
59
+ for (const section of template.sections) {
60
+ const layout = section.layout || 'grid-3';
61
+ lines.push(`### ${section.title}`);
62
+ if (layout === 'table') {
63
+ lines.push(`Layout: table`);
64
+ if (section.dataKey) {
65
+ lines.push(`Data key: \`${section.dataKey}\``);
66
+ }
67
+ lines.push('');
68
+ if (section.columns) {
69
+ lines.push('Columns:');
70
+ for (const col of section.columns) {
71
+ let colLine = `- **${col.header}** \u2192 \`${col.key}\``;
72
+ if (col.format && col.format !== 'text') {
73
+ colLine += ` (${col.format})`;
74
+ }
75
+ lines.push(colLine);
76
+ }
77
+ }
78
+ }
79
+ else if (layout === 'chart') {
80
+ lines.push(`Layout: chart`);
81
+ if (section.chart) {
82
+ const chart = section.chart;
83
+ if (chart.title) {
84
+ lines.push(`Chart title: ${chart.title}`);
85
+ }
86
+ if (chart.description) {
87
+ lines.push(`Description: ${chart.description}`);
88
+ }
89
+ const markType = chart.spec.mark
90
+ ? (typeof chart.spec.mark === 'string' ? chart.spec.mark : chart.spec.mark.type || 'unknown')
91
+ : 'composite';
92
+ lines.push(`Chart type: ${markType}`);
93
+ if (chart.dataKey) {
94
+ lines.push(`Data key: \`${chart.dataKey}\``);
95
+ if (!dataKeys.includes(chart.dataKey)) {
96
+ lines.push('\u26a0\ufe0f **dataKey not found in data**');
97
+ }
98
+ }
99
+ else if (chart.spec.data?.values) {
100
+ lines.push(`Inline data: ${chart.spec.data.values.length} points`);
101
+ }
102
+ if (chart.height) {
103
+ lines.push(`Height: ${chart.height}px`);
104
+ }
105
+ }
106
+ lines.push('');
107
+ }
108
+ else {
109
+ const layoutDesc = layout === 'list' ? 'vertical list' : `${layout.split('-')[1]}-column grid`;
110
+ lines.push(`Layout: ${layoutDesc}${section.collapsed ? ' (collapsed by default)' : ''}`);
111
+ lines.push('');
112
+ if (section.fields) {
113
+ for (const field of section.fields) {
114
+ let fieldLine = `- **${field.label}** \u2192 \`${field.key}\``;
115
+ const attributes = [];
116
+ if (field.format && field.format !== 'text') {
117
+ attributes.push(field.format);
118
+ }
119
+ if (field.unit) {
120
+ attributes.push(`unit: "${field.unit}"`);
121
+ }
122
+ if (field.editable) {
123
+ attributes.push('editable');
124
+ }
125
+ if (field.highlight) {
126
+ attributes.push(`highlight: ${field.highlight}`);
127
+ }
128
+ if (attributes.length > 0) {
129
+ fieldLine += ` (${attributes.join(', ')})`;
130
+ }
131
+ // Check if key exists in data
132
+ if (!dataKeys.includes(field.key)) {
133
+ fieldLine += ' \u26a0\ufe0f **key not found in data**';
134
+ }
135
+ lines.push(fieldLine);
136
+ }
137
+ }
138
+ }
139
+ lines.push('');
140
+ }
141
+ if (template.footer) {
142
+ lines.push('---');
143
+ lines.push(`Footer: ${template.footer}`);
144
+ lines.push('');
145
+ }
146
+ // Summary
147
+ const totalFields = template.sections.reduce((sum, s) => sum + (s.fields?.length || 0) + (s.columns?.length || 0), 0);
148
+ const missingKeys = template.sections
149
+ .flatMap(s => s.fields || [])
150
+ .filter(f => !dataKeys.includes(f.key))
151
+ .map(f => f.key);
152
+ lines.push('---');
153
+ lines.push(`Summary: ${template.sections.length} section(s), ${totalFields} field(s)/column(s)`);
154
+ if (missingKeys.length > 0) {
155
+ lines.push(`\u26a0\ufe0f Missing keys: ${missingKeys.join(', ')}`);
156
+ }
157
+ else {
158
+ lines.push('\u2705 All field keys found in data');
159
+ }
160
+ return lines.join('\n');
161
+ }
162
+ /**
163
+ * Generate a compact description for tool responses
164
+ */
165
+ export function generateCompactPreview(template) {
166
+ const sections = template.sections.map(s => {
167
+ if (s.layout === 'table' && s.columns) {
168
+ const colList = s.columns
169
+ .slice(0, 3)
170
+ .map(c => c.header)
171
+ .join(', ');
172
+ const more = s.columns.length > 3 ? `, +${s.columns.length - 3} more` : '';
173
+ return `${s.title} (table): ${colList}${more}`;
174
+ }
175
+ if (s.layout === 'chart' && s.chart) {
176
+ const markType = s.chart.spec.mark
177
+ ? (typeof s.chart.spec.mark === 'string' ? s.chart.spec.mark : s.chart.spec.mark.type || 'chart')
178
+ : 'chart';
179
+ return `${s.title} (${markType} chart)`;
180
+ }
181
+ if (s.fields) {
182
+ const fieldList = s.fields
183
+ .slice(0, 3)
184
+ .map(f => f.label)
185
+ .join(', ');
186
+ const more = s.fields.length > 3 ? `, +${s.fields.length - 3} more` : '';
187
+ return `${s.title}: ${fieldList}${more}`;
188
+ }
189
+ return s.title;
190
+ });
191
+ const title = template.title ? `"${template.title}" - ` : '';
192
+ return `${title}${sections.join(' | ')}`;
193
+ }
194
+ //# sourceMappingURL=textPreview.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"textPreview.js","sourceRoot":"","sources":["../../../src/render/textPreview.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Fusion Fragment Types
3
+ *
4
+ * These types define the structure of model-generated UI templates.
5
+ * Models generate templates (structure), the system provides data (values).
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Error formatting utilities for model-friendly output
3
+ */
4
+ /**
5
+ * Format validation errors as a model-friendly string
6
+ * @param errors - Array of validation errors
7
+ * @returns Formatted error message
8
+ */
9
+ export function formatValidationErrors(errors) {
10
+ if (errors.length === 0) {
11
+ return 'Template is valid.';
12
+ }
13
+ const header = `Template validation failed with ${errors.length} error${errors.length > 1 ? 's' : ''}:\n`;
14
+ const formattedErrors = errors.map((error, index) => {
15
+ let message = `${index + 1}. ${error.message}`;
16
+ message += `\n Path: ${error.path}`;
17
+ if (error.suggestion) {
18
+ message += `\n \u2192 ${error.suggestion}`;
19
+ }
20
+ return message;
21
+ });
22
+ return header + '\n' + formattedErrors.join('\n\n');
23
+ }
24
+ /**
25
+ * Format a successful validation with preview info
26
+ * @param template - The validated template
27
+ * @param dataKeys - Available data keys
28
+ * @returns Success message with preview
29
+ */
30
+ export function formatValidationSuccess(template, dataKeys) {
31
+ const lines = ['Template valid. Preview:'];
32
+ lines.push('');
33
+ if (template.title) {
34
+ lines.push(`**${template.title}**`);
35
+ lines.push('');
36
+ }
37
+ for (const section of template.sections) {
38
+ const fieldCount = section.fields.length;
39
+ lines.push(`[${section.title}] ${fieldCount} field${fieldCount > 1 ? 's' : ''}:`);
40
+ for (const field of section.fields) {
41
+ let fieldDesc = `- ${field.label} (${field.key}`;
42
+ if (field.format && field.format !== 'text') {
43
+ fieldDesc += `, ${field.format}`;
44
+ }
45
+ fieldDesc += ')';
46
+ // Check if key exists in data
47
+ if (!dataKeys.includes(field.key)) {
48
+ fieldDesc += ' \u26a0\ufe0f key not in data';
49
+ }
50
+ lines.push(fieldDesc);
51
+ }
52
+ lines.push('');
53
+ }
54
+ return lines.join('\n');
55
+ }
56
+ /**
57
+ * Format a list of available keys for model reference
58
+ * @param dataKeys - Available data keys
59
+ * @param groupByPrefix - Whether to group keys by common prefix
60
+ * @returns Formatted key list
61
+ */
62
+ export function formatAvailableKeys(dataKeys, groupByPrefix = true) {
63
+ if (dataKeys.length === 0) {
64
+ return 'No data keys available.';
65
+ }
66
+ if (!groupByPrefix || dataKeys.length <= 10) {
67
+ return `Available keys: ${dataKeys.join(', ')}`;
68
+ }
69
+ // Group by prefix (e.g., fund.name, fund.type -> fund.*)
70
+ const groups = new Map();
71
+ for (const key of dataKeys) {
72
+ const dotIndex = key.indexOf('.');
73
+ if (dotIndex > 0) {
74
+ const prefix = key.substring(0, dotIndex);
75
+ const rest = key.substring(dotIndex + 1);
76
+ const group = groups.get(prefix) || [];
77
+ group.push(rest);
78
+ groups.set(prefix, group);
79
+ }
80
+ else {
81
+ const group = groups.get('') || [];
82
+ group.push(key);
83
+ groups.set('', group);
84
+ }
85
+ }
86
+ const lines = ['Available keys:'];
87
+ // Top-level keys first
88
+ const topLevel = groups.get('');
89
+ if (topLevel && topLevel.length > 0) {
90
+ lines.push(` ${topLevel.join(', ')}`);
91
+ }
92
+ // Grouped keys
93
+ for (const [prefix, keys] of groups) {
94
+ if (prefix === '')
95
+ continue;
96
+ if (keys.length <= 3) {
97
+ lines.push(` ${prefix}: ${keys.join(', ')}`);
98
+ }
99
+ else {
100
+ lines.push(` ${prefix}: ${keys.slice(0, 3).join(', ')}, ... (${keys.length} total)`);
101
+ }
102
+ }
103
+ return lines.join('\n');
104
+ }
105
+ //# sourceMappingURL=formatErrors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatErrors.js","sourceRoot":"","sources":["../../../src/validation/formatErrors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAAyB;IAC9D,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,oBAAoB,CAAC;IAC9B,CAAC;IAED,MAAM,MAAM,GAAG,mCAAmC,MAAM,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC;IAE1G,MAAM,eAAe,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QAClD,IAAI,OAAO,GAAG,GAAG,KAAK,GAAG,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC;QAC/C,OAAO,IAAI,cAAc,KAAK,CAAC,IAAI,EAAE,CAAC;QACtC,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;YACrB,OAAO,IAAI,eAAe,KAAK,CAAC,UAAU,EAAE,CAAC;QAC/C,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,GAAG,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACtD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CACrC,QAAgI,EAChI,QAAkB;IAElB,MAAM,KAAK,GAAa,CAAC,0BAA0B,CAAC,CAAC;IACrD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEf,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;QACnB,KAAK,CAAC,IAAI,CAAC,KAAK,QAAQ,CAAC,KAAK,IAAI,CAAC,CAAC;QACpC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IAED,KAAK,MAAM,OAAO,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;QACxC,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC;QACzC,KAAK,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,KAAK,KAAK,UAAU,SAAS,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QAElF,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACnC,IAAI,SAAS,GAAG,KAAK,KAAK,CAAC,KAAK,KAAK,KAAK,CAAC,GAAG,EAAE,CAAC;YACjD,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;gBAC5C,SAAS,IAAI,KAAK,KAAK,CAAC,MAAM,EAAE,CAAC;YACnC,CAAC;YACD,SAAS,IAAI,GAAG,CAAC;YAEjB,8BAA8B;YAC9B,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;gBAClC,SAAS,IAAI,+BAA+B,CAAC;YAC/C,CAAC;YAED,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACxB,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CACjC,QAAkB,EAClB,gBAAyB,IAAI;IAE7B,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,yBAAyB,CAAC;IACnC,CAAC;IAED,IAAI,CAAC,aAAa,IAAI,QAAQ,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;QAC5C,OAAO,mBAAmB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;IAClD,CAAC;IAED,yDAAyD;IACzD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAoB,CAAC;IAE3C,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;YACjB,MAAM,MAAM,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;YAC1C,MAAM,IAAI,GAAG,GAAG,CAAC,SAAS,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;YACzC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YACvC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACjB,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAC5B,CAAC;aAAM,CAAC;YACN,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;YACnC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAChB,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IAED,MAAM,KAAK,GAAa,CAAC,iBAAiB,CAAC,CAAC;IAE5C,uBAAuB;IACvB,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChC,IAAI,QAAQ,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpC,KAAK,CAAC,IAAI,CAAC,KAAK,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,eAAe;IACf,KAAK,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,MAAM,EAAE,CAAC;QACpC,IAAI,MAAM,KAAK,EAAE;YAAE,SAAS;QAC5B,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;YACrB,KAAK,CAAC,IAAI,CAAC,KAAK,MAAM,KAAK,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChD,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,KAAK,MAAM,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,MAAM,SAAS,CAAC,CAAC;QACxF,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Fuzzy matching utilities for key suggestions
3
+ * Uses Levenshtein distance for finding similar keys
4
+ */
5
+ /**
6
+ * Calculate Levenshtein distance between two strings
7
+ */
8
+ export function levenshteinDistance(a, b) {
9
+ const matrix = [];
10
+ // Initialize first column
11
+ for (let i = 0; i <= a.length; i++) {
12
+ matrix[i] = [i];
13
+ }
14
+ // Initialize first row
15
+ for (let j = 0; j <= b.length; j++) {
16
+ matrix[0][j] = j;
17
+ }
18
+ // Fill in the rest of the matrix
19
+ for (let i = 1; i <= a.length; i++) {
20
+ for (let j = 1; j <= b.length; j++) {
21
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
22
+ matrix[i][j] = Math.min(matrix[i - 1][j] + 1, // deletion
23
+ matrix[i][j - 1] + 1, // insertion
24
+ matrix[i - 1][j - 1] + cost // substitution
25
+ );
26
+ }
27
+ }
28
+ return matrix[a.length][b.length];
29
+ }
30
+ /**
31
+ * Find the closest matching key from a list of valid keys
32
+ * @param input - The key that wasn't found
33
+ * @param validKeys - List of valid keys to search
34
+ * @param maxDistance - Maximum edit distance to consider (default: 3)
35
+ * @returns The closest key, or undefined if none are close enough
36
+ */
37
+ export function findClosestKey(input, validKeys, maxDistance = 3) {
38
+ if (validKeys.length === 0)
39
+ return undefined;
40
+ const inputLower = input.toLowerCase();
41
+ let bestMatch;
42
+ let bestDistance = Infinity;
43
+ for (const key of validKeys) {
44
+ const keyLower = key.toLowerCase();
45
+ // Exact case-insensitive match
46
+ if (inputLower === keyLower) {
47
+ return key;
48
+ }
49
+ // Check if input is a substring or key is a substring
50
+ if (inputLower.includes(keyLower) || keyLower.includes(inputLower)) {
51
+ const distance = Math.abs(inputLower.length - keyLower.length);
52
+ if (distance < bestDistance) {
53
+ bestDistance = distance;
54
+ bestMatch = key;
55
+ }
56
+ continue;
57
+ }
58
+ // Levenshtein distance
59
+ const distance = levenshteinDistance(inputLower, keyLower);
60
+ if (distance < bestDistance && distance <= maxDistance) {
61
+ bestDistance = distance;
62
+ bestMatch = key;
63
+ }
64
+ }
65
+ return bestMatch;
66
+ }
67
+ /**
68
+ * Find multiple similar keys, sorted by relevance
69
+ * @param input - The key that wasn't found
70
+ * @param validKeys - List of valid keys to search
71
+ * @param maxResults - Maximum number of suggestions (default: 3)
72
+ * @returns Array of similar keys
73
+ */
74
+ export function findSimilarKeys(input, validKeys, maxResults = 3) {
75
+ if (validKeys.length === 0)
76
+ return [];
77
+ const inputLower = input.toLowerCase();
78
+ const scored = validKeys
79
+ .map(key => ({
80
+ key,
81
+ distance: levenshteinDistance(inputLower, key.toLowerCase())
82
+ }))
83
+ .filter(({ distance }) => distance <= 4) // Filter out very different keys
84
+ .sort((a, b) => a.distance - b.distance);
85
+ return scored.slice(0, maxResults).map(({ key }) => key);
86
+ }
87
+ //# sourceMappingURL=fuzzyMatch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fuzzyMatch.js","sourceRoot":"","sources":["../../../src/validation/fuzzyMatch.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,CAAS,EAAE,CAAS;IACtD,MAAM,MAAM,GAAe,EAAE,CAAC;IAE9B,0BAA0B;IAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,uBAAuB;IACvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACnB,CAAC;IAED,iCAAiC;IACjC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACnC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3C,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CACrB,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAM,WAAW;YACrC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,EAAM,YAAY;YACtC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,eAAe;aAC5C,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AACpC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAC5B,KAAa,EACb,SAAmB,EACnB,cAAsB,CAAC;IAEvB,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAE7C,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IACvC,IAAI,SAA6B,CAAC;IAClC,IAAI,YAAY,GAAG,QAAQ,CAAC;IAE5B,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;QAEnC,+BAA+B;QAC/B,IAAI,UAAU,KAAK,QAAQ,EAAE,CAAC;YAC5B,OAAO,GAAG,CAAC;QACb,CAAC;QAED,sDAAsD;QACtD,IAAI,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;YACnE,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;YAC/D,IAAI,QAAQ,GAAG,YAAY,EAAE,CAAC;gBAC5B,YAAY,GAAG,QAAQ,CAAC;gBACxB,SAAS,GAAG,GAAG,CAAC;YAClB,CAAC;YACD,SAAS;QACX,CAAC;QAED,uBAAuB;QACvB,MAAM,QAAQ,GAAG,mBAAmB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAC3D,IAAI,QAAQ,GAAG,YAAY,IAAI,QAAQ,IAAI,WAAW,EAAE,CAAC;YACvD,YAAY,GAAG,QAAQ,CAAC;YACxB,SAAS,GAAG,GAAG,CAAC;QAClB,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAC7B,KAAa,EACb,SAAmB,EACnB,aAAqB,CAAC;IAEtB,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEtC,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IAEvC,MAAM,MAAM,GAAG,SAAS;SACrB,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACX,GAAG;QACH,QAAQ,EAAE,mBAAmB,CAAC,UAAU,EAAE,GAAG,CAAC,WAAW,EAAE,CAAC;KAC7D,CAAC,CAAC;SACF,MAAM,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,QAAQ,IAAI,CAAC,CAAC,CAAC,iCAAiC;SACzE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC;IAE3C,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;AAC3D,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Validation module exports
3
+ */
4
+ export { validateTemplate, parseAndValidateTemplate } from './validateTemplate.js';
5
+ export { FragmentTemplateSchema, SectionTemplateSchema, FieldTemplateSchema } from './schemas.js';
6
+ export { findClosestKey, findSimilarKeys, levenshteinDistance } from './fuzzyMatch.js';
7
+ export { formatValidationErrors, formatValidationSuccess, formatAvailableKeys } from './formatErrors.js';
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/validation/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACnF,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAClG,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACvF,OAAO,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC"}