@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.
Files changed (335) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/README.md +13 -116
  3. package/dist/src/core/control-panel.d.ts.map +1 -1
  4. package/dist/src/core/control-panel.js +6 -4
  5. package/dist/src/core/control-panel.js.map +1 -1
  6. package/dist/src/core/gateway.d.ts.map +1 -1
  7. package/dist/src/core/gateway.js +24 -2
  8. package/dist/src/core/gateway.js.map +1 -1
  9. package/dist/src/core/plugin-registry.d.ts +15 -2
  10. package/dist/src/core/plugin-registry.d.ts.map +1 -1
  11. package/dist/src/core/plugin-registry.js.map +1 -1
  12. package/dist/src/index.d.ts +2 -2
  13. package/dist/src/index.d.ts.map +1 -1
  14. package/dist/src/index.js +9 -3
  15. package/dist/src/index.js.map +1 -1
  16. package/dist/src/plugins/api-keys/api-keys-plugin.d.ts +5 -2
  17. package/dist/src/plugins/api-keys/api-keys-plugin.d.ts.map +1 -1
  18. package/dist/src/plugins/api-keys/api-keys-plugin.js +61 -19
  19. package/dist/src/plugins/api-keys/api-keys-plugin.js.map +1 -1
  20. package/dist/src/plugins/api-keys/index.d.ts +0 -4
  21. package/dist/src/plugins/api-keys/index.d.ts.map +1 -1
  22. package/dist/src/plugins/api-keys/index.js +2 -3
  23. package/dist/src/plugins/api-keys/index.js.map +1 -1
  24. package/dist/src/plugins/api-keys/stores/postgres-store.d.ts.map +1 -1
  25. package/dist/src/plugins/api-keys/stores/postgres-store.js +29 -0
  26. package/dist/src/plugins/api-keys/stores/postgres-store.js.map +1 -1
  27. package/dist/src/plugins/api-keys/types.d.ts +9 -3
  28. package/dist/src/plugins/api-keys/types.d.ts.map +1 -1
  29. package/dist/src/plugins/api-keys/types.js.map +1 -1
  30. package/dist/src/plugins/auth/auth-plugin.d.ts.map +1 -1
  31. package/dist/src/plugins/auth/auth-plugin.js +4 -2
  32. package/dist/src/plugins/auth/auth-plugin.js.map +1 -1
  33. package/dist/src/plugins/auth/env-config.d.ts.map +1 -1
  34. package/dist/src/plugins/auth/env-config.js +1 -0
  35. package/dist/src/plugins/auth/env-config.js.map +1 -1
  36. package/dist/src/plugins/auth/index.d.ts +0 -4
  37. package/dist/src/plugins/auth/index.d.ts.map +1 -1
  38. package/dist/src/plugins/auth/index.js +2 -3
  39. package/dist/src/plugins/auth/index.js.map +1 -1
  40. package/dist/src/plugins/bans/bans-plugin.d.ts +5 -2
  41. package/dist/src/plugins/bans/bans-plugin.d.ts.map +1 -1
  42. package/dist/src/plugins/bans/bans-plugin.js +71 -25
  43. package/dist/src/plugins/bans/bans-plugin.js.map +1 -1
  44. package/dist/src/plugins/bans/index.d.ts +1 -5
  45. package/dist/src/plugins/bans/index.d.ts.map +1 -1
  46. package/dist/src/plugins/bans/index.js +3 -4
  47. package/dist/src/plugins/bans/index.js.map +1 -1
  48. package/dist/src/plugins/bans/stores/in-memory-store.d.ts +34 -0
  49. package/dist/src/plugins/bans/stores/in-memory-store.d.ts.map +1 -0
  50. package/dist/src/plugins/bans/stores/in-memory-store.js +97 -0
  51. package/dist/src/plugins/bans/stores/in-memory-store.js.map +1 -0
  52. package/dist/src/plugins/bans/stores/index.d.ts +1 -0
  53. package/dist/src/plugins/bans/stores/index.d.ts.map +1 -1
  54. package/dist/src/plugins/bans/stores/index.js +1 -0
  55. package/dist/src/plugins/bans/stores/index.js.map +1 -1
  56. package/dist/src/plugins/bans/types.d.ts +13 -6
  57. package/dist/src/plugins/bans/types.d.ts.map +1 -1
  58. package/dist/src/plugins/cache-plugin.d.ts +35 -16
  59. package/dist/src/plugins/cache-plugin.d.ts.map +1 -1
  60. package/dist/src/plugins/cache-plugin.js +299 -20
  61. package/dist/src/plugins/cache-plugin.js.map +1 -1
  62. package/dist/src/plugins/cms/cms-plugin.d.ts.map +1 -1
  63. package/dist/src/plugins/cms/cms-plugin.js +3 -1
  64. package/dist/src/plugins/cms/cms-plugin.js.map +1 -1
  65. package/dist/src/plugins/devices/devices-plugin.d.ts +5 -2
  66. package/dist/src/plugins/devices/devices-plugin.d.ts.map +1 -1
  67. package/dist/src/plugins/devices/devices-plugin.js +62 -26
  68. package/dist/src/plugins/devices/devices-plugin.js.map +1 -1
  69. package/dist/src/plugins/devices/index.d.ts +0 -4
  70. package/dist/src/plugins/devices/index.d.ts.map +1 -1
  71. package/dist/src/plugins/devices/index.js +2 -3
  72. package/dist/src/plugins/devices/index.js.map +1 -1
  73. package/dist/src/plugins/entitlements/entitlements-plugin.d.ts +5 -2
  74. package/dist/src/plugins/entitlements/entitlements-plugin.d.ts.map +1 -1
  75. package/dist/src/plugins/entitlements/entitlements-plugin.js +78 -41
  76. package/dist/src/plugins/entitlements/entitlements-plugin.js.map +1 -1
  77. package/dist/src/plugins/entitlements/index.d.ts +1 -5
  78. package/dist/src/plugins/entitlements/index.d.ts.map +1 -1
  79. package/dist/src/plugins/entitlements/index.js +3 -4
  80. package/dist/src/plugins/entitlements/index.js.map +1 -1
  81. package/dist/src/plugins/entitlements/sources/in-memory-source.d.ts +9 -0
  82. package/dist/src/plugins/entitlements/sources/in-memory-source.d.ts.map +1 -0
  83. package/dist/src/plugins/entitlements/sources/in-memory-source.js +65 -0
  84. package/dist/src/plugins/entitlements/sources/in-memory-source.js.map +1 -0
  85. package/dist/src/plugins/entitlements/sources/index.d.ts +1 -0
  86. package/dist/src/plugins/entitlements/sources/index.d.ts.map +1 -1
  87. package/dist/src/plugins/entitlements/sources/index.js +1 -0
  88. package/dist/src/plugins/entitlements/sources/index.js.map +1 -1
  89. package/dist/src/plugins/entitlements/types.d.ts +9 -2
  90. package/dist/src/plugins/entitlements/types.d.ts.map +1 -1
  91. package/dist/src/plugins/health-plugin.d.ts.map +1 -1
  92. package/dist/src/plugins/health-plugin.js +1 -0
  93. package/dist/src/plugins/health-plugin.js.map +1 -1
  94. package/dist/src/plugins/index.d.ts +4 -4
  95. package/dist/src/plugins/index.d.ts.map +1 -1
  96. package/dist/src/plugins/index.js +4 -4
  97. package/dist/src/plugins/index.js.map +1 -1
  98. package/dist/src/plugins/logs-plugin.d.ts.map +1 -1
  99. package/dist/src/plugins/logs-plugin.js +49 -1
  100. package/dist/src/plugins/logs-plugin.js.map +1 -1
  101. package/dist/src/plugins/maintenance-plugin.d.ts.map +1 -1
  102. package/dist/src/plugins/maintenance-plugin.js +39 -0
  103. package/dist/src/plugins/maintenance-plugin.js.map +1 -1
  104. package/dist/src/plugins/notifications/index.d.ts +0 -4
  105. package/dist/src/plugins/notifications/index.d.ts.map +1 -1
  106. package/dist/src/plugins/notifications/index.js +2 -3
  107. package/dist/src/plugins/notifications/index.js.map +1 -1
  108. package/dist/src/plugins/notifications/notifications-plugin.d.ts +5 -2
  109. package/dist/src/plugins/notifications/notifications-plugin.d.ts.map +1 -1
  110. package/dist/src/plugins/notifications/notifications-plugin.js +46 -13
  111. package/dist/src/plugins/notifications/notifications-plugin.js.map +1 -1
  112. package/dist/src/plugins/parental/index.d.ts +0 -4
  113. package/dist/src/plugins/parental/index.d.ts.map +1 -1
  114. package/dist/src/plugins/parental/index.js +2 -3
  115. package/dist/src/plugins/parental/index.js.map +1 -1
  116. package/dist/src/plugins/parental/parental-plugin.d.ts +5 -2
  117. package/dist/src/plugins/parental/parental-plugin.d.ts.map +1 -1
  118. package/dist/src/plugins/parental/parental-plugin.js +60 -24
  119. package/dist/src/plugins/parental/parental-plugin.js.map +1 -1
  120. package/dist/src/plugins/postgres-plugin.d.ts +3 -1
  121. package/dist/src/plugins/postgres-plugin.d.ts.map +1 -1
  122. package/dist/src/plugins/postgres-plugin.js +18 -8
  123. package/dist/src/plugins/postgres-plugin.js.map +1 -1
  124. package/dist/src/plugins/preferences/index.d.ts +0 -4
  125. package/dist/src/plugins/preferences/index.d.ts.map +1 -1
  126. package/dist/src/plugins/preferences/index.js +2 -3
  127. package/dist/src/plugins/preferences/index.js.map +1 -1
  128. package/dist/src/plugins/preferences/preferences-plugin.d.ts +5 -2
  129. package/dist/src/plugins/preferences/preferences-plugin.d.ts.map +1 -1
  130. package/dist/src/plugins/preferences/preferences-plugin.js +63 -19
  131. package/dist/src/plugins/preferences/preferences-plugin.js.map +1 -1
  132. package/dist/src/plugins/profiles/index.d.ts +0 -4
  133. package/dist/src/plugins/profiles/index.d.ts.map +1 -1
  134. package/dist/src/plugins/profiles/index.js +2 -3
  135. package/dist/src/plugins/profiles/index.js.map +1 -1
  136. package/dist/src/plugins/profiles/profiles-plugin.d.ts +5 -2
  137. package/dist/src/plugins/profiles/profiles-plugin.d.ts.map +1 -1
  138. package/dist/src/plugins/profiles/profiles-plugin.js +60 -26
  139. package/dist/src/plugins/profiles/profiles-plugin.js.map +1 -1
  140. package/dist/src/plugins/profiles/types.d.ts +9 -2
  141. package/dist/src/plugins/profiles/types.d.ts.map +1 -1
  142. package/dist/src/plugins/qwickbrain/index.d.ts +0 -4
  143. package/dist/src/plugins/qwickbrain/index.d.ts.map +1 -1
  144. package/dist/src/plugins/qwickbrain/index.js +2 -3
  145. package/dist/src/plugins/qwickbrain/index.js.map +1 -1
  146. package/dist/src/plugins/qwickbrain/qwickbrain-plugin.d.ts.map +1 -1
  147. package/dist/src/plugins/qwickbrain/qwickbrain-plugin.js +117 -0
  148. package/dist/src/plugins/qwickbrain/qwickbrain-plugin.js.map +1 -1
  149. package/dist/src/plugins/rate-limit/index.d.ts +0 -4
  150. package/dist/src/plugins/rate-limit/index.d.ts.map +1 -1
  151. package/dist/src/plugins/rate-limit/index.js +2 -3
  152. package/dist/src/plugins/rate-limit/index.js.map +1 -1
  153. package/dist/src/plugins/subscriptions/index.d.ts +0 -4
  154. package/dist/src/plugins/subscriptions/index.d.ts.map +1 -1
  155. package/dist/src/plugins/subscriptions/index.js +2 -3
  156. package/dist/src/plugins/subscriptions/index.js.map +1 -1
  157. package/dist/src/plugins/subscriptions/subscriptions-plugin.d.ts +5 -2
  158. package/dist/src/plugins/subscriptions/subscriptions-plugin.d.ts.map +1 -1
  159. package/dist/src/plugins/subscriptions/subscriptions-plugin.js +63 -29
  160. package/dist/src/plugins/subscriptions/subscriptions-plugin.js.map +1 -1
  161. package/dist/src/plugins/subscriptions/types.d.ts +8 -2
  162. package/dist/src/plugins/subscriptions/types.d.ts.map +1 -1
  163. package/dist/src/plugins/tenants/index.d.ts +1 -1
  164. package/dist/src/plugins/tenants/index.d.ts.map +1 -1
  165. package/dist/src/plugins/tenants/index.js +1 -1
  166. package/dist/src/plugins/tenants/index.js.map +1 -1
  167. package/dist/src/plugins/tenants/stores/in-memory-store.d.ts +59 -0
  168. package/dist/src/plugins/tenants/stores/in-memory-store.d.ts.map +1 -0
  169. package/dist/src/plugins/tenants/stores/in-memory-store.js +257 -0
  170. package/dist/src/plugins/tenants/stores/in-memory-store.js.map +1 -0
  171. package/dist/src/plugins/tenants/stores/index.d.ts +8 -0
  172. package/dist/src/plugins/tenants/stores/index.d.ts.map +1 -0
  173. package/dist/src/plugins/tenants/stores/index.js +8 -0
  174. package/dist/src/plugins/tenants/stores/index.js.map +1 -0
  175. package/dist/src/plugins/tenants/tenants-plugin.d.ts +5 -2
  176. package/dist/src/plugins/tenants/tenants-plugin.d.ts.map +1 -1
  177. package/dist/src/plugins/tenants/tenants-plugin.js +93 -60
  178. package/dist/src/plugins/tenants/tenants-plugin.js.map +1 -1
  179. package/dist/src/plugins/tenants/types.d.ts +8 -2
  180. package/dist/src/plugins/tenants/types.d.ts.map +1 -1
  181. package/dist/src/plugins/usage/index.d.ts +0 -4
  182. package/dist/src/plugins/usage/index.d.ts.map +1 -1
  183. package/dist/src/plugins/usage/index.js +2 -3
  184. package/dist/src/plugins/usage/index.js.map +1 -1
  185. package/dist/src/plugins/usage/usage-plugin.d.ts +5 -2
  186. package/dist/src/plugins/usage/usage-plugin.d.ts.map +1 -1
  187. package/dist/src/plugins/usage/usage-plugin.js +57 -23
  188. package/dist/src/plugins/usage/usage-plugin.js.map +1 -1
  189. package/dist/src/plugins/users/index.d.ts +1 -1
  190. package/dist/src/plugins/users/index.d.ts.map +1 -1
  191. package/dist/src/plugins/users/index.js +1 -1
  192. package/dist/src/plugins/users/index.js.map +1 -1
  193. package/dist/src/plugins/users/stores/in-memory-store.d.ts +36 -0
  194. package/dist/src/plugins/users/stores/in-memory-store.d.ts.map +1 -0
  195. package/dist/src/plugins/users/stores/in-memory-store.js +122 -0
  196. package/dist/src/plugins/users/stores/in-memory-store.js.map +1 -0
  197. package/dist/src/plugins/users/stores/index.d.ts +1 -0
  198. package/dist/src/plugins/users/stores/index.d.ts.map +1 -1
  199. package/dist/src/plugins/users/stores/index.js +1 -0
  200. package/dist/src/plugins/users/stores/index.js.map +1 -1
  201. package/dist/src/plugins/users/types.d.ts +7 -2
  202. package/dist/src/plugins/users/types.d.ts.map +1 -1
  203. package/dist/src/plugins/users/users-plugin.d.ts +5 -2
  204. package/dist/src/plugins/users/users-plugin.d.ts.map +1 -1
  205. package/dist/src/plugins/users/users-plugin.js +56 -23
  206. package/dist/src/plugins/users/users-plugin.js.map +1 -1
  207. package/dist/ui/src/api/controlPanelApi.d.ts +10 -1
  208. package/dist/ui/src/api/controlPanelApi.d.ts.map +1 -1
  209. package/dist/ui/src/api/controlPanelApi.js.map +1 -1
  210. package/dist/ui/src/dashboard/PluginWidgetRenderer.d.ts +3 -1
  211. package/dist/ui/src/dashboard/PluginWidgetRenderer.d.ts.map +1 -1
  212. package/dist/ui/src/dashboard/PluginWidgetRenderer.js +5 -1
  213. package/dist/ui/src/dashboard/PluginWidgetRenderer.js.map +1 -1
  214. package/dist/ui/src/dashboard/builtInWidgets.d.ts.map +1 -1
  215. package/dist/ui/src/dashboard/builtInWidgets.js +13 -1
  216. package/dist/ui/src/dashboard/builtInWidgets.js.map +1 -1
  217. package/dist/ui/src/dashboard/widgets/CacheMaintenanceWidget.d.ts +11 -0
  218. package/dist/ui/src/dashboard/widgets/CacheMaintenanceWidget.d.ts.map +1 -0
  219. package/dist/ui/src/dashboard/widgets/CacheMaintenanceWidget.js +77 -0
  220. package/dist/ui/src/dashboard/widgets/CacheMaintenanceWidget.js.map +1 -0
  221. package/dist/ui/src/dashboard/widgets/DatabaseOpsWidget.d.ts +10 -0
  222. package/dist/ui/src/dashboard/widgets/DatabaseOpsWidget.d.ts.map +1 -0
  223. package/dist/ui/src/dashboard/widgets/DatabaseOpsWidget.js +14 -0
  224. package/dist/ui/src/dashboard/widgets/DatabaseOpsWidget.js.map +1 -0
  225. package/dist/ui/src/dashboard/widgets/EnvironmentConfigWidget.d.ts +10 -0
  226. package/dist/ui/src/dashboard/widgets/EnvironmentConfigWidget.d.ts.map +1 -0
  227. package/dist/ui/src/dashboard/widgets/EnvironmentConfigWidget.js +14 -0
  228. package/dist/ui/src/dashboard/widgets/EnvironmentConfigWidget.js.map +1 -0
  229. package/dist/ui/src/dashboard/widgets/LogsMaintenanceWidget.d.ts +11 -0
  230. package/dist/ui/src/dashboard/widgets/LogsMaintenanceWidget.d.ts.map +1 -0
  231. package/dist/ui/src/dashboard/widgets/LogsMaintenanceWidget.js +96 -0
  232. package/dist/ui/src/dashboard/widgets/LogsMaintenanceWidget.js.map +1 -0
  233. package/dist/ui/src/dashboard/widgets/SeedManagementWidget.d.ts +10 -0
  234. package/dist/ui/src/dashboard/widgets/SeedManagementWidget.d.ts.map +1 -0
  235. package/dist/ui/src/dashboard/widgets/SeedManagementWidget.js +55 -0
  236. package/dist/ui/src/dashboard/widgets/SeedManagementWidget.js.map +1 -0
  237. package/dist/ui/src/dashboard/widgets/ServiceControlWidget.d.ts +10 -0
  238. package/dist/ui/src/dashboard/widgets/ServiceControlWidget.d.ts.map +1 -0
  239. package/dist/ui/src/dashboard/widgets/ServiceControlWidget.js +14 -0
  240. package/dist/ui/src/dashboard/widgets/ServiceControlWidget.js.map +1 -0
  241. package/dist/ui/src/dashboard/widgets/index.d.ts +6 -0
  242. package/dist/ui/src/dashboard/widgets/index.d.ts.map +1 -1
  243. package/dist/ui/src/dashboard/widgets/index.js +6 -0
  244. package/dist/ui/src/dashboard/widgets/index.js.map +1 -1
  245. package/dist/ui/src/pages/DashboardPage.js +1 -1
  246. package/dist/ui/src/pages/DashboardPage.js.map +1 -1
  247. package/dist-ui/assets/index-0gzisPdy.js +528 -0
  248. package/dist-ui/assets/{index-lm1yX6UD.js.map → index-0gzisPdy.js.map} +1 -1
  249. package/dist-ui/index.html +1 -1
  250. package/dist-ui-lib/index.js +3109 -2774
  251. package/dist-ui-lib/index.js.map +1 -1
  252. package/dist-ui-lib/src/api/controlPanelApi.d.ts +10 -1
  253. package/dist-ui-lib/src/dashboard/PluginWidgetRenderer.d.ts +3 -1
  254. package/dist-ui-lib/src/dashboard/widgets/CacheMaintenanceWidget.d.ts +10 -0
  255. package/dist-ui-lib/src/dashboard/widgets/DatabaseOpsWidget.d.ts +9 -0
  256. package/dist-ui-lib/src/dashboard/widgets/EnvironmentConfigWidget.d.ts +9 -0
  257. package/dist-ui-lib/src/dashboard/widgets/LogsMaintenanceWidget.d.ts +10 -0
  258. package/dist-ui-lib/src/dashboard/widgets/SeedManagementWidget.d.ts +9 -0
  259. package/dist-ui-lib/src/dashboard/widgets/ServiceControlWidget.d.ts +9 -0
  260. package/dist-ui-lib/src/dashboard/widgets/index.d.ts +6 -0
  261. package/package.json +12 -6
  262. package/src/core/control-panel.ts +6 -4
  263. package/src/core/gateway.ts +25 -2
  264. package/src/core/plugin-registry.ts +15 -2
  265. package/src/index.ts +53 -0
  266. package/src/plugins/api-keys/api-keys-plugin.ts +64 -20
  267. package/src/plugins/api-keys/index.ts +2 -5
  268. package/src/plugins/api-keys/stores/postgres-store.ts +30 -0
  269. package/src/plugins/api-keys/types.ts +9 -3
  270. package/src/plugins/auth/auth-plugin.ts +4 -2
  271. package/src/plugins/auth/env-config.ts +1 -0
  272. package/src/plugins/auth/index.ts +3 -5
  273. package/src/plugins/bans/bans-plugin.ts +71 -26
  274. package/src/plugins/bans/index.ts +4 -6
  275. package/src/plugins/bans/stores/in-memory-store.ts +106 -0
  276. package/src/plugins/bans/stores/index.ts +1 -0
  277. package/src/plugins/bans/types.ts +13 -6
  278. package/src/plugins/cache-plugin.test.ts +2 -2
  279. package/src/plugins/cache-plugin.ts +331 -30
  280. package/src/plugins/cms/cms-plugin.ts +3 -1
  281. package/src/plugins/devices/devices-plugin.ts +62 -27
  282. package/src/plugins/devices/index.ts +3 -5
  283. package/src/plugins/entitlements/entitlements-plugin.ts +81 -43
  284. package/src/plugins/entitlements/index.ts +4 -6
  285. package/src/plugins/entitlements/sources/in-memory-source.ts +76 -0
  286. package/src/plugins/entitlements/sources/index.ts +1 -0
  287. package/src/plugins/entitlements/types.ts +9 -2
  288. package/src/plugins/health-plugin.ts +1 -0
  289. package/src/plugins/index.ts +4 -1
  290. package/src/plugins/logs-plugin.ts +55 -1
  291. package/src/plugins/maintenance-plugin.ts +43 -0
  292. package/src/plugins/notifications/index.ts +3 -5
  293. package/src/plugins/notifications/notifications-plugin.ts +49 -19
  294. package/src/plugins/parental/index.ts +3 -5
  295. package/src/plugins/parental/parental-plugin.ts +63 -25
  296. package/src/plugins/postgres-plugin.test.ts +2 -2
  297. package/src/plugins/postgres-plugin.ts +20 -9
  298. package/src/plugins/preferences/index.ts +3 -5
  299. package/src/plugins/preferences/preferences-plugin.ts +66 -20
  300. package/src/plugins/profiles/index.ts +3 -5
  301. package/src/plugins/profiles/profiles-plugin.ts +60 -27
  302. package/src/plugins/profiles/types.ts +9 -2
  303. package/src/plugins/qwickbrain/index.ts +3 -5
  304. package/src/plugins/qwickbrain/qwickbrain-plugin.ts +135 -0
  305. package/src/plugins/rate-limit/index.ts +3 -5
  306. package/src/plugins/subscriptions/index.ts +3 -5
  307. package/src/plugins/subscriptions/subscriptions-plugin.ts +63 -30
  308. package/src/plugins/subscriptions/types.ts +8 -2
  309. package/src/plugins/tenants/index.ts +1 -1
  310. package/src/plugins/tenants/stores/in-memory-store.ts +335 -0
  311. package/src/plugins/tenants/stores/index.ts +13 -0
  312. package/src/plugins/tenants/tenants-plugin.ts +97 -62
  313. package/src/plugins/tenants/types.ts +8 -2
  314. package/src/plugins/usage/index.ts +3 -5
  315. package/src/plugins/usage/usage-plugin.ts +60 -26
  316. package/src/plugins/users/index.ts +1 -1
  317. package/src/plugins/users/stores/in-memory-store.ts +140 -0
  318. package/src/plugins/users/stores/index.ts +1 -0
  319. package/src/plugins/users/types.ts +7 -2
  320. package/src/plugins/users/users-plugin.ts +56 -24
  321. package/src/testing/index.ts +1 -0
  322. package/src/testing/pg-mem-pool.ts +33 -0
  323. package/ui/src/api/controlPanelApi.ts +10 -1
  324. package/ui/src/dashboard/PluginWidgetRenderer.tsx +8 -0
  325. package/ui/src/dashboard/builtInWidgets.tsx +19 -1
  326. package/ui/src/dashboard/widgets/CacheMaintenanceWidget.tsx +195 -0
  327. package/ui/src/dashboard/widgets/DatabaseOpsWidget.tsx +29 -0
  328. package/ui/src/dashboard/widgets/EnvironmentConfigWidget.tsx +29 -0
  329. package/ui/src/dashboard/widgets/LogsMaintenanceWidget.tsx +247 -0
  330. package/ui/src/dashboard/widgets/SeedManagementWidget.tsx +128 -0
  331. package/ui/src/dashboard/widgets/ServiceControlWidget.tsx +29 -0
  332. package/ui/src/dashboard/widgets/index.ts +6 -0
  333. package/ui/src/pages/DashboardPage.tsx +2 -2
  334. package/ui/src/pages/MaintenancePage.tsx +1 -1
  335. package/dist-ui/assets/index-lm1yX6UD.js +0 -528
@@ -17,6 +17,8 @@ import type {
17
17
  UsageStatus,
18
18
  UsageSummary,
19
19
  } from './types.js';
20
+ import { hasPostgres, getPostgres } from '../postgres-plugin.js';
21
+ import { postgresUsageStore } from './stores/index.js';
20
22
 
21
23
  // Import subscription helpers if available
22
24
  let getFeatureLimitFn: ((userId: string, featureCode: string) => Promise<number | null>) | null = null;
@@ -44,15 +46,18 @@ function getTomorrowMidnight(): Date {
44
46
  }
45
47
 
46
48
  /**
47
- * Create the Usage plugin
49
+ * Create the Usage plugin with smart defaults
50
+ *
51
+ * Config is optional - plugin will use defaults and get dependencies from registry.
52
+ * Gracefully handles missing dependencies with clear log messages.
48
53
  */
49
- export function createUsagePlugin(config: UsagePluginConfig): Plugin {
50
- const debug = config.debug || false;
51
- const apiPrefix = config.api?.prefix || '/'; // Framework adds /usage prefix automatically
52
-
53
- function log(message: string, data?: Record<string, unknown>) {
54
- if (debug) {
55
- console.log(`[UsagePlugin] ${message}`, data || '');
54
+ export function createUsagePlugin(config: Partial<UsagePluginConfig> = {}): Plugin {
55
+ function log(message: string, data?: Record<string, unknown>, isError = false) {
56
+ const prefix = '[UsagePlugin]';
57
+ if (isError) {
58
+ console.error(`${prefix} ${message}`, data || '');
59
+ } else if (config.debug) {
60
+ console.log(`${prefix} ${message}`, data || '');
56
61
  }
57
62
  }
58
63
 
@@ -62,15 +67,48 @@ export function createUsagePlugin(config: UsagePluginConfig): Plugin {
62
67
  version: '1.0.0',
63
68
 
64
69
  async onStart(_pluginConfig: PluginConfig, registry: PluginRegistry): Promise<void> {
70
+ const logger = registry.getLogger('usage');
71
+
72
+ // Check for postgres in registry
73
+ if (!hasPostgres()) {
74
+ logger.warn('No Database! Usage plugin disabled.');
75
+ registry.registerHealthCheck({
76
+ name: 'usage-store',
77
+ type: 'custom',
78
+ check: async () => ({
79
+ healthy: false,
80
+ details: {
81
+ error: 'PostgreSQL not available',
82
+ state: 'disabled',
83
+ },
84
+ }),
85
+ });
86
+ return;
87
+ }
88
+
89
+ // Smart defaults - get dependencies from registry
90
+ const store = config.store ?? postgresUsageStore({
91
+ pool: () => getPostgres().getPool(),
92
+ autoCreateTables: true,
93
+ });
94
+
95
+ const debug = config.debug ?? false;
96
+ const apiPrefix = config.api?.prefix ?? '/'; // Framework adds /usage prefix automatically
97
+ const apiEnabled = config.api?.enabled ?? true;
98
+ const dailyRetentionDays = config.cleanup?.dailyRetentionDays ?? 90;
99
+ const monthlyRetentionMonths = config.cleanup?.monthlyRetentionMonths ?? 24;
100
+ const runOnStartup = config.cleanup?.runOnStartup ?? false;
101
+ const cleanupIntervalHours = config.cleanup?.cleanupIntervalHours ?? 0;
102
+
65
103
  log('Starting usage plugin');
66
104
 
67
105
  // Initialize the store (creates tables if needed)
68
- await config.store.initialize();
106
+ await store.initialize();
69
107
  log('Usage plugin migrations complete');
70
108
 
71
109
  // Store references for helper access
72
- currentStore = config.store;
73
- currentConfig = config;
110
+ currentStore = store;
111
+ currentConfig = { ...config, store, debug };
74
112
 
75
113
  // Try to get the feature limit function from subscriptions plugin
76
114
  try {
@@ -96,25 +134,19 @@ export function createUsagePlugin(config: UsagePluginConfig): Plugin {
96
134
  });
97
135
 
98
136
  // Run cleanup on startup if configured
99
- if (config.cleanup?.runOnStartup) {
100
- const dailyDays = config.cleanup.dailyRetentionDays || 90;
101
- const monthlyMonths = config.cleanup.monthlyRetentionMonths || 24;
102
-
103
- const dailyDeleted = await config.store.cleanupOldDaily(dailyDays);
104
- const monthlyDeleted = await config.store.cleanupOldMonthly(monthlyMonths);
137
+ if (runOnStartup) {
138
+ const dailyDeleted = await store.cleanupOldDaily(dailyRetentionDays);
139
+ const monthlyDeleted = await store.cleanupOldMonthly(monthlyRetentionMonths);
105
140
  log('Startup cleanup complete', { dailyDeleted, monthlyDeleted });
106
141
  }
107
142
 
108
143
  // Set up periodic cleanup if configured
109
- if (config.cleanup?.cleanupIntervalHours && config.cleanup.cleanupIntervalHours > 0) {
110
- const intervalMs = config.cleanup.cleanupIntervalHours * 60 * 60 * 1000;
144
+ if (cleanupIntervalHours > 0) {
145
+ const intervalMs = cleanupIntervalHours * 60 * 60 * 1000;
111
146
  cleanupIntervalId = setInterval(async () => {
112
147
  try {
113
- const dailyDays = config.cleanup?.dailyRetentionDays || 90;
114
- const monthlyMonths = config.cleanup?.monthlyRetentionMonths || 24;
115
-
116
- const dailyDeleted = await config.store.cleanupOldDaily(dailyDays);
117
- const monthlyDeleted = await config.store.cleanupOldMonthly(monthlyMonths);
148
+ const dailyDeleted = await store.cleanupOldDaily(dailyRetentionDays);
149
+ const monthlyDeleted = await store.cleanupOldMonthly(monthlyRetentionMonths);
118
150
  log('Periodic cleanup complete', { dailyDeleted, monthlyDeleted });
119
151
  } catch (error) {
120
152
  console.error('[UsagePlugin] Cleanup error:', error);
@@ -123,7 +155,7 @@ export function createUsagePlugin(config: UsagePluginConfig): Plugin {
123
155
  }
124
156
 
125
157
  // Add API routes if enabled
126
- if (config.api?.enabled !== false) {
158
+ if (apiEnabled) {
127
159
  // Get daily usage summary
128
160
  registry.addRoute({
129
161
  method: 'get',
@@ -211,7 +243,9 @@ export function createUsagePlugin(config: UsagePluginConfig): Plugin {
211
243
  cleanupIntervalId = null;
212
244
  }
213
245
 
214
- await config.store.shutdown();
246
+ if (currentStore) {
247
+ await currentStore.shutdown();
248
+ }
215
249
  currentStore = null;
216
250
  currentConfig = null;
217
251
  log('Usage plugin stopped');
@@ -41,4 +41,4 @@ export type {
41
41
  } from './types.js';
42
42
 
43
43
  // Stores
44
- export { postgresUserStore } from './stores/index.js';
44
+ export { postgresUserStore, inMemoryUserStore } from './stores/index.js';
@@ -0,0 +1,140 @@
1
+ /**
2
+ * In-memory User Store for Demo/Testing
3
+ *
4
+ * Implements the UserStore interface with in-memory storage.
5
+ * Pre-populated with demo users for testing and showcase purposes.
6
+ */
7
+
8
+ export function createInMemoryUserStore() {
9
+ const users = new Map<string, any>();
10
+ let idCounter = 1;
11
+
12
+ // Pre-populate demo users
13
+ const demoUsers = [
14
+ { email: 'demo@example.com', name: 'Demo User' },
15
+ { email: 'pro@example.com', name: 'Pro User' },
16
+ { email: 'enterprise@example.com', name: 'Enterprise User' },
17
+ { email: 'basic@example.com', name: 'Basic User' },
18
+ ];
19
+
20
+ demoUsers.forEach((u) => {
21
+ const id = String(idCounter++);
22
+ users.set(id, {
23
+ id,
24
+ email: u.email,
25
+ name: u.name,
26
+ created_at: new Date(),
27
+ updated_at: new Date(),
28
+ });
29
+ });
30
+
31
+ return {
32
+ name: 'in-memory',
33
+
34
+ async initialize() {
35
+ console.log('[InMemoryUserStore] Initialized with demo users');
36
+ },
37
+
38
+ async getById(id: string) {
39
+ return users.get(id) || null;
40
+ },
41
+
42
+ async getByEmail(email: string) {
43
+ for (const user of users.values()) {
44
+ if (user.email === email.toLowerCase()) {
45
+ return user;
46
+ }
47
+ }
48
+ return null;
49
+ },
50
+
51
+ async getByExternalId(externalId: string, provider: string) {
52
+ for (const user of users.values()) {
53
+ if (user.external_id === externalId && user.provider === provider) {
54
+ return user;
55
+ }
56
+ }
57
+ return null;
58
+ },
59
+
60
+ async create(input: any) {
61
+ const id = String(idCounter++);
62
+ const user = {
63
+ id,
64
+ email: input.email.toLowerCase(),
65
+ name: input.name || null,
66
+ external_id: input.external_id,
67
+ provider: input.provider,
68
+ picture: input.picture,
69
+ created_at: new Date(),
70
+ updated_at: new Date(),
71
+ metadata: input.metadata || {},
72
+ };
73
+ users.set(id, user);
74
+ return user;
75
+ },
76
+
77
+ async update(id: string, input: any) {
78
+ const user = users.get(id);
79
+ if (!user) return null;
80
+ Object.assign(user, input, { updated_at: new Date() });
81
+ return user;
82
+ },
83
+
84
+ async delete(id: string) {
85
+ return users.delete(id);
86
+ },
87
+
88
+ async search(params: any = {}) {
89
+ let result = Array.from(users.values());
90
+
91
+ if (params.query) {
92
+ const query = params.query.toLowerCase();
93
+ result = result.filter(
94
+ (u) =>
95
+ u.email.toLowerCase().includes(query) ||
96
+ (u.name && u.name.toLowerCase().includes(query))
97
+ );
98
+ }
99
+
100
+ if (params.provider) {
101
+ result = result.filter((u) => u.provider === params.provider);
102
+ }
103
+
104
+ const sortBy = params.sortBy || 'created_at';
105
+ const sortOrder = params.sortOrder || 'desc';
106
+ result.sort((a, b) => {
107
+ const aVal = a[sortBy];
108
+ const bVal = b[sortBy];
109
+ if (aVal < bVal) return sortOrder === 'asc' ? -1 : 1;
110
+ if (aVal > bVal) return sortOrder === 'asc' ? 1 : -1;
111
+ return 0;
112
+ });
113
+
114
+ const total = result.length;
115
+ const page = params.page || 1;
116
+ const limit = params.limit || 20;
117
+ const offset = (page - 1) * limit;
118
+ result = result.slice(offset, offset + limit);
119
+
120
+ return {
121
+ users: result,
122
+ total,
123
+ page,
124
+ limit,
125
+ totalPages: Math.ceil(total / limit),
126
+ };
127
+ },
128
+
129
+ async updateLastLogin(id: string) {
130
+ const user = users.get(id);
131
+ if (user) {
132
+ user.last_login_at = new Date();
133
+ }
134
+ },
135
+
136
+ async shutdown() {
137
+ console.log('[InMemoryUserStore] Shutdown');
138
+ },
139
+ };
140
+ }
@@ -5,3 +5,4 @@
5
5
  */
6
6
 
7
7
  export { postgresUserStore } from './postgres-store.js';
8
+ export { createInMemoryUserStore as inMemoryUserStore } from './in-memory-store.js';
@@ -269,10 +269,15 @@ export interface UsersUiConfig {
269
269
 
270
270
  /**
271
271
  * Users plugin configuration
272
+ *
273
+ * All properties are optional - plugin will use smart defaults:
274
+ * - store: Postgres user store using registry's postgres instance
275
+ * - api.prefix: '/users'
276
+ * - debug: false
272
277
  */
273
278
  export interface UsersPluginConfig {
274
- /** User storage backend */
275
- store: UserStore;
279
+ /** User storage backend (default: postgres user store from registry) */
280
+ store?: UserStore;
276
281
  /** Sync configuration (optional) */
277
282
  sync?: UserSyncConfig;
278
283
  /** API configuration */
@@ -30,22 +30,26 @@ import { getEntitlements } from '../entitlements/entitlements-plugin.js';
30
30
  import { getPreferences } from '../preferences/preferences-plugin.js';
31
31
  import { getActiveBan } from '../bans/bans-plugin.js';
32
32
  import { autoCreateUserTenant } from '../tenants/index.js';
33
+ import { hasPostgres, getPostgres } from '../postgres-plugin.js';
34
+ import { postgresUserStore } from './stores/index.js';
33
35
 
34
36
  // Store instance for helper access
35
37
  let currentStore: UserStore | null = null;
36
38
  let currentRegistry: PluginRegistry | null = null;
37
39
 
38
40
  /**
39
- * Create the Users plugin
41
+ * Create the Users plugin with smart defaults
42
+ *
43
+ * Config is optional - plugin will use defaults and get dependencies from registry.
44
+ * Gracefully handles missing dependencies with clear log messages.
40
45
  */
41
- export function createUsersPlugin(config: UsersPluginConfig): Plugin {
42
- const debug = config.debug || false;
43
- // Routes are mounted under /api by the control panel, so don't include /api in prefix
44
- const apiPrefix = config.api?.prefix || '/'; // Framework adds /users prefix automatically
45
-
46
- function log(message: string, data?: Record<string, unknown>) {
47
- if (debug) {
48
- console.log(`[UsersPlugin] ${message}`, data || '');
46
+ export function createUsersPlugin(config: Partial<UsersPluginConfig> = {}): Plugin {
47
+ function log(message: string, data?: Record<string, unknown>, isError = false) {
48
+ const prefix = '[UsersPlugin]';
49
+ if (isError) {
50
+ console.error(`${prefix} ${message}`, data || '');
51
+ } else if (config.debug) {
52
+ console.log(`${prefix} ${message}`, data || '');
49
53
  }
50
54
  }
51
55
 
@@ -55,14 +59,42 @@ export function createUsersPlugin(config: UsersPluginConfig): Plugin {
55
59
  version: '1.0.0',
56
60
 
57
61
  async onStart(_pluginConfig: PluginConfig, registry: PluginRegistry): Promise<void> {
62
+ const logger = registry.getLogger('users');
63
+
64
+ // Check for postgres in registry
65
+ if (!hasPostgres()) {
66
+ logger.warn('No Database! Users plugin disabled.');
67
+ registry.registerHealthCheck({
68
+ name: 'users-store',
69
+ type: 'custom',
70
+ check: async () => ({
71
+ healthy: false,
72
+ details: {
73
+ error: 'PostgreSQL not available',
74
+ state: 'disabled',
75
+ },
76
+ }),
77
+ });
78
+ return;
79
+ }
80
+
81
+ // Smart defaults - get dependencies from registry
82
+ const store = config.store ?? postgresUserStore({
83
+ pool: () => getPostgres().getPool(),
84
+ autoCreateTables: true,
85
+ });
86
+
87
+ const debug = config.debug ?? false;
88
+ const apiPrefix = config.api?.prefix ?? '/users';
89
+
58
90
  log('Starting users plugin');
59
91
 
60
92
  // Initialize the store (creates tables if needed)
61
- await config.store.initialize();
93
+ await store.initialize();
62
94
  log('Users plugin migrations complete');
63
95
 
64
96
  // Store references for helper access
65
- currentStore = config.store;
97
+ currentStore = store;
66
98
  currentRegistry = registry;
67
99
 
68
100
  // Register health check
@@ -72,7 +104,7 @@ export function createUsersPlugin(config: UsersPluginConfig): Plugin {
72
104
  check: async () => {
73
105
  try {
74
106
  // Simple health check - try to search with limit 1
75
- await config.store.search({ limit: 1 });
107
+ await store.search({ limit: 1 });
76
108
  return { healthy: true };
77
109
  } catch {
78
110
  return { healthy: false };
@@ -98,7 +130,7 @@ export function createUsersPlugin(config: UsersPluginConfig): Plugin {
98
130
  sortOrder: (req.query.sortOrder as UserSearchParams['sortOrder']) || 'desc',
99
131
  };
100
132
 
101
- const result = await config.store.search(params);
133
+ const result = await store.search(params);
102
134
  res.json(result);
103
135
  } catch (error) {
104
136
  console.error('[UsersPlugin] Search error:', error);
@@ -114,7 +146,7 @@ export function createUsersPlugin(config: UsersPluginConfig): Plugin {
114
146
  pluginId: 'users',
115
147
  handler: async (req: Request, res: Response) => {
116
148
  try {
117
- const user = await config.store.getById(req.params.id);
149
+ const user = await store.getById(req.params.id);
118
150
  if (!user) {
119
151
  return res.status(404).json({ error: 'User not found' });
120
152
  }
@@ -147,12 +179,12 @@ export function createUsersPlugin(config: UsersPluginConfig): Plugin {
147
179
  }
148
180
 
149
181
  // Check if user already exists
150
- const existing = await config.store.getByEmail(input.email);
182
+ const existing = await store.getByEmail(input.email);
151
183
  if (existing) {
152
184
  return res.status(409).json({ error: 'User with this email already exists' });
153
185
  }
154
186
 
155
- const user = await config.store.create(input);
187
+ const user = await store.create(input);
156
188
 
157
189
  // Auto-create personal tenant if tenants plugin available
158
190
  if (registry.hasPlugin('tenants')) {
@@ -187,7 +219,7 @@ export function createUsersPlugin(config: UsersPluginConfig): Plugin {
187
219
  }
188
220
 
189
221
  // Check if user already exists
190
- const existing = await config.store.getByEmail(email);
222
+ const existing = await store.getByEmail(email);
191
223
  if (existing) {
192
224
  return res.status(409).json({ error: 'User with this email already exists' });
193
225
  }
@@ -200,7 +232,7 @@ export function createUsersPlugin(config: UsersPluginConfig): Plugin {
200
232
  expiresAt.setDate(expiresAt.getDate() + 7);
201
233
 
202
234
  // Create user with invited status
203
- const user = await config.store.create({
235
+ const user = await store.create({
204
236
  email,
205
237
  name,
206
238
  metadata: role ? { role } : undefined,
@@ -251,7 +283,7 @@ export function createUsersPlugin(config: UsersPluginConfig): Plugin {
251
283
  return res.status(400).json({ error: 'Invitation token is required' });
252
284
  }
253
285
 
254
- const user = await config.store.acceptInvitation(token);
286
+ const user = await store.acceptInvitation(token);
255
287
 
256
288
  if (!user) {
257
289
  return res.status(404).json({
@@ -290,7 +322,7 @@ export function createUsersPlugin(config: UsersPluginConfig): Plugin {
290
322
  metadata: req.body.metadata,
291
323
  };
292
324
 
293
- const user = await config.store.update(req.params.id, input);
325
+ const user = await store.update(req.params.id, input);
294
326
  if (!user) {
295
327
  return res.status(404).json({ error: 'User not found' });
296
328
  }
@@ -309,7 +341,7 @@ export function createUsersPlugin(config: UsersPluginConfig): Plugin {
309
341
  pluginId: 'users',
310
342
  handler: async (req: Request, res: Response) => {
311
343
  try {
312
- const deleted = await config.store.delete(req.params.id);
344
+ const deleted = await store.delete(req.params.id);
313
345
  if (!deleted) {
314
346
  return res.status(404).json({ error: 'User not found' });
315
347
  }
@@ -328,7 +360,7 @@ export function createUsersPlugin(config: UsersPluginConfig): Plugin {
328
360
  pluginId: 'users',
329
361
  handler: async (req: Request, res: Response) => {
330
362
  try {
331
- const user = await config.store.getById(req.params.id);
363
+ const user = await store.getById(req.params.id);
332
364
  if (!user) {
333
365
  return res.status(404).json({ error: 'User not found' });
334
366
  }
@@ -391,7 +423,7 @@ export function createUsersPlugin(config: UsersPluginConfig): Plugin {
391
423
  pluginId: 'users',
392
424
  handler: async (_req: Request, res: Response) => {
393
425
  try {
394
- const allUsers = await config.store.search({ limit: 10000 });
426
+ const allUsers = await store.search({ limit: 10000 });
395
427
  const now = Date.now();
396
428
  const sevenDaysAgo = now - 7 * 24 * 60 * 60 * 1000;
397
429
 
@@ -419,7 +451,7 @@ export function createUsersPlugin(config: UsersPluginConfig): Plugin {
419
451
 
420
452
  async onStop(): Promise<void> {
421
453
  log('Stopping users plugin');
422
- await config.store.shutdown();
454
+ if (currentStore) { await currentStore.shutdown(); };
423
455
  currentStore = null;
424
456
  currentRegistry = null;
425
457
  log('Users plugin stopped');
@@ -0,0 +1 @@
1
+ export { createPgMemPool } from './pg-mem-pool.js';
@@ -0,0 +1,33 @@
1
+ /**
2
+ * pg-mem Pool Adapter
3
+ *
4
+ * Provides a pg.Pool-compatible interface for pg-mem (in-memory PostgreSQL).
5
+ * Used by demos to run without requiring an actual PostgreSQL installation.
6
+ *
7
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
8
+ */
9
+
10
+ import { newDb } from 'pg-mem';
11
+
12
+ /**
13
+ * Create an in-memory PostgreSQL database with a Pool-compatible interface
14
+ *
15
+ * @returns Pool-compatible interface backed by pg-mem
16
+ */
17
+ export function createPgMemPool() {
18
+ const db = newDb();
19
+
20
+ // Get the Pool-compatible adapter from pg-mem
21
+ const { Pool } = db.adapters.createPg();
22
+ const pool = new Pool();
23
+
24
+ // Add a fake connection string for plugins that need it (like notifications)
25
+ // pg-mem doesn't use connection strings, but some plugins try to extract it
26
+ (pool as any).options = {
27
+ connectionString: 'postgresql://localhost/pgmem',
28
+ };
29
+
30
+ console.log('[pg-mem] In-memory PostgreSQL database created');
31
+
32
+ return pool;
33
+ }
@@ -304,9 +304,18 @@ export interface WidgetContribution {
304
304
  title: string;
305
305
  /** Component name to render (matched by frontend widget registry) */
306
306
  component: string;
307
+ /**
308
+ * Widget type/category - determines which page(s) can display this widget
309
+ * - 'status': System health, service status, monitoring metrics (Dashboard)
310
+ * - 'maintenance': Operational tasks like seeding, service control, config (Maintenance page)
311
+ * - 'analytics': Charts, graphs, usage metrics (Dashboard or Analytics page)
312
+ * - 'monitoring': Performance, logs, real-time data (Monitoring page)
313
+ * - 'custom': Custom widgets for specific use cases
314
+ */
315
+ type: 'status' | 'maintenance' | 'analytics' | 'monitoring' | 'custom';
307
316
  /** Priority for ordering (lower = first, default: 100) */
308
317
  priority?: number;
309
- /** Whether this widget is shown by default */
318
+ /** Whether this widget is shown by default on its designated page */
310
319
  showByDefault?: boolean;
311
320
  pluginId: string;
312
321
  }
@@ -19,12 +19,15 @@ interface WidgetContribution {
19
19
  id: string;
20
20
  title: string;
21
21
  component: string;
22
+ type: 'status' | 'maintenance' | 'analytics' | 'monitoring' | 'custom';
22
23
  priority?: number;
23
24
  showByDefault?: boolean;
24
25
  pluginId: string;
25
26
  }
26
27
 
27
28
  interface PluginWidgetRendererProps {
29
+ /** Filter widgets by type (e.g., 'status' for dashboard, 'maintenance' for maintenance page) */
30
+ widgetType?: 'status' | 'maintenance' | 'analytics' | 'monitoring' | 'custom';
28
31
  /** Only show widgets marked as showByDefault (default: true) */
29
32
  defaultOnly?: boolean;
30
33
  /** Additional widget IDs to show (beyond showByDefault) */
@@ -35,6 +38,7 @@ interface PluginWidgetRendererProps {
35
38
  * Renders widgets from plugins that have registered them via the server API
36
39
  */
37
40
  export function PluginWidgetRenderer({
41
+ widgetType,
38
42
  defaultOnly = true,
39
43
  additionalWidgetIds = [],
40
44
  }: PluginWidgetRendererProps) {
@@ -78,6 +82,10 @@ export function PluginWidgetRenderer({
78
82
  // Filter widgets to show
79
83
  const visibleWidgets = widgets
80
84
  .filter(widget => {
85
+ // Filter by widget type if specified
86
+ if (widgetType && widget.type !== widgetType) {
87
+ return false;
88
+ }
81
89
  // Show if marked as default, or if in additionalWidgetIds
82
90
  if (defaultOnly) {
83
91
  return widget.showByDefault || additionalWidgetIds.includes(widget.id);
@@ -16,7 +16,13 @@ import {
16
16
  AuthStatusWidget,
17
17
  NotificationsStatsWidget,
18
18
  CMSStatusWidget,
19
- CMSMaintenanceWidget
19
+ CMSMaintenanceWidget,
20
+ SeedManagementWidget,
21
+ ServiceControlWidget,
22
+ EnvironmentConfigWidget,
23
+ DatabaseOpsWidget,
24
+ LogsMaintenanceWidget,
25
+ CacheMaintenanceWidget,
20
26
  } from './widgets';
21
27
  import { PreferencesPage } from '../pages/PreferencesPage';
22
28
  import type { WidgetComponent } from './WidgetComponentRegistry';
@@ -32,6 +38,12 @@ export const builtInWidgetComponents: Record<string, React.ComponentType> = {
32
38
  NotificationsStatsWidget: NotificationsStatsWidget,
33
39
  CMSStatusWidget: CMSStatusWidget,
34
40
  CMSMaintenanceWidget: CMSMaintenanceWidget,
41
+ SeedManagementWidget: SeedManagementWidget,
42
+ ServiceControlWidget: ServiceControlWidget,
43
+ EnvironmentConfigWidget: EnvironmentConfigWidget,
44
+ DatabaseOpsWidget: DatabaseOpsWidget,
45
+ LogsMaintenanceWidget: LogsMaintenanceWidget,
46
+ CacheMaintenanceWidget: CacheMaintenanceWidget,
35
47
  PreferencesPage: PreferencesPage,
36
48
  };
37
49
 
@@ -50,6 +62,12 @@ export function getBuiltInWidgetComponents(): WidgetComponent[] {
50
62
  { name: 'NotificationsStatsWidget', component: NotificationsStatsWidget },
51
63
  { name: 'CMSStatusWidget', component: CMSStatusWidget },
52
64
  { name: 'CMSMaintenanceWidget', component: CMSMaintenanceWidget },
65
+ { name: 'SeedManagementWidget', component: SeedManagementWidget },
66
+ { name: 'ServiceControlWidget', component: ServiceControlWidget },
67
+ { name: 'EnvironmentConfigWidget', component: EnvironmentConfigWidget },
68
+ { name: 'DatabaseOpsWidget', component: DatabaseOpsWidget },
69
+ { name: 'LogsMaintenanceWidget', component: LogsMaintenanceWidget },
70
+ { name: 'CacheMaintenanceWidget', component: CacheMaintenanceWidget },
53
71
  { name: 'PreferencesPage', component: PreferencesPage },
54
72
  ];
55
73
  }