@qwickapps/server 1.5.0 → 1.5.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.
Files changed (78) hide show
  1. package/CHANGELOG.md +528 -0
  2. package/README.md +9 -0
  3. package/dist/core/control-panel.d.ts.map +1 -1
  4. package/dist/core/control-panel.js +41 -0
  5. package/dist/core/control-panel.js.map +1 -1
  6. package/dist/core/guards.d.ts.map +1 -1
  7. package/dist/core/guards.js +77 -0
  8. package/dist/core/guards.js.map +1 -1
  9. package/dist/core/health-manager.d.ts +4 -0
  10. package/dist/core/health-manager.d.ts.map +1 -1
  11. package/dist/core/health-manager.js +6 -1
  12. package/dist/core/health-manager.js.map +1 -1
  13. package/dist/core/plugin-registry.d.ts +55 -5
  14. package/dist/core/plugin-registry.d.ts.map +1 -1
  15. package/dist/core/plugin-registry.js +57 -19
  16. package/dist/core/plugin-registry.js.map +1 -1
  17. package/dist/core/types.d.ts +2 -0
  18. package/dist/core/types.d.ts.map +1 -1
  19. package/dist/index.d.ts +2 -2
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +3 -1
  22. package/dist/index.js.map +1 -1
  23. package/dist/plugins/auth/auth-plugin.d.ts.map +1 -1
  24. package/dist/plugins/auth/auth-plugin.js +16 -0
  25. package/dist/plugins/auth/auth-plugin.js.map +1 -1
  26. package/dist/plugins/auth/auth-plugin.test.js +133 -0
  27. package/dist/plugins/auth/auth-plugin.test.js.map +1 -1
  28. package/dist/plugins/auth/env-config.d.ts.map +1 -1
  29. package/dist/plugins/auth/env-config.js +4 -0
  30. package/dist/plugins/auth/env-config.js.map +1 -1
  31. package/dist/plugins/auth/types.d.ts +10 -0
  32. package/dist/plugins/auth/types.d.ts.map +1 -1
  33. package/dist/plugins/auth/types.js.map +1 -1
  34. package/dist/plugins/devices/__tests__/token-utils.test.js +4 -2
  35. package/dist/plugins/devices/__tests__/token-utils.test.js.map +1 -1
  36. package/dist/plugins/frontend-app-plugin.d.ts.map +1 -1
  37. package/dist/plugins/frontend-app-plugin.js +18 -4
  38. package/dist/plugins/frontend-app-plugin.js.map +1 -1
  39. package/dist/plugins/index.d.ts +2 -0
  40. package/dist/plugins/index.d.ts.map +1 -1
  41. package/dist/plugins/index.js +2 -0
  42. package/dist/plugins/index.js.map +1 -1
  43. package/dist/plugins/qwickbrain/index.d.ts +25 -0
  44. package/dist/plugins/qwickbrain/index.d.ts.map +1 -0
  45. package/dist/plugins/qwickbrain/index.js +24 -0
  46. package/dist/plugins/qwickbrain/index.js.map +1 -0
  47. package/dist/plugins/qwickbrain/qwickbrain-plugin.d.ts +23 -0
  48. package/dist/plugins/qwickbrain/qwickbrain-plugin.d.ts.map +1 -0
  49. package/dist/plugins/qwickbrain/qwickbrain-plugin.js +528 -0
  50. package/dist/plugins/qwickbrain/qwickbrain-plugin.js.map +1 -0
  51. package/dist/plugins/qwickbrain/types.d.ts +131 -0
  52. package/dist/plugins/qwickbrain/types.d.ts.map +1 -0
  53. package/dist/plugins/qwickbrain/types.js +9 -0
  54. package/dist/plugins/qwickbrain/types.js.map +1 -0
  55. package/dist-ui/assets/{index-CynOqPkb.js → index-BfC7mG5L.js} +2 -2
  56. package/dist-ui/assets/{index-CynOqPkb.js.map → index-BfC7mG5L.js.map} +1 -1
  57. package/dist-ui/index.html +1 -1
  58. package/dist-ui-lib/api/controlPanelApi.d.ts +6 -0
  59. package/dist-ui-lib/index.js +277 -266
  60. package/dist-ui-lib/index.js.map +1 -1
  61. package/package.json +3 -2
  62. package/src/core/control-panel.ts +47 -0
  63. package/src/core/guards.ts +89 -0
  64. package/src/core/health-manager.ts +6 -1
  65. package/src/core/plugin-registry.ts +123 -25
  66. package/src/core/types.ts +2 -0
  67. package/src/index.ts +11 -0
  68. package/src/plugins/auth/auth-plugin.test.ts +167 -0
  69. package/src/plugins/auth/auth-plugin.ts +16 -0
  70. package/src/plugins/auth/env-config.ts +4 -0
  71. package/src/plugins/auth/types.ts +10 -0
  72. package/src/plugins/devices/__tests__/token-utils.test.ts +4 -2
  73. package/src/plugins/frontend-app-plugin.ts +19 -4
  74. package/src/plugins/index.ts +15 -0
  75. package/src/plugins/qwickbrain/index.ts +33 -0
  76. package/src/plugins/qwickbrain/qwickbrain-plugin.ts +642 -0
  77. package/src/plugins/qwickbrain/types.ts +146 -0
  78. package/ui/src/api/controlPanelApi.ts +49 -37
@@ -403,6 +403,7 @@ export function createAuthPluginFromEnv(options?: AuthEnvPluginOptions): Plugin
403
403
  authRequired,
404
404
  debug,
405
405
  onUnauthorized: options?.onUnauthorized,
406
+ onAuthenticated: options?.onAuthenticated,
406
407
  };
407
408
 
408
409
  // Update status
@@ -418,6 +419,7 @@ export function createAuthPluginFromEnv(options?: AuthEnvPluginOptions): Plugin
418
419
  // Wrap to add config status routes
419
420
  return {
420
421
  ...basePlugin,
422
+ type: 'system' as const, // Explicit system type (auth can handle any path)
421
423
  async onStart(pluginConfig: PluginConfig, registry: PluginRegistry): Promise<void> {
422
424
  // Call base plugin onStart
423
425
  await basePlugin.onStart?.(pluginConfig, registry);
@@ -825,6 +827,7 @@ function createDisabledPlugin(): Plugin {
825
827
  id: 'auth',
826
828
  name: 'Auth Plugin (Disabled)',
827
829
  version: '1.0.0',
830
+ type: 'system' as const,
828
831
 
829
832
  async onStart(_pluginConfig: PluginConfig, registry: PluginRegistry): Promise<void> {
830
833
  const logger = registry.getLogger('auth');
@@ -848,6 +851,7 @@ function createErrorPlugin(error: string): Plugin {
848
851
  id: 'auth',
849
852
  name: 'Auth Plugin (Error)',
850
853
  version: '1.0.0',
854
+ type: 'system' as const,
851
855
 
852
856
  async onStart(_pluginConfig: PluginConfig, registry: PluginRegistry): Promise<void> {
853
857
  const logger = registry.getLogger('auth');
@@ -182,6 +182,11 @@ export interface AuthPluginConfig {
182
182
  authRequired?: boolean;
183
183
  /** Custom unauthorized handler */
184
184
  onUnauthorized?: (req: Request, res: Response) => void;
185
+ /**
186
+ * Callback invoked after successful authentication.
187
+ * Use this to sync users to a local database on first login.
188
+ */
189
+ onAuthenticated?: (user: AuthenticatedUser) => Promise<void>;
185
190
  /** Enable debug logging */
186
191
  debug?: boolean;
187
192
  }
@@ -226,6 +231,11 @@ export interface AuthEnvPluginOptions {
226
231
  debug?: boolean;
227
232
  /** Custom unauthorized handler */
228
233
  onUnauthorized?: (req: Request, res: Response) => void;
234
+ /**
235
+ * Callback invoked after successful authentication.
236
+ * Use this to sync users to a local database on first login.
237
+ */
238
+ onAuthenticated?: (user: AuthenticatedUser) => Promise<void>;
229
239
  }
230
240
 
231
241
  /**
@@ -24,13 +24,15 @@ describe('Token Utilities', () => {
24
24
 
25
25
  it('should generate a 43-character secret after prefix', async () => {
26
26
  const result = await generateDeviceToken('mob');
27
- const secret = result.token.split('_')[1];
27
+ // Use slice to get everything after 'mob_' since base64url can contain '_'
28
+ const secret = result.token.slice(4); // 'mob_'.length = 4
28
29
  expect(secret.length).toBe(43);
29
30
  });
30
31
 
31
32
  it('should generate base64url-safe characters', async () => {
32
33
  const result = await generateDeviceToken('test');
33
- const secret = result.token.split('_')[1];
34
+ // Use slice to get everything after 'test_' since base64url can contain '_'
35
+ const secret = result.token.slice(5); // 'test_'.length = 5
34
36
  expect(secret).toMatch(/^[A-Za-z0-9_-]+$/);
35
37
  });
36
38
 
@@ -50,6 +50,7 @@ export function createFrontendAppPlugin(config: FrontendAppPluginConfig): Plugin
50
50
  id: 'frontend-app',
51
51
  name: 'Frontend App Plugin',
52
52
  version: '1.0.0',
53
+ type: 'system' as const,
53
54
 
54
55
  async onStart(_pluginConfig: PluginConfig, registry: PluginRegistry): Promise<void> {
55
56
  const logger = registry.getLogger('frontend-app');
@@ -80,11 +81,25 @@ export function createFrontendAppPlugin(config: FrontendAppPluginConfig): Plugin
80
81
  // Priority 2: Serve static files
81
82
  if (config.staticPath && existsSync(config.staticPath)) {
82
83
  logger.info(`Frontend app: Serving static files from ${config.staticPath}`);
83
- app.use('/', express.static(config.staticPath));
84
84
 
85
- // SPA fallback
86
- app.get('/', (_req, res) => {
87
- res.sendFile(resolve(config.staticPath!, 'index.html'));
85
+ // Serve static assets first
86
+ app.use(express.static(config.staticPath, { index: false }));
87
+
88
+ // SPA fallback for all non-API routes
89
+ // This must be registered after static files but handles routes that don't match files
90
+ app.get('*', (req, res, next) => {
91
+ // Skip API routes and control panel
92
+ if (req.path.startsWith('/api') || req.path.startsWith(config.mountPath || '/cpanel')) {
93
+ return next();
94
+ }
95
+
96
+ // Serve index.html for all other routes (SPA routing)
97
+ const indexPath = resolve(config.staticPath!, 'index.html');
98
+ if (existsSync(indexPath)) {
99
+ res.sendFile(indexPath);
100
+ } else {
101
+ next();
102
+ }
88
103
  });
89
104
  return;
90
105
  }
@@ -423,3 +423,18 @@ export type {
423
423
  ConnectionHealth,
424
424
  NotificationsManagerInterface,
425
425
  } from './notifications/index.js';
426
+
427
+ // QwickBrain MCP plugin
428
+ export {
429
+ createQwickBrainPlugin,
430
+ getConnectionStatus,
431
+ isConnected,
432
+ } from './qwickbrain/index.js';
433
+ export type {
434
+ QwickBrainPluginConfig,
435
+ MCPToolDefinition,
436
+ MCPToolCallRequest,
437
+ MCPToolCallResponse,
438
+ QwickBrainConnectionStatus,
439
+ MCPRateLimitConfig,
440
+ } from './qwickbrain/index.js';
@@ -0,0 +1,33 @@
1
+ /**
2
+ * QwickBrain Plugin
3
+ *
4
+ * MCP proxy plugin for exposing QwickBrain tools to external AI clients.
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * import { createControlPanel } from '@qwickapps/server';
9
+ * import { createQwickBrainPlugin } from '@qwickapps/server/plugins';
10
+ *
11
+ * const panel = await createControlPanel({
12
+ * plugins: [
13
+ * createQwickBrainPlugin({
14
+ * qwickbrainUrl: 'http://macmini.tailnet-xxx.ts.net:8080',
15
+ * exposedTools: '*', // or ['search_codebase', 'get_document', ...]
16
+ * }),
17
+ * ],
18
+ * });
19
+ * ```
20
+ *
21
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
22
+ */
23
+
24
+ export { createQwickBrainPlugin, getConnectionStatus, isConnected } from './qwickbrain-plugin.js';
25
+
26
+ export type {
27
+ QwickBrainPluginConfig,
28
+ MCPToolDefinition,
29
+ MCPToolCallRequest,
30
+ MCPToolCallResponse,
31
+ QwickBrainConnectionStatus,
32
+ MCPRateLimitConfig,
33
+ } from './types.js';