@qwickapps/server 1.7.0 → 1.7.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 +66 -0
- package/README.md +13 -116
- package/dist/src/core/control-panel.d.ts.map +1 -1
- package/dist/src/core/control-panel.js +6 -4
- 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 +24 -2
- package/dist/src/core/gateway.js.map +1 -1
- package/dist/src/core/plugin-registry.d.ts +15 -2
- package/dist/src/core/plugin-registry.d.ts.map +1 -1
- package/dist/src/core/plugin-registry.js.map +1 -1
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +9 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/plugins/api-keys/api-keys-plugin.d.ts +5 -2
- package/dist/src/plugins/api-keys/api-keys-plugin.d.ts.map +1 -1
- package/dist/src/plugins/api-keys/api-keys-plugin.js +61 -19
- package/dist/src/plugins/api-keys/api-keys-plugin.js.map +1 -1
- package/dist/src/plugins/api-keys/index.d.ts +0 -4
- package/dist/src/plugins/api-keys/index.d.ts.map +1 -1
- package/dist/src/plugins/api-keys/index.js +2 -3
- package/dist/src/plugins/api-keys/index.js.map +1 -1
- package/dist/src/plugins/api-keys/stores/postgres-store.d.ts.map +1 -1
- package/dist/src/plugins/api-keys/stores/postgres-store.js +29 -0
- package/dist/src/plugins/api-keys/stores/postgres-store.js.map +1 -1
- package/dist/src/plugins/api-keys/types.d.ts +9 -3
- package/dist/src/plugins/api-keys/types.d.ts.map +1 -1
- package/dist/src/plugins/api-keys/types.js.map +1 -1
- package/dist/src/plugins/auth/auth-plugin.d.ts.map +1 -1
- package/dist/src/plugins/auth/auth-plugin.js +4 -2
- package/dist/src/plugins/auth/auth-plugin.js.map +1 -1
- package/dist/src/plugins/auth/env-config.d.ts.map +1 -1
- package/dist/src/plugins/auth/env-config.js +1 -0
- package/dist/src/plugins/auth/env-config.js.map +1 -1
- package/dist/src/plugins/auth/index.d.ts +0 -4
- package/dist/src/plugins/auth/index.d.ts.map +1 -1
- package/dist/src/plugins/auth/index.js +2 -3
- package/dist/src/plugins/auth/index.js.map +1 -1
- package/dist/src/plugins/bans/bans-plugin.d.ts +5 -2
- package/dist/src/plugins/bans/bans-plugin.d.ts.map +1 -1
- package/dist/src/plugins/bans/bans-plugin.js +71 -25
- package/dist/src/plugins/bans/bans-plugin.js.map +1 -1
- package/dist/src/plugins/bans/index.d.ts +1 -5
- package/dist/src/plugins/bans/index.d.ts.map +1 -1
- package/dist/src/plugins/bans/index.js +3 -4
- package/dist/src/plugins/bans/index.js.map +1 -1
- package/dist/src/plugins/bans/stores/in-memory-store.d.ts +34 -0
- package/dist/src/plugins/bans/stores/in-memory-store.d.ts.map +1 -0
- package/dist/src/plugins/bans/stores/in-memory-store.js +97 -0
- package/dist/src/plugins/bans/stores/in-memory-store.js.map +1 -0
- package/dist/src/plugins/bans/stores/index.d.ts +1 -0
- package/dist/src/plugins/bans/stores/index.d.ts.map +1 -1
- package/dist/src/plugins/bans/stores/index.js +1 -0
- package/dist/src/plugins/bans/stores/index.js.map +1 -1
- package/dist/src/plugins/bans/types.d.ts +13 -6
- package/dist/src/plugins/bans/types.d.ts.map +1 -1
- package/dist/src/plugins/cache-plugin.d.ts +35 -16
- package/dist/src/plugins/cache-plugin.d.ts.map +1 -1
- package/dist/src/plugins/cache-plugin.js +299 -20
- package/dist/src/plugins/cache-plugin.js.map +1 -1
- package/dist/src/plugins/cms/cms-plugin.d.ts.map +1 -1
- package/dist/src/plugins/cms/cms-plugin.js +3 -1
- package/dist/src/plugins/cms/cms-plugin.js.map +1 -1
- package/dist/src/plugins/devices/devices-plugin.d.ts +5 -2
- package/dist/src/plugins/devices/devices-plugin.d.ts.map +1 -1
- package/dist/src/plugins/devices/devices-plugin.js +62 -26
- package/dist/src/plugins/devices/devices-plugin.js.map +1 -1
- package/dist/src/plugins/devices/index.d.ts +0 -4
- package/dist/src/plugins/devices/index.d.ts.map +1 -1
- package/dist/src/plugins/devices/index.js +2 -3
- package/dist/src/plugins/devices/index.js.map +1 -1
- package/dist/src/plugins/entitlements/entitlements-plugin.d.ts +5 -2
- package/dist/src/plugins/entitlements/entitlements-plugin.d.ts.map +1 -1
- package/dist/src/plugins/entitlements/entitlements-plugin.js +78 -41
- package/dist/src/plugins/entitlements/entitlements-plugin.js.map +1 -1
- package/dist/src/plugins/entitlements/index.d.ts +1 -5
- package/dist/src/plugins/entitlements/index.d.ts.map +1 -1
- package/dist/src/plugins/entitlements/index.js +3 -4
- package/dist/src/plugins/entitlements/index.js.map +1 -1
- package/dist/src/plugins/entitlements/sources/in-memory-source.d.ts +9 -0
- package/dist/src/plugins/entitlements/sources/in-memory-source.d.ts.map +1 -0
- package/dist/src/plugins/entitlements/sources/in-memory-source.js +65 -0
- package/dist/src/plugins/entitlements/sources/in-memory-source.js.map +1 -0
- package/dist/src/plugins/entitlements/sources/index.d.ts +1 -0
- package/dist/src/plugins/entitlements/sources/index.d.ts.map +1 -1
- package/dist/src/plugins/entitlements/sources/index.js +1 -0
- package/dist/src/plugins/entitlements/sources/index.js.map +1 -1
- package/dist/src/plugins/entitlements/types.d.ts +9 -2
- package/dist/src/plugins/entitlements/types.d.ts.map +1 -1
- package/dist/src/plugins/health-plugin.d.ts.map +1 -1
- package/dist/src/plugins/health-plugin.js +1 -0
- package/dist/src/plugins/health-plugin.js.map +1 -1
- package/dist/src/plugins/index.d.ts +4 -4
- package/dist/src/plugins/index.d.ts.map +1 -1
- package/dist/src/plugins/index.js +4 -4
- package/dist/src/plugins/index.js.map +1 -1
- package/dist/src/plugins/logs-plugin.d.ts.map +1 -1
- package/dist/src/plugins/logs-plugin.js +49 -1
- package/dist/src/plugins/logs-plugin.js.map +1 -1
- package/dist/src/plugins/maintenance-plugin.d.ts.map +1 -1
- package/dist/src/plugins/maintenance-plugin.js +39 -0
- package/dist/src/plugins/maintenance-plugin.js.map +1 -1
- package/dist/src/plugins/notifications/index.d.ts +0 -4
- package/dist/src/plugins/notifications/index.d.ts.map +1 -1
- package/dist/src/plugins/notifications/index.js +2 -3
- package/dist/src/plugins/notifications/index.js.map +1 -1
- package/dist/src/plugins/notifications/notifications-plugin.d.ts +5 -2
- package/dist/src/plugins/notifications/notifications-plugin.d.ts.map +1 -1
- package/dist/src/plugins/notifications/notifications-plugin.js +46 -13
- package/dist/src/plugins/notifications/notifications-plugin.js.map +1 -1
- package/dist/src/plugins/parental/index.d.ts +0 -4
- package/dist/src/plugins/parental/index.d.ts.map +1 -1
- package/dist/src/plugins/parental/index.js +2 -3
- package/dist/src/plugins/parental/index.js.map +1 -1
- package/dist/src/plugins/parental/parental-plugin.d.ts +5 -2
- package/dist/src/plugins/parental/parental-plugin.d.ts.map +1 -1
- package/dist/src/plugins/parental/parental-plugin.js +60 -24
- package/dist/src/plugins/parental/parental-plugin.js.map +1 -1
- package/dist/src/plugins/postgres-plugin.d.ts +3 -1
- package/dist/src/plugins/postgres-plugin.d.ts.map +1 -1
- package/dist/src/plugins/postgres-plugin.js +18 -8
- package/dist/src/plugins/postgres-plugin.js.map +1 -1
- package/dist/src/plugins/preferences/index.d.ts +0 -4
- package/dist/src/plugins/preferences/index.d.ts.map +1 -1
- package/dist/src/plugins/preferences/index.js +2 -3
- package/dist/src/plugins/preferences/index.js.map +1 -1
- package/dist/src/plugins/preferences/preferences-plugin.d.ts +5 -2
- package/dist/src/plugins/preferences/preferences-plugin.d.ts.map +1 -1
- package/dist/src/plugins/preferences/preferences-plugin.js +63 -19
- package/dist/src/plugins/preferences/preferences-plugin.js.map +1 -1
- package/dist/src/plugins/profiles/index.d.ts +0 -4
- package/dist/src/plugins/profiles/index.d.ts.map +1 -1
- package/dist/src/plugins/profiles/index.js +2 -3
- package/dist/src/plugins/profiles/index.js.map +1 -1
- package/dist/src/plugins/profiles/profiles-plugin.d.ts +5 -2
- package/dist/src/plugins/profiles/profiles-plugin.d.ts.map +1 -1
- package/dist/src/plugins/profiles/profiles-plugin.js +60 -26
- package/dist/src/plugins/profiles/profiles-plugin.js.map +1 -1
- package/dist/src/plugins/profiles/types.d.ts +9 -2
- package/dist/src/plugins/profiles/types.d.ts.map +1 -1
- package/dist/src/plugins/qwickbrain/index.d.ts +0 -4
- package/dist/src/plugins/qwickbrain/index.d.ts.map +1 -1
- package/dist/src/plugins/qwickbrain/index.js +2 -3
- package/dist/src/plugins/qwickbrain/index.js.map +1 -1
- package/dist/src/plugins/qwickbrain/qwickbrain-plugin.d.ts.map +1 -1
- package/dist/src/plugins/qwickbrain/qwickbrain-plugin.js +117 -0
- package/dist/src/plugins/qwickbrain/qwickbrain-plugin.js.map +1 -1
- package/dist/src/plugins/rate-limit/index.d.ts +0 -4
- package/dist/src/plugins/rate-limit/index.d.ts.map +1 -1
- package/dist/src/plugins/rate-limit/index.js +2 -3
- package/dist/src/plugins/rate-limit/index.js.map +1 -1
- package/dist/src/plugins/subscriptions/index.d.ts +0 -4
- package/dist/src/plugins/subscriptions/index.d.ts.map +1 -1
- package/dist/src/plugins/subscriptions/index.js +2 -3
- package/dist/src/plugins/subscriptions/index.js.map +1 -1
- package/dist/src/plugins/subscriptions/subscriptions-plugin.d.ts +5 -2
- package/dist/src/plugins/subscriptions/subscriptions-plugin.d.ts.map +1 -1
- package/dist/src/plugins/subscriptions/subscriptions-plugin.js +63 -29
- package/dist/src/plugins/subscriptions/subscriptions-plugin.js.map +1 -1
- package/dist/src/plugins/subscriptions/types.d.ts +8 -2
- package/dist/src/plugins/subscriptions/types.d.ts.map +1 -1
- package/dist/src/plugins/tenants/index.d.ts +1 -1
- package/dist/src/plugins/tenants/index.d.ts.map +1 -1
- package/dist/src/plugins/tenants/index.js +1 -1
- package/dist/src/plugins/tenants/index.js.map +1 -1
- package/dist/src/plugins/tenants/stores/in-memory-store.d.ts +59 -0
- package/dist/src/plugins/tenants/stores/in-memory-store.d.ts.map +1 -0
- package/dist/src/plugins/tenants/stores/in-memory-store.js +257 -0
- package/dist/src/plugins/tenants/stores/in-memory-store.js.map +1 -0
- package/dist/src/plugins/tenants/stores/index.d.ts +8 -0
- package/dist/src/plugins/tenants/stores/index.d.ts.map +1 -0
- package/dist/src/plugins/tenants/stores/index.js +8 -0
- package/dist/src/plugins/tenants/stores/index.js.map +1 -0
- package/dist/src/plugins/tenants/tenants-plugin.d.ts +5 -2
- package/dist/src/plugins/tenants/tenants-plugin.d.ts.map +1 -1
- package/dist/src/plugins/tenants/tenants-plugin.js +93 -60
- package/dist/src/plugins/tenants/tenants-plugin.js.map +1 -1
- package/dist/src/plugins/tenants/types.d.ts +8 -2
- package/dist/src/plugins/tenants/types.d.ts.map +1 -1
- package/dist/src/plugins/usage/index.d.ts +0 -4
- package/dist/src/plugins/usage/index.d.ts.map +1 -1
- package/dist/src/plugins/usage/index.js +2 -3
- package/dist/src/plugins/usage/index.js.map +1 -1
- package/dist/src/plugins/usage/usage-plugin.d.ts +5 -2
- package/dist/src/plugins/usage/usage-plugin.d.ts.map +1 -1
- package/dist/src/plugins/usage/usage-plugin.js +57 -23
- package/dist/src/plugins/usage/usage-plugin.js.map +1 -1
- package/dist/src/plugins/users/index.d.ts +1 -1
- package/dist/src/plugins/users/index.d.ts.map +1 -1
- package/dist/src/plugins/users/index.js +1 -1
- package/dist/src/plugins/users/index.js.map +1 -1
- package/dist/src/plugins/users/stores/in-memory-store.d.ts +36 -0
- package/dist/src/plugins/users/stores/in-memory-store.d.ts.map +1 -0
- package/dist/src/plugins/users/stores/in-memory-store.js +122 -0
- package/dist/src/plugins/users/stores/in-memory-store.js.map +1 -0
- package/dist/src/plugins/users/stores/index.d.ts +1 -0
- package/dist/src/plugins/users/stores/index.d.ts.map +1 -1
- package/dist/src/plugins/users/stores/index.js +1 -0
- package/dist/src/plugins/users/stores/index.js.map +1 -1
- package/dist/src/plugins/users/types.d.ts +7 -2
- package/dist/src/plugins/users/types.d.ts.map +1 -1
- package/dist/src/plugins/users/users-plugin.d.ts +5 -2
- package/dist/src/plugins/users/users-plugin.d.ts.map +1 -1
- package/dist/src/plugins/users/users-plugin.js +56 -23
- package/dist/src/plugins/users/users-plugin.js.map +1 -1
- package/dist/ui/src/api/controlPanelApi.d.ts +10 -1
- package/dist/ui/src/api/controlPanelApi.d.ts.map +1 -1
- package/dist/ui/src/api/controlPanelApi.js.map +1 -1
- package/dist/ui/src/dashboard/PluginWidgetRenderer.d.ts +3 -1
- package/dist/ui/src/dashboard/PluginWidgetRenderer.d.ts.map +1 -1
- package/dist/ui/src/dashboard/PluginWidgetRenderer.js +5 -1
- package/dist/ui/src/dashboard/PluginWidgetRenderer.js.map +1 -1
- package/dist/ui/src/dashboard/builtInWidgets.d.ts.map +1 -1
- package/dist/ui/src/dashboard/builtInWidgets.js +13 -1
- package/dist/ui/src/dashboard/builtInWidgets.js.map +1 -1
- package/dist/ui/src/dashboard/widgets/CacheMaintenanceWidget.d.ts +11 -0
- package/dist/ui/src/dashboard/widgets/CacheMaintenanceWidget.d.ts.map +1 -0
- package/dist/ui/src/dashboard/widgets/CacheMaintenanceWidget.js +77 -0
- package/dist/ui/src/dashboard/widgets/CacheMaintenanceWidget.js.map +1 -0
- package/dist/ui/src/dashboard/widgets/DatabaseOpsWidget.d.ts +10 -0
- package/dist/ui/src/dashboard/widgets/DatabaseOpsWidget.d.ts.map +1 -0
- package/dist/ui/src/dashboard/widgets/DatabaseOpsWidget.js +14 -0
- package/dist/ui/src/dashboard/widgets/DatabaseOpsWidget.js.map +1 -0
- package/dist/ui/src/dashboard/widgets/EnvironmentConfigWidget.d.ts +10 -0
- package/dist/ui/src/dashboard/widgets/EnvironmentConfigWidget.d.ts.map +1 -0
- package/dist/ui/src/dashboard/widgets/EnvironmentConfigWidget.js +14 -0
- package/dist/ui/src/dashboard/widgets/EnvironmentConfigWidget.js.map +1 -0
- package/dist/ui/src/dashboard/widgets/LogsMaintenanceWidget.d.ts +11 -0
- package/dist/ui/src/dashboard/widgets/LogsMaintenanceWidget.d.ts.map +1 -0
- package/dist/ui/src/dashboard/widgets/LogsMaintenanceWidget.js +96 -0
- package/dist/ui/src/dashboard/widgets/LogsMaintenanceWidget.js.map +1 -0
- package/dist/ui/src/dashboard/widgets/SeedManagementWidget.d.ts +10 -0
- package/dist/ui/src/dashboard/widgets/SeedManagementWidget.d.ts.map +1 -0
- package/dist/ui/src/dashboard/widgets/SeedManagementWidget.js +55 -0
- package/dist/ui/src/dashboard/widgets/SeedManagementWidget.js.map +1 -0
- package/dist/ui/src/dashboard/widgets/ServiceControlWidget.d.ts +10 -0
- package/dist/ui/src/dashboard/widgets/ServiceControlWidget.d.ts.map +1 -0
- package/dist/ui/src/dashboard/widgets/ServiceControlWidget.js +14 -0
- package/dist/ui/src/dashboard/widgets/ServiceControlWidget.js.map +1 -0
- package/dist/ui/src/dashboard/widgets/index.d.ts +6 -0
- package/dist/ui/src/dashboard/widgets/index.d.ts.map +1 -1
- package/dist/ui/src/dashboard/widgets/index.js +6 -0
- package/dist/ui/src/dashboard/widgets/index.js.map +1 -1
- package/dist/ui/src/pages/DashboardPage.js +1 -1
- package/dist/ui/src/pages/DashboardPage.js.map +1 -1
- package/dist-ui/assets/index-0gzisPdy.js +528 -0
- package/dist-ui/assets/{index-lm1yX6UD.js.map → index-0gzisPdy.js.map} +1 -1
- package/dist-ui/index.html +1 -1
- package/dist-ui-lib/index.js +3109 -2774
- package/dist-ui-lib/index.js.map +1 -1
- package/dist-ui-lib/src/api/controlPanelApi.d.ts +10 -1
- package/dist-ui-lib/src/dashboard/PluginWidgetRenderer.d.ts +3 -1
- package/dist-ui-lib/src/dashboard/widgets/CacheMaintenanceWidget.d.ts +10 -0
- package/dist-ui-lib/src/dashboard/widgets/DatabaseOpsWidget.d.ts +9 -0
- package/dist-ui-lib/src/dashboard/widgets/EnvironmentConfigWidget.d.ts +9 -0
- package/dist-ui-lib/src/dashboard/widgets/LogsMaintenanceWidget.d.ts +10 -0
- package/dist-ui-lib/src/dashboard/widgets/SeedManagementWidget.d.ts +9 -0
- package/dist-ui-lib/src/dashboard/widgets/ServiceControlWidget.d.ts +9 -0
- package/dist-ui-lib/src/dashboard/widgets/index.d.ts +6 -0
- package/package.json +12 -6
- package/src/core/control-panel.ts +6 -4
- package/src/core/gateway.ts +25 -2
- package/src/core/plugin-registry.ts +15 -2
- package/src/index.ts +53 -0
- package/src/plugins/api-keys/api-keys-plugin.ts +64 -20
- package/src/plugins/api-keys/index.ts +2 -5
- package/src/plugins/api-keys/stores/postgres-store.ts +30 -0
- package/src/plugins/api-keys/types.ts +9 -3
- package/src/plugins/auth/auth-plugin.ts +4 -2
- package/src/plugins/auth/env-config.ts +1 -0
- package/src/plugins/auth/index.ts +3 -5
- package/src/plugins/bans/bans-plugin.ts +71 -26
- package/src/plugins/bans/index.ts +4 -6
- package/src/plugins/bans/stores/in-memory-store.ts +106 -0
- package/src/plugins/bans/stores/index.ts +1 -0
- package/src/plugins/bans/types.ts +13 -6
- package/src/plugins/cache-plugin.test.ts +2 -2
- package/src/plugins/cache-plugin.ts +331 -30
- package/src/plugins/cms/cms-plugin.ts +3 -1
- package/src/plugins/devices/devices-plugin.ts +62 -27
- package/src/plugins/devices/index.ts +3 -5
- package/src/plugins/entitlements/entitlements-plugin.ts +81 -43
- package/src/plugins/entitlements/index.ts +4 -6
- package/src/plugins/entitlements/sources/in-memory-source.ts +76 -0
- package/src/plugins/entitlements/sources/index.ts +1 -0
- package/src/plugins/entitlements/types.ts +9 -2
- package/src/plugins/health-plugin.ts +1 -0
- package/src/plugins/index.ts +4 -1
- package/src/plugins/logs-plugin.ts +55 -1
- package/src/plugins/maintenance-plugin.ts +43 -0
- package/src/plugins/notifications/index.ts +3 -5
- package/src/plugins/notifications/notifications-plugin.ts +49 -19
- package/src/plugins/parental/index.ts +3 -5
- package/src/plugins/parental/parental-plugin.ts +63 -25
- package/src/plugins/postgres-plugin.test.ts +2 -2
- package/src/plugins/postgres-plugin.ts +20 -9
- package/src/plugins/preferences/index.ts +3 -5
- package/src/plugins/preferences/preferences-plugin.ts +66 -20
- package/src/plugins/profiles/index.ts +3 -5
- package/src/plugins/profiles/profiles-plugin.ts +60 -27
- package/src/plugins/profiles/types.ts +9 -2
- package/src/plugins/qwickbrain/index.ts +3 -5
- package/src/plugins/qwickbrain/qwickbrain-plugin.ts +135 -0
- package/src/plugins/rate-limit/index.ts +3 -5
- package/src/plugins/subscriptions/index.ts +3 -5
- package/src/plugins/subscriptions/subscriptions-plugin.ts +63 -30
- package/src/plugins/subscriptions/types.ts +8 -2
- package/src/plugins/tenants/index.ts +1 -1
- package/src/plugins/tenants/stores/in-memory-store.ts +335 -0
- package/src/plugins/tenants/stores/index.ts +13 -0
- package/src/plugins/tenants/tenants-plugin.ts +97 -62
- package/src/plugins/tenants/types.ts +8 -2
- package/src/plugins/usage/index.ts +3 -5
- package/src/plugins/usage/usage-plugin.ts +60 -26
- package/src/plugins/users/index.ts +1 -1
- package/src/plugins/users/stores/in-memory-store.ts +140 -0
- package/src/plugins/users/stores/index.ts +1 -0
- package/src/plugins/users/types.ts +7 -2
- package/src/plugins/users/users-plugin.ts +56 -24
- package/src/testing/index.ts +1 -0
- package/src/testing/pg-mem-pool.ts +33 -0
- package/ui/src/api/controlPanelApi.ts +10 -1
- package/ui/src/dashboard/PluginWidgetRenderer.tsx +8 -0
- package/ui/src/dashboard/builtInWidgets.tsx +19 -1
- package/ui/src/dashboard/widgets/CacheMaintenanceWidget.tsx +195 -0
- package/ui/src/dashboard/widgets/DatabaseOpsWidget.tsx +29 -0
- package/ui/src/dashboard/widgets/EnvironmentConfigWidget.tsx +29 -0
- package/ui/src/dashboard/widgets/LogsMaintenanceWidget.tsx +247 -0
- package/ui/src/dashboard/widgets/SeedManagementWidget.tsx +128 -0
- package/ui/src/dashboard/widgets/ServiceControlWidget.tsx +29 -0
- package/ui/src/dashboard/widgets/index.ts +6 -0
- package/ui/src/pages/DashboardPage.tsx +2 -2
- package/ui/src/pages/MaintenancePage.tsx +1 -1
- package/dist-ui/assets/index-lm1yX6UD.js +0 -528
|
@@ -68,8 +68,6 @@ export {
|
|
|
68
68
|
} from './token-utils.js';
|
|
69
69
|
export type { DeviceTokenPair } from './token-utils.js';
|
|
70
70
|
|
|
71
|
-
// UI Components
|
|
72
|
-
export
|
|
73
|
-
|
|
74
|
-
export { DevicesManagementPage } from './DevicesManagementPage.js';
|
|
75
|
-
export type { DevicesManagementPageProps } from './DevicesManagementPage.js';
|
|
71
|
+
// UI Components are exported from main package index (@qwickapps/server)
|
|
72
|
+
// Do NOT export here to avoid loading UI dependencies when importing plugins
|
|
73
|
+
|
|
@@ -21,7 +21,9 @@ import type {
|
|
|
21
21
|
EntitlementStats,
|
|
22
22
|
} from './types.js';
|
|
23
23
|
import type { AuthenticatedRequest } from '../auth/types.js';
|
|
24
|
-
import { getCache, type CacheInstance } from '../cache-plugin.js';
|
|
24
|
+
import { getCache, hasCache, type CacheInstance } from '../cache-plugin.js';
|
|
25
|
+
import { hasPostgres, getPostgres } from '../postgres-plugin.js';
|
|
26
|
+
import { postgresEntitlementSource } from './sources/index.js';
|
|
25
27
|
|
|
26
28
|
// Plugin state
|
|
27
29
|
let primarySource: EntitlementSource | null = null;
|
|
@@ -35,67 +37,103 @@ let cacheEnabled = true;
|
|
|
35
37
|
let cacheVersion = 1;
|
|
36
38
|
|
|
37
39
|
/**
|
|
38
|
-
* Create the Entitlements plugin
|
|
40
|
+
* Create the Entitlements plugin with smart defaults
|
|
41
|
+
*
|
|
42
|
+
* Config is optional - plugin will use defaults and get dependencies from registry.
|
|
43
|
+
* Gracefully handles missing dependencies with clear log messages.
|
|
39
44
|
*/
|
|
40
|
-
export function createEntitlementsPlugin(config: EntitlementsPluginConfig): Plugin {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
function log(message: string, data?: Record<string, unknown>) {
|
|
48
|
-
if (debug) {
|
|
49
|
-
console.log(`[EntitlementsPlugin] ${message}`, data || '');
|
|
45
|
+
export function createEntitlementsPlugin(config: Partial<EntitlementsPluginConfig> = {}): Plugin {
|
|
46
|
+
function log(message: string, data?: Record<string, unknown>, isError = false) {
|
|
47
|
+
const prefix = '[EntitlementsPlugin]';
|
|
48
|
+
if (isError) {
|
|
49
|
+
console.error(`${prefix} ${message}`, data || '');
|
|
50
|
+
} else if (config.debug) {
|
|
51
|
+
console.log(`${prefix} ${message}`, data || '');
|
|
50
52
|
}
|
|
51
53
|
}
|
|
52
54
|
|
|
53
|
-
// Cache key helpers
|
|
54
|
-
const keys = {
|
|
55
|
-
entitlements: (email: string) => `${cacheKeyPrefix}user:${email.toLowerCase()}`,
|
|
56
|
-
mapping: (source: string, id: string) => `${cacheKeyPrefix}mapping:${source}:${id}`,
|
|
57
|
-
};
|
|
58
|
-
|
|
59
55
|
return {
|
|
60
56
|
id: 'entitlements',
|
|
61
57
|
name: 'Entitlements',
|
|
62
58
|
version: '1.0.0',
|
|
63
59
|
|
|
64
60
|
async onStart(_pluginConfig: PluginConfig, registry: PluginRegistry): Promise<void> {
|
|
61
|
+
const logger = registry.getLogger('entitlements');
|
|
62
|
+
|
|
63
|
+
// Check for postgres in registry (needed for default source)
|
|
64
|
+
if (!hasPostgres()) {
|
|
65
|
+
logger.warn('No Database! Entitlements plugin disabled.');
|
|
66
|
+
registry.registerHealthCheck({
|
|
67
|
+
name: 'entitlements-source',
|
|
68
|
+
type: 'custom',
|
|
69
|
+
check: async () => ({
|
|
70
|
+
healthy: false,
|
|
71
|
+
details: {
|
|
72
|
+
error: 'PostgreSQL not available',
|
|
73
|
+
state: 'disabled',
|
|
74
|
+
},
|
|
75
|
+
}),
|
|
76
|
+
});
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Smart defaults - get dependencies from registry
|
|
81
|
+
const source = config.source ?? postgresEntitlementSource({
|
|
82
|
+
pool: () => getPostgres().getPool(),
|
|
83
|
+
autoCreateTables: true,
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
const debug = config.debug ?? false;
|
|
87
|
+
const apiPrefix = config.api?.prefix ?? '/entitlements';
|
|
88
|
+
const apiEnabled = config.api?.enabled ?? true;
|
|
89
|
+
const enableWriteApi = config.api?.enableWrite ?? true;
|
|
90
|
+
|
|
65
91
|
log('Starting entitlements plugin');
|
|
66
92
|
|
|
67
93
|
// Initialize primary source
|
|
68
|
-
await
|
|
69
|
-
primarySource =
|
|
70
|
-
log('Primary source initialized', { source:
|
|
94
|
+
await source.initialize();
|
|
95
|
+
primarySource = source;
|
|
96
|
+
log('Primary source initialized', { source: source.name });
|
|
71
97
|
|
|
72
98
|
// Initialize additional sources
|
|
73
99
|
additionalSources = config.additionalSources || [];
|
|
74
|
-
for (const
|
|
75
|
-
await
|
|
76
|
-
log('Additional source initialized', { source:
|
|
100
|
+
for (const additionalSource of additionalSources) {
|
|
101
|
+
await additionalSource.initialize();
|
|
102
|
+
log('Additional source initialized', { source: additionalSource.name });
|
|
77
103
|
}
|
|
78
104
|
|
|
79
105
|
// Store config
|
|
80
|
-
pluginConfig = config;
|
|
106
|
+
pluginConfig = { ...config, source, debug };
|
|
81
107
|
|
|
82
|
-
// Setup caching if enabled
|
|
108
|
+
// Setup caching if enabled and available
|
|
83
109
|
cacheEnabled = config.cache?.enabled !== false;
|
|
84
110
|
if (cacheEnabled) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
111
|
+
if (hasCache()) {
|
|
112
|
+
try {
|
|
113
|
+
const instanceName = config.cache?.instanceName || 'default';
|
|
114
|
+
cacheInstance = getCache(instanceName);
|
|
115
|
+
cacheKeyPrefix = config.cache?.keyPrefix || 'entitlements:';
|
|
116
|
+
cacheTtl = config.cache?.ttl || 300;
|
|
117
|
+
cacheMappingTtl = config.cache?.mappingTtl || cacheTtl * 2;
|
|
118
|
+
log('Cache configured', { instanceName, prefix: cacheKeyPrefix, ttl: cacheTtl });
|
|
119
|
+
} catch {
|
|
120
|
+
log('Cache instance not available, running without caching');
|
|
121
|
+
cacheEnabled = false;
|
|
122
|
+
cacheInstance = null;
|
|
123
|
+
}
|
|
124
|
+
} else {
|
|
125
|
+
log('Cache plugin not available, running without caching');
|
|
94
126
|
cacheEnabled = false;
|
|
95
127
|
cacheInstance = null;
|
|
96
128
|
}
|
|
97
129
|
}
|
|
98
130
|
|
|
131
|
+
// Cache key helpers
|
|
132
|
+
const keys = {
|
|
133
|
+
entitlements: (email: string) => `${cacheKeyPrefix}user:${email.toLowerCase()}`,
|
|
134
|
+
mapping: (sourceId: string, id: string) => `${cacheKeyPrefix}mapping:${sourceId}:${id}`,
|
|
135
|
+
};
|
|
136
|
+
|
|
99
137
|
// Register health check
|
|
100
138
|
registry.registerHealthCheck({
|
|
101
139
|
name: 'entitlements-source',
|
|
@@ -104,8 +142,8 @@ export function createEntitlementsPlugin(config: EntitlementsPluginConfig): Plug
|
|
|
104
142
|
try {
|
|
105
143
|
// Use source's isHealthy() method if available (avoids API calls)
|
|
106
144
|
// Otherwise just check that source is initialized
|
|
107
|
-
if (
|
|
108
|
-
const healthy = await
|
|
145
|
+
if (source.isHealthy) {
|
|
146
|
+
const healthy = await source.isHealthy();
|
|
109
147
|
return { healthy };
|
|
110
148
|
}
|
|
111
149
|
// Source is healthy if initialized (we got here means it started)
|
|
@@ -145,9 +183,9 @@ export function createEntitlementsPlugin(config: EntitlementsPluginConfig): Plug
|
|
|
145
183
|
try {
|
|
146
184
|
const sources = [
|
|
147
185
|
{
|
|
148
|
-
name:
|
|
149
|
-
description:
|
|
150
|
-
readonly:
|
|
186
|
+
name: source.name,
|
|
187
|
+
description: source.description,
|
|
188
|
+
readonly: source.readonly ?? false,
|
|
151
189
|
primary: true,
|
|
152
190
|
},
|
|
153
191
|
...additionalSources.map((s) => ({
|
|
@@ -159,8 +197,8 @@ export function createEntitlementsPlugin(config: EntitlementsPluginConfig): Plug
|
|
|
159
197
|
];
|
|
160
198
|
|
|
161
199
|
res.json({
|
|
162
|
-
readonly:
|
|
163
|
-
writeEnabled: enableWriteApi && !
|
|
200
|
+
readonly: source.readonly ?? false,
|
|
201
|
+
writeEnabled: enableWriteApi && !source.readonly,
|
|
164
202
|
cacheEnabled,
|
|
165
203
|
cacheTtl,
|
|
166
204
|
sources,
|
|
@@ -311,7 +349,7 @@ export function createEntitlementsPlugin(config: EntitlementsPluginConfig): Plug
|
|
|
311
349
|
});
|
|
312
350
|
|
|
313
351
|
// Write endpoints (grant/revoke) - only if enabled and source is writable
|
|
314
|
-
if (enableWriteApi && !
|
|
352
|
+
if (enableWriteApi && !source.readonly) {
|
|
315
353
|
// Grant entitlement
|
|
316
354
|
registry.addRoute({
|
|
317
355
|
method: 'post',
|
|
@@ -33,7 +33,7 @@ export {
|
|
|
33
33
|
} from './entitlements-plugin.js';
|
|
34
34
|
|
|
35
35
|
// Sources
|
|
36
|
-
export { postgresEntitlementSource } from './sources/index.js';
|
|
36
|
+
export { postgresEntitlementSource, inMemoryEntitlementSource } from './sources/index.js';
|
|
37
37
|
|
|
38
38
|
// Types
|
|
39
39
|
export type {
|
|
@@ -50,8 +50,6 @@ export type {
|
|
|
50
50
|
EntitlementStats,
|
|
51
51
|
} from './types.js';
|
|
52
52
|
|
|
53
|
-
// UI Components
|
|
54
|
-
export
|
|
55
|
-
|
|
56
|
-
export { EntitlementsManagementPage } from './EntitlementsManagementPage.js';
|
|
57
|
-
export type { EntitlementsManagementPageProps } from './EntitlementsManagementPage.js';
|
|
53
|
+
// UI Components are exported from main package index (@qwickapps/server)
|
|
54
|
+
// Do NOT export here to avoid loading UI dependencies when importing plugins
|
|
55
|
+
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory Entitlement Source for Demo/Testing
|
|
3
|
+
*
|
|
4
|
+
* Implements the EntitlementSource interface with in-memory storage.
|
|
5
|
+
* Pre-populated with demo data for testing and showcase purposes.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { EntitlementSource, EntitlementDefinition } from '../types.js';
|
|
9
|
+
|
|
10
|
+
export function createInMemoryEntitlementSource(): EntitlementSource {
|
|
11
|
+
const userEntitlements = new Map<string, string[]>();
|
|
12
|
+
const availableEntitlements: EntitlementDefinition[] = [
|
|
13
|
+
{ id: '1', name: 'premium', category: 'subscription', description: 'Premium subscription tier' },
|
|
14
|
+
{ id: '2', name: 'pro', category: 'subscription', description: 'Professional subscription tier' },
|
|
15
|
+
{ id: '3', name: 'enterprise', category: 'subscription', description: 'Enterprise subscription tier' },
|
|
16
|
+
{ id: '4', name: 'beta-access', category: 'features', description: 'Access to beta features' },
|
|
17
|
+
{ id: '5', name: 'api-access', category: 'features', description: 'API access enabled' },
|
|
18
|
+
{ id: '6', name: 'support-priority', category: 'support', description: 'Priority support access' },
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
// Pre-populate some demo data
|
|
22
|
+
userEntitlements.set('demo@example.com', ['premium', 'api-access']);
|
|
23
|
+
userEntitlements.set('pro@example.com', ['pro', 'beta-access', 'api-access']);
|
|
24
|
+
userEntitlements.set('enterprise@example.com', ['enterprise', 'beta-access', 'api-access', 'support-priority']);
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
name: 'in-memory',
|
|
28
|
+
description: 'In-memory entitlement source for demo/testing',
|
|
29
|
+
readonly: false,
|
|
30
|
+
|
|
31
|
+
async initialize() {
|
|
32
|
+
console.log('[InMemorySource] Initialized with demo data');
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
async getEntitlements(identifier: string): Promise<string[]> {
|
|
36
|
+
return userEntitlements.get(identifier.toLowerCase()) || [];
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
async getAllAvailable(): Promise<EntitlementDefinition[]> {
|
|
40
|
+
return availableEntitlements;
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
async getUsersWithEntitlement(entitlement: string) {
|
|
44
|
+
const emails: string[] = [];
|
|
45
|
+
userEntitlements.forEach((ents, email) => {
|
|
46
|
+
if (ents.includes(entitlement)) {
|
|
47
|
+
emails.push(email);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
return { emails, total: emails.length };
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
async addEntitlement(identifier: string, entitlement: string) {
|
|
54
|
+
const email = identifier.toLowerCase();
|
|
55
|
+
const current = userEntitlements.get(email) || [];
|
|
56
|
+
if (!current.includes(entitlement)) {
|
|
57
|
+
current.push(entitlement);
|
|
58
|
+
userEntitlements.set(email, current);
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
async removeEntitlement(identifier: string, entitlement: string) {
|
|
63
|
+
const email = identifier.toLowerCase();
|
|
64
|
+
const current = userEntitlements.get(email) || [];
|
|
65
|
+
const index = current.indexOf(entitlement);
|
|
66
|
+
if (index > -1) {
|
|
67
|
+
current.splice(index, 1);
|
|
68
|
+
userEntitlements.set(email, current);
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
async shutdown() {
|
|
73
|
+
console.log('[InMemorySource] Shutdown');
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
@@ -200,10 +200,17 @@ export interface EntitlementsApiConfig {
|
|
|
200
200
|
|
|
201
201
|
/**
|
|
202
202
|
* Entitlements plugin configuration
|
|
203
|
+
*
|
|
204
|
+
* All properties are optional - plugin will use smart defaults:
|
|
205
|
+
* - source: Postgres entitlement source using registry's postgres instance
|
|
206
|
+
* - cache: Uses cache from registry if available
|
|
207
|
+
* - api.prefix: '/entitlements'
|
|
208
|
+
* - api.enabled: true
|
|
209
|
+
* - debug: false
|
|
203
210
|
*/
|
|
204
211
|
export interface EntitlementsPluginConfig {
|
|
205
|
-
/** Primary entitlement source */
|
|
206
|
-
source
|
|
212
|
+
/** Primary entitlement source (default: postgres source from registry) */
|
|
213
|
+
source?: EntitlementSource;
|
|
207
214
|
|
|
208
215
|
/** Additional sources to query (results are merged) */
|
|
209
216
|
additionalSources?: EntitlementSource[];
|
package/src/plugins/index.ts
CHANGED
|
@@ -93,6 +93,7 @@ export {
|
|
|
93
93
|
linkUserIdentifiers,
|
|
94
94
|
findOrCreateUser,
|
|
95
95
|
postgresUserStore,
|
|
96
|
+
inMemoryUserStore,
|
|
96
97
|
} from './users/index.js';
|
|
97
98
|
export type {
|
|
98
99
|
UsersPluginConfig,
|
|
@@ -111,7 +112,7 @@ export type {
|
|
|
111
112
|
} from './users/index.js';
|
|
112
113
|
|
|
113
114
|
// Tenants plugin (multi-tenant data isolation, depends on Users)
|
|
114
|
-
export { createTenantsPlugin, getTenantStore, postgresTenantStore } from './tenants/index.js';
|
|
115
|
+
export { createTenantsPlugin, getTenantStore, postgresTenantStore, inMemoryTenantStore } from './tenants/index.js';
|
|
115
116
|
export type {
|
|
116
117
|
TenantsPluginConfig,
|
|
117
118
|
TenantStore,
|
|
@@ -139,6 +140,7 @@ export {
|
|
|
139
140
|
unbanUser,
|
|
140
141
|
listActiveBans,
|
|
141
142
|
postgresBanStore,
|
|
143
|
+
inMemoryBanStore,
|
|
142
144
|
} from './bans/index.js';
|
|
143
145
|
export type {
|
|
144
146
|
BansPluginConfig,
|
|
@@ -198,6 +200,7 @@ export {
|
|
|
198
200
|
requireAnyEntitlement,
|
|
199
201
|
requireAllEntitlements,
|
|
200
202
|
postgresEntitlementSource,
|
|
203
|
+
inMemoryEntitlementSource,
|
|
201
204
|
} from './entitlements/index.js';
|
|
202
205
|
export type {
|
|
203
206
|
EntitlementsPluginConfig,
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* Copyright (c) 2025 QwickApps.com. All rights reserved.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { existsSync, readFileSync, statSync } from 'fs';
|
|
10
|
+
import { existsSync, readFileSync, statSync, truncateSync, unlinkSync } from 'fs';
|
|
11
11
|
import { resolve } from 'path';
|
|
12
12
|
import type { Request, Response } from 'express';
|
|
13
13
|
import type { Plugin, PluginConfig, PluginRegistry } from '../core/plugin-registry.js';
|
|
@@ -165,6 +165,60 @@ export function createLogsPlugin(config: LogsPluginConfig = {}): Plugin {
|
|
|
165
165
|
},
|
|
166
166
|
});
|
|
167
167
|
|
|
168
|
+
// Register /clear route (slug prefix added automatically by framework)
|
|
169
|
+
registry.addRoute({
|
|
170
|
+
method: 'post',
|
|
171
|
+
path: '/clear',
|
|
172
|
+
pluginId: 'logs',
|
|
173
|
+
handler: (req: Request, res: Response) => {
|
|
174
|
+
try {
|
|
175
|
+
const sources = getSources();
|
|
176
|
+
const sourceName = (req.body.source as string) || sources[0]?.name;
|
|
177
|
+
const source = sources.find((s) => s.name === sourceName);
|
|
178
|
+
|
|
179
|
+
if (!source) {
|
|
180
|
+
return res.status(404).json({ error: `Source "${sourceName}" not found` });
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (source.type !== 'file' || !source.path) {
|
|
184
|
+
return res.status(400).json({ error: 'Clear only available for file sources' });
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const resolvedPath = resolve(source.path);
|
|
188
|
+
if (!existsSync(resolvedPath)) {
|
|
189
|
+
return res.status(404).json({ error: `Log file not found: ${source.path}` });
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Truncate the file (clear contents but keep file)
|
|
193
|
+
truncateSync(resolvedPath, 0);
|
|
194
|
+
logger.info(`Cleared log file: ${source.name} (${source.path})`);
|
|
195
|
+
|
|
196
|
+
return res.json({
|
|
197
|
+
success: true,
|
|
198
|
+
message: `Log file "${source.name}" cleared successfully`,
|
|
199
|
+
source: source.name,
|
|
200
|
+
});
|
|
201
|
+
} catch (error) {
|
|
202
|
+
logger.error('Failed to clear log file', { error });
|
|
203
|
+
return res.status(500).json({
|
|
204
|
+
error: 'Failed to clear log file',
|
|
205
|
+
message: error instanceof Error ? error.message : String(error),
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
// Register maintenance widget
|
|
212
|
+
registry.addWidget({
|
|
213
|
+
id: 'logs-maintenance',
|
|
214
|
+
title: 'Log Management',
|
|
215
|
+
component: 'LogsMaintenanceWidget',
|
|
216
|
+
type: 'maintenance',
|
|
217
|
+
priority: 50,
|
|
218
|
+
showByDefault: true,
|
|
219
|
+
pluginId: 'logs',
|
|
220
|
+
});
|
|
221
|
+
|
|
168
222
|
const sources = getSources();
|
|
169
223
|
logger.debug(`Logs plugin initialized with ${sources.length} sources`);
|
|
170
224
|
},
|
|
@@ -362,22 +362,65 @@ export function createMaintenancePlugin(config: MaintenancePluginConfig = {}): P
|
|
|
362
362
|
});
|
|
363
363
|
}
|
|
364
364
|
|
|
365
|
+
// Register maintenance widgets
|
|
366
|
+
if (config.enableSeeds !== false) {
|
|
367
|
+
registry.addWidget({
|
|
368
|
+
id: 'seed-management',
|
|
369
|
+
title: 'Seed Management',
|
|
370
|
+
component: 'SeedManagementWidget',
|
|
371
|
+
type: 'maintenance',
|
|
372
|
+
priority: 10,
|
|
373
|
+
showByDefault: true, // Show by default on maintenance page
|
|
374
|
+
pluginId: 'maintenance',
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
|
|
365
378
|
// TODO: Register service control routes
|
|
366
379
|
if (config.enableServiceControl !== false) {
|
|
367
380
|
logger.debug('Service control enabled');
|
|
368
381
|
// Routes will be added in #703
|
|
382
|
+
|
|
383
|
+
registry.addWidget({
|
|
384
|
+
id: 'service-control',
|
|
385
|
+
title: 'Service Control',
|
|
386
|
+
component: 'ServiceControlWidget',
|
|
387
|
+
type: 'maintenance',
|
|
388
|
+
priority: 20,
|
|
389
|
+
showByDefault: false,
|
|
390
|
+
pluginId: 'maintenance',
|
|
391
|
+
});
|
|
369
392
|
}
|
|
370
393
|
|
|
371
394
|
// TODO: Register environment variable management routes
|
|
372
395
|
if (config.enableEnvManagement !== false) {
|
|
373
396
|
logger.debug('Environment variable management enabled');
|
|
374
397
|
// Routes will be added in #704
|
|
398
|
+
|
|
399
|
+
registry.addWidget({
|
|
400
|
+
id: 'environment-config',
|
|
401
|
+
title: 'Environment Configuration',
|
|
402
|
+
component: 'EnvironmentConfigWidget',
|
|
403
|
+
type: 'maintenance',
|
|
404
|
+
priority: 30,
|
|
405
|
+
showByDefault: false,
|
|
406
|
+
pluginId: 'maintenance',
|
|
407
|
+
});
|
|
375
408
|
}
|
|
376
409
|
|
|
377
410
|
// TODO: Register database operation routes
|
|
378
411
|
if (config.enableDatabaseOps !== false) {
|
|
379
412
|
logger.debug('Database operations enabled');
|
|
380
413
|
// Routes will be added in #705
|
|
414
|
+
|
|
415
|
+
registry.addWidget({
|
|
416
|
+
id: 'database-ops',
|
|
417
|
+
title: 'Database Operations',
|
|
418
|
+
component: 'DatabaseOpsWidget',
|
|
419
|
+
type: 'maintenance',
|
|
420
|
+
priority: 40,
|
|
421
|
+
showByDefault: false,
|
|
422
|
+
pluginId: 'maintenance',
|
|
423
|
+
});
|
|
381
424
|
}
|
|
382
425
|
|
|
383
426
|
// Register UI page
|
|
@@ -90,8 +90,6 @@ export type {
|
|
|
90
90
|
NotificationsManagerInterface,
|
|
91
91
|
} from './types.js';
|
|
92
92
|
|
|
93
|
-
// UI Components
|
|
94
|
-
export
|
|
95
|
-
|
|
96
|
-
export type { NotificationsStatusWidgetProps } from './NotificationsStatusWidget.js';
|
|
97
|
-
export type { NotificationsManagementPageProps } from './NotificationsManagementPage.js';
|
|
93
|
+
// UI Components are exported from main package index (@qwickapps/server)
|
|
94
|
+
// Do NOT export here to avoid loading UI dependencies when importing plugins
|
|
95
|
+
|
|
@@ -96,7 +96,10 @@ function validateId(id: string | undefined, paramName: string): { valid: boolean
|
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
/**
|
|
99
|
-
* Create the Notifications plugin
|
|
99
|
+
* Create the Notifications plugin with smart defaults
|
|
100
|
+
*
|
|
101
|
+
* Config is optional - plugin will use defaults and get dependencies from registry.
|
|
102
|
+
* Gracefully handles missing dependencies with clear log messages.
|
|
100
103
|
*
|
|
101
104
|
* @param config Plugin configuration
|
|
102
105
|
* @returns Plugin instance
|
|
@@ -112,11 +115,7 @@ function validateId(id: string | undefined, paramName: string): { valid: boolean
|
|
|
112
115
|
* });
|
|
113
116
|
* ```
|
|
114
117
|
*/
|
|
115
|
-
export function createNotificationsPlugin(config: NotificationsPluginConfig): Plugin {
|
|
116
|
-
const apiPrefix = config.api?.prefix || '/'; // Framework adds /notifications prefix automatically
|
|
117
|
-
const streamEnabled = config.api?.stream !== false;
|
|
118
|
-
const statsEnabled = config.api?.stats !== false;
|
|
119
|
-
|
|
118
|
+
export function createNotificationsPlugin(config: Partial<NotificationsPluginConfig> = {}): Plugin {
|
|
120
119
|
let manager: NotificationsManager | null = null;
|
|
121
120
|
|
|
122
121
|
return {
|
|
@@ -129,10 +128,19 @@ export function createNotificationsPlugin(config: NotificationsPluginConfig): Pl
|
|
|
129
128
|
|
|
130
129
|
// Check for postgres plugin dependency
|
|
131
130
|
if (!hasPostgres()) {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
131
|
+
logger.warn('No Database! Notifications plugin disabled.');
|
|
132
|
+
registry.registerHealthCheck({
|
|
133
|
+
name: 'notifications',
|
|
134
|
+
type: 'custom',
|
|
135
|
+
check: async () => ({
|
|
136
|
+
healthy: false,
|
|
137
|
+
details: {
|
|
138
|
+
error: 'PostgreSQL not available',
|
|
139
|
+
state: 'disabled',
|
|
140
|
+
},
|
|
141
|
+
}),
|
|
142
|
+
});
|
|
143
|
+
return;
|
|
136
144
|
}
|
|
137
145
|
|
|
138
146
|
// Get database connection string from postgres plugin
|
|
@@ -150,22 +158,43 @@ export function createNotificationsPlugin(config: NotificationsPluginConfig): Pl
|
|
|
150
158
|
}
|
|
151
159
|
|
|
152
160
|
if (!connectionString) {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
161
|
+
logger.warn('Could not determine PostgreSQL connection string. Notifications plugin disabled.');
|
|
162
|
+
registry.registerHealthCheck({
|
|
163
|
+
name: 'notifications',
|
|
164
|
+
type: 'custom',
|
|
165
|
+
check: async () => ({
|
|
166
|
+
healthy: false,
|
|
167
|
+
details: {
|
|
168
|
+
error: 'Connection string not available',
|
|
169
|
+
state: 'disabled',
|
|
170
|
+
},
|
|
171
|
+
}),
|
|
172
|
+
});
|
|
173
|
+
return;
|
|
157
174
|
}
|
|
158
175
|
|
|
176
|
+
// Smart defaults
|
|
177
|
+
const channels = config.channels ?? [];
|
|
178
|
+
const apiPrefix = config.api?.prefix ?? '/'; // Framework adds /notifications prefix automatically
|
|
179
|
+
const streamEnabled = config.api?.stream ?? true;
|
|
180
|
+
const statsEnabled = config.api?.stats ?? true;
|
|
181
|
+
|
|
159
182
|
logger.debug('Initializing notifications manager', {
|
|
160
|
-
channels:
|
|
183
|
+
channels: channels,
|
|
161
184
|
heartbeatInterval: config.heartbeat?.interval,
|
|
162
185
|
});
|
|
163
186
|
|
|
187
|
+
// Create full config with defaults for required fields
|
|
188
|
+
const fullConfig: NotificationsPluginConfig = {
|
|
189
|
+
...config,
|
|
190
|
+
channels, // Required field with default
|
|
191
|
+
};
|
|
192
|
+
|
|
164
193
|
// Create and initialize manager
|
|
165
194
|
manager = new NotificationsManager(
|
|
166
195
|
connectionString,
|
|
167
|
-
|
|
168
|
-
|
|
196
|
+
channels,
|
|
197
|
+
fullConfig,
|
|
169
198
|
logger
|
|
170
199
|
);
|
|
171
200
|
|
|
@@ -182,7 +211,7 @@ export function createNotificationsPlugin(config: NotificationsPluginConfig): Pl
|
|
|
182
211
|
healthy: health?.isHealthy ?? false,
|
|
183
212
|
details: {
|
|
184
213
|
connected: health?.isConnected,
|
|
185
|
-
channels:
|
|
214
|
+
channels: channels,
|
|
186
215
|
activeClients: manager?.getStats().currentConnections ?? 0,
|
|
187
216
|
lastEventAt: health?.lastEventAt?.toISOString(),
|
|
188
217
|
isReconnecting: health?.isReconnecting,
|
|
@@ -273,7 +302,7 @@ export function createNotificationsPlugin(config: NotificationsPluginConfig): Pl
|
|
|
273
302
|
const stats = manager.getStats();
|
|
274
303
|
res.json({
|
|
275
304
|
...stats,
|
|
276
|
-
channels:
|
|
305
|
+
channels: channels,
|
|
277
306
|
lastEventAt: stats.connectionHealth.lastEventAt?.toISOString(),
|
|
278
307
|
lastReconnectionAt: stats.lastReconnectionAt?.toISOString(),
|
|
279
308
|
});
|
|
@@ -378,6 +407,7 @@ export function createNotificationsPlugin(config: NotificationsPluginConfig): Pl
|
|
|
378
407
|
id: 'notifications-stats',
|
|
379
408
|
title: 'Notifications',
|
|
380
409
|
component: 'NotificationsStatsWidget',
|
|
410
|
+
type: 'status',
|
|
381
411
|
priority: 25, // After ServiceHealthWidget (10) and AuthStatusWidget (20)
|
|
382
412
|
showByDefault: true,
|
|
383
413
|
pluginId: 'notifications',
|
|
@@ -54,8 +54,6 @@ export { postgresParentalStore } from './stores/index.js';
|
|
|
54
54
|
export { kidsAdapter } from './adapters/index.js';
|
|
55
55
|
export type { KidsAdapterConfig } from './adapters/index.js';
|
|
56
56
|
|
|
57
|
-
// UI Components
|
|
58
|
-
export
|
|
59
|
-
|
|
60
|
-
export { ParentalManagementPage } from './ParentalManagementPage.js';
|
|
61
|
-
export type { ParentalManagementPageProps } from './ParentalManagementPage.js';
|
|
57
|
+
// UI Components are exported from main package index (@qwickapps/server)
|
|
58
|
+
// Do NOT export here to avoid loading UI dependencies when importing plugins
|
|
59
|
+
|