slicejs-web-framework 1.0.30 → 1.0.31

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.
@@ -110,6 +110,14 @@ export default class Controller {
110
110
  return this.componentCategories.get(componentSliceId);
111
111
  }
112
112
 
113
+ /*
114
+ Fetches a text resource (HTML, CSS, theme, or styles) for a component.
115
+ @param {string} componentName - The name of the component.
116
+ @param {string} resourceType - The type of resource to fetch ('html', 'css', 'theme', or 'styles').
117
+ @param {string} [componentCategory] - Optional category of the component.
118
+ @param {string} [customPath] - Optional custom path to fetch the resource from.
119
+ @returns {Promise<string>} - A promise that resolves to the fetched text.
120
+ */
113
121
  async fetchText(componentName, resourceType, componentCategory, customPath) {
114
122
  try {
115
123
  const baseUrl = window.location.origin;
@@ -121,9 +129,20 @@ export default class Controller {
121
129
 
122
130
  let isVisual = resourceType === 'html' || resourceType === 'css';
123
131
 
124
- if(isVisual) {
125
- path = `${slice.paths.components[componentCategory].path}/${componentName}`;
126
- resourceType === 'html' ? path += `/${componentName}.html` : path += `/${componentName}.css`;
132
+ if (isVisual) {
133
+ // CORREGIDO: Verificar que la categoría existe y agregar baseUrl
134
+ if (slice.paths.components[componentCategory]) {
135
+ path = `${baseUrl}${slice.paths.components[componentCategory].path}/${componentName}`;
136
+ resourceType === 'html' ? path += `/${componentName}.html` : path += `/${componentName}.css`;
137
+ } else {
138
+ // ✅ FALLBACK: Para componentes Structural o categorías no configuradas
139
+ if (componentCategory === 'Structural') {
140
+ path = `${baseUrl}/Slice/Components/Structural/${componentName}`;
141
+ resourceType === 'html' ? path += `/${componentName}.html` : path += `/${componentName}.css`;
142
+ } else {
143
+ throw new Error(`Component category '${componentCategory}' not found in paths configuration`);
144
+ }
145
+ }
127
146
  }
128
147
 
129
148
  if (resourceType === 'theme') {
@@ -134,35 +153,129 @@ export default class Controller {
134
153
  path = `${baseUrl}${slice.paths.styles}/${componentName}.css`;
135
154
  }
136
155
 
137
- if(customPath){
156
+ if (customPath) {
138
157
  path = customPath;
139
158
  }
140
159
 
160
+ // ✅ MEJORADO: Logging para debugging
161
+ slice.logger.logInfo('Controller', `Fetching ${resourceType} from: ${path}`);
162
+
141
163
  const response = await fetch(path);
142
164
 
143
165
  if (!response.ok) {
144
166
  throw new Error(`Failed to fetch ${path}: ${response.statusText}`);
145
167
  }
146
168
 
147
- const html = await response.text();
148
- return html;
169
+ const content = await response.text();
170
+ slice.logger.logInfo('Controller', `Successfully fetched ${resourceType} for ${componentName}`);
171
+ return content;
149
172
  } catch (error) {
150
173
  slice.logger.logError('Controller', `Error fetching ${resourceType} for component ${componentName}:`, error);
151
- // You can also re-throw the error if you want it to propagate
152
- // throw error;
174
+ // CORREGIDO: Re-lanzar el error para que el debugger pueda manejarlo
175
+ throw error;
153
176
  }
154
177
  }
155
178
 
156
-
157
-
158
-
159
179
  setComponentProps(component, props) {
180
+ const ComponentClass = component.constructor;
181
+ const componentName = ComponentClass.name;
182
+
183
+ // ✅ Aplicar defaults si tiene static props
184
+ if (ComponentClass.props) {
185
+ this.applyDefaultProps(component, ComponentClass.props, props);
186
+ }
187
+
188
+ // ✅ Validar solo en desarrollo
189
+ if (ComponentClass.props && !slice.isProduction()) {
190
+ this.validatePropsInDevelopment(ComponentClass, props, componentName);
191
+ }
192
+
193
+ // ✅ CÓDIGO EXISTENTE: Aplicar props
160
194
  for (const prop in props) {
161
195
  component[`_${prop}`] = null;
162
196
  component[prop] = props[prop];
163
197
  }
164
198
  }
165
199
 
200
+ getComponentPropsForDebugger(component) {
201
+ const ComponentClass = component.constructor;
202
+
203
+ if (ComponentClass.props) {
204
+ // Si tiene props estáticos, usar esos como referencia
205
+ return {
206
+ availableProps: Object.keys(ComponentClass.props),
207
+ propsConfig: ComponentClass.props,
208
+ usedProps: this.extractUsedProps(component, ComponentClass.props)
209
+ };
210
+ } else {
211
+ // Si no tiene props estáticos, usar modo legacy
212
+ return {
213
+ availableProps: this.extractUsedProps(component),
214
+ propsConfig: null,
215
+ usedProps: this.extractUsedProps(component)
216
+ };
217
+ }
218
+ }
219
+
220
+ applyDefaultProps(component, staticProps, providedProps) {
221
+ Object.entries(staticProps).forEach(([prop, config]) => {
222
+ if (config.default !== undefined && !(prop in (providedProps || {}))) {
223
+ component[`_${prop}`] = null;
224
+ component[prop] = config.default;
225
+ }
226
+ });
227
+ }
228
+
229
+ validatePropsInDevelopment(ComponentClass, providedProps, componentName) {
230
+ const staticProps = ComponentClass.props;
231
+ const usedProps = Object.keys(providedProps || {});
232
+
233
+ const availableProps = Object.keys(staticProps);
234
+ const unknownProps = usedProps.filter(prop => !availableProps.includes(prop));
235
+
236
+ if (unknownProps.length > 0) {
237
+ slice.logger.logWarning(
238
+ 'PropsValidator',
239
+ `${componentName}: Unknown props [${unknownProps.join(', ')}]. Available: [${availableProps.join(', ')}]`
240
+ );
241
+ }
242
+
243
+ const requiredProps = Object.entries(staticProps)
244
+ .filter(([_, config]) => config.required)
245
+ .map(([prop, _]) => prop);
246
+
247
+ const missingRequired = requiredProps.filter(prop => !(prop in (providedProps || {})));
248
+ if (missingRequired.length > 0) {
249
+ slice.logger.logError(
250
+ componentName,
251
+ `Missing required props: [${missingRequired.join(', ')}]`
252
+ );
253
+ }
254
+ }
255
+
256
+ extractUsedProps(component, staticProps = null) {
257
+ const usedProps = {};
258
+
259
+ if (staticProps) {
260
+ // Si tiene props estáticos, buscar solo esos
261
+ Object.keys(staticProps).forEach(prop => {
262
+ if (component[prop] !== undefined) {
263
+ usedProps[prop] = component[prop];
264
+ }
265
+ });
266
+ } else {
267
+ // Modo legacy: buscar cualquier prop que empiece con _
268
+ Object.getOwnPropertyNames(component).forEach(key => {
269
+ if (key.startsWith('_') && key !== '_isActive') {
270
+ const propName = key.substring(1);
271
+ usedProps[propName] = component[propName];
272
+ }
273
+ });
274
+ }
275
+
276
+ return usedProps;
277
+ }
278
+
166
279
  destroyComponent(component) {
167
280
  const sliceId = component.sliceId;
168
281
  this.activeComponents.delete(sliceId);
@@ -172,4 +285,4 @@ export default class Controller {
172
285
 
173
286
  function getRelativePath(levels) {
174
287
  return '../'.repeat(levels);
175
- }
288
+ }