@qwickapps/server 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. package/README.md +238 -0
  2. package/dist/core/control-panel.d.ts +7 -2
  3. package/dist/core/control-panel.d.ts.map +1 -1
  4. package/dist/core/control-panel.js +92 -54
  5. package/dist/core/control-panel.js.map +1 -1
  6. package/dist/core/gateway.d.ts +159 -79
  7. package/dist/core/gateway.d.ts.map +1 -1
  8. package/dist/core/gateway.js +679 -319
  9. package/dist/core/gateway.js.map +1 -1
  10. package/dist/core/index.d.ts +3 -1
  11. package/dist/core/index.d.ts.map +1 -1
  12. package/dist/core/index.js +2 -0
  13. package/dist/core/index.js.map +1 -1
  14. package/dist/core/plugin-registry.d.ts +271 -0
  15. package/dist/core/plugin-registry.d.ts.map +1 -0
  16. package/dist/core/plugin-registry.js +326 -0
  17. package/dist/core/plugin-registry.js.map +1 -0
  18. package/dist/core/types.d.ts +16 -33
  19. package/dist/core/types.d.ts.map +1 -1
  20. package/dist/index.d.ts +8 -5
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +15 -7
  23. package/dist/index.js.map +1 -1
  24. package/dist/plugins/auth/adapters/auth0-adapter.d.ts +14 -0
  25. package/dist/plugins/auth/adapters/auth0-adapter.d.ts.map +1 -0
  26. package/dist/plugins/auth/adapters/auth0-adapter.js +179 -0
  27. package/dist/plugins/auth/adapters/auth0-adapter.js.map +1 -0
  28. package/dist/plugins/auth/adapters/basic-adapter.d.ts +13 -0
  29. package/dist/plugins/auth/adapters/basic-adapter.d.ts.map +1 -0
  30. package/dist/plugins/auth/adapters/basic-adapter.js +51 -0
  31. package/dist/plugins/auth/adapters/basic-adapter.js.map +1 -0
  32. package/dist/plugins/auth/adapters/index.d.ts +9 -0
  33. package/dist/plugins/auth/adapters/index.d.ts.map +1 -0
  34. package/dist/plugins/auth/adapters/index.js +9 -0
  35. package/dist/plugins/auth/adapters/index.js.map +1 -0
  36. package/dist/plugins/auth/adapters/supabase-adapter.d.ts +13 -0
  37. package/dist/plugins/auth/adapters/supabase-adapter.d.ts.map +1 -0
  38. package/dist/plugins/auth/adapters/supabase-adapter.js +109 -0
  39. package/dist/plugins/auth/adapters/supabase-adapter.js.map +1 -0
  40. package/dist/plugins/auth/auth-plugin.d.ts +40 -0
  41. package/dist/plugins/auth/auth-plugin.d.ts.map +1 -0
  42. package/dist/plugins/auth/auth-plugin.js +255 -0
  43. package/dist/plugins/auth/auth-plugin.js.map +1 -0
  44. package/dist/plugins/auth/auth-plugin.test.d.ts +9 -0
  45. package/dist/plugins/auth/auth-plugin.test.d.ts.map +1 -0
  46. package/dist/plugins/auth/auth-plugin.test.js +147 -0
  47. package/dist/plugins/auth/auth-plugin.test.js.map +1 -0
  48. package/dist/plugins/auth/index.d.ts +12 -0
  49. package/dist/plugins/auth/index.d.ts.map +1 -0
  50. package/dist/plugins/auth/index.js +13 -0
  51. package/dist/plugins/auth/index.js.map +1 -0
  52. package/dist/plugins/auth/types.d.ts +148 -0
  53. package/dist/plugins/auth/types.d.ts.map +1 -0
  54. package/dist/plugins/auth/types.js +14 -0
  55. package/dist/plugins/auth/types.js.map +1 -0
  56. package/dist/plugins/bans/bans-plugin.d.ts +59 -0
  57. package/dist/plugins/bans/bans-plugin.d.ts.map +1 -0
  58. package/dist/plugins/bans/bans-plugin.js +428 -0
  59. package/dist/plugins/bans/bans-plugin.js.map +1 -0
  60. package/dist/plugins/bans/index.d.ts +9 -0
  61. package/dist/plugins/bans/index.d.ts.map +1 -0
  62. package/dist/plugins/bans/index.js +10 -0
  63. package/dist/plugins/bans/index.js.map +1 -0
  64. package/dist/plugins/bans/stores/index.d.ts +7 -0
  65. package/dist/plugins/bans/stores/index.d.ts.map +1 -0
  66. package/dist/plugins/bans/stores/index.js +7 -0
  67. package/dist/plugins/bans/stores/index.js.map +1 -0
  68. package/dist/plugins/bans/stores/postgres-store.d.ts +29 -0
  69. package/dist/plugins/bans/stores/postgres-store.d.ts.map +1 -0
  70. package/dist/plugins/bans/stores/postgres-store.js +132 -0
  71. package/dist/plugins/bans/stores/postgres-store.js.map +1 -0
  72. package/dist/plugins/bans/types.d.ts +128 -0
  73. package/dist/plugins/bans/types.d.ts.map +1 -0
  74. package/dist/plugins/bans/types.js +11 -0
  75. package/dist/plugins/bans/types.js.map +1 -0
  76. package/dist/plugins/cache-plugin.d.ts +14 -3
  77. package/dist/plugins/cache-plugin.d.ts.map +1 -1
  78. package/dist/plugins/cache-plugin.js +27 -7
  79. package/dist/plugins/cache-plugin.js.map +1 -1
  80. package/dist/plugins/cache-plugin.test.js +96 -32
  81. package/dist/plugins/cache-plugin.test.js.map +1 -1
  82. package/dist/plugins/config-plugin.d.ts +3 -2
  83. package/dist/plugins/config-plugin.d.ts.map +1 -1
  84. package/dist/plugins/config-plugin.js +17 -10
  85. package/dist/plugins/config-plugin.js.map +1 -1
  86. package/dist/plugins/diagnostics-plugin.d.ts +2 -2
  87. package/dist/plugins/diagnostics-plugin.d.ts.map +1 -1
  88. package/dist/plugins/diagnostics-plugin.js +17 -10
  89. package/dist/plugins/diagnostics-plugin.js.map +1 -1
  90. package/dist/plugins/entitlements/entitlements-plugin.d.ts +95 -0
  91. package/dist/plugins/entitlements/entitlements-plugin.d.ts.map +1 -0
  92. package/dist/plugins/entitlements/entitlements-plugin.js +707 -0
  93. package/dist/plugins/entitlements/entitlements-plugin.js.map +1 -0
  94. package/dist/plugins/entitlements/index.d.ts +12 -0
  95. package/dist/plugins/entitlements/index.d.ts.map +1 -0
  96. package/dist/plugins/entitlements/index.js +16 -0
  97. package/dist/plugins/entitlements/index.js.map +1 -0
  98. package/dist/plugins/entitlements/sources/index.d.ts +9 -0
  99. package/dist/plugins/entitlements/sources/index.d.ts.map +1 -0
  100. package/dist/plugins/entitlements/sources/index.js +9 -0
  101. package/dist/plugins/entitlements/sources/index.js.map +1 -0
  102. package/dist/plugins/entitlements/sources/postgres-source.d.ts +29 -0
  103. package/dist/plugins/entitlements/sources/postgres-source.d.ts.map +1 -0
  104. package/dist/plugins/entitlements/sources/postgres-source.js +169 -0
  105. package/dist/plugins/entitlements/sources/postgres-source.js.map +1 -0
  106. package/dist/plugins/entitlements/types.d.ts +232 -0
  107. package/dist/plugins/entitlements/types.d.ts.map +1 -0
  108. package/dist/plugins/entitlements/types.js +11 -0
  109. package/dist/plugins/entitlements/types.js.map +1 -0
  110. package/dist/plugins/frontend-app-plugin.d.ts +9 -3
  111. package/dist/plugins/frontend-app-plugin.d.ts.map +1 -1
  112. package/dist/plugins/frontend-app-plugin.js +14 -9
  113. package/dist/plugins/frontend-app-plugin.js.map +1 -1
  114. package/dist/plugins/health-plugin.d.ts +5 -2
  115. package/dist/plugins/health-plugin.d.ts.map +1 -1
  116. package/dist/plugins/health-plugin.js +20 -5
  117. package/dist/plugins/health-plugin.js.map +1 -1
  118. package/dist/plugins/index.d.ts +8 -2
  119. package/dist/plugins/index.d.ts.map +1 -1
  120. package/dist/plugins/index.js +8 -2
  121. package/dist/plugins/index.js.map +1 -1
  122. package/dist/plugins/logs-plugin.d.ts +3 -2
  123. package/dist/plugins/logs-plugin.d.ts.map +1 -1
  124. package/dist/plugins/logs-plugin.js +21 -12
  125. package/dist/plugins/logs-plugin.js.map +1 -1
  126. package/dist/plugins/postgres-plugin.d.ts +3 -3
  127. package/dist/plugins/postgres-plugin.d.ts.map +1 -1
  128. package/dist/plugins/postgres-plugin.js +9 -7
  129. package/dist/plugins/postgres-plugin.js.map +1 -1
  130. package/dist/plugins/postgres-plugin.test.js +47 -29
  131. package/dist/plugins/postgres-plugin.test.js.map +1 -1
  132. package/dist/plugins/users/index.d.ts +12 -0
  133. package/dist/plugins/users/index.d.ts.map +1 -0
  134. package/dist/plugins/users/index.js +13 -0
  135. package/dist/plugins/users/index.js.map +1 -0
  136. package/dist/plugins/users/stores/index.d.ts +7 -0
  137. package/dist/plugins/users/stores/index.d.ts.map +1 -0
  138. package/dist/plugins/users/stores/index.js +7 -0
  139. package/dist/plugins/users/stores/index.js.map +1 -0
  140. package/dist/plugins/users/stores/postgres-store.d.ts +28 -0
  141. package/dist/plugins/users/stores/postgres-store.d.ts.map +1 -0
  142. package/dist/plugins/users/stores/postgres-store.js +157 -0
  143. package/dist/plugins/users/stores/postgres-store.js.map +1 -0
  144. package/dist/plugins/users/types.d.ts +189 -0
  145. package/dist/plugins/users/types.d.ts.map +1 -0
  146. package/dist/plugins/users/types.js +12 -0
  147. package/dist/plugins/users/types.js.map +1 -0
  148. package/dist/plugins/users/users-plugin.d.ts +39 -0
  149. package/dist/plugins/users/users-plugin.d.ts.map +1 -0
  150. package/dist/plugins/users/users-plugin.js +242 -0
  151. package/dist/plugins/users/users-plugin.js.map +1 -0
  152. package/dist-ui/assets/index-Bsp2ntcw.js +465 -0
  153. package/dist-ui/assets/index-Bsp2ntcw.js.map +1 -0
  154. package/dist-ui/index.html +1 -1
  155. package/dist-ui-lib/api/controlPanelApi.d.ts +232 -0
  156. package/dist-ui-lib/components/ControlPanelApp.d.ts +61 -0
  157. package/dist-ui-lib/components/index.d.ts +18 -0
  158. package/dist-ui-lib/config/AppConfig.d.ts +7 -0
  159. package/dist-ui-lib/dashboard/DashboardWidgetRegistry.d.ts +62 -0
  160. package/dist-ui-lib/dashboard/DashboardWidgetRenderer.d.ts +8 -0
  161. package/dist-ui-lib/dashboard/PluginWidgetRenderer.d.ts +19 -0
  162. package/dist-ui-lib/dashboard/WidgetComponentRegistry.d.ts +44 -0
  163. package/dist-ui-lib/dashboard/builtInWidgets.d.ts +19 -0
  164. package/dist-ui-lib/dashboard/index.d.ts +13 -0
  165. package/dist-ui-lib/dashboard/widgets/ServiceHealthWidget.d.ts +12 -0
  166. package/dist-ui-lib/dashboard/widgets/index.d.ts +6 -0
  167. package/dist-ui-lib/index.js +6441 -0
  168. package/dist-ui-lib/index.js.map +1 -0
  169. package/dist-ui-lib/pages/ConfigPage.d.ts +1 -0
  170. package/dist-ui-lib/pages/DashboardPage.d.ts +1 -0
  171. package/dist-ui-lib/pages/DiagnosticsPage.d.ts +1 -0
  172. package/dist-ui-lib/pages/EntitlementsPage.d.ts +17 -0
  173. package/dist-ui-lib/pages/LogsPage.d.ts +1 -0
  174. package/dist-ui-lib/pages/NotFoundPage.d.ts +1 -0
  175. package/dist-ui-lib/pages/PluginPage.d.ts +15 -0
  176. package/dist-ui-lib/pages/SystemPage.d.ts +1 -0
  177. package/dist-ui-lib/pages/UsersPage.d.ts +22 -0
  178. package/package.json +18 -6
  179. package/src/core/control-panel.ts +114 -61
  180. package/src/core/gateway.ts +863 -403
  181. package/src/core/index.ts +21 -2
  182. package/src/core/plugin-registry.ts +653 -0
  183. package/src/core/types.ts +31 -37
  184. package/src/index.ts +118 -19
  185. package/src/plugins/auth/adapters/auth0-adapter.ts +214 -0
  186. package/src/plugins/auth/adapters/basic-adapter.ts +61 -0
  187. package/src/plugins/auth/adapters/index.ts +9 -0
  188. package/src/plugins/auth/adapters/supabase-adapter.ts +141 -0
  189. package/src/plugins/auth/auth-plugin.test.ts +176 -0
  190. package/src/plugins/auth/auth-plugin.ts +303 -0
  191. package/src/plugins/auth/index.ts +33 -0
  192. package/src/plugins/auth/types.ts +165 -0
  193. package/src/plugins/bans/bans-plugin.ts +485 -0
  194. package/src/plugins/bans/index.ts +31 -0
  195. package/src/plugins/bans/stores/index.ts +7 -0
  196. package/src/plugins/bans/stores/postgres-store.ts +195 -0
  197. package/src/plugins/bans/types.ts +141 -0
  198. package/src/plugins/cache-plugin.test.ts +105 -32
  199. package/src/plugins/cache-plugin.ts +40 -9
  200. package/src/plugins/config-plugin.ts +23 -12
  201. package/src/plugins/diagnostics-plugin.ts +22 -12
  202. package/src/plugins/entitlements/entitlements-plugin.ts +820 -0
  203. package/src/plugins/entitlements/index.ts +51 -0
  204. package/src/plugins/entitlements/sources/index.ts +9 -0
  205. package/src/plugins/entitlements/sources/postgres-source.ts +253 -0
  206. package/src/plugins/entitlements/types.ts +256 -0
  207. package/src/plugins/frontend-app-plugin.ts +24 -12
  208. package/src/plugins/health-plugin.ts +27 -7
  209. package/src/plugins/index.ts +106 -4
  210. package/src/plugins/logs-plugin.ts +28 -14
  211. package/src/plugins/postgres-plugin.test.ts +49 -29
  212. package/src/plugins/postgres-plugin.ts +11 -9
  213. package/src/plugins/users/index.ts +35 -0
  214. package/src/plugins/users/stores/index.ts +7 -0
  215. package/src/plugins/users/stores/postgres-store.ts +225 -0
  216. package/src/plugins/users/types.ts +209 -0
  217. package/src/plugins/users/users-plugin.ts +281 -0
  218. package/ui/src/App.tsx +185 -31
  219. package/ui/src/api/controlPanelApi.ts +354 -1
  220. package/ui/src/components/ControlPanelApp.tsx +209 -0
  221. package/ui/src/components/index.ts +62 -0
  222. package/ui/src/dashboard/DashboardWidgetRegistry.tsx +129 -0
  223. package/ui/src/dashboard/DashboardWidgetRenderer.tsx +34 -0
  224. package/ui/src/dashboard/PluginWidgetRenderer.tsx +115 -0
  225. package/ui/src/dashboard/WidgetComponentRegistry.tsx +116 -0
  226. package/ui/src/dashboard/builtInWidgets.tsx +29 -0
  227. package/ui/src/dashboard/index.ts +35 -0
  228. package/ui/src/dashboard/widgets/ServiceHealthWidget.tsx +140 -0
  229. package/ui/src/dashboard/widgets/index.ts +7 -0
  230. package/ui/src/pages/DashboardPage.tsx +28 -149
  231. package/ui/src/pages/EntitlementsPage.tsx +557 -0
  232. package/ui/src/pages/LogsPage.tsx +174 -8
  233. package/ui/src/pages/PluginPage.tsx +148 -0
  234. package/ui/src/pages/SystemPage.tsx +445 -0
  235. package/ui/src/pages/UsersPage.tsx +837 -0
  236. package/ui/tsconfig.lib.json +11 -0
  237. package/ui/vite.lib.config.ts +51 -0
  238. package/dist-ui/assets/index-CW1BviRn.js +0 -465
  239. package/dist-ui/assets/index-CW1BviRn.js.map +0 -1
  240. package/ui/src/pages/HealthPage.tsx +0 -204
@@ -6,30 +6,50 @@
6
6
  * Copyright (c) 2025 QwickApps.com. All rights reserved.
7
7
  */
8
8
 
9
- import type { ControlPanelPlugin, HealthCheck, PluginContext } from '../core/types.js';
9
+ import type { Plugin, PluginConfig, PluginRegistry } from '../core/plugin-registry.js';
10
+ import type { HealthCheck } from '../core/types.js';
10
11
 
11
12
  export interface HealthPluginConfig {
12
13
  checks: HealthCheck[];
13
14
  aggregateEndpoint?: string;
15
+ /** Whether to show the ServiceHealthWidget on the dashboard (default: true) */
16
+ showWidget?: boolean;
14
17
  }
15
18
 
16
19
  /**
17
20
  * Create a health check plugin
18
21
  */
19
- export function createHealthPlugin(config: HealthPluginConfig): ControlPanelPlugin {
22
+ export function createHealthPlugin(config: HealthPluginConfig): Plugin {
20
23
  return {
21
- name: 'health',
22
- order: 10,
24
+ id: 'health',
25
+ name: 'Health Plugin',
26
+ version: '1.0.0',
23
27
 
24
- async onInit(context: PluginContext): Promise<void> {
25
- const { registerHealthCheck, logger } = context;
28
+ async onStart(_pluginConfig: PluginConfig, registry: PluginRegistry): Promise<void> {
29
+ const logger = registry.getLogger('health');
26
30
 
27
31
  // Register all health checks
28
32
  for (const check of config.checks) {
29
- registerHealthCheck(check);
33
+ registry.registerHealthCheck(check);
34
+ }
35
+
36
+ // Register the ServiceHealthWidget (shown by default unless disabled)
37
+ if (config.showWidget !== false) {
38
+ registry.addWidget({
39
+ id: 'service-health',
40
+ title: 'Service Health',
41
+ component: 'ServiceHealthWidget',
42
+ priority: 10,
43
+ showByDefault: true,
44
+ pluginId: 'health',
45
+ });
30
46
  }
31
47
 
32
48
  logger.debug(`Registered ${config.checks.length} health checks`);
33
49
  },
50
+
51
+ async onStop(): Promise<void> {
52
+ // Nothing to cleanup
53
+ },
34
54
  };
35
55
  }
@@ -22,9 +22,111 @@ export type { FrontendAppPluginConfig } from './frontend-app-plugin.js';
22
22
  export { createPostgresPlugin, getPostgres, hasPostgres } from './postgres-plugin.js';
23
23
  export type { PostgresPluginConfig, PostgresInstance, TransactionCallback } from './postgres-plugin.js';
24
24
 
25
- // Backward compatibility aliases (deprecated)
26
- export { createPostgresPlugin as createDatabasePlugin, getPostgres as getDatabase, hasPostgres as hasDatabase } from './postgres-plugin.js';
27
- export type { PostgresPluginConfig as DatabasePluginConfig, PostgresInstance as DatabaseInstance } from './postgres-plugin.js';
28
-
29
25
  export { createCachePlugin, getCache, hasCache } from './cache-plugin.js';
30
26
  export type { CachePluginConfig, CacheInstance } from './cache-plugin.js';
27
+
28
+ // Auth plugin
29
+ export {
30
+ createAuthPlugin,
31
+ isAuthenticated,
32
+ getAuthenticatedUser,
33
+ getAccessToken,
34
+ requireAuth,
35
+ requireRoles,
36
+ requireAnyRole,
37
+ auth0Adapter,
38
+ basicAdapter,
39
+ supabaseAdapter,
40
+ isAuthenticatedRequest,
41
+ } from './auth/index.js';
42
+ export type {
43
+ AuthPluginConfig,
44
+ AuthAdapter,
45
+ AuthenticatedUser,
46
+ AuthenticatedRequest,
47
+ Auth0AdapterConfig,
48
+ SupabaseAdapterConfig,
49
+ BasicAdapterConfig,
50
+ } from './auth/index.js';
51
+
52
+ // Users plugin
53
+ export {
54
+ createUsersPlugin,
55
+ getUserStore,
56
+ getUserById,
57
+ getUserByEmail,
58
+ findOrCreateUser,
59
+ postgresUserStore,
60
+ } from './users/index.js';
61
+ export type {
62
+ UsersPluginConfig,
63
+ UserStore,
64
+ User,
65
+ CreateUserInput,
66
+ UpdateUserInput,
67
+ UserSearchParams,
68
+ UserListResponse,
69
+ PostgresUserStoreConfig,
70
+ UserSyncConfig,
71
+ UsersApiConfig,
72
+ UsersUiConfig,
73
+ } from './users/index.js';
74
+
75
+ // Bans plugin (separate from Users, depends on Users)
76
+ export {
77
+ createBansPlugin,
78
+ getBanStore,
79
+ isUserBanned,
80
+ isEmailBanned,
81
+ getActiveBan,
82
+ banUser,
83
+ unbanUser,
84
+ listActiveBans,
85
+ postgresBanStore,
86
+ } from './bans/index.js';
87
+ export type {
88
+ BansPluginConfig,
89
+ BanStore,
90
+ Ban,
91
+ CreateBanInput,
92
+ RemoveBanInput,
93
+ BanCallbacks,
94
+ PostgresBanStoreConfig,
95
+ } from './bans/index.js';
96
+
97
+ // Entitlements plugin
98
+ export {
99
+ createEntitlementsPlugin,
100
+ getEntitlementSource,
101
+ isSourceReadonly,
102
+ getEntitlements,
103
+ refreshEntitlements,
104
+ hasEntitlement,
105
+ hasAnyEntitlement,
106
+ hasAllEntitlements,
107
+ grantEntitlement,
108
+ revokeEntitlement,
109
+ setEntitlements,
110
+ getAvailableEntitlements,
111
+ getEntitlementStats,
112
+ invalidateEntitlementCache,
113
+ storeExternalIdMapping,
114
+ invalidateByExternalId,
115
+ requireEntitlement,
116
+ requireAnyEntitlement,
117
+ requireAllEntitlements,
118
+ postgresEntitlementSource,
119
+ } from './entitlements/index.js';
120
+ export type {
121
+ EntitlementsPluginConfig,
122
+ EntitlementSource,
123
+ EntitlementResult,
124
+ EntitlementDefinition,
125
+ EntitlementCallbacks,
126
+ EntitlementsCacheConfig,
127
+ EntitlementsApiConfig,
128
+ PostgresEntitlementSourceConfig,
129
+ UserEntitlement,
130
+ CachedEntitlements,
131
+ EntitlementStats,
132
+ } from './entitlements/index.js';
@@ -10,7 +10,8 @@
10
10
  import { existsSync, readFileSync, statSync } from 'fs';
11
11
  import { resolve } from 'path';
12
12
  import type { Request, Response } from 'express';
13
- import type { ControlPanelPlugin, LogSource, PluginContext } from '../core/types.js';
13
+ import type { Plugin, PluginConfig, PluginRegistry } from '../core/plugin-registry.js';
14
+ import type { LogSource } from '../core/types.js';
14
15
  import { getLoggingSubsystem } from '../core/logging.js';
15
16
 
16
17
  export interface LogsPluginConfig {
@@ -61,7 +62,7 @@ function getDefaultSources(): LogSource[] {
61
62
  /**
62
63
  * Create a logs plugin
63
64
  */
64
- export function createLogsPlugin(config: LogsPluginConfig = {}): ControlPanelPlugin {
65
+ export function createLogsPlugin(config: LogsPluginConfig = {}): Plugin {
65
66
  const maxLines = config.retention?.maxLines || 10000;
66
67
 
67
68
  // Use provided sources or default to logging subsystem paths
@@ -73,13 +74,18 @@ export function createLogsPlugin(config: LogsPluginConfig = {}): ControlPanelPlu
73
74
  };
74
75
 
75
76
  return {
76
- name: 'logs',
77
- order: 20,
77
+ id: 'logs',
78
+ name: 'Logs Plugin',
79
+ version: '1.0.0',
78
80
 
79
- routes: [
80
- {
81
+ async onStart(_pluginConfig: PluginConfig, registry: PluginRegistry): Promise<void> {
82
+ const logger = registry.getLogger('logs');
83
+
84
+ // Register /logs/sources route
85
+ registry.addRoute({
81
86
  method: 'get',
82
87
  path: '/logs/sources',
88
+ pluginId: 'logs',
83
89
  handler: (_req: Request, res: Response) => {
84
90
  const sources = getSources();
85
91
  res.json({
@@ -89,10 +95,13 @@ export function createLogsPlugin(config: LogsPluginConfig = {}): ControlPanelPlu
89
95
  })),
90
96
  });
91
97
  },
92
- },
93
- {
98
+ });
99
+
100
+ // Register /logs route
101
+ registry.addRoute({
94
102
  method: 'get',
95
103
  path: '/logs',
104
+ pluginId: 'logs',
96
105
  handler: (req: Request, res: Response) => {
97
106
  try {
98
107
  const sources = getSources();
@@ -124,10 +133,13 @@ export function createLogsPlugin(config: LogsPluginConfig = {}): ControlPanelPlu
124
133
  });
125
134
  }
126
135
  },
127
- },
128
- {
136
+ });
137
+
138
+ // Register /logs/stats route
139
+ registry.addRoute({
129
140
  method: 'get',
130
141
  path: '/logs/stats',
142
+ pluginId: 'logs',
131
143
  handler: (req: Request, res: Response) => {
132
144
  try {
133
145
  const sources = getSources();
@@ -151,12 +163,14 @@ export function createLogsPlugin(config: LogsPluginConfig = {}): ControlPanelPlu
151
163
  });
152
164
  }
153
165
  },
154
- },
155
- ],
166
+ });
156
167
 
157
- async onInit(context: PluginContext): Promise<void> {
158
168
  const sources = getSources();
159
- context.logger.debug(`Logs plugin initialized with ${sources.length} sources`);
169
+ logger.debug(`Logs plugin initialized with ${sources.length} sources`);
170
+ },
171
+
172
+ async onStop(): Promise<void> {
173
+ // Nothing to cleanup
160
174
  },
161
175
  };
162
176
  }
@@ -38,6 +38,7 @@ import {
38
38
  hasPostgres,
39
39
  type PostgresPluginConfig,
40
40
  } from './postgres-plugin.js';
41
+ import type { PluginRegistry } from '../core/plugin-registry.js';
41
42
 
42
43
  describe('PostgreSQL Plugin', () => {
43
44
  const mockConfig: PostgresPluginConfig = {
@@ -46,21 +47,39 @@ describe('PostgreSQL Plugin', () => {
46
47
  healthCheck: false, // Disable for unit tests
47
48
  };
48
49
 
49
- const mockContext = {
50
- config: { productName: 'Test', port: 3000 },
51
- app: {} as any,
52
- router: {} as any,
53
- logger: {
50
+ // Create a mock registry that matches the new Plugin interface
51
+ const createMockRegistry = (): PluginRegistry => ({
52
+ hasPlugin: vi.fn().mockReturnValue(false),
53
+ getPlugin: vi.fn().mockReturnValue(null),
54
+ listPlugins: vi.fn().mockReturnValue([]),
55
+ addRoute: vi.fn(),
56
+ addMenuItem: vi.fn(),
57
+ addPage: vi.fn(),
58
+ addWidget: vi.fn(),
59
+ getRoutes: vi.fn().mockReturnValue([]),
60
+ getMenuItems: vi.fn().mockReturnValue([]),
61
+ getPages: vi.fn().mockReturnValue([]),
62
+ getWidgets: vi.fn().mockReturnValue([]),
63
+ getConfig: vi.fn().mockReturnValue({}),
64
+ setConfig: vi.fn().mockResolvedValue(undefined),
65
+ subscribe: vi.fn().mockReturnValue(() => {}),
66
+ emit: vi.fn(),
67
+ registerHealthCheck: vi.fn(),
68
+ getApp: vi.fn().mockReturnValue({} as any),
69
+ getRouter: vi.fn().mockReturnValue({} as any),
70
+ getLogger: vi.fn().mockReturnValue({
54
71
  debug: vi.fn(),
55
72
  info: vi.fn(),
56
73
  warn: vi.fn(),
57
74
  error: vi.fn(),
58
- },
59
- registerHealthCheck: vi.fn(),
60
- };
75
+ }),
76
+ });
77
+
78
+ let mockRegistry: PluginRegistry;
61
79
 
62
80
  beforeEach(() => {
63
81
  vi.clearAllMocks();
82
+ mockRegistry = createMockRegistry();
64
83
  });
65
84
 
66
85
  afterEach(async () => {
@@ -74,33 +93,34 @@ describe('PostgreSQL Plugin', () => {
74
93
  describe('createPostgresPlugin', () => {
75
94
  it('should create a plugin with correct name', () => {
76
95
  const plugin = createPostgresPlugin(mockConfig, 'test');
77
- expect(plugin.name).toBe('postgres:test');
96
+ expect(plugin.name).toBe('PostgreSQL (test)');
78
97
  });
79
98
 
80
99
  it('should use "default" as instance name when not specified', () => {
81
100
  const plugin = createPostgresPlugin(mockConfig);
82
- expect(plugin.name).toBe('postgres:default');
101
+ expect(plugin.name).toBe('PostgreSQL (default)');
83
102
  });
84
103
 
85
- it('should have low order number (initialize early)', () => {
86
- const plugin = createPostgresPlugin(mockConfig);
87
- expect(plugin.order).toBeLessThan(10);
104
+ it('should have correct plugin id', () => {
105
+ const plugin = createPostgresPlugin(mockConfig, 'test');
106
+ expect(plugin.id).toBe('postgres:test');
88
107
  });
89
108
  });
90
109
 
91
- describe('onInit', () => {
110
+ describe('onStart', () => {
92
111
  it('should register the postgres instance', async () => {
93
112
  const plugin = createPostgresPlugin(mockConfig, 'test');
94
- await plugin.onInit?.(mockContext as any);
113
+ await plugin.onStart({}, mockRegistry);
95
114
 
96
115
  expect(hasPostgres('test')).toBe(true);
97
116
  });
98
117
 
99
118
  it('should log debug message on successful connection', async () => {
100
119
  const plugin = createPostgresPlugin(mockConfig, 'test');
101
- await plugin.onInit?.(mockContext as any);
120
+ await plugin.onStart({}, mockRegistry);
102
121
 
103
- expect(mockContext.logger.debug).toHaveBeenCalledWith(
122
+ const logger = mockRegistry.getLogger('postgres:test');
123
+ expect(logger.debug).toHaveBeenCalledWith(
104
124
  expect.stringContaining('connected')
105
125
  );
106
126
  });
@@ -108,9 +128,9 @@ describe('PostgreSQL Plugin', () => {
108
128
  it('should register health check when enabled', async () => {
109
129
  const configWithHealth = { ...mockConfig, healthCheck: true };
110
130
  const plugin = createPostgresPlugin(configWithHealth, 'test');
111
- await plugin.onInit?.(mockContext as any);
131
+ await plugin.onStart({}, mockRegistry);
112
132
 
113
- expect(mockContext.registerHealthCheck).toHaveBeenCalledWith(
133
+ expect(mockRegistry.registerHealthCheck).toHaveBeenCalledWith(
114
134
  expect.objectContaining({
115
135
  name: 'postgres',
116
136
  type: 'custom',
@@ -125,9 +145,9 @@ describe('PostgreSQL Plugin', () => {
125
145
  healthCheckName: 'custom-db',
126
146
  };
127
147
  const plugin = createPostgresPlugin(configWithCustomName, 'test');
128
- await plugin.onInit?.(mockContext as any);
148
+ await plugin.onStart({}, mockRegistry);
129
149
 
130
- expect(mockContext.registerHealthCheck).toHaveBeenCalledWith(
150
+ expect(mockRegistry.registerHealthCheck).toHaveBeenCalledWith(
131
151
  expect.objectContaining({
132
152
  name: 'custom-db',
133
153
  })
@@ -138,7 +158,7 @@ describe('PostgreSQL Plugin', () => {
138
158
  describe('getPostgres', () => {
139
159
  it('should return registered instance', async () => {
140
160
  const plugin = createPostgresPlugin(mockConfig, 'test');
141
- await plugin.onInit?.(mockContext as any);
161
+ await plugin.onStart({}, mockRegistry);
142
162
 
143
163
  const db = getPostgres('test');
144
164
  expect(db).toBeDefined();
@@ -161,7 +181,7 @@ describe('PostgreSQL Plugin', () => {
161
181
 
162
182
  it('should return true for registered instance', async () => {
163
183
  const plugin = createPostgresPlugin(mockConfig, 'test');
164
- await plugin.onInit?.(mockContext as any);
184
+ await plugin.onStart({}, mockRegistry);
165
185
 
166
186
  expect(hasPostgres('test')).toBe(true);
167
187
  });
@@ -170,7 +190,7 @@ describe('PostgreSQL Plugin', () => {
170
190
  describe('PostgresInstance', () => {
171
191
  it('should execute query and return rows', async () => {
172
192
  const plugin = createPostgresPlugin(mockConfig, 'test');
173
- await plugin.onInit?.(mockContext as any);
193
+ await plugin.onStart({}, mockRegistry);
174
194
 
175
195
  const db = getPostgres('test');
176
196
  const result = await db.query('SELECT 1');
@@ -179,7 +199,7 @@ describe('PostgreSQL Plugin', () => {
179
199
 
180
200
  it('should return null from queryOne when no rows', async () => {
181
201
  const plugin = createPostgresPlugin(mockConfig, 'test');
182
- await plugin.onInit?.(mockContext as any);
202
+ await plugin.onStart({}, mockRegistry);
183
203
 
184
204
  const db = getPostgres('test');
185
205
  const result = await db.queryOne('SELECT 1');
@@ -188,7 +208,7 @@ describe('PostgreSQL Plugin', () => {
188
208
 
189
209
  it('should return pool stats', async () => {
190
210
  const plugin = createPostgresPlugin(mockConfig, 'test');
191
- await plugin.onInit?.(mockContext as any);
211
+ await plugin.onStart({}, mockRegistry);
192
212
 
193
213
  const db = getPostgres('test');
194
214
  const stats = db.getStats();
@@ -198,14 +218,14 @@ describe('PostgreSQL Plugin', () => {
198
218
  });
199
219
  });
200
220
 
201
- describe('onShutdown', () => {
221
+ describe('onStop', () => {
202
222
  it('should close pool and unregister instance', async () => {
203
223
  const plugin = createPostgresPlugin(mockConfig, 'test');
204
- await plugin.onInit?.(mockContext as any);
224
+ await plugin.onStart({}, mockRegistry);
205
225
 
206
226
  expect(hasPostgres('test')).toBe(true);
207
227
 
208
- await plugin.onShutdown?.();
228
+ await plugin.onStop();
209
229
 
210
230
  expect(hasPostgres('test')).toBe(false);
211
231
  });
@@ -47,7 +47,7 @@
47
47
  */
48
48
 
49
49
  import pg from 'pg';
50
- import type { ControlPanelPlugin, PluginContext } from '../core/types.js';
50
+ import type { Plugin, PluginConfig, PluginRegistry } from '../core/plugin-registry.js';
51
51
 
52
52
  const { Pool } = pg;
53
53
 
@@ -173,7 +173,7 @@ export function hasPostgres(name = 'default'): boolean {
173
173
  *
174
174
  * @param config - PostgreSQL configuration
175
175
  * @param instanceName - Name for this PostgreSQL instance (default: 'default')
176
- * @returns A control panel plugin
176
+ * @returns A plugin
177
177
  *
178
178
  * @example
179
179
  * ```typescript
@@ -187,8 +187,9 @@ export function hasPostgres(name = 'default'): boolean {
187
187
  export function createPostgresPlugin(
188
188
  config: PostgresPluginConfig,
189
189
  instanceName = 'default'
190
- ): ControlPanelPlugin {
190
+ ): Plugin {
191
191
  let pool: pg.Pool | null = null;
192
+ const pluginId = `postgres:${instanceName}`;
192
193
 
193
194
  const createInstance = (): PostgresInstance => {
194
195
  if (!pool) {
@@ -282,11 +283,12 @@ export function createPostgresPlugin(
282
283
  };
283
284
 
284
285
  return {
285
- name: `postgres:${instanceName}`,
286
- order: 5, // Initialize early, before other plugins that may need DB
286
+ id: pluginId,
287
+ name: `PostgreSQL (${instanceName})`,
288
+ version: '1.0.0',
287
289
 
288
- async onInit(context: PluginContext): Promise<void> {
289
- const { registerHealthCheck, logger } = context;
290
+ async onStart(_pluginConfig: PluginConfig, registry: PluginRegistry): Promise<void> {
291
+ const logger = registry.getLogger(pluginId);
290
292
 
291
293
  // Create and register the instance
292
294
  const instance = createInstance();
@@ -303,7 +305,7 @@ export function createPostgresPlugin(
303
305
 
304
306
  // Register health check if enabled
305
307
  if (config.healthCheck !== false) {
306
- registerHealthCheck({
308
+ registry.registerHealthCheck({
307
309
  name: config.healthCheckName ?? 'postgres',
308
310
  type: 'custom',
309
311
  interval: config.healthCheckInterval ?? 30000,
@@ -334,7 +336,7 @@ export function createPostgresPlugin(
334
336
  }
335
337
  },
336
338
 
337
- async onShutdown(): Promise<void> {
339
+ async onStop(): Promise<void> {
338
340
  const instance = instances.get(instanceName);
339
341
  if (instance) {
340
342
  await instance.close();
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Users Plugin Index
3
+ *
4
+ * User identity management plugin.
5
+ * For ban management, use the separate Bans Plugin which depends on this plugin.
6
+ *
7
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
8
+ */
9
+
10
+ // Main plugin
11
+ export {
12
+ createUsersPlugin,
13
+ getUserStore,
14
+ getUserById,
15
+ getUserByEmail,
16
+ findOrCreateUser,
17
+ } from './users-plugin.js';
18
+
19
+ // Types
20
+ export type {
21
+ UsersPluginConfig,
22
+ UserStore,
23
+ User,
24
+ CreateUserInput,
25
+ UpdateUserInput,
26
+ UserSearchParams,
27
+ UserListResponse,
28
+ PostgresUserStoreConfig,
29
+ UserSyncConfig,
30
+ UsersApiConfig,
31
+ UsersUiConfig,
32
+ } from './types.js';
33
+
34
+ // Stores
35
+ export { postgresUserStore } from './stores/index.js';
@@ -0,0 +1,7 @@
1
+ /**
2
+ * User Stores Index
3
+ *
4
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
5
+ */
6
+
7
+ export { postgresUserStore } from './postgres-store.js';