@qwickapps/server 1.2.0 → 1.3.1
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/README.md +392 -0
- package/dist/core/control-panel.d.ts +7 -2
- package/dist/core/control-panel.d.ts.map +1 -1
- package/dist/core/control-panel.js +120 -54
- package/dist/core/control-panel.js.map +1 -1
- package/dist/core/gateway.d.ts +159 -79
- package/dist/core/gateway.d.ts.map +1 -1
- package/dist/core/gateway.js +679 -319
- package/dist/core/gateway.js.map +1 -1
- package/dist/core/index.d.ts +3 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +2 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/plugin-registry.d.ts +307 -0
- package/dist/core/plugin-registry.d.ts.map +1 -0
- package/dist/core/plugin-registry.js +352 -0
- package/dist/core/plugin-registry.js.map +1 -0
- package/dist/core/types.d.ts +16 -33
- package/dist/core/types.d.ts.map +1 -1
- package/dist/index.d.ts +8 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -7
- package/dist/index.js.map +1 -1
- package/dist/plugins/auth/adapters/auth0-adapter.d.ts +14 -0
- package/dist/plugins/auth/adapters/auth0-adapter.d.ts.map +1 -0
- package/dist/plugins/auth/adapters/auth0-adapter.js +179 -0
- package/dist/plugins/auth/adapters/auth0-adapter.js.map +1 -0
- package/dist/plugins/auth/adapters/basic-adapter.d.ts +13 -0
- package/dist/plugins/auth/adapters/basic-adapter.d.ts.map +1 -0
- package/dist/plugins/auth/adapters/basic-adapter.js +51 -0
- package/dist/plugins/auth/adapters/basic-adapter.js.map +1 -0
- package/dist/plugins/auth/adapters/index.d.ts +10 -0
- package/dist/plugins/auth/adapters/index.d.ts.map +1 -0
- package/dist/plugins/auth/adapters/index.js +10 -0
- package/dist/plugins/auth/adapters/index.js.map +1 -0
- package/dist/plugins/auth/adapters/supabase-adapter.d.ts +13 -0
- package/dist/plugins/auth/adapters/supabase-adapter.d.ts.map +1 -0
- package/dist/plugins/auth/adapters/supabase-adapter.js +109 -0
- package/dist/plugins/auth/adapters/supabase-adapter.js.map +1 -0
- package/dist/plugins/auth/adapters/supertokens-adapter.d.ts +18 -0
- package/dist/plugins/auth/adapters/supertokens-adapter.d.ts.map +1 -0
- package/dist/plugins/auth/adapters/supertokens-adapter.js +267 -0
- package/dist/plugins/auth/adapters/supertokens-adapter.js.map +1 -0
- package/dist/plugins/auth/auth-plugin.d.ts +40 -0
- package/dist/plugins/auth/auth-plugin.d.ts.map +1 -0
- package/dist/plugins/auth/auth-plugin.js +255 -0
- package/dist/plugins/auth/auth-plugin.js.map +1 -0
- package/dist/plugins/auth/auth-plugin.test.d.ts +9 -0
- package/dist/plugins/auth/auth-plugin.test.d.ts.map +1 -0
- package/dist/plugins/auth/auth-plugin.test.js +147 -0
- package/dist/plugins/auth/auth-plugin.test.js.map +1 -0
- package/dist/plugins/auth/env-config.d.ts +88 -0
- package/dist/plugins/auth/env-config.d.ts.map +1 -0
- package/dist/plugins/auth/env-config.js +489 -0
- package/dist/plugins/auth/env-config.js.map +1 -0
- package/dist/plugins/auth/index.d.ts +14 -0
- package/dist/plugins/auth/index.d.ts.map +1 -0
- package/dist/plugins/auth/index.js +16 -0
- package/dist/plugins/auth/index.js.map +1 -0
- package/dist/plugins/auth/supertokens-adapter.test.d.ts +10 -0
- package/dist/plugins/auth/supertokens-adapter.test.d.ts.map +1 -0
- package/dist/plugins/auth/supertokens-adapter.test.js +486 -0
- package/dist/plugins/auth/supertokens-adapter.test.js.map +1 -0
- package/dist/plugins/auth/types.d.ts +218 -0
- package/dist/plugins/auth/types.d.ts.map +1 -0
- package/dist/plugins/auth/types.js +14 -0
- package/dist/plugins/auth/types.js.map +1 -0
- package/dist/plugins/bans/bans-plugin.d.ts +59 -0
- package/dist/plugins/bans/bans-plugin.d.ts.map +1 -0
- package/dist/plugins/bans/bans-plugin.js +428 -0
- package/dist/plugins/bans/bans-plugin.js.map +1 -0
- package/dist/plugins/bans/index.d.ts +9 -0
- package/dist/plugins/bans/index.d.ts.map +1 -0
- package/dist/plugins/bans/index.js +10 -0
- package/dist/plugins/bans/index.js.map +1 -0
- package/dist/plugins/bans/stores/index.d.ts +7 -0
- package/dist/plugins/bans/stores/index.d.ts.map +1 -0
- package/dist/plugins/bans/stores/index.js +7 -0
- package/dist/plugins/bans/stores/index.js.map +1 -0
- package/dist/plugins/bans/stores/postgres-store.d.ts +29 -0
- package/dist/plugins/bans/stores/postgres-store.d.ts.map +1 -0
- package/dist/plugins/bans/stores/postgres-store.js +132 -0
- package/dist/plugins/bans/stores/postgres-store.js.map +1 -0
- package/dist/plugins/bans/types.d.ts +128 -0
- package/dist/plugins/bans/types.d.ts.map +1 -0
- package/dist/plugins/bans/types.js +11 -0
- package/dist/plugins/bans/types.js.map +1 -0
- package/dist/plugins/cache-plugin.d.ts +14 -3
- package/dist/plugins/cache-plugin.d.ts.map +1 -1
- package/dist/plugins/cache-plugin.js +27 -7
- package/dist/plugins/cache-plugin.js.map +1 -1
- package/dist/plugins/cache-plugin.test.js +99 -32
- package/dist/plugins/cache-plugin.test.js.map +1 -1
- package/dist/plugins/config-plugin.d.ts +3 -2
- package/dist/plugins/config-plugin.d.ts.map +1 -1
- package/dist/plugins/config-plugin.js +17 -10
- package/dist/plugins/config-plugin.js.map +1 -1
- package/dist/plugins/diagnostics-plugin.d.ts +2 -2
- package/dist/plugins/diagnostics-plugin.d.ts.map +1 -1
- package/dist/plugins/diagnostics-plugin.js +17 -10
- package/dist/plugins/diagnostics-plugin.js.map +1 -1
- package/dist/plugins/entitlements/entitlements-plugin.d.ts +95 -0
- package/dist/plugins/entitlements/entitlements-plugin.d.ts.map +1 -0
- package/dist/plugins/entitlements/entitlements-plugin.js +707 -0
- package/dist/plugins/entitlements/entitlements-plugin.js.map +1 -0
- package/dist/plugins/entitlements/index.d.ts +12 -0
- package/dist/plugins/entitlements/index.d.ts.map +1 -0
- package/dist/plugins/entitlements/index.js +16 -0
- package/dist/plugins/entitlements/index.js.map +1 -0
- package/dist/plugins/entitlements/sources/index.d.ts +9 -0
- package/dist/plugins/entitlements/sources/index.d.ts.map +1 -0
- package/dist/plugins/entitlements/sources/index.js +9 -0
- package/dist/plugins/entitlements/sources/index.js.map +1 -0
- package/dist/plugins/entitlements/sources/postgres-source.d.ts +29 -0
- package/dist/plugins/entitlements/sources/postgres-source.d.ts.map +1 -0
- package/dist/plugins/entitlements/sources/postgres-source.js +169 -0
- package/dist/plugins/entitlements/sources/postgres-source.js.map +1 -0
- package/dist/plugins/entitlements/types.d.ts +232 -0
- package/dist/plugins/entitlements/types.d.ts.map +1 -0
- package/dist/plugins/entitlements/types.js +11 -0
- package/dist/plugins/entitlements/types.js.map +1 -0
- package/dist/plugins/frontend-app-plugin.d.ts +9 -3
- package/dist/plugins/frontend-app-plugin.d.ts.map +1 -1
- package/dist/plugins/frontend-app-plugin.js +14 -9
- package/dist/plugins/frontend-app-plugin.js.map +1 -1
- package/dist/plugins/health-plugin.d.ts +5 -2
- package/dist/plugins/health-plugin.d.ts.map +1 -1
- package/dist/plugins/health-plugin.js +20 -5
- package/dist/plugins/health-plugin.js.map +1 -1
- package/dist/plugins/index.d.ts +10 -2
- package/dist/plugins/index.d.ts.map +1 -1
- package/dist/plugins/index.js +10 -2
- package/dist/plugins/index.js.map +1 -1
- package/dist/plugins/logs-plugin.d.ts +3 -2
- package/dist/plugins/logs-plugin.d.ts.map +1 -1
- package/dist/plugins/logs-plugin.js +21 -12
- package/dist/plugins/logs-plugin.js.map +1 -1
- package/dist/plugins/postgres-plugin.d.ts +3 -3
- package/dist/plugins/postgres-plugin.d.ts.map +1 -1
- package/dist/plugins/postgres-plugin.js +9 -7
- package/dist/plugins/postgres-plugin.js.map +1 -1
- package/dist/plugins/postgres-plugin.test.js +50 -29
- package/dist/plugins/postgres-plugin.test.js.map +1 -1
- package/dist/plugins/preferences/__tests__/deep-merge.test.d.ts +7 -0
- package/dist/plugins/preferences/__tests__/deep-merge.test.d.ts.map +1 -0
- package/dist/plugins/preferences/__tests__/deep-merge.test.js +215 -0
- package/dist/plugins/preferences/__tests__/deep-merge.test.js.map +1 -0
- package/dist/plugins/preferences/__tests__/preferences-plugin.test.d.ts +7 -0
- package/dist/plugins/preferences/__tests__/preferences-plugin.test.d.ts.map +1 -0
- package/dist/plugins/preferences/__tests__/preferences-plugin.test.js +265 -0
- package/dist/plugins/preferences/__tests__/preferences-plugin.test.js.map +1 -0
- package/dist/plugins/preferences/index.d.ts +12 -0
- package/dist/plugins/preferences/index.d.ts.map +1 -0
- package/dist/plugins/preferences/index.js +13 -0
- package/dist/plugins/preferences/index.js.map +1 -0
- package/dist/plugins/preferences/preferences-plugin.d.ts +39 -0
- package/dist/plugins/preferences/preferences-plugin.d.ts.map +1 -0
- package/dist/plugins/preferences/preferences-plugin.js +226 -0
- package/dist/plugins/preferences/preferences-plugin.js.map +1 -0
- package/dist/plugins/preferences/stores/index.d.ts +9 -0
- package/dist/plugins/preferences/stores/index.d.ts.map +1 -0
- package/dist/plugins/preferences/stores/index.js +9 -0
- package/dist/plugins/preferences/stores/index.js.map +1 -0
- package/dist/plugins/preferences/stores/postgres-store.d.ts +41 -0
- package/dist/plugins/preferences/stores/postgres-store.d.ts.map +1 -0
- package/dist/plugins/preferences/stores/postgres-store.js +181 -0
- package/dist/plugins/preferences/stores/postgres-store.js.map +1 -0
- package/dist/plugins/preferences/types.d.ts +91 -0
- package/dist/plugins/preferences/types.d.ts.map +1 -0
- package/dist/plugins/preferences/types.js +10 -0
- package/dist/plugins/preferences/types.js.map +1 -0
- package/dist/plugins/users/__tests__/users-plugin.test.d.ts +9 -0
- package/dist/plugins/users/__tests__/users-plugin.test.d.ts.map +1 -0
- package/dist/plugins/users/__tests__/users-plugin.test.js +546 -0
- package/dist/plugins/users/__tests__/users-plugin.test.js.map +1 -0
- package/dist/plugins/users/index.d.ts +12 -0
- package/dist/plugins/users/index.d.ts.map +1 -0
- package/dist/plugins/users/index.js +13 -0
- package/dist/plugins/users/index.js.map +1 -0
- package/dist/plugins/users/stores/index.d.ts +7 -0
- package/dist/plugins/users/stores/index.d.ts.map +1 -0
- package/dist/plugins/users/stores/index.js +7 -0
- package/dist/plugins/users/stores/index.js.map +1 -0
- package/dist/plugins/users/stores/postgres-store.d.ts +28 -0
- package/dist/plugins/users/stores/postgres-store.d.ts.map +1 -0
- package/dist/plugins/users/stores/postgres-store.js +157 -0
- package/dist/plugins/users/stores/postgres-store.js.map +1 -0
- package/dist/plugins/users/types.d.ts +225 -0
- package/dist/plugins/users/types.d.ts.map +1 -0
- package/dist/plugins/users/types.js +12 -0
- package/dist/plugins/users/types.js.map +1 -0
- package/dist/plugins/users/users-plugin.d.ts +45 -0
- package/dist/plugins/users/users-plugin.d.ts.map +1 -0
- package/dist/plugins/users/users-plugin.js +359 -0
- package/dist/plugins/users/users-plugin.js.map +1 -0
- package/dist-ui/assets/index-BY8OxNgO.js +465 -0
- package/dist-ui/assets/index-BY8OxNgO.js.map +1 -0
- package/dist-ui/index.html +1 -1
- package/dist-ui-lib/api/controlPanelApi.d.ts +278 -0
- package/dist-ui-lib/components/ControlPanelApp.d.ts +61 -0
- package/dist-ui-lib/components/index.d.ts +18 -0
- package/dist-ui-lib/config/AppConfig.d.ts +7 -0
- package/dist-ui-lib/dashboard/DashboardWidgetRegistry.d.ts +62 -0
- package/dist-ui-lib/dashboard/DashboardWidgetRenderer.d.ts +8 -0
- package/dist-ui-lib/dashboard/PluginWidgetRenderer.d.ts +19 -0
- package/dist-ui-lib/dashboard/WidgetComponentRegistry.d.ts +48 -0
- package/dist-ui-lib/dashboard/builtInWidgets.d.ts +25 -0
- package/dist-ui-lib/dashboard/index.d.ts +13 -0
- package/dist-ui-lib/dashboard/widgets/ServiceHealthWidget.d.ts +12 -0
- package/dist-ui-lib/dashboard/widgets/index.d.ts +6 -0
- package/dist-ui-lib/index.js +5172 -0
- package/dist-ui-lib/index.js.map +1 -0
- package/dist-ui-lib/pages/AuthPage.d.ts +1 -0
- package/dist-ui-lib/pages/ConfigPage.d.ts +1 -0
- package/dist-ui-lib/pages/DashboardPage.d.ts +1 -0
- package/dist-ui-lib/pages/DiagnosticsPage.d.ts +1 -0
- package/dist-ui-lib/pages/EntitlementsPage.d.ts +17 -0
- package/dist-ui-lib/pages/LogsPage.d.ts +1 -0
- package/dist-ui-lib/pages/NotFoundPage.d.ts +1 -0
- package/dist-ui-lib/pages/PluginPage.d.ts +15 -0
- package/dist-ui-lib/pages/PluginsPage.d.ts +1 -0
- package/dist-ui-lib/pages/SystemPage.d.ts +1 -0
- package/dist-ui-lib/pages/UsersPage.d.ts +22 -0
- package/package.json +24 -7
- package/src/core/control-panel.ts +145 -61
- package/src/core/gateway.ts +863 -403
- package/src/core/index.ts +21 -2
- package/src/core/plugin-registry.ts +716 -0
- package/src/core/types.ts +31 -37
- package/src/index.ts +125 -19
- package/src/plugins/auth/adapters/auth0-adapter.ts +214 -0
- package/src/plugins/auth/adapters/basic-adapter.ts +61 -0
- package/src/plugins/auth/adapters/index.ts +10 -0
- package/src/plugins/auth/adapters/supabase-adapter.ts +149 -0
- package/src/plugins/auth/adapters/supertokens-adapter.ts +326 -0
- package/src/plugins/auth/auth-plugin.test.ts +176 -0
- package/src/plugins/auth/auth-plugin.ts +303 -0
- package/src/plugins/auth/env-config.ts +572 -0
- package/src/plugins/auth/index.ts +42 -0
- package/src/plugins/auth/supertokens-adapter.test.ts +621 -0
- package/src/plugins/auth/types.ts +245 -0
- package/src/plugins/bans/bans-plugin.ts +485 -0
- package/src/plugins/bans/index.ts +31 -0
- package/src/plugins/bans/stores/index.ts +7 -0
- package/src/plugins/bans/stores/postgres-store.ts +195 -0
- package/src/plugins/bans/types.ts +141 -0
- package/src/plugins/cache-plugin.test.ts +108 -32
- package/src/plugins/cache-plugin.ts +40 -9
- package/src/plugins/config-plugin.ts +23 -12
- package/src/plugins/diagnostics-plugin.ts +22 -12
- package/src/plugins/entitlements/entitlements-plugin.ts +820 -0
- package/src/plugins/entitlements/index.ts +51 -0
- package/src/plugins/entitlements/sources/index.ts +9 -0
- package/src/plugins/entitlements/sources/postgres-source.ts +253 -0
- package/src/plugins/entitlements/types.ts +256 -0
- package/src/plugins/frontend-app-plugin.ts +24 -12
- package/src/plugins/health-plugin.ts +27 -7
- package/src/plugins/index.ts +132 -4
- package/src/plugins/logs-plugin.ts +28 -14
- package/src/plugins/postgres-plugin.test.ts +52 -29
- package/src/plugins/postgres-plugin.ts +11 -9
- package/src/plugins/preferences/__tests__/deep-merge.test.ts +242 -0
- package/src/plugins/preferences/__tests__/preferences-plugin.test.ts +350 -0
- package/src/plugins/preferences/index.ts +30 -0
- package/src/plugins/preferences/preferences-plugin.ts +270 -0
- package/src/plugins/preferences/stores/index.ts +9 -0
- package/src/plugins/preferences/stores/postgres-store.ts +252 -0
- package/src/plugins/preferences/types.ts +100 -0
- package/src/plugins/users/__tests__/users-plugin.test.ts +690 -0
- package/src/plugins/users/index.ts +38 -0
- package/src/plugins/users/stores/index.ts +7 -0
- package/src/plugins/users/stores/postgres-store.ts +225 -0
- package/src/plugins/users/types.ts +247 -0
- package/src/plugins/users/users-plugin.ts +418 -0
- package/ui/src/App.tsx +188 -31
- package/ui/src/api/controlPanelApi.ts +453 -1
- package/ui/src/components/ControlPanelApp.tsx +212 -0
- package/ui/src/components/index.ts +62 -0
- package/ui/src/dashboard/DashboardWidgetRegistry.tsx +129 -0
- package/ui/src/dashboard/DashboardWidgetRenderer.tsx +34 -0
- package/ui/src/dashboard/PluginWidgetRenderer.tsx +118 -0
- package/ui/src/dashboard/WidgetComponentRegistry.tsx +120 -0
- package/ui/src/dashboard/builtInWidgets.tsx +35 -0
- package/ui/src/dashboard/index.ts +35 -0
- package/ui/src/dashboard/widgets/ServiceHealthWidget.tsx +140 -0
- package/ui/src/dashboard/widgets/index.ts +7 -0
- package/ui/src/pages/AuthPage.tsx +259 -0
- package/ui/src/pages/DashboardPage.tsx +28 -149
- package/ui/src/pages/EntitlementsPage.tsx +557 -0
- package/ui/src/pages/LogsPage.tsx +174 -8
- package/ui/src/pages/PluginPage.tsx +148 -0
- package/ui/src/pages/PluginsPage.tsx +394 -0
- package/ui/src/pages/SystemPage.tsx +445 -0
- package/ui/src/pages/UsersPage.tsx +837 -0
- package/ui/tsconfig.lib.json +11 -0
- package/ui/vite.lib.config.ts +56 -0
- package/dist-ui/assets/index-CW1BviRn.js +0 -465
- package/dist-ui/assets/index-CW1BviRn.js.map +0 -1
- package/ui/src/pages/HealthPage.tsx +0 -204
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function AuthPage(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function ConfigPage(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function DashboardPage(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function DiagnosticsPage(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* EntitlementsPage Component
|
|
3
|
+
*
|
|
4
|
+
* Entitlement catalog management page. Allows viewing and managing available entitlements.
|
|
5
|
+
* Write operations (create, edit, delete) are only available when source is not readonly.
|
|
6
|
+
*
|
|
7
|
+
* Copyright (c) 2025 QwickApps.com. All rights reserved.
|
|
8
|
+
*/
|
|
9
|
+
export interface EntitlementsPageProps {
|
|
10
|
+
/** Page title */
|
|
11
|
+
title?: string;
|
|
12
|
+
/** Page subtitle */
|
|
13
|
+
subtitle?: string;
|
|
14
|
+
/** Custom actions to render in the header */
|
|
15
|
+
headerActions?: React.ReactNode;
|
|
16
|
+
}
|
|
17
|
+
export declare function EntitlementsPage({ title, subtitle, headerActions, }: EntitlementsPageProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function LogsPage(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function NotFoundPage(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PluginPage Component
|
|
3
|
+
*
|
|
4
|
+
* A generic page component for plugin-contributed routes.
|
|
5
|
+
* Fetches and displays plugin-specific content from the API.
|
|
6
|
+
*
|
|
7
|
+
* Copyright (c) 2025 QwickApps.com. All rights reserved.
|
|
8
|
+
*/
|
|
9
|
+
interface PluginPageProps {
|
|
10
|
+
pluginId: string;
|
|
11
|
+
title: string;
|
|
12
|
+
route: string;
|
|
13
|
+
}
|
|
14
|
+
export declare function PluginPage({ pluginId, title, route }: PluginPageProps): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function PluginsPage(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function SystemPage(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UsersPage Component
|
|
3
|
+
*
|
|
4
|
+
* Generic user management page that works with Users, Bans, and Entitlements plugins.
|
|
5
|
+
* All features are optional and auto-detected based on available plugins.
|
|
6
|
+
*
|
|
7
|
+
* Copyright (c) 2025 QwickApps.com. All rights reserved.
|
|
8
|
+
*/
|
|
9
|
+
import { type User, type PluginFeatures } from '../api/controlPanelApi';
|
|
10
|
+
export interface UsersPageProps {
|
|
11
|
+
/** Page title */
|
|
12
|
+
title?: string;
|
|
13
|
+
/** Page subtitle */
|
|
14
|
+
subtitle?: string;
|
|
15
|
+
/** Override automatic feature detection */
|
|
16
|
+
features?: Partial<PluginFeatures>;
|
|
17
|
+
/** Custom actions to render in the header */
|
|
18
|
+
headerActions?: React.ReactNode;
|
|
19
|
+
/** Callback when a user is selected */
|
|
20
|
+
onUserSelect?: (user: User) => void;
|
|
21
|
+
}
|
|
22
|
+
export declare function UsersPage({ title, subtitle, features: featureOverrides, headerActions, onUserSelect, }: UsersPageProps): import("react/jsx-runtime").JSX.Element;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qwickapps/server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "Plugin-based application server framework for building websites, APIs, admin dashboards, and full-stack products",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -13,25 +13,35 @@
|
|
|
13
13
|
"./plugins": {
|
|
14
14
|
"types": "./dist/plugins/index.d.ts",
|
|
15
15
|
"import": "./dist/plugins/index.js"
|
|
16
|
+
},
|
|
17
|
+
"./ui": {
|
|
18
|
+
"types": "./dist-ui-lib/components/index.d.ts",
|
|
19
|
+
"import": "./dist-ui-lib/index.js"
|
|
16
20
|
}
|
|
17
21
|
},
|
|
18
22
|
"files": [
|
|
19
23
|
"dist",
|
|
20
24
|
"dist-ui",
|
|
25
|
+
"dist-ui-lib",
|
|
21
26
|
"src",
|
|
22
27
|
"ui"
|
|
23
28
|
],
|
|
24
29
|
"scripts": {
|
|
25
|
-
"build": "npm run build:server && npm run build:ui",
|
|
30
|
+
"build": "npm run build:server && npm run build:ui && npm run build:ui-lib",
|
|
26
31
|
"build:server": "tsc",
|
|
27
32
|
"build:ui": "cd ui && vite build",
|
|
28
|
-
"build:
|
|
33
|
+
"build:ui-lib": "cd ui && vite build --config vite.lib.config.ts && tsc -p tsconfig.lib.json",
|
|
34
|
+
"build:clean": "rm -rf dist dist-ui dist-ui-lib && npm run build",
|
|
29
35
|
"dev": "tsc --watch",
|
|
30
36
|
"dev:ui": "cd ui && vite",
|
|
31
|
-
"clean": "rm -rf dist dist-ui node_modules",
|
|
37
|
+
"clean": "rm -rf dist dist-ui dist-ui-lib node_modules",
|
|
32
38
|
"test": "vitest run",
|
|
33
39
|
"test:watch": "vitest",
|
|
34
40
|
"test:coverage": "vitest run --coverage",
|
|
41
|
+
"test:e2e": "playwright test",
|
|
42
|
+
"test:e2e:ui": "playwright test --ui",
|
|
43
|
+
"test:e2e:headed": "playwright test --headed",
|
|
44
|
+
"demo": "npx tsx examples/demo-server.ts",
|
|
35
45
|
"type-check": "tsc --noEmit",
|
|
36
46
|
"type-check:ui": "cd ui && tsc --noEmit",
|
|
37
47
|
"validate:clean-install": "./qa/clean-install/validate.sh",
|
|
@@ -50,6 +60,7 @@
|
|
|
50
60
|
"@emotion/styled": "^11.14.0",
|
|
51
61
|
"@mui/icons-material": "^7.2.0",
|
|
52
62
|
"@mui/material": "^7.2.0",
|
|
63
|
+
"@playwright/test": "^1.57.0",
|
|
53
64
|
"@qwickapps/react-framework": "^1.5.5",
|
|
54
65
|
"@types/compression": "^1.7.5",
|
|
55
66
|
"@types/cors": "^2.8.17",
|
|
@@ -57,14 +68,16 @@
|
|
|
57
68
|
"@types/node": "^20.10.5",
|
|
58
69
|
"@types/pg": "^8.11.0",
|
|
59
70
|
"@types/react": "^18.2.0",
|
|
60
|
-
"ioredis": "^5.4.0",
|
|
61
|
-
"pg": "^8.13.0",
|
|
62
71
|
"@types/react-dom": "^18.2.0",
|
|
63
72
|
"@vitejs/plugin-react": "^4.3.4",
|
|
64
73
|
"express-openid-connect": "^2.19.3",
|
|
74
|
+
"ioredis": "^5.4.0",
|
|
75
|
+
"pg": "^8.13.0",
|
|
65
76
|
"react": "^18.2.0",
|
|
66
77
|
"react-dom": "^18.2.0",
|
|
67
78
|
"react-router-dom": "^6.30.1",
|
|
79
|
+
"supertokens-node": "^20.1.7",
|
|
80
|
+
"tsx": "^4.20.6",
|
|
68
81
|
"typescript": "^5.3.3",
|
|
69
82
|
"vite": "^6.0.0",
|
|
70
83
|
"vitest": "^2.1.0"
|
|
@@ -73,7 +86,8 @@
|
|
|
73
86
|
"@qwickapps/react-framework": ">=1.0.0",
|
|
74
87
|
"express-openid-connect": ">=2.0.0",
|
|
75
88
|
"ioredis": ">=5.0.0",
|
|
76
|
-
"pg": ">=8.0.0"
|
|
89
|
+
"pg": ">=8.0.0",
|
|
90
|
+
"supertokens-node": ">=20.0.0"
|
|
77
91
|
},
|
|
78
92
|
"peerDependenciesMeta": {
|
|
79
93
|
"@qwickapps/react-framework": {
|
|
@@ -87,6 +101,9 @@
|
|
|
87
101
|
},
|
|
88
102
|
"pg": {
|
|
89
103
|
"optional": true
|
|
104
|
+
},
|
|
105
|
+
"supertokens-node": {
|
|
106
|
+
"optional": true
|
|
90
107
|
}
|
|
91
108
|
},
|
|
92
109
|
"keywords": [
|
|
@@ -10,7 +10,7 @@ import express, { type Application, type Router, type Request, type Response } f
|
|
|
10
10
|
import helmet from 'helmet';
|
|
11
11
|
import cors from 'cors';
|
|
12
12
|
import compression from 'compression';
|
|
13
|
-
import { existsSync } from 'node:fs';
|
|
13
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
14
14
|
import { fileURLToPath } from 'node:url';
|
|
15
15
|
import { dirname, join } from 'node:path';
|
|
16
16
|
import { HealthManager } from './health-manager.js';
|
|
@@ -18,13 +18,17 @@ import { initializeLogging, getControlPanelLogger, type LoggingConfig } from './
|
|
|
18
18
|
import { createRouteGuard } from './guards.js';
|
|
19
19
|
import type {
|
|
20
20
|
ControlPanelConfig,
|
|
21
|
-
ControlPanelPlugin,
|
|
22
21
|
ControlPanelInstance,
|
|
23
|
-
PluginContext,
|
|
24
22
|
DiagnosticsReport,
|
|
25
23
|
HealthCheck,
|
|
26
24
|
Logger,
|
|
27
25
|
} from './types.js';
|
|
26
|
+
import {
|
|
27
|
+
createPluginRegistry,
|
|
28
|
+
type Plugin,
|
|
29
|
+
type PluginConfig,
|
|
30
|
+
type PluginRegistryImpl,
|
|
31
|
+
} from './plugin-registry.js';
|
|
28
32
|
|
|
29
33
|
// Get the package root directory for serving UI assets
|
|
30
34
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -35,9 +39,22 @@ const packageRoot = __dirname.includes('/src/')
|
|
|
35
39
|
: join(__dirname, '..', '..');
|
|
36
40
|
const uiDistPath = join(packageRoot, 'dist-ui');
|
|
37
41
|
|
|
42
|
+
// Read @qwickapps/server package version
|
|
43
|
+
let frameworkVersion = '1.0.0';
|
|
44
|
+
try {
|
|
45
|
+
const packageJsonPath = join(packageRoot, 'package.json');
|
|
46
|
+
if (existsSync(packageJsonPath)) {
|
|
47
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
|
|
48
|
+
frameworkVersion = packageJson.version || '1.0.0';
|
|
49
|
+
}
|
|
50
|
+
} catch {
|
|
51
|
+
// Keep default version if reading fails
|
|
52
|
+
}
|
|
53
|
+
|
|
38
54
|
export interface CreateControlPanelOptions {
|
|
39
55
|
config: ControlPanelConfig;
|
|
40
|
-
|
|
56
|
+
/** Plugins to start with the control panel */
|
|
57
|
+
plugins?: Array<{ plugin: Plugin; config?: PluginConfig }>;
|
|
41
58
|
logger?: Logger;
|
|
42
59
|
/** Logging configuration */
|
|
43
60
|
logging?: LoggingConfig;
|
|
@@ -61,10 +78,18 @@ export function createControlPanel(options: CreateControlPanelOptions): ControlP
|
|
|
61
78
|
const app: Application = express();
|
|
62
79
|
const router: Router = express.Router();
|
|
63
80
|
const healthManager = new HealthManager(logger);
|
|
64
|
-
const registeredPlugins: ControlPanelPlugin[] = [];
|
|
65
81
|
let server: ReturnType<typeof app.listen> | null = null;
|
|
66
82
|
const startTime = Date.now();
|
|
67
83
|
|
|
84
|
+
// Initialize the new plugin registry
|
|
85
|
+
const pluginRegistry = createPluginRegistry(
|
|
86
|
+
app,
|
|
87
|
+
router,
|
|
88
|
+
logger,
|
|
89
|
+
healthManager,
|
|
90
|
+
getControlPanelLogger
|
|
91
|
+
);
|
|
92
|
+
|
|
68
93
|
// Security middleware
|
|
69
94
|
app.use(
|
|
70
95
|
helmet({
|
|
@@ -139,6 +164,8 @@ export function createControlPanel(options: CreateControlPanelOptions): ControlP
|
|
|
139
164
|
router.get('/info', (_req: Request, res: Response) => {
|
|
140
165
|
res.json({
|
|
141
166
|
product: config.productName,
|
|
167
|
+
logoName: config.logoName || config.productName,
|
|
168
|
+
logoIconUrl: config.logoIconUrl,
|
|
142
169
|
version: config.version || 'unknown',
|
|
143
170
|
uptime: Date.now() - startTime,
|
|
144
171
|
links: config.links || [],
|
|
@@ -154,6 +181,61 @@ export function createControlPanel(options: CreateControlPanelOptions): ControlP
|
|
|
154
181
|
res.json(report);
|
|
155
182
|
});
|
|
156
183
|
|
|
184
|
+
/**
|
|
185
|
+
* GET /api/ui-contributions - UI contributions from all plugins
|
|
186
|
+
*
|
|
187
|
+
* Returns menu items, pages, and widgets registered by plugins.
|
|
188
|
+
* Used by the React UI to build dynamic navigation and pages.
|
|
189
|
+
*/
|
|
190
|
+
router.get('/ui-contributions', (_req: Request, res: Response) => {
|
|
191
|
+
res.json({
|
|
192
|
+
menuItems: pluginRegistry.getMenuItems(),
|
|
193
|
+
pages: pluginRegistry.getPages(),
|
|
194
|
+
widgets: pluginRegistry.getWidgets(),
|
|
195
|
+
plugins: pluginRegistry.listPlugins(),
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* GET /api/plugins - List all registered plugins with contribution counts
|
|
201
|
+
*/
|
|
202
|
+
router.get('/plugins', (_req: Request, res: Response) => {
|
|
203
|
+
const plugins = pluginRegistry.listPlugins().map((plugin) => {
|
|
204
|
+
const contributions = pluginRegistry.getPluginContributions(plugin.id);
|
|
205
|
+
return {
|
|
206
|
+
...plugin,
|
|
207
|
+
contributionCounts: {
|
|
208
|
+
routes: contributions.routes.length,
|
|
209
|
+
menuItems: contributions.menuItems.length,
|
|
210
|
+
pages: contributions.pages.length,
|
|
211
|
+
widgets: contributions.widgets.length,
|
|
212
|
+
hasConfig: !!contributions.config,
|
|
213
|
+
},
|
|
214
|
+
};
|
|
215
|
+
});
|
|
216
|
+
res.json({ plugins });
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* GET /api/plugins/:id - Get detailed plugin info with contributions
|
|
221
|
+
*/
|
|
222
|
+
router.get('/plugins/:id', (req: Request, res: Response) => {
|
|
223
|
+
const { id } = req.params;
|
|
224
|
+
const plugins = pluginRegistry.listPlugins();
|
|
225
|
+
const plugin = plugins.find((p) => p.id === id);
|
|
226
|
+
|
|
227
|
+
if (!plugin) {
|
|
228
|
+
res.status(404).json({ error: `Plugin not found: ${id}` });
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const contributions = pluginRegistry.getPluginContributions(id);
|
|
233
|
+
res.json({
|
|
234
|
+
...plugin,
|
|
235
|
+
contributions,
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
|
|
157
239
|
/**
|
|
158
240
|
* Serve dashboard UI at the configured mount path
|
|
159
241
|
*
|
|
@@ -171,22 +253,61 @@ export function createControlPanel(options: CreateControlPanelOptions): ControlP
|
|
|
171
253
|
|
|
172
254
|
if (useRichUI) {
|
|
173
255
|
logger.debug(`Serving React UI from ${effectiveUiPath}`);
|
|
256
|
+
|
|
257
|
+
// Read index.html template
|
|
258
|
+
const indexHtmlPath = join(effectiveUiPath, 'index.html');
|
|
259
|
+
const indexHtmlTemplate = readFileSync(indexHtmlPath, 'utf-8');
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Get index.html with the base path injected.
|
|
263
|
+
*
|
|
264
|
+
* The server injects the base path as window.__APP_BASE_PATH__ so the React app
|
|
265
|
+
* can read it at runtime without complex detection logic. This is the standard
|
|
266
|
+
* pattern used by frameworks like Next.js (__NEXT_DATA__).
|
|
267
|
+
*
|
|
268
|
+
* When served behind a gateway proxy, use X-Forwarded-Prefix to determine
|
|
269
|
+
* the public path for assets and the React Router basename.
|
|
270
|
+
*/
|
|
271
|
+
const getIndexHtml = (req: Request): string => {
|
|
272
|
+
// Determine the effective public path:
|
|
273
|
+
// - If X-Forwarded-Prefix header is set (proxied), use that
|
|
274
|
+
// - Otherwise, use the configured mountPath
|
|
275
|
+
const forwardedPrefix = req.get('X-Forwarded-Prefix');
|
|
276
|
+
const effectivePath = forwardedPrefix || mountPath;
|
|
277
|
+
const normalizedPath = effectivePath === '/' ? '' : effectivePath;
|
|
278
|
+
|
|
279
|
+
// Inject base path as global variable before other scripts
|
|
280
|
+
const basePathScript = `<script>window.__APP_BASE_PATH__="${normalizedPath}";</script>`;
|
|
281
|
+
let html = indexHtmlTemplate.replace('<head>', `<head>\n ${basePathScript}`);
|
|
282
|
+
|
|
283
|
+
// Rewrite asset paths if mounted at a subpath
|
|
284
|
+
if (normalizedPath) {
|
|
285
|
+
html = html.replace(/src="\/assets\//g, `src="${normalizedPath}/assets/`);
|
|
286
|
+
html = html.replace(/href="\/assets\//g, `href="${normalizedPath}/assets/`);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
return html;
|
|
290
|
+
};
|
|
291
|
+
|
|
174
292
|
// Serve static assets from dist-ui at the mount path
|
|
175
|
-
|
|
293
|
+
// Disable index: false to prevent serving index.html automatically
|
|
294
|
+
// We handle index.html separately with rewritten asset paths
|
|
295
|
+
app.use(mountPath, express.static(effectiveUiPath, { index: false }));
|
|
176
296
|
|
|
177
297
|
// SPA fallback - serve index.html for all non-API routes under the mount path
|
|
178
|
-
|
|
298
|
+
const spaFallbackPath = mountPath === '/' ? '/*' : `${mountPath}/*`;
|
|
299
|
+
app.get(spaFallbackPath, (req: Request, res: Response, next) => {
|
|
179
300
|
// Skip API routes
|
|
180
301
|
if (req.path.startsWith(apiBasePath)) {
|
|
181
302
|
return next();
|
|
182
303
|
}
|
|
183
|
-
res.
|
|
304
|
+
res.type('html').send(getIndexHtml(req));
|
|
184
305
|
});
|
|
185
306
|
|
|
186
307
|
// Also serve the mount path root
|
|
187
308
|
if (mountPath !== '/') {
|
|
188
|
-
app.get(mountPath, (
|
|
189
|
-
res.
|
|
309
|
+
app.get(mountPath, (req: Request, res: Response) => {
|
|
310
|
+
res.type('html').send(getIndexHtml(req));
|
|
190
311
|
});
|
|
191
312
|
}
|
|
192
313
|
} else {
|
|
@@ -199,47 +320,9 @@ export function createControlPanel(options: CreateControlPanelOptions): ControlP
|
|
|
199
320
|
}
|
|
200
321
|
}
|
|
201
322
|
|
|
202
|
-
//
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
app,
|
|
206
|
-
router,
|
|
207
|
-
logger: getControlPanelLogger(pluginName),
|
|
208
|
-
registerHealthCheck: (check: HealthCheck) => healthManager.register(check),
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
// Register plugin
|
|
212
|
-
const registerPlugin = async (plugin: ControlPanelPlugin): Promise<void> => {
|
|
213
|
-
logger.debug(`Registering plugin: ${plugin.name}`);
|
|
214
|
-
|
|
215
|
-
// Register routes
|
|
216
|
-
if (plugin.routes) {
|
|
217
|
-
for (const route of plugin.routes) {
|
|
218
|
-
switch (route.method) {
|
|
219
|
-
case 'get':
|
|
220
|
-
router.get(route.path, route.handler);
|
|
221
|
-
break;
|
|
222
|
-
case 'post':
|
|
223
|
-
router.post(route.path, route.handler);
|
|
224
|
-
break;
|
|
225
|
-
case 'put':
|
|
226
|
-
router.put(route.path, route.handler);
|
|
227
|
-
break;
|
|
228
|
-
case 'delete':
|
|
229
|
-
router.delete(route.path, route.handler);
|
|
230
|
-
break;
|
|
231
|
-
}
|
|
232
|
-
logger.debug(`Registered route: ${route.method.toUpperCase()} ${route.path}`);
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
// Initialize plugin with plugin-specific logger
|
|
237
|
-
if (plugin.onInit) {
|
|
238
|
-
await plugin.onInit(createPluginContext(plugin.name));
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
registeredPlugins.push(plugin);
|
|
242
|
-
logger.debug(`Plugin registered: ${plugin.name}`);
|
|
323
|
+
// Start a plugin with the registry
|
|
324
|
+
const startPlugin = async (plugin: Plugin, pluginConfig: PluginConfig = {}): Promise<boolean> => {
|
|
325
|
+
return pluginRegistry.startPlugin(plugin, pluginConfig);
|
|
243
326
|
};
|
|
244
327
|
|
|
245
328
|
// Get diagnostics report
|
|
@@ -250,6 +333,7 @@ export function createControlPanel(options: CreateControlPanelOptions): ControlP
|
|
|
250
333
|
timestamp: new Date().toISOString(),
|
|
251
334
|
product: config.productName,
|
|
252
335
|
version: config.version,
|
|
336
|
+
frameworkVersion,
|
|
253
337
|
uptime: Date.now() - startTime,
|
|
254
338
|
health: healthManager.getResults(),
|
|
255
339
|
system: {
|
|
@@ -270,9 +354,12 @@ export function createControlPanel(options: CreateControlPanelOptions): ControlP
|
|
|
270
354
|
|
|
271
355
|
// Start server
|
|
272
356
|
const start = async (): Promise<void> => {
|
|
273
|
-
//
|
|
274
|
-
for (const plugin of plugins) {
|
|
275
|
-
await
|
|
357
|
+
// Start initial plugins via registry
|
|
358
|
+
for (const { plugin, config: pluginConfig } of plugins) {
|
|
359
|
+
const success = await pluginRegistry.startPlugin(plugin, pluginConfig || {});
|
|
360
|
+
if (!success) {
|
|
361
|
+
logger.error(`Failed to start plugin: ${plugin.id}`);
|
|
362
|
+
}
|
|
276
363
|
}
|
|
277
364
|
|
|
278
365
|
return new Promise((resolve) => {
|
|
@@ -285,12 +372,8 @@ export function createControlPanel(options: CreateControlPanelOptions): ControlP
|
|
|
285
372
|
|
|
286
373
|
// Stop server
|
|
287
374
|
const stop = async (): Promise<void> => {
|
|
288
|
-
//
|
|
289
|
-
|
|
290
|
-
if (plugin.onShutdown) {
|
|
291
|
-
await plugin.onShutdown();
|
|
292
|
-
}
|
|
293
|
-
}
|
|
375
|
+
// Stop all plugins via registry
|
|
376
|
+
await pluginRegistry.stopAllPlugins();
|
|
294
377
|
|
|
295
378
|
// Shutdown health manager
|
|
296
379
|
healthManager.shutdown();
|
|
@@ -310,9 +393,10 @@ export function createControlPanel(options: CreateControlPanelOptions): ControlP
|
|
|
310
393
|
app,
|
|
311
394
|
start,
|
|
312
395
|
stop,
|
|
313
|
-
|
|
396
|
+
startPlugin,
|
|
314
397
|
getHealthStatus: () => healthManager.getResults(),
|
|
315
398
|
getDiagnostics,
|
|
399
|
+
getPluginRegistry: () => pluginRegistry,
|
|
316
400
|
};
|
|
317
401
|
}
|
|
318
402
|
|