@qwickapps/server 1.5.1 → 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.
- package/CHANGELOG.md +21 -0
- package/dist/core/control-panel.d.ts.map +1 -1
- package/dist/core/control-panel.js +41 -0
- package/dist/core/control-panel.js.map +1 -1
- package/dist/core/guards.d.ts.map +1 -1
- package/dist/core/guards.js +77 -0
- package/dist/core/guards.js.map +1 -1
- package/dist/core/health-manager.d.ts +4 -0
- package/dist/core/health-manager.d.ts.map +1 -1
- package/dist/core/health-manager.js +6 -1
- package/dist/core/health-manager.js.map +1 -1
- package/dist/core/plugin-registry.d.ts +55 -5
- package/dist/core/plugin-registry.d.ts.map +1 -1
- package/dist/core/plugin-registry.js +57 -19
- package/dist/core/plugin-registry.js.map +1 -1
- package/dist/core/types.d.ts +2 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/plugins/auth/auth-plugin.d.ts.map +1 -1
- package/dist/plugins/auth/auth-plugin.js +16 -0
- package/dist/plugins/auth/auth-plugin.js.map +1 -1
- package/dist/plugins/auth/auth-plugin.test.js +133 -0
- package/dist/plugins/auth/auth-plugin.test.js.map +1 -1
- package/dist/plugins/auth/env-config.d.ts.map +1 -1
- package/dist/plugins/auth/env-config.js +4 -0
- package/dist/plugins/auth/env-config.js.map +1 -1
- package/dist/plugins/auth/types.d.ts +10 -0
- package/dist/plugins/auth/types.d.ts.map +1 -1
- package/dist/plugins/auth/types.js.map +1 -1
- package/dist/plugins/devices/__tests__/token-utils.test.js +4 -2
- package/dist/plugins/devices/__tests__/token-utils.test.js.map +1 -1
- package/dist/plugins/frontend-app-plugin.d.ts.map +1 -1
- package/dist/plugins/frontend-app-plugin.js +18 -4
- package/dist/plugins/frontend-app-plugin.js.map +1 -1
- package/dist/plugins/index.d.ts +2 -0
- package/dist/plugins/index.d.ts.map +1 -1
- package/dist/plugins/index.js +2 -0
- package/dist/plugins/index.js.map +1 -1
- package/dist/plugins/qwickbrain/index.d.ts +25 -0
- package/dist/plugins/qwickbrain/index.d.ts.map +1 -0
- package/dist/plugins/qwickbrain/index.js +24 -0
- package/dist/plugins/qwickbrain/index.js.map +1 -0
- package/dist/plugins/qwickbrain/qwickbrain-plugin.d.ts +23 -0
- package/dist/plugins/qwickbrain/qwickbrain-plugin.d.ts.map +1 -0
- package/dist/plugins/qwickbrain/qwickbrain-plugin.js +528 -0
- package/dist/plugins/qwickbrain/qwickbrain-plugin.js.map +1 -0
- package/dist/plugins/qwickbrain/types.d.ts +131 -0
- package/dist/plugins/qwickbrain/types.d.ts.map +1 -0
- package/dist/plugins/qwickbrain/types.js +9 -0
- package/dist/plugins/qwickbrain/types.js.map +1 -0
- package/dist-ui/assets/{index-CynOqPkb.js → index-BfC7mG5L.js} +2 -2
- package/dist-ui/assets/{index-CynOqPkb.js.map → index-BfC7mG5L.js.map} +1 -1
- package/dist-ui/index.html +1 -1
- package/dist-ui-lib/api/controlPanelApi.d.ts +6 -0
- package/dist-ui-lib/index.js +277 -266
- package/dist-ui-lib/index.js.map +1 -1
- package/package.json +1 -1
- package/src/core/control-panel.ts +47 -0
- package/src/core/guards.ts +89 -0
- package/src/core/health-manager.ts +6 -1
- package/src/core/plugin-registry.ts +123 -25
- package/src/core/types.ts +2 -0
- package/src/index.ts +11 -0
- package/src/plugins/auth/auth-plugin.test.ts +167 -0
- package/src/plugins/auth/auth-plugin.ts +16 -0
- package/src/plugins/auth/env-config.ts +4 -0
- package/src/plugins/auth/types.ts +10 -0
- package/src/plugins/devices/__tests__/token-utils.test.ts +4 -2
- package/src/plugins/frontend-app-plugin.ts +19 -4
- package/src/plugins/index.ts +15 -0
- package/src/plugins/qwickbrain/index.ts +33 -0
- package/src/plugins/qwickbrain/qwickbrain-plugin.ts +642 -0
- package/src/plugins/qwickbrain/types.ts +146 -0
- package/ui/src/api/controlPanelApi.ts +49 -37
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QwickBrain Plugin Types
|
|
3
|
+
*
|
|
4
|
+
* Type definitions for the QwickBrain MCP proxy plugin.
|
|
5
|
+
*
|
|
6
|
+
* Copyright (c) 2025 QwickApps.com. All rights reserved.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Configuration for the QwickBrain plugin
|
|
11
|
+
*/
|
|
12
|
+
export interface QwickBrainPluginConfig {
|
|
13
|
+
/**
|
|
14
|
+
* Base URL of the QwickBrain instance (via Tailscale)
|
|
15
|
+
* Example: "http://macmini.tailnet-xxx.ts.net:8080"
|
|
16
|
+
*/
|
|
17
|
+
qwickbrainUrl: string;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Request timeout in milliseconds
|
|
21
|
+
* @default 30000
|
|
22
|
+
*/
|
|
23
|
+
timeout?: number;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Which MCP tools to expose publicly
|
|
27
|
+
* Use '*' to expose all tools, or provide a list of tool names
|
|
28
|
+
* @default '*'
|
|
29
|
+
*/
|
|
30
|
+
exposedTools?: string[] | '*';
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* API configuration
|
|
34
|
+
*/
|
|
35
|
+
api?: {
|
|
36
|
+
/**
|
|
37
|
+
* Enable API routes
|
|
38
|
+
* @default true
|
|
39
|
+
*/
|
|
40
|
+
enabled?: boolean;
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* API route prefix (mounted under /api)
|
|
44
|
+
* @default '/mcp'
|
|
45
|
+
*/
|
|
46
|
+
prefix?: string;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Authentication configuration
|
|
51
|
+
*/
|
|
52
|
+
auth?: {
|
|
53
|
+
/**
|
|
54
|
+
* Require authentication for MCP tool endpoints
|
|
55
|
+
* When true, /mcp/tools and /mcp/tools/:name require valid auth
|
|
56
|
+
* Status endpoint (/mcp/status) is always public
|
|
57
|
+
* @default true
|
|
58
|
+
*/
|
|
59
|
+
required?: boolean;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Roles required to access MCP tools (optional)
|
|
63
|
+
* If set, user must have at least one of these roles
|
|
64
|
+
*/
|
|
65
|
+
allowedRoles?: string[];
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Rate limiting configuration
|
|
70
|
+
*/
|
|
71
|
+
rateLimit?: MCPRateLimitConfig;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Enable debug logging
|
|
75
|
+
* @default false
|
|
76
|
+
*/
|
|
77
|
+
debug?: boolean;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* MCP Tool definition from QwickBrain
|
|
82
|
+
*/
|
|
83
|
+
export interface MCPToolDefinition {
|
|
84
|
+
name: string;
|
|
85
|
+
description: string;
|
|
86
|
+
inputSchema: {
|
|
87
|
+
type: 'object';
|
|
88
|
+
properties: Record<string, unknown>;
|
|
89
|
+
required?: string[];
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* MCP Tool call request
|
|
95
|
+
*/
|
|
96
|
+
export interface MCPToolCallRequest {
|
|
97
|
+
name: string;
|
|
98
|
+
arguments: Record<string, unknown>;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* MCP Tool call response
|
|
103
|
+
*/
|
|
104
|
+
export interface MCPToolCallResponse {
|
|
105
|
+
content: Array<{
|
|
106
|
+
type: 'text' | 'image' | 'resource';
|
|
107
|
+
text?: string;
|
|
108
|
+
data?: string;
|
|
109
|
+
mimeType?: string;
|
|
110
|
+
}>;
|
|
111
|
+
isError?: boolean;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* QwickBrain connection status
|
|
116
|
+
*/
|
|
117
|
+
export interface QwickBrainConnectionStatus {
|
|
118
|
+
connected: boolean;
|
|
119
|
+
lastCheck: Date;
|
|
120
|
+
latencyMs?: number;
|
|
121
|
+
error?: string;
|
|
122
|
+
tailscaleStatus?: 'connected' | 'disconnected' | 'unknown';
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Rate limit configuration for MCP requests
|
|
127
|
+
*/
|
|
128
|
+
export interface MCPRateLimitConfig {
|
|
129
|
+
/**
|
|
130
|
+
* Enable rate limiting
|
|
131
|
+
* @default true
|
|
132
|
+
*/
|
|
133
|
+
enabled?: boolean;
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Requests per minute per client
|
|
137
|
+
* @default 60
|
|
138
|
+
*/
|
|
139
|
+
perClientPerMinute?: number;
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Total requests per minute (global)
|
|
143
|
+
* @default 1000
|
|
144
|
+
*/
|
|
145
|
+
globalPerMinute?: number;
|
|
146
|
+
}
|
|
@@ -444,13 +444,25 @@ class ControlPanelApi {
|
|
|
444
444
|
return this.baseUrl;
|
|
445
445
|
}
|
|
446
446
|
|
|
447
|
+
/**
|
|
448
|
+
* Internal fetch wrapper that includes credentials for Basic Auth support.
|
|
449
|
+
* Using 'same-origin' ensures the browser sends stored Basic Auth credentials
|
|
450
|
+
* without embedding them in the URL (which would cause fetch to fail).
|
|
451
|
+
*/
|
|
452
|
+
private async _fetch(url: string, options?: RequestInit): Promise<Response> {
|
|
453
|
+
return fetch(url, {
|
|
454
|
+
...options,
|
|
455
|
+
credentials: 'same-origin',
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
|
|
447
459
|
/**
|
|
448
460
|
* Generic fetch method for API requests.
|
|
449
461
|
* Automatically prepends the base URL and /api prefix.
|
|
450
462
|
*/
|
|
451
463
|
async fetch<T = unknown>(path: string, options?: RequestInit): Promise<T> {
|
|
452
464
|
const url = `${this.baseUrl}/api${path.startsWith('/') ? path : `/${path}`}`;
|
|
453
|
-
const response = await
|
|
465
|
+
const response = await this._fetch(url, {
|
|
454
466
|
...options,
|
|
455
467
|
headers: {
|
|
456
468
|
'Content-Type': 'application/json',
|
|
@@ -494,7 +506,7 @@ class ControlPanelApi {
|
|
|
494
506
|
|
|
495
507
|
private async checkEndpoint(path: string): Promise<boolean> {
|
|
496
508
|
try {
|
|
497
|
-
const response = await
|
|
509
|
+
const response = await this._fetch(`${this.baseUrl}${path}`, { method: 'HEAD' });
|
|
498
510
|
// 200, 401, 403 mean the endpoint exists (might need auth)
|
|
499
511
|
// 404 means it doesn't exist
|
|
500
512
|
return response.status !== 404;
|
|
@@ -517,7 +529,7 @@ class ControlPanelApi {
|
|
|
517
529
|
if (options.page) params.set('page', options.page.toString());
|
|
518
530
|
if (options.search) params.set('q', options.search);
|
|
519
531
|
|
|
520
|
-
const response = await
|
|
532
|
+
const response = await this._fetch(`${this.baseUrl}/api/users?${params}`);
|
|
521
533
|
if (!response.ok) {
|
|
522
534
|
throw new Error(`Users request failed: ${response.statusText}`);
|
|
523
535
|
}
|
|
@@ -525,7 +537,7 @@ class ControlPanelApi {
|
|
|
525
537
|
}
|
|
526
538
|
|
|
527
539
|
async getUserById(id: string): Promise<User> {
|
|
528
|
-
const response = await
|
|
540
|
+
const response = await this._fetch(`${this.baseUrl}/api/users/${id}`);
|
|
529
541
|
if (!response.ok) {
|
|
530
542
|
throw new Error(`User request failed: ${response.statusText}`);
|
|
531
543
|
}
|
|
@@ -537,7 +549,7 @@ class ControlPanelApi {
|
|
|
537
549
|
// ==================
|
|
538
550
|
|
|
539
551
|
async getBans(): Promise<BansResponse> {
|
|
540
|
-
const response = await
|
|
552
|
+
const response = await this._fetch(`${this.baseUrl}/api/bans`);
|
|
541
553
|
if (!response.ok) {
|
|
542
554
|
throw new Error(`Bans request failed: ${response.statusText}`);
|
|
543
555
|
}
|
|
@@ -553,7 +565,7 @@ class ControlPanelApi {
|
|
|
553
565
|
duration = Math.max(0, Math.floor((expiresDate.getTime() - now.getTime()) / 1000));
|
|
554
566
|
}
|
|
555
567
|
|
|
556
|
-
const response = await
|
|
568
|
+
const response = await this._fetch(`${this.baseUrl}/api/bans/email/${encodeURIComponent(email)}`, {
|
|
557
569
|
method: 'POST',
|
|
558
570
|
headers: { 'Content-Type': 'application/json' },
|
|
559
571
|
body: JSON.stringify({ reason, duration }),
|
|
@@ -565,7 +577,7 @@ class ControlPanelApi {
|
|
|
565
577
|
}
|
|
566
578
|
|
|
567
579
|
async unbanUser(email: string): Promise<void> {
|
|
568
|
-
const response = await
|
|
580
|
+
const response = await this._fetch(`${this.baseUrl}/api/bans/email/${encodeURIComponent(email)}`, {
|
|
569
581
|
method: 'DELETE',
|
|
570
582
|
});
|
|
571
583
|
if (!response.ok) {
|
|
@@ -574,7 +586,7 @@ class ControlPanelApi {
|
|
|
574
586
|
}
|
|
575
587
|
|
|
576
588
|
async checkBan(email: string): Promise<{ banned: boolean; ban?: Ban }> {
|
|
577
|
-
const response = await
|
|
589
|
+
const response = await this._fetch(`${this.baseUrl}/api/bans/email/${encodeURIComponent(email)}`);
|
|
578
590
|
if (!response.ok) {
|
|
579
591
|
throw new Error(`Ban check failed: ${response.statusText}`);
|
|
580
592
|
}
|
|
@@ -588,7 +600,7 @@ class ControlPanelApi {
|
|
|
588
600
|
// ==================
|
|
589
601
|
|
|
590
602
|
async getEntitlements(email: string): Promise<EntitlementResult> {
|
|
591
|
-
const response = await
|
|
603
|
+
const response = await this._fetch(`${this.baseUrl}/api/entitlements/${encodeURIComponent(email)}`);
|
|
592
604
|
if (!response.ok) {
|
|
593
605
|
throw new Error(`Entitlements request failed: ${response.statusText}`);
|
|
594
606
|
}
|
|
@@ -596,7 +608,7 @@ class ControlPanelApi {
|
|
|
596
608
|
}
|
|
597
609
|
|
|
598
610
|
async refreshEntitlements(email: string): Promise<EntitlementResult> {
|
|
599
|
-
const response = await
|
|
611
|
+
const response = await this._fetch(`${this.baseUrl}/api/entitlements/${encodeURIComponent(email)}/refresh`, {
|
|
600
612
|
method: 'POST',
|
|
601
613
|
});
|
|
602
614
|
if (!response.ok) {
|
|
@@ -606,7 +618,7 @@ class ControlPanelApi {
|
|
|
606
618
|
}
|
|
607
619
|
|
|
608
620
|
async checkEntitlement(email: string, entitlement: string): Promise<{ has: boolean }> {
|
|
609
|
-
const response = await
|
|
621
|
+
const response = await this._fetch(
|
|
610
622
|
`${this.baseUrl}/api/entitlements/${encodeURIComponent(email)}/check/${encodeURIComponent(entitlement)}`
|
|
611
623
|
);
|
|
612
624
|
if (!response.ok) {
|
|
@@ -616,7 +628,7 @@ class ControlPanelApi {
|
|
|
616
628
|
}
|
|
617
629
|
|
|
618
630
|
async getAvailableEntitlements(): Promise<EntitlementDefinition[]> {
|
|
619
|
-
const response = await
|
|
631
|
+
const response = await this._fetch(`${this.baseUrl}/api/entitlements/available`);
|
|
620
632
|
if (!response.ok) {
|
|
621
633
|
throw new Error(`Available entitlements request failed: ${response.statusText}`);
|
|
622
634
|
}
|
|
@@ -625,7 +637,7 @@ class ControlPanelApi {
|
|
|
625
637
|
}
|
|
626
638
|
|
|
627
639
|
async grantEntitlement(email: string, entitlement: string): Promise<void> {
|
|
628
|
-
const response = await
|
|
640
|
+
const response = await this._fetch(`${this.baseUrl}/api/entitlements/${encodeURIComponent(email)}`, {
|
|
629
641
|
method: 'POST',
|
|
630
642
|
headers: { 'Content-Type': 'application/json' },
|
|
631
643
|
body: JSON.stringify({ entitlement }),
|
|
@@ -637,7 +649,7 @@ class ControlPanelApi {
|
|
|
637
649
|
}
|
|
638
650
|
|
|
639
651
|
async revokeEntitlement(email: string, entitlement: string): Promise<void> {
|
|
640
|
-
const response = await
|
|
652
|
+
const response = await this._fetch(
|
|
641
653
|
`${this.baseUrl}/api/entitlements/${encodeURIComponent(email)}/${encodeURIComponent(entitlement)}`,
|
|
642
654
|
{ method: 'DELETE' }
|
|
643
655
|
);
|
|
@@ -647,7 +659,7 @@ class ControlPanelApi {
|
|
|
647
659
|
}
|
|
648
660
|
|
|
649
661
|
async invalidateEntitlementCache(email: string): Promise<void> {
|
|
650
|
-
const response = await
|
|
662
|
+
const response = await this._fetch(`${this.baseUrl}/api/entitlements/cache/${encodeURIComponent(email)}`, {
|
|
651
663
|
method: 'DELETE',
|
|
652
664
|
});
|
|
653
665
|
if (!response.ok) {
|
|
@@ -656,7 +668,7 @@ class ControlPanelApi {
|
|
|
656
668
|
}
|
|
657
669
|
|
|
658
670
|
async getEntitlementsStatus(): Promise<EntitlementsStatus> {
|
|
659
|
-
const response = await
|
|
671
|
+
const response = await this._fetch(`${this.baseUrl}/api/entitlements/status`);
|
|
660
672
|
if (!response.ok) {
|
|
661
673
|
throw new Error(`Entitlements status request failed: ${response.statusText}`);
|
|
662
674
|
}
|
|
@@ -668,7 +680,7 @@ class ControlPanelApi {
|
|
|
668
680
|
// ==================
|
|
669
681
|
|
|
670
682
|
async getHealth(): Promise<HealthResponse> {
|
|
671
|
-
const response = await
|
|
683
|
+
const response = await this._fetch(`${this.baseUrl}/api/health`);
|
|
672
684
|
if (!response.ok) {
|
|
673
685
|
throw new Error(`Health check failed: ${response.statusText}`);
|
|
674
686
|
}
|
|
@@ -676,7 +688,7 @@ class ControlPanelApi {
|
|
|
676
688
|
}
|
|
677
689
|
|
|
678
690
|
async getInfo(): Promise<InfoResponse> {
|
|
679
|
-
const response = await
|
|
691
|
+
const response = await this._fetch(`${this.baseUrl}/api/info`);
|
|
680
692
|
if (!response.ok) {
|
|
681
693
|
throw new Error(`Info request failed: ${response.statusText}`);
|
|
682
694
|
}
|
|
@@ -684,7 +696,7 @@ class ControlPanelApi {
|
|
|
684
696
|
}
|
|
685
697
|
|
|
686
698
|
async getDiagnostics(): Promise<DiagnosticsResponse> {
|
|
687
|
-
const response = await
|
|
699
|
+
const response = await this._fetch(`${this.baseUrl}/api/diagnostics`);
|
|
688
700
|
if (!response.ok) {
|
|
689
701
|
throw new Error(`Diagnostics request failed: ${response.statusText}`);
|
|
690
702
|
}
|
|
@@ -692,7 +704,7 @@ class ControlPanelApi {
|
|
|
692
704
|
}
|
|
693
705
|
|
|
694
706
|
async getConfig(): Promise<ConfigResponse> {
|
|
695
|
-
const response = await
|
|
707
|
+
const response = await this._fetch(`${this.baseUrl}/api/config`);
|
|
696
708
|
if (!response.ok) {
|
|
697
709
|
throw new Error(`Config request failed: ${response.statusText}`);
|
|
698
710
|
}
|
|
@@ -713,7 +725,7 @@ class ControlPanelApi {
|
|
|
713
725
|
if (options.limit) params.set('limit', options.limit.toString());
|
|
714
726
|
if (options.page) params.set('page', options.page.toString());
|
|
715
727
|
|
|
716
|
-
const response = await
|
|
728
|
+
const response = await this._fetch(`${this.baseUrl}/api/logs?${params}`);
|
|
717
729
|
if (!response.ok) {
|
|
718
730
|
throw new Error(`Logs request failed: ${response.statusText}`);
|
|
719
731
|
}
|
|
@@ -721,7 +733,7 @@ class ControlPanelApi {
|
|
|
721
733
|
}
|
|
722
734
|
|
|
723
735
|
async getLogSources(): Promise<LogSource[]> {
|
|
724
|
-
const response = await
|
|
736
|
+
const response = await this._fetch(`${this.baseUrl}/api/logs/sources`);
|
|
725
737
|
if (!response.ok) {
|
|
726
738
|
throw new Error(`Log sources request failed: ${response.statusText}`);
|
|
727
739
|
}
|
|
@@ -734,7 +746,7 @@ class ControlPanelApi {
|
|
|
734
746
|
// ==================
|
|
735
747
|
|
|
736
748
|
async getPlugins(): Promise<PluginsResponse> {
|
|
737
|
-
const response = await
|
|
749
|
+
const response = await this._fetch(`${this.baseUrl}/api/plugins`);
|
|
738
750
|
if (!response.ok) {
|
|
739
751
|
throw new Error(`Plugins request failed: ${response.statusText}`);
|
|
740
752
|
}
|
|
@@ -742,7 +754,7 @@ class ControlPanelApi {
|
|
|
742
754
|
}
|
|
743
755
|
|
|
744
756
|
async getPluginDetail(id: string): Promise<PluginDetailResponse> {
|
|
745
|
-
const response = await
|
|
757
|
+
const response = await this._fetch(`${this.baseUrl}/api/plugins/${encodeURIComponent(id)}`);
|
|
746
758
|
if (!response.ok) {
|
|
747
759
|
if (response.status === 404) {
|
|
748
760
|
throw new Error(`Plugin not found: ${id}`);
|
|
@@ -757,7 +769,7 @@ class ControlPanelApi {
|
|
|
757
769
|
// ==================
|
|
758
770
|
|
|
759
771
|
async getUiContributions(): Promise<UiContributionsResponse> {
|
|
760
|
-
const response = await
|
|
772
|
+
const response = await this._fetch(`${this.baseUrl}/api/ui-contributions`);
|
|
761
773
|
if (!response.ok) {
|
|
762
774
|
throw new Error(`UI contributions request failed: ${response.statusText}`);
|
|
763
775
|
}
|
|
@@ -769,7 +781,7 @@ class ControlPanelApi {
|
|
|
769
781
|
// ==================
|
|
770
782
|
|
|
771
783
|
async getAuthConfigStatus(): Promise<AuthConfigStatus> {
|
|
772
|
-
const response = await
|
|
784
|
+
const response = await this._fetch(`${this.baseUrl}/api/auth/config/status`);
|
|
773
785
|
if (!response.ok) {
|
|
774
786
|
// Return disabled state if endpoint not available
|
|
775
787
|
if (response.status === 404) {
|
|
@@ -781,7 +793,7 @@ class ControlPanelApi {
|
|
|
781
793
|
}
|
|
782
794
|
|
|
783
795
|
async getAuthConfig(): Promise<AuthConfigStatus> {
|
|
784
|
-
const response = await
|
|
796
|
+
const response = await this._fetch(`${this.baseUrl}/api/auth/config`);
|
|
785
797
|
if (!response.ok) {
|
|
786
798
|
if (response.status === 404) {
|
|
787
799
|
return { state: 'disabled', adapter: null };
|
|
@@ -795,7 +807,7 @@ class ControlPanelApi {
|
|
|
795
807
|
* Update auth configuration (save to database for hot-reload)
|
|
796
808
|
*/
|
|
797
809
|
async updateAuthConfig(request: UpdateAuthConfigRequest): Promise<{ success: boolean; message: string }> {
|
|
798
|
-
const response = await
|
|
810
|
+
const response = await this._fetch(`${this.baseUrl}/api/auth/config`, {
|
|
799
811
|
method: 'PUT',
|
|
800
812
|
headers: { 'Content-Type': 'application/json' },
|
|
801
813
|
body: JSON.stringify(request),
|
|
@@ -811,7 +823,7 @@ class ControlPanelApi {
|
|
|
811
823
|
* Delete auth configuration (revert to environment variables)
|
|
812
824
|
*/
|
|
813
825
|
async deleteAuthConfig(): Promise<{ success: boolean; message: string }> {
|
|
814
|
-
const response = await
|
|
826
|
+
const response = await this._fetch(`${this.baseUrl}/api/auth/config`, {
|
|
815
827
|
method: 'DELETE',
|
|
816
828
|
});
|
|
817
829
|
if (!response.ok) {
|
|
@@ -825,7 +837,7 @@ class ControlPanelApi {
|
|
|
825
837
|
* Test auth provider connection without saving
|
|
826
838
|
*/
|
|
827
839
|
async testAuthProvider(request: TestProviderRequest): Promise<TestProviderResponse> {
|
|
828
|
-
const response = await
|
|
840
|
+
const response = await this._fetch(`${this.baseUrl}/api/auth/test-provider`, {
|
|
829
841
|
method: 'POST',
|
|
830
842
|
headers: { 'Content-Type': 'application/json' },
|
|
831
843
|
body: JSON.stringify(request),
|
|
@@ -841,7 +853,7 @@ class ControlPanelApi {
|
|
|
841
853
|
* Test current auth provider connection (uses existing env/runtime config)
|
|
842
854
|
*/
|
|
843
855
|
async testCurrentAuthProvider(): Promise<TestProviderResponse> {
|
|
844
|
-
const response = await
|
|
856
|
+
const response = await this._fetch(`${this.baseUrl}/api/auth/test-current`, {
|
|
845
857
|
method: 'POST',
|
|
846
858
|
headers: { 'Content-Type': 'application/json' },
|
|
847
859
|
});
|
|
@@ -857,7 +869,7 @@ class ControlPanelApi {
|
|
|
857
869
|
// ==================
|
|
858
870
|
|
|
859
871
|
async getRateLimitConfig(): Promise<RateLimitConfig> {
|
|
860
|
-
const response = await
|
|
872
|
+
const response = await this._fetch(`${this.baseUrl}/api/rate-limit/config`);
|
|
861
873
|
if (!response.ok) {
|
|
862
874
|
throw new Error(`Rate limit config request failed: ${response.statusText}`);
|
|
863
875
|
}
|
|
@@ -865,7 +877,7 @@ class ControlPanelApi {
|
|
|
865
877
|
}
|
|
866
878
|
|
|
867
879
|
async updateRateLimitConfig(updates: RateLimitConfigUpdateRequest): Promise<RateLimitConfigUpdateResponse> {
|
|
868
|
-
const response = await
|
|
880
|
+
const response = await this._fetch(`${this.baseUrl}/api/rate-limit/config`, {
|
|
869
881
|
method: 'PUT',
|
|
870
882
|
headers: { 'Content-Type': 'application/json' },
|
|
871
883
|
body: JSON.stringify(updates),
|
|
@@ -882,7 +894,7 @@ class ControlPanelApi {
|
|
|
882
894
|
// ==================
|
|
883
895
|
|
|
884
896
|
async getNotificationsStats(): Promise<NotificationsStatsResponse> {
|
|
885
|
-
const response = await
|
|
897
|
+
const response = await this._fetch(`${this.baseUrl}/api/notifications/stats`);
|
|
886
898
|
if (!response.ok) {
|
|
887
899
|
throw new Error(`Notifications stats request failed: ${response.statusText}`);
|
|
888
900
|
}
|
|
@@ -890,7 +902,7 @@ class ControlPanelApi {
|
|
|
890
902
|
}
|
|
891
903
|
|
|
892
904
|
async getNotificationsClients(): Promise<NotificationsClientsResponse> {
|
|
893
|
-
const response = await
|
|
905
|
+
const response = await this._fetch(`${this.baseUrl}/api/notifications/clients`);
|
|
894
906
|
if (!response.ok) {
|
|
895
907
|
throw new Error(`Notifications clients request failed: ${response.statusText}`);
|
|
896
908
|
}
|
|
@@ -898,7 +910,7 @@ class ControlPanelApi {
|
|
|
898
910
|
}
|
|
899
911
|
|
|
900
912
|
async disconnectNotificationsClient(clientId: string): Promise<{ success: boolean }> {
|
|
901
|
-
const response = await
|
|
913
|
+
const response = await this._fetch(`${this.baseUrl}/api/notifications/clients/${encodeURIComponent(clientId)}`, {
|
|
902
914
|
method: 'DELETE',
|
|
903
915
|
});
|
|
904
916
|
if (!response.ok) {
|
|
@@ -909,7 +921,7 @@ class ControlPanelApi {
|
|
|
909
921
|
}
|
|
910
922
|
|
|
911
923
|
async forceNotificationsReconnect(): Promise<{ success: boolean; message: string }> {
|
|
912
|
-
const response = await
|
|
924
|
+
const response = await this._fetch(`${this.baseUrl}/api/notifications/reconnect`, {
|
|
913
925
|
method: 'POST',
|
|
914
926
|
});
|
|
915
927
|
if (!response.ok) {
|