@decido/shell-vscode-core 4.0.3 → 4.0.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.
- package/dist/index.js +20 -1985
- package/dist/index.mjs +20 -1918
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,1866 +1,44 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __export = (target, all) => {
|
|
9
|
-
for (var name in all)
|
|
10
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
-
};
|
|
12
|
-
var __copyProps = (to, from, except, desc) => {
|
|
13
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
-
for (let key of __getOwnPropNames(from))
|
|
15
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
-
}
|
|
18
|
-
return to;
|
|
19
|
-
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
-
|
|
30
|
-
// src/index.ts
|
|
31
|
-
var index_exports = {};
|
|
32
|
-
__export(index_exports, {
|
|
33
|
-
ApiService: () => ApiService,
|
|
34
|
-
AuthService: () => AuthService,
|
|
35
|
-
BaseService: () => BaseService,
|
|
36
|
-
CORE_HOOK_NAMES: () => CORE_HOOK_NAMES,
|
|
37
|
-
CORE_SLOT_NAMES: () => CORE_SLOT_NAMES,
|
|
38
|
-
CalendarService: () => CalendarService,
|
|
39
|
-
CommandService: () => CommandService,
|
|
40
|
-
DebugService: () => DebugService,
|
|
41
|
-
DecidoDB: () => DecidoDB,
|
|
42
|
-
GamificationService: () => GamificationService,
|
|
43
|
-
HookService: () => HookService,
|
|
44
|
-
ModalService: () => ModalService,
|
|
45
|
-
ModuleManager: () => ModuleManager,
|
|
46
|
-
NotificationService: () => NotificationService,
|
|
47
|
-
RouterService: () => RouterService,
|
|
48
|
-
ServiceContainer: () => ServiceContainer,
|
|
49
|
-
ShortcutService: () => ShortcutService,
|
|
50
|
-
StorageService: () => StorageService,
|
|
51
|
-
SyncService: () => SyncService,
|
|
52
|
-
ThemeService: () => ThemeService,
|
|
53
|
-
apiService: () => apiService,
|
|
54
|
-
authService: () => authService,
|
|
55
|
-
createEffect: () => createEffect,
|
|
56
|
-
createMemo: () => createMemo,
|
|
57
|
-
createPlatformAPI: () => createPlatformAPI,
|
|
58
|
-
createSignal: () => createSignal,
|
|
59
|
-
db: () => db,
|
|
60
|
-
formatDate: () => formatDate,
|
|
61
|
-
html: () => html,
|
|
62
|
-
initEventListeners: () => initEventListeners,
|
|
63
|
-
makeDraggable: () => makeDraggable,
|
|
64
|
-
processModuleDefinitions: () => processModuleDefinitions,
|
|
65
|
-
registerCoreCommands: () => registerCoreCommands,
|
|
66
|
-
routerService: () => routerService,
|
|
67
|
-
storageService: () => storageService,
|
|
68
|
-
syncService: () => syncService,
|
|
69
|
-
themeService: () => themeService
|
|
70
|
-
});
|
|
71
|
-
module.exports = __toCommonJS(index_exports);
|
|
72
|
-
|
|
73
|
-
// src/core/ServiceContainer.ts
|
|
74
|
-
var ServiceContainer = class {
|
|
75
|
-
services = /* @__PURE__ */ new Map();
|
|
76
|
-
/**
|
|
77
|
-
* Registra una instancia de un servicio.
|
|
78
|
-
* El tipo es validado contra el `ServiceRegistry`.
|
|
79
|
-
*/
|
|
80
|
-
register(key, instance) {
|
|
81
|
-
if (this.services.has(key)) {
|
|
82
|
-
console.warn(`[ServiceContainer] El servicio '${key}' ya est\xE1 registrado. Se sobrescribir\xE1.`);
|
|
83
|
-
}
|
|
84
|
-
this.services.set(key, instance);
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Obtiene la instancia de un servicio registrado.
|
|
88
|
-
* El tipo de retorno es inferido automáticamente a partir de la clave.
|
|
89
|
-
*/
|
|
90
|
-
get(key) {
|
|
91
|
-
const service = this.services.get(key);
|
|
92
|
-
if (!service) {
|
|
93
|
-
throw new Error(`[ServiceContainer] No se encontr\xF3 servicio registrado con la clave: ${key}`);
|
|
94
|
-
}
|
|
95
|
-
return service;
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
// src/core/app/ModuleManager.ts
|
|
100
|
-
var import_react = __toESM(require("react"));
|
|
101
|
-
var ModuleManager = class {
|
|
102
|
-
api;
|
|
103
|
-
container;
|
|
104
|
-
modules = /* @__PURE__ */ new Map();
|
|
105
|
-
activatedModules = /* @__PURE__ */ new Set();
|
|
106
|
-
// Un mapa para saber qué módulo provee qué servicio.
|
|
107
|
-
serviceProviderMap = /* @__PURE__ */ new Map();
|
|
108
|
-
// private coreModuleImporter: ModuleImporterFn | null = null;
|
|
109
|
-
constructor(api, container) {
|
|
110
|
-
this.api = api;
|
|
111
|
-
this.container = container;
|
|
112
|
-
}
|
|
113
|
-
/**
|
|
114
|
-
* FASE 1: Procesa los manifiestos de todos los módulos disponibles.
|
|
115
|
-
* @param moduleDefs Un array de objetos con el id del módulo y su manifiesto.
|
|
116
|
-
*/
|
|
117
|
-
// public async processManifests(moduleDefs: { id: string, manifest: any, path: string }[]) {
|
|
118
|
-
// for (const def of moduleDefs) {
|
|
119
|
-
// this.modules.set(def.id, { ...def });
|
|
120
|
-
// console.log(`[Manifest] Procesando contribuciones para '${def.id}'`);
|
|
121
|
-
// this.registerStaticContributions(def.manifest);
|
|
122
|
-
// }
|
|
123
|
-
// }
|
|
124
|
-
async registerModules(moduleDefs) {
|
|
125
|
-
for (const def of moduleDefs) {
|
|
126
|
-
if (this.modules.has(def.id)) {
|
|
127
|
-
console.warn(`[ModuleManager] El m\xF3dulo '${def.id}' ya est\xE1 registrado. Omitiendo duplicado.`);
|
|
128
|
-
continue;
|
|
129
|
-
}
|
|
130
|
-
this.modules.set(def.id, def);
|
|
131
|
-
console.log(`[Manifest] Registrando contribuciones para '${def.id}'`);
|
|
132
|
-
this.registerStaticContributions(def.manifest);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* NUEVO MÉTODO: Este es el "puerto de carga". La aplicación llamará a este método
|
|
137
|
-
* para darle al ModuleManager la capacidad de cargar módulos del núcleo.
|
|
138
|
-
*/
|
|
139
|
-
// public setCoreModuleImporter(importer: ModuleImporterFn) {
|
|
140
|
-
// this.coreModuleImporter = importer;
|
|
141
|
-
// }
|
|
142
|
-
/**
|
|
143
|
-
* Lee la sección `contributes` y registra "placeholders" para la UI.
|
|
144
|
-
* Estos placeholders activarán el módulo cuando se interactúe con ellos.
|
|
145
|
-
*/
|
|
146
|
-
registerStaticContributions(manifest) {
|
|
147
|
-
const moduleId = manifest.name;
|
|
148
|
-
if (!moduleId || !manifest.contributes) return;
|
|
149
|
-
const contributions = manifest.contributes;
|
|
150
|
-
manifest.provides?.forEach((serviceKey) => {
|
|
151
|
-
this.serviceProviderMap.set(serviceKey, moduleId);
|
|
152
|
-
});
|
|
153
|
-
contributions.commands?.forEach((cmd) => {
|
|
154
|
-
this.api.commands.register({
|
|
155
|
-
...cmd,
|
|
156
|
-
execute: (api, args) => this.activateAndExecute(moduleId, cmd.id, args)
|
|
157
|
-
});
|
|
158
|
-
});
|
|
159
|
-
contributions.sidebarViews?.forEach((view) => {
|
|
160
|
-
if (this.api.layout.registerSidebarView) {
|
|
161
|
-
const LazyLoader = this.createLazyModuleView(moduleId, view.title);
|
|
162
|
-
this.api.layout.registerSidebarView({
|
|
163
|
-
...view,
|
|
164
|
-
// Si el view ya traía component (definido estáticamente?), lo usamos, si no, Lazy
|
|
165
|
-
// Normalmente JSON no trae component.
|
|
166
|
-
component: LazyLoader
|
|
167
|
-
});
|
|
168
|
-
} else if (view.render) {
|
|
169
|
-
this.api.layout.registerSidebarView({
|
|
170
|
-
...view,
|
|
171
|
-
render: (container) => {
|
|
172
|
-
container.innerHTML = `<div class="p-4 text-center text-muted-foreground">Cargando ${view.title}...</div>`;
|
|
173
|
-
this.activateModule(moduleId).then(() => {
|
|
174
|
-
this.api.layout.renderSidebar();
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
});
|
|
180
|
-
contributions.activityBar?.forEach((item) => {
|
|
181
|
-
this.api.layout.registerActivityBarItem({
|
|
182
|
-
...item
|
|
183
|
-
});
|
|
184
|
-
});
|
|
185
|
-
contributions.panelViews?.forEach((view) => {
|
|
186
|
-
if (this.api.layout.registerPanelView && this.createLazyModuleView) {
|
|
187
|
-
const LazyLoader = this.createLazyModuleView(moduleId, view.title);
|
|
188
|
-
this.api.layout.registerPanelView({
|
|
189
|
-
...view,
|
|
190
|
-
component: LazyLoader
|
|
191
|
-
});
|
|
192
|
-
} else if (view.render) {
|
|
193
|
-
this.api.layout.registerPanelView({
|
|
194
|
-
...view,
|
|
195
|
-
render: (container) => {
|
|
196
|
-
container.innerHTML = `<div class="p-4 text-center text-muted-foreground">Cargando ${view.title}...</div>`;
|
|
197
|
-
this.activateModule(moduleId).then(() => {
|
|
198
|
-
this.api.layout.renderPanel();
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
|
-
});
|
|
202
|
-
}
|
|
203
|
-
});
|
|
204
|
-
contributions.topBarItems?.forEach((item) => {
|
|
205
|
-
this.api.layout.registerTopBarItem(item);
|
|
206
|
-
});
|
|
207
|
-
contributions.statusBarItems?.forEach((item) => {
|
|
208
|
-
this.api.layout.registerStatusBarItem(item);
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
/**
|
|
212
|
-
* FASE 2: Activa un módulo (carga su código y ejecuta `activate`).
|
|
213
|
-
* @param moduleId El ID del módulo a activar (ej: 'decido.projects').
|
|
214
|
-
*/
|
|
215
|
-
async activateModule(moduleId) {
|
|
216
|
-
if (this.activatedModules.has(moduleId)) {
|
|
217
|
-
return;
|
|
218
|
-
}
|
|
219
|
-
const moduleDef = this.modules.get(moduleId);
|
|
220
|
-
if (!moduleDef) {
|
|
221
|
-
throw new Error(`Intento de activar un m\xF3dulo no registrado: ${moduleId}`);
|
|
222
|
-
}
|
|
223
|
-
console.log(`\u{1F680} Activando m\xF3dulo del n\xFAcleo '${moduleId}'...`);
|
|
224
|
-
try {
|
|
225
|
-
const module2 = await moduleDef.importer();
|
|
226
|
-
if (module2.activate && typeof module2.activate === "function") {
|
|
227
|
-
await module2.activate(this.api);
|
|
228
|
-
this.activatedModules.add(moduleId);
|
|
229
|
-
console.log(`\u2705 M\xF3dulo '${moduleId}' activado con \xE9xito.`);
|
|
230
|
-
} else {
|
|
231
|
-
throw new Error(`El m\xF3dulo no tiene una funci\xF3n de exportaci\xF3n 'activate' v\xE1lida.`);
|
|
232
|
-
}
|
|
233
|
-
} catch (error) {
|
|
234
|
-
console.error(`\u274C Fallo al activar el m\xF3dulo '${moduleId}':`, error);
|
|
235
|
-
this.api.notifications.show("error", `Fallo al activar: ${moduleId}`, error.message);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
async loadExternalModules(moduleDefs) {
|
|
239
|
-
for (const def of moduleDefs) {
|
|
240
|
-
if (this.activatedModules.has(def.id)) {
|
|
241
|
-
continue;
|
|
242
|
-
}
|
|
243
|
-
console.log(`\u{1F50C} Cargando m\xF3dulo externo '${def.id}' desde '${def.path}'`);
|
|
244
|
-
try {
|
|
245
|
-
const moduleUrl = `${window.location.origin}${def.path}/index.js`;
|
|
246
|
-
const module2 = await import(
|
|
247
|
-
/* @vite-ignore */
|
|
248
|
-
moduleUrl
|
|
249
|
-
);
|
|
250
|
-
if (module2.activate && typeof module2.activate === "function") {
|
|
251
|
-
await module2.activate(this.api);
|
|
252
|
-
this.activatedModules.add(def.id);
|
|
253
|
-
console.log(`\u2705 M\xF3dulo externo '${def.id}' activado.`);
|
|
254
|
-
} else {
|
|
255
|
-
throw new Error(`El m\xF3dulo externo no exporta una funci\xF3n 'activate'.`);
|
|
256
|
-
}
|
|
257
|
-
} catch (error) {
|
|
258
|
-
console.error(`\u274C Fallo al cargar el m\xF3dulo externo '${def.id}':`, error);
|
|
259
|
-
this.api.notifications.show("error", `Fallo de M\xF3dulo Externo`, error.message);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
/**
|
|
264
|
-
* Devuelve el ID del módulo que provee un servicio específico.
|
|
265
|
-
*/
|
|
266
|
-
getModuleIdForService(serviceKey) {
|
|
267
|
-
return this.serviceProviderMap.get(serviceKey);
|
|
268
|
-
}
|
|
269
|
-
/**
|
|
270
|
-
* Una función de ayuda que asegura la activación de un módulo antes de ejecutar un comando.
|
|
271
|
-
*/
|
|
272
|
-
async activateAndExecute(moduleId, commandId, args) {
|
|
273
|
-
await this.activateModule(moduleId);
|
|
274
|
-
this.api.commands.execute(commandId, args);
|
|
275
|
-
}
|
|
276
|
-
/**
|
|
277
|
-
* Crea un componente React que activa el módulo al montarse.
|
|
278
|
-
*/
|
|
279
|
-
createLazyModuleView(moduleId, title) {
|
|
280
|
-
return () => {
|
|
281
|
-
(0, import_react.useEffect)(() => {
|
|
282
|
-
this.activateModule(moduleId).catch((err) => console.error("Lazy Load failed", err));
|
|
283
|
-
}, []);
|
|
284
|
-
return import_react.default.createElement(
|
|
285
|
-
"div",
|
|
286
|
-
{ className: "flex items-center justify-center h-full text-muted-foreground" },
|
|
287
|
-
`Cargando m\xF3dulo: ${title}...`
|
|
288
|
-
);
|
|
289
|
-
};
|
|
290
|
-
}
|
|
291
|
-
};
|
|
292
|
-
|
|
293
|
-
// src/core/EventBus.ts
|
|
294
|
-
var EventBus = class {
|
|
295
|
-
events;
|
|
296
|
-
spy = null;
|
|
297
|
-
constructor() {
|
|
298
|
-
this.events = /* @__PURE__ */ new Map();
|
|
299
|
-
}
|
|
300
|
-
/**
|
|
301
|
-
* Se suscribe a un evento.
|
|
302
|
-
* @param eventName El nombre del evento (e.g., 'app:ready', 'view:changed').
|
|
303
|
-
* @param handler La función a ejecutar cuando el evento se emita.
|
|
304
|
-
*/
|
|
305
|
-
on(eventName, handler) {
|
|
306
|
-
if (!this.events.has(eventName)) {
|
|
307
|
-
this.events.set(eventName, /* @__PURE__ */ new Set());
|
|
308
|
-
}
|
|
309
|
-
this.events.get(eventName).add(handler);
|
|
310
|
-
}
|
|
311
|
-
/**
|
|
312
|
-
* Se desuscribe de un evento.
|
|
313
|
-
* @param eventName El nombre del evento.
|
|
314
|
-
* @param handler La función a remover.
|
|
315
|
-
*/
|
|
316
|
-
off(eventName, handler) {
|
|
317
|
-
const handlers = this.events.get(eventName);
|
|
318
|
-
if (handlers) {
|
|
319
|
-
handlers.delete(handler);
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
/**
|
|
323
|
-
* Emite un evento, llamando a todos los suscriptores.
|
|
324
|
-
* @param eventName El nombre del evento a emitir.
|
|
325
|
-
* @param data Datos opcionales para pasar a los manejadores.
|
|
326
|
-
*/
|
|
327
|
-
emit(eventName, data) {
|
|
328
|
-
const handlers = this.events.get(eventName);
|
|
329
|
-
if (handlers) {
|
|
330
|
-
handlers.forEach((handler) => handler(data));
|
|
331
|
-
}
|
|
332
|
-
if (this.spy) {
|
|
333
|
-
this.spy(eventName, data);
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
/**
|
|
337
|
-
* Registra una única función que recibirá TODOS los eventos emitidos.
|
|
338
|
-
* @param handler La función espía.
|
|
339
|
-
*/
|
|
340
|
-
spyOn(handler) {
|
|
341
|
-
this.spy = handler;
|
|
342
|
-
}
|
|
343
|
-
};
|
|
344
|
-
|
|
345
|
-
// src/core/CommandService.ts
|
|
346
|
-
var CommandService = class {
|
|
347
|
-
commands = /* @__PURE__ */ new Map();
|
|
348
|
-
api;
|
|
349
|
-
spy = null;
|
|
350
|
-
constructor() {
|
|
351
|
-
}
|
|
352
|
-
register(command) {
|
|
353
|
-
if (this.commands.has(command.id)) {
|
|
354
|
-
console.warn(`[CommandService] El comando "${command.id}" ya est\xE1 registrado. Se sobrescribir\xE1.`);
|
|
355
|
-
}
|
|
356
|
-
this.commands.set(command.id, command);
|
|
357
|
-
}
|
|
358
|
-
execute(commandId, arg, callerId) {
|
|
359
|
-
const command = this.commands.get(commandId);
|
|
360
|
-
if (command) {
|
|
361
|
-
try {
|
|
362
|
-
const targetServiceId = `svc:${command.id.split(".")[0]}Service`;
|
|
363
|
-
const startTime = performance.now();
|
|
364
|
-
command.execute(this.api, arg);
|
|
365
|
-
const endTime = performance.now();
|
|
366
|
-
const duration = (endTime - startTime).toFixed(2);
|
|
367
|
-
this.api.debug?.probe(targetServiceId, "active", {
|
|
368
|
-
sourceNodeId: callerId,
|
|
369
|
-
command: commandId,
|
|
370
|
-
// <-- PASAMOS LA FUENTE
|
|
371
|
-
duration: `${duration} ms`
|
|
372
|
-
// <-- AÑADE LA MÉTRICA
|
|
373
|
-
});
|
|
374
|
-
this.api.events.emit(`command:${commandId}:executed`, { arg });
|
|
375
|
-
} catch (error) {
|
|
376
|
-
console.error(`Error ejecutando el comando "${commandId}":`, error);
|
|
377
|
-
this.api.notifications.show("error", "Error de Comando", `No se pudo ejecutar "${command.title}".`);
|
|
378
|
-
}
|
|
379
|
-
} else {
|
|
380
|
-
console.error(`[CommandService] Intento de ejecutar un comando no registrado: "${commandId}"`);
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
getAll() {
|
|
384
|
-
return Array.from(this.commands.values());
|
|
385
|
-
}
|
|
386
|
-
/**
|
|
387
|
-
* Registra una única función que recibirá TODOS los eventos emitidos.
|
|
388
|
-
* @param handler La función espía.
|
|
389
|
-
*/
|
|
390
|
-
spyOn(handler) {
|
|
391
|
-
this.spy = handler;
|
|
392
|
-
}
|
|
393
|
-
};
|
|
394
|
-
|
|
395
|
-
// src/utils.ts
|
|
396
|
-
function formatDate(dateString) {
|
|
397
|
-
if (!dateString) return "Sin fecha";
|
|
398
|
-
const date = new Date(dateString);
|
|
399
|
-
const userTimezoneOffset = date.getTimezoneOffset() * 6e4;
|
|
400
|
-
return new Date(date.getTime() + userTimezoneOffset).toLocaleDateString("es-ES", {
|
|
401
|
-
year: "numeric",
|
|
402
|
-
month: "short",
|
|
403
|
-
day: "numeric"
|
|
404
|
-
});
|
|
405
|
-
}
|
|
406
|
-
function html(strings, ...values) {
|
|
407
|
-
return String.raw({ raw: strings }, ...values);
|
|
408
|
-
}
|
|
409
|
-
function makeDraggable(_element, _handle) {
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
// src/core/NotificationService.ts
|
|
413
|
-
var NotificationService = class {
|
|
414
|
-
container;
|
|
415
|
-
constructor() {
|
|
416
|
-
this.container = document.createElement("div");
|
|
417
|
-
this.container.id = "notification-container";
|
|
418
|
-
this.container.className = "fixed top-5 right-5 z-10000 w-96 space-y-3";
|
|
419
|
-
document.body.appendChild(this.container);
|
|
420
|
-
}
|
|
421
|
-
show(type, title, message, duration = 4e3) {
|
|
422
|
-
const id = `notif_${Date.now()}`;
|
|
423
|
-
const notificationEl = document.createElement("div");
|
|
424
|
-
notificationEl.id = id;
|
|
425
|
-
const typeStyles = {
|
|
426
|
-
info: { icon: "fas fa-info-circle", color: "border-secondary" },
|
|
427
|
-
success: { icon: "fas fa-check-circle", color: "border-success" },
|
|
428
|
-
warning: { icon: "fas fa-exclamation-triangle", color: "border-accent" },
|
|
429
|
-
error: { icon: "fas fa-times-circle", color: "border-danger" },
|
|
430
|
-
achievement: { icon: "fas fa-trophy", color: "border-accent" }
|
|
431
|
-
};
|
|
432
|
-
const styles = typeStyles[type];
|
|
433
|
-
notificationEl.innerHTML = html`
|
|
434
|
-
<div class="notification-item glass-card animate-slide-in-right border-l-4 ${styles.color}">
|
|
435
|
-
<i class="notification-icon ${styles.icon}"></i>
|
|
1
|
+
"use strict";var se=Object.create;var C=Object.defineProperty;var ce=Object.getOwnPropertyDescriptor;var le=Object.getOwnPropertyNames;var de=Object.getPrototypeOf,me=Object.prototype.hasOwnProperty;var Q=(i,e)=>{for(var t in e)C(i,t,{get:e[t],enumerable:!0})},Z=(i,e,t,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of le(e))!me.call(i,o)&&o!==t&&C(i,o,{get:()=>e[o],enumerable:!(a=ce(e,o))||a.enumerable});return i};var ee=(i,e,t)=>(t=i!=null?se(de(i)):{},Z(e||!i||!i.__esModule?C(t,"default",{value:i,enumerable:!0}):t,i)),ue=i=>Z(C({},"__esModule",{value:!0}),i);var Je={};Q(Je,{ApiService:()=>$,AuthService:()=>N,BaseService:()=>Y,CORE_HOOK_NAMES:()=>Ge,CORE_SLOT_NAMES:()=>Ue,CalendarService:()=>T,CommandService:()=>x,DebugService:()=>q,DecidoDB:()=>R,GamificationService:()=>I,HookService:()=>A,ModalService:()=>P,ModuleManager:()=>v,NotificationService:()=>w,RouterService:()=>O,ServiceContainer:()=>D,ShortcutService:()=>E,StorageService:()=>f,SyncService:()=>b,ThemeService:()=>y,apiService:()=>d,authService:()=>h,createEffect:()=>oe,createMemo:()=>he,createPlatformAPI:()=>ne,createSignal:()=>l,db:()=>u,formatDate:()=>pe,html:()=>g,initEventListeners:()=>Ve,makeDraggable:()=>ge,processModuleDefinitions:()=>qe,registerCoreCommands:()=>ze,routerService:()=>X,storageService:()=>fe,syncService:()=>_e,themeService:()=>Oe});module.exports=ue(Je);var D=class{services=new Map;register(e,t){this.services.has(e)&&console.warn(`[ServiceContainer] El servicio '${e}' ya est\xE1 registrado. Se sobrescribir\xE1.`),this.services.set(e,t)}get(e){let t=this.services.get(e);if(!t)throw new Error(`[ServiceContainer] No se encontr\xF3 servicio registrado con la clave: ${e}`);return t}};var H=ee(require("react")),v=class{api;container;modules=new Map;activatedModules=new Set;serviceProviderMap=new Map;constructor(e,t){this.api=e,this.container=t}async registerModules(e){for(let t of e){if(this.modules.has(t.id)){console.warn(`[ModuleManager] El m\xF3dulo '${t.id}' ya est\xE1 registrado. Omitiendo duplicado.`);continue}this.modules.set(t.id,t),console.log(`[Manifest] Registrando contribuciones para '${t.id}'`),this.registerStaticContributions(t.manifest)}}registerStaticContributions(e){let t=e.name;if(!t||!e.contributes)return;let a=e.contributes;e.provides?.forEach(o=>{this.serviceProviderMap.set(o,t)}),a.commands?.forEach(o=>{this.api.commands.register({...o,execute:(r,n)=>this.activateAndExecute(t,o.id,n)})}),a.sidebarViews?.forEach(o=>{if(this.api.layout.registerSidebarView){let r=this.createLazyModuleView(t,o.title);this.api.layout.registerSidebarView({...o,component:r})}else o.render&&this.api.layout.registerSidebarView({...o,render:r=>{r.innerHTML=`<div class="p-4 text-center text-muted-foreground">Cargando ${o.title}...</div>`,this.activateModule(t).then(()=>{this.api.layout.renderSidebar()})}})}),a.activityBar?.forEach(o=>{this.api.layout.registerActivityBarItem({...o})}),a.panelViews?.forEach(o=>{if(this.api.layout.registerPanelView&&this.createLazyModuleView){let r=this.createLazyModuleView(t,o.title);this.api.layout.registerPanelView({...o,component:r})}else o.render&&this.api.layout.registerPanelView({...o,render:r=>{r.innerHTML=`<div class="p-4 text-center text-muted-foreground">Cargando ${o.title}...</div>`,this.activateModule(t).then(()=>{this.api.layout.renderPanel()})}})}),a.topBarItems?.forEach(o=>{this.api.layout.registerTopBarItem(o)}),a.statusBarItems?.forEach(o=>{this.api.layout.registerStatusBarItem(o)})}async activateModule(e){if(this.activatedModules.has(e))return;let t=this.modules.get(e);if(!t)throw new Error(`Intento de activar un m\xF3dulo no registrado: ${e}`);console.log(`\u{1F680} Activando m\xF3dulo del n\xFAcleo '${e}'...`);try{let a=await t.importer();if(a.activate&&typeof a.activate=="function")await a.activate(this.api),this.activatedModules.add(e),console.log(`\u2705 M\xF3dulo '${e}' activado con \xE9xito.`);else throw new Error("El m\xF3dulo no tiene una funci\xF3n de exportaci\xF3n 'activate' v\xE1lida.")}catch(a){console.error(`\u274C Fallo al activar el m\xF3dulo '${e}':`,a),this.api.notifications.show("error",`Fallo al activar: ${e}`,a.message)}}async loadExternalModules(e){for(let t of e)if(!this.activatedModules.has(t.id)){console.log(`\u{1F50C} Cargando m\xF3dulo externo '${t.id}' desde '${t.path}'`);try{let o=await import(`${window.location.origin}${t.path}/index.js`);if(o.activate&&typeof o.activate=="function")await o.activate(this.api),this.activatedModules.add(t.id),console.log(`\u2705 M\xF3dulo externo '${t.id}' activado.`);else throw new Error("El m\xF3dulo externo no exporta una funci\xF3n 'activate'.")}catch(a){console.error(`\u274C Fallo al cargar el m\xF3dulo externo '${t.id}':`,a),this.api.notifications.show("error","Fallo de M\xF3dulo Externo",a.message)}}}getModuleIdForService(e){return this.serviceProviderMap.get(e)}async activateAndExecute(e,t,a){await this.activateModule(e),this.api.commands.execute(t,a)}createLazyModuleView(e,t){return()=>((0,H.useEffect)(()=>{this.activateModule(e).catch(a=>console.error("Lazy Load failed",a))},[]),H.default.createElement("div",{className:"flex items-center justify-center h-full text-muted-foreground"},`Cargando m\xF3dulo: ${t}...`))}};var S=class{events;spy=null;constructor(){this.events=new Map}on(e,t){this.events.has(e)||this.events.set(e,new Set),this.events.get(e).add(t)}off(e,t){let a=this.events.get(e);a&&a.delete(t)}emit(e,t){let a=this.events.get(e);a&&a.forEach(o=>o(t)),this.spy&&this.spy(e,t)}spyOn(e){this.spy=e}};var x=class{commands=new Map;api;spy=null;constructor(){}register(e){this.commands.has(e.id)&&console.warn(`[CommandService] El comando "${e.id}" ya est\xE1 registrado. Se sobrescribir\xE1.`),this.commands.set(e.id,e)}execute(e,t,a){let o=this.commands.get(e);if(o)try{let r=`svc:${o.id.split(".")[0]}Service`,n=performance.now();o.execute(this.api,t);let c=(performance.now()-n).toFixed(2);this.api.debug?.probe(r,"active",{sourceNodeId:a,command:e,duration:`${c} ms`}),this.api.events.emit(`command:${e}:executed`,{arg:t})}catch(r){console.error(`Error ejecutando el comando "${e}":`,r),this.api.notifications.show("error","Error de Comando",`No se pudo ejecutar "${o.title}".`)}else console.error(`[CommandService] Intento de ejecutar un comando no registrado: "${e}"`)}getAll(){return Array.from(this.commands.values())}spyOn(e){this.spy=e}};function pe(i){if(!i)return"Sin fecha";let e=new Date(i),t=e.getTimezoneOffset()*6e4;return new Date(e.getTime()+t).toLocaleDateString("es-ES",{year:"numeric",month:"short",day:"numeric"})}function g(i,...e){return String.raw({raw:i},...e)}function ge(i,e){}var w=class{container;constructor(){this.container=document.createElement("div"),this.container.id="notification-container",this.container.className="fixed top-5 right-5 z-10000 w-96 space-y-3",document.body.appendChild(this.container)}show(e,t,a,o=4e3){let r=`notif_${Date.now()}`,n=document.createElement("div");n.id=r;let c={info:{icon:"fas fa-info-circle",color:"border-secondary"},success:{icon:"fas fa-check-circle",color:"border-success"},warning:{icon:"fas fa-exclamation-triangle",color:"border-accent"},error:{icon:"fas fa-times-circle",color:"border-danger"},achievement:{icon:"fas fa-trophy",color:"border-accent"}}[e];n.innerHTML=g`
|
|
2
|
+
<div class="notification-item glass-card animate-slide-in-right border-l-4 ${c.color}">
|
|
3
|
+
<i class="notification-icon ${c.icon}"></i>
|
|
436
4
|
<div class="flex-grow">
|
|
437
|
-
<h4 class="notification-title">${
|
|
438
|
-
<p class="notification-message">${
|
|
5
|
+
<h4 class="notification-title">${t}</h4>
|
|
6
|
+
<p class="notification-message">${a}</p>
|
|
439
7
|
</div>
|
|
440
|
-
<button class="notification-close-btn" data-close-id="${
|
|
8
|
+
<button class="notification-close-btn" data-close-id="${r}">×</button>
|
|
441
9
|
</div>
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
notificationEl.remove();
|
|
445
|
-
});
|
|
446
|
-
this.container.appendChild(notificationEl);
|
|
447
|
-
setTimeout(() => {
|
|
448
|
-
document.getElementById(id)?.remove();
|
|
449
|
-
}, duration);
|
|
450
|
-
}
|
|
451
|
-
};
|
|
452
|
-
|
|
453
|
-
// src/core/ModalService.ts
|
|
454
|
-
var ModalService = class {
|
|
455
|
-
container;
|
|
456
|
-
constructor() {
|
|
457
|
-
this.container = document.createElement("div");
|
|
458
|
-
this.container.id = "modal-container";
|
|
459
|
-
document.body.appendChild(this.container);
|
|
460
|
-
}
|
|
461
|
-
show(options) {
|
|
462
|
-
this.hide();
|
|
463
|
-
const modalId = `modal_${Date.now()}`;
|
|
464
|
-
const sizeClasses = {
|
|
465
|
-
sm: "max-w-md",
|
|
466
|
-
md: "max-w-lg",
|
|
467
|
-
lg: "max-w-2xl",
|
|
468
|
-
xl: "max-w-4xl"
|
|
469
|
-
};
|
|
470
|
-
const modalWrapper = document.createElement("div");
|
|
471
|
-
modalWrapper.id = modalId;
|
|
472
|
-
modalWrapper.className = "fixed inset-0 bg-darker/80 backdrop-blur-sm flex items-center justify-center z-50";
|
|
473
|
-
modalWrapper.innerHTML = html`
|
|
474
|
-
<div class="glass-premium p-8 rounded-2xl w-full ${sizeClasses[options.size || "md"]} animate-scale-in">
|
|
10
|
+
`,n.querySelector(".notification-close-btn")?.addEventListener("click",()=>{n.remove()}),this.container.appendChild(n),setTimeout(()=>{document.getElementById(r)?.remove()},o)}};var P=class{container;constructor(){this.container=document.createElement("div"),this.container.id="modal-container",document.body.appendChild(this.container)}show(e){this.hide();let t=`modal_${Date.now()}`,a={sm:"max-w-md",md:"max-w-lg",lg:"max-w-2xl",xl:"max-w-4xl"},o=document.createElement("div");o.id=t,o.className="fixed inset-0 bg-darker/80 backdrop-blur-sm flex items-center justify-center z-50",o.innerHTML=g`
|
|
11
|
+
<div class="glass-premium p-8 rounded-2xl w-full ${a[e.size||"md"]} animate-scale-in">
|
|
475
12
|
<div class="flex justify-between items-center mb-6">
|
|
476
|
-
<h2 class="text-2xl font-bold text-white">${
|
|
13
|
+
<h2 class="text-2xl font-bold text-white">${e.title}</h2>
|
|
477
14
|
<button class="text-muted-foreground hover:text-foreground text-2xl close-btn">×</button>
|
|
478
15
|
</div>
|
|
479
16
|
<div class="modal-body"></div>
|
|
480
|
-
${
|
|
17
|
+
${e.actions&&e.actions.length>0?`
|
|
481
18
|
<div class="pt-6 border-t border-white/10 mt-6 text-right space-x-4 modal-footer">
|
|
482
19
|
</div>
|
|
483
|
-
|
|
20
|
+
`:""}
|
|
484
21
|
</div>
|
|
485
|
-
`;
|
|
486
|
-
const closeModal = () => modalWrapper.remove();
|
|
487
|
-
const body = modalWrapper.querySelector(".modal-body");
|
|
488
|
-
if (typeof options.content === "string") {
|
|
489
|
-
body.innerHTML = options.content;
|
|
490
|
-
} else {
|
|
491
|
-
body.appendChild(options.content);
|
|
492
|
-
}
|
|
493
|
-
const footer = modalWrapper.querySelector(".modal-footer");
|
|
494
|
-
if (footer && options.actions) {
|
|
495
|
-
options.actions.forEach((action) => {
|
|
496
|
-
const btn = document.createElement("button");
|
|
497
|
-
btn.textContent = action.text;
|
|
498
|
-
btn.className = action.type === "primary" ? "btn-premium" : "btn-secondary";
|
|
499
|
-
btn.onclick = () => action.onClick(closeModal);
|
|
500
|
-
footer.appendChild(btn);
|
|
501
|
-
});
|
|
502
|
-
}
|
|
503
|
-
modalWrapper.querySelector(".close-btn")?.addEventListener("click", closeModal);
|
|
504
|
-
modalWrapper.addEventListener("click", (e) => {
|
|
505
|
-
if (e.target === modalWrapper) {
|
|
506
|
-
closeModal();
|
|
507
|
-
}
|
|
508
|
-
});
|
|
509
|
-
this.container.appendChild(modalWrapper);
|
|
510
|
-
return {
|
|
511
|
-
close: closeModal
|
|
512
|
-
};
|
|
513
|
-
}
|
|
514
|
-
hide() {
|
|
515
|
-
const modal = this.container.querySelector(".fixed");
|
|
516
|
-
if (modal) {
|
|
517
|
-
modal.remove();
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
};
|
|
521
|
-
|
|
522
|
-
// src/core/GamificationService.ts
|
|
523
|
-
var GamificationService = class {
|
|
524
|
-
api;
|
|
525
|
-
levelFormula = (level) => Math.floor(100 * Math.pow(level, 1.5));
|
|
526
|
-
/**
|
|
527
|
-
* Añade una cantidad de XP, gestiona subidas de nivel y devuelve el estado actualizado.
|
|
528
|
-
* YA NO llama a checkAndUnlockAchievements para romper el bucle.
|
|
529
|
-
*/
|
|
530
|
-
addXP(amount, reason = "Acci\xF3n completada") {
|
|
531
|
-
const { state, notifications } = this.api;
|
|
532
|
-
const gamificationState = state.gamification();
|
|
533
|
-
const newXP = gamificationState.xp + amount;
|
|
534
|
-
const currentLevel = gamificationState.level;
|
|
535
|
-
let newLevel = currentLevel;
|
|
536
|
-
let leveledUp = false;
|
|
537
|
-
let xpForNextLevel = this.levelFormula(currentLevel);
|
|
538
|
-
while (newXP >= xpForNextLevel) {
|
|
539
|
-
newLevel++;
|
|
540
|
-
leveledUp = true;
|
|
541
|
-
xpForNextLevel = this.levelFormula(newLevel);
|
|
542
|
-
}
|
|
543
|
-
state.setGamification({ ...gamificationState, xp: newXP, level: newLevel });
|
|
544
|
-
notifications.show("success", `+${amount} XP!`, reason);
|
|
545
|
-
if (leveledUp) {
|
|
546
|
-
setTimeout(() => {
|
|
547
|
-
notifications.show("success", `\xA1Subiste de Nivel!`, `\u{1F680} \xA1Felicidades! Has alcanzado el Nivel ${newLevel}.`);
|
|
548
|
-
}, 500);
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
/**
|
|
552
|
-
* Actualiza la racha del diario. Ahora también es más simple.
|
|
553
|
-
*/
|
|
554
|
-
updateJournalStreak() {
|
|
555
|
-
const { state } = this.api;
|
|
556
|
-
const gamificationState = state.gamification();
|
|
557
|
-
const today = /* @__PURE__ */ new Date();
|
|
558
|
-
const lastDate = gamificationState.lastJournalDate ? new Date(gamificationState.lastJournalDate) : null;
|
|
559
|
-
let newStreak = gamificationState.streak;
|
|
560
|
-
const isSameDay = (d1, d2) => d1.toDateString() === d2.toDateString();
|
|
561
|
-
if (lastDate && isSameDay(today, lastDate)) return;
|
|
562
|
-
const yesterday = /* @__PURE__ */ new Date();
|
|
563
|
-
yesterday.setDate(today.getDate() - 1);
|
|
564
|
-
newStreak = lastDate && isSameDay(yesterday, lastDate) ? newStreak + 1 : 1;
|
|
565
|
-
if (newStreak > gamificationState.streak) {
|
|
566
|
-
const streakBonusXP = Math.min(newStreak * 5, 50);
|
|
567
|
-
this.addXP(streakBonusXP, `Racha de ${newStreak} d\xEDas`);
|
|
568
|
-
}
|
|
569
|
-
state.setGamification({
|
|
570
|
-
...state.gamification(),
|
|
571
|
-
streak: newStreak,
|
|
572
|
-
lastJournalDate: today.toISOString().slice(0, 10)
|
|
573
|
-
});
|
|
574
|
-
}
|
|
575
|
-
/**
|
|
576
|
-
* Comprueba los logros, y si desbloquea alguno, añade el XP y actualiza el estado UNA SOLA VEZ.
|
|
577
|
-
*/
|
|
578
|
-
checkAndUnlockAchievements() {
|
|
579
|
-
const { state, notifications } = this.api;
|
|
580
|
-
const gamificationState = state.gamification();
|
|
581
|
-
let totalXpFromAchievements = 0;
|
|
582
|
-
const newlyUnlockedIds = [];
|
|
583
|
-
gamificationState.achievements.forEach((achievement) => {
|
|
584
|
-
if (gamificationState.unlockedAchievements.includes(achievement.id)) return;
|
|
585
|
-
let conditionMet = false;
|
|
586
|
-
switch (achievement.conditionType) {
|
|
587
|
-
// case 'tasks_completed':
|
|
588
|
-
// if (tasks.filter(t => t.status === 'done').length >= achievement.conditionValue) conditionMet = true;
|
|
589
|
-
// break;
|
|
590
|
-
// case 'goals_created':
|
|
591
|
-
// if (goals.length >= achievement.conditionValue) conditionMet = true;
|
|
592
|
-
// break;
|
|
593
|
-
case "journal_streak":
|
|
594
|
-
if (gamificationState.streak >= achievement.conditionValue) conditionMet = true;
|
|
595
|
-
break;
|
|
596
|
-
case "level":
|
|
597
|
-
if (gamificationState.level >= achievement.conditionValue) conditionMet = true;
|
|
598
|
-
break;
|
|
599
|
-
}
|
|
600
|
-
if (conditionMet) {
|
|
601
|
-
newlyUnlockedIds.push(achievement.id);
|
|
602
|
-
totalXpFromAchievements += achievement.reward_xp;
|
|
603
|
-
notifications.show("success", "\xA1Logro Desbloqueado!", `\u{1F3C6} ${achievement.title}`);
|
|
604
|
-
}
|
|
605
|
-
});
|
|
606
|
-
if (newlyUnlockedIds.length > 0) {
|
|
607
|
-
this.addXP(totalXpFromAchievements, `Recompensa por ${newlyUnlockedIds.length} logros`);
|
|
608
|
-
const finalGamificationState = state.gamification();
|
|
609
|
-
state.setGamification({
|
|
610
|
-
...finalGamificationState,
|
|
611
|
-
unlockedAchievements: [...finalGamificationState.unlockedAchievements, ...newlyUnlockedIds]
|
|
612
|
-
});
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
};
|
|
616
|
-
|
|
617
|
-
// src/core/CalendarService.ts
|
|
618
|
-
var CalendarService = class {
|
|
619
|
-
api;
|
|
620
|
-
/**
|
|
621
|
-
* Crea un nuevo evento y lo añade al estado.
|
|
622
|
-
*/
|
|
623
|
-
createEvent(eventData) {
|
|
624
|
-
const newEvent = {
|
|
625
|
-
...eventData,
|
|
626
|
-
id: Date.now()
|
|
627
|
-
};
|
|
628
|
-
this.api.notifications.show("success", "Evento Creado", `Se a\xF1adi\xF3 "${newEvent.title}" a tu calendario.`);
|
|
629
|
-
return newEvent;
|
|
630
|
-
}
|
|
631
|
-
/**
|
|
632
|
-
* Obtiene todos los eventos para un día específico.
|
|
633
|
-
* @param date El día para el que se quieren obtener los eventos.
|
|
634
|
-
*/
|
|
635
|
-
getEventsForDay(date) {
|
|
636
|
-
}
|
|
637
|
-
// En el futuro, podríamos añadir métodos como:
|
|
638
|
-
// public updateEvent(eventId: number, updates: Partial<CalendarEvent>) { ... }
|
|
639
|
-
// public deleteEvent(eventId: number) { ... }
|
|
640
|
-
};
|
|
641
|
-
|
|
642
|
-
// src/core/ShortcutService.ts
|
|
643
|
-
var ShortcutService = class {
|
|
644
|
-
api;
|
|
645
|
-
shortcuts = /* @__PURE__ */ new Map();
|
|
646
|
-
init(api) {
|
|
647
|
-
this.api = api;
|
|
648
|
-
window.addEventListener("keydown", this.handleKeyDown.bind(this));
|
|
649
|
-
}
|
|
650
|
-
register(shortcut) {
|
|
651
|
-
const key = shortcut.keys.toLowerCase().split("+").sort().join("_");
|
|
652
|
-
this.shortcuts.set(key, shortcut);
|
|
653
|
-
}
|
|
654
|
-
handleKeyDown(e) {
|
|
655
|
-
const keyParts = [];
|
|
656
|
-
if (e.ctrlKey) keyParts.push("control");
|
|
657
|
-
if (e.metaKey) keyParts.push("meta");
|
|
658
|
-
if (e.shiftKey) keyParts.push("shift");
|
|
659
|
-
if (e.altKey) keyParts.push("alt");
|
|
660
|
-
if (!["Control", "Meta", "Shift", "Alt"].includes(e.key)) {
|
|
661
|
-
keyParts.push(e.key.toLowerCase());
|
|
662
|
-
}
|
|
663
|
-
if (keyParts.length > 1) {
|
|
664
|
-
const key = keyParts.sort().join("_");
|
|
665
|
-
const shortcut = this.shortcuts.get(key);
|
|
666
|
-
if (shortcut) {
|
|
667
|
-
e.preventDefault();
|
|
668
|
-
this.api.commands.execute(shortcut.commandId, shortcut.commandArg);
|
|
669
|
-
}
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
|
-
};
|
|
673
|
-
|
|
674
|
-
// src/core/ApiService.ts
|
|
675
|
-
var ApiService = class {
|
|
676
|
-
id = Math.random().toString(36).substr(2, 9);
|
|
677
|
-
authService;
|
|
678
|
-
init(authService2) {
|
|
679
|
-
console.log(`[ApiService:${this.id}] init called`);
|
|
680
|
-
this.authService = authService2;
|
|
681
|
-
}
|
|
682
|
-
async fetch(endpoint, options = {}, isText = false) {
|
|
683
|
-
console.log(`[ApiService Mock] Ignorando invocaci\xF3n de red a: ${endpoint}`);
|
|
684
|
-
return {};
|
|
685
|
-
}
|
|
686
|
-
async login(email, password) {
|
|
687
|
-
return {};
|
|
688
|
-
}
|
|
689
|
-
async refresh(refreshToken) {
|
|
690
|
-
return { token: "dev" };
|
|
691
|
-
}
|
|
692
|
-
async register(username, email, password) {
|
|
693
|
-
return {};
|
|
694
|
-
}
|
|
695
|
-
logout() {
|
|
696
|
-
}
|
|
697
|
-
async getProfile() {
|
|
698
|
-
return { id: 1, name: "Local Dev" };
|
|
699
|
-
}
|
|
700
|
-
async updateProfile(profileData) {
|
|
701
|
-
return profileData;
|
|
702
|
-
}
|
|
703
|
-
// IA & Marketplace Mocks
|
|
704
|
-
async getAIProjectPlan(goal) {
|
|
705
|
-
return {};
|
|
706
|
-
}
|
|
707
|
-
async generateBlueprint(goalData) {
|
|
708
|
-
return "";
|
|
709
|
-
}
|
|
710
|
-
async getAIGoalSuggestion(idea) {
|
|
711
|
-
return {};
|
|
712
|
-
}
|
|
713
|
-
async getRefinedText(text, context2) {
|
|
714
|
-
return text;
|
|
715
|
-
}
|
|
716
|
-
async getModules() {
|
|
717
|
-
return [];
|
|
718
|
-
}
|
|
719
|
-
async uploadModule(formData) {
|
|
720
|
-
return {};
|
|
721
|
-
}
|
|
722
|
-
async generateTheme(prompt) {
|
|
723
|
-
return {};
|
|
724
|
-
}
|
|
725
|
-
};
|
|
726
|
-
var apiService = new ApiService();
|
|
727
|
-
|
|
728
|
-
// src/appState.ts
|
|
729
|
-
var appState_exports = {};
|
|
730
|
-
__export(appState_exports, {
|
|
731
|
-
activeCalendarId: () => activeCalendarId,
|
|
732
|
-
activeDashboardContext: () => activeDashboardContext,
|
|
733
|
-
activeGoalId: () => activeGoalId,
|
|
734
|
-
activePaneId: () => activePaneId,
|
|
735
|
-
activeProjectId: () => activeProjectId,
|
|
736
|
-
calendar: () => calendar,
|
|
737
|
-
editorPanes: () => editorPanes,
|
|
738
|
-
gamification: () => gamification,
|
|
739
|
-
getFullStateSnapshot: () => getFullStateSnapshot,
|
|
740
|
-
history: () => history,
|
|
741
|
-
initializeStateFromStorage: () => initializeStateFromStorage,
|
|
742
|
-
isTimeTraveling: () => isTimeTraveling,
|
|
743
|
-
restoreStateFromSnapshot: () => restoreStateFromSnapshot,
|
|
744
|
-
setActiveCalendarId: () => setActiveCalendarId,
|
|
745
|
-
setActiveDashboardContext: () => setActiveDashboardContext,
|
|
746
|
-
setActiveGoalId: () => setActiveGoalId,
|
|
747
|
-
setActivePaneId: () => setActivePaneId,
|
|
748
|
-
setActiveProjectId: () => setActiveProjectId,
|
|
749
|
-
setCalendar: () => setCalendar,
|
|
750
|
-
setEditorPanes: () => setEditorPanes,
|
|
751
|
-
setGamification: () => setGamification,
|
|
752
|
-
setHistory: () => setHistory,
|
|
753
|
-
setIsTimeTraveling: () => setIsTimeTraveling,
|
|
754
|
-
setSnapshotDates: () => setSnapshotDates,
|
|
755
|
-
setTimeTravelDate: () => setTimeTravelDate,
|
|
756
|
-
setTimeTravelState: () => setTimeTravelState,
|
|
757
|
-
setViewData: () => setViewData,
|
|
758
|
-
snapshotDates: () => snapshotDates,
|
|
759
|
-
timeTravel: () => timeTravel,
|
|
760
|
-
timeTravelDate: () => timeTravelDate,
|
|
761
|
-
timeTravelLocal: () => timeTravelLocal,
|
|
762
|
-
timeTravelState: () => timeTravelState,
|
|
763
|
-
updateState: () => updateState,
|
|
764
|
-
viewData: () => viewData
|
|
765
|
-
});
|
|
766
|
-
|
|
767
|
-
// src/lib/local-db.ts
|
|
768
|
-
var import_dexie = __toESM(require("dexie"));
|
|
769
|
-
var DecidoDB = class extends import_dexie.default {
|
|
770
|
-
moduleData;
|
|
771
|
-
syncQueue;
|
|
772
|
-
dailySnapshots;
|
|
773
|
-
projects;
|
|
774
|
-
settings;
|
|
775
|
-
constructor() {
|
|
776
|
-
super("DecidoDB");
|
|
777
|
-
this.version(4).stores({
|
|
778
|
-
// Añadimos 'entityType' como un índice individual.
|
|
779
|
-
moduleData: "id, entityId, [moduleId+entityType], userId, entityType",
|
|
780
|
-
syncQueue: "++id, type, status",
|
|
781
|
-
dailySnapshots: "date",
|
|
782
|
-
// Schemas nuevos
|
|
783
|
-
projects: "id, name, updatedAt",
|
|
784
|
-
// Índices para búsqueda rápida
|
|
785
|
-
settings: "key"
|
|
786
|
-
});
|
|
787
|
-
}
|
|
788
|
-
};
|
|
789
|
-
var db = new DecidoDB();
|
|
790
|
-
|
|
791
|
-
// src/core/StorageService.ts
|
|
792
|
-
var StorageService = class {
|
|
793
|
-
// --- Métodos para Colecciones de Entidades (Tareas, Metas, etc.) ---
|
|
794
|
-
async getCollection(entityType) {
|
|
795
|
-
const results = await db.moduleData.where({ entityType }).toArray();
|
|
796
|
-
return results.map((item) => item.data);
|
|
797
|
-
}
|
|
798
|
-
async saveEntity(entityType, entity) {
|
|
799
|
-
const record = {
|
|
800
|
-
id: `${entityType}-${entity.id}`,
|
|
801
|
-
entityId: entity.id,
|
|
802
|
-
moduleId: entityType + "s",
|
|
803
|
-
entityType,
|
|
804
|
-
data: entity
|
|
805
|
-
};
|
|
806
|
-
await db.moduleData.put(record);
|
|
807
|
-
}
|
|
808
|
-
async deleteEntity(entityType, entityId) {
|
|
809
|
-
await db.moduleData.delete(`${entityType}-${entityId}`);
|
|
810
|
-
}
|
|
811
|
-
// --- Métodos para Objetos de Estado Únicos (Journal, Settings, etc.) ---
|
|
812
|
-
async getValue(key) {
|
|
813
|
-
const result = await db.moduleData.get(`value-${key}`);
|
|
814
|
-
return result ? result.data : void 0;
|
|
815
|
-
}
|
|
816
|
-
async saveValue(key, value) {
|
|
817
|
-
const record = {
|
|
818
|
-
id: `value-${key}`,
|
|
819
|
-
entityId: key,
|
|
820
|
-
moduleId: "values",
|
|
821
|
-
entityType: "value",
|
|
822
|
-
data: value
|
|
823
|
-
};
|
|
824
|
-
await db.moduleData.put(record);
|
|
825
|
-
}
|
|
826
|
-
/**
|
|
827
|
-
* Guarda un snapshot completo del estado de la aplicación para una fecha específica.
|
|
828
|
-
* La fecha se guarda en formato 'YYYY-MM-DD'.
|
|
829
|
-
* @param date La fecha del snapshot.
|
|
830
|
-
* @param state El objeto de estado completo a guardar.
|
|
831
|
-
*/
|
|
832
|
-
async saveDailySnapshot(date, state) {
|
|
833
|
-
const dateKey = date.toISOString().split("T")[0];
|
|
834
|
-
const snapshotRecord = {
|
|
835
|
-
date: dateKey,
|
|
836
|
-
data: state,
|
|
837
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
838
|
-
};
|
|
839
|
-
await db.dailySnapshots.put(snapshotRecord);
|
|
840
|
-
console.log(`\u{1F4F8} Snapshot guardado para la fecha: ${dateKey}`);
|
|
841
|
-
}
|
|
842
|
-
/**
|
|
843
|
-
* Recupera el snapshot de un día específico.
|
|
844
|
-
* @param date La fecha del snapshot a recuperar.
|
|
845
|
-
* @returns El estado guardado para esa fecha, o undefined si no existe.
|
|
846
|
-
*/
|
|
847
|
-
async getDailySnapshot(date) {
|
|
848
|
-
const dateKey = date.toISOString().split("T")[0];
|
|
849
|
-
const result = await db.dailySnapshots.get(dateKey);
|
|
850
|
-
return result ? result.data : void 0;
|
|
851
|
-
}
|
|
852
|
-
/**
|
|
853
|
-
* Obtiene una lista de todas las fechas para las que existe un snapshot.
|
|
854
|
-
* @returns Un array de strings con las fechas en formato 'YYYY-MM-DD'.
|
|
855
|
-
*/
|
|
856
|
-
async getAvailableSnapshotDates() {
|
|
857
|
-
return await db.dailySnapshots.toCollection().keys();
|
|
858
|
-
}
|
|
859
|
-
// --- PROYECTOS (Manejo de datos pesados) ---
|
|
860
|
-
async saveProject(id, name, flowData) {
|
|
861
|
-
await db.projects.put({
|
|
862
|
-
id,
|
|
863
|
-
name,
|
|
864
|
-
data: flowData,
|
|
865
|
-
// Aquí puedes guardar MBs de nodos sin problema
|
|
866
|
-
updatedAt: Date.now()
|
|
867
|
-
});
|
|
868
|
-
console.log(`\u{1F4BE} Proyecto ${id} guardado en IndexedDB`);
|
|
869
|
-
}
|
|
870
|
-
async getProject(id) {
|
|
871
|
-
return await db.projects.get(id);
|
|
872
|
-
}
|
|
873
|
-
async getAllProjectsMetadata() {
|
|
874
|
-
return await db.projects.toArray();
|
|
875
|
-
}
|
|
876
|
-
async deleteProject(id) {
|
|
877
|
-
await db.projects.delete(id);
|
|
878
|
-
}
|
|
879
|
-
// --- CONFIGURACIÓN (Settings ligeros) ---
|
|
880
|
-
async setSetting(key, value) {
|
|
881
|
-
await db.settings.put({ key, value });
|
|
882
|
-
}
|
|
883
|
-
async getSetting(key) {
|
|
884
|
-
const item = await db.settings.get(key);
|
|
885
|
-
return item?.value;
|
|
886
|
-
}
|
|
887
|
-
};
|
|
888
|
-
var storageService = new StorageService();
|
|
889
|
-
|
|
890
|
-
// src/core/signals.ts
|
|
891
|
-
var context = [];
|
|
892
|
-
function createSignal(value, options) {
|
|
893
|
-
const subscribers = /* @__PURE__ */ new Set();
|
|
894
|
-
const get = () => {
|
|
895
|
-
const runningEffect = context[context.length - 1];
|
|
896
|
-
if (runningEffect) {
|
|
897
|
-
subscribers.add(runningEffect);
|
|
898
|
-
}
|
|
899
|
-
return value;
|
|
900
|
-
};
|
|
901
|
-
const set = (newValue) => {
|
|
902
|
-
const finalValue = typeof newValue === "function" ? newValue(value) : newValue;
|
|
903
|
-
const areEqual = options?.equals === false ? false : typeof options?.equals === "function" ? options.equals(value, finalValue) : Object.is(value, finalValue);
|
|
904
|
-
if (areEqual) {
|
|
905
|
-
return;
|
|
906
|
-
}
|
|
907
|
-
value = finalValue;
|
|
908
|
-
[...subscribers].forEach((effect) => effect());
|
|
909
|
-
};
|
|
910
|
-
return [get, set];
|
|
911
|
-
}
|
|
912
|
-
function createEffect(fn) {
|
|
913
|
-
const effect = () => {
|
|
914
|
-
context.push(effect);
|
|
915
|
-
try {
|
|
916
|
-
fn();
|
|
917
|
-
} finally {
|
|
918
|
-
context.pop();
|
|
919
|
-
}
|
|
920
|
-
};
|
|
921
|
-
effect();
|
|
922
|
-
}
|
|
923
|
-
function createMemo(fn) {
|
|
924
|
-
const [get, set] = createSignal(void 0, { equals: false });
|
|
925
|
-
createEffect(() => {
|
|
926
|
-
set(fn());
|
|
927
|
-
});
|
|
928
|
-
return get;
|
|
929
|
-
}
|
|
930
|
-
|
|
931
|
-
// src/stores/editorStore.ts
|
|
932
|
-
var [editorPanes, setEditorPanes] = createSignal([]);
|
|
933
|
-
var [activePaneId, setActivePaneId] = createSignal(null);
|
|
934
|
-
var [viewData, setViewData] = createSignal(null);
|
|
935
|
-
|
|
936
|
-
// src/stores/gamificationStore.ts
|
|
937
|
-
var [gamification, setGamification] = createSignal({ xp: 0, level: 1, streak: 0, lastJournalDate: null, unlockedAchievements: [], achievements: [] });
|
|
938
|
-
|
|
939
|
-
// src/stores/workspaceStore.ts
|
|
940
|
-
var [activeCalendarId, setActiveCalendarId] = createSignal("all");
|
|
941
|
-
var [activeDashboardContext, setActiveDashboardContext] = createSignal({ type: "global", id: null });
|
|
942
|
-
var [activeGoalId, setActiveGoalId] = createSignal(null);
|
|
943
|
-
var [activeProjectId, setActiveProjectId] = createSignal(null);
|
|
944
|
-
var [calendar, setCalendar] = createSignal([]);
|
|
945
|
-
|
|
946
|
-
// src/stores/historyStore.ts
|
|
947
|
-
var [isTimeTraveling, setIsTimeTraveling] = createSignal(false);
|
|
948
|
-
var [timeTravelState, setTimeTravelState] = createSignal(null);
|
|
949
|
-
var [timeTravelDate, setTimeTravelDate] = createSignal(/* @__PURE__ */ new Date());
|
|
950
|
-
var [snapshotDates, setSnapshotDates] = createSignal([]);
|
|
951
|
-
var [history, setHistory] = createSignal([]);
|
|
952
|
-
|
|
953
|
-
// src/appState.ts
|
|
954
|
-
var isDebuggingTimeTravel = false;
|
|
955
|
-
var storage = new StorageService();
|
|
956
|
-
async function initializeStateFromStorage(storage2) {
|
|
957
|
-
console.log("\u{1F4BE} Cargando estado desde IndexedDB...");
|
|
958
|
-
const stateMap = [
|
|
959
|
-
// Para objetos únicos
|
|
960
|
-
{ key: "gamification", setter: setGamification, isSingle: true },
|
|
961
|
-
{ key: "editorPanes", setter: setEditorPanes, isSingle: true },
|
|
962
|
-
{ key: "activePaneId", setter: setActivePaneId, isSingle: true }
|
|
963
|
-
];
|
|
964
|
-
for (const item of stateMap) {
|
|
965
|
-
const value = item.isSingle ? await storage2.getValue(item.key) : await storage2.getCollection(item.key);
|
|
966
|
-
if (value !== void 0 && value !== null && Array.isArray(value) && value.length > 0) {
|
|
967
|
-
item.setter(value);
|
|
968
|
-
} else if (value !== void 0 && value !== null && !Array.isArray(value)) {
|
|
969
|
-
item.setter(value);
|
|
970
|
-
}
|
|
971
|
-
}
|
|
972
|
-
if (editorPanes().length === 0) {
|
|
973
|
-
console.log("No se encontr\xF3 layout de editor, creando uno por defecto.");
|
|
974
|
-
const defaultPane = {
|
|
975
|
-
id: "pane-main",
|
|
976
|
-
tabs: [{
|
|
977
|
-
id: "welcome",
|
|
978
|
-
title: "Bienvenido",
|
|
979
|
-
componentTag: "welcome-view",
|
|
980
|
-
icon: "fas fa-hand-sparkles"
|
|
981
|
-
}],
|
|
982
|
-
activeTabId: "welcome"
|
|
983
|
-
};
|
|
984
|
-
setEditorPanes([defaultPane]);
|
|
985
|
-
setActivePaneId(defaultPane.id);
|
|
986
|
-
}
|
|
987
|
-
console.log("\u2705 Estado cargado desde IndexedDB.");
|
|
988
|
-
}
|
|
989
|
-
var isTimeTravelingLocal = false;
|
|
990
|
-
function updateState(action, updater, persistenceFn) {
|
|
991
|
-
if (isTimeTraveling()) {
|
|
992
|
-
console.warn(`[STATE] Escritura bloqueada (${action}). La aplicaci\xF3n est\xE1 en modo de revisi\xF3n de solo lectura.`);
|
|
993
|
-
return;
|
|
994
|
-
}
|
|
995
|
-
if (!isDebuggingTimeTravel) {
|
|
996
|
-
const snapshot = getFullStateSnapshot();
|
|
997
|
-
setHistory((prev) => [...prev, { id: prev.length, timestamp: /* @__PURE__ */ new Date(), action, snapshot }]);
|
|
998
|
-
}
|
|
999
|
-
updater();
|
|
1000
|
-
if (persistenceFn) {
|
|
1001
|
-
persistenceFn().catch((err) => {
|
|
1002
|
-
console.error(`[STATE] Fallo de persistencia en la acci\xF3n '${action}':`, err);
|
|
1003
|
-
});
|
|
1004
|
-
}
|
|
1005
|
-
}
|
|
1006
|
-
function getFullStateSnapshot() {
|
|
1007
|
-
return {
|
|
1008
|
-
gamification: gamification(),
|
|
1009
|
-
editorPanes: editorPanes(),
|
|
1010
|
-
activePaneId: activePaneId()
|
|
1011
|
-
// ... el resto de tu estado ...
|
|
1012
|
-
};
|
|
1013
|
-
}
|
|
1014
|
-
function restoreStateFromSnapshot(snapshot) {
|
|
1015
|
-
if (!snapshot) return;
|
|
1016
|
-
setGamification(snapshot.gamification || { xp: 0, level: 1, streak: 0, lastJournalDate: null, unlockedAchievements: [], achievements: [] });
|
|
1017
|
-
setEditorPanes(snapshot.editorPanes || []);
|
|
1018
|
-
setActivePaneId(snapshot.activePaneId || null);
|
|
1019
|
-
}
|
|
1020
|
-
function timeTravelLocal(historyIndex) {
|
|
1021
|
-
const log = history();
|
|
1022
|
-
if (!log[historyIndex]) return;
|
|
1023
|
-
isDebuggingTimeTravel = true;
|
|
1024
|
-
restoreStateFromSnapshot(log[historyIndex].snapshot);
|
|
1025
|
-
setHistory(log.slice(0, historyIndex + 1));
|
|
1026
|
-
isDebuggingTimeTravel = false;
|
|
1027
|
-
}
|
|
1028
|
-
function timeTravel(historyIndex) {
|
|
1029
|
-
const log = history();
|
|
1030
|
-
if (!log[historyIndex]) return;
|
|
1031
|
-
const snapshot = log[historyIndex].snapshot;
|
|
1032
|
-
isTimeTravelingLocal = true;
|
|
1033
|
-
console.log(`\u2708\uFE0F Viajando en el tiempo al estado ${historyIndex}`, snapshot);
|
|
1034
|
-
setHistory(log.slice(0, historyIndex + 1));
|
|
1035
|
-
isTimeTravelingLocal = false;
|
|
1036
|
-
}
|
|
1037
|
-
|
|
1038
|
-
// src/core/ThemeService.ts
|
|
1039
|
-
var themes = {
|
|
1040
|
-
dark: {
|
|
1041
|
-
"--bg-main": "#070720",
|
|
1042
|
-
"--bg-content": "#0F0F23",
|
|
1043
|
-
"--bg-surface": "rgba(255, 255, 255, 0.03)",
|
|
1044
|
-
"--text-primary": "#FFFFFF",
|
|
1045
|
-
"--text-secondary": "#9CA3AF"
|
|
1046
|
-
},
|
|
1047
|
-
light: {
|
|
1048
|
-
"--bg-main": "#f8f9fa",
|
|
1049
|
-
"--bg-content": "#FFFFFF",
|
|
1050
|
-
"--bg-surface": "rgba(0, 0, 0, 0.03)",
|
|
1051
|
-
"--text-primary": "#212529",
|
|
1052
|
-
"--text-secondary": "#495057"
|
|
1053
|
-
}
|
|
1054
|
-
};
|
|
1055
|
-
var ThemeService = class {
|
|
1056
|
-
activeTheme;
|
|
1057
|
-
constructor() {
|
|
1058
|
-
const savedTheme = localStorage.getItem("decido-theme") || "dark";
|
|
1059
|
-
this.activeTheme = createSignal(savedTheme);
|
|
1060
|
-
this.applyTheme(savedTheme);
|
|
1061
|
-
}
|
|
1062
|
-
setTheme(themeName) {
|
|
1063
|
-
this.activeTheme[1](themeName);
|
|
1064
|
-
this.applyTheme(themeName);
|
|
1065
|
-
localStorage.setItem("decido-theme", themeName);
|
|
1066
|
-
}
|
|
1067
|
-
applyTheme(themeName) {
|
|
1068
|
-
const theme = themes[themeName];
|
|
1069
|
-
for (const [key, value] of Object.entries(theme)) {
|
|
1070
|
-
document.documentElement.style.setProperty(key, value);
|
|
1071
|
-
}
|
|
1072
|
-
}
|
|
1073
|
-
// Permite actualizar un token individual en tiempo real para el panel
|
|
1074
|
-
updateToken(tokenName, value) {
|
|
1075
|
-
document.documentElement.style.setProperty(tokenName, value);
|
|
1076
|
-
}
|
|
1077
|
-
applyPalette(palette) {
|
|
1078
|
-
const tokenMap = {
|
|
1079
|
-
primary: "--color-primary",
|
|
1080
|
-
secondary: "--color-secondary",
|
|
1081
|
-
accent: "--color-accent",
|
|
1082
|
-
bgMain: "--bg-main",
|
|
1083
|
-
bgContent: "--bg-content",
|
|
1084
|
-
textPrimary: "--text-primary",
|
|
1085
|
-
textSecondary: "--text-secondary"
|
|
1086
|
-
};
|
|
1087
|
-
for (const [key, value] of Object.entries(palette)) {
|
|
1088
|
-
const tokenName = tokenMap[key];
|
|
1089
|
-
if (tokenName) {
|
|
1090
|
-
this.updateToken(tokenName, value);
|
|
1091
|
-
}
|
|
1092
|
-
}
|
|
1093
|
-
}
|
|
1094
|
-
};
|
|
1095
|
-
var themeService = new ThemeService();
|
|
1096
|
-
|
|
1097
|
-
// src/core/AuthService.ts
|
|
1098
|
-
var AuthService = class {
|
|
1099
|
-
apiService;
|
|
1100
|
-
session;
|
|
1101
|
-
constructor() {
|
|
1102
|
-
this.session = createSignal({
|
|
1103
|
-
user: null,
|
|
1104
|
-
token: null,
|
|
1105
|
-
status: "loading"
|
|
1106
|
-
});
|
|
1107
|
-
}
|
|
1108
|
-
init(apiService2) {
|
|
1109
|
-
this.apiService = apiService2;
|
|
1110
|
-
}
|
|
1111
|
-
async checkSession() {
|
|
1112
|
-
const fakeUser = { id: 1, name: "Local Dev", email: "dev@local.host" };
|
|
1113
|
-
this.setSession({ user: fakeUser, token: "local-dev-token", status: "authenticated" });
|
|
1114
|
-
console.log("[Auth] CheckSession local - Auto autenticado.");
|
|
1115
|
-
}
|
|
1116
|
-
login = async (email, password) => {
|
|
1117
|
-
const fakeUser = { id: 1, name: "Local Dev", email };
|
|
1118
|
-
this.setSession({ user: fakeUser, token: "local-dev-token", status: "authenticated" });
|
|
1119
|
-
const fullscreenContainer = document.getElementById("fullscreen-view-container");
|
|
1120
|
-
if (fullscreenContainer) fullscreenContainer.innerHTML = "";
|
|
1121
|
-
const appContainer = document.getElementById("app");
|
|
1122
|
-
if (appContainer) appContainer.style.display = "block";
|
|
1123
|
-
return fakeUser;
|
|
1124
|
-
};
|
|
1125
|
-
async register(username, email, password) {
|
|
1126
|
-
return { success: true };
|
|
1127
|
-
}
|
|
1128
|
-
logout = () => {
|
|
1129
|
-
this.setSession({ user: null, token: null, status: "unauthenticated" });
|
|
1130
|
-
};
|
|
1131
|
-
refreshToken = async () => {
|
|
1132
|
-
return "local-dev-token";
|
|
1133
|
-
};
|
|
1134
|
-
listeners = /* @__PURE__ */ new Set();
|
|
1135
|
-
subscribe(cb) {
|
|
1136
|
-
this.listeners.add(cb);
|
|
1137
|
-
cb(this.session[0]());
|
|
1138
|
-
return () => {
|
|
1139
|
-
this.listeners.delete(cb);
|
|
1140
|
-
};
|
|
1141
|
-
}
|
|
1142
|
-
setSession(partialState) {
|
|
1143
|
-
const [get, set] = this.session;
|
|
1144
|
-
set({ ...get(), ...partialState });
|
|
1145
|
-
const newState = get();
|
|
1146
|
-
this.listeners.forEach((cb) => cb(newState));
|
|
1147
|
-
}
|
|
1148
|
-
};
|
|
1149
|
-
var authService = new AuthService();
|
|
1150
|
-
|
|
1151
|
-
// src/core/RouterService.ts
|
|
1152
|
-
var RouterService = class {
|
|
1153
|
-
routes = [];
|
|
1154
|
-
api;
|
|
1155
|
-
init(api) {
|
|
1156
|
-
this.api = api;
|
|
1157
|
-
window.addEventListener("hashchange", this.handleRouteChange);
|
|
1158
|
-
}
|
|
1159
|
-
registerRoute(route) {
|
|
1160
|
-
this.routes.push(route);
|
|
1161
|
-
}
|
|
1162
|
-
navigate(path) {
|
|
1163
|
-
window.location.hash = path;
|
|
1164
|
-
}
|
|
1165
|
-
// Centraliza la lectura del hash en un solo lugar.
|
|
1166
|
-
_getCurrentHash() {
|
|
1167
|
-
return window.location.hash.slice(1) || "/";
|
|
1168
|
-
}
|
|
1169
|
-
handleRouteChange = () => {
|
|
1170
|
-
const path = this._getCurrentHash();
|
|
1171
|
-
const route = this.routes.find((r) => r.path === path);
|
|
1172
|
-
const session = authService.session[0]();
|
|
1173
|
-
if (!route) {
|
|
1174
|
-
console.error(`Ruta no encontrada: ${path}`);
|
|
1175
|
-
this.api.layout.renderComponent("not-found-view");
|
|
1176
|
-
return;
|
|
1177
|
-
}
|
|
1178
|
-
const isAuthenticated = session.status === "authenticated";
|
|
1179
|
-
if (route.auth === "protected" && !isAuthenticated) {
|
|
1180
|
-
this.navigate("/login");
|
|
1181
|
-
return;
|
|
1182
|
-
}
|
|
1183
|
-
if (route.auth === "guestOnly" && isAuthenticated) {
|
|
1184
|
-
this.navigate("/dashboard");
|
|
1185
|
-
return;
|
|
1186
|
-
}
|
|
1187
|
-
if (route.title) document.title = `Decido - ${route.title}`;
|
|
1188
|
-
this.api.layout.renderComponent(route.componentTag, { isFullscreen: route.isFullscreen });
|
|
1189
|
-
};
|
|
1190
|
-
};
|
|
1191
|
-
var routerService = new RouterService();
|
|
1192
|
-
|
|
1193
|
-
// src/lib/sync-service.ts
|
|
1194
|
-
var SyncService = class {
|
|
1195
|
-
isSyncing = false;
|
|
1196
|
-
// Llamar esto en el arranque de la app
|
|
1197
|
-
startSyncLoop() {
|
|
1198
|
-
setInterval(() => this.sync(), 1e4);
|
|
1199
|
-
window.addEventListener("online", () => this.sync());
|
|
1200
|
-
}
|
|
1201
|
-
async sync() {
|
|
1202
|
-
if (this.isSyncing || !navigator.onLine) return;
|
|
1203
|
-
this.isSyncing = true;
|
|
1204
|
-
try {
|
|
1205
|
-
const activeProjectId2 = localStorage.getItem("active_project_id");
|
|
1206
|
-
if (activeProjectId2) {
|
|
1207
|
-
const localProj = await db.projects.get(activeProjectId2);
|
|
1208
|
-
if (localProj) {
|
|
1209
|
-
console.log("\u2601\uFE0F Sincronizando con la nube...");
|
|
1210
|
-
await apiService.fetch(`/module-data/projects/${localProj.id}`, {
|
|
1211
|
-
method: "PUT",
|
|
1212
|
-
body: JSON.stringify({
|
|
1213
|
-
data: localProj.data,
|
|
1214
|
-
name: localProj.name
|
|
1215
|
-
})
|
|
1216
|
-
});
|
|
1217
|
-
}
|
|
1218
|
-
}
|
|
1219
|
-
} catch (e) {
|
|
1220
|
-
console.error("Error de sincronizaci\xF3n", e);
|
|
1221
|
-
} finally {
|
|
1222
|
-
this.isSyncing = false;
|
|
1223
|
-
}
|
|
1224
|
-
}
|
|
1225
|
-
};
|
|
1226
|
-
var syncService = new SyncService();
|
|
1227
|
-
|
|
1228
|
-
// src/core/HookService.ts
|
|
1229
|
-
var HookService = class {
|
|
1230
|
-
hooks = /* @__PURE__ */ new Map();
|
|
1231
|
-
/**
|
|
1232
|
-
* Registra un callback para un hook y devuelve una función para desregistrarlo.
|
|
1233
|
-
* @param hookName El nombre del hook al que suscribirse.
|
|
1234
|
-
* @param callback La función a ejecutar cuando el hook se dispare.
|
|
1235
|
-
* @returns Una función que, al llamarla, desuscribe el callback.
|
|
1236
|
-
*/
|
|
1237
|
-
on(hookName, callback) {
|
|
1238
|
-
if (!this.hooks.has(hookName)) {
|
|
1239
|
-
this.hooks.set(hookName, []);
|
|
1240
|
-
}
|
|
1241
|
-
this.hooks.get(hookName).push(callback);
|
|
1242
|
-
return () => this.off(hookName, callback);
|
|
1243
|
-
}
|
|
1244
|
-
/**
|
|
1245
|
-
* Alias para el método `on`.
|
|
1246
|
-
*/
|
|
1247
|
-
register(hookName, callback) {
|
|
1248
|
-
return this.on(hookName, callback);
|
|
1249
|
-
}
|
|
1250
|
-
/**
|
|
1251
|
-
* Elimina un callback previamente registrado para un hook.
|
|
1252
|
-
* @param hookName El nombre del hook.
|
|
1253
|
-
* @param callbackToRemove La instancia exacta del callback a eliminar.
|
|
1254
|
-
*/
|
|
1255
|
-
off(hookName, callbackToRemove) {
|
|
1256
|
-
const callbacks = this.hooks.get(hookName);
|
|
1257
|
-
if (!callbacks) return;
|
|
1258
|
-
const updatedCallbacks = callbacks.filter((cb) => cb !== callbackToRemove);
|
|
1259
|
-
if (updatedCallbacks.length > 0) {
|
|
1260
|
-
this.hooks.set(hookName, updatedCallbacks);
|
|
1261
|
-
} else {
|
|
1262
|
-
this.hooks.delete(hookName);
|
|
1263
|
-
}
|
|
1264
|
-
}
|
|
1265
|
-
/**
|
|
1266
|
-
* Dispara un hook, ejecutando todos los callbacks registrados para él.
|
|
1267
|
-
* @param hookName El nombre del hook a disparar.
|
|
1268
|
-
* @param data Los datos a pasar a los callbacks.
|
|
1269
|
-
*/
|
|
1270
|
-
async trigger(hookName, data) {
|
|
1271
|
-
const callbacks = this.hooks.get(hookName);
|
|
1272
|
-
if (!callbacks || callbacks.length === 0) return;
|
|
1273
|
-
console.log(`\u{1FA9D} Disparando hook: ${hookName}`, data);
|
|
1274
|
-
for (const callback of [...callbacks]) {
|
|
1275
|
-
try {
|
|
1276
|
-
await Promise.resolve(callback(data));
|
|
1277
|
-
} catch (error) {
|
|
1278
|
-
console.error(`Error en un callback del hook '${hookName}':`, error);
|
|
1279
|
-
}
|
|
1280
|
-
}
|
|
1281
|
-
}
|
|
1282
|
-
};
|
|
1283
|
-
|
|
1284
|
-
// src/core/WebSocketService.ts
|
|
1285
|
-
var WebSocketService = class {
|
|
1286
|
-
api;
|
|
1287
|
-
status = "disconnected";
|
|
1288
|
-
/**
|
|
1289
|
-
* @param api La instancia de la API de la plataforma.
|
|
1290
|
-
*/
|
|
1291
|
-
init(api) {
|
|
1292
|
-
this.api = api;
|
|
1293
|
-
console.log("\u{1F50C} WebSocketService (Mock) inicializado en modo Offline.");
|
|
1294
|
-
}
|
|
1295
|
-
connect() {
|
|
1296
|
-
console.log("[WebSocket] Ignorado: Conectando local (Micro-IDE).");
|
|
1297
|
-
}
|
|
1298
|
-
disconnect() {
|
|
1299
|
-
}
|
|
1300
|
-
emit(eventName, payload) {
|
|
1301
|
-
console.log(`[WebSocket Mock] Env\xEDo evadido: ${eventName}`, payload);
|
|
1302
|
-
}
|
|
1303
|
-
};
|
|
1304
|
-
|
|
1305
|
-
// src/core/app/apiFactory.ts
|
|
1306
|
-
function createPlatformAPI(container) {
|
|
1307
|
-
const eventBus = new EventBus();
|
|
1308
|
-
authService.init(apiService);
|
|
1309
|
-
apiService.init(authService);
|
|
1310
|
-
container.register("events", new EventBus());
|
|
1311
|
-
container.register("notifications", new NotificationService());
|
|
1312
|
-
container.register("modals", new ModalService());
|
|
1313
|
-
container.register("commands", new CommandService());
|
|
1314
|
-
container.register("shortcuts", new ShortcutService());
|
|
1315
|
-
container.register("gamification", new GamificationService());
|
|
1316
|
-
container.register("calendar", new CalendarService());
|
|
1317
|
-
container.register("storage", new StorageService());
|
|
1318
|
-
container.register("sync", new SyncService());
|
|
1319
|
-
container.register("hooks", new HookService());
|
|
1320
|
-
container.register("theme", new ThemeService());
|
|
1321
|
-
container.register("websocket", new WebSocketService());
|
|
1322
|
-
const getModuleManager = () => container.get("moduleManager");
|
|
1323
|
-
const api = {
|
|
1324
|
-
debug: void 0,
|
|
1325
|
-
events: container.get("events"),
|
|
1326
|
-
state: appState_exports,
|
|
1327
|
-
commands: container.get("commands"),
|
|
1328
|
-
modals: container.get("modals"),
|
|
1329
|
-
notifications: container.get("notifications"),
|
|
1330
|
-
shortcuts: container.get("shortcuts"),
|
|
1331
|
-
gamification: container.get("gamification"),
|
|
1332
|
-
calendar: container.get("calendar"),
|
|
1333
|
-
theme: container.get("theme"),
|
|
1334
|
-
storage: container.get("storage"),
|
|
1335
|
-
sync: container.get("sync"),
|
|
1336
|
-
moduleManager: null,
|
|
1337
|
-
// TODO: revisar por que se asignaba como null
|
|
1338
|
-
auth: authService,
|
|
1339
|
-
router: routerService,
|
|
1340
|
-
hooks: container.get("hooks"),
|
|
1341
|
-
websocket: container.get("websocket"),
|
|
1342
|
-
modules: {
|
|
1343
|
-
getModules: () => apiService.fetch("/marketplace/modules"),
|
|
1344
|
-
getInstalledModules: () => apiService.fetch("/marketplace/user/modules"),
|
|
1345
|
-
installModule: (moduleId) => apiService.fetch(`/marketplace/install/${moduleId}`, { method: "POST" }),
|
|
1346
|
-
uploadModule: (formData) => apiService.uploadModule(formData),
|
|
1347
|
-
getProfile: apiService.getProfile.bind(apiService),
|
|
1348
|
-
updateProfile: apiService.updateProfile.bind(apiService),
|
|
1349
|
-
rateModule: (id, rating, review) => apiService.fetch(`/marketplace/rate/${id}`, { method: "POST", body: JSON.stringify({ rating, review }) }),
|
|
1350
|
-
getModuleById: (moduleId) => apiService.fetch(`/marketplace/module/${moduleId}`),
|
|
1351
|
-
getCategories: () => apiService.fetch("/marketplace/categories")
|
|
1352
|
-
},
|
|
1353
|
-
ai: {
|
|
1354
|
-
generateTheme: (prompt) => apiService.fetch("/ai/generate-theme", { method: "POST", body: JSON.stringify({ prompt }) })
|
|
1355
|
-
// generateContent: (prompt, history, mcpServerId) => apiService.fetch('/ai/chat', { method: 'POST', body: { prompt, history, mcpServerId } }),
|
|
1356
|
-
},
|
|
1357
|
-
// mcp: {
|
|
1358
|
-
// getServers: () => apiService.fetch('/mcp/servers'),
|
|
1359
|
-
// installServer: (server) => apiService.fetch('/mcp/servers', { method: 'POST', body: server }),
|
|
1360
|
-
// updateServer: (id, data) => apiService.fetch(`/mcp/servers/${id}`, { method: 'PUT', body: data }),
|
|
1361
|
-
// uninstallServer: (id) => apiService.fetch(`/mcp/servers/${id}`, { method: 'DELETE' }),
|
|
1362
|
-
// },
|
|
1363
|
-
// chat: {
|
|
1364
|
-
// getConversations: () => apiService.fetch('/chat/conversations'),
|
|
1365
|
-
// getConversation: (id) => apiService.fetch(`/chat/conversations/${id}`),
|
|
1366
|
-
// createConversation: (data) => apiService.fetch('/chat/conversations', { method: 'POST', body: data }),
|
|
1367
|
-
// updateConversation: (id, data) => apiService.fetch(`/chat/conversations/${id}`, { method: 'PUT', body: data }),
|
|
1368
|
-
// deleteConversation: (id) => apiService.fetch(`/chat/conversations/${id}`, { method: 'DELETE' }),
|
|
1369
|
-
// },
|
|
1370
|
-
timetravel: {
|
|
1371
|
-
revertToDate: (date) => apiService.fetch("/timetravel/revert", { method: "POST", body: JSON.stringify({ date }) }),
|
|
1372
|
-
getSnapshotDates: () => apiService.fetch("/timetravel/snapshots/dates"),
|
|
1373
|
-
getPreviousActivityDate: (date) => apiService.fetch(`/timetravel/previous-activity-date?currentDate=${date}`),
|
|
1374
|
-
getNextActivityDate: (date) => apiService.fetch(`/timetravel/next-activity-date?currentDate=${date}`)
|
|
1375
|
-
},
|
|
1376
|
-
container,
|
|
1377
|
-
// Exponemos el contenedor directamente
|
|
1378
|
-
services: {
|
|
1379
|
-
// El método register es una fachada para el contenedor
|
|
1380
|
-
register: (key, instance) => container.register(key, instance),
|
|
1381
|
-
// El método get también usa el contenedor
|
|
1382
|
-
get: async (key) => {
|
|
1383
|
-
try {
|
|
1384
|
-
return container.get(key);
|
|
1385
|
-
} catch (e) {
|
|
1386
|
-
console.log(`[API] Servicio '${key}' no encontrado. Buscando proveedor...`);
|
|
1387
|
-
const moduleManager = getModuleManager();
|
|
1388
|
-
const moduleId = moduleManager.getModuleIdForService(key);
|
|
1389
|
-
if (moduleId) {
|
|
1390
|
-
await moduleManager.activateModule(moduleId);
|
|
1391
|
-
return container.get(key);
|
|
1392
|
-
} else {
|
|
1393
|
-
throw new Error(`[API] No se encontr\xF3 ning\xFAn m\xF3dulo que provea el servicio '${key}'.`);
|
|
1394
|
-
}
|
|
1395
|
-
}
|
|
1396
|
-
}
|
|
1397
|
-
}
|
|
1398
|
-
};
|
|
1399
|
-
container.register("moduleManager", new ModuleManager(api, container));
|
|
1400
|
-
api.websocket?.init(api);
|
|
1401
|
-
return api;
|
|
1402
|
-
}
|
|
1403
|
-
|
|
1404
|
-
// src/core/DebugService.ts
|
|
1405
|
-
var DebugService = class {
|
|
1406
|
-
api;
|
|
1407
|
-
graphState = createSignal({ nodes: [], links: [] });
|
|
1408
|
-
probeLog = createSignal([]);
|
|
1409
|
-
playbackState = createSignal({ isPlaying: false, currentIndex: -1 });
|
|
1410
|
-
// --- NUEVAS SEÑALES PARA LOGS ---
|
|
1411
|
-
consoleLogs = createSignal([]);
|
|
1412
|
-
statusTimeouts = /* @__PURE__ */ new Map();
|
|
1413
|
-
constructor(api) {
|
|
1414
|
-
this.api = api;
|
|
1415
|
-
this.setupInterceptors();
|
|
1416
|
-
this.api.commands.spyOn((commandId) => {
|
|
1417
|
-
this.probe(`cmd:${commandId}`, "active");
|
|
1418
|
-
});
|
|
1419
|
-
}
|
|
1420
|
-
// --- NUEVOS MÉTODOS (Movidos desde tu 'services.ts') ---
|
|
1421
|
-
setupInterceptors() {
|
|
1422
|
-
this.interceptConsole();
|
|
1423
|
-
}
|
|
1424
|
-
interceptConsole() {
|
|
1425
|
-
const originalConsole = { ...window.console };
|
|
1426
|
-
["log", "info", "warn", "error"].forEach((level) => {
|
|
1427
|
-
window.console[level] = (...args) => {
|
|
1428
|
-
const newLog = {
|
|
1429
|
-
id: `log_${Date.now()}`,
|
|
1430
|
-
type: level,
|
|
1431
|
-
timestamp: /* @__PURE__ */ new Date(),
|
|
1432
|
-
message: args,
|
|
1433
|
-
stack: level === "error" ? new Error().stack : void 0
|
|
1434
|
-
};
|
|
1435
|
-
this.consoleLogs[1]((prevLogs) => [...prevLogs, newLog]);
|
|
1436
|
-
originalConsole[level](...args);
|
|
1437
|
-
};
|
|
1438
|
-
});
|
|
1439
|
-
}
|
|
1440
|
-
// --- FIN DE NUEVOS MÉTODOS ---
|
|
1441
|
-
clearLogs(logType) {
|
|
1442
|
-
if (logType === "console") {
|
|
1443
|
-
this.consoleLogs[1]([]);
|
|
1444
|
-
}
|
|
1445
|
-
}
|
|
1446
|
-
// public async loadArchitectureGraph(path: string) {
|
|
1447
|
-
// try {
|
|
1448
|
-
// const response = await fetch(path);
|
|
1449
|
-
// const graphData = await response.json();
|
|
1450
|
-
// // Inicializa todos los nodos con estado 'idle'
|
|
1451
|
-
// graphData.nodes.forEach((node: Node) => node.status = 'idle');
|
|
1452
|
-
// this.graphState[1](graphData);
|
|
1453
|
-
// console.log('✅ Mapa de arquitectura cargado en el DebugService.');
|
|
1454
|
-
// } catch (error) {
|
|
1455
|
-
// console.error('❌ Error al cargar el mapa de arquitectura:', error);
|
|
1456
|
-
// }
|
|
1457
|
-
// }
|
|
1458
|
-
async loadArchitectureGraph(path) {
|
|
1459
|
-
try {
|
|
1460
|
-
const response = await fetch(path);
|
|
1461
|
-
const graphData = await response.json();
|
|
1462
|
-
graphData.nodes.forEach((node) => {
|
|
1463
|
-
node.status = "idle";
|
|
1464
|
-
});
|
|
1465
|
-
this.graphState[1](graphData);
|
|
1466
|
-
this.probeLog[1]([]);
|
|
1467
|
-
this.playbackState[1]({ isPlaying: false, currentIndex: -1 });
|
|
1468
|
-
console.log(`\u2705 Nuevo mapa de arquitectura cargado: ${path}`);
|
|
1469
|
-
} catch (error) {
|
|
1470
|
-
console.error(`\u274C Error al cargar el mapa: ${path}`, error);
|
|
1471
|
-
}
|
|
1472
|
-
}
|
|
1473
|
-
/**
|
|
1474
|
-
* El "sensor" principal de nuestro sistema de diagnóstico.
|
|
1475
|
-
* Llama a este método desde cualquier parte del código para actualizar el estado de un nodo.
|
|
1476
|
-
*/
|
|
1477
|
-
probe(nodeId, status, metadata) {
|
|
1478
|
-
const logEntry = { timestamp: Date.now(), nodeId, status, metadata };
|
|
1479
|
-
this.probeLog[1]((prevLog) => [...prevLog, logEntry]);
|
|
1480
|
-
if (!this.playbackState[0]().isPlaying) {
|
|
1481
|
-
this.applyProbeToGraph(logEntry);
|
|
1482
|
-
this.playbackState[1]((prev) => ({ ...prev, currentIndex: this.probeLog[0]().length - 1 }));
|
|
1483
|
-
}
|
|
1484
|
-
}
|
|
1485
|
-
applyProbeToGraph(probe) {
|
|
1486
|
-
const [getGraph, setGraph] = this.graphState;
|
|
1487
|
-
const currentGraph = getGraph();
|
|
1488
|
-
const node = currentGraph.nodes.find((n) => n.id === probe.nodeId);
|
|
1489
|
-
if (node) {
|
|
1490
|
-
node.status = probe.status;
|
|
1491
|
-
node.metadata = probe.metadata;
|
|
1492
|
-
setGraph({ ...currentGraph });
|
|
1493
|
-
if (probe.status === "active") {
|
|
1494
|
-
if (this.statusTimeouts.has(probe.nodeId)) clearTimeout(this.statusTimeouts.get(probe.nodeId));
|
|
1495
|
-
const timeoutId = window.setTimeout(() => {
|
|
1496
|
-
const latestNodeState = this.probeLog[0]().filter((p) => p.nodeId === probe.nodeId).pop();
|
|
1497
|
-
this.applyProbeToGraph({ ...latestNodeState, status: "loaded" });
|
|
1498
|
-
}, 1500);
|
|
1499
|
-
this.statusTimeouts.set(probe.nodeId, timeoutId);
|
|
1500
|
-
}
|
|
1501
|
-
}
|
|
1502
|
-
}
|
|
1503
|
-
// --- CONTROL ---
|
|
1504
|
-
goToLogIndex(index) {
|
|
1505
|
-
const log = this.probeLog[0]();
|
|
1506
|
-
if (index < 0 || index >= log.length) return;
|
|
1507
|
-
this.playbackState[1]((prev) => ({ ...prev, currentIndex: index, isPlaying: false }));
|
|
1508
|
-
const snapshot = log.slice(0, index + 1).reduce((acc, probe) => {
|
|
1509
|
-
acc[probe.nodeId] = probe;
|
|
1510
|
-
return acc;
|
|
1511
|
-
}, {});
|
|
1512
|
-
const [getGraph, setGraph] = this.graphState;
|
|
1513
|
-
const currentGraph = getGraph();
|
|
1514
|
-
currentGraph.nodes.forEach((node) => {
|
|
1515
|
-
if (snapshot[node.id]) {
|
|
1516
|
-
node.status = snapshot[node.id].status;
|
|
1517
|
-
node.metadata = snapshot[node.id].metadata;
|
|
1518
|
-
} else {
|
|
1519
|
-
node.status = "idle";
|
|
1520
|
-
}
|
|
1521
|
-
});
|
|
1522
|
-
setGraph({ ...currentGraph });
|
|
1523
|
-
}
|
|
1524
|
-
};
|
|
1525
|
-
|
|
1526
|
-
// src/core/app/moduleLoader.ts
|
|
1527
|
-
function processModuleDefinitions(imports, manifests, enabledModules) {
|
|
1528
|
-
const definitions = [];
|
|
1529
|
-
for (const path in imports) {
|
|
1530
|
-
const manifestPath = path.replace("index.ts", "package.json");
|
|
1531
|
-
const manifest = manifests[manifestPath];
|
|
1532
|
-
if (!manifest || !manifest.name) {
|
|
1533
|
-
continue;
|
|
1534
|
-
}
|
|
1535
|
-
if (!enabledModules || enabledModules.has(manifest.name)) {
|
|
1536
|
-
definitions.push({
|
|
1537
|
-
id: manifest.name,
|
|
1538
|
-
manifest,
|
|
1539
|
-
importer: imports[path]
|
|
1540
|
-
});
|
|
1541
|
-
}
|
|
1542
|
-
}
|
|
1543
|
-
return definitions;
|
|
1544
|
-
}
|
|
1545
|
-
|
|
1546
|
-
// src/core/BaseService.ts
|
|
1547
|
-
var BaseService = class {
|
|
1548
|
-
// Las dependencias comunes se declaran como protegidas
|
|
1549
|
-
storage;
|
|
1550
|
-
hooks;
|
|
1551
|
-
notifications;
|
|
1552
|
-
gamification;
|
|
1553
|
-
api;
|
|
1554
|
-
container;
|
|
1555
|
-
constructor(container) {
|
|
1556
|
-
this.container = container;
|
|
1557
|
-
this.storage = container.get("storage");
|
|
1558
|
-
this.hooks = container.get("hooks");
|
|
1559
|
-
this.notifications = container.get("notifications");
|
|
1560
|
-
this.gamification = container.get("gamification");
|
|
1561
|
-
this.api = container.get("api");
|
|
1562
|
-
}
|
|
1563
|
-
/**
|
|
1564
|
-
* Envuelve la función global `updateState`.
|
|
1565
|
-
* Este es el único punto de entrada para realizar cambios de estado persistentes.
|
|
1566
|
-
* @param action El nombre de la acción para el historial de depuración (ej: 'TASK:CREATE').
|
|
1567
|
-
* @param updater La función que modifica la señal de estado en memoria.
|
|
1568
|
-
* @param persistenceFn La función asíncrona que guarda el cambio en IndexedDB.
|
|
1569
|
-
*/
|
|
1570
|
-
executeUpdate(action, updater, persistenceFn) {
|
|
1571
|
-
}
|
|
1572
|
-
};
|
|
1573
|
-
|
|
1574
|
-
// src/core/EventHandler.ts
|
|
1575
|
-
function initEventListeners(api) {
|
|
1576
|
-
const { commands } = api;
|
|
1577
|
-
document.body.addEventListener("click", (e) => {
|
|
1578
|
-
const commandTarget = e.target.closest("[data-command]");
|
|
1579
|
-
if (!commandTarget || commandTarget.tagName === "FORM") return;
|
|
1580
|
-
e.preventDefault();
|
|
1581
|
-
const commandId = commandTarget.getAttribute("data-command");
|
|
1582
|
-
const commandArg = commandTarget.getAttribute("data-command-arg");
|
|
1583
|
-
const componentId = commandTarget.closest("[data-component-id]")?.getAttribute("data-component-id") ?? void 0;
|
|
1584
|
-
if (commandId) {
|
|
1585
|
-
commands.execute(commandId, commandArg, componentId);
|
|
1586
|
-
}
|
|
1587
|
-
});
|
|
1588
|
-
document.body.addEventListener("submit", (e) => {
|
|
1589
|
-
const form = e.target;
|
|
1590
|
-
if (form.dataset.command) {
|
|
1591
|
-
e.preventDefault();
|
|
1592
|
-
commands.execute(form.dataset.command, new FormData(form));
|
|
1593
|
-
}
|
|
1594
|
-
});
|
|
1595
|
-
let draggedTaskId = null;
|
|
1596
|
-
document.body.addEventListener("dragstart", (e) => {
|
|
1597
|
-
const target = e.target;
|
|
1598
|
-
if (target.classList.contains("task-card-premium")) {
|
|
1599
|
-
draggedTaskId = Number(target.dataset.taskId);
|
|
1600
|
-
setTimeout(() => target.classList.add("dragging"), 0);
|
|
1601
|
-
}
|
|
1602
|
-
});
|
|
1603
|
-
document.body.addEventListener("dragover", (e) => {
|
|
1604
|
-
const column = e.target.closest(".kanban-column");
|
|
1605
|
-
if (column) {
|
|
1606
|
-
e.preventDefault();
|
|
1607
|
-
document.querySelectorAll(".kanban-column").forEach((c) => c.classList.remove("drag-over"));
|
|
1608
|
-
column.classList.add("drag-over");
|
|
1609
|
-
}
|
|
1610
|
-
});
|
|
1611
|
-
document.body.addEventListener("dragleave", (e) => {
|
|
1612
|
-
e.target.closest(".kanban-column")?.classList.remove("drag-over");
|
|
1613
|
-
});
|
|
1614
|
-
document.body.addEventListener("drop", (e) => {
|
|
1615
|
-
e.preventDefault();
|
|
1616
|
-
const column = e.target.closest(".kanban-column");
|
|
1617
|
-
document.querySelectorAll(".kanban-column").forEach((c) => c.classList.remove("drag-over"));
|
|
1618
|
-
if (column && draggedTaskId !== null) {
|
|
1619
|
-
const newStatus = column.dataset.status;
|
|
1620
|
-
api.commands.execute("kanban.moveTask", { taskId: draggedTaskId, newStatus });
|
|
1621
|
-
}
|
|
1622
|
-
document.querySelectorAll(".kanban-column").forEach((c) => c.classList.remove("drag-over"));
|
|
1623
|
-
draggedTaskId = null;
|
|
1624
|
-
});
|
|
1625
|
-
document.body.addEventListener("dragend", (e) => {
|
|
1626
|
-
const target = e.target;
|
|
1627
|
-
if (target.classList.contains("task-card-premium")) {
|
|
1628
|
-
target.classList.remove("dragging");
|
|
1629
|
-
}
|
|
1630
|
-
draggedTaskId = null;
|
|
1631
|
-
});
|
|
1632
|
-
}
|
|
1633
|
-
|
|
1634
|
-
// src/platform/extensionPoints.ts
|
|
1635
|
-
var CORE_HOOK_NAMES = {
|
|
1636
|
-
APP_BEFORE_START: "app:beforeStart",
|
|
1637
|
-
APP_READY: "app:ready",
|
|
1638
|
-
APP_SHUTDOWN: "app:shutdown",
|
|
1639
|
-
WORKBENCH_BEFORE_START: "workbench:before-start",
|
|
1640
|
-
WORKBENCH_LAYOUT_READY: "workbench:layout-ready",
|
|
1641
|
-
WORKBENCH_USER_AUTHENTICATED: "workbench:user-authenticated",
|
|
1642
|
-
WORKBENCH_READY: "workbench:ready"
|
|
1643
|
-
// ...etc
|
|
1644
|
-
};
|
|
1645
|
-
var CORE_SLOT_NAMES = {
|
|
1646
|
-
ACTIVITY_BAR: "ui:activityBar",
|
|
1647
|
-
STATUS_BAR_LEFT: "ui:statusBar.left",
|
|
1648
|
-
STATUS_BAR_RIGHT: "ui:statusBar.right"
|
|
1649
|
-
// ...etc
|
|
1650
|
-
};
|
|
1651
|
-
|
|
1652
|
-
// src/ui/Palette.ts
|
|
1653
|
-
var Palette = class {
|
|
1654
|
-
api;
|
|
1655
|
-
dom = {};
|
|
1656
|
-
allCommands = [];
|
|
1657
|
-
filteredCommands = [];
|
|
1658
|
-
selectedIndex = 0;
|
|
1659
|
-
constructor(api) {
|
|
1660
|
-
this.api = api;
|
|
1661
|
-
this.init();
|
|
1662
|
-
}
|
|
1663
|
-
/**
|
|
1664
|
-
* Alterna la visibilidad de la paleta.
|
|
1665
|
-
*/
|
|
1666
|
-
toggle() {
|
|
1667
|
-
const isHidden = this.dom.modal?.classList.contains("hidden");
|
|
1668
|
-
if (isHidden) this.show();
|
|
1669
|
-
else this.hide();
|
|
1670
|
-
}
|
|
1671
|
-
/**
|
|
1672
|
-
* Muestra la paleta, carga los comandos y enfoca el input.
|
|
1673
|
-
*/
|
|
1674
|
-
show() {
|
|
1675
|
-
this.allCommands = this.api.commands.getAll();
|
|
1676
|
-
this.filteredCommands = this.allCommands;
|
|
1677
|
-
this.selectedIndex = 0;
|
|
1678
|
-
this.renderResults();
|
|
1679
|
-
this.dom.modal?.classList.remove("hidden");
|
|
1680
|
-
this.dom.input?.focus();
|
|
1681
|
-
}
|
|
1682
|
-
/**
|
|
1683
|
-
* Oculta la paleta y resetea el input.
|
|
1684
|
-
*/
|
|
1685
|
-
hide() {
|
|
1686
|
-
const input = this.dom.input;
|
|
1687
|
-
if (input) input.value = "";
|
|
1688
|
-
this.dom.modal?.classList.add("hidden");
|
|
1689
|
-
}
|
|
1690
|
-
/**
|
|
1691
|
-
* Crea el HTML de la paleta y lo añade al DOM.
|
|
1692
|
-
*/
|
|
1693
|
-
init() {
|
|
1694
|
-
const paletteEl = document.createElement("div");
|
|
1695
|
-
paletteEl.id = "command-palette-modal";
|
|
1696
|
-
paletteEl.className = "fixed inset-0 bg-darker/80 backdrop-blur-sm flex items-start justify-center hidden pt-24";
|
|
1697
|
-
paletteEl.style.zIndex = "10000";
|
|
1698
|
-
paletteEl.style.position = "fixed";
|
|
1699
|
-
paletteEl.innerHTML = html`
|
|
22
|
+
`;let r=()=>o.remove(),n=o.querySelector(".modal-body");typeof e.content=="string"?n.innerHTML=e.content:n.appendChild(e.content);let s=o.querySelector(".modal-footer");return s&&e.actions&&e.actions.forEach(c=>{let m=document.createElement("button");m.textContent=c.text,m.className=c.type==="primary"?"btn-premium":"btn-secondary",m.onclick=()=>c.onClick(r),s.appendChild(m)}),o.querySelector(".close-btn")?.addEventListener("click",r),o.addEventListener("click",c=>{c.target===o&&r()}),this.container.appendChild(o),{close:r}}hide(){let e=this.container.querySelector(".fixed");e&&e.remove()}};var I=class{api;levelFormula=e=>Math.floor(100*Math.pow(e,1.5));addXP(e,t="Acci\xF3n completada"){let{state:a,notifications:o}=this.api,r=a.gamification(),n=r.xp+e,s=r.level,c=s,m=!1,p=this.levelFormula(s);for(;n>=p;)c++,m=!0,p=this.levelFormula(c);a.setGamification({...r,xp:n,level:c}),o.show("success",`+${e} XP!`,t),m&&setTimeout(()=>{o.show("success","\xA1Subiste de Nivel!",`\u{1F680} \xA1Felicidades! Has alcanzado el Nivel ${c}.`)},500)}updateJournalStreak(){let{state:e}=this.api,t=e.gamification(),a=new Date,o=t.lastJournalDate?new Date(t.lastJournalDate):null,r=t.streak,n=(c,m)=>c.toDateString()===m.toDateString();if(o&&n(a,o))return;let s=new Date;if(s.setDate(a.getDate()-1),r=o&&n(s,o)?r+1:1,r>t.streak){let c=Math.min(r*5,50);this.addXP(c,`Racha de ${r} d\xEDas`)}e.setGamification({...e.gamification(),streak:r,lastJournalDate:a.toISOString().slice(0,10)})}checkAndUnlockAchievements(){let{state:e,notifications:t}=this.api,a=e.gamification(),o=0,r=[];if(a.achievements.forEach(n=>{if(a.unlockedAchievements.includes(n.id))return;let s=!1;switch(n.conditionType){case"journal_streak":a.streak>=n.conditionValue&&(s=!0);break;case"level":a.level>=n.conditionValue&&(s=!0);break}s&&(r.push(n.id),o+=n.reward_xp,t.show("success","\xA1Logro Desbloqueado!",`\u{1F3C6} ${n.title}`))}),r.length>0){this.addXP(o,`Recompensa por ${r.length} logros`);let n=e.gamification();e.setGamification({...n,unlockedAchievements:[...n.unlockedAchievements,...r]})}}};var T=class{api;createEvent(e){let t={...e,id:Date.now()};return this.api.notifications.show("success","Evento Creado",`Se a\xF1adi\xF3 "${t.title}" a tu calendario.`),t}getEventsForDay(e){}};var E=class{api;shortcuts=new Map;init(e){this.api=e,window.addEventListener("keydown",this.handleKeyDown.bind(this))}register(e){let t=e.keys.toLowerCase().split("+").sort().join("_");this.shortcuts.set(t,e)}handleKeyDown(e){let t=[];if(e.ctrlKey&&t.push("control"),e.metaKey&&t.push("meta"),e.shiftKey&&t.push("shift"),e.altKey&&t.push("alt"),["Control","Meta","Shift","Alt"].includes(e.key)||t.push(e.key.toLowerCase()),t.length>1){let a=t.sort().join("_"),o=this.shortcuts.get(a);o&&(e.preventDefault(),this.api.commands.execute(o.commandId,o.commandArg))}}};var $=class{id=Math.random().toString(36).substr(2,9);authService;init(e){console.log(`[ApiService:${this.id}] init called`),this.authService=e}async fetch(e,t={},a=!1){return console.log(`[ApiService Mock] Ignorando invocaci\xF3n de red a: ${e}`),{}}async login(e,t){return{}}async refresh(e){return{token:"dev"}}async register(e,t,a){return{}}logout(){}async getProfile(){return{id:1,name:"Local Dev"}}async updateProfile(e){return e}async getAIProjectPlan(e){return{}}async generateBlueprint(e){return""}async getAIGoalSuggestion(e){return{}}async getRefinedText(e,t){return e}async getModules(){return[]}async uploadModule(e){return{}}async generateTheme(e){return{}}},d=new $;var W={};Q(W,{activeCalendarId:()=>be,activeDashboardContext:()=>xe,activeGoalId:()=>Pe,activePaneId:()=>G,activeProjectId:()=>Te,calendar:()=>ke,editorPanes:()=>K,gamification:()=>U,getFullStateSnapshot:()=>ie,history:()=>B,initializeStateFromStorage:()=>je,isTimeTraveling:()=>z,restoreStateFromSnapshot:()=>re,setActiveCalendarId:()=>Se,setActiveDashboardContext:()=>we,setActiveGoalId:()=>Ie,setActivePaneId:()=>M,setActiveProjectId:()=>Ee,setCalendar:()=>Me,setEditorPanes:()=>k,setGamification:()=>F,setHistory:()=>L,setIsTimeTraveling:()=>Le,setSnapshotDates:()=>Re,setTimeTravelDate:()=>He,setTimeTravelState:()=>Ce,setViewData:()=>ye,snapshotDates:()=>$e,timeTravel:()=>Be,timeTravelDate:()=>De,timeTravelLocal:()=>Fe,timeTravelState:()=>Ae,updateState:()=>Ke,viewData:()=>ve});var te=ee(require("dexie")),R=class extends te.default{moduleData;syncQueue;dailySnapshots;projects;settings;constructor(){super("DecidoDB"),this.version(4).stores({moduleData:"id, entityId, [moduleId+entityType], userId, entityType",syncQueue:"++id, type, status",dailySnapshots:"date",projects:"id, name, updatedAt",settings:"key"})}},u=new R;var f=class{async getCollection(e){return(await u.moduleData.where({entityType:e}).toArray()).map(a=>a.data)}async saveEntity(e,t){let a={id:`${e}-${t.id}`,entityId:t.id,moduleId:e+"s",entityType:e,data:t};await u.moduleData.put(a)}async deleteEntity(e,t){await u.moduleData.delete(`${e}-${t}`)}async getValue(e){let t=await u.moduleData.get(`value-${e}`);return t?t.data:void 0}async saveValue(e,t){let a={id:`value-${e}`,entityId:e,moduleId:"values",entityType:"value",data:t};await u.moduleData.put(a)}async saveDailySnapshot(e,t){let a=e.toISOString().split("T")[0],o={date:a,data:t,timestamp:new Date};await u.dailySnapshots.put(o),console.log(`\u{1F4F8} Snapshot guardado para la fecha: ${a}`)}async getDailySnapshot(e){let t=e.toISOString().split("T")[0],a=await u.dailySnapshots.get(t);return a?a.data:void 0}async getAvailableSnapshotDates(){return await u.dailySnapshots.toCollection().keys()}async saveProject(e,t,a){await u.projects.put({id:e,name:t,data:a,updatedAt:Date.now()}),console.log(`\u{1F4BE} Proyecto ${e} guardado en IndexedDB`)}async getProject(e){return await u.projects.get(e)}async getAllProjectsMetadata(){return await u.projects.toArray()}async deleteProject(e){await u.projects.delete(e)}async setSetting(e,t){await u.settings.put({key:e,value:t})}async getSetting(e){return(await u.settings.get(e))?.value}},fe=new f;var j=[];function l(i,e){let t=new Set;return[()=>{let r=j[j.length-1];return r&&t.add(r),i},r=>{let n=typeof r=="function"?r(i):r;e?.equals!==!1&&(typeof e?.equals=="function"?e.equals(i,n):Object.is(i,n))||(i=n,[...t].forEach(c=>c()))}]}function oe(i){let e=()=>{j.push(e);try{i()}finally{j.pop()}};e()}function he(i){let[e,t]=l(void 0,{equals:!1});return oe(()=>{t(i())}),e}var[K,k]=l([]),[G,M]=l(null),[ve,ye]=l(null);var[U,F]=l({xp:0,level:1,streak:0,lastJournalDate:null,unlockedAchievements:[],achievements:[]});var[be,Se]=l("all"),[xe,we]=l({type:"global",id:null}),[Pe,Ie]=l(null),[Te,Ee]=l(null),[ke,Me]=l([]);var[z,Le]=l(!1),[Ae,Ce]=l(null),[De,He]=l(new Date),[$e,Re]=l([]),[B,L]=l([]);var J=!1,Lt=new f;async function je(i){console.log("\u{1F4BE} Cargando estado desde IndexedDB...");let e=[{key:"gamification",setter:F,isSingle:!0},{key:"editorPanes",setter:k,isSingle:!0},{key:"activePaneId",setter:M,isSingle:!0}];for(let t of e){let a=t.isSingle?await i.getValue(t.key):await i.getCollection(t.key);(a!=null&&Array.isArray(a)&&a.length>0||a!=null&&!Array.isArray(a))&&t.setter(a)}if(K().length===0){console.log("No se encontr\xF3 layout de editor, creando uno por defecto.");let t={id:"pane-main",tabs:[{id:"welcome",title:"Bienvenido",componentTag:"welcome-view",icon:"fas fa-hand-sparkles"}],activeTabId:"welcome"};k([t]),M(t.id)}console.log("\u2705 Estado cargado desde IndexedDB.")}var ae=!1;function Ke(i,e,t){if(z()){console.warn(`[STATE] Escritura bloqueada (${i}). La aplicaci\xF3n est\xE1 en modo de revisi\xF3n de solo lectura.`);return}if(!J){let a=ie();L(o=>[...o,{id:o.length,timestamp:new Date,action:i,snapshot:a}])}e(),t&&t().catch(a=>{console.error(`[STATE] Fallo de persistencia en la acci\xF3n '${i}':`,a)})}function ie(){return{gamification:U(),editorPanes:K(),activePaneId:G()}}function re(i){i&&(F(i.gamification||{xp:0,level:1,streak:0,lastJournalDate:null,unlockedAchievements:[],achievements:[]}),k(i.editorPanes||[]),M(i.activePaneId||null))}function Fe(i){let e=B();e[i]&&(J=!0,re(e[i].snapshot),L(e.slice(0,i+1)),J=!1)}function Be(i){let e=B();if(!e[i])return;let t=e[i].snapshot;ae=!0,console.log(`\u2708\uFE0F Viajando en el tiempo al estado ${i}`,t),L(e.slice(0,i+1)),ae=!1}var Ne={dark:{"--bg-main":"#070720","--bg-content":"#0F0F23","--bg-surface":"rgba(255, 255, 255, 0.03)","--text-primary":"#FFFFFF","--text-secondary":"#9CA3AF"},light:{"--bg-main":"#f8f9fa","--bg-content":"#FFFFFF","--bg-surface":"rgba(0, 0, 0, 0.03)","--text-primary":"#212529","--text-secondary":"#495057"}},y=class{activeTheme;constructor(){let e=localStorage.getItem("decido-theme")||"dark";this.activeTheme=l(e),this.applyTheme(e)}setTheme(e){this.activeTheme[1](e),this.applyTheme(e),localStorage.setItem("decido-theme",e)}applyTheme(e){let t=Ne[e];for(let[a,o]of Object.entries(t))document.documentElement.style.setProperty(a,o)}updateToken(e,t){document.documentElement.style.setProperty(e,t)}applyPalette(e){let t={primary:"--color-primary",secondary:"--color-secondary",accent:"--color-accent",bgMain:"--bg-main",bgContent:"--bg-content",textPrimary:"--text-primary",textSecondary:"--text-secondary"};for(let[a,o]of Object.entries(e)){let r=t[a];r&&this.updateToken(r,o)}}},Oe=new y;var N=class{apiService;session;constructor(){this.session=l({user:null,token:null,status:"loading"})}init(e){this.apiService=e}async checkSession(){let e={id:1,name:"Local Dev",email:"dev@local.host"};this.setSession({user:e,token:"local-dev-token",status:"authenticated"}),console.log("[Auth] CheckSession local - Auto autenticado.")}login=async(e,t)=>{let a={id:1,name:"Local Dev",email:e};this.setSession({user:a,token:"local-dev-token",status:"authenticated"});let o=document.getElementById("fullscreen-view-container");o&&(o.innerHTML="");let r=document.getElementById("app");return r&&(r.style.display="block"),a};async register(e,t,a){return{success:!0}}logout=()=>{this.setSession({user:null,token:null,status:"unauthenticated"})};refreshToken=async()=>"local-dev-token";listeners=new Set;subscribe(e){return this.listeners.add(e),e(this.session[0]()),()=>{this.listeners.delete(e)}}setSession(e){let[t,a]=this.session;a({...t(),...e});let o=t();this.listeners.forEach(r=>r(o))}},h=new N;var O=class{routes=[];api;init(e){this.api=e,window.addEventListener("hashchange",this.handleRouteChange)}registerRoute(e){this.routes.push(e)}navigate(e){window.location.hash=e}_getCurrentHash(){return window.location.hash.slice(1)||"/"}handleRouteChange=()=>{let e=this._getCurrentHash(),t=this.routes.find(r=>r.path===e),a=h.session[0]();if(!t){console.error(`Ruta no encontrada: ${e}`),this.api.layout.renderComponent("not-found-view");return}let o=a.status==="authenticated";if(t.auth==="protected"&&!o){this.navigate("/login");return}if(t.auth==="guestOnly"&&o){this.navigate("/dashboard");return}t.title&&(document.title=`Decido - ${t.title}`),this.api.layout.renderComponent(t.componentTag,{isFullscreen:t.isFullscreen})}},X=new O;var b=class{isSyncing=!1;startSyncLoop(){setInterval(()=>this.sync(),1e4),window.addEventListener("online",()=>this.sync())}async sync(){if(!(this.isSyncing||!navigator.onLine)){this.isSyncing=!0;try{let e=localStorage.getItem("active_project_id");if(e){let t=await u.projects.get(e);t&&(console.log("\u2601\uFE0F Sincronizando con la nube..."),await d.fetch(`/module-data/projects/${t.id}`,{method:"PUT",body:JSON.stringify({data:t.data,name:t.name})}))}}catch(e){console.error("Error de sincronizaci\xF3n",e)}finally{this.isSyncing=!1}}}},_e=new b;var A=class{hooks=new Map;on(e,t){return this.hooks.has(e)||this.hooks.set(e,[]),this.hooks.get(e).push(t),()=>this.off(e,t)}register(e,t){return this.on(e,t)}off(e,t){let a=this.hooks.get(e);if(!a)return;let o=a.filter(r=>r!==t);o.length>0?this.hooks.set(e,o):this.hooks.delete(e)}async trigger(e,t){let a=this.hooks.get(e);if(!(!a||a.length===0)){console.log(`\u{1FA9D} Disparando hook: ${e}`,t);for(let o of[...a])try{await Promise.resolve(o(t))}catch(r){console.error(`Error en un callback del hook '${e}':`,r)}}}};var _=class{api;status="disconnected";init(e){this.api=e,console.log("\u{1F50C} WebSocketService (Mock) inicializado en modo Offline.")}connect(){console.log("[WebSocket] Ignorado: Conectando local (Micro-IDE).")}disconnect(){}emit(e,t){console.log(`[WebSocket Mock] Env\xEDo evadido: ${e}`,t)}};function ne(i){let e=new S;h.init(d),d.init(h),i.register("events",new S),i.register("notifications",new w),i.register("modals",new P),i.register("commands",new x),i.register("shortcuts",new E),i.register("gamification",new I),i.register("calendar",new T),i.register("storage",new f),i.register("sync",new b),i.register("hooks",new A),i.register("theme",new y),i.register("websocket",new _);let t=()=>i.get("moduleManager"),a={debug:void 0,events:i.get("events"),state:W,commands:i.get("commands"),modals:i.get("modals"),notifications:i.get("notifications"),shortcuts:i.get("shortcuts"),gamification:i.get("gamification"),calendar:i.get("calendar"),theme:i.get("theme"),storage:i.get("storage"),sync:i.get("sync"),moduleManager:null,auth:h,router:X,hooks:i.get("hooks"),websocket:i.get("websocket"),modules:{getModules:()=>d.fetch("/marketplace/modules"),getInstalledModules:()=>d.fetch("/marketplace/user/modules"),installModule:o=>d.fetch(`/marketplace/install/${o}`,{method:"POST"}),uploadModule:o=>d.uploadModule(o),getProfile:d.getProfile.bind(d),updateProfile:d.updateProfile.bind(d),rateModule:(o,r,n)=>d.fetch(`/marketplace/rate/${o}`,{method:"POST",body:JSON.stringify({rating:r,review:n})}),getModuleById:o=>d.fetch(`/marketplace/module/${o}`),getCategories:()=>d.fetch("/marketplace/categories")},ai:{generateTheme:o=>d.fetch("/ai/generate-theme",{method:"POST",body:JSON.stringify({prompt:o})})},timetravel:{revertToDate:o=>d.fetch("/timetravel/revert",{method:"POST",body:JSON.stringify({date:o})}),getSnapshotDates:()=>d.fetch("/timetravel/snapshots/dates"),getPreviousActivityDate:o=>d.fetch(`/timetravel/previous-activity-date?currentDate=${o}`),getNextActivityDate:o=>d.fetch(`/timetravel/next-activity-date?currentDate=${o}`)},container:i,services:{register:(o,r)=>i.register(o,r),get:async o=>{try{return i.get(o)}catch{console.log(`[API] Servicio '${o}' no encontrado. Buscando proveedor...`);let n=t(),s=n.getModuleIdForService(o);if(s)return await n.activateModule(s),i.get(o);throw new Error(`[API] No se encontr\xF3 ning\xFAn m\xF3dulo que provea el servicio '${o}'.`)}}}};return i.register("moduleManager",new v(a,i)),a.websocket?.init(a),a}var q=class{api;graphState=l({nodes:[],links:[]});probeLog=l([]);playbackState=l({isPlaying:!1,currentIndex:-1});consoleLogs=l([]);statusTimeouts=new Map;constructor(e){this.api=e,this.setupInterceptors(),this.api.commands.spyOn(t=>{this.probe(`cmd:${t}`,"active")})}setupInterceptors(){this.interceptConsole()}interceptConsole(){let e={...window.console};["log","info","warn","error"].forEach(t=>{window.console[t]=(...a)=>{let o={id:`log_${Date.now()}`,type:t,timestamp:new Date,message:a,stack:t==="error"?new Error().stack:void 0};this.consoleLogs[1](r=>[...r,o]),e[t](...a)}})}clearLogs(e){e==="console"&&this.consoleLogs[1]([])}async loadArchitectureGraph(e){try{let a=await(await fetch(e)).json();a.nodes.forEach(o=>{o.status="idle"}),this.graphState[1](a),this.probeLog[1]([]),this.playbackState[1]({isPlaying:!1,currentIndex:-1}),console.log(`\u2705 Nuevo mapa de arquitectura cargado: ${e}`)}catch(t){console.error(`\u274C Error al cargar el mapa: ${e}`,t)}}probe(e,t,a){let o={timestamp:Date.now(),nodeId:e,status:t,metadata:a};this.probeLog[1](r=>[...r,o]),this.playbackState[0]().isPlaying||(this.applyProbeToGraph(o),this.playbackState[1](r=>({...r,currentIndex:this.probeLog[0]().length-1})))}applyProbeToGraph(e){let[t,a]=this.graphState,o=t(),r=o.nodes.find(n=>n.id===e.nodeId);if(r&&(r.status=e.status,r.metadata=e.metadata,a({...o}),e.status==="active")){this.statusTimeouts.has(e.nodeId)&&clearTimeout(this.statusTimeouts.get(e.nodeId));let n=window.setTimeout(()=>{let s=this.probeLog[0]().filter(c=>c.nodeId===e.nodeId).pop();this.applyProbeToGraph({...s,status:"loaded"})},1500);this.statusTimeouts.set(e.nodeId,n)}}goToLogIndex(e){let t=this.probeLog[0]();if(e<0||e>=t.length)return;this.playbackState[1](s=>({...s,currentIndex:e,isPlaying:!1}));let a=t.slice(0,e+1).reduce((s,c)=>(s[c.nodeId]=c,s),{}),[o,r]=this.graphState,n=o();n.nodes.forEach(s=>{a[s.id]?(s.status=a[s.id].status,s.metadata=a[s.id].metadata):s.status="idle"}),r({...n})}};function qe(i,e,t){let a=[];for(let o in i){let r=o.replace("index.ts","package.json"),n=e[r];!n||!n.name||(!t||t.has(n.name))&&a.push({id:n.name,manifest:n,importer:i[o]})}return a}var Y=class{storage;hooks;notifications;gamification;api;container;constructor(e){this.container=e,this.storage=e.get("storage"),this.hooks=e.get("hooks"),this.notifications=e.get("notifications"),this.gamification=e.get("gamification"),this.api=e.get("api")}executeUpdate(e,t,a){}};function Ve(i){let{commands:e}=i;document.body.addEventListener("click",a=>{let o=a.target.closest("[data-command]");if(!o||o.tagName==="FORM")return;a.preventDefault();let r=o.getAttribute("data-command"),n=o.getAttribute("data-command-arg"),s=o.closest("[data-component-id]")?.getAttribute("data-component-id")??void 0;r&&e.execute(r,n,s)}),document.body.addEventListener("submit",a=>{let o=a.target;o.dataset.command&&(a.preventDefault(),e.execute(o.dataset.command,new FormData(o)))});let t=null;document.body.addEventListener("dragstart",a=>{let o=a.target;o.classList.contains("task-card-premium")&&(t=Number(o.dataset.taskId),setTimeout(()=>o.classList.add("dragging"),0))}),document.body.addEventListener("dragover",a=>{let o=a.target.closest(".kanban-column");o&&(a.preventDefault(),document.querySelectorAll(".kanban-column").forEach(r=>r.classList.remove("drag-over")),o.classList.add("drag-over"))}),document.body.addEventListener("dragleave",a=>{a.target.closest(".kanban-column")?.classList.remove("drag-over")}),document.body.addEventListener("drop",a=>{a.preventDefault();let o=a.target.closest(".kanban-column");if(document.querySelectorAll(".kanban-column").forEach(r=>r.classList.remove("drag-over")),o&&t!==null){let r=o.dataset.status;i.commands.execute("kanban.moveTask",{taskId:t,newStatus:r})}document.querySelectorAll(".kanban-column").forEach(r=>r.classList.remove("drag-over")),t=null}),document.body.addEventListener("dragend",a=>{let o=a.target;o.classList.contains("task-card-premium")&&o.classList.remove("dragging"),t=null})}var Ge={APP_BEFORE_START:"app:beforeStart",APP_READY:"app:ready",APP_SHUTDOWN:"app:shutdown",WORKBENCH_BEFORE_START:"workbench:before-start",WORKBENCH_LAYOUT_READY:"workbench:layout-ready",WORKBENCH_USER_AUTHENTICATED:"workbench:user-authenticated",WORKBENCH_READY:"workbench:ready"},Ue={ACTIVITY_BAR:"ui:activityBar",STATUS_BAR_LEFT:"ui:statusBar.left",STATUS_BAR_RIGHT:"ui:statusBar.right"};var V=class{api;dom={};allCommands=[];filteredCommands=[];selectedIndex=0;constructor(e){this.api=e,this.init()}toggle(){this.dom.modal?.classList.contains("hidden")?this.show():this.hide()}show(){this.allCommands=this.api.commands.getAll(),this.filteredCommands=this.allCommands,this.selectedIndex=0,this.renderResults(),this.dom.modal?.classList.remove("hidden"),this.dom.input?.focus()}hide(){let e=this.dom.input;e&&(e.value=""),this.dom.modal?.classList.add("hidden")}init(){let e=document.createElement("div");e.id="command-palette-modal",e.className="fixed inset-0 bg-darker/80 backdrop-blur-sm flex items-start justify-center hidden pt-24",e.style.zIndex="10000",e.style.position="fixed",e.innerHTML=g`
|
|
1700
23
|
<div class="glass-premium p-4 rounded-2xl w-full max-w-2xl animate-scale-in flex flex-col max-h-[70vh]">
|
|
1701
24
|
<input id="palette-search-input" type="text" class="form-input-premium text-lg mb-2" placeholder="Escribe un comando...">
|
|
1702
25
|
<div id="palette-results-list" class="overflow-y-auto"></div>
|
|
1703
26
|
</div>
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
this.dom.modal = paletteEl;
|
|
1707
|
-
this.dom.input = paletteEl.querySelector("#palette-search-input");
|
|
1708
|
-
this.dom.results = paletteEl.querySelector("#palette-results-list");
|
|
1709
|
-
this.attachEventListeners();
|
|
1710
|
-
}
|
|
1711
|
-
/**
|
|
1712
|
-
* Adjunta todos los listeners necesarios para la interactividad de la paleta.
|
|
1713
|
-
*/
|
|
1714
|
-
attachEventListeners() {
|
|
1715
|
-
this.dom.modal?.addEventListener("click", (e) => {
|
|
1716
|
-
if (e.target === this.dom.modal) this.hide();
|
|
1717
|
-
});
|
|
1718
|
-
this.dom.input?.addEventListener("input", () => {
|
|
1719
|
-
const searchTerm = this.dom.input.value.toLowerCase();
|
|
1720
|
-
this.filteredCommands = this.allCommands.filter(
|
|
1721
|
-
(cmd) => cmd.title.toLowerCase().includes(searchTerm) || cmd.category?.toLowerCase().includes(searchTerm)
|
|
1722
|
-
);
|
|
1723
|
-
this.selectedIndex = 0;
|
|
1724
|
-
this.renderResults();
|
|
1725
|
-
});
|
|
1726
|
-
this.dom.input?.addEventListener("keydown", (e) => {
|
|
1727
|
-
switch (e.key) {
|
|
1728
|
-
case "ArrowDown":
|
|
1729
|
-
e.preventDefault();
|
|
1730
|
-
this.selectedIndex = Math.min(this.selectedIndex + 1, this.filteredCommands.length - 1);
|
|
1731
|
-
this.renderResults();
|
|
1732
|
-
break;
|
|
1733
|
-
case "ArrowUp":
|
|
1734
|
-
e.preventDefault();
|
|
1735
|
-
this.selectedIndex = Math.max(this.selectedIndex - 1, 0);
|
|
1736
|
-
this.renderResults();
|
|
1737
|
-
break;
|
|
1738
|
-
case "Enter":
|
|
1739
|
-
e.preventDefault();
|
|
1740
|
-
this.executeSelected();
|
|
1741
|
-
break;
|
|
1742
|
-
case "Escape":
|
|
1743
|
-
this.hide();
|
|
1744
|
-
break;
|
|
1745
|
-
}
|
|
1746
|
-
});
|
|
1747
|
-
this.dom.results?.addEventListener("click", (e) => {
|
|
1748
|
-
const item = e.target.closest(".command-palette-item");
|
|
1749
|
-
if (item?.dataset.commandId) {
|
|
1750
|
-
this.api.commands.execute(item.dataset.commandId);
|
|
1751
|
-
this.hide();
|
|
1752
|
-
}
|
|
1753
|
-
});
|
|
1754
|
-
}
|
|
1755
|
-
/**
|
|
1756
|
-
* Dibuja la lista de comandos filtrados en el DOM.
|
|
1757
|
-
*/
|
|
1758
|
-
renderResults() {
|
|
1759
|
-
if (!this.dom.results) return;
|
|
1760
|
-
if (this.filteredCommands.length === 0) {
|
|
1761
|
-
this.dom.results.innerHTML = `<div class="p-4 text-center text-muted-foreground">No se encontraron comandos.</div>`;
|
|
1762
|
-
return;
|
|
1763
|
-
}
|
|
1764
|
-
this.dom.results.innerHTML = this.filteredCommands.map((cmd, index) => html`
|
|
1765
|
-
<div class="command-palette-item ${index === this.selectedIndex ? "selected" : ""}" data-command-id="${cmd.id}">
|
|
27
|
+
`,document.body.appendChild(e),this.dom.modal=e,this.dom.input=e.querySelector("#palette-search-input"),this.dom.results=e.querySelector("#palette-results-list"),this.attachEventListeners()}attachEventListeners(){this.dom.modal?.addEventListener("click",e=>{e.target===this.dom.modal&&this.hide()}),this.dom.input?.addEventListener("input",()=>{let e=this.dom.input.value.toLowerCase();this.filteredCommands=this.allCommands.filter(t=>t.title.toLowerCase().includes(e)||t.category?.toLowerCase().includes(e)),this.selectedIndex=0,this.renderResults()}),this.dom.input?.addEventListener("keydown",e=>{switch(e.key){case"ArrowDown":e.preventDefault(),this.selectedIndex=Math.min(this.selectedIndex+1,this.filteredCommands.length-1),this.renderResults();break;case"ArrowUp":e.preventDefault(),this.selectedIndex=Math.max(this.selectedIndex-1,0),this.renderResults();break;case"Enter":e.preventDefault(),this.executeSelected();break;case"Escape":this.hide();break}}),this.dom.results?.addEventListener("click",e=>{let t=e.target.closest(".command-palette-item");t?.dataset.commandId&&(this.api.commands.execute(t.dataset.commandId),this.hide())})}renderResults(){if(this.dom.results){if(this.filteredCommands.length===0){this.dom.results.innerHTML='<div class="p-4 text-center text-muted-foreground">No se encontraron comandos.</div>';return}this.dom.results.innerHTML=this.filteredCommands.map((e,t)=>g`
|
|
28
|
+
<div class="command-palette-item ${t===this.selectedIndex?"selected":""}" data-command-id="${e.id}">
|
|
1766
29
|
<div class="flex items-center gap-3">
|
|
1767
|
-
<i class="${
|
|
1768
|
-
<span>${
|
|
30
|
+
<i class="${e.icon||"fas fa-cogs"}"></i>
|
|
31
|
+
<span>${e.title}</span>
|
|
1769
32
|
</div>
|
|
1770
|
-
${
|
|
33
|
+
${e.category?`<span class="category">${e.category}</span>`:""}
|
|
1771
34
|
</div>
|
|
1772
|
-
`).join("");
|
|
1773
|
-
this.dom.results.querySelector(".selected")?.scrollIntoView({ block: "nearest" });
|
|
1774
|
-
}
|
|
1775
|
-
/**
|
|
1776
|
-
* Ejecuta el comando actualmente seleccionado en la lista.
|
|
1777
|
-
*/
|
|
1778
|
-
executeSelected() {
|
|
1779
|
-
const command = this.filteredCommands[this.selectedIndex];
|
|
1780
|
-
if (command) {
|
|
1781
|
-
this.api.commands.execute(command.id);
|
|
1782
|
-
this.hide();
|
|
1783
|
-
}
|
|
1784
|
-
}
|
|
1785
|
-
};
|
|
1786
|
-
|
|
1787
|
-
// src/core/app/commandManager.ts
|
|
1788
|
-
function registerCoreCommands(platformAPI) {
|
|
1789
|
-
const palette = new Palette(platformAPI);
|
|
1790
|
-
platformAPI.commands.register({ id: "palette.toggle", title: "Abrir Paleta de Comandos", execute: () => palette.toggle() });
|
|
1791
|
-
platformAPI.shortcuts.register({ id: "togglePalette", keys: "Control+K", commandId: "palette.toggle", description: "Abrir/Cerrar Paleta de Comandos" });
|
|
1792
|
-
platformAPI.layout.registerTopBarItem({
|
|
1793
|
-
id: "right.toggle-left-sidebar",
|
|
1794
|
-
icon: "fas fa-arrow-right-from-bracket",
|
|
1795
|
-
title: "Panel Izquierdo",
|
|
1796
|
-
commandId: "layout.toggleSidebar",
|
|
1797
|
-
order: 1
|
|
1798
|
-
});
|
|
1799
|
-
platformAPI.layout.registerTopBarItem({
|
|
1800
|
-
id: "right.toggle-right-sidebar",
|
|
1801
|
-
icon: "fas fa-arrow-left",
|
|
1802
|
-
title: "Panel Derecho",
|
|
1803
|
-
commandId: "layout.toggleSidebarRight",
|
|
1804
|
-
order: 2
|
|
1805
|
-
});
|
|
1806
|
-
platformAPI.layout.registerTopBarItem({
|
|
1807
|
-
id: "right.toggle-bottom-panel",
|
|
1808
|
-
icon: "fas fa-panel-bottom",
|
|
1809
|
-
title: "Panel Inferior",
|
|
1810
|
-
commandId: "layout.togglePanel",
|
|
1811
|
-
order: 3
|
|
1812
|
-
});
|
|
1813
|
-
platformAPI.commands.register({
|
|
1814
|
-
id: "app.showInfo",
|
|
1815
|
-
title: "Mostrar Informaci\xF3n de la App",
|
|
1816
|
-
category: "Ayuda",
|
|
1817
|
-
execute: () => {
|
|
1818
|
-
platformAPI.modals.show({
|
|
1819
|
-
title: "Acerca de Decido",
|
|
1820
|
-
content: html`<div class="text-center"><h2 class="text-2xl font-bold">Decido</h2><p class="text-lg">Tu sistema operativo para la vida.</p><p class="mt-4">Versión 0.3.1 - Estable</p></div>`
|
|
1821
|
-
});
|
|
1822
|
-
}
|
|
1823
|
-
});
|
|
1824
|
-
platformAPI.commands.register({
|
|
1825
|
-
id: "auth.showLoginModal",
|
|
1826
|
-
title: "Iniciar Sesi\xF3n",
|
|
1827
|
-
category: "Usuario",
|
|
1828
|
-
execute: () => {
|
|
1829
|
-
const modalContent = document.createElement("div");
|
|
1830
|
-
modalContent.innerHTML = html`
|
|
35
|
+
`).join(""),this.dom.results.querySelector(".selected")?.scrollIntoView({block:"nearest"})}}executeSelected(){let e=this.filteredCommands[this.selectedIndex];e&&(this.api.commands.execute(e.id),this.hide())}};function ze(i){let e=new V(i);i.commands.register({id:"palette.toggle",title:"Abrir Paleta de Comandos",execute:()=>e.toggle()}),i.shortcuts.register({id:"togglePalette",keys:"Control+K",commandId:"palette.toggle",description:"Abrir/Cerrar Paleta de Comandos"}),i.layout.registerTopBarItem({id:"right.toggle-left-sidebar",icon:"fas fa-arrow-right-from-bracket",title:"Panel Izquierdo",commandId:"layout.toggleSidebar",order:1}),i.layout.registerTopBarItem({id:"right.toggle-right-sidebar",icon:"fas fa-arrow-left",title:"Panel Derecho",commandId:"layout.toggleSidebarRight",order:2}),i.layout.registerTopBarItem({id:"right.toggle-bottom-panel",icon:"fas fa-panel-bottom",title:"Panel Inferior",commandId:"layout.togglePanel",order:3}),i.commands.register({id:"app.showInfo",title:"Mostrar Informaci\xF3n de la App",category:"Ayuda",execute:()=>{i.modals.show({title:"Acerca de Decido",content:g`<div class="text-center"><h2 class="text-2xl font-bold">Decido</h2><p class="text-lg">Tu sistema operativo para la vida.</p><p class="mt-4">Versión 0.3.1 - Estable</p></div>`})}}),i.commands.register({id:"auth.showLoginModal",title:"Iniciar Sesi\xF3n",category:"Usuario",execute:()=>{let t=document.createElement("div");t.innerHTML=g`
|
|
1831
36
|
<form id="login-form" class="space-y-4">
|
|
1832
37
|
<div><label for="email" class="journal-label">Email</label><input type="email" name="email" class="form-input-premium" required value="test@test.com"></div>
|
|
1833
38
|
<div><label for="password" class="journal-label">Contraseña</label><input type="password" name="password" class="form-input-premium" required value="password"></div>
|
|
1834
39
|
<div class="pt-4 text-right"><button type="submit" class="btn-premium">Entrar</button></div>
|
|
1835
40
|
</form>
|
|
1836
|
-
`;
|
|
1837
|
-
const modal = platformAPI.modals.show({
|
|
1838
|
-
title: "Iniciar Sesi\xF3n",
|
|
1839
|
-
content: modalContent,
|
|
1840
|
-
actions: []
|
|
1841
|
-
});
|
|
1842
|
-
modalContent.querySelector("#login-form")?.addEventListener("submit", async (e) => {
|
|
1843
|
-
e.preventDefault();
|
|
1844
|
-
const form = e.target;
|
|
1845
|
-
const email = form.elements.namedItem("email").value;
|
|
1846
|
-
const password = form.elements.namedItem("password").value;
|
|
1847
|
-
try {
|
|
1848
|
-
await platformAPI.auth.login(email, password);
|
|
1849
|
-
modal.close();
|
|
1850
|
-
} catch (error) {
|
|
1851
|
-
const errorMessage = error instanceof Error ? error.message : "Error desconocido";
|
|
1852
|
-
platformAPI.notifications.show("error", "Error de Login", errorMessage);
|
|
1853
|
-
}
|
|
1854
|
-
});
|
|
1855
|
-
}
|
|
1856
|
-
});
|
|
1857
|
-
platformAPI.commands.register({
|
|
1858
|
-
id: "auth.showRegisterModal",
|
|
1859
|
-
title: "Registrarse",
|
|
1860
|
-
category: "Usuario",
|
|
1861
|
-
execute: () => {
|
|
1862
|
-
const modalContent = document.createElement("div");
|
|
1863
|
-
modalContent.innerHTML = html`
|
|
41
|
+
`;let a=i.modals.show({title:"Iniciar Sesi\xF3n",content:t,actions:[]});t.querySelector("#login-form")?.addEventListener("submit",async o=>{o.preventDefault();let r=o.target,n=r.elements.namedItem("email").value,s=r.elements.namedItem("password").value;try{await i.auth.login(n,s),a.close()}catch(c){let m=c instanceof Error?c.message:"Error desconocido";i.notifications.show("error","Error de Login",m)}})}}),i.commands.register({id:"auth.showRegisterModal",title:"Registrarse",category:"Usuario",execute:()=>{let t=document.createElement("div");t.innerHTML=g`
|
|
1864
42
|
<form id="register-form" class="space-y-4">
|
|
1865
43
|
<div><label for="username" class="journal-label">Nombre</label><input type="text" name="username" class="form-input-premium" required></div>
|
|
1866
44
|
<div><label for="email" class="journal-label">Email</label><input type="email" name="email" class="form-input-premium" required></div>
|
|
@@ -1870,147 +48,4 @@ function registerCoreCommands(platformAPI) {
|
|
|
1870
48
|
<div class="text-center mt-4">
|
|
1871
49
|
<a href="#" class="text-sm text-accent hover:underline" data-command="auth.showLoginModal">¿Ya tienes cuenta? Inicia sesión</a>
|
|
1872
50
|
</div>
|
|
1873
|
-
`;
|
|
1874
|
-
const modal = platformAPI.modals.show({
|
|
1875
|
-
title: "Crear Cuenta",
|
|
1876
|
-
content: modalContent,
|
|
1877
|
-
actions: []
|
|
1878
|
-
});
|
|
1879
|
-
modalContent.querySelector("#register-form")?.addEventListener("submit", async (e) => {
|
|
1880
|
-
e.preventDefault();
|
|
1881
|
-
const form = e.target;
|
|
1882
|
-
const username = form.elements.namedItem("username").value;
|
|
1883
|
-
const email = form.elements.namedItem("email").value;
|
|
1884
|
-
const password = form.elements.namedItem("password").value;
|
|
1885
|
-
try {
|
|
1886
|
-
await platformAPI.auth.register(username, email, password);
|
|
1887
|
-
modal.close();
|
|
1888
|
-
platformAPI.notifications.show("success", "Registro Exitoso", "Ahora puedes iniciar sesi\xF3n.");
|
|
1889
|
-
platformAPI.commands.execute("auth.showLoginModal");
|
|
1890
|
-
} catch (error) {
|
|
1891
|
-
const errorMessage = error instanceof Error ? error.message : "Error desconocido";
|
|
1892
|
-
platformAPI.notifications.show("error", "Error de Registro", errorMessage);
|
|
1893
|
-
}
|
|
1894
|
-
});
|
|
1895
|
-
}
|
|
1896
|
-
});
|
|
1897
|
-
platformAPI.commands.register({
|
|
1898
|
-
id: "workbench.splitPane",
|
|
1899
|
-
title: "Dividir Editor",
|
|
1900
|
-
category: "Layout",
|
|
1901
|
-
execute: (api) => {
|
|
1902
|
-
const currentPanes = api.state.editorPanes();
|
|
1903
|
-
const newPaneId = `pane-${Date.now()}`;
|
|
1904
|
-
const newPane = {
|
|
1905
|
-
id: newPaneId,
|
|
1906
|
-
tabs: [],
|
|
1907
|
-
activeTabId: null
|
|
1908
|
-
};
|
|
1909
|
-
api.state.setEditorPanes([...currentPanes, newPane]);
|
|
1910
|
-
api.state.setActivePaneId(newPaneId);
|
|
1911
|
-
}
|
|
1912
|
-
});
|
|
1913
|
-
platformAPI.commands.register({
|
|
1914
|
-
id: "workbench.openTab",
|
|
1915
|
-
title: "Abrir Vista en Editor",
|
|
1916
|
-
category: "Layout",
|
|
1917
|
-
execute: (api, tabData) => {
|
|
1918
|
-
const { state, layout } = api;
|
|
1919
|
-
let panes = state.editorPanes();
|
|
1920
|
-
let activePaneId2 = state.activePaneId();
|
|
1921
|
-
if (panes.length === 0) {
|
|
1922
|
-
const newPane = {
|
|
1923
|
-
id: `pane-${Date.now()}`,
|
|
1924
|
-
tabs: [],
|
|
1925
|
-
activeTabId: null
|
|
1926
|
-
};
|
|
1927
|
-
panes = [newPane];
|
|
1928
|
-
activePaneId2 = newPane.id;
|
|
1929
|
-
state.setActivePaneId(activePaneId2);
|
|
1930
|
-
}
|
|
1931
|
-
const targetPane = panes.find((p) => p.id === activePaneId2);
|
|
1932
|
-
const tabExists = targetPane.tabs.some((t) => t.id === tabData.id);
|
|
1933
|
-
if (!tabExists) {
|
|
1934
|
-
targetPane.tabs.push(tabData);
|
|
1935
|
-
}
|
|
1936
|
-
targetPane.activeTabId = tabData.id;
|
|
1937
|
-
state.setEditorPanes([...panes]);
|
|
1938
|
-
}
|
|
1939
|
-
});
|
|
1940
|
-
platformAPI.commands.register({
|
|
1941
|
-
id: "workbench.focusTab",
|
|
1942
|
-
title: "Enfocar Vista",
|
|
1943
|
-
execute: (api, { paneId, tabId }) => {
|
|
1944
|
-
const { state } = api;
|
|
1945
|
-
const panes = state.editorPanes();
|
|
1946
|
-
const targetPane = panes.find((p) => p.id === paneId);
|
|
1947
|
-
if (targetPane) {
|
|
1948
|
-
targetPane.activeTabId = tabId;
|
|
1949
|
-
state.setActivePaneId(paneId);
|
|
1950
|
-
state.setEditorPanes([...panes]);
|
|
1951
|
-
}
|
|
1952
|
-
}
|
|
1953
|
-
});
|
|
1954
|
-
platformAPI.commands.register({
|
|
1955
|
-
id: "workbench.closeTab",
|
|
1956
|
-
title: "Cerrar Vista",
|
|
1957
|
-
execute: (api, { paneId, tabId }) => {
|
|
1958
|
-
const { state } = api;
|
|
1959
|
-
let panes = state.editorPanes();
|
|
1960
|
-
const targetPane = panes.find((p) => p.id === paneId);
|
|
1961
|
-
if (!targetPane) return;
|
|
1962
|
-
const remainingTabs = targetPane.tabs.filter((t) => t.id !== tabId);
|
|
1963
|
-
if (remainingTabs.length === 0 && panes.length > 1) {
|
|
1964
|
-
panes = panes.filter((p) => p.id !== paneId);
|
|
1965
|
-
const newActivePaneId = panes[panes.length - 1]?.id || null;
|
|
1966
|
-
state.setActivePaneId(newActivePaneId);
|
|
1967
|
-
} else {
|
|
1968
|
-
targetPane.tabs = remainingTabs;
|
|
1969
|
-
if (targetPane.activeTabId === tabId) {
|
|
1970
|
-
targetPane.activeTabId = remainingTabs[remainingTabs.length - 1]?.id || null;
|
|
1971
|
-
}
|
|
1972
|
-
}
|
|
1973
|
-
state.setEditorPanes([...panes]);
|
|
1974
|
-
}
|
|
1975
|
-
});
|
|
1976
|
-
}
|
|
1977
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
1978
|
-
0 && (module.exports = {
|
|
1979
|
-
ApiService,
|
|
1980
|
-
AuthService,
|
|
1981
|
-
BaseService,
|
|
1982
|
-
CORE_HOOK_NAMES,
|
|
1983
|
-
CORE_SLOT_NAMES,
|
|
1984
|
-
CalendarService,
|
|
1985
|
-
CommandService,
|
|
1986
|
-
DebugService,
|
|
1987
|
-
DecidoDB,
|
|
1988
|
-
GamificationService,
|
|
1989
|
-
HookService,
|
|
1990
|
-
ModalService,
|
|
1991
|
-
ModuleManager,
|
|
1992
|
-
NotificationService,
|
|
1993
|
-
RouterService,
|
|
1994
|
-
ServiceContainer,
|
|
1995
|
-
ShortcutService,
|
|
1996
|
-
StorageService,
|
|
1997
|
-
SyncService,
|
|
1998
|
-
ThemeService,
|
|
1999
|
-
apiService,
|
|
2000
|
-
authService,
|
|
2001
|
-
createEffect,
|
|
2002
|
-
createMemo,
|
|
2003
|
-
createPlatformAPI,
|
|
2004
|
-
createSignal,
|
|
2005
|
-
db,
|
|
2006
|
-
formatDate,
|
|
2007
|
-
html,
|
|
2008
|
-
initEventListeners,
|
|
2009
|
-
makeDraggable,
|
|
2010
|
-
processModuleDefinitions,
|
|
2011
|
-
registerCoreCommands,
|
|
2012
|
-
routerService,
|
|
2013
|
-
storageService,
|
|
2014
|
-
syncService,
|
|
2015
|
-
themeService
|
|
2016
|
-
});
|
|
51
|
+
`;let a=i.modals.show({title:"Crear Cuenta",content:t,actions:[]});t.querySelector("#register-form")?.addEventListener("submit",async o=>{o.preventDefault();let r=o.target,n=r.elements.namedItem("username").value,s=r.elements.namedItem("email").value,c=r.elements.namedItem("password").value;try{await i.auth.register(n,s,c),a.close(),i.notifications.show("success","Registro Exitoso","Ahora puedes iniciar sesi\xF3n."),i.commands.execute("auth.showLoginModal")}catch(m){let p=m instanceof Error?m.message:"Error desconocido";i.notifications.show("error","Error de Registro",p)}})}}),i.commands.register({id:"workbench.splitPane",title:"Dividir Editor",category:"Layout",execute:t=>{let a=t.state.editorPanes(),o=`pane-${Date.now()}`,r={id:o,tabs:[],activeTabId:null};t.state.setEditorPanes([...a,r]),t.state.setActivePaneId(o)}}),i.commands.register({id:"workbench.openTab",title:"Abrir Vista en Editor",category:"Layout",execute:(t,a)=>{let{state:o,layout:r}=t,n=o.editorPanes(),s=o.activePaneId();if(n.length===0){let p={id:`pane-${Date.now()}`,tabs:[],activeTabId:null};n=[p],s=p.id,o.setActivePaneId(s)}let c=n.find(p=>p.id===s);c.tabs.some(p=>p.id===a.id)||c.tabs.push(a),c.activeTabId=a.id,o.setEditorPanes([...n])}}),i.commands.register({id:"workbench.focusTab",title:"Enfocar Vista",execute:(t,{paneId:a,tabId:o})=>{let{state:r}=t,n=r.editorPanes(),s=n.find(c=>c.id===a);s&&(s.activeTabId=o,r.setActivePaneId(a),r.setEditorPanes([...n]))}}),i.commands.register({id:"workbench.closeTab",title:"Cerrar Vista",execute:(t,{paneId:a,tabId:o})=>{let{state:r}=t,n=r.editorPanes(),s=n.find(m=>m.id===a);if(!s)return;let c=s.tabs.filter(m=>m.id!==o);if(c.length===0&&n.length>1){n=n.filter(p=>p.id!==a);let m=n[n.length-1]?.id||null;r.setActivePaneId(m)}else s.tabs=c,s.activeTabId===o&&(s.activeTabId=c[c.length-1]?.id||null);r.setEditorPanes([...n])}})}0&&(module.exports={ApiService,AuthService,BaseService,CORE_HOOK_NAMES,CORE_SLOT_NAMES,CalendarService,CommandService,DebugService,DecidoDB,GamificationService,HookService,ModalService,ModuleManager,NotificationService,RouterService,ServiceContainer,ShortcutService,StorageService,SyncService,ThemeService,apiService,authService,createEffect,createMemo,createPlatformAPI,createSignal,db,formatDate,html,initEventListeners,makeDraggable,processModuleDefinitions,registerCoreCommands,routerService,storageService,syncService,themeService});
|