@qwickapps/server 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/LICENSE +45 -0
  2. package/README.md +321 -0
  3. package/dist/core/control-panel.d.ts +21 -0
  4. package/dist/core/control-panel.d.ts.map +1 -0
  5. package/dist/core/control-panel.js +416 -0
  6. package/dist/core/control-panel.js.map +1 -0
  7. package/dist/core/gateway.d.ts +133 -0
  8. package/dist/core/gateway.d.ts.map +1 -0
  9. package/dist/core/gateway.js +270 -0
  10. package/dist/core/gateway.js.map +1 -0
  11. package/dist/core/health-manager.d.ts +52 -0
  12. package/dist/core/health-manager.d.ts.map +1 -0
  13. package/dist/core/health-manager.js +192 -0
  14. package/dist/core/health-manager.js.map +1 -0
  15. package/dist/core/index.d.ts +10 -0
  16. package/dist/core/index.d.ts.map +1 -0
  17. package/dist/core/index.js +8 -0
  18. package/dist/core/index.js.map +1 -0
  19. package/dist/core/logging.d.ts +83 -0
  20. package/dist/core/logging.d.ts.map +1 -0
  21. package/dist/core/logging.js +191 -0
  22. package/dist/core/logging.js.map +1 -0
  23. package/dist/core/types.d.ts +195 -0
  24. package/dist/core/types.d.ts.map +1 -0
  25. package/dist/core/types.js +7 -0
  26. package/dist/core/types.js.map +1 -0
  27. package/dist/index.d.ts +18 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +17 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/plugins/config-plugin.d.ts +15 -0
  32. package/dist/plugins/config-plugin.d.ts.map +1 -0
  33. package/dist/plugins/config-plugin.js +96 -0
  34. package/dist/plugins/config-plugin.js.map +1 -0
  35. package/dist/plugins/diagnostics-plugin.d.ts +29 -0
  36. package/dist/plugins/diagnostics-plugin.d.ts.map +1 -0
  37. package/dist/plugins/diagnostics-plugin.js +142 -0
  38. package/dist/plugins/diagnostics-plugin.js.map +1 -0
  39. package/dist/plugins/health-plugin.d.ts +17 -0
  40. package/dist/plugins/health-plugin.d.ts.map +1 -0
  41. package/dist/plugins/health-plugin.js +25 -0
  42. package/dist/plugins/health-plugin.js.map +1 -0
  43. package/dist/plugins/index.d.ts +14 -0
  44. package/dist/plugins/index.d.ts.map +1 -0
  45. package/dist/plugins/index.js +10 -0
  46. package/dist/plugins/index.js.map +1 -0
  47. package/dist/plugins/logs-plugin.d.ts +22 -0
  48. package/dist/plugins/logs-plugin.d.ts.map +1 -0
  49. package/dist/plugins/logs-plugin.js +242 -0
  50. package/dist/plugins/logs-plugin.js.map +1 -0
  51. package/dist-ui/assets/index-Bk7ypbI4.js +465 -0
  52. package/dist-ui/assets/index-Bk7ypbI4.js.map +1 -0
  53. package/dist-ui/assets/index-CiizQQnb.css +1 -0
  54. package/dist-ui/index.html +13 -0
  55. package/package.json +98 -0
  56. package/src/core/control-panel.ts +493 -0
  57. package/src/core/gateway.ts +421 -0
  58. package/src/core/health-manager.ts +227 -0
  59. package/src/core/index.ts +25 -0
  60. package/src/core/logging.ts +234 -0
  61. package/src/core/types.ts +218 -0
  62. package/src/index.ts +55 -0
  63. package/src/plugins/config-plugin.ts +117 -0
  64. package/src/plugins/diagnostics-plugin.ts +178 -0
  65. package/src/plugins/health-plugin.ts +35 -0
  66. package/src/plugins/index.ts +17 -0
  67. package/src/plugins/logs-plugin.ts +314 -0
  68. package/ui/index.html +12 -0
  69. package/ui/src/App.tsx +65 -0
  70. package/ui/src/api/controlPanelApi.ts +148 -0
  71. package/ui/src/config/AppConfig.ts +18 -0
  72. package/ui/src/index.css +29 -0
  73. package/ui/src/index.tsx +11 -0
  74. package/ui/src/pages/ConfigPage.tsx +199 -0
  75. package/ui/src/pages/DashboardPage.tsx +264 -0
  76. package/ui/src/pages/DiagnosticsPage.tsx +315 -0
  77. package/ui/src/pages/HealthPage.tsx +204 -0
  78. package/ui/src/pages/LogsPage.tsx +267 -0
  79. package/ui/src/pages/NotFoundPage.tsx +41 -0
  80. package/ui/tsconfig.json +19 -0
  81. package/ui/vite.config.ts +21 -0
@@ -0,0 +1,416 @@
1
+ /**
2
+ * Control Panel Core
3
+ *
4
+ * Creates and manages the control panel Express application
5
+ *
6
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
7
+ */
8
+ import express from 'express';
9
+ import helmet from 'helmet';
10
+ import cors from 'cors';
11
+ import compression from 'compression';
12
+ import { existsSync } from 'node:fs';
13
+ import { fileURLToPath } from 'node:url';
14
+ import { dirname, join } from 'node:path';
15
+ import { HealthManager } from './health-manager.js';
16
+ import { initializeLogging, getControlPanelLogger } from './logging.js';
17
+ // Get the package root directory for serving UI assets
18
+ const __filename = fileURLToPath(import.meta.url);
19
+ const __dirname = dirname(__filename);
20
+ // Handle both src/core and dist/core paths - go up to find package root
21
+ const packageRoot = __dirname.includes('/src/')
22
+ ? join(__dirname, '..', '..')
23
+ : join(__dirname, '..', '..');
24
+ const uiDistPath = join(packageRoot, 'dist-ui');
25
+ /**
26
+ * Create a control panel instance
27
+ */
28
+ export function createControlPanel(options) {
29
+ const { config, plugins = [], logging: loggingConfig } = options;
30
+ // Initialize logging subsystem
31
+ const loggingSubsystem = initializeLogging({
32
+ namespace: config.productName,
33
+ ...loggingConfig,
34
+ });
35
+ // Use provided logger or get one from the logging subsystem
36
+ const logger = options.logger || loggingSubsystem.getRootLogger();
37
+ const app = express();
38
+ const router = express.Router();
39
+ const healthManager = new HealthManager(logger);
40
+ const registeredPlugins = [];
41
+ let server = null;
42
+ const startTime = Date.now();
43
+ // Security middleware
44
+ app.use(helmet({
45
+ contentSecurityPolicy: false, // Allow inline scripts for simple UI
46
+ }));
47
+ // CORS
48
+ app.use(cors({
49
+ origin: config.cors?.origins || '*',
50
+ credentials: true,
51
+ }));
52
+ // Body parsing (skip for specified paths to allow proxy middleware to work)
53
+ const skipBodyParserPaths = config.skipBodyParserPaths || [];
54
+ if (skipBodyParserPaths.length > 0) {
55
+ app.use((req, res, next) => {
56
+ // Skip body parsing for specified paths (useful for proxy middleware)
57
+ if (skipBodyParserPaths.some(path => req.path.startsWith(path))) {
58
+ return next();
59
+ }
60
+ express.json()(req, res, next);
61
+ });
62
+ }
63
+ else {
64
+ app.use(express.json());
65
+ }
66
+ app.use(compression());
67
+ // Basic auth middleware if configured
68
+ if (config.auth?.enabled && config.auth.provider === 'basic' && config.auth.users) {
69
+ app.use((req, res, next) => {
70
+ const authHeader = req.headers.authorization;
71
+ if (!authHeader || !authHeader.startsWith('Basic ')) {
72
+ res.set('WWW-Authenticate', 'Basic realm="Control Panel"');
73
+ return res.status(401).json({ error: 'Authentication required' });
74
+ }
75
+ const base64Credentials = authHeader.substring(6);
76
+ const credentials = Buffer.from(base64Credentials, 'base64').toString('utf-8');
77
+ const [username, password] = credentials.split(':');
78
+ const validUser = config.auth.users.find((u) => u.username === username && u.password === password);
79
+ if (!validUser) {
80
+ return res.status(401).json({ error: 'Invalid credentials' });
81
+ }
82
+ next();
83
+ });
84
+ }
85
+ // Custom auth middleware
86
+ if (config.auth?.enabled && config.auth.provider === 'custom' && config.auth.customMiddleware) {
87
+ app.use(config.auth.customMiddleware);
88
+ }
89
+ // Request logging
90
+ app.use((req, _res, next) => {
91
+ logger.debug(`${req.method} ${req.path}`);
92
+ next();
93
+ });
94
+ // Mount router
95
+ app.use('/api', router);
96
+ // Built-in routes
97
+ /**
98
+ * GET /api/health - Aggregated health status
99
+ */
100
+ router.get('/health', (_req, res) => {
101
+ const results = healthManager.getResults();
102
+ const status = healthManager.getAggregatedStatus();
103
+ const uptime = Date.now() - startTime;
104
+ res.status(status === 'healthy' ? 200 : status === 'degraded' ? 200 : 503).json({
105
+ status,
106
+ timestamp: new Date().toISOString(),
107
+ uptime,
108
+ checks: results,
109
+ });
110
+ });
111
+ /**
112
+ * GET /api/info - Product information
113
+ */
114
+ router.get('/info', (_req, res) => {
115
+ res.json({
116
+ product: config.productName,
117
+ version: config.version || 'unknown',
118
+ uptime: Date.now() - startTime,
119
+ links: config.links || [],
120
+ branding: config.branding || {},
121
+ });
122
+ });
123
+ /**
124
+ * GET /api/diagnostics - Full diagnostics for AI agents
125
+ */
126
+ router.get('/diagnostics', (_req, res) => {
127
+ const report = getDiagnostics();
128
+ res.json(report);
129
+ });
130
+ /**
131
+ * Serve dashboard UI
132
+ *
133
+ * Priority:
134
+ * 1. If useRichUI is true and dist-ui exists, serve React SPA
135
+ * 2. Otherwise serve simple static HTML dashboard
136
+ */
137
+ if (!config.disableDashboard) {
138
+ // Use customUiPath if provided, otherwise fall back to package's dist-ui
139
+ const effectiveUiPath = config.customUiPath || uiDistPath;
140
+ const hasRichUI = existsSync(effectiveUiPath);
141
+ const useRichUI = config.useRichUI !== false && hasRichUI;
142
+ logger.debug(`Dashboard config: __dirname=${__dirname}, effectiveUiPath=${effectiveUiPath}, hasRichUI=${hasRichUI}, useRichUI=${useRichUI}`);
143
+ if (useRichUI) {
144
+ logger.info(`Serving rich React UI from ${effectiveUiPath}`);
145
+ // Serve static assets from dist-ui
146
+ app.use(express.static(effectiveUiPath));
147
+ // SPA fallback - serve index.html for all non-API routes
148
+ app.get('*', (req, res, next) => {
149
+ // Skip API routes (must check for /api/ with trailing slash to avoid matching /api-keys etc)
150
+ if (req.path.startsWith('/api/') || req.path === '/api') {
151
+ return next();
152
+ }
153
+ res.sendFile(join(effectiveUiPath, 'index.html'));
154
+ });
155
+ }
156
+ else {
157
+ logger.info('Serving basic HTML dashboard');
158
+ app.get('/', (_req, res) => {
159
+ const html = generateDashboardHtml(config, healthManager.getResults());
160
+ res.type('html').send(html);
161
+ });
162
+ }
163
+ }
164
+ // Plugin context factory - creates context with plugin-specific logger
165
+ const createPluginContext = (pluginName) => ({
166
+ config,
167
+ app,
168
+ router,
169
+ logger: getControlPanelLogger(pluginName),
170
+ registerHealthCheck: (check) => healthManager.register(check),
171
+ });
172
+ // Register plugin
173
+ const registerPlugin = async (plugin) => {
174
+ logger.info(`Registering plugin: ${plugin.name}`);
175
+ // Register routes
176
+ if (plugin.routes) {
177
+ for (const route of plugin.routes) {
178
+ switch (route.method) {
179
+ case 'get':
180
+ router.get(route.path, route.handler);
181
+ break;
182
+ case 'post':
183
+ router.post(route.path, route.handler);
184
+ break;
185
+ case 'put':
186
+ router.put(route.path, route.handler);
187
+ break;
188
+ case 'delete':
189
+ router.delete(route.path, route.handler);
190
+ break;
191
+ }
192
+ logger.debug(`Registered route: ${route.method.toUpperCase()} ${route.path}`);
193
+ }
194
+ }
195
+ // Initialize plugin with plugin-specific logger
196
+ if (plugin.onInit) {
197
+ await plugin.onInit(createPluginContext(plugin.name));
198
+ }
199
+ registeredPlugins.push(plugin);
200
+ logger.info(`Plugin registered: ${plugin.name}`);
201
+ };
202
+ // Get diagnostics report
203
+ const getDiagnostics = () => {
204
+ const memUsage = process.memoryUsage();
205
+ return {
206
+ timestamp: new Date().toISOString(),
207
+ product: config.productName,
208
+ version: config.version,
209
+ uptime: Date.now() - startTime,
210
+ health: healthManager.getResults(),
211
+ system: {
212
+ nodeVersion: process.version,
213
+ platform: process.platform,
214
+ arch: process.arch,
215
+ memory: {
216
+ total: memUsage.heapTotal,
217
+ used: memUsage.heapUsed,
218
+ free: memUsage.heapTotal - memUsage.heapUsed,
219
+ },
220
+ cpu: {
221
+ usage: 0, // Would need os.cpus() for real measurement
222
+ },
223
+ },
224
+ };
225
+ };
226
+ // Start server
227
+ const start = async () => {
228
+ // Register initial plugins
229
+ for (const plugin of plugins) {
230
+ await registerPlugin(plugin);
231
+ }
232
+ return new Promise((resolve) => {
233
+ server = app.listen(config.port, () => {
234
+ logger.info(`Control panel started on port ${config.port}`);
235
+ logger.info(`Dashboard: http://localhost:${config.port}`);
236
+ logger.info(`Health: http://localhost:${config.port}/api/health`);
237
+ logger.info(`Diagnostics: http://localhost:${config.port}/api/diagnostics`);
238
+ resolve();
239
+ });
240
+ });
241
+ };
242
+ // Stop server
243
+ const stop = async () => {
244
+ // Shutdown plugins
245
+ for (const plugin of registeredPlugins) {
246
+ if (plugin.onShutdown) {
247
+ await plugin.onShutdown();
248
+ }
249
+ }
250
+ // Shutdown health manager
251
+ healthManager.shutdown();
252
+ // Close server
253
+ if (server) {
254
+ return new Promise((resolve) => {
255
+ server.close(() => {
256
+ logger.info('Control panel stopped');
257
+ resolve();
258
+ });
259
+ });
260
+ }
261
+ };
262
+ return {
263
+ app,
264
+ start,
265
+ stop,
266
+ registerPlugin,
267
+ getHealthStatus: () => healthManager.getResults(),
268
+ getDiagnostics,
269
+ };
270
+ }
271
+ /**
272
+ * Generate simple dashboard HTML
273
+ */
274
+ function generateDashboardHtml(config, health) {
275
+ const healthEntries = Object.entries(health);
276
+ const overallStatus = healthEntries.every((e) => e[1].status === 'healthy')
277
+ ? 'healthy'
278
+ : healthEntries.some((e) => e[1].status === 'unhealthy')
279
+ ? 'unhealthy'
280
+ : 'degraded';
281
+ const statusColor = overallStatus === 'healthy' ? '#22c55e' : overallStatus === 'degraded' ? '#f59e0b' : '#ef4444';
282
+ const linksHtml = (config.links || [])
283
+ .map((link) => `<a href="${link.url}" ${link.external ? 'target="_blank"' : ''} class="link">${link.label}</a>`)
284
+ .join('');
285
+ const healthHtml = healthEntries
286
+ .map(([name, result]) => `
287
+ <div class="health-item">
288
+ <span class="status-dot" style="background-color: ${result.status === 'healthy' ? '#22c55e' : result.status === 'degraded' ? '#f59e0b' : '#ef4444'}"></span>
289
+ <span class="name">${name}</span>
290
+ <span class="latency">${result.latency ? `${result.latency}ms` : '-'}</span>
291
+ </div>
292
+ `)
293
+ .join('');
294
+ return `<!DOCTYPE html>
295
+ <html lang="en">
296
+ <head>
297
+ <meta charset="UTF-8">
298
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
299
+ <title>${config.productName} - Control Panel</title>
300
+ <style>
301
+ * { margin: 0; padding: 0; box-sizing: border-box; }
302
+ body {
303
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
304
+ background: #0f172a;
305
+ color: #e2e8f0;
306
+ min-height: 100vh;
307
+ padding: 2rem;
308
+ }
309
+ .container { max-width: 1200px; margin: 0 auto; }
310
+ header {
311
+ display: flex;
312
+ justify-content: space-between;
313
+ align-items: center;
314
+ margin-bottom: 2rem;
315
+ padding-bottom: 1rem;
316
+ border-bottom: 1px solid #334155;
317
+ }
318
+ h1 { font-size: 1.5rem; color: ${config.branding?.primaryColor || '#6366f1'}; }
319
+ .status-badge {
320
+ display: inline-flex;
321
+ align-items: center;
322
+ gap: 0.5rem;
323
+ padding: 0.5rem 1rem;
324
+ border-radius: 9999px;
325
+ background: ${statusColor}20;
326
+ color: ${statusColor};
327
+ font-weight: 600;
328
+ }
329
+ .status-dot {
330
+ width: 8px;
331
+ height: 8px;
332
+ border-radius: 50%;
333
+ background: currentColor;
334
+ }
335
+ .cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 1.5rem; }
336
+ .card {
337
+ background: #1e293b;
338
+ border-radius: 0.75rem;
339
+ padding: 1.5rem;
340
+ border: 1px solid #334155;
341
+ }
342
+ .card h2 {
343
+ font-size: 0.875rem;
344
+ text-transform: uppercase;
345
+ letter-spacing: 0.05em;
346
+ color: #94a3b8;
347
+ margin-bottom: 1rem;
348
+ }
349
+ .health-item {
350
+ display: flex;
351
+ align-items: center;
352
+ gap: 0.75rem;
353
+ padding: 0.75rem 0;
354
+ border-bottom: 1px solid #334155;
355
+ }
356
+ .health-item:last-child { border-bottom: none; }
357
+ .health-item .name { flex: 1; }
358
+ .health-item .latency { color: #64748b; font-size: 0.875rem; }
359
+ .links { display: flex; flex-wrap: wrap; gap: 0.75rem; }
360
+ .link {
361
+ display: inline-block;
362
+ padding: 0.75rem 1.5rem;
363
+ background: #334155;
364
+ color: #e2e8f0;
365
+ text-decoration: none;
366
+ border-radius: 0.5rem;
367
+ transition: background 0.2s;
368
+ }
369
+ .link:hover { background: #475569; }
370
+ .api-links { margin-top: 2rem; padding-top: 1rem; border-top: 1px solid #334155; }
371
+ .api-links a { color: #6366f1; margin-right: 1.5rem; text-decoration: none; }
372
+ .api-links a:hover { text-decoration: underline; }
373
+ </style>
374
+ </head>
375
+ <body>
376
+ <div class="container">
377
+ <header>
378
+ <h1>${config.productName} Control Panel</h1>
379
+ <div class="status-badge">
380
+ <span class="status-dot"></span>
381
+ ${overallStatus.charAt(0).toUpperCase() + overallStatus.slice(1)}
382
+ </div>
383
+ </header>
384
+
385
+ <div class="cards">
386
+ <div class="card">
387
+ <h2>Health Checks</h2>
388
+ ${healthHtml || '<p style="color: #64748b;">No health checks configured</p>'}
389
+ </div>
390
+
391
+ ${(config.links || []).length > 0
392
+ ? `
393
+ <div class="card">
394
+ <h2>Quick Links</h2>
395
+ <div class="links">${linksHtml}</div>
396
+ </div>
397
+ `
398
+ : ''}
399
+ </div>
400
+
401
+ <div class="api-links">
402
+ <strong>API:</strong>
403
+ <a href="/api/health">Health</a>
404
+ <a href="/api/info">Info</a>
405
+ <a href="/api/diagnostics">Diagnostics</a>
406
+ </div>
407
+ </div>
408
+
409
+ <script>
410
+ // Auto-refresh health status every 10 seconds
411
+ setTimeout(() => location.reload(), 10000);
412
+ </script>
413
+ </body>
414
+ </html>`;
415
+ }
416
+ //# sourceMappingURL=control-panel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"control-panel.js","sourceRoot":"","sources":["../../src/core/control-panel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Gateway Server for @qwickapps/server
3
+ *
4
+ * Provides a production-ready gateway pattern that:
5
+ * 1. Serves the control panel UI (always responsive)
6
+ * 2. Proxies API requests to an internal service
7
+ * 3. Provides health and diagnostics endpoints
8
+ *
9
+ * Architecture:
10
+ * Internet → Gateway (GATEWAY_PORT, public) → Service (SERVICE_PORT, internal)
11
+ *
12
+ * The gateway is always responsive even if the internal service is down,
13
+ * allowing diagnostics and error visibility.
14
+ *
15
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
16
+ */
17
+ import type { Application } from 'express';
18
+ import type { Server } from 'http';
19
+ import type { ControlPanelConfig, ControlPanelPlugin, Logger } from './types.js';
20
+ import { createControlPanel } from './control-panel.js';
21
+ import { type LoggingConfig } from './logging.js';
22
+ /**
23
+ * Gateway configuration
24
+ */
25
+ export interface GatewayConfig {
26
+ /** Port for the gateway (public-facing). Defaults to GATEWAY_PORT env or 3101 */
27
+ gatewayPort?: number;
28
+ /** Port for the internal service. Defaults to SERVICE_PORT env or 3100 */
29
+ servicePort?: number;
30
+ /** Product name for the control panel */
31
+ productName: string;
32
+ /** Product version */
33
+ version?: string;
34
+ /** Branding configuration */
35
+ branding?: ControlPanelConfig['branding'];
36
+ /** CORS origins */
37
+ corsOrigins?: string[];
38
+ /** Control panel plugins */
39
+ plugins?: ControlPanelPlugin[];
40
+ /** Quick links for the control panel */
41
+ links?: ControlPanelConfig['links'];
42
+ /** Path to custom React UI dist folder */
43
+ customUiPath?: string;
44
+ /**
45
+ * API paths to proxy to the internal service.
46
+ * Defaults to ['/api/v1'] if not specified.
47
+ * The gateway always proxies /health to the internal service.
48
+ */
49
+ proxyPaths?: string[];
50
+ /**
51
+ * Authentication mode for the control panel (not the API).
52
+ * - 'none': No authentication (not recommended for production)
53
+ * - 'basic': HTTP Basic Auth with username/password
54
+ * - 'auto': Auto-generate password on startup (default)
55
+ */
56
+ authMode?: 'none' | 'basic' | 'auto';
57
+ /** Basic auth username (defaults to 'admin') */
58
+ basicAuthUser?: string;
59
+ /** Basic auth password (required if authMode is 'basic') */
60
+ basicAuthPassword?: string;
61
+ /** Logger instance (deprecated: use logging config instead) */
62
+ logger?: Logger;
63
+ /** Logging configuration */
64
+ logging?: LoggingConfig;
65
+ }
66
+ /**
67
+ * Service factory function type
68
+ * Called with the service port, should return an object with:
69
+ * - app: Express application (or compatible)
70
+ * - server: HTTP server (created by calling listen)
71
+ * - shutdown: Async function to gracefully shut down the service
72
+ */
73
+ export interface ServiceFactory {
74
+ (port: number): Promise<{
75
+ app: Application;
76
+ server: Server;
77
+ shutdown: () => Promise<void>;
78
+ }>;
79
+ }
80
+ /**
81
+ * Gateway instance returned by createGateway
82
+ */
83
+ export interface GatewayInstance {
84
+ /** The control panel instance */
85
+ controlPanel: ReturnType<typeof createControlPanel>;
86
+ /** The internal service (if started) */
87
+ service: {
88
+ app: Application;
89
+ server: Server;
90
+ shutdown: () => Promise<void>;
91
+ } | null;
92
+ /** Start the gateway and internal service */
93
+ start: () => Promise<void>;
94
+ /** Stop everything gracefully */
95
+ stop: () => Promise<void>;
96
+ /** Gateway port */
97
+ gatewayPort: number;
98
+ /** Service port */
99
+ servicePort: number;
100
+ }
101
+ /**
102
+ * Create a gateway that proxies to an internal service
103
+ *
104
+ * @param config - Gateway configuration
105
+ * @param serviceFactory - Factory function to create the internal service
106
+ * @returns Gateway instance
107
+ *
108
+ * @example
109
+ * ```typescript
110
+ * import { createGateway } from '@qwickapps/server';
111
+ *
112
+ * const gateway = createGateway(
113
+ * {
114
+ * productName: 'My Service',
115
+ * gatewayPort: 3101,
116
+ * servicePort: 3100,
117
+ * },
118
+ * async (port) => {
119
+ * const app = createMyApp();
120
+ * const server = app.listen(port);
121
+ * return {
122
+ * app,
123
+ * server,
124
+ * shutdown: async () => { server.close(); },
125
+ * };
126
+ * }
127
+ * );
128
+ *
129
+ * await gateway.start();
130
+ * ```
131
+ */
132
+ export declare function createGateway(config: GatewayConfig, serviceFactory: ServiceFactory): GatewayInstance;
133
+ //# sourceMappingURL=gateway.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../../src/core/gateway.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAmC,MAAM,SAAS,CAAC;AAG5E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AACnC,OAAO,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACjF,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAA4C,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AAO5F;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,iFAAiF;IACjF,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,0EAA0E;IAC1E,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,yCAAyC;IACzC,WAAW,EAAE,MAAM,CAAC;IAEpB,sBAAsB;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,6BAA6B;IAC7B,QAAQ,CAAC,EAAE,kBAAkB,CAAC,UAAU,CAAC,CAAC;IAE1C,mBAAmB;IACnB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IAEvB,4BAA4B;IAC5B,OAAO,CAAC,EAAE,kBAAkB,EAAE,CAAC;IAE/B,wCAAwC;IACxC,KAAK,CAAC,EAAE,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAEpC,0CAA0C;IAC1C,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IAEtB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;IAErC,gDAAgD;IAChD,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,4DAA4D;IAC5D,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,4BAA4B;IAC5B,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QACtB,GAAG,EAAE,WAAW,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;KAC/B,CAAC,CAAC;CACJ;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,iCAAiC;IACjC,YAAY,EAAE,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;IAEpD,wCAAwC;IACxC,OAAO,EAAE;QACP,GAAG,EAAE,WAAW,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;KAC/B,GAAG,IAAI,CAAC;IAET,6CAA6C;IAC7C,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAE3B,iCAAiC;IACjC,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1B,mBAAmB;IACnB,WAAW,EAAE,MAAM,CAAC;IAEpB,mBAAmB;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AA+DD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,aAAa,EACrB,cAAc,EAAE,cAAc,GAC7B,eAAe,CAkMjB"}