@decido/shell-vscode-core 4.0.1 → 4.0.2
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/package.json +14 -13
- package/.turbo/turbo-build.log +0 -13
- package/CHANGELOG.md +0 -31
- package/src/appState.ts +0 -167
- package/src/core/AIService.ts +0 -109
- package/src/core/ApiService.ts +0 -40
- package/src/core/AuthService.ts +0 -85
- package/src/core/BaseService.ts +0 -47
- package/src/core/CalendarService.ts +0 -44
- package/src/core/CommandService.ts +0 -69
- package/src/core/DebugPanelService.ts +0 -38
- package/src/core/DebugService.ts +0 -181
- package/src/core/EventBus.ts +0 -60
- package/src/core/EventHandler.ts +0 -97
- package/src/core/GamificationService.ts +0 -120
- package/src/core/HookService.ts +0 -86
- package/src/core/ModalService.ts +0 -97
- package/src/core/NotificationService.ts +0 -53
- package/src/core/RouterService.ts +0 -68
- package/src/core/ServiceContainer.ts +0 -31
- package/src/core/ShortcutService.ts +0 -49
- package/src/core/StorageService.ts +0 -123
- package/src/core/ThemeService.ts +0 -71
- package/src/core/WebSocketService.ts +0 -32
- package/src/core/api.ts +0 -78
- package/src/core/app/ModuleManager.ts +0 -273
- package/src/core/app/apiFactory.ts +0 -130
- package/src/core/app/commandManager.ts +0 -218
- package/src/core/app/moduleLoader.ts +0 -39
- package/src/core/app/routeManager.ts +0 -8
- package/src/core/index.ts +0 -15
- package/src/core/signals.ts +0 -84
- package/src/core/uiState.ts +0 -13
- package/src/index.ts +0 -18
- package/src/lib/local-db.ts +0 -65
- package/src/lib/sync-service.ts +0 -44
- package/src/platform/ILayoutService.ts +0 -77
- package/src/platform/IRenderer.ts +0 -16
- package/src/platform/ServiceRegistry.ts +0 -53
- package/src/platform/extensionPoints.ts +0 -202
- package/src/platform/index.ts +0 -4
- package/src/stores/editorStore.ts +0 -6
- package/src/stores/gamificationStore.ts +0 -4
- package/src/stores/historyStore.ts +0 -14
- package/src/stores/workspaceStore.ts +0 -8
- package/src/types/app.ts +0 -36
- package/src/types/debug.ts +0 -69
- package/src/types/index.ts +0 -3
- package/src/types/platform.ts +0 -112
- package/src/ui/Palette.ts +0 -161
- package/src/utils.ts +0 -63
- package/tsconfig.json +0 -23
package/package.json
CHANGED
|
@@ -1,18 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decido/shell-vscode-core",
|
|
3
|
-
"version": "4.0.
|
|
4
|
-
"main": "dist/index.js",
|
|
3
|
+
"version": "4.0.2",
|
|
4
|
+
"main": "./dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"exports": {
|
|
7
|
-
".":
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
"./services": "./dist/core/index.js",
|
|
14
|
-
"./platform": "./dist/platform/index.js",
|
|
15
|
-
"./signals": "./dist/core/signals.js"
|
|
7
|
+
".": {
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"import": "./dist/index.mjs",
|
|
10
|
+
"require": "./dist/index.js",
|
|
11
|
+
"default": "./dist/index.mjs"
|
|
12
|
+
}
|
|
16
13
|
},
|
|
17
14
|
"dependencies": {
|
|
18
15
|
"@types/react": "^19.2.7",
|
|
@@ -20,7 +17,7 @@
|
|
|
20
17
|
"lit-html": "^3.3.1",
|
|
21
18
|
"react": "^18.3.1",
|
|
22
19
|
"socket.io-client": "^4.8.1",
|
|
23
|
-
"@decido/kernel-bridge": "4.0.
|
|
20
|
+
"@decido/kernel-bridge": "4.0.2"
|
|
24
21
|
},
|
|
25
22
|
"devDependencies": {
|
|
26
23
|
"typescript": "^5.5.2"
|
|
@@ -29,8 +26,12 @@
|
|
|
29
26
|
"access": "public"
|
|
30
27
|
},
|
|
31
28
|
"license": "UNLICENSED",
|
|
29
|
+
"files": [
|
|
30
|
+
"dist"
|
|
31
|
+
],
|
|
32
|
+
"module": "./dist/index.mjs",
|
|
32
33
|
"scripts": {
|
|
33
|
-
"build": "tsup src/index.ts --format esm
|
|
34
|
+
"build": "tsup src/index.ts --format esm,cjs",
|
|
34
35
|
"dev": "tsc -w",
|
|
35
36
|
"clean": "rimraf node_modules"
|
|
36
37
|
}
|
package/.turbo/turbo-build.log
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
Debugger listening on ws://127.0.0.1:58988/416d46af-e9d2-4022-8c63-fb7988c63c54
|
|
3
|
-
For help, see: https://nodejs.org/en/docs/inspector
|
|
4
|
-
Debugger attached.
|
|
5
|
-
|
|
6
|
-
> @decido/core@1.0.0 build /Users/julioramirez/dev/active/OnBoardingDecido/packages/shell-vscode/core
|
|
7
|
-
> tsc
|
|
8
|
-
|
|
9
|
-
Debugger listening on ws://127.0.0.1:58993/8240c74c-acca-4edc-9de1-0d7097b0f29f
|
|
10
|
-
For help, see: https://nodejs.org/en/docs/inspector
|
|
11
|
-
Debugger attached.
|
|
12
|
-
Waiting for the debugger to disconnect...
|
|
13
|
-
Waiting for the debugger to disconnect...
|
package/CHANGELOG.md
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
# @decido/shell-vscode-core
|
|
2
|
-
|
|
3
|
-
## 4.0.1
|
|
4
|
-
|
|
5
|
-
### Patch Changes
|
|
6
|
-
|
|
7
|
-
- readme
|
|
8
|
-
- Updated dependencies
|
|
9
|
-
- @decido/kernel-bridge@4.0.1
|
|
10
|
-
|
|
11
|
-
## 4.0.0
|
|
12
|
-
|
|
13
|
-
### Minor Changes
|
|
14
|
-
|
|
15
|
-
- build
|
|
16
|
-
|
|
17
|
-
### Patch Changes
|
|
18
|
-
|
|
19
|
-
- Updated dependencies
|
|
20
|
-
- @decido/kernel-bridge@4.0.0
|
|
21
|
-
|
|
22
|
-
## 3.0.0
|
|
23
|
-
|
|
24
|
-
### Minor Changes
|
|
25
|
-
|
|
26
|
-
- eef837b: quitar codigo fuente
|
|
27
|
-
|
|
28
|
-
### Patch Changes
|
|
29
|
-
|
|
30
|
-
- Updated dependencies [eef837b]
|
|
31
|
-
- @decido/kernel-bridge@3.0.0
|
package/src/appState.ts
DELETED
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
// src/appState.ts
|
|
2
|
-
|
|
3
|
-
import { createSignal } from "./core/signals";
|
|
4
|
-
import { StorageService } from "./core/StorageService";
|
|
5
|
-
import { Pane, GamificationState, CalendarEvent } from "./types";
|
|
6
|
-
|
|
7
|
-
export * from "./stores/editorStore";
|
|
8
|
-
export * from "./stores/gamificationStore";
|
|
9
|
-
export * from "./stores/workspaceStore";
|
|
10
|
-
export * from "./stores/historyStore";
|
|
11
|
-
|
|
12
|
-
import { editorPanes, setEditorPanes, setActivePaneId, activePaneId } from "./stores/editorStore";
|
|
13
|
-
import { gamification, setGamification } from "./stores/gamificationStore";
|
|
14
|
-
import { history, setHistory, isTimeTraveling } from "./stores/historyStore";
|
|
15
|
-
let isDebuggingTimeTravel = false; // Flag interna para el modo de depuración
|
|
16
|
-
// --- LÓGICA DE MANEJO DE ESTADO ---
|
|
17
|
-
|
|
18
|
-
const storage = new StorageService(); // Instancia del servicio
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Carga el estado inicial de la aplicación desde IndexedDB usando el StorageService.
|
|
25
|
-
* @param storage El servicio de almacenamiento para interactuar con la BD.
|
|
26
|
-
*/
|
|
27
|
-
// Esta función es más genérica y fácil de mantener
|
|
28
|
-
export async function initializeStateFromStorage(storage: StorageService) {
|
|
29
|
-
console.log("💾 Cargando estado desde IndexedDB...");
|
|
30
|
-
|
|
31
|
-
const stateMap = [
|
|
32
|
-
// Para objetos únicos
|
|
33
|
-
{ key: 'gamification', setter: setGamification, isSingle: true },
|
|
34
|
-
{ key: 'editorPanes', setter: setEditorPanes, isSingle: true },
|
|
35
|
-
{ key: 'activePaneId', setter: setActivePaneId, isSingle: true }
|
|
36
|
-
];
|
|
37
|
-
|
|
38
|
-
for (const item of stateMap) {
|
|
39
|
-
const value = item.isSingle
|
|
40
|
-
? await storage.getValue(item.key)
|
|
41
|
-
: await storage.getCollection(item.key);
|
|
42
|
-
|
|
43
|
-
if (value !== undefined && value !== null && Array.isArray(value) && value.length > 0) {
|
|
44
|
-
// @ts-ignore
|
|
45
|
-
item.setter(value);
|
|
46
|
-
} else if (value !== undefined && value !== null && !Array.isArray(value)) {
|
|
47
|
-
// @ts-ignore
|
|
48
|
-
item.setter(value);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// Si después de cargar, no hay paneles, crea uno por defecto.
|
|
53
|
-
if (editorPanes().length === 0) {
|
|
54
|
-
console.log("No se encontró layout de editor, creando uno por defecto.");
|
|
55
|
-
const defaultPane: Pane = {
|
|
56
|
-
id: 'pane-main',
|
|
57
|
-
tabs: [{
|
|
58
|
-
id: 'welcome',
|
|
59
|
-
title: 'Bienvenido',
|
|
60
|
-
componentTag: 'welcome-view',
|
|
61
|
-
icon: 'fas fa-hand-sparkles'
|
|
62
|
-
}],
|
|
63
|
-
activeTabId: 'welcome'
|
|
64
|
-
};
|
|
65
|
-
setEditorPanes([defaultPane]);
|
|
66
|
-
setActivePaneId(defaultPane.id);
|
|
67
|
-
}
|
|
68
|
-
console.log("✅ Estado cargado desde IndexedDB.");
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Una bandera para evitar que el viaje en el tiempo se grabe a sí mismo en el historial
|
|
72
|
-
let isTimeTravelingLocal = false;
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Función central y ÚNICA para modificar el estado de la aplicación.
|
|
76
|
-
* Es llamada por los Servicios de Lógica de Negocio.
|
|
77
|
-
* @param action Un nombre descriptivo para el cambio (ej: 'TASK:CREATE').
|
|
78
|
-
* @param updater Una función que realiza el cambio de estado en memoria (llama a un setter).
|
|
79
|
-
* @param persistenceFn Una función asíncrona que guarda los cambios en la base de datos.
|
|
80
|
-
*/
|
|
81
|
-
export function updateState(action: string, updater: () => void, persistenceFn?: () => Promise<void>) {
|
|
82
|
-
if (isTimeTraveling()) {
|
|
83
|
-
console.warn(`[STATE] Escritura bloqueada (${action}). La aplicación está en modo de revisión de solo lectura.`);
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
if (!isDebuggingTimeTravel) {
|
|
88
|
-
const snapshot = getFullStateSnapshot();
|
|
89
|
-
setHistory(prev => [...prev, { id: prev.length, timestamp: new Date(), action, snapshot }]);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// 1. Actualización optimista en la UI (en memoria)
|
|
93
|
-
updater();
|
|
94
|
-
|
|
95
|
-
// 2. Persistencia asíncrona en segundo plano
|
|
96
|
-
if (persistenceFn) {
|
|
97
|
-
persistenceFn().catch(err => {
|
|
98
|
-
console.error(`[STATE] Fallo de persistencia en la acción '${action}':`, err);
|
|
99
|
-
// Aquí se podría implementar una lógica de "rollback" o reintento.
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
// --- FUNCIONES DE AYUDA Y DE INICIALIZACIÓN ---
|
|
106
|
-
// (Estas funciones como `getFullStateSnapshot`, `restoreStateFromSnapshot`,
|
|
107
|
-
// `initializeStateFromStorage`, `timeTravelLocal`, etc., se quedan aquí,
|
|
108
|
-
// ya que operan directamente sobre el conjunto del estado).
|
|
109
|
-
|
|
110
|
-
export function getFullStateSnapshot(): any {
|
|
111
|
-
return {
|
|
112
|
-
gamification: gamification(),
|
|
113
|
-
editorPanes: editorPanes(),
|
|
114
|
-
activePaneId: activePaneId(),
|
|
115
|
-
// ... el resto de tu estado ...
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
export function restoreStateFromSnapshot(snapshot: any) {
|
|
120
|
-
if (!snapshot) return;
|
|
121
|
-
setGamification(snapshot.gamification || { xp: 0, level: 1, streak: 0, lastJournalDate: null, unlockedAchievements: [], achievements: [] });
|
|
122
|
-
setEditorPanes(snapshot.editorPanes || []);
|
|
123
|
-
setActivePaneId(snapshot.activePaneId || null);
|
|
124
|
-
// ... el resto de tus setters ...
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
export function timeTravelLocal(historyIndex: number) {
|
|
128
|
-
const log = history();
|
|
129
|
-
if (!log[historyIndex]) return;
|
|
130
|
-
|
|
131
|
-
isDebuggingTimeTravel = true;
|
|
132
|
-
restoreStateFromSnapshot(log[historyIndex].snapshot);
|
|
133
|
-
setHistory(log.slice(0, historyIndex + 1));
|
|
134
|
-
isDebuggingTimeTravel = false;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
export function timeTravel(historyIndex: number) {
|
|
138
|
-
const log = history();
|
|
139
|
-
if (!log[historyIndex]) return;
|
|
140
|
-
|
|
141
|
-
// Obtenemos la "foto" del estado que queremos restaurar
|
|
142
|
-
const snapshot = log[historyIndex].snapshot;
|
|
143
|
-
|
|
144
|
-
// Activamos la bandera para que `updateState` no grabe este cambio
|
|
145
|
-
isTimeTravelingLocal = true;
|
|
146
|
-
|
|
147
|
-
// Restauramos el estado llamando a los setters originales
|
|
148
|
-
// Esto es un ejemplo, debes hacerlo para todas tus señales
|
|
149
|
-
// setUser(snapshot.user);
|
|
150
|
-
// setAppSettings(snapshot.settings);
|
|
151
|
-
// setActiveView(snapshot.activeView);
|
|
152
|
-
|
|
153
|
-
console.log(`✈️ Viajando en el tiempo al estado ${historyIndex}`, snapshot);
|
|
154
|
-
|
|
155
|
-
// Cortamos el historial para que el estado actual sea el final de la línea de tiempo
|
|
156
|
-
setHistory(log.slice(0, historyIndex + 1));
|
|
157
|
-
|
|
158
|
-
// Desactivamos la bandera
|
|
159
|
-
isTimeTravelingLocal = false;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Ejemplo de cómo usarlo en tu app:
|
|
163
|
-
/*
|
|
164
|
-
updateState('SET_USER_NAME', () => {
|
|
165
|
-
setUserName('Nuevo Nombre');
|
|
166
|
-
});
|
|
167
|
-
*/
|
package/src/core/AIService.ts
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
// File: packages/core/src/core/AIService.ts
|
|
2
|
-
|
|
3
|
-
import { IPlatformAPI } from './api.js';
|
|
4
|
-
import { createSignal, Signal } from './signals.js';
|
|
5
|
-
|
|
6
|
-
export interface AIServiceOptions {
|
|
7
|
-
// Si es `true`, devuelve una señal que se actualiza en tiempo real.
|
|
8
|
-
// Si es `false`, devuelve una Promesa con el resultado completo.
|
|
9
|
-
stream?: boolean;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Servicio central para interactuar con las capacidades de IA de la plataforma.
|
|
14
|
-
* Abstrae las llamadas al backend de Genkit y gestiona el streaming de respuestas.
|
|
15
|
-
*/
|
|
16
|
-
export class AIService {
|
|
17
|
-
private api!: IPlatformAPI;
|
|
18
|
-
|
|
19
|
-
public init(api: IPlatformAPI): void {
|
|
20
|
-
this.api = api;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Ejecuta un flujo de Genkit definido en el backend.
|
|
25
|
-
* @param flowId El ID del flujo a ejecutar (ej. 'decidoFlow').
|
|
26
|
-
* @param payload El objeto de entrada para el flujo, con `promptKey` y `context`.
|
|
27
|
-
* @param options Opciones de ejecución, como habilitar el streaming.
|
|
28
|
-
* @returns Si stream=true, devuelve el getter de una señal. Si no, una Promesa con el resultado final.
|
|
29
|
-
*/
|
|
30
|
-
public runFlow<T = string>(
|
|
31
|
-
flowId: string,
|
|
32
|
-
payload: { promptKey: string, context: Record<string, unknown> | unknown },
|
|
33
|
-
options: { stream: true }
|
|
34
|
-
): Signal<T>[0]; // Devuelve el getter de la señal
|
|
35
|
-
public runFlow<T = string>(
|
|
36
|
-
flowId: string,
|
|
37
|
-
payload: { promptKey: string, context: Record<string, unknown> | unknown },
|
|
38
|
-
options?: { stream?: false }
|
|
39
|
-
): Promise<T>; // Devuelve una Promesa
|
|
40
|
-
public runFlow<T = string>(
|
|
41
|
-
flowId: string,
|
|
42
|
-
payload: { promptKey: string, context: Record<string, unknown> | unknown },
|
|
43
|
-
options: AIServiceOptions = {}
|
|
44
|
-
): Promise<T> | Signal<T>[0] {
|
|
45
|
-
const { stream = false } = options;
|
|
46
|
-
|
|
47
|
-
if (!stream) {
|
|
48
|
-
// Caso simple: No streaming. Ejecución directa HTTP
|
|
49
|
-
return new Promise<T>(async (resolve, reject) => {
|
|
50
|
-
try {
|
|
51
|
-
const token = localStorage.getItem('decido-token');
|
|
52
|
-
const response = await fetch(`http://localhost:8888/flow/${flowId}`, {
|
|
53
|
-
method: 'POST',
|
|
54
|
-
headers: {
|
|
55
|
-
'Content-Type': 'application/json',
|
|
56
|
-
'Authorization': `Bearer ${token}`
|
|
57
|
-
},
|
|
58
|
-
body: JSON.stringify(payload)
|
|
59
|
-
});
|
|
60
|
-
if (!response.ok) throw new Error(`HTTP Error: ${response.statusText}`);
|
|
61
|
-
const json = await response.json();
|
|
62
|
-
resolve(json as T);
|
|
63
|
-
} catch (e) {
|
|
64
|
-
reject(e);
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// --- Caso Avanzado: Streaming ---
|
|
70
|
-
const [getStreamedResponse, setStreamedResponse] = createSignal("" as any);
|
|
71
|
-
|
|
72
|
-
// Envolvemos la lógica de streaming en una función asíncrona
|
|
73
|
-
const startStreaming = async () => {
|
|
74
|
-
try {
|
|
75
|
-
const token = localStorage.getItem('decido-token');
|
|
76
|
-
const response = await fetch(`http://localhost:8888/flow/${flowId}/stream`, {
|
|
77
|
-
method: 'POST',
|
|
78
|
-
headers: {
|
|
79
|
-
'Content-Type': 'application/json',
|
|
80
|
-
'Authorization': `Bearer ${token}`
|
|
81
|
-
},
|
|
82
|
-
body: JSON.stringify(payload),
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
if (!response.ok || !response.body) {
|
|
86
|
-
throw new Error(`Error en la respuesta del servidor: ${response.statusText}`);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const reader = response.body.getReader();
|
|
90
|
-
const decoder = new TextDecoder();
|
|
91
|
-
let fullText = "";
|
|
92
|
-
|
|
93
|
-
while (true) {
|
|
94
|
-
const { done, value } = await reader.read();
|
|
95
|
-
if (done) break;
|
|
96
|
-
|
|
97
|
-
fullText += decoder.decode(value, { stream: true });
|
|
98
|
-
setStreamedResponse(fullText);
|
|
99
|
-
}
|
|
100
|
-
} catch (error) {
|
|
101
|
-
console.error("[AIService] Error durante el streaming:", error);
|
|
102
|
-
setStreamedResponse("Error al generar la respuesta." as any);
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
startStreaming();
|
|
107
|
-
return getStreamedResponse; // Devolvemos el getter inmediatamente
|
|
108
|
-
}
|
|
109
|
-
}
|
package/src/core/ApiService.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import type { AuthService } from "./AuthService";
|
|
2
|
-
|
|
3
|
-
const API_BASE_URL = 'http://localhost:8888/api';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Clase para gestionar las interacciones con la API del backend.
|
|
7
|
-
* Encapsula la lógica de fetch, la gestión de errores y la autenticación.
|
|
8
|
-
*/
|
|
9
|
-
export class ApiService {
|
|
10
|
-
public id = Math.random().toString(36).substr(2, 9);
|
|
11
|
-
private authService!: AuthService;
|
|
12
|
-
|
|
13
|
-
public init(authService: AuthService) {
|
|
14
|
-
console.log(`[ApiService:${this.id}] init called`);
|
|
15
|
-
this.authService = authService;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
async fetch<T = unknown>(endpoint: string, options: RequestInit = {}, isText = false): Promise<T> {
|
|
19
|
-
console.log(`[ApiService Mock] Ignorando invocación de red a: ${endpoint}`);
|
|
20
|
-
return {} as T;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
async login(email: string, password: string): Promise<unknown> { return {}; }
|
|
24
|
-
async refresh(refreshToken: string): Promise<{ token: string }> { return { token: "dev" }; }
|
|
25
|
-
async register(username: string, email: string, password: string): Promise<unknown> { return {}; }
|
|
26
|
-
logout(): void { }
|
|
27
|
-
async getProfile(): Promise<{ id: number; name: string }> { return { id: 1, name: "Local Dev" }; }
|
|
28
|
-
async updateProfile(profileData: Record<string, unknown>): Promise<Record<string, unknown>> { return profileData; }
|
|
29
|
-
|
|
30
|
-
// IA & Marketplace Mocks
|
|
31
|
-
async getAIProjectPlan(goal: { title: string; coreValueId: string }): Promise<unknown> { return {}; }
|
|
32
|
-
async generateBlueprint(goalData: Record<string, unknown>): Promise<string> { return ""; }
|
|
33
|
-
async getAIGoalSuggestion(idea: string): Promise<unknown> { return {}; }
|
|
34
|
-
async getRefinedText(text: string, context: string): Promise<string> { return text; }
|
|
35
|
-
async getModules(): Promise<unknown[]> { return []; }
|
|
36
|
-
async uploadModule(formData: FormData): Promise<unknown> { return {}; }
|
|
37
|
-
async generateTheme(prompt: string): Promise<unknown> { return {}; }
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export const apiService = new ApiService();
|
package/src/core/AuthService.ts
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import { createSignal, Signal } from './signals.js';
|
|
2
|
-
import type { ApiService } from './ApiService.js'; // Type-only import to break cycle
|
|
3
|
-
|
|
4
|
-
type AuthStatus = 'loading' | 'authenticated' | 'unauthenticated' | 'error';
|
|
5
|
-
|
|
6
|
-
//TODO: Completar propiedades
|
|
7
|
-
interface User {
|
|
8
|
-
id: string | number;
|
|
9
|
-
name: string;
|
|
10
|
-
email: string;
|
|
11
|
-
// ... otras propiedades del usuario
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
interface Session {
|
|
15
|
-
user: User | null;
|
|
16
|
-
token: string | null;
|
|
17
|
-
status: AuthStatus;
|
|
18
|
-
error?: string;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export class AuthService {
|
|
22
|
-
private apiService!: ApiService;
|
|
23
|
-
public session: Signal<Session>;
|
|
24
|
-
|
|
25
|
-
constructor() {
|
|
26
|
-
this.session = createSignal<Session>({
|
|
27
|
-
user: null,
|
|
28
|
-
token: null,
|
|
29
|
-
status: 'loading',
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
public init(apiService: ApiService) {
|
|
34
|
-
this.apiService = apiService;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
async checkSession() {
|
|
38
|
-
const fakeUser: User = { id: 1, name: "Local Dev", email: "dev@local.host" };
|
|
39
|
-
this.setSession({ user: fakeUser, token: "local-dev-token", status: 'authenticated' });
|
|
40
|
-
console.log('[Auth] CheckSession local - Auto autenticado.');
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
login = async (email: any, password: any) => {
|
|
44
|
-
const fakeUser: User = { id: 1, name: "Local Dev", email };
|
|
45
|
-
this.setSession({ user: fakeUser, token: "local-dev-token", status: 'authenticated' });
|
|
46
|
-
|
|
47
|
-
const fullscreenContainer = document.getElementById('fullscreen-view-container');
|
|
48
|
-
if (fullscreenContainer) fullscreenContainer.innerHTML = '';
|
|
49
|
-
const appContainer = document.getElementById('app');
|
|
50
|
-
if (appContainer) appContainer.style.display = 'block';
|
|
51
|
-
return fakeUser;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
async register(username: string, email: string, password: string): Promise<any> {
|
|
55
|
-
return { success: true };
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
public logout = () => {
|
|
59
|
-
this.setSession({ user: null, token: null, status: 'unauthenticated' });
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
refreshToken = async (): Promise<string | null> => {
|
|
63
|
-
return "local-dev-token";
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
private listeners = new Set<(session: Session) => void>();
|
|
67
|
-
|
|
68
|
-
public subscribe(cb: (session: Session) => void) {
|
|
69
|
-
this.listeners.add(cb);
|
|
70
|
-
cb(this.session[0]());
|
|
71
|
-
return () => {
|
|
72
|
-
this.listeners.delete(cb);
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
private setSession(partialState: Partial<Session>) {
|
|
77
|
-
const [get, set] = this.session;
|
|
78
|
-
set({ ...get(), ...partialState });
|
|
79
|
-
const newState = get();
|
|
80
|
-
this.listeners.forEach(cb => cb(newState));
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Exportamos una instancia única para toda la aplicación
|
|
85
|
-
export const authService = new AuthService();
|
package/src/core/BaseService.ts
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { StorageService } from './StorageService.js';
|
|
2
|
-
import { HookService } from './HookService.js';
|
|
3
|
-
// import { updateState } from '../appState.js';
|
|
4
|
-
import { ServiceContainer } from './ServiceContainer.js';
|
|
5
|
-
import { NotificationService } from './NotificationService.js';
|
|
6
|
-
import { GamificationService } from './GamificationService.js';
|
|
7
|
-
import { IPlatformAPI } from './api.js';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* La clase base para todos los servicios de lógica de negocio.
|
|
11
|
-
* Utiliza el ServiceContainer para obtener sus dependencias, promoviendo
|
|
12
|
-
* un bajo acoplamiento.
|
|
13
|
-
*/
|
|
14
|
-
export class BaseService {
|
|
15
|
-
// Las dependencias comunes se declaran como protegidas
|
|
16
|
-
protected storage: StorageService;
|
|
17
|
-
protected hooks: HookService;
|
|
18
|
-
protected notifications: NotificationService;
|
|
19
|
-
protected gamification: GamificationService;
|
|
20
|
-
protected api: IPlatformAPI;
|
|
21
|
-
protected container: ServiceContainer;
|
|
22
|
-
|
|
23
|
-
constructor(container: ServiceContainer) {
|
|
24
|
-
// Cada servicio base pide al contenedor lo que necesita.
|
|
25
|
-
this.container = container;
|
|
26
|
-
this.storage = container.get('storage');
|
|
27
|
-
this.hooks = container.get('hooks');
|
|
28
|
-
this.notifications = container.get('notifications');
|
|
29
|
-
this.gamification = container.get('gamification');
|
|
30
|
-
this.api = container.get('api');
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Envuelve la función global `updateState`.
|
|
35
|
-
* Este es el único punto de entrada para realizar cambios de estado persistentes.
|
|
36
|
-
* @param action El nombre de la acción para el historial de depuración (ej: 'TASK:CREATE').
|
|
37
|
-
* @param updater La función que modifica la señal de estado en memoria.
|
|
38
|
-
* @param persistenceFn La función asíncrona que guarda el cambio en IndexedDB.
|
|
39
|
-
*/
|
|
40
|
-
protected executeUpdate(
|
|
41
|
-
action: string,
|
|
42
|
-
updater: () => void,
|
|
43
|
-
persistenceFn: () => Promise<void>
|
|
44
|
-
) {
|
|
45
|
-
// updateState(action, updater, persistenceFn);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
// /src/core/CalendarService.ts
|
|
2
|
-
|
|
3
|
-
import { CalendarEvent } from '../types/platform.js';
|
|
4
|
-
import { IPlatformAPI } from './api.js';
|
|
5
|
-
|
|
6
|
-
export class CalendarService {
|
|
7
|
-
public api!: IPlatformAPI;
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Crea un nuevo evento y lo añade al estado.
|
|
11
|
-
*/
|
|
12
|
-
public createEvent(eventData: Omit<CalendarEvent, 'id'>): CalendarEvent {
|
|
13
|
-
const newEvent: CalendarEvent = {
|
|
14
|
-
...eventData,
|
|
15
|
-
id: Date.now(),
|
|
16
|
-
};
|
|
17
|
-
// const currentEvents = this.api.state.calendar();
|
|
18
|
-
// this.api.state.setCalendar([...currentEvents, newEvent]);
|
|
19
|
-
this.api.notifications.show('success', 'Evento Creado', `Se añadió "${newEvent.title}" a tu calendario.`);
|
|
20
|
-
return newEvent;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Obtiene todos los eventos para un día específico.
|
|
25
|
-
* @param date El día para el que se quieren obtener los eventos.
|
|
26
|
-
*/
|
|
27
|
-
public getEventsForDay(date: Date) {
|
|
28
|
-
// const allEvents = this.api.state.calendar();
|
|
29
|
-
// const dayStart = new Date(date);
|
|
30
|
-
// dayStart.setHours(0, 0, 0, 0);
|
|
31
|
-
|
|
32
|
-
// const dayEnd = new Date(date);
|
|
33
|
-
// dayEnd.setHours(23, 59, 59, 999);
|
|
34
|
-
|
|
35
|
-
// return allEvents.filter((event: any) => {
|
|
36
|
-
// const eventStart = new Date(event.start);
|
|
37
|
-
// return eventStart >= dayStart && eventStart <= dayEnd;
|
|
38
|
-
// });
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// En el futuro, podríamos añadir métodos como:
|
|
42
|
-
// public updateEvent(eventId: number, updates: Partial<CalendarEvent>) { ... }
|
|
43
|
-
// public deleteEvent(eventId: number) { ... }
|
|
44
|
-
}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
// src/platform/CommandService.ts
|
|
2
|
-
import { IPlatformAPI } from './api.js';
|
|
3
|
-
type SpyCommandHandler = (commandId: string, data?: any) => void;
|
|
4
|
-
|
|
5
|
-
export interface Command {
|
|
6
|
-
id: string;
|
|
7
|
-
title: string;
|
|
8
|
-
icon?: string;
|
|
9
|
-
category?: string;
|
|
10
|
-
execute: (api: IPlatformAPI, arg?: any) => void;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export class CommandService {
|
|
14
|
-
private commands: Map<string, Command> = new Map();
|
|
15
|
-
public api!: IPlatformAPI;
|
|
16
|
-
private spy: SpyCommandHandler | null = null;
|
|
17
|
-
|
|
18
|
-
constructor() {
|
|
19
|
-
// The API is injected after construction to break circular dependencies.
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
register(command: Command) {
|
|
23
|
-
if (this.commands.has(command.id)) {
|
|
24
|
-
console.warn(`[CommandService] El comando "${command.id}" ya está registrado. Se sobrescribirá.`);
|
|
25
|
-
}
|
|
26
|
-
this.commands.set(command.id, command);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
execute(commandId: string, arg?: any, callerId?: string) {
|
|
30
|
-
const command = this.commands.get(commandId);
|
|
31
|
-
if (command) {
|
|
32
|
-
try {
|
|
33
|
-
// Asumimos que un comando mapea a un servicio.
|
|
34
|
-
// TODO: Hay qye mejorar la implementación real, el comando podría declarar qué servicio utiliza.
|
|
35
|
-
// Por ahora, usamos una convención: 'kanban.moveTask' activa 'svc:KanbanService'.
|
|
36
|
-
const targetServiceId = `svc:${command.id.split('.')[0]}Service`;
|
|
37
|
-
|
|
38
|
-
const startTime = performance.now(); // <-- INICIA EL CRONÓMETRO
|
|
39
|
-
command.execute(this.api, arg);
|
|
40
|
-
const endTime = performance.now(); // <-- DETIENE EL CRONÓMETRO
|
|
41
|
-
const duration = (endTime - startTime).toFixed(2);
|
|
42
|
-
|
|
43
|
-
this.api.debug?.probe(targetServiceId, 'active', {
|
|
44
|
-
sourceNodeId: callerId,
|
|
45
|
-
command: commandId, // <-- PASAMOS LA FUENTE
|
|
46
|
-
duration: `${duration} ms` // <-- AÑADE LA MÉTRICA
|
|
47
|
-
});
|
|
48
|
-
this.api.events.emit(`command:${commandId}:executed`, { arg });
|
|
49
|
-
} catch (error) {
|
|
50
|
-
console.error(`Error ejecutando el comando "${commandId}":`, error);
|
|
51
|
-
this.api.notifications.show('error', 'Error de Comando', `No se pudo ejecutar "${command.title}".`);
|
|
52
|
-
}
|
|
53
|
-
} else {
|
|
54
|
-
console.error(`[CommandService] Intento de ejecutar un comando no registrado: "${commandId}"`);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
getAll(): Command[] {
|
|
59
|
-
return Array.from(this.commands.values());
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Registra una única función que recibirá TODOS los eventos emitidos.
|
|
64
|
-
* @param handler La función espía.
|
|
65
|
-
*/
|
|
66
|
-
spyOn(handler: SpyCommandHandler): void {
|
|
67
|
-
this.spy = handler;
|
|
68
|
-
}
|
|
69
|
-
}
|