@mostfeatured/dbi 0.2.14 → 0.2.16

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 (50) hide show
  1. package/dist/src/types/Components/HTMLComponentsV2/index.d.ts +35 -1
  2. package/dist/src/types/Components/HTMLComponentsV2/index.d.ts.map +1 -1
  3. package/dist/src/types/Components/HTMLComponentsV2/index.js +416 -83
  4. package/dist/src/types/Components/HTMLComponentsV2/index.js.map +1 -1
  5. package/dist/src/types/Components/HTMLComponentsV2/parser.d.ts +52 -0
  6. package/dist/src/types/Components/HTMLComponentsV2/parser.d.ts.map +1 -1
  7. package/dist/src/types/Components/HTMLComponentsV2/parser.js +275 -0
  8. package/dist/src/types/Components/HTMLComponentsV2/parser.js.map +1 -1
  9. package/dist/src/types/Components/HTMLComponentsV2/svelteParser.d.ts +28 -1
  10. package/dist/src/types/Components/HTMLComponentsV2/svelteParser.d.ts.map +1 -1
  11. package/dist/src/types/Components/HTMLComponentsV2/svelteParser.js +478 -34
  12. package/dist/src/types/Components/HTMLComponentsV2/svelteParser.js.map +1 -1
  13. package/dist/src/types/Components/HTMLComponentsV2/svelteRenderer.d.ts +12 -0
  14. package/dist/src/types/Components/HTMLComponentsV2/svelteRenderer.d.ts.map +1 -1
  15. package/dist/src/types/Components/HTMLComponentsV2/svelteRenderer.js +102 -18
  16. package/dist/src/types/Components/HTMLComponentsV2/svelteRenderer.js.map +1 -1
  17. package/dist/test/index.js +76 -3
  18. package/dist/test/index.js.map +1 -1
  19. package/dist/test/test.d.ts +2 -0
  20. package/dist/test/test.d.ts.map +1 -0
  21. package/dist/test/test.js +7 -0
  22. package/dist/test/test.js.map +1 -0
  23. package/docs/ADVANCED_FEATURES.md +4 -0
  24. package/docs/API_REFERENCE.md +4 -0
  25. package/docs/CHAT_INPUT.md +4 -0
  26. package/docs/COMPONENTS.md +4 -0
  27. package/docs/EVENTS.md +4 -0
  28. package/docs/GETTING_STARTED.md +4 -0
  29. package/docs/LOCALIZATION.md +4 -0
  30. package/docs/README.md +4 -0
  31. package/docs/SVELTE_COMPONENTS.md +162 -6
  32. package/docs/llm/ADVANCED_FEATURES.txt +521 -0
  33. package/docs/llm/API_REFERENCE.txt +659 -0
  34. package/docs/llm/CHAT_INPUT.txt +514 -0
  35. package/docs/llm/COMPONENTS.txt +595 -0
  36. package/docs/llm/EVENTS.txt +449 -0
  37. package/docs/llm/GETTING_STARTED.txt +296 -0
  38. package/docs/llm/LOCALIZATION.txt +501 -0
  39. package/docs/llm/README.txt +193 -0
  40. package/docs/llm/SVELTE_COMPONENTS.txt +566 -0
  41. package/generated/svelte-dbi.d.ts +122 -0
  42. package/package.json +1 -1
  43. package/src/types/Components/HTMLComponentsV2/index.ts +478 -95
  44. package/src/types/Components/HTMLComponentsV2/parser.ts +317 -0
  45. package/src/types/Components/HTMLComponentsV2/svelteParser.ts +536 -35
  46. package/src/types/Components/HTMLComponentsV2/svelteRenderer.ts +121 -20
  47. package/test/index.ts +76 -3
  48. package/test/product-showcase.svelte +383 -24
  49. package/test/test.ts +3 -0
  50. package/llm.txt +0 -1088
@@ -1,20 +1,33 @@
1
1
  import { compile } from "svelte/compiler";
2
2
  import { DBI } from "../../../DBI";
3
3
  import { NamespaceEnums } from "../../../../generated/namespaceData";
4
- import { parseHTMLComponentsV2 } from "./parser";
5
- import { parseSvelteComponent, createHandlerContext, SvelteComponentInfo, HandlerContextResult } from "./svelteParser";
4
+ import { parseHTMLComponentsV2, parseHTMLComponentsV2Multi } from "./parser";
5
+ import { parseSvelteComponent, createHandlerContext, SvelteComponentInfo, HandlerContextResult, validateSvelteComponent, logValidationWarnings } from "./svelteParser";
6
6
  import * as stuffs from "stuffs";
7
7
  import * as vm from "vm";
8
8
 
9
9
  export interface SvelteRenderOptions {
10
10
  data?: Record<string, any>;
11
11
  ttl?: number;
12
+ /** If true, skips validation warnings (useful for production) */
13
+ skipValidation?: boolean;
14
+ /** The file path of the Svelte component (used for resolving relative imports) */
15
+ filePath?: string;
16
+ }
17
+
18
+ export interface ModalDefinition {
19
+ title: string;
20
+ customId: string;
21
+ components: any[];
22
+ modalId: string;
12
23
  }
13
24
 
14
25
  export interface SvelteRenderResult {
15
26
  components: any[];
16
27
  handlers: Map<string, { handlerFn: Function, context: any }>;
17
28
  componentInfo: SvelteComponentInfo;
29
+ /** Modal definitions parsed from <components type="modal"> elements */
30
+ modals: Map<string, ModalDefinition>;
18
31
  }
19
32
 
20
33
  /**
@@ -26,35 +39,99 @@ export async function renderSvelteComponent(
26
39
  dbiName: string,
27
40
  options: SvelteRenderOptions = {}
28
41
  ): Promise<SvelteRenderResult> {
29
- const { data = {}, ttl = 0 } = options;
42
+ const { data = {}, ttl = 0, skipValidation = false, filePath } = options;
30
43
 
31
44
  // Parse the Svelte component to extract handlers
32
45
  // This also injects auto-generated names into elements without name attribute
33
46
  const componentInfo = await parseSvelteComponent(source, data);
34
47
 
48
+ // Validate the component and log warnings (only on first render, not re-renders)
49
+ if (!skipValidation && !data.$ref) {
50
+ const warnings = validateSvelteComponent(componentInfo, data, dbiName);
51
+ if (warnings.length > 0) {
52
+ logValidationWarnings(warnings);
53
+ }
54
+ }
55
+
35
56
  // Use the processed source (with auto-generated names injected)
36
57
  const processedSource = componentInfo.processedSource;
37
58
 
38
59
  // Compile the Svelte component for SSR (Svelte 5)
39
- const compiled = compile(processedSource, {
40
- generate: "server",
41
- css: "injected",
42
- dev: false,
43
- } as any);
60
+ let compiled;
61
+ try {
62
+ compiled = compile(processedSource, {
63
+ generate: "server",
64
+ css: "injected",
65
+ dev: false,
66
+ } as any);
67
+ } catch (compileError: any) {
68
+ // Format Svelte compile error with helpful details
69
+ const errorMessage = compileError.message || 'Unknown compile error';
70
+ const location = compileError.start || compileError.loc || compileError.position;
71
+ let details = errorMessage;
72
+
73
+ if (location) {
74
+ const lines = processedSource.split('\n');
75
+ const lineNum = location.line || 1;
76
+ const column = location.column || 0;
77
+ const errorLine = lines[lineNum - 1] || '';
78
+ const prevLine = lines[lineNum - 2] || '';
79
+ const nextLine = lines[lineNum] || '';
80
+
81
+ details = `
82
+ Svelte Compile Error at line ${lineNum}, column ${column}:
83
+ ${errorMessage}
84
+
85
+ ${lineNum > 1 ? `${lineNum - 1} | ${prevLine}\n` : ''}${lineNum} | ${errorLine}
86
+ ${' '.repeat(String(lineNum).length + 3 + column)}^
87
+ ${nextLine ? `${lineNum + 1} | ${nextLine}` : ''}
88
+ `.trim();
89
+ }
90
+
91
+ // Check for common mistakes and add hints
92
+ let hint = '';
93
+ if (errorMessage.includes('Unexpected token')) {
94
+ hint = '\n\n💡 Hint: Check for missing closing tags, unclosed braces, or invalid JavaScript syntax.';
95
+ } else if (errorMessage.includes('is not defined')) {
96
+ hint = '\n\n💡 Hint: Make sure all variables are declared in $props() or as local variables.';
97
+ } else if (errorMessage.includes('Expected')) {
98
+ hint = '\n\n💡 Hint: There might be a syntax error in your template or script.';
99
+ }
100
+
101
+ const enhancedError = new Error(`[DBI-Svelte] Failed to compile component "${dbiName}":\n${details}${hint}`);
102
+ (enhancedError as any).originalError = compileError;
103
+ (enhancedError as any).type = 'svelte-compile-error';
104
+ throw enhancedError;
105
+ }
44
106
 
45
107
  // Create a module context for the compiled code
46
108
  let html = "";
47
109
  try {
48
110
  const moduleContext = createModuleContext(dbi, data, ttl);
49
- const Component = evaluateCompiledComponent(compiled.js.code, moduleContext);
111
+ const Component = evaluateCompiledComponent(compiled.js.code, moduleContext, filePath);
50
112
 
51
113
  // Svelte 5 SSR: Use render from svelte/server
52
114
  const { render } = require("svelte/server");
53
115
  // Pass data properties as top-level props (Svelte 5 expects flat props object)
54
116
  const renderResult = render(Component, { props: data });
55
117
  html = renderResult.body || "";
56
- } catch (error) {
57
- throw error;
118
+ } catch (runtimeError: any) {
119
+ // Format runtime error with helpful details
120
+ const errorMessage = runtimeError.message || 'Unknown runtime error';
121
+ let hint = '';
122
+
123
+ if (errorMessage.includes('is not a function')) {
124
+ hint = '\n\n💡 Hint: A function you are trying to call is undefined. Check handler names.';
125
+ } else if (errorMessage.includes('Cannot read properties of undefined') || errorMessage.includes('undefined is not an object')) {
126
+ hint = '\n\n💡 Hint: You are trying to access a property of an undefined value. Check your data object.';
127
+ } else if (errorMessage.includes('is not defined')) {
128
+ hint = '\n\n💡 Hint: A variable is used but not declared. Make sure it is in $props() or declared locally.';
129
+ }
130
+
131
+ const enhancedError = new Error(`[DBI-Svelte] Runtime error in component "${dbiName}":\n${errorMessage}${hint}`);
132
+ (enhancedError as any).originalError = runtimeError;
133
+ (enhancedError as any).type = 'svelte-runtime-error';
134
+ throw enhancedError;
58
135
  }
59
136
 
60
137
  // For Svelte mode, inject state into interactive elements as a ref
@@ -102,11 +179,17 @@ export async function renderSvelteComponent(
102
179
  });
103
180
  }
104
181
 
105
- // Parse the rendered HTML to Discord components
106
- const components = parseHTMLComponentsV2(dbi, html, dbiName, { data, ttl });
182
+ // Parse the rendered HTML to Discord components (with modal support)
183
+ const parseResult = parseHTMLComponentsV2Multi(dbi, html, dbiName, { data, ttl });
184
+ const components = parseResult.components;
185
+ const modals = parseResult.modals;
186
+
187
+ // Get source directory for resolving relative imports
188
+ const path = require("path");
189
+ const sourceDir = filePath ? path.dirname(path.resolve(filePath)) : undefined;
107
190
 
108
191
  // Create handler context (also captures $effect callbacks)
109
- const handlerContext = createHandlerContext(componentInfo.scriptContent, data);
192
+ const handlerContext = createHandlerContext(componentInfo.scriptContent, data, undefined, undefined, sourceDir);
110
193
  const handlers = new Map<string, { handlerFn: Function, context: any }>();
111
194
 
112
195
  // Run effects on initial render
@@ -126,7 +209,8 @@ export async function renderSvelteComponent(
126
209
  return {
127
210
  components,
128
211
  handlers,
129
- componentInfo
212
+ componentInfo,
213
+ modals
130
214
  };
131
215
  }
132
216
 
@@ -155,10 +239,14 @@ function createModuleContext(dbi: DBI<NamespaceEnums>, data: Record<string, any>
155
239
  /**
156
240
  * Evaluate the compiled Svelte component code
157
241
  */
158
- function evaluateCompiledComponent(code: string, context: Record<string, any>): any {
242
+ function evaluateCompiledComponent(code: string, context: Record<string, any>, filePath?: string): any {
159
243
  try {
160
244
  // Load Svelte 5 internal runtime
161
245
  const svelteInternal = require("svelte/internal/server");
246
+ const path = require("path");
247
+
248
+ // Get the directory of the source file for resolving relative imports
249
+ const sourceDir = filePath ? path.dirname(path.resolve(filePath)) : process.cwd();
162
250
 
163
251
  // Process the code to work in our context
164
252
  let processedCode = code;
@@ -186,7 +274,11 @@ function evaluateCompiledComponent(code: string, context: Record<string, any>):
186
274
  // Skip svelte imports
187
275
  if (modulePath.startsWith('svelte')) return '';
188
276
  try {
189
- const mod = require(modulePath);
277
+ // Resolve relative paths from source file directory
278
+ const resolvedPath = modulePath.startsWith('.')
279
+ ? path.resolve(sourceDir, modulePath)
280
+ : modulePath;
281
+ const mod = require(resolvedPath);
190
282
  externalModules[varName] = mod.default || mod;
191
283
  return `const ${varName} = __externalModules.${varName};`;
192
284
  } catch (e) {
@@ -202,7 +294,11 @@ function evaluateCompiledComponent(code: string, context: Record<string, any>):
202
294
  // Skip svelte imports
203
295
  if (modulePath.startsWith('svelte')) return '';
204
296
  try {
205
- const mod = require(modulePath);
297
+ // Resolve relative paths from source file directory
298
+ const resolvedPath = modulePath.startsWith('.')
299
+ ? path.resolve(sourceDir, modulePath)
300
+ : modulePath;
301
+ const mod = require(resolvedPath);
206
302
  const importList = imports.split(',').map((i: string) => i.trim());
207
303
  importList.forEach((importName: string) => {
208
304
  const [name, alias] = importName.split(' as ').map(s => s.trim());
@@ -225,7 +321,11 @@ function evaluateCompiledComponent(code: string, context: Record<string, any>):
225
321
  // Skip svelte imports
226
322
  if (modulePath.startsWith('svelte')) return '';
227
323
  try {
228
- const mod = require(modulePath);
324
+ // Resolve relative paths from source file directory
325
+ const resolvedPath = modulePath.startsWith('.')
326
+ ? path.resolve(sourceDir, modulePath)
327
+ : modulePath;
328
+ const mod = require(resolvedPath);
229
329
  externalModules[varName] = mod;
230
330
  return `const ${varName} = __externalModules.${varName};`;
231
331
  } catch (e) {
@@ -311,5 +411,6 @@ export async function renderSvelteComponentFromFile(
311
411
  ): Promise<SvelteRenderResult> {
312
412
  const fs = require("fs");
313
413
  const source = fs.readFileSync(filePath, "utf-8");
314
- return await renderSvelteComponent(dbi, source, dbiName, options);
414
+ // Pass filePath to options for resolving relative imports
415
+ return await renderSvelteComponent(dbi, source, dbiName, { ...options, filePath });
315
416
  }
package/test/index.ts CHANGED
@@ -26,8 +26,7 @@ dbi.register(({ ChatInput, HTMLComponentsV2 }) => {
26
26
  HTMLComponentsV2({
27
27
  name: "product-showcase",
28
28
  mode: 'svelte',
29
- file: path.join(__dirname, "product-showcase.svelte"),
30
- onExecute(ctx) {}
29
+ file: path.join(__dirname, "product-showcase.svelte")
31
30
  });
32
31
 
33
32
  // Test command
@@ -73,6 +72,78 @@ dbi.register(({ ChatInput, HTMLComponentsV2 }) => {
73
72
  category: "Furniture",
74
73
  rating: 4.6,
75
74
  stock: 31
75
+ },
76
+ {
77
+ name: "Webcam 4K",
78
+ description: "Ultra HD webcam with autofocus and noise-canceling mic",
79
+ price: 129,
80
+ image: "https://cdn.discordapp.com/embed/avatars/4.png",
81
+ category: "Electronics",
82
+ rating: 4.7,
83
+ stock: 15
84
+ },
85
+ {
86
+ name: "Desk Lamp",
87
+ description: "LED desk lamp with adjustable brightness and color temperature",
88
+ price: 45,
89
+ image: "https://cdn.discordapp.com/embed/avatars/0.png",
90
+ category: "Furniture",
91
+ rating: 4.4,
92
+ stock: 60
93
+ },
94
+ {
95
+ name: "Headphone Stand",
96
+ description: "Aluminum headphone stand with cable holder",
97
+ price: 35,
98
+ image: "https://cdn.discordapp.com/embed/avatars/1.png",
99
+ category: "Accessories",
100
+ rating: 4.2,
101
+ stock: 28
102
+ },
103
+ {
104
+ name: "Gaming Headset",
105
+ description: "7.1 surround sound gaming headset with RGB lighting",
106
+ price: 99,
107
+ image: "https://cdn.discordapp.com/embed/avatars/2.png",
108
+ category: "Electronics",
109
+ rating: 4.6,
110
+ stock: 35
111
+ },
112
+ {
113
+ name: "Mouse Pad XL",
114
+ description: "Extended mouse pad with stitched edges, 900x400mm",
115
+ price: 25,
116
+ image: "https://cdn.discordapp.com/embed/avatars/3.png",
117
+ category: "Accessories",
118
+ rating: 4.8,
119
+ stock: 100
120
+ },
121
+ {
122
+ name: "Ergonomic Chair",
123
+ description: "Mesh office chair with lumbar support and adjustable armrests",
124
+ price: 299,
125
+ image: "https://cdn.discordapp.com/embed/avatars/4.png",
126
+ category: "Furniture",
127
+ rating: 4.9,
128
+ stock: 8
129
+ },
130
+ {
131
+ name: "Cable Management Kit",
132
+ description: "Complete kit with cable clips, ties, and sleeve",
133
+ price: 19,
134
+ image: "https://cdn.discordapp.com/embed/avatars/0.png",
135
+ category: "Accessories",
136
+ rating: 4.1,
137
+ stock: 75
138
+ },
139
+ {
140
+ name: "Portable SSD 1TB",
141
+ description: "Ultra-fast portable SSD with USB 3.2 Gen 2",
142
+ price: 109,
143
+ image: "https://cdn.discordapp.com/embed/avatars/1.png",
144
+ category: "Electronics",
145
+ rating: 4.7,
146
+ stock: 22
76
147
  }
77
148
  ];
78
149
 
@@ -84,7 +155,9 @@ dbi.register(({ ChatInput, HTMLComponentsV2 }) => {
84
155
  currentIndex: 0,
85
156
  cart: [],
86
157
  view: 'browse',
87
- elapsedTime: 0
158
+ elapsedTime: 0,
159
+ reviews: [],
160
+ editingProduct: null
88
161
  }
89
162
  });
90
163
  }