@deployforme/core 1.0.2 → 1.0.3

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.d.ts CHANGED
@@ -3,3 +3,4 @@ export { ModuleRegistry } from './module-registry';
3
3
  export { ModuleLoader } from './loader';
4
4
  export { createRuntimeContext, DefaultLogger } from './context';
5
5
  export * from './types';
6
+ export * from './monitoring';
package/dist/index.js CHANGED
@@ -25,3 +25,4 @@ var context_1 = require("./context");
25
25
  Object.defineProperty(exports, "createRuntimeContext", { enumerable: true, get: function () { return context_1.createRuntimeContext; } });
26
26
  Object.defineProperty(exports, "DefaultLogger", { enumerable: true, get: function () { return context_1.DefaultLogger; } });
27
27
  __exportStar(require("./types"), exports);
28
+ __exportStar(require("./monitoring"), exports);
package/dist/kernel.d.ts CHANGED
@@ -1,10 +1,18 @@
1
1
  import { RuntimeContext } from './types';
2
+ import { Monitor } from './monitoring/monitor';
3
+ import { MonitoringConfig } from './monitoring/types';
2
4
  export declare class Kernel {
3
5
  private registry;
4
6
  private loader;
5
7
  private context;
6
8
  private routeTracker;
7
- constructor(context: RuntimeContext);
9
+ private monitor;
10
+ private dashboard?;
11
+ private config;
12
+ constructor(context: RuntimeContext, config?: MonitoringConfig);
13
+ private startDashboard;
14
+ stopDashboard(): void;
15
+ getMonitor(): Monitor;
8
16
  load(modulePath: string): Promise<void>;
9
17
  unload(moduleName: string): Promise<void>;
10
18
  reload(modulePath: string): Promise<void>;
package/dist/kernel.js CHANGED
@@ -3,43 +3,80 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Kernel = void 0;
4
4
  const module_registry_1 = require("./module-registry");
5
5
  const loader_1 = require("./loader");
6
+ const monitor_1 = require("./monitoring/monitor");
7
+ const dashboard_1 = require("./monitoring/dashboard");
6
8
  class Kernel {
7
- constructor(context) {
9
+ constructor(context, config = { liveRunnerActions: false }) {
8
10
  this.routeTracker = new Map();
9
11
  this.context = context;
10
12
  this.registry = new module_registry_1.ModuleRegistry();
11
13
  this.loader = new loader_1.ModuleLoader();
14
+ this.monitor = new monitor_1.Monitor();
15
+ this.config = config;
16
+ if (config.liveRunnerActions) {
17
+ this.startDashboard(config.port, config.host);
18
+ }
19
+ }
20
+ async startDashboard(port, host) {
21
+ try {
22
+ this.dashboard = new dashboard_1.Dashboard(this.monitor, port || 0, host || 'localhost');
23
+ await this.dashboard.start();
24
+ }
25
+ catch (error) {
26
+ this.context.logger?.error(`[Deploy4Me] Failed to start dashboard: ${error}`);
27
+ }
28
+ }
29
+ stopDashboard() {
30
+ if (this.dashboard) {
31
+ this.dashboard.stop();
32
+ this.dashboard = undefined;
33
+ }
34
+ }
35
+ getMonitor() {
36
+ return this.monitor;
12
37
  }
13
38
  async load(modulePath) {
14
- const module = await this.loader.load(modulePath);
15
- // Unload existing module if present
16
- if (this.registry.has(module.name)) {
17
- await this.unload(module.name);
39
+ const buildId = this.monitor.startBuild('unknown', modulePath);
40
+ try {
41
+ const module = await this.loader.load(modulePath);
42
+ this.monitor.completeBuild(buildId, 'success');
43
+ this.monitor.startBuild(module.name, modulePath);
44
+ // Unload existing module if present
45
+ if (this.registry.has(module.name)) {
46
+ await this.unload(module.name);
47
+ }
48
+ this.context.logger?.log(`[Deploy4Me] Loading module: ${module.name}@${module.version}`);
49
+ // Track routes registered during module.register()
50
+ const routeIds = [];
51
+ const originalRegister = this.context.http.registerRoute.bind(this.context.http);
52
+ this.context.http.registerRoute = (definition) => {
53
+ routeIds.push(definition.id);
54
+ originalRegister(definition);
55
+ };
56
+ // Register module
57
+ module.register(this.context);
58
+ // Restore original registerRoute
59
+ this.context.http.registerRoute = originalRegister;
60
+ // Store in registry
61
+ this.registry.register(module, routeIds);
62
+ this.routeTracker.set(module.name, routeIds);
63
+ // Register in monitor
64
+ this.monitor.registerModule(module.name, module.version, routeIds.length);
65
+ this.context.logger?.log(`[Deploy4Me] Module registered: ${module.name} (${routeIds.length} routes)`);
66
+ }
67
+ catch (error) {
68
+ const errorMessage = error instanceof Error ? error.message : String(error);
69
+ this.monitor.completeBuild(buildId, 'error', errorMessage);
70
+ throw error;
18
71
  }
19
- this.context.logger?.log(`Loading module: ${module.name}@${module.version}`);
20
- // Track routes registered during module.register()
21
- const routeIds = [];
22
- const originalRegister = this.context.http.registerRoute.bind(this.context.http);
23
- this.context.http.registerRoute = (definition) => {
24
- routeIds.push(definition.id);
25
- originalRegister(definition);
26
- };
27
- // Register module
28
- module.register(this.context);
29
- // Restore original registerRoute
30
- this.context.http.registerRoute = originalRegister;
31
- // Store in registry
32
- this.registry.register(module, routeIds);
33
- this.routeTracker.set(module.name, routeIds);
34
- this.context.logger?.log(`Module loaded: ${module.name} (${routeIds.length} routes)`);
35
72
  }
36
73
  async unload(moduleName) {
37
74
  const metadata = this.registry.get(moduleName);
38
75
  if (!metadata) {
39
- this.context.logger?.warn(`Module not found: ${moduleName}`);
76
+ this.context.logger?.warn(`[Deploy4Me] Module not found: ${moduleName}`);
40
77
  return;
41
78
  }
42
- this.context.logger?.log(`Unloading module: ${moduleName}`);
79
+ this.context.logger?.log(`[Deploy4Me] Unloading module: ${moduleName}`);
43
80
  // Call dispose if exists
44
81
  if (metadata.module.dispose) {
45
82
  metadata.module.dispose();
@@ -52,7 +89,9 @@ class Kernel {
52
89
  // Remove from registry
53
90
  this.registry.unregister(moduleName);
54
91
  this.routeTracker.delete(moduleName);
55
- this.context.logger?.log(`Module unloaded: ${moduleName}`);
92
+ // Unregister from monitor
93
+ this.monitor.unregisterModule(moduleName);
94
+ this.context.logger?.log(`[Deploy4Me] Module unloaded: ${moduleName}`);
56
95
  }
57
96
  async reload(modulePath) {
58
97
  await this.load(modulePath);
@@ -0,0 +1,14 @@
1
+ import { Monitor } from './monitor';
2
+ export declare class Dashboard {
3
+ private server?;
4
+ private monitor;
5
+ private port;
6
+ private host;
7
+ constructor(monitor: Monitor, port?: number, host?: string);
8
+ start(): Promise<number>;
9
+ stop(): void;
10
+ private handleRequest;
11
+ private sendJSON;
12
+ private sendHTML;
13
+ private getHTML;
14
+ }
@@ -0,0 +1,386 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.Dashboard = void 0;
37
+ const http = __importStar(require("http"));
38
+ class Dashboard {
39
+ constructor(monitor, port = 0, host = 'localhost') {
40
+ this.monitor = monitor;
41
+ this.port = port;
42
+ this.host = host;
43
+ }
44
+ async start() {
45
+ return new Promise((resolve, reject) => {
46
+ this.server = http.createServer((req, res) => {
47
+ this.handleRequest(req, res);
48
+ });
49
+ this.server.on('error', reject);
50
+ this.server.listen(this.port, this.host, () => {
51
+ const addr = this.server.address();
52
+ const actualPort = typeof addr === 'object' ? addr.port : this.port;
53
+ const timestamp = new Date().toISOString();
54
+ console.log(`[${timestamp}] [SUCCESS] Dashboard started at http://${this.host}:${actualPort}`);
55
+ resolve(actualPort);
56
+ });
57
+ });
58
+ }
59
+ stop() {
60
+ if (this.server) {
61
+ this.server.close();
62
+ this.server = undefined;
63
+ }
64
+ }
65
+ handleRequest(req, res) {
66
+ const url = req.url || '/';
67
+ if (url === '/api/state') {
68
+ this.sendJSON(res, {
69
+ builds: this.monitor.getBuilds(),
70
+ modules: this.monitor.getActiveModules(),
71
+ stats: this.monitor.getStats()
72
+ });
73
+ }
74
+ else {
75
+ this.sendHTML(res);
76
+ }
77
+ }
78
+ sendJSON(res, data) {
79
+ res.writeHead(200, { 'Content-Type': 'application/json' });
80
+ res.end(JSON.stringify(data));
81
+ }
82
+ sendHTML(res) {
83
+ res.writeHead(200, { 'Content-Type': 'text/html' });
84
+ res.end(this.getHTML());
85
+ }
86
+ getHTML() {
87
+ return `<!DOCTYPE html>
88
+ <html lang="tr">
89
+ <head>
90
+ <meta charset="UTF-8">
91
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
92
+ <title>Deploy4Me Dashboard</title>
93
+ <style>
94
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&display=swap');
95
+
96
+ :root {
97
+ --bg: #0a0a0a;
98
+ --text: #f2f2f2;
99
+ --text-dim: #666666;
100
+ --border: #1a1a1a;
101
+ --success: #4ade80;
102
+ --error: #f87171;
103
+ --process: #60a5fa;
104
+ --accent: #ffffff;
105
+ }
106
+
107
+ * { margin: 0; padding: 0; box-sizing: border-box; }
108
+
109
+ body {
110
+ font-family: 'Inter', sans-serif;
111
+ background: var(--bg);
112
+ color: var(--text);
113
+ line-height: 1.6;
114
+ padding: 4rem 2rem;
115
+ display: flex;
116
+ justify-content: center;
117
+ -webkit-font-smoothing: antialiased;
118
+ }
119
+
120
+ .container { width: 100%; max-width: 900px; }
121
+
122
+ header {
123
+ margin-bottom: 4rem;
124
+ border-bottom: 1px solid var(--text);
125
+ padding-bottom: 1.5rem;
126
+ display: flex;
127
+ justify-content: space-between;
128
+ align-items: flex-end;
129
+ }
130
+
131
+ h1 { font-size: 1.4rem; font-weight: 500; letter-spacing: -0.03em; text-transform: lowercase; }
132
+ .subtitle { color: var(--text-dim); font-size: 0.8rem; }
133
+
134
+ .stats {
135
+ display: grid;
136
+ grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
137
+ gap: 2rem;
138
+ margin-bottom: 5rem;
139
+ }
140
+
141
+ .stat-label { font-size: 0.65rem; text-transform: uppercase; letter-spacing: 0.1em; color: var(--text-dim); margin-bottom: 0.5rem; }
142
+ .stat-value { font-size: 1.4rem; font-variant-numeric: tabular-nums; }
143
+
144
+ .section { margin-bottom: 4rem; }
145
+
146
+ .section-header {
147
+ display: flex;
148
+ justify-content: space-between;
149
+ align-items: center;
150
+ border-bottom: 1px solid var(--border);
151
+ margin-bottom: 1rem;
152
+ padding-bottom: 0.5rem;
153
+ }
154
+
155
+ .section-title {
156
+ font-size: 0.75rem;
157
+ font-weight: 600;
158
+ text-transform: uppercase;
159
+ letter-spacing: 0.15em;
160
+ color: var(--text-dim);
161
+ }
162
+
163
+ /* Tabs Styling */
164
+ .tabs { display: flex; gap: 1.5rem; }
165
+ .tab {
166
+ background: none;
167
+ border: none;
168
+ color: var(--text-dim);
169
+ font-family: inherit;
170
+ font-size: 0.75rem;
171
+ font-weight: 600;
172
+ text-transform: uppercase;
173
+ cursor: pointer;
174
+ padding: 0.5rem 0;
175
+ transition: color 0.2s;
176
+ position: relative;
177
+ }
178
+ .tab:hover { color: var(--text); }
179
+ .tab.active { color: var(--accent); }
180
+ .tab.active::after {
181
+ content: '';
182
+ position: absolute;
183
+ bottom: -0.6rem;
184
+ left: 0;
185
+ width: 100%;
186
+ height: 1px;
187
+ background: var(--accent);
188
+ }
189
+
190
+ .list-item {
191
+ display: grid;
192
+ grid-template-columns: 1fr auto;
193
+ padding: 1rem 0;
194
+ border-bottom: 1px solid var(--border);
195
+ align-items: center;
196
+ }
197
+
198
+ .item-name { font-weight: 500; font-size: 1rem; }
199
+ .item-details {
200
+ font-size: 0.75rem;
201
+ color: var(--text-dim);
202
+ display: flex;
203
+ gap: 1rem;
204
+ font-family: 'ui-monospace', monospace;
205
+ }
206
+
207
+ .status-text { font-size: 0.65rem; font-weight: 600; text-transform: uppercase; }
208
+ .status-building { color: var(--process); }
209
+ .status-success { color: var(--success); }
210
+ .status-error { color: var(--error); }
211
+
212
+ .error-log {
213
+ grid-column: 1 / -1;
214
+ font-family: 'ui-monospace', monospace;
215
+ font-size: 0.7rem;
216
+ color: var(--error);
217
+ padding: 0.5rem 0;
218
+ opacity: 0.8;
219
+ }
220
+
221
+ /* Pagination Styling */
222
+ .pagination {
223
+ display: flex;
224
+ justify-content: center;
225
+ align-items: center;
226
+ gap: 2rem;
227
+ margin-top: 2rem;
228
+ font-size: 0.75rem;
229
+ color: var(--text-dim);
230
+ text-transform: uppercase;
231
+ letter-spacing: 0.1em;
232
+ }
233
+ .page-btn {
234
+ background: none;
235
+ border: 1px solid var(--border);
236
+ color: var(--text);
237
+ padding: 0.4rem 1rem;
238
+ cursor: pointer;
239
+ transition: all 0.2s;
240
+ }
241
+ .page-btn:disabled { color: var(--text-dim); cursor: not-allowed; border-color: transparent; }
242
+ .page-btn:not(:disabled):hover { border-color: var(--text-dim); }
243
+
244
+ .empty { color: var(--text-dim); padding: 2rem 0; font-style: italic; font-size: 0.8rem; }
245
+ </style>
246
+ </head>
247
+ <body>
248
+ <div class="container">
249
+ <header>
250
+ <h1>deploy4me.dashboard</h1>
251
+ <div id="stat-uptime" class="subtitle">0s</div>
252
+ </header>
253
+
254
+ <div class="stats">
255
+ <div class="stat-item"><div class="stat-label">builds</div><div class="stat-value" id="stat-total">0</div></div>
256
+ <div class="stat-item"><div class="stat-label">success</div><div class="stat-value" id="stat-success">0</div></div>
257
+ <div class="stat-item"><div class="stat-label">failed</div><div class="stat-value" id="stat-failed">0</div></div>
258
+ <div class="stat-item"><div class="stat-label">active</div><div class="stat-value" id="stat-modules">0</div></div>
259
+ </div>
260
+
261
+ <div class="section">
262
+ <div class="section-header"><div class="section-title">Active Modules</div></div>
263
+ <div id="modules"><div class="empty">Inquiring...</div></div>
264
+ </div>
265
+
266
+ <div class="section">
267
+ <div class="section-header">
268
+ <div class="section-title">Build History</div>
269
+ <div class="tabs">
270
+ <button class="tab active" onclick="setFilter('all')">All</button>
271
+ <button class="tab" onclick="setFilter('building')">Building</button>
272
+ <button class="tab" onclick="setFilter('success')">Success</button>
273
+ <button class="tab" onclick="setFilter('error')">Failed</button>
274
+ </div>
275
+ </div>
276
+ <div id="builds"></div>
277
+ <div class="pagination">
278
+ <button id="prev-btn" class="page-btn" onclick="changePage(-1)">Previous</button>
279
+ <span id="page-info">Page 1</span>
280
+ <button id="next-btn" class="page-btn" onclick="changePage(1)">Next</button>
281
+ </div>
282
+ </div>
283
+ </div>
284
+
285
+ <script>
286
+ let allBuilds = [];
287
+ let currentFilter = 'all';
288
+ let currentPage = 1;
289
+ const itemsPerPage = 8;
290
+
291
+ function formatUptime(ms) {
292
+ const s = Math.floor(ms / 1000);
293
+ const m = Math.floor(s / 60);
294
+ return m > 0 ? \`up \${m}m \${s%60}s\` : \`up \${s}s\`;
295
+ }
296
+
297
+ function setFilter(filter) {
298
+ currentFilter = filter;
299
+ currentPage = 1;
300
+ document.querySelectorAll('.tab').forEach(t => {
301
+ t.classList.toggle('active', t.textContent.toLowerCase() === filter || (filter === 'error' && t.textContent === 'Failed'));
302
+ });
303
+ render();
304
+ }
305
+
306
+ function changePage(step) {
307
+ currentPage += step;
308
+ render();
309
+ }
310
+
311
+ function render() {
312
+ // Stats & Modules rendering
313
+ // ... (handled in fetchData)
314
+ }
315
+
316
+ async function fetchData() {
317
+ try {
318
+ const res = await fetch('/api/state');
319
+ const data = await res.json();
320
+
321
+ // Update Stats
322
+ document.getElementById('stat-total').textContent = data.stats.totalBuilds;
323
+ document.getElementById('stat-success').textContent = data.stats.successfulBuilds;
324
+ document.getElementById('stat-failed').textContent = data.stats.failedBuilds;
325
+ document.getElementById('stat-modules').textContent = data.stats.activeModules;
326
+ document.getElementById('stat-uptime').textContent = formatUptime(data.stats.uptime);
327
+
328
+ // Update Modules
329
+ const modContainer = document.getElementById('modules');
330
+ modContainer.innerHTML = data.modules.map(mod => \`
331
+ <div class="list-item">
332
+ <div class="item-name">\${mod.name} <span style="color:var(--text-dim); font-size:0.7rem">v\${mod.version}</span></div>
333
+ <div class="status-text status-active">active</div>
334
+ </div>
335
+ \`).join('') || '<div class="empty">No active modules.</div>';
336
+
337
+ allBuilds = data.builds;
338
+ renderBuilds();
339
+ } catch (e) { console.error('Sync error'); }
340
+ }
341
+
342
+ function renderBuilds() {
343
+ const container = document.getElementById('builds');
344
+
345
+ // Filter
346
+ const filtered = allBuilds.filter(b => currentFilter === 'all' || b.status === currentFilter);
347
+
348
+ // Pagination
349
+ const totalPages = Math.ceil(filtered.length / itemsPerPage) || 1;
350
+ if (currentPage > totalPages) currentPage = totalPages;
351
+
352
+ const start = (currentPage - 1) * itemsPerPage;
353
+ const paginated = filtered.slice(start, start + itemsPerPage);
354
+
355
+ document.getElementById('page-info').textContent = \`Page \${currentPage} of \${totalPages}\`;
356
+ document.getElementById('prev-btn').disabled = currentPage === 1;
357
+ document.getElementById('next-btn').disabled = currentPage === totalPages;
358
+
359
+ if (!paginated.length) {
360
+ container.innerHTML = '<div class="empty">No records found for this filter.</div>';
361
+ return;
362
+ }
363
+
364
+ container.innerHTML = paginated.map(build => \`
365
+ <div class="list-item">
366
+ <div>
367
+ <div class="item-name">\${build.moduleName}</div>
368
+ <div class="item-details">
369
+ <span>\${new Date(build.startTime).toLocaleTimeString('tr-TR')}</span>
370
+ <span>\${build.duration ? (build.duration/1000).toFixed(2)+'s' : '--'}</span>
371
+ </div>
372
+ </div>
373
+ <div class="status-text status-\${build.status}">\${build.status}</div>
374
+ \${build.error ? \`<div class="error-log">\${build.error}</div>\` : ''}
375
+ </div>
376
+ \`).join('');
377
+ }
378
+
379
+ fetchData();
380
+ setInterval(fetchData, 3000);
381
+ </script>
382
+ </body>
383
+ </html>`;
384
+ }
385
+ }
386
+ exports.Dashboard = Dashboard;
@@ -0,0 +1,3 @@
1
+ export { Monitor } from './monitor';
2
+ export { Dashboard } from './dashboard';
3
+ export * from './types';
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.Dashboard = exports.Monitor = void 0;
18
+ var monitor_1 = require("./monitor");
19
+ Object.defineProperty(exports, "Monitor", { enumerable: true, get: function () { return monitor_1.Monitor; } });
20
+ var dashboard_1 = require("./dashboard");
21
+ Object.defineProperty(exports, "Dashboard", { enumerable: true, get: function () { return dashboard_1.Dashboard; } });
22
+ __exportStar(require("./types"), exports);
@@ -0,0 +1,21 @@
1
+ import { BuildRecord, ActiveModule, MonitoringState } from './types';
2
+ export declare class Monitor {
3
+ private state;
4
+ private maxBuilds;
5
+ constructor();
6
+ startBuild(moduleName: string, modulePath: string): string;
7
+ completeBuild(id: string, status: 'success' | 'error', error?: string): void;
8
+ registerModule(name: string, version: string, routeCount: number): void;
9
+ unregisterModule(name: string): void;
10
+ getState(): MonitoringState;
11
+ getBuilds(): BuildRecord[];
12
+ getActiveModules(): ActiveModule[];
13
+ getStats(): {
14
+ totalBuilds: number;
15
+ successfulBuilds: number;
16
+ failedBuilds: number;
17
+ buildingNow: number;
18
+ activeModules: number;
19
+ uptime: number;
20
+ };
21
+ }
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Monitor = void 0;
4
+ class Monitor {
5
+ constructor() {
6
+ this.maxBuilds = 100;
7
+ this.state = {
8
+ builds: [],
9
+ activeModules: new Map(),
10
+ startTime: new Date()
11
+ };
12
+ }
13
+ startBuild(moduleName, modulePath) {
14
+ const id = `${moduleName}-${Date.now()}`;
15
+ const record = {
16
+ id,
17
+ moduleName,
18
+ modulePath,
19
+ status: 'building',
20
+ startTime: new Date()
21
+ };
22
+ this.state.builds.unshift(record);
23
+ if (this.state.builds.length > this.maxBuilds) {
24
+ this.state.builds = this.state.builds.slice(0, this.maxBuilds);
25
+ }
26
+ return id;
27
+ }
28
+ completeBuild(id, status, error) {
29
+ const build = this.state.builds.find(b => b.id === id);
30
+ if (build) {
31
+ build.status = status;
32
+ build.endTime = new Date();
33
+ build.duration = build.endTime.getTime() - build.startTime.getTime();
34
+ if (error) {
35
+ build.error = error;
36
+ }
37
+ }
38
+ }
39
+ registerModule(name, version, routeCount) {
40
+ this.state.activeModules.set(name, {
41
+ name,
42
+ version,
43
+ loadedAt: new Date(),
44
+ routeCount,
45
+ status: 'active'
46
+ });
47
+ }
48
+ unregisterModule(name) {
49
+ this.state.activeModules.delete(name);
50
+ }
51
+ getState() {
52
+ return {
53
+ ...this.state,
54
+ activeModules: new Map(this.state.activeModules)
55
+ };
56
+ }
57
+ getBuilds() {
58
+ return [...this.state.builds];
59
+ }
60
+ getActiveModules() {
61
+ return Array.from(this.state.activeModules.values());
62
+ }
63
+ getStats() {
64
+ const builds = this.state.builds;
65
+ return {
66
+ totalBuilds: builds.length,
67
+ successfulBuilds: builds.filter(b => b.status === 'success').length,
68
+ failedBuilds: builds.filter(b => b.status === 'error').length,
69
+ buildingNow: builds.filter(b => b.status === 'building').length,
70
+ activeModules: this.state.activeModules.size,
71
+ uptime: Date.now() - this.state.startTime.getTime()
72
+ };
73
+ }
74
+ }
75
+ exports.Monitor = Monitor;
@@ -0,0 +1,28 @@
1
+ export interface MonitoringConfig {
2
+ liveRunnerActions: boolean;
3
+ port?: number;
4
+ host?: string;
5
+ }
6
+ export type BuildStatus = 'building' | 'success' | 'error';
7
+ export interface BuildRecord {
8
+ id: string;
9
+ moduleName: string;
10
+ modulePath: string;
11
+ status: BuildStatus;
12
+ startTime: Date;
13
+ endTime?: Date;
14
+ duration?: number;
15
+ error?: string;
16
+ }
17
+ export interface ActiveModule {
18
+ name: string;
19
+ version: string;
20
+ loadedAt: Date;
21
+ routeCount: number;
22
+ status: 'active' | 'error';
23
+ }
24
+ export interface MonitoringState {
25
+ builds: BuildRecord[];
26
+ activeModules: Map<string, ActiveModule>;
27
+ startTime: Date;
28
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deployforme/core",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Framework-agnostic runtime module management kernel",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",