@qwickapps/server 1.8.1 → 1.8.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 +7 -0
- package/dist/src/core/control-panel.d.ts.map +1 -1
- package/dist/src/core/control-panel.js +10 -7
- package/dist/src/core/control-panel.js.map +1 -1
- package/dist/src/core/gateway.d.ts.map +1 -1
- package/dist/src/core/gateway.js +46 -47
- package/dist/src/core/gateway.js.map +1 -1
- package/dist/src/plugins/api-keys/ApiKeysManagementPage.d.ts.map +1 -1
- package/dist/src/plugins/api-keys/ApiKeysManagementPage.js +1 -1
- package/dist/src/plugins/api-keys/ApiKeysManagementPage.js.map +1 -1
- package/dist/src/plugins/api-keys/ApiKeysStatusWidget.d.ts.map +1 -1
- package/dist/src/plugins/api-keys/ApiKeysStatusWidget.js +1 -1
- package/dist/src/plugins/api-keys/ApiKeysStatusWidget.js.map +1 -1
- package/dist/src/plugins/auth/AuthManagementPage.d.ts.map +1 -1
- package/dist/src/plugins/auth/AuthManagementPage.js +1 -1
- package/dist/src/plugins/auth/AuthManagementPage.js.map +1 -1
- package/dist/src/plugins/auth/AuthStatusWidget.d.ts.map +1 -1
- package/dist/src/plugins/auth/AuthStatusWidget.js +1 -1
- package/dist/src/plugins/auth/AuthStatusWidget.js.map +1 -1
- package/dist/src/plugins/auth/auth-plugin.d.ts.map +1 -1
- package/dist/src/plugins/auth/auth-plugin.js +9 -0
- package/dist/src/plugins/auth/auth-plugin.js.map +1 -1
- package/dist/src/plugins/bans/BansManagementPage.d.ts.map +1 -1
- package/dist/src/plugins/bans/BansManagementPage.js +1 -1
- package/dist/src/plugins/bans/BansManagementPage.js.map +1 -1
- package/dist/src/plugins/bans/BansStatusWidget.d.ts.map +1 -1
- package/dist/src/plugins/bans/BansStatusWidget.js +1 -1
- package/dist/src/plugins/bans/BansStatusWidget.js.map +1 -1
- package/dist/src/plugins/cache/CacheManagementPage.js +1 -1
- package/dist/src/plugins/cache/CacheManagementPage.js.map +1 -1
- package/dist/src/plugins/cache/CacheStatusWidget.js +1 -1
- package/dist/src/plugins/cache/CacheStatusWidget.js.map +1 -1
- package/dist/src/plugins/devices/DevicesManagementPage.d.ts.map +1 -1
- package/dist/src/plugins/devices/DevicesManagementPage.js +1 -1
- package/dist/src/plugins/devices/DevicesManagementPage.js.map +1 -1
- package/dist/src/plugins/devices/DevicesStatusWidget.d.ts.map +1 -1
- package/dist/src/plugins/devices/DevicesStatusWidget.js +1 -1
- package/dist/src/plugins/devices/DevicesStatusWidget.js.map +1 -1
- package/dist/src/plugins/diagnostics/DiagnosticsManagementPage.js +1 -1
- package/dist/src/plugins/diagnostics/DiagnosticsManagementPage.js.map +1 -1
- package/dist/src/plugins/diagnostics/DiagnosticsStatusWidget.js +1 -1
- package/dist/src/plugins/diagnostics/DiagnosticsStatusWidget.js.map +1 -1
- package/dist/src/plugins/entitlements/EntitlementsManagementPage.d.ts.map +1 -1
- package/dist/src/plugins/entitlements/EntitlementsManagementPage.js +1 -1
- package/dist/src/plugins/entitlements/EntitlementsManagementPage.js.map +1 -1
- package/dist/src/plugins/entitlements/EntitlementsStatusWidget.d.ts.map +1 -1
- package/dist/src/plugins/entitlements/EntitlementsStatusWidget.js +1 -1
- package/dist/src/plugins/entitlements/EntitlementsStatusWidget.js.map +1 -1
- package/dist/src/plugins/health/HealthManagementPage.js +1 -1
- package/dist/src/plugins/health/HealthManagementPage.js.map +1 -1
- package/dist/src/plugins/health/HealthStatusWidget.js +1 -1
- package/dist/src/plugins/health/HealthStatusWidget.js.map +1 -1
- package/dist/src/plugins/logs/LogsManagementPage.js +1 -1
- package/dist/src/plugins/logs/LogsManagementPage.js.map +1 -1
- package/dist/src/plugins/logs/LogsStatusWidget.js +1 -1
- package/dist/src/plugins/logs/LogsStatusWidget.js.map +1 -1
- package/dist/src/plugins/maintenance/MaintenanceManagementPage.js +1 -1
- package/dist/src/plugins/maintenance/MaintenanceManagementPage.js.map +1 -1
- package/dist/src/plugins/maintenance/MaintenanceStatusWidget.js +1 -1
- package/dist/src/plugins/maintenance/MaintenanceStatusWidget.js.map +1 -1
- package/dist/src/plugins/maintenance/SeedManagementPage.js +1 -1
- package/dist/src/plugins/maintenance/SeedManagementPage.js.map +1 -1
- package/dist/src/plugins/maintenance/seed-executor.js +2 -2
- package/dist/src/plugins/maintenance/seed-executor.js.map +1 -1
- package/dist/src/plugins/maintenance-plugin.d.ts +2 -0
- package/dist/src/plugins/maintenance-plugin.d.ts.map +1 -1
- package/dist/src/plugins/maintenance-plugin.js +402 -2
- package/dist/src/plugins/maintenance-plugin.js.map +1 -1
- package/dist/src/plugins/notifications/NotificationsManagementPage.js +1 -1
- package/dist/src/plugins/notifications/NotificationsManagementPage.js.map +1 -1
- package/dist/src/plugins/notifications/NotificationsStatusWidget.d.ts.map +1 -1
- package/dist/src/plugins/notifications/NotificationsStatusWidget.js +1 -1
- package/dist/src/plugins/notifications/NotificationsStatusWidget.js.map +1 -1
- package/dist/src/plugins/parental/ParentalManagementPage.d.ts.map +1 -1
- package/dist/src/plugins/parental/ParentalManagementPage.js +1 -1
- package/dist/src/plugins/parental/ParentalManagementPage.js.map +1 -1
- package/dist/src/plugins/parental/ParentalStatusWidget.d.ts.map +1 -1
- package/dist/src/plugins/parental/ParentalStatusWidget.js +1 -1
- package/dist/src/plugins/parental/ParentalStatusWidget.js.map +1 -1
- package/dist/src/plugins/postgres/PostgresManagementPage.js +1 -1
- package/dist/src/plugins/postgres/PostgresManagementPage.js.map +1 -1
- package/dist/src/plugins/postgres/PostgresStatusWidget.js +1 -1
- package/dist/src/plugins/postgres/PostgresStatusWidget.js.map +1 -1
- package/dist/src/plugins/preferences/PreferencesManagementPage.d.ts.map +1 -1
- package/dist/src/plugins/preferences/PreferencesManagementPage.js +1 -1
- package/dist/src/plugins/preferences/PreferencesManagementPage.js.map +1 -1
- package/dist/src/plugins/preferences/PreferencesStatusWidget.d.ts.map +1 -1
- package/dist/src/plugins/preferences/PreferencesStatusWidget.js +1 -1
- package/dist/src/plugins/preferences/PreferencesStatusWidget.js.map +1 -1
- package/dist/src/plugins/profiles/ProfilesManagementPage.d.ts.map +1 -1
- package/dist/src/plugins/profiles/ProfilesManagementPage.js +1 -1
- package/dist/src/plugins/profiles/ProfilesManagementPage.js.map +1 -1
- package/dist/src/plugins/profiles/ProfilesStatusWidget.d.ts.map +1 -1
- package/dist/src/plugins/profiles/ProfilesStatusWidget.js +1 -1
- package/dist/src/plugins/profiles/ProfilesStatusWidget.js.map +1 -1
- package/dist/src/plugins/qwickbrain/QwickbrainManagementPage.js +1 -1
- package/dist/src/plugins/qwickbrain/QwickbrainManagementPage.js.map +1 -1
- package/dist/src/plugins/qwickbrain/QwickbrainStatusWidget.d.ts.map +1 -1
- package/dist/src/plugins/qwickbrain/QwickbrainStatusWidget.js +1 -1
- package/dist/src/plugins/qwickbrain/QwickbrainStatusWidget.js.map +1 -1
- package/dist/src/plugins/rate-limit/RateLimitManagementPage.js +1 -1
- package/dist/src/plugins/rate-limit/RateLimitManagementPage.js.map +1 -1
- package/dist/src/plugins/rate-limit/RateLimitStatusWidget.d.ts.map +1 -1
- package/dist/src/plugins/rate-limit/RateLimitStatusWidget.js +1 -1
- package/dist/src/plugins/rate-limit/RateLimitStatusWidget.js.map +1 -1
- package/dist/src/plugins/subscriptions/SubscriptionsManagementPage.d.ts.map +1 -1
- package/dist/src/plugins/subscriptions/SubscriptionsManagementPage.js +1 -1
- package/dist/src/plugins/subscriptions/SubscriptionsManagementPage.js.map +1 -1
- package/dist/src/plugins/subscriptions/SubscriptionsStatusWidget.d.ts.map +1 -1
- package/dist/src/plugins/subscriptions/SubscriptionsStatusWidget.js +1 -1
- package/dist/src/plugins/subscriptions/SubscriptionsStatusWidget.js.map +1 -1
- package/dist/src/plugins/usage/UsageManagementPage.d.ts.map +1 -1
- package/dist/src/plugins/usage/UsageManagementPage.js +1 -1
- package/dist/src/plugins/usage/UsageManagementPage.js.map +1 -1
- package/dist/src/plugins/usage/UsageStatusWidget.d.ts.map +1 -1
- package/dist/src/plugins/usage/UsageStatusWidget.js +1 -1
- package/dist/src/plugins/usage/UsageStatusWidget.js.map +1 -1
- package/dist/src/plugins/users/UsersManagementPage.js +1 -1
- package/dist/src/plugins/users/UsersManagementPage.js.map +1 -1
- package/dist/src/plugins/users/UsersStatusWidget.js +1 -1
- package/dist/src/plugins/users/UsersStatusWidget.js.map +1 -1
- package/dist/ui/src/api/clientBuilder.d.ts +3 -3
- package/dist/ui/src/api/clientBuilder.js +5 -5
- package/dist/ui/src/api/clientBuilder.js.map +1 -1
- package/dist/ui/src/api/controlPanelApi.js +19 -19
- package/dist/ui/src/api/controlPanelApi.js.map +1 -1
- package/dist/ui/src/components/ControlPanelApp.d.ts.map +1 -1
- package/dist/ui/src/components/ControlPanelApp.js +5 -4
- package/dist/ui/src/components/ControlPanelApp.js.map +1 -1
- package/dist/ui/src/dashboard/builtInWidgets.d.ts.map +1 -1
- package/dist/ui/src/dashboard/builtInWidgets.js +3 -1
- package/dist/ui/src/dashboard/builtInWidgets.js.map +1 -1
- package/dist/ui/src/dashboard/widgets/CMSMaintenanceWidget.js +8 -8
- package/dist/ui/src/dashboard/widgets/CMSMaintenanceWidget.js.map +1 -1
- package/dist/ui/src/dashboard/widgets/CMSStatusWidget.js +2 -2
- package/dist/ui/src/dashboard/widgets/CMSStatusWidget.js.map +1 -1
- package/dist/ui/src/dashboard/widgets/CacheMaintenanceWidget.js +4 -4
- package/dist/ui/src/dashboard/widgets/CacheMaintenanceWidget.js.map +1 -1
- package/dist/ui/src/dashboard/widgets/DatabaseOperationsWidget.d.ts.map +1 -1
- package/dist/ui/src/dashboard/widgets/DatabaseOperationsWidget.js +2 -1
- package/dist/ui/src/dashboard/widgets/DatabaseOperationsWidget.js.map +1 -1
- package/dist/ui/src/dashboard/widgets/LogsMaintenanceWidget.js +6 -6
- package/dist/ui/src/dashboard/widgets/LogsMaintenanceWidget.js.map +1 -1
- package/dist/ui/src/dashboard/widgets/MigrationManagementWidget.d.ts +8 -0
- package/dist/ui/src/dashboard/widgets/MigrationManagementWidget.d.ts.map +1 -0
- package/dist/ui/src/dashboard/widgets/MigrationManagementWidget.js +132 -0
- package/dist/ui/src/dashboard/widgets/MigrationManagementWidget.js.map +1 -0
- package/dist/ui/src/dashboard/widgets/SeedManagementWidget.js +6 -6
- package/dist/ui/src/dashboard/widgets/SeedManagementWidget.js.map +1 -1
- package/dist/ui/src/dashboard/widgets/index.d.ts +1 -0
- package/dist/ui/src/dashboard/widgets/index.d.ts.map +1 -1
- package/dist/ui/src/dashboard/widgets/index.js +1 -0
- package/dist/ui/src/dashboard/widgets/index.js.map +1 -1
- package/dist-ui/assets/{index-D-4HKPkw.js → index-Cez_jyhl.js} +111 -108
- package/dist-ui/assets/{index-D-4HKPkw.js.map → index-Cez_jyhl.js.map} +1 -1
- package/dist-ui/assets/{index-DRG9n0cx.css → index-De-dCl_t.css} +1 -1
- package/dist-ui/index.html +2 -2
- package/dist-ui-lib/index.js +2623 -2441
- package/dist-ui-lib/index.js.map +1 -1
- package/dist-ui-lib/src/api/clientBuilder.d.ts +3 -3
- package/dist-ui-lib/src/dashboard/widgets/MigrationManagementWidget.d.ts +7 -0
- package/dist-ui-lib/src/dashboard/widgets/index.d.ts +1 -0
- package/package.json +27 -26
- package/src/core/control-panel.ts +10 -7
- package/src/core/gateway.ts +48 -51
- package/src/plugins/api-keys/ApiKeysManagementPage.tsx +1 -1
- package/src/plugins/api-keys/ApiKeysStatusWidget.tsx +1 -1
- package/src/plugins/auth/AuthManagementPage.tsx +1 -1
- package/src/plugins/auth/AuthStatusWidget.tsx +1 -1
- package/src/plugins/auth/auth-plugin.ts +9 -0
- package/src/plugins/bans/BansManagementPage.tsx +1 -1
- package/src/plugins/bans/BansStatusWidget.tsx +1 -1
- package/src/plugins/cache/CacheManagementPage.tsx +1 -1
- package/src/plugins/cache/CacheStatusWidget.tsx +1 -1
- package/src/plugins/devices/DevicesManagementPage.tsx +1 -1
- package/src/plugins/devices/DevicesStatusWidget.tsx +1 -1
- package/src/plugins/diagnostics/DiagnosticsManagementPage.tsx +1 -1
- package/src/plugins/diagnostics/DiagnosticsStatusWidget.tsx +1 -1
- package/src/plugins/entitlements/EntitlementsManagementPage.tsx +1 -1
- package/src/plugins/entitlements/EntitlementsStatusWidget.tsx +1 -1
- package/src/plugins/health/HealthManagementPage.tsx +1 -1
- package/src/plugins/health/HealthStatusWidget.tsx +1 -1
- package/src/plugins/logs/LogsManagementPage.tsx +1 -1
- package/src/plugins/logs/LogsStatusWidget.tsx +1 -1
- package/src/plugins/maintenance/MaintenanceManagementPage.tsx +1 -1
- package/src/plugins/maintenance/MaintenanceStatusWidget.tsx +1 -1
- package/src/plugins/maintenance/SeedManagementPage.tsx +1 -1
- package/src/plugins/maintenance/seed-executor.ts +2 -2
- package/src/plugins/maintenance-plugin.ts +474 -2
- package/src/plugins/notifications/NotificationsManagementPage.tsx +1 -1
- package/src/plugins/notifications/NotificationsStatusWidget.tsx +1 -1
- package/src/plugins/parental/ParentalManagementPage.tsx +1 -1
- package/src/plugins/parental/ParentalStatusWidget.tsx +1 -1
- package/src/plugins/postgres/PostgresManagementPage.tsx +1 -1
- package/src/plugins/postgres/PostgresStatusWidget.tsx +1 -1
- package/src/plugins/preferences/PreferencesManagementPage.tsx +1 -1
- package/src/plugins/preferences/PreferencesStatusWidget.tsx +1 -1
- package/src/plugins/profiles/ProfilesManagementPage.tsx +1 -1
- package/src/plugins/profiles/ProfilesStatusWidget.tsx +1 -1
- package/src/plugins/qwickbrain/QwickbrainManagementPage.tsx +1 -1
- package/src/plugins/qwickbrain/QwickbrainStatusWidget.tsx +1 -1
- package/src/plugins/rate-limit/RateLimitManagementPage.tsx +1 -1
- package/src/plugins/rate-limit/RateLimitStatusWidget.tsx +1 -1
- package/src/plugins/subscriptions/SubscriptionsManagementPage.tsx +1 -1
- package/src/plugins/subscriptions/SubscriptionsStatusWidget.tsx +1 -1
- package/src/plugins/usage/UsageManagementPage.tsx +1 -1
- package/src/plugins/usage/UsageStatusWidget.tsx +1 -1
- package/src/plugins/users/UsersManagementPage.tsx +1 -1
- package/src/plugins/users/UsersStatusWidget.tsx +1 -1
- package/ui/src/App.tsx +4 -3
- package/ui/src/api/clientBuilder.ts +5 -5
- package/ui/src/api/controlPanelApi.ts +19 -19
- package/ui/src/components/ControlPanelApp.tsx +5 -4
- package/ui/src/dashboard/builtInWidgets.tsx +3 -0
- package/ui/src/dashboard/widgets/CMSMaintenanceWidget.tsx +8 -8
- package/ui/src/dashboard/widgets/CMSStatusWidget.tsx +2 -2
- package/ui/src/dashboard/widgets/CacheMaintenanceWidget.tsx +4 -4
- package/ui/src/dashboard/widgets/DatabaseOperationsWidget.tsx +2 -1
- package/ui/src/dashboard/widgets/LogsMaintenanceWidget.tsx +6 -6
- package/ui/src/dashboard/widgets/MigrationManagementWidget.tsx +319 -0
- package/ui/src/dashboard/widgets/SeedManagementWidget.tsx +6 -6
- package/ui/src/dashboard/widgets/index.ts +1 -0
- package/ui/src/hooks/useJobStream.ts +2 -2
- package/ui/src/pages/ContentOpsJobsPage.tsx +3 -3
- package/ui/src/pages/PluginPage.tsx +1 -1
- package/ui/src/pages/TenantsManagementPage.tsx +1 -1
|
@@ -18,15 +18,15 @@ export interface RouteManifestEntry {
|
|
|
18
18
|
/**
|
|
19
19
|
* Build typed API client from server manifest
|
|
20
20
|
*
|
|
21
|
-
* Fetches the manifest from /
|
|
21
|
+
* Fetches the manifest from /client-manifest (baseUrl already includes /qapi) and generates a nested
|
|
22
22
|
* client object with methods for each route.
|
|
23
23
|
*
|
|
24
|
-
* @param baseUrl - Base URL
|
|
24
|
+
* @param baseUrl - Base URL for QwickApps Server APIs (e.g., '/qapi' or 'http://localhost:3000/qapi')
|
|
25
25
|
* @returns Promise resolving to the generated client
|
|
26
26
|
*
|
|
27
27
|
* @example
|
|
28
28
|
* ```typescript
|
|
29
|
-
* const client = await buildClientFromManifest<APIClient>('
|
|
29
|
+
* const client = await buildClientFromManifest<APIClient>('/qapi');
|
|
30
30
|
* const logs = await client.logs.query({ limit: 10 });
|
|
31
31
|
* ```
|
|
32
32
|
*/
|
|
@@ -10,6 +10,7 @@ export { NotificationsStatsWidget } from './NotificationsStatsWidget';
|
|
|
10
10
|
export { CMSStatusWidget } from './CMSStatusWidget';
|
|
11
11
|
export { CMSMaintenanceWidget } from './CMSMaintenanceWidget';
|
|
12
12
|
export { SeedManagementWidget } from './SeedManagementWidget';
|
|
13
|
+
export { MigrationManagementWidget } from './MigrationManagementWidget';
|
|
13
14
|
export { ServiceControlWidget } from './ServiceControlWidget';
|
|
14
15
|
export { EnvironmentConfigWidget } from './EnvironmentConfigWidget';
|
|
15
16
|
export { DatabaseOpsWidget } from './DatabaseOpsWidget';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qwickapps/server",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.2",
|
|
4
4
|
"description": "Plugin-based application server framework for building websites, APIs, admin dashboards, and full-stack products",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"types": "dist/src/index.d.ts",
|
|
@@ -29,29 +29,6 @@
|
|
|
29
29
|
"ui",
|
|
30
30
|
"CHANGELOG.md"
|
|
31
31
|
],
|
|
32
|
-
"scripts": {
|
|
33
|
-
"build": "npm run build:ui-lib && npm run build:server && npm run build:ui",
|
|
34
|
-
"build:server": "tsc",
|
|
35
|
-
"build:ui": "cd ui && vite build",
|
|
36
|
-
"build:ui-lib": "cd ui && vite build --config vite.lib.config.ts && tsc -p tsconfig.lib.json",
|
|
37
|
-
"build:clean": "rm -rf dist dist-ui dist-ui-lib && npm run build",
|
|
38
|
-
"dev": "tsc --watch",
|
|
39
|
-
"dev:ui": "cd ui && vite",
|
|
40
|
-
"clean": "rm -rf dist dist-ui dist-ui-lib node_modules",
|
|
41
|
-
"test": "vitest run",
|
|
42
|
-
"test:watch": "vitest",
|
|
43
|
-
"test:coverage": "vitest run --coverage",
|
|
44
|
-
"test:e2e": "playwright test",
|
|
45
|
-
"test:e2e:ui": "playwright test --ui",
|
|
46
|
-
"test:e2e:headed": "playwright test --headed",
|
|
47
|
-
"demo": "npm run build:server && pnpm tsx examples/demo-server.ts",
|
|
48
|
-
"demo:gateway": "npm run build:server && pnpm tsx examples/demo-gateway.ts",
|
|
49
|
-
"demo:all": "npm run build:server && pnpm tsx examples/demo-all.ts",
|
|
50
|
-
"type-check": "tsc --noEmit",
|
|
51
|
-
"type-check:ui": "cd ui && tsc --noEmit",
|
|
52
|
-
"validate:clean-install": "./qa/clean-install/validate.sh",
|
|
53
|
-
"prepublishOnly": "npm run test && npm run build && npm run validate:clean-install"
|
|
54
|
-
},
|
|
55
32
|
"dependencies": {
|
|
56
33
|
"@qwickapps/logging": "^1.0.2",
|
|
57
34
|
"compression": "^1.7.4",
|
|
@@ -59,6 +36,8 @@
|
|
|
59
36
|
"express": "^4.18.2",
|
|
60
37
|
"helmet": "^7.1.0",
|
|
61
38
|
"http-proxy-middleware": "^3.0.3",
|
|
39
|
+
"prop-types": "^15.8.1",
|
|
40
|
+
"react-is": "^18.2.0",
|
|
62
41
|
"zod": "^3.22.4"
|
|
63
42
|
},
|
|
64
43
|
"devDependencies": {
|
|
@@ -90,7 +69,7 @@
|
|
|
90
69
|
"react": "^18.2.0",
|
|
91
70
|
"react-dom": "^18.2.0",
|
|
92
71
|
"react-router-dom": "^6.30.1",
|
|
93
|
-
"supertokens-node": "^
|
|
72
|
+
"supertokens-node": "^18.0.0",
|
|
94
73
|
"tsx": "^4.20.6",
|
|
95
74
|
"typescript": "^5.3.3",
|
|
96
75
|
"vite": "^6.0.0",
|
|
@@ -141,5 +120,27 @@
|
|
|
141
120
|
"homepage": "https://github.com/qwickapps/server#readme",
|
|
142
121
|
"publishConfig": {
|
|
143
122
|
"access": "public"
|
|
123
|
+
},
|
|
124
|
+
"scripts": {
|
|
125
|
+
"build": "npm run build:ui-lib && npm run build:server && npm run build:ui",
|
|
126
|
+
"build:server": "tsc",
|
|
127
|
+
"build:ui": "cd ui && vite build",
|
|
128
|
+
"build:ui-lib": "cd ui && vite build --config vite.lib.config.ts && tsc -p tsconfig.lib.json",
|
|
129
|
+
"build:clean": "rm -rf dist dist-ui dist-ui-lib && npm run build",
|
|
130
|
+
"dev": "tsc --watch",
|
|
131
|
+
"dev:ui": "cd ui && vite",
|
|
132
|
+
"clean": "rm -rf dist dist-ui dist-ui-lib node_modules",
|
|
133
|
+
"test": "vitest run",
|
|
134
|
+
"test:watch": "vitest",
|
|
135
|
+
"test:coverage": "vitest run --coverage",
|
|
136
|
+
"test:e2e": "playwright test",
|
|
137
|
+
"test:e2e:ui": "playwright test --ui",
|
|
138
|
+
"test:e2e:headed": "playwright test --headed",
|
|
139
|
+
"demo": "npm run build:server && pnpm tsx examples/demo-server.ts",
|
|
140
|
+
"demo:gateway": "npm run build:server && pnpm tsx examples/demo-gateway.ts",
|
|
141
|
+
"demo:all": "npm run build:server && pnpm tsx examples/demo-all.ts",
|
|
142
|
+
"type-check": "tsc --noEmit",
|
|
143
|
+
"type-check:ui": "cd ui && tsc --noEmit",
|
|
144
|
+
"validate:clean-install": "./qa/clean-install/validate.sh"
|
|
144
145
|
}
|
|
145
|
-
}
|
|
146
|
+
}
|
|
@@ -200,10 +200,11 @@ export function createControlPanel(options: CreateControlPanelOptions): ControlP
|
|
|
200
200
|
next();
|
|
201
201
|
});
|
|
202
202
|
|
|
203
|
-
// CRITICAL:
|
|
204
|
-
// This
|
|
205
|
-
//
|
|
206
|
-
|
|
203
|
+
// CRITICAL: QwickApps Server APIs always mount at /qapi regardless of mountPath
|
|
204
|
+
// This avoids conflicts with application-level APIs (e.g., Payload CMS uses /api)
|
|
205
|
+
// /qapi = QwickApps framework APIs (SuperTokens, health, postgres, cache, etc.)
|
|
206
|
+
// /api = Application/CMS APIs (Payload, custom app routes)
|
|
207
|
+
app.use('/qapi', router);
|
|
207
208
|
|
|
208
209
|
// Built-in routes
|
|
209
210
|
|
|
@@ -238,7 +239,7 @@ export function createControlPanel(options: CreateControlPanelOptions): ControlP
|
|
|
238
239
|
|
|
239
240
|
manifest[key] = {
|
|
240
241
|
method: route.method.toUpperCase(),
|
|
241
|
-
path:
|
|
242
|
+
path: route.path,
|
|
242
243
|
auth: route.auth?.required || false,
|
|
243
244
|
};
|
|
244
245
|
}
|
|
@@ -284,8 +285,10 @@ export function createControlPanel(options: CreateControlPanelOptions): ControlP
|
|
|
284
285
|
const effectivePath = forwardedPrefix || mountPath;
|
|
285
286
|
const normalizedPath = effectivePath === '/' ? '' : effectivePath;
|
|
286
287
|
|
|
287
|
-
// Inject base
|
|
288
|
-
|
|
288
|
+
// Inject base paths as global variables before other scripts
|
|
289
|
+
// __APP_BASE_PATH__: UI mount path for routing (e.g., '/cpanel')
|
|
290
|
+
// __API_BASE_PATH__: Base URL for QwickApps Server APIs (always '/qapi')
|
|
291
|
+
const basePathScript = `<script>window.__APP_BASE_PATH__="${normalizedPath}";window.__API_BASE_PATH__="/qapi";</script>`;
|
|
289
292
|
let html = indexHtmlTemplate.replace('<head>', `<head>\n ${basePathScript}`);
|
|
290
293
|
|
|
291
294
|
// Rewrite asset paths if mounted at a subpath
|
package/src/core/gateway.ts
CHANGED
|
@@ -1311,54 +1311,37 @@ export function createGateway(config: GatewayConfig): GatewayInstance {
|
|
|
1311
1311
|
);
|
|
1312
1312
|
}
|
|
1313
1313
|
|
|
1314
|
-
// 2.
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
//
|
|
1319
|
-
//
|
|
1320
|
-
|
|
1321
|
-
const cpApiPath = `${cpPath}/api`;
|
|
1322
|
-
const apiProxy = createProxyMiddleware({
|
|
1314
|
+
// 2. Create HTTP server (but don't listen yet - need server object for WS)
|
|
1315
|
+
server = createServer(app);
|
|
1316
|
+
|
|
1317
|
+
// 3. Setup mounted apps WITH QwickApps Server API proxy injected at the right position
|
|
1318
|
+
// QwickApps Server APIs (/qapi/*) need to be registered BEFORE root path proxy
|
|
1319
|
+
// to prevent being caught by frontend catch-all routing
|
|
1320
|
+
const qwickAppsApiProxy = createProxyMiddleware({
|
|
1323
1321
|
target: `http://localhost:${cpPort}`,
|
|
1324
1322
|
changeOrigin: true,
|
|
1325
|
-
pathRewrite: (path) => `/api${path}`, // Express removed {cpPath}/api, add back just /api (control panel APIs are at /api/*)
|
|
1326
1323
|
on: {
|
|
1327
1324
|
proxyReq: (proxyReq, req) => {
|
|
1328
|
-
|
|
1329
|
-
proxyReq.setHeader('X-Forwarded-Prefix', cpPath);
|
|
1330
|
-
logger.debug(`[API Proxy] Forwarding ${req.method} ${req.url} to control panel`);
|
|
1325
|
+
logger.debug(`[QwickApps API] Forwarding ${req.method} ${req.url} to QwickApps Server`);
|
|
1331
1326
|
},
|
|
1332
1327
|
proxyRes: (proxyRes, req) => {
|
|
1333
|
-
logger.debug(`[API
|
|
1328
|
+
logger.debug(`[QwickApps API] Response for ${req.url}: ${proxyRes.statusCode}`);
|
|
1334
1329
|
},
|
|
1335
1330
|
error: (err: Error, req: IncomingMessage, res: ServerResponse | Socket) => {
|
|
1336
|
-
logger.error(`[API
|
|
1331
|
+
logger.error(`[QwickApps API] Error for ${req.url}`, { error: err.message });
|
|
1337
1332
|
if (res && 'writeHead' in res && !res.headersSent) {
|
|
1338
1333
|
res.writeHead(503, { 'Content-Type': 'application/json' });
|
|
1339
1334
|
res.end(JSON.stringify({
|
|
1340
1335
|
error: 'Service Unavailable',
|
|
1341
|
-
message: '
|
|
1336
|
+
message: 'QwickApps Server APIs are currently unavailable.',
|
|
1342
1337
|
details: nodeEnv === 'development' ? err.message : undefined,
|
|
1343
1338
|
}));
|
|
1344
1339
|
}
|
|
1345
1340
|
},
|
|
1346
1341
|
},
|
|
1347
1342
|
});
|
|
1348
|
-
app.use(cpApiPath, apiProxy);
|
|
1349
|
-
logger.debug(`Setting up proxy: ${cpApiPath} -> http://localhost:${cpPort}/api`);
|
|
1350
|
-
mountedApps.push({ path: cpApiPath, type: 'proxy', target: `http://localhost:${cpPort}` });
|
|
1351
|
-
}
|
|
1352
|
-
|
|
1353
|
-
// 3. Create HTTP server (but don't listen yet - need server object for WS)
|
|
1354
|
-
server = createServer(app);
|
|
1355
1343
|
|
|
1356
|
-
|
|
1357
|
-
if (cpEnabled) {
|
|
1358
|
-
const cpPort = parseInt(process.env.CPANEL_PORT || String(gatewayPort + 1), 10);
|
|
1359
|
-
|
|
1360
|
-
// Proxy /cpanel to control panel UI
|
|
1361
|
-
// Express strips cpPath prefix, so we need custom proxy to add it back
|
|
1344
|
+
// Create control panel UI proxy (will be registered before root proxy)
|
|
1362
1345
|
const cpUiProxy = createProxyMiddleware({
|
|
1363
1346
|
target: `http://localhost:${cpPort}`,
|
|
1364
1347
|
changeOrigin: true,
|
|
@@ -1378,23 +1361,46 @@ export function createGateway(config: GatewayConfig): GatewayInstance {
|
|
|
1378
1361
|
},
|
|
1379
1362
|
},
|
|
1380
1363
|
});
|
|
1381
|
-
app.use(cpPath, cpUiProxy);
|
|
1382
1364
|
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1365
|
+
const apps = config.apps || [];
|
|
1366
|
+
for (const appConfig of apps) {
|
|
1367
|
+
// IMPORTANT: Insert QwickApps Server and Control Panel proxies BEFORE root path proxy
|
|
1368
|
+
// This ensures /qapi/* and /cpanel requests don't get caught by frontend catch-all routing
|
|
1369
|
+
if (appConfig.path === '/') {
|
|
1370
|
+
// 1. Register QwickApps Server API proxy at /qapi/* BEFORE the root proxy
|
|
1371
|
+
// These are framework APIs: SuperTokens auth, health checks, postgres, cache, etc.
|
|
1372
|
+
// Payload CMS uses natural Next.js /api/* path
|
|
1373
|
+
app.use((req, res, next) => {
|
|
1374
|
+
if (req.path.startsWith('/qapi/')) {
|
|
1375
|
+
return qwickAppsApiProxy(req, res, next);
|
|
1376
|
+
}
|
|
1377
|
+
next();
|
|
1378
|
+
});
|
|
1379
|
+
logger.debug(`Setting up proxy: /qapi/* -> http://localhost:${cpPort} (QwickApps Server APIs)`);
|
|
1380
|
+
mountedApps.push({ path: '/qapi', type: 'proxy', target: `http://localhost:${cpPort}` });
|
|
1381
|
+
|
|
1382
|
+
// 2. Register Control Panel UI proxy BEFORE the root proxy
|
|
1383
|
+
app.use(cpPath, cpUiProxy);
|
|
1384
|
+
mountedApps.push({ path: cpPath, type: 'proxy', target: `http://localhost:${cpPort}` });
|
|
1385
|
+
|
|
1386
|
+
// 3. Setup WebSocket upgrade handling for control panel UI
|
|
1387
|
+
server!.on('upgrade', (req: IncomingMessage, socket: Duplex, head: Buffer) => {
|
|
1388
|
+
if (req.url?.startsWith(cpPath)) {
|
|
1389
|
+
cpUiProxy.upgrade?.(req, socket as Socket, head);
|
|
1390
|
+
}
|
|
1391
|
+
});
|
|
1387
1392
|
}
|
|
1388
|
-
});
|
|
1389
1393
|
|
|
1390
|
-
|
|
1394
|
+
// Now register the app itself
|
|
1395
|
+
if (appConfig.source.type === 'proxy') {
|
|
1396
|
+
setupProxyApp(appConfig, server);
|
|
1397
|
+
} else {
|
|
1398
|
+
setupStaticApp(appConfig);
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1391
1401
|
}
|
|
1392
1402
|
|
|
1393
|
-
//
|
|
1394
|
-
const apps = config.apps || [];
|
|
1395
|
-
|
|
1396
|
-
// If plugins need maintenance, add root-level maintenance page
|
|
1397
|
-
// but keep /cpanel and /diagnostics accessible
|
|
1403
|
+
// 6. Add maintenance page if needed (after all proxies are set up)
|
|
1398
1404
|
if (cpEnabled) {
|
|
1399
1405
|
const pluginsNeedingMaintenance = controlPanelInstance!.getPluginRegistry().getPluginsNeedingMaintenance();
|
|
1400
1406
|
if (pluginsNeedingMaintenance.length > 0) {
|
|
@@ -1429,16 +1435,7 @@ export function createGateway(config: GatewayConfig): GatewayInstance {
|
|
|
1429
1435
|
}
|
|
1430
1436
|
}
|
|
1431
1437
|
|
|
1432
|
-
// Setup
|
|
1433
|
-
for (const appConfig of apps) {
|
|
1434
|
-
if (appConfig.source.type === 'proxy') {
|
|
1435
|
-
setupProxyApp(appConfig, server);
|
|
1436
|
-
} else {
|
|
1437
|
-
setupStaticApp(appConfig);
|
|
1438
|
-
}
|
|
1439
|
-
}
|
|
1440
|
-
|
|
1441
|
-
// 6. Setup frontend app at root
|
|
1438
|
+
// 7. Setup frontend app at root
|
|
1442
1439
|
setupFrontendApp();
|
|
1443
1440
|
|
|
1444
1441
|
// 7. Start listening (LAST STEP - after all middleware is registered)
|
|
@@ -24,7 +24,7 @@ interface ApiKey {
|
|
|
24
24
|
usageCount: number;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
export function ApiKeysManagementPage({ apiPrefix = '/
|
|
27
|
+
export function ApiKeysManagementPage({ apiPrefix = '/qapi/api-keys' }: ApiKeysManagementPageProps) {
|
|
28
28
|
const [activeTab, setActiveTab] = useState<'all' | 'active' | 'expired' | 'config'>('all');
|
|
29
29
|
const [keys, setKeys] = useState<ApiKey[]>([]);
|
|
30
30
|
const [loading, setLoading] = useState(true);
|
|
@@ -10,7 +10,7 @@ export interface ApiKeysStatusWidgetProps {
|
|
|
10
10
|
apiPrefix?: string;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
export function ApiKeysStatusWidget({ apiPrefix = '/
|
|
13
|
+
export function ApiKeysStatusWidget({ apiPrefix = '/qapi/api-keys' }: ApiKeysStatusWidgetProps) {
|
|
14
14
|
const [stats, setStats] = useState<{
|
|
15
15
|
totalKeys: number;
|
|
16
16
|
activeKeys: number;
|
|
@@ -30,7 +30,7 @@ interface AuthSession {
|
|
|
30
30
|
ipAddress?: string;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
export function AuthManagementPage({ apiPrefix = '/
|
|
33
|
+
export function AuthManagementPage({ apiPrefix = '/qapi/auth' }: AuthManagementPageProps) {
|
|
34
34
|
const [activeTab, setActiveTab] = useState<'overview' | 'providers' | 'sessions' | 'config'>('overview');
|
|
35
35
|
const [providers, setProviders] = useState<AuthProvider[]>([]);
|
|
36
36
|
const [sessions, setSessions] = useState<AuthSession[]>([]);
|
|
@@ -10,7 +10,7 @@ export interface AuthStatusWidgetProps {
|
|
|
10
10
|
apiPrefix?: string;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
export function AuthStatusWidget({ apiPrefix = '/
|
|
13
|
+
export function AuthStatusWidget({ apiPrefix = '/qapi/auth' }: AuthStatusWidgetProps) {
|
|
14
14
|
const [stats, setStats] = useState<{
|
|
15
15
|
totalProviders: number;
|
|
16
16
|
activeProviders: number;
|
|
@@ -73,6 +73,15 @@ export function createAuthPlugin(config: AuthPluginConfig): Plugin {
|
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
+
// Register SuperTokens middleware on router for /auth/* paths
|
|
77
|
+
// This ensures Gateway forwards ALL /api/auth/* requests to control panel
|
|
78
|
+
// where SuperTokens can handle them dynamically
|
|
79
|
+
if (Array.isArray(primaryMiddleware)) {
|
|
80
|
+
router.use('/auth', ...primaryMiddleware);
|
|
81
|
+
} else {
|
|
82
|
+
router.use('/auth', primaryMiddleware);
|
|
83
|
+
}
|
|
84
|
+
|
|
76
85
|
// Add the auth checking middleware to router (not app)
|
|
77
86
|
// This ensures it processes requests to /api/* routes
|
|
78
87
|
router.use(createAuthMiddleware());
|
|
@@ -23,7 +23,7 @@ interface Ban {
|
|
|
23
23
|
createdBy?: string;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
export function BansManagementPage({ apiPrefix = '/
|
|
26
|
+
export function BansManagementPage({ apiPrefix = '/qapi/bans' }: BansManagementPageProps) {
|
|
27
27
|
const [activeTab, setActiveTab] = useState<'all' | 'active' | 'expired' | 'config'>('all');
|
|
28
28
|
const [bans, setBans] = useState<Ban[]>([]);
|
|
29
29
|
const [loading, setLoading] = useState(true);
|
|
@@ -10,7 +10,7 @@ export interface BansStatusWidgetProps {
|
|
|
10
10
|
apiPrefix?: string;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
export function BansStatusWidget({ apiPrefix = '/
|
|
13
|
+
export function BansStatusWidget({ apiPrefix = '/qapi/bans' }: BansStatusWidgetProps) {
|
|
14
14
|
const [stats, setStats] = useState<{
|
|
15
15
|
totalBans: number;
|
|
16
16
|
activeBans: number;
|
|
@@ -32,7 +32,7 @@ interface CacheInfo {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
export const CacheManagementPage: React.FC<CacheManagementPageProps> = ({
|
|
35
|
-
apiPrefix = '/
|
|
35
|
+
apiPrefix = '/qapi/plugins/cache',
|
|
36
36
|
}) => {
|
|
37
37
|
const [keys, setKeys] = useState<CacheKey[]>([]);
|
|
38
38
|
const [info, setInfo] = useState<CacheInfo | null>(null);
|
|
@@ -26,7 +26,7 @@ interface CacheStats {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
export const CacheStatusWidget: React.FC<CacheStatusWidgetProps> = ({
|
|
29
|
-
apiPrefix = '/
|
|
29
|
+
apiPrefix = '/qapi/plugins/cache',
|
|
30
30
|
}) => {
|
|
31
31
|
const [stats, setStats] = useState<CacheStats | null>(null);
|
|
32
32
|
const [loading, setLoading] = useState(true);
|
|
@@ -23,7 +23,7 @@ interface Device {
|
|
|
23
23
|
lastActiveAt?: string;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
export function DevicesManagementPage({ apiPrefix = '/
|
|
26
|
+
export function DevicesManagementPage({ apiPrefix = '/qapi/devices' }: DevicesManagementPageProps) {
|
|
27
27
|
const [activeTab, setActiveTab] = useState<'all' | 'active' | 'pending' | 'config'>('all');
|
|
28
28
|
const [devices, setDevices] = useState<Device[]>([]);
|
|
29
29
|
const [loading, setLoading] = useState(true);
|
|
@@ -10,7 +10,7 @@ export interface DevicesStatusWidgetProps {
|
|
|
10
10
|
apiPrefix?: string;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
export function DevicesStatusWidget({ apiPrefix = '/
|
|
13
|
+
export function DevicesStatusWidget({ apiPrefix = '/qapi/devices' }: DevicesStatusWidgetProps) {
|
|
14
14
|
const [stats, setStats] = useState<{
|
|
15
15
|
totalDevices: number;
|
|
16
16
|
activeDevices: number;
|
|
@@ -38,7 +38,7 @@ interface DiagnosticsReport {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
export const DiagnosticsManagementPage: React.FC<DiagnosticsManagementPageProps> = ({
|
|
41
|
-
apiPrefix = '/
|
|
41
|
+
apiPrefix = '/qapi/plugins/diagnostics',
|
|
42
42
|
}) => {
|
|
43
43
|
const [report, setReport] = useState<DiagnosticsReport | null>(null);
|
|
44
44
|
const [loading, setLoading] = useState(true);
|
|
@@ -26,7 +26,7 @@ interface DiagnosticsStats {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
export const DiagnosticsStatusWidget: React.FC<DiagnosticsStatusWidgetProps> = ({
|
|
29
|
-
apiPrefix = '/
|
|
29
|
+
apiPrefix = '/qapi/plugins/diagnostics',
|
|
30
30
|
}) => {
|
|
31
31
|
const [stats, setStats] = useState<DiagnosticsStats | null>(null);
|
|
32
32
|
const [loading, setLoading] = useState(true);
|
|
@@ -22,7 +22,7 @@ interface Entitlement {
|
|
|
22
22
|
grantedBy?: string;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
export function EntitlementsManagementPage({ apiPrefix = '/
|
|
25
|
+
export function EntitlementsManagementPage({ apiPrefix = '/qapi/entitlements' }: EntitlementsManagementPageProps) {
|
|
26
26
|
const [activeTab, setActiveTab] = useState<'all' | 'active' | 'expired' | 'config'>('all');
|
|
27
27
|
const [entitlements, setEntitlements] = useState<Entitlement[]>([]);
|
|
28
28
|
const [loading, setLoading] = useState(true);
|
|
@@ -10,7 +10,7 @@ export interface EntitlementsStatusWidgetProps {
|
|
|
10
10
|
apiPrefix?: string;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
export function EntitlementsStatusWidget({ apiPrefix = '/
|
|
13
|
+
export function EntitlementsStatusWidget({ apiPrefix = '/qapi/entitlements' }: EntitlementsStatusWidgetProps) {
|
|
14
14
|
const [stats, setStats] = useState<{
|
|
15
15
|
totalEntitlements: number;
|
|
16
16
|
activeEntitlements: number;
|
|
@@ -33,7 +33,7 @@ interface HealthSummary {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
export const HealthManagementPage: React.FC<HealthManagementPageProps> = ({
|
|
36
|
-
apiPrefix = '/
|
|
36
|
+
apiPrefix = '/qapi/plugins/health',
|
|
37
37
|
}) => {
|
|
38
38
|
const [summary, setSummary] = useState<HealthSummary | null>(null);
|
|
39
39
|
const [selectedCheck, setSelectedCheck] = useState<HealthCheckResult | null>(null);
|
|
@@ -33,7 +33,7 @@ interface HealthSummary {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
export const HealthStatusWidget: React.FC<HealthStatusWidgetProps> = ({
|
|
36
|
-
apiPrefix = '/
|
|
36
|
+
apiPrefix = '/qapi/plugins/health',
|
|
37
37
|
}) => {
|
|
38
38
|
const [summary, setSummary] = useState<HealthSummary | null>(null);
|
|
39
39
|
const [loading, setLoading] = useState(true);
|
|
@@ -42,7 +42,7 @@ interface LogStats {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
export const LogsManagementPage: React.FC<LogsManagementPageProps> = ({
|
|
45
|
-
apiPrefix = '/
|
|
45
|
+
apiPrefix = '/qapi/plugins/logs',
|
|
46
46
|
}) => {
|
|
47
47
|
const [logs, setLogs] = useState<LogEntry[]>([]);
|
|
48
48
|
const [sources, setSources] = useState<LogSource[]>([]);
|
|
@@ -28,7 +28,7 @@ interface LogStats {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
export const LogsStatusWidget: React.FC<LogsStatusWidgetProps> = ({
|
|
31
|
-
apiPrefix = '/
|
|
31
|
+
apiPrefix = '/qapi/plugins/logs',
|
|
32
32
|
}) => {
|
|
33
33
|
const [stats, setStats] = useState<LogStats | null>(null);
|
|
34
34
|
const [loading, setLoading] = useState(true);
|
|
@@ -30,7 +30,7 @@ interface MaintenanceStatus {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
export const MaintenanceManagementPage: React.FC<MaintenanceManagementPageProps> = ({
|
|
33
|
-
apiPrefix = '/
|
|
33
|
+
apiPrefix = '/qapi/plugins/maintenance',
|
|
34
34
|
}) => {
|
|
35
35
|
const [status, setStatus] = useState<MaintenanceStatus | null>(null);
|
|
36
36
|
const [loading, setLoading] = useState(true);
|
|
@@ -26,7 +26,7 @@ interface MaintenanceStatus {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
export const MaintenanceStatusWidget: React.FC<MaintenanceStatusWidgetProps> = ({
|
|
29
|
-
apiPrefix = '/
|
|
29
|
+
apiPrefix = '/qapi/plugins/maintenance',
|
|
30
30
|
}) => {
|
|
31
31
|
const [status, setStatus] = useState<MaintenanceStatus | null>(null);
|
|
32
32
|
const [loading, setLoading] = useState(true);
|
|
@@ -19,7 +19,7 @@ export interface SeedManagementPageProps {
|
|
|
19
19
|
type Tab = 'list' | 'execute' | 'history';
|
|
20
20
|
|
|
21
21
|
export const SeedManagementPage: React.FC<SeedManagementPageProps> = ({
|
|
22
|
-
apiPrefix = '/
|
|
22
|
+
apiPrefix = '/qapi/plugins/maintenance',
|
|
23
23
|
}) => {
|
|
24
24
|
const [activeTab, setActiveTab] = useState<Tab>('list');
|
|
25
25
|
const [selectedSeed, setSelectedSeed] = useState<string | null>(null);
|
|
@@ -45,8 +45,8 @@ const MAX_OUTPUT_SIZE = 100 * 1024;
|
|
|
45
45
|
* @returns Resolved absolute path if valid, null if invalid
|
|
46
46
|
*/
|
|
47
47
|
export function validateScriptPath(scriptPath: string, scriptsPath: string): string | null {
|
|
48
|
-
// Only allow .mjs files
|
|
49
|
-
if (!scriptPath.endsWith('.mjs')) {
|
|
48
|
+
// Only allow .mjs and .ts files
|
|
49
|
+
if (!scriptPath.endsWith('.mjs') && !scriptPath.endsWith('.ts')) {
|
|
50
50
|
return null;
|
|
51
51
|
}
|
|
52
52
|
|