wu-framework 1.0.6 → 1.1.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.
- package/README.md +773 -366
- package/package.json +34 -9
- package/src/adapters/angular.d.ts +154 -0
- package/src/adapters/angular.js +642 -0
- package/src/adapters/index.js +157 -0
- package/src/adapters/lit.d.ts +120 -0
- package/src/adapters/lit.js +726 -0
- package/src/adapters/preact.d.ts +108 -0
- package/src/adapters/preact.js +665 -0
- package/src/adapters/react.d.ts +212 -0
- package/src/adapters/react.js +513 -0
- package/src/adapters/solid.d.ts +101 -0
- package/src/adapters/solid.js +591 -0
- package/src/adapters/svelte.d.ts +166 -0
- package/src/adapters/svelte.js +803 -0
- package/src/adapters/vanilla.d.ts +179 -0
- package/src/adapters/vanilla.js +791 -0
- package/src/adapters/vue.d.ts +299 -0
- package/src/adapters/vue.js +570 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 🚀 WU-FRAMEWORK SOLID.JS ADAPTER - TypeScript Declarations
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { WuCore } from '../core/wu-core';
|
|
6
|
+
|
|
7
|
+
// Solid types (generics to avoid hard dependency)
|
|
8
|
+
type Component<P = {}> = (props: P) => any;
|
|
9
|
+
type Accessor<T> = () => T;
|
|
10
|
+
type Setter<T> = (value: T | ((prev: T) => T)) => T;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Opciones de registro Solid
|
|
14
|
+
*/
|
|
15
|
+
export interface SolidRegisterOptions {
|
|
16
|
+
/** Props iniciales */
|
|
17
|
+
props?: Record<string, any>;
|
|
18
|
+
/** Callback después de montar */
|
|
19
|
+
onMount?: (container: HTMLElement) => void;
|
|
20
|
+
/** Callback antes de desmontar */
|
|
21
|
+
onUnmount?: (container: HTMLElement) => void;
|
|
22
|
+
/** Permitir ejecución standalone */
|
|
23
|
+
standalone?: boolean;
|
|
24
|
+
/** Selector para modo standalone */
|
|
25
|
+
standaloneContainer?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Props del componente WuSlot
|
|
30
|
+
*/
|
|
31
|
+
export interface WuSlotProps {
|
|
32
|
+
name: string;
|
|
33
|
+
url: string;
|
|
34
|
+
appName?: string;
|
|
35
|
+
fallback?: string;
|
|
36
|
+
onLoad?: (data: { name: string; url: string }) => void;
|
|
37
|
+
onError?: (error: Error) => void;
|
|
38
|
+
class?: string;
|
|
39
|
+
style?: Record<string, string | number>;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Resultado de createWuStore
|
|
44
|
+
*/
|
|
45
|
+
export type WuStoreResult<T = any> = [
|
|
46
|
+
Accessor<T>,
|
|
47
|
+
(path: string, value: any) => void
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Helper de eventos Wu para Solid
|
|
52
|
+
*/
|
|
53
|
+
export interface UseWuEventsResult {
|
|
54
|
+
emit: (event: string, data?: any, options?: any) => void;
|
|
55
|
+
on: (event: string, callback: (data: any) => void) => () => void;
|
|
56
|
+
once: (event: string, callback: (data: any) => void) => () => void;
|
|
57
|
+
off: (event: string, callback: (data: any) => void) => void;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Contexto de Wu
|
|
62
|
+
*/
|
|
63
|
+
export interface WuContextResult {
|
|
64
|
+
WuProvider: Component<{ children?: any }>;
|
|
65
|
+
useWu: () => WuCore | null;
|
|
66
|
+
WuContext: any;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function register(
|
|
70
|
+
appName: string,
|
|
71
|
+
Component: Component,
|
|
72
|
+
options?: SolidRegisterOptions
|
|
73
|
+
): Promise<boolean>;
|
|
74
|
+
|
|
75
|
+
export function createWuSlot(): Component<WuSlotProps>;
|
|
76
|
+
|
|
77
|
+
export function createWuStore<T = any>(namespace?: string): WuStoreResult<T>;
|
|
78
|
+
|
|
79
|
+
export function createWuEvent<T = any>(eventPattern: string): Accessor<T | null>;
|
|
80
|
+
|
|
81
|
+
export function useWuEvents(): UseWuEventsResult;
|
|
82
|
+
|
|
83
|
+
export function createWuContext(): WuContextResult;
|
|
84
|
+
|
|
85
|
+
export function getWuInstance(): WuCore | null;
|
|
86
|
+
|
|
87
|
+
export function waitForWu(timeout?: number): Promise<WuCore>;
|
|
88
|
+
|
|
89
|
+
export interface WuSolidAdapter {
|
|
90
|
+
register: typeof register;
|
|
91
|
+
createWuSlot: typeof createWuSlot;
|
|
92
|
+
createWuStore: typeof createWuStore;
|
|
93
|
+
createWuEvent: typeof createWuEvent;
|
|
94
|
+
useWuEvents: typeof useWuEvents;
|
|
95
|
+
createWuContext: typeof createWuContext;
|
|
96
|
+
getWuInstance: typeof getWuInstance;
|
|
97
|
+
waitForWu: typeof waitForWu;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export const wuSolid: WuSolidAdapter;
|
|
101
|
+
export default wuSolid;
|
|
@@ -0,0 +1,591 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 🚀 WU-FRAMEWORK SOLID.JS ADAPTER
|
|
3
|
+
*
|
|
4
|
+
* Simplifica la integración de Solid.js con Wu Framework.
|
|
5
|
+
* Aprovecha la reactividad fine-grained de Solid para microfrontends eficientes.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* // Microfrontend (main.jsx)
|
|
9
|
+
* import { wuSolid } from 'wu-framework/adapters/solid';
|
|
10
|
+
* import App from './App';
|
|
11
|
+
*
|
|
12
|
+
* wuSolid.register('my-app', App);
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* // Shell (cargar microfrontend)
|
|
16
|
+
* import { WuSlot } from 'wu-framework/adapters/solid';
|
|
17
|
+
*
|
|
18
|
+
* <WuSlot name="my-app" url="http://localhost:3001" />
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
// Estado global del adapter
|
|
22
|
+
const adapterState = {
|
|
23
|
+
apps: new Map(),
|
|
24
|
+
solid: null,
|
|
25
|
+
solidWeb: null,
|
|
26
|
+
initialized: false
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Detecta y obtiene Solid del contexto global o lo importa
|
|
31
|
+
*/
|
|
32
|
+
async function ensureSolid() {
|
|
33
|
+
if (adapterState.initialized) return true;
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
// Intentar obtener de window
|
|
37
|
+
if (typeof window !== 'undefined' && window.Solid) {
|
|
38
|
+
adapterState.solid = window.Solid;
|
|
39
|
+
adapterState.solidWeb = window.SolidWeb;
|
|
40
|
+
adapterState.initialized = true;
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Intentar import dinámico
|
|
45
|
+
const [solid, solidWeb] = await Promise.all([
|
|
46
|
+
import('solid-js'),
|
|
47
|
+
import('solid-js/web')
|
|
48
|
+
]);
|
|
49
|
+
|
|
50
|
+
adapterState.solid = solid;
|
|
51
|
+
adapterState.solidWeb = solidWeb;
|
|
52
|
+
adapterState.initialized = true;
|
|
53
|
+
return true;
|
|
54
|
+
|
|
55
|
+
} catch (error) {
|
|
56
|
+
console.error('[WuSolid] Failed to load Solid:', error);
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Obtiene la instancia de Wu Framework
|
|
63
|
+
*/
|
|
64
|
+
function getWuInstance() {
|
|
65
|
+
if (typeof window === 'undefined') return null;
|
|
66
|
+
|
|
67
|
+
return window.wu
|
|
68
|
+
|| window.parent?.wu
|
|
69
|
+
|| window.top?.wu
|
|
70
|
+
|| null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Espera a que Wu Framework esté disponible
|
|
75
|
+
*/
|
|
76
|
+
function waitForWu(timeout = 5000) {
|
|
77
|
+
return new Promise((resolve, reject) => {
|
|
78
|
+
const wu = getWuInstance();
|
|
79
|
+
if (wu) {
|
|
80
|
+
resolve(wu);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const startTime = Date.now();
|
|
85
|
+
|
|
86
|
+
const handleWuReady = () => {
|
|
87
|
+
cleanup();
|
|
88
|
+
resolve(getWuInstance());
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
window.addEventListener('wu:ready', handleWuReady);
|
|
92
|
+
window.addEventListener('wu:app:ready', handleWuReady);
|
|
93
|
+
|
|
94
|
+
const checkInterval = setInterval(() => {
|
|
95
|
+
const wu = getWuInstance();
|
|
96
|
+
if (wu) {
|
|
97
|
+
cleanup();
|
|
98
|
+
resolve(wu);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (Date.now() - startTime > timeout) {
|
|
103
|
+
cleanup();
|
|
104
|
+
reject(new Error(`Wu Framework not found after ${timeout}ms`));
|
|
105
|
+
}
|
|
106
|
+
}, 200);
|
|
107
|
+
|
|
108
|
+
function cleanup() {
|
|
109
|
+
clearInterval(checkInterval);
|
|
110
|
+
window.removeEventListener('wu:ready', handleWuReady);
|
|
111
|
+
window.removeEventListener('wu:app:ready', handleWuReady);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Registra un componente Solid como microfrontend
|
|
118
|
+
*
|
|
119
|
+
* @param {string} appName - Nombre único del microfrontend
|
|
120
|
+
* @param {Function} Component - Componente Solid principal
|
|
121
|
+
* @param {Object} options - Opciones adicionales
|
|
122
|
+
* @param {Object} options.props - Props iniciales para el componente
|
|
123
|
+
* @param {Function} options.onMount - Callback después de montar
|
|
124
|
+
* @param {Function} options.onUnmount - Callback antes de desmontar
|
|
125
|
+
* @param {boolean} options.standalone - Permitir ejecución standalone (default: true)
|
|
126
|
+
* @param {string} options.standaloneContainer - Selector para modo standalone (default: '#root')
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* // Básico
|
|
130
|
+
* wuSolid.register('my-app', App);
|
|
131
|
+
*
|
|
132
|
+
* @example
|
|
133
|
+
* // Con props
|
|
134
|
+
* wuSolid.register('my-app', App, {
|
|
135
|
+
* props: { apiUrl: 'https://api.example.com' },
|
|
136
|
+
* onMount: (container) => console.log('Mounted!')
|
|
137
|
+
* });
|
|
138
|
+
*/
|
|
139
|
+
async function register(appName, Component, options = {}) {
|
|
140
|
+
const {
|
|
141
|
+
props = {},
|
|
142
|
+
onMount = null,
|
|
143
|
+
onUnmount = null,
|
|
144
|
+
standalone = true,
|
|
145
|
+
standaloneContainer = '#root'
|
|
146
|
+
} = options;
|
|
147
|
+
|
|
148
|
+
// Asegurar que Solid está disponible
|
|
149
|
+
const hasSolid = await ensureSolid();
|
|
150
|
+
if (!hasSolid) {
|
|
151
|
+
console.error(`[WuSolid] Cannot register ${appName}: Solid not available`);
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const { render } = adapterState.solidWeb;
|
|
156
|
+
|
|
157
|
+
let disposeApp = null;
|
|
158
|
+
|
|
159
|
+
// Función de mount interna
|
|
160
|
+
const mountApp = (container) => {
|
|
161
|
+
if (!container) {
|
|
162
|
+
console.error(`[WuSolid] Mount failed for ${appName}: container is null`);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Evitar doble mount
|
|
167
|
+
if (adapterState.apps.has(appName)) {
|
|
168
|
+
console.warn(`[WuSolid] ${appName} already mounted, unmounting first`);
|
|
169
|
+
unmountApp();
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
try {
|
|
173
|
+
// Limpiar container
|
|
174
|
+
container.innerHTML = '';
|
|
175
|
+
|
|
176
|
+
// Renderizar componente Solid
|
|
177
|
+
// render() retorna una función dispose
|
|
178
|
+
disposeApp = render(
|
|
179
|
+
() => Component({
|
|
180
|
+
...props,
|
|
181
|
+
wuAppName: appName,
|
|
182
|
+
wuInstance: getWuInstance()
|
|
183
|
+
}),
|
|
184
|
+
container
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
// Guardar referencia
|
|
188
|
+
adapterState.apps.set(appName, {
|
|
189
|
+
container,
|
|
190
|
+
Component,
|
|
191
|
+
dispose: disposeApp
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
console.log(`[WuSolid] ✅ ${appName} mounted successfully`);
|
|
195
|
+
|
|
196
|
+
if (onMount) {
|
|
197
|
+
onMount(container);
|
|
198
|
+
}
|
|
199
|
+
} catch (error) {
|
|
200
|
+
console.error(`[WuSolid] Mount error for ${appName}:`, error);
|
|
201
|
+
throw error;
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
// Función de unmount interna
|
|
206
|
+
const unmountApp = (container) => {
|
|
207
|
+
const appData = adapterState.apps.get(appName);
|
|
208
|
+
|
|
209
|
+
if (appData) {
|
|
210
|
+
try {
|
|
211
|
+
if (onUnmount) {
|
|
212
|
+
onUnmount(appData.container);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Dispose de Solid (limpia todas las reactividades)
|
|
216
|
+
if (appData.dispose && typeof appData.dispose === 'function') {
|
|
217
|
+
appData.dispose();
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Limpiar DOM
|
|
221
|
+
appData.container.innerHTML = '';
|
|
222
|
+
|
|
223
|
+
adapterState.apps.delete(appName);
|
|
224
|
+
|
|
225
|
+
console.log(`[WuSolid] ✅ ${appName} unmounted successfully`);
|
|
226
|
+
} catch (error) {
|
|
227
|
+
console.error(`[WuSolid] Unmount error for ${appName}:`, error);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (container) {
|
|
232
|
+
container.innerHTML = '';
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
// Intentar registrar con Wu Framework
|
|
237
|
+
try {
|
|
238
|
+
const wu = await waitForWu(3000);
|
|
239
|
+
|
|
240
|
+
wu.define(appName, {
|
|
241
|
+
mount: mountApp,
|
|
242
|
+
unmount: unmountApp
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
console.log(`[WuSolid] ✅ ${appName} registered with Wu Framework`);
|
|
246
|
+
return true;
|
|
247
|
+
|
|
248
|
+
} catch (error) {
|
|
249
|
+
console.warn(`[WuSolid] Wu Framework not available for ${appName}`);
|
|
250
|
+
|
|
251
|
+
if (standalone) {
|
|
252
|
+
const containerElement = document.querySelector(standaloneContainer);
|
|
253
|
+
|
|
254
|
+
if (containerElement) {
|
|
255
|
+
console.log(`[WuSolid] Running ${appName} in standalone mode`);
|
|
256
|
+
mountApp(containerElement);
|
|
257
|
+
return true;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return false;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Crea un componente WuSlot para Solid
|
|
267
|
+
*
|
|
268
|
+
* @example
|
|
269
|
+
* import { WuSlot } from 'wu-framework/adapters/solid';
|
|
270
|
+
*
|
|
271
|
+
* function Shell() {
|
|
272
|
+
* return (
|
|
273
|
+
* <div>
|
|
274
|
+
* <WuSlot name="header" url="http://localhost:3001" />
|
|
275
|
+
* <WuSlot name="content" url="http://localhost:3002" />
|
|
276
|
+
* </div>
|
|
277
|
+
* );
|
|
278
|
+
* }
|
|
279
|
+
*/
|
|
280
|
+
function createWuSlot() {
|
|
281
|
+
// Esta función debe ser llamada dentro del contexto de Solid
|
|
282
|
+
return async function WuSlot(props) {
|
|
283
|
+
const {
|
|
284
|
+
name,
|
|
285
|
+
url,
|
|
286
|
+
appName = null,
|
|
287
|
+
fallback = null,
|
|
288
|
+
onLoad = null,
|
|
289
|
+
onError = null,
|
|
290
|
+
class: className = '',
|
|
291
|
+
style = {}
|
|
292
|
+
} = props;
|
|
293
|
+
|
|
294
|
+
const { createSignal, onMount, onCleanup } = adapterState.solid;
|
|
295
|
+
|
|
296
|
+
const [loading, setLoading] = createSignal(true);
|
|
297
|
+
const [error, setError] = createSignal(null);
|
|
298
|
+
|
|
299
|
+
let containerRef;
|
|
300
|
+
let appInstance = null;
|
|
301
|
+
|
|
302
|
+
const actualAppName = appName || name;
|
|
303
|
+
|
|
304
|
+
onMount(async () => {
|
|
305
|
+
try {
|
|
306
|
+
const wu = getWuInstance();
|
|
307
|
+
if (!wu) throw new Error('Wu Framework not initialized');
|
|
308
|
+
|
|
309
|
+
const containerId = `wu-slot-${actualAppName}-${Date.now()}`;
|
|
310
|
+
const innerContainer = document.createElement('div');
|
|
311
|
+
innerContainer.id = containerId;
|
|
312
|
+
innerContainer.style.cssText = 'width: 100%; height: 100%;';
|
|
313
|
+
|
|
314
|
+
containerRef.innerHTML = '';
|
|
315
|
+
containerRef.appendChild(innerContainer);
|
|
316
|
+
|
|
317
|
+
const app = wu.app(actualAppName, {
|
|
318
|
+
url,
|
|
319
|
+
container: `#${containerId}`,
|
|
320
|
+
autoInit: true
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
appInstance = app;
|
|
324
|
+
await app.mount();
|
|
325
|
+
|
|
326
|
+
setLoading(false);
|
|
327
|
+
if (onLoad) onLoad({ name: actualAppName, url });
|
|
328
|
+
|
|
329
|
+
} catch (err) {
|
|
330
|
+
console.error(`[WuSlot] Error loading ${actualAppName}:`, err);
|
|
331
|
+
setError(err.message || 'Failed to load microfrontend');
|
|
332
|
+
setLoading(false);
|
|
333
|
+
if (onError) onError(err);
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
onCleanup(async () => {
|
|
338
|
+
if (appInstance) {
|
|
339
|
+
try {
|
|
340
|
+
await appInstance.unmount();
|
|
341
|
+
} catch (e) {}
|
|
342
|
+
appInstance = null;
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
// Retornar JSX de Solid
|
|
347
|
+
return (() => {
|
|
348
|
+
const el = document.createElement('div');
|
|
349
|
+
el.className = `wu-slot ${loading() ? 'wu-slot-loading' : ''} ${error() ? 'wu-slot-error' : ''} ${className}`;
|
|
350
|
+
el.style.cssText = 'min-height: 100px; position: relative;';
|
|
351
|
+
el.setAttribute('data-wu-app', actualAppName);
|
|
352
|
+
el.setAttribute('data-wu-url', url);
|
|
353
|
+
|
|
354
|
+
Object.assign(el.style, style);
|
|
355
|
+
|
|
356
|
+
containerRef = el;
|
|
357
|
+
|
|
358
|
+
if (error()) {
|
|
359
|
+
el.innerHTML = `
|
|
360
|
+
<div style="padding: 1rem; border: 1px solid #f5c6cb; border-radius: 4px; background: #f8d7da; color: #721c24;">
|
|
361
|
+
<strong>Error loading ${name}</strong>
|
|
362
|
+
<p style="margin: 0.5rem 0 0 0;">${error()}</p>
|
|
363
|
+
</div>
|
|
364
|
+
`;
|
|
365
|
+
} else if (loading()) {
|
|
366
|
+
el.innerHTML = fallback || `
|
|
367
|
+
<div style="display: flex; align-items: center; justify-content: center; padding: 2rem; color: #666;">
|
|
368
|
+
Loading ${name}...
|
|
369
|
+
</div>
|
|
370
|
+
`;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
return el;
|
|
374
|
+
})();
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Crea un store de Wu compatible con la reactividad de Solid
|
|
380
|
+
*
|
|
381
|
+
* @param {string} namespace - Namespace en el store de Wu
|
|
382
|
+
* @returns {Array} [state, setState] similar a createSignal
|
|
383
|
+
*
|
|
384
|
+
* @example
|
|
385
|
+
* import { createWuStore } from 'wu-framework/adapters/solid';
|
|
386
|
+
*
|
|
387
|
+
* function MyComponent() {
|
|
388
|
+
* const [user, setUser] = createWuStore('user');
|
|
389
|
+
*
|
|
390
|
+
* return (
|
|
391
|
+
* <div>
|
|
392
|
+
* <p>Name: {user()?.name}</p>
|
|
393
|
+
* <button onClick={() => setUser('name', 'John')}>
|
|
394
|
+
* Set Name
|
|
395
|
+
* </button>
|
|
396
|
+
* </div>
|
|
397
|
+
* );
|
|
398
|
+
* }
|
|
399
|
+
*/
|
|
400
|
+
function createWuStore(namespace = '') {
|
|
401
|
+
const { createSignal, onCleanup } = adapterState.solid;
|
|
402
|
+
|
|
403
|
+
const wu = getWuInstance();
|
|
404
|
+
const initialValue = wu?.store?.get(namespace) || null;
|
|
405
|
+
|
|
406
|
+
const [state, setState] = createSignal(initialValue);
|
|
407
|
+
|
|
408
|
+
// Suscribirse a cambios en Wu Store
|
|
409
|
+
if (wu?.store) {
|
|
410
|
+
const pattern = namespace ? `${namespace}.*` : '*';
|
|
411
|
+
const unsubscribe = wu.store.on(pattern, () => {
|
|
412
|
+
setState(wu.store.get(namespace));
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
onCleanup(unsubscribe);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// Función para actualizar el store
|
|
419
|
+
const setWuState = (path, value) => {
|
|
420
|
+
if (wu?.store) {
|
|
421
|
+
const fullPath = namespace ? `${namespace}.${path}` : path;
|
|
422
|
+
wu.store.set(fullPath, value);
|
|
423
|
+
}
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
return [state, setWuState];
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* Crea un signal reactivo basado en eventos de Wu
|
|
431
|
+
*
|
|
432
|
+
* @param {string} eventPattern - Patrón de eventos
|
|
433
|
+
* @returns {Function} Signal con el último evento
|
|
434
|
+
*
|
|
435
|
+
* @example
|
|
436
|
+
* import { createWuEvent } from 'wu-framework/adapters/solid';
|
|
437
|
+
*
|
|
438
|
+
* function MyComponent() {
|
|
439
|
+
* const lastUserEvent = createWuEvent('user:*');
|
|
440
|
+
*
|
|
441
|
+
* return (
|
|
442
|
+
* <Show when={lastUserEvent()}>
|
|
443
|
+
* <p>Last event: {lastUserEvent()?.name}</p>
|
|
444
|
+
* </Show>
|
|
445
|
+
* );
|
|
446
|
+
* }
|
|
447
|
+
*/
|
|
448
|
+
function createWuEvent(eventPattern) {
|
|
449
|
+
const { createSignal, onCleanup } = adapterState.solid;
|
|
450
|
+
|
|
451
|
+
const [event, setEvent] = createSignal(null);
|
|
452
|
+
|
|
453
|
+
const wu = getWuInstance();
|
|
454
|
+
if (wu?.eventBus) {
|
|
455
|
+
const unsubscribe = wu.eventBus.on(eventPattern, (e) => {
|
|
456
|
+
setEvent(e);
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
onCleanup(unsubscribe);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
return event;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* Hook para usar el EventBus de Wu Framework en Solid
|
|
467
|
+
*
|
|
468
|
+
* @example
|
|
469
|
+
* import { useWuEvents } from 'wu-framework/adapters/solid';
|
|
470
|
+
*
|
|
471
|
+
* function MyComponent() {
|
|
472
|
+
* const { emit, on } = useWuEvents();
|
|
473
|
+
*
|
|
474
|
+
* onMount(() => {
|
|
475
|
+
* on('user:login', (data) => console.log('User logged in:', data));
|
|
476
|
+
* });
|
|
477
|
+
*
|
|
478
|
+
* return (
|
|
479
|
+
* <button onClick={() => emit('user:logout', { reason: 'manual' })}>
|
|
480
|
+
* Logout
|
|
481
|
+
* </button>
|
|
482
|
+
* );
|
|
483
|
+
* }
|
|
484
|
+
*/
|
|
485
|
+
function useWuEvents() {
|
|
486
|
+
const { onCleanup } = adapterState.solid;
|
|
487
|
+
const subscriptions = [];
|
|
488
|
+
|
|
489
|
+
const emit = (event, data, options) => {
|
|
490
|
+
const wu = getWuInstance();
|
|
491
|
+
if (wu?.eventBus) {
|
|
492
|
+
wu.eventBus.emit(event, data, options);
|
|
493
|
+
}
|
|
494
|
+
};
|
|
495
|
+
|
|
496
|
+
const on = (event, callback) => {
|
|
497
|
+
const wu = getWuInstance();
|
|
498
|
+
if (wu?.eventBus) {
|
|
499
|
+
const unsubscribe = wu.eventBus.on(event, callback);
|
|
500
|
+
subscriptions.push(unsubscribe);
|
|
501
|
+
return unsubscribe;
|
|
502
|
+
}
|
|
503
|
+
return () => {};
|
|
504
|
+
};
|
|
505
|
+
|
|
506
|
+
const once = (event, callback) => {
|
|
507
|
+
const wu = getWuInstance();
|
|
508
|
+
if (wu?.eventBus) {
|
|
509
|
+
return wu.eventBus.once(event, callback);
|
|
510
|
+
}
|
|
511
|
+
return () => {};
|
|
512
|
+
};
|
|
513
|
+
|
|
514
|
+
const off = (event, callback) => {
|
|
515
|
+
const wu = getWuInstance();
|
|
516
|
+
if (wu?.eventBus) {
|
|
517
|
+
wu.eventBus.off(event, callback);
|
|
518
|
+
}
|
|
519
|
+
};
|
|
520
|
+
|
|
521
|
+
// Cleanup automático
|
|
522
|
+
onCleanup(() => {
|
|
523
|
+
subscriptions.forEach(unsub => unsub());
|
|
524
|
+
});
|
|
525
|
+
|
|
526
|
+
return { emit, on, once, off };
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
/**
|
|
530
|
+
* Contexto de Wu para Solid
|
|
531
|
+
* Permite acceder a Wu desde cualquier componente hijo
|
|
532
|
+
*
|
|
533
|
+
* @example
|
|
534
|
+
* import { WuProvider, useWu } from 'wu-framework/adapters/solid';
|
|
535
|
+
*
|
|
536
|
+
* // En el root
|
|
537
|
+
* <WuProvider>
|
|
538
|
+
* <App />
|
|
539
|
+
* </WuProvider>
|
|
540
|
+
*
|
|
541
|
+
* // En cualquier componente hijo
|
|
542
|
+
* function MyComponent() {
|
|
543
|
+
* const wu = useWu();
|
|
544
|
+
* // ...
|
|
545
|
+
* }
|
|
546
|
+
*/
|
|
547
|
+
function createWuContext() {
|
|
548
|
+
const { createContext, useContext } = adapterState.solid;
|
|
549
|
+
|
|
550
|
+
const WuContext = createContext(null);
|
|
551
|
+
|
|
552
|
+
function WuProvider(props) {
|
|
553
|
+
const wu = getWuInstance();
|
|
554
|
+
return WuContext.Provider({
|
|
555
|
+
value: wu,
|
|
556
|
+
children: props.children
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
function useWu() {
|
|
561
|
+
return useContext(WuContext) || getWuInstance();
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
return { WuProvider, useWu, WuContext };
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
// API pública del adapter
|
|
568
|
+
export const wuSolid = {
|
|
569
|
+
register,
|
|
570
|
+
createWuSlot,
|
|
571
|
+
createWuStore,
|
|
572
|
+
createWuEvent,
|
|
573
|
+
useWuEvents,
|
|
574
|
+
createWuContext,
|
|
575
|
+
getWuInstance,
|
|
576
|
+
waitForWu
|
|
577
|
+
};
|
|
578
|
+
|
|
579
|
+
// Named exports
|
|
580
|
+
export {
|
|
581
|
+
register,
|
|
582
|
+
createWuSlot,
|
|
583
|
+
createWuStore,
|
|
584
|
+
createWuEvent,
|
|
585
|
+
useWuEvents,
|
|
586
|
+
createWuContext,
|
|
587
|
+
getWuInstance,
|
|
588
|
+
waitForWu
|
|
589
|
+
};
|
|
590
|
+
|
|
591
|
+
export default wuSolid;
|