@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
@@ -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 { DevicesStatusWidget } from './DevicesStatusWidget.js';
73
- export type { DevicesStatusWidgetProps } from './DevicesStatusWidget.js';
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
- const debug = config.debug || false;
42
- // Routes are mounted under /api by the control panel, so don't include /api in prefix
43
- const apiPrefix = config.api?.prefix || ''; // Framework adds /entitlements prefix automatically (empty string to avoid double slash)
44
- const apiEnabled = config.api?.enabled !== false;
45
- const enableWriteApi = config.api?.enableWrite !== false;
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 config.source.initialize();
69
- primarySource = config.source;
70
- log('Primary source initialized', { source: config.source.name });
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 source of additionalSources) {
75
- await source.initialize();
76
- log('Additional source initialized', { source: source.name });
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
- try {
86
- const instanceName = config.cache?.instanceName || 'default';
87
- cacheInstance = getCache(instanceName);
88
- cacheKeyPrefix = config.cache?.keyPrefix || 'entitlements:';
89
- cacheTtl = config.cache?.ttl || 300;
90
- cacheMappingTtl = config.cache?.mappingTtl || cacheTtl * 2;
91
- log('Cache configured', { instanceName, prefix: cacheKeyPrefix, ttl: cacheTtl });
92
- } catch {
93
- log('Cache not available, running without caching');
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 (config.source.isHealthy) {
108
- const healthy = await config.source.isHealthy();
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: config.source.name,
149
- description: config.source.description,
150
- readonly: config.source.readonly ?? false,
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: config.source.readonly ?? false,
163
- writeEnabled: enableWriteApi && !config.source.readonly,
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 && !config.source.readonly) {
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 { EntitlementsStatusWidget } from './EntitlementsStatusWidget.js';
55
- export type { EntitlementsStatusWidgetProps } from './EntitlementsStatusWidget.js';
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
+ }
@@ -7,3 +7,4 @@
7
7
  */
8
8
 
9
9
  export { postgresEntitlementSource } from './postgres-source.js';
10
+ export { createInMemoryEntitlementSource as inMemoryEntitlementSource } from './in-memory-source.js';
@@ -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: EntitlementSource;
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[];
@@ -39,6 +39,7 @@ export function createHealthPlugin(config: HealthPluginConfig): Plugin {
39
39
  id: 'service-health',
40
40
  title: 'Service Health',
41
41
  component: 'ServiceHealthWidget',
42
+ type: 'status',
42
43
  priority: 10,
43
44
  showByDefault: true,
44
45
  pluginId: 'health',
@@ -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 { NotificationsStatusWidget } from './NotificationsStatusWidget.js';
95
- export { NotificationsManagementPage } from './NotificationsManagementPage.js';
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
- throw new Error(
133
- 'Notifications plugin requires postgres plugin. ' +
134
- 'Please add createPostgresPlugin() before createNotificationsPlugin().'
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
- throw new Error(
154
- 'Could not determine PostgreSQL connection string. ' +
155
- 'Ensure DATABASE_URL is set or postgres plugin was configured with a URL.'
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: config.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
- config.channels,
168
- config,
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: config.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: config.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 { ParentalStatusWidget } from './ParentalStatusWidget.js';
59
- export type { ParentalStatusWidgetProps } from './ParentalStatusWidget.js';
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
+