slicejs-web-framework 2.4.2 → 2.4.4
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.
|
@@ -295,9 +295,18 @@ export default class Controller {
|
|
|
295
295
|
return Promise.resolve(false);
|
|
296
296
|
}
|
|
297
297
|
|
|
298
|
-
|
|
298
|
+
// Set tracking flags synchronously before any async work, so callers that
|
|
299
|
+
// await import() see the flags set immediately when the Promise resolves.
|
|
300
|
+
const { components, metadata } = bundle;
|
|
301
|
+
const bundleKey = metadata?.bundleKey;
|
|
302
|
+
if (bundleKey) {
|
|
303
|
+
this.loadedBundles.add(bundleKey);
|
|
304
|
+
if (metadata?.type === 'critical') {
|
|
305
|
+
this.criticalBundleLoaded = true;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
299
308
|
|
|
300
|
-
|
|
309
|
+
console.log(`📦 Registering bundle: ${metadata.type} (${metadata.componentCount} components)`);
|
|
301
310
|
|
|
302
311
|
const entries = Object.entries(components);
|
|
303
312
|
const chunkSize = 50;
|
|
@@ -327,6 +336,13 @@ export default class Controller {
|
|
|
327
336
|
? `Framework/Structural/${componentName}`
|
|
328
337
|
: componentName;
|
|
329
338
|
this.classes.set(registeredName, componentData.class);
|
|
339
|
+
if (componentName === 'Loading') {
|
|
340
|
+
console.log('🔎 Bundle class registered: Loading', {
|
|
341
|
+
registeredName,
|
|
342
|
+
type: typeof componentData.class,
|
|
343
|
+
isFunction: typeof componentData.class === 'function'
|
|
344
|
+
});
|
|
345
|
+
}
|
|
330
346
|
if (componentName === 'InputSearchDocs' || componentName === 'MainMenu') {
|
|
331
347
|
console.log(`🔎 Bundle class registered: ${componentName}`, {
|
|
332
348
|
registeredName,
|
|
@@ -19,7 +19,8 @@ export default class StylesManager {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
if (slice.themeConfig.enabled) {
|
|
22
|
-
const ThemeManagerClass = slice.frameworkClasses?.ThemeManager
|
|
22
|
+
const ThemeManagerClass = slice.frameworkClasses?.ThemeManager
|
|
23
|
+
|| await slice.getClass(`${slice.paths.structuralComponentFolderPath}/StylesManager/ThemeManager/ThemeManager.js`);
|
|
23
24
|
if (!ThemeManagerClass) {
|
|
24
25
|
throw new Error('ThemeManager not available');
|
|
25
26
|
}
|
package/Slice/Slice.js
CHANGED
|
@@ -21,6 +21,10 @@ export default class Slice {
|
|
|
21
21
|
this.loadingConfig = sliceConfig.loading;
|
|
22
22
|
this.eventsConfig = sliceConfig.events;
|
|
23
23
|
|
|
24
|
+
// Default to production until init() resolves the actual mode.
|
|
25
|
+
// Safe to call isProduction() before init() completes.
|
|
26
|
+
this._mode = 'production';
|
|
27
|
+
|
|
24
28
|
// 📦 Bundle system is initialized automatically via import in index.js
|
|
25
29
|
}
|
|
26
30
|
|
|
@@ -39,11 +43,12 @@ export default class Slice {
|
|
|
39
43
|
}
|
|
40
44
|
|
|
41
45
|
/**
|
|
42
|
-
*
|
|
46
|
+
* Returns true when running in production mode.
|
|
47
|
+
* Reliable after init() has completed.
|
|
43
48
|
* @returns {boolean}
|
|
44
49
|
*/
|
|
45
50
|
isProduction() {
|
|
46
|
-
return
|
|
51
|
+
return this._mode === 'production';
|
|
47
52
|
}
|
|
48
53
|
|
|
49
54
|
/**
|
|
@@ -157,6 +162,13 @@ export default class Slice {
|
|
|
157
162
|
delete props.sliceId;
|
|
158
163
|
|
|
159
164
|
const ComponentClass = this.controller.classes.get(componentName);
|
|
165
|
+
if (componentName === 'Loading') {
|
|
166
|
+
console.log('🔎 Build component: Loading', {
|
|
167
|
+
classType: typeof ComponentClass,
|
|
168
|
+
isFunction: typeof ComponentClass === 'function',
|
|
169
|
+
classValue: ComponentClass
|
|
170
|
+
});
|
|
171
|
+
}
|
|
160
172
|
if (componentName === 'InputSearchDocs' || componentName === 'MainMenu') {
|
|
161
173
|
console.log(`🔎 Build component: ${componentName}`, {
|
|
162
174
|
classType: typeof ComponentClass,
|
|
@@ -226,7 +238,6 @@ async function loadConfig() {
|
|
|
226
238
|
const response = await fetch('/sliceConfig.json'); // 🔹 Express lo sirve desde `src/`
|
|
227
239
|
if (!response.ok) throw new Error('Error loading sliceConfig.json');
|
|
228
240
|
const json = await response.json();
|
|
229
|
-
console.log(json);
|
|
230
241
|
return json;
|
|
231
242
|
} catch (error) {
|
|
232
243
|
console.error(`Error loading config file: ${error.message}`);
|
|
@@ -243,6 +254,20 @@ async function init() {
|
|
|
243
254
|
return;
|
|
244
255
|
}
|
|
245
256
|
|
|
257
|
+
// 1. Resolve runtime mode via dev server endpoint.
|
|
258
|
+
// In production the endpoint returns 404 (not registered), so catch/non-ok is expected.
|
|
259
|
+
let envMode = null;
|
|
260
|
+
try {
|
|
261
|
+
const envRes = await fetch('/slice-env.json', { cache: 'no-store' });
|
|
262
|
+
if (envRes.ok) {
|
|
263
|
+
const env = await envRes.json();
|
|
264
|
+
envMode = env.mode; // 'development' | 'production'
|
|
265
|
+
}
|
|
266
|
+
} catch (error) {
|
|
267
|
+
// Endpoint not available — normal in production
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// 2. Fetch bundle config (existing logic, unchanged)
|
|
246
271
|
let frameworkClasses = null;
|
|
247
272
|
let bundleConfigJson = null;
|
|
248
273
|
try {
|
|
@@ -254,47 +279,68 @@ async function init() {
|
|
|
254
279
|
// ignore
|
|
255
280
|
}
|
|
256
281
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
282
|
+
// 3. Determine canonical mode: env endpoint takes precedence, then bundle config
|
|
283
|
+
let resolvedMode;
|
|
284
|
+
if (envMode) {
|
|
285
|
+
resolvedMode = envMode;
|
|
286
|
+
} else if (bundleConfigJson?.production) {
|
|
287
|
+
resolvedMode = 'production';
|
|
288
|
+
} else {
|
|
289
|
+
resolvedMode = 'development';
|
|
264
290
|
}
|
|
265
291
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
292
|
+
// 4. Load framework classes.
|
|
293
|
+
// In production the bundler generates slice-bundle.framework.js which
|
|
294
|
+
// sets window.SLICE_FRAMEWORK_CLASSES. In dev mode always use individual
|
|
295
|
+
// imports so the live /Slice/ source is served directly without bundles.
|
|
296
|
+
if (resolvedMode === 'production' && bundleConfigJson?.bundles?.framework?.file) {
|
|
297
|
+
try {
|
|
298
|
+
await import(`/bundles/${bundleConfigJson.bundles.framework.file}`);
|
|
299
|
+
if (window.SLICE_FRAMEWORK_CLASSES) {
|
|
300
|
+
frameworkClasses = window.SLICE_FRAMEWORK_CLASSES;
|
|
301
|
+
}
|
|
302
|
+
} catch (e) {
|
|
303
|
+
// framework bundle failed — fall through to individual imports
|
|
304
|
+
console.error('[Slice.js] framework bundle import failed:', e?.message || e);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
if (!frameworkClasses) {
|
|
309
|
+
try {
|
|
310
|
+
const imports = await Promise.all([
|
|
311
|
+
import('./Components/Structural/Controller/Controller.js'),
|
|
312
|
+
import('./Components/Structural/StylesManager/StylesManager.js')
|
|
313
|
+
]);
|
|
314
|
+
frameworkClasses = {
|
|
315
|
+
Controller: imports[0].default,
|
|
316
|
+
StylesManager: imports[1].default
|
|
317
|
+
};
|
|
318
|
+
} catch (e) {
|
|
319
|
+
console.error('[Slice.js] individual imports fallback failed:', e?.message || e);
|
|
320
|
+
throw e;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
276
323
|
|
|
324
|
+
// 5. Create Slice instance and set resolved mode
|
|
277
325
|
window.slice = new Slice(sliceConfig, frameworkClasses);
|
|
326
|
+
window.slice._mode = resolvedMode;
|
|
278
327
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
328
|
+
// Initialize bundles before building components.
|
|
329
|
+
// Only in production — dev mode loads each component individually from source.
|
|
330
|
+
// bundleConfigJson was already fetched above (step 2); reuse it.
|
|
331
|
+
try {
|
|
332
|
+
if (resolvedMode === 'production' && bundleConfigJson) {
|
|
333
|
+
window.slice.controller.bundleConfig = bundleConfigJson;
|
|
334
|
+
}
|
|
286
335
|
|
|
287
336
|
if (window.slice.controller.bundleConfig) {
|
|
288
337
|
const config = window.slice.controller.bundleConfig;
|
|
289
338
|
|
|
290
339
|
const criticalFile = config?.bundles?.critical?.file;
|
|
291
340
|
if (criticalFile) {
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
window.slice.controller.loadedBundles.add('critical');
|
|
296
|
-
window.slice.controller.criticalBundleLoaded = true;
|
|
297
|
-
}
|
|
341
|
+
// Bundle auto-registers itself on import via its own registration block.
|
|
342
|
+
// No explicit registerBundle() call needed — flags are set inside registerBundle().
|
|
343
|
+
await import(`/bundles/${criticalFile}`);
|
|
298
344
|
}
|
|
299
345
|
|
|
300
346
|
const routeBundles = config?.routeBundles || {};
|
|
@@ -306,11 +352,8 @@ async function init() {
|
|
|
306
352
|
if (bundleName === 'critical') continue;
|
|
307
353
|
const bundleInfo = config?.bundles?.routes?.[bundleName];
|
|
308
354
|
if (!bundleInfo?.file) continue;
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
window.slice.controller.registerBundle(routeModule.SLICE_BUNDLE);
|
|
312
|
-
window.slice.controller.loadedBundles.add(bundleName);
|
|
313
|
-
}
|
|
355
|
+
// Bundle auto-registers itself on import.
|
|
356
|
+
await import(`/bundles/${bundleInfo.file}`);
|
|
314
357
|
}
|
|
315
358
|
};
|
|
316
359
|
|
package/api/index.js
CHANGED
|
@@ -86,6 +86,23 @@ app.use((req, res, next) => {
|
|
|
86
86
|
}
|
|
87
87
|
});
|
|
88
88
|
|
|
89
|
+
// ==============================================
|
|
90
|
+
// RUNTIME MODE ENDPOINT
|
|
91
|
+
// ==============================================
|
|
92
|
+
|
|
93
|
+
// Expone el modo actual al framework Slice.js en runtime.
|
|
94
|
+
// Solo se registra en development — 404 en production indica modo producción.
|
|
95
|
+
if (runMode === 'development') {
|
|
96
|
+
app.get('/slice-env.json', (req, res) => {
|
|
97
|
+
res.json({ mode: 'development' });
|
|
98
|
+
});
|
|
99
|
+
} else {
|
|
100
|
+
// Explicit 404 so the SPA fallback doesn't return 200 for this dev-only endpoint.
|
|
101
|
+
app.get('/slice-env.json', (req, res) => {
|
|
102
|
+
res.status(404).json({ error: 'Not found' });
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
89
106
|
// ==============================================
|
|
90
107
|
// ARCHIVOS ESTÁTICOS (DESPUÉS DE SEGURIDAD)
|
|
91
108
|
// ==============================================
|