@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
@@ -24,6 +24,9 @@ import type {
24
24
  CreateRestrictionInput,
25
25
  LogActivityInput,
26
26
  } from './types.js';
27
+ import { hasPostgres, getPostgres } from '../postgres-plugin.js';
28
+ import { postgresParentalStore } from './stores/index.js';
29
+ import { kidsAdapter } from './adapters/index.js';
27
30
 
28
31
  // Store instances for helper access
29
32
  let currentStore: ParentalStore | null = null;
@@ -54,17 +57,18 @@ function isWithinSchedule(schedule: Record<string, { start: string; end: string
54
57
  }
55
58
 
56
59
  /**
57
- * Create the Parental plugin
60
+ * Create the Parental plugin with smart defaults
61
+ *
62
+ * Config is optional - plugin will use defaults and get dependencies from registry.
63
+ * Gracefully handles missing dependencies with clear log messages.
58
64
  */
59
- export function createParentalPlugin(config: ParentalPluginConfig): Plugin {
60
- const debug = config.debug || false;
61
- const apiPrefix = config.api?.prefix || '/'; // Framework adds /parental prefix automatically
62
- const maxPinAttempts = config.maxPinAttempts || 5;
63
- const pinLockoutMinutes = config.pinLockoutMinutes || 30;
64
-
65
- function log(message: string, data?: Record<string, unknown>) {
66
- if (debug) {
67
- console.log(`[ParentalPlugin] ${message}`, data || '');
65
+ export function createParentalPlugin(config: Partial<ParentalPluginConfig> = {}): Plugin {
66
+ function log(message: string, data?: Record<string, unknown>, isError = false) {
67
+ const prefix = '[ParentalPlugin]';
68
+ if (isError) {
69
+ console.error(`${prefix} ${message}`, data || '');
70
+ } else if (config.debug) {
71
+ console.log(`${prefix} ${message}`, data || '');
68
72
  }
69
73
  }
70
74
 
@@ -74,16 +78,48 @@ export function createParentalPlugin(config: ParentalPluginConfig): Plugin {
74
78
  version: '1.0.0',
75
79
 
76
80
  async onStart(_pluginConfig: PluginConfig, registry: PluginRegistry): Promise<void> {
81
+ const logger = registry.getLogger('parental');
82
+
83
+ // Check for postgres in registry
84
+ if (!hasPostgres()) {
85
+ logger.warn('No Database! Parental plugin disabled.');
86
+ registry.registerHealthCheck({
87
+ name: 'parental-store',
88
+ type: 'custom',
89
+ check: async () => ({
90
+ healthy: false,
91
+ details: {
92
+ error: 'PostgreSQL not available',
93
+ state: 'disabled',
94
+ },
95
+ }),
96
+ });
97
+ return;
98
+ }
99
+
100
+ // Smart defaults - get dependencies from registry
101
+ const store = config.store ?? postgresParentalStore({
102
+ pool: () => getPostgres().getPool(),
103
+ autoCreateTables: true,
104
+ });
105
+
106
+ const adapter = config.adapter ?? kidsAdapter();
107
+ const debug = config.debug ?? false;
108
+ const apiPrefix = config.api?.prefix ?? '/'; // Framework adds /parental prefix automatically
109
+ const apiEnabled = config.api?.enabled ?? true;
110
+ const maxPinAttempts = config.maxPinAttempts ?? 5;
111
+ const pinLockoutMinutes = config.pinLockoutMinutes ?? 30;
112
+
77
113
  log('Starting parental plugin');
78
114
 
79
115
  // Initialize the store (creates tables if needed)
80
- await config.store.initialize();
116
+ await store.initialize();
81
117
  log('Parental store initialized');
82
118
 
83
119
  // Store references for helper access
84
- currentStore = config.store;
85
- currentAdapter = config.adapter;
86
- currentConfig = config;
120
+ currentStore = store;
121
+ currentAdapter = adapter;
122
+ currentConfig = { ...config, store, adapter, debug, maxPinAttempts, pinLockoutMinutes };
87
123
 
88
124
  // Register health check
89
125
  registry.registerHealthCheck({
@@ -99,7 +135,7 @@ export function createParentalPlugin(config: ParentalPluginConfig): Plugin {
99
135
  });
100
136
 
101
137
  // Add API routes if enabled
102
- if (config.api?.enabled !== false) {
138
+ if (apiEnabled) {
103
139
  // ═══════════════════════════════════════════════════════════════════════
104
140
  // Guardian Settings Routes
105
141
  // ═══════════════════════════════════════════════════════════════════════
@@ -140,7 +176,7 @@ export function createParentalPlugin(config: ParentalPluginConfig): Plugin {
140
176
  // Hash PIN if provided
141
177
  const processedInput = {
142
178
  ...input,
143
- adapter_type: config.adapter.name,
179
+ adapter_type: adapter.name,
144
180
  pin: input.pin ? hashPin(input.pin) : undefined,
145
181
  };
146
182
 
@@ -290,8 +326,8 @@ export function createParentalPlugin(config: ParentalPluginConfig): Plugin {
290
326
  const input = req.body as CreateRestrictionInput;
291
327
 
292
328
  // Validate with adapter
293
- if (config.adapter.validateRestriction) {
294
- const validation = config.adapter.validateRestriction(input);
329
+ if (adapter.validateRestriction) {
330
+ const validation = adapter.validateRestriction(input);
295
331
  if (!validation.valid) {
296
332
  return res.status(400).json({ error: 'Invalid restriction', errors: validation.errors });
297
333
  }
@@ -416,7 +452,7 @@ export function createParentalPlugin(config: ParentalPluginConfig): Plugin {
416
452
  const input = req.body as LogActivityInput;
417
453
  const activity = await logActivity({
418
454
  ...input,
419
- adapter_type: config.adapter.name,
455
+ adapter_type: adapter.name,
420
456
  });
421
457
  res.status(201).json(activity);
422
458
  } catch (error) {
@@ -441,10 +477,10 @@ export function createParentalPlugin(config: ParentalPluginConfig): Plugin {
441
477
 
442
478
  // Format details with adapter if available
443
479
  const formattedActivities = activities.map((activity) => {
444
- if (config.adapter.formatActivityDetails) {
480
+ if (adapter.formatActivityDetails) {
445
481
  return {
446
482
  ...activity,
447
- formatted_details: config.adapter.formatActivityDetails(activity),
483
+ formatted_details: adapter.formatActivityDetails(activity),
448
484
  };
449
485
  }
450
486
  return activity;
@@ -466,9 +502,9 @@ export function createParentalPlugin(config: ParentalPluginConfig): Plugin {
466
502
  handler: async (_req: Request, res: Response) => {
467
503
  try {
468
504
  res.json({
469
- name: config.adapter.name,
470
- activity_types: config.adapter.getActivityTypes(),
471
- default_daily_limit: config.adapter.getDefaultDailyLimit(),
505
+ name: adapter.name,
506
+ activity_types: adapter.getActivityTypes(),
507
+ default_daily_limit: adapter.getDefaultDailyLimit(),
472
508
  });
473
509
  } catch (error) {
474
510
  console.error('[ParentalPlugin] Get adapter info error:', error);
@@ -483,7 +519,9 @@ export function createParentalPlugin(config: ParentalPluginConfig): Plugin {
483
519
 
484
520
  async onStop(): Promise<void> {
485
521
  log('Stopping parental plugin');
486
- await config.store.shutdown();
522
+ if (currentStore) {
523
+ await currentStore.shutdown();
524
+ }
487
525
  currentStore = null;
488
526
  currentAdapter = null;
489
527
  currentConfig = null;
@@ -118,12 +118,12 @@ describe('PostgreSQL Plugin', () => {
118
118
  expect(hasPostgres('test')).toBe(true);
119
119
  });
120
120
 
121
- it('should log debug message on successful connection', async () => {
121
+ it('should log info message on successful connection', async () => {
122
122
  const plugin = createPostgresPlugin(mockConfig, 'test');
123
123
  await plugin.onStart({}, mockRegistry);
124
124
 
125
125
  const logger = mockRegistry.getLogger('postgres:test');
126
- expect(logger.debug).toHaveBeenCalledWith(
126
+ expect(logger.info).toHaveBeenCalledWith(
127
127
  expect.stringContaining('connected')
128
128
  );
129
129
  });
@@ -56,7 +56,10 @@ const { Pool } = pg;
56
56
  */
57
57
  export interface PostgresPluginConfig {
58
58
  /** Database connection URL (e.g., postgresql://user:pass@host:5432/db) */
59
- url: string;
59
+ url?: string;
60
+
61
+ /** Pre-configured pg.Pool instance (alternative to url) */
62
+ pool?: pg.Pool;
60
63
 
61
64
  /** Maximum number of clients in the pool (default: 20) */
62
65
  maxConnections?: number;
@@ -193,14 +196,22 @@ export function createPostgresPlugin(
193
196
 
194
197
  const createInstance = (): PostgresInstance => {
195
198
  if (!pool) {
196
- pool = new Pool({
197
- connectionString: config.url,
198
- max: config.maxConnections ?? 20,
199
- min: config.minConnections ?? 2,
200
- idleTimeoutMillis: config.idleTimeoutMs ?? 30000,
201
- connectionTimeoutMillis: config.connectionTimeoutMs ?? 5000,
202
- statement_timeout: config.statementTimeoutMs,
203
- });
199
+ if (config.pool) {
200
+ // Use pre-configured pool (e.g., pg-mem for testing)
201
+ pool = config.pool;
202
+ } else if (config.url) {
203
+ // Create pool from URL
204
+ pool = new Pool({
205
+ connectionString: config.url,
206
+ max: config.maxConnections ?? 20,
207
+ min: config.minConnections ?? 2,
208
+ idleTimeoutMillis: config.idleTimeoutMs ?? 30000,
209
+ connectionTimeoutMillis: config.connectionTimeoutMs ?? 5000,
210
+ statement_timeout: config.statementTimeoutMs,
211
+ });
212
+ } else {
213
+ throw new Error('PostgresPluginConfig must have either url or pool');
214
+ }
204
215
 
205
216
  // Handle pool errors
206
217
  pool.on('error', (err) => {
@@ -29,8 +29,6 @@ export type {
29
29
  // Stores
30
30
  export { postgresPreferencesStore, deepMerge } from './stores/index.js';
31
31
 
32
- // UI Components
33
- export { PreferencesStatusWidget } from './PreferencesStatusWidget.js';
34
- export type { PreferencesStatusWidgetProps } from './PreferencesStatusWidget.js';
35
- export { PreferencesManagementPage } from './PreferencesManagementPage.js';
36
- export type { PreferencesManagementPageProps } from './PreferencesManagementPage.js';
32
+ // UI Components are exported from main package index (@qwickapps/server)
33
+ // Do NOT export here to avoid loading UI dependencies when importing plugins
34
+
@@ -16,8 +16,9 @@ import type {
16
16
  PreferencesStore,
17
17
  } from './types.js';
18
18
  import type { AuthenticatedRequest } from '../auth/types.js';
19
- import { deepMerge } from './stores/postgres-store.js';
19
+ import { deepMerge, postgresPreferencesStore } from './stores/postgres-store.js';
20
20
  import { MAX_PREFERENCES_SIZE, MAX_NESTING_DEPTH } from './types.js';
21
+ import { hasPostgres, getPostgres } from '../postgres-plugin.js';
21
22
 
22
23
  /**
23
24
  * Check if an object exceeds maximum nesting depth
@@ -38,17 +39,18 @@ let currentStore: PreferencesStore | null = null;
38
39
  let pluginDefaults: Record<string, unknown> = {};
39
40
 
40
41
  /**
41
- * Create the Preferences plugin
42
+ * Create the Preferences plugin with smart defaults
43
+ *
44
+ * Config is optional - plugin will use defaults and get dependencies from registry.
45
+ * Gracefully handles missing dependencies with clear log messages.
42
46
  */
43
- export function createPreferencesPlugin(config: PreferencesPluginConfig): Plugin {
44
- const debug = config.debug || false;
45
- // Routes are mounted under /api by the control panel, so don't include /api in prefix
46
- const apiPrefix = config.api?.prefix || '/'; // Framework adds /preferences prefix automatically
47
- const apiEnabled = config.api?.enabled !== false;
48
-
49
- function log(message: string, data?: Record<string, unknown>) {
50
- if (debug) {
51
- console.log(`[PreferencesPlugin] ${message}`, data || '');
47
+ export function createPreferencesPlugin(config: Partial<PreferencesPluginConfig> = {}): Plugin {
48
+ function log(message: string, data?: Record<string, unknown>, isError = false) {
49
+ const prefix = '[PreferencesPlugin]';
50
+ if (isError) {
51
+ console.error(`${prefix} ${message}`, data || '');
52
+ } else if (config.debug) {
53
+ console.log(`${prefix} ${message}`, data || '');
52
54
  }
53
55
  }
54
56
 
@@ -58,20 +60,62 @@ export function createPreferencesPlugin(config: PreferencesPluginConfig): Plugin
58
60
  version: '1.0.0',
59
61
 
60
62
  async onStart(_pluginConfig: PluginConfig, registry: PluginRegistry): Promise<void> {
61
- log('Starting preferences plugin');
63
+ const logger = registry.getLogger('preferences');
62
64
 
63
65
  // Check for users plugin dependency
64
66
  if (!registry.hasPlugin('users')) {
65
- throw new Error('Preferences plugin requires Users plugin to be loaded first');
67
+ logger.warn('Users plugin not loaded! Preferences plugin disabled.');
68
+ registry.registerHealthCheck({
69
+ name: 'preferences-store',
70
+ type: 'custom',
71
+ check: async () => ({
72
+ healthy: false,
73
+ details: {
74
+ error: 'Users plugin not available',
75
+ state: 'disabled',
76
+ },
77
+ }),
78
+ });
79
+ return;
80
+ }
81
+
82
+ // Check for postgres in registry
83
+ if (!hasPostgres()) {
84
+ logger.warn('No Database! Preferences plugin disabled.');
85
+ registry.registerHealthCheck({
86
+ name: 'preferences-store',
87
+ type: 'custom',
88
+ check: async () => ({
89
+ healthy: false,
90
+ details: {
91
+ error: 'PostgreSQL not available',
92
+ state: 'disabled',
93
+ },
94
+ }),
95
+ });
96
+ return;
66
97
  }
67
98
 
99
+ // Smart defaults - get dependencies from registry
100
+ const store = config.store ?? postgresPreferencesStore({
101
+ pool: () => getPostgres().getPool(),
102
+ autoCreateTables: true,
103
+ });
104
+
105
+ const debug = config.debug ?? false;
106
+ const apiPrefix = config.api?.prefix ?? '/'; // Framework adds /preferences prefix automatically
107
+ const apiEnabled = config.api?.enabled ?? true;
108
+ const defaults = config.defaults ?? {};
109
+
110
+ log('Starting preferences plugin');
111
+
68
112
  // Initialize the store (creates tables and RLS policies if needed)
69
- await config.store.initialize();
113
+ await store.initialize();
70
114
  log('Preferences plugin migrations complete');
71
115
 
72
116
  // Store references for helper access
73
- currentStore = config.store;
74
- pluginDefaults = config.defaults || {};
117
+ currentStore = store;
118
+ pluginDefaults = defaults;
75
119
 
76
120
  // Register health check
77
121
  registry.registerHealthCheck({
@@ -105,7 +149,7 @@ export function createPreferencesPlugin(config: PreferencesPluginConfig): Plugin
105
149
  return res.status(401).json({ error: 'Authentication required' });
106
150
  }
107
151
 
108
- const stored = await config.store.get(userId);
152
+ const stored = await store.get(userId);
109
153
 
110
154
  // Merge with defaults (defaults as base, stored values override)
111
155
  const preferences = stored
@@ -153,7 +197,7 @@ export function createPreferencesPlugin(config: PreferencesPluginConfig): Plugin
153
197
  return res.status(400).json({ error: 'Preferences object too deeply nested (max 10 levels)' });
154
198
  }
155
199
 
156
- const updated = await config.store.update(userId, newPreferences);
200
+ const updated = await store.update(userId, newPreferences);
157
201
 
158
202
  // Merge with defaults for response
159
203
  const preferences = deepMerge(pluginDefaults, updated);
@@ -183,7 +227,7 @@ export function createPreferencesPlugin(config: PreferencesPluginConfig): Plugin
183
227
  return res.status(401).json({ error: 'Authentication required' });
184
228
  }
185
229
 
186
- await config.store.delete(userId);
230
+ await store.delete(userId);
187
231
 
188
232
  // Return 204 No Content (idempotent - success even if no row existed)
189
233
  res.status(204).send();
@@ -208,7 +252,9 @@ export function createPreferencesPlugin(config: PreferencesPluginConfig): Plugin
208
252
 
209
253
  async onStop(): Promise<void> {
210
254
  log('Stopping preferences plugin');
211
- await config.store.shutdown();
255
+ if (currentStore) {
256
+ await currentStore.shutdown();
257
+ }
212
258
  currentStore = null;
213
259
  pluginDefaults = {};
214
260
  log('Preferences plugin stopped');
@@ -48,8 +48,6 @@ export type {
48
48
  // Stores
49
49
  export { postgresProfileStore } from './stores/index.js';
50
50
 
51
- // UI Components
52
- export { ProfilesStatusWidget } from './ProfilesStatusWidget.js';
53
- export type { ProfilesStatusWidgetProps } from './ProfilesStatusWidget.js';
54
- export { ProfilesManagementPage } from './ProfilesManagementPage.js';
55
- export type { ProfilesManagementPageProps } from './ProfilesManagementPage.js';
51
+ // UI Components are exported from main package index (@qwickapps/server)
52
+ // Do NOT export here to avoid loading UI dependencies when importing plugins
53
+
@@ -20,6 +20,8 @@ import type {
20
20
  ContentFilterLevel,
21
21
  TimeRestrictionResult,
22
22
  } from './types.js';
23
+ import { hasPostgres, getPostgres } from '../postgres-plugin.js';
24
+ import { postgresProfileStore } from './stores/index.js';
23
25
 
24
26
  // Store instance for helper access
25
27
  let currentStore: ProfileStore | null = null;
@@ -66,17 +68,18 @@ function isWithinAllowedHours(start?: string, end?: string): boolean {
66
68
  }
67
69
 
68
70
  /**
69
- * Create the Profiles plugin
71
+ * Create the Profiles plugin with smart defaults
72
+ *
73
+ * Config is optional - plugin will use defaults and get dependencies from registry.
74
+ * Gracefully handles missing dependencies with clear log messages.
70
75
  */
71
- export function createProfilesPlugin(config: ProfilesPluginConfig): Plugin {
72
- const debug = config.debug || false;
73
- const maxProfilesPerUser = config.maxProfilesPerUser || 10;
74
- const defaultFilterLevel = config.defaultFilterLevel || 'moderate';
75
- const apiPrefix = config.api?.prefix || '/'; // Framework adds /profiles prefix automatically
76
-
77
- function log(message: string, data?: Record<string, unknown>) {
78
- if (debug) {
79
- console.log(`[ProfilesPlugin] ${message}`, data || '');
76
+ export function createProfilesPlugin(config: Partial<ProfilesPluginConfig> = {}): Plugin {
77
+ function log(message: string, data?: Record<string, unknown>, isError = false) {
78
+ const prefix = '[ProfilesPlugin]';
79
+ if (isError) {
80
+ console.error(`${prefix} ${message}`, data || '');
81
+ } else if (config.debug) {
82
+ console.log(`${prefix} ${message}`, data || '');
80
83
  }
81
84
  }
82
85
 
@@ -86,15 +89,45 @@ export function createProfilesPlugin(config: ProfilesPluginConfig): Plugin {
86
89
  version: '1.0.0',
87
90
 
88
91
  async onStart(_pluginConfig: PluginConfig, registry: PluginRegistry): Promise<void> {
92
+ const logger = registry.getLogger('profiles');
93
+
94
+ // Check for postgres in registry
95
+ if (!hasPostgres()) {
96
+ logger.warn('No Database! Profiles plugin disabled.');
97
+ registry.registerHealthCheck({
98
+ name: 'profiles-store',
99
+ type: 'custom',
100
+ check: async () => ({
101
+ healthy: false,
102
+ details: {
103
+ error: 'PostgreSQL not available',
104
+ state: 'disabled',
105
+ },
106
+ }),
107
+ });
108
+ return;
109
+ }
110
+
111
+ // Smart defaults - get dependencies from registry
112
+ const store = config.store ?? postgresProfileStore({
113
+ pool: () => getPostgres().getPool(),
114
+ autoCreateTables: true,
115
+ });
116
+
117
+ const debug = config.debug ?? false;
118
+ const maxProfilesPerUser = config.maxProfilesPerUser ?? 10;
119
+ const defaultFilterLevel = config.defaultFilterLevel ?? 'moderate';
120
+ const apiPrefix = config.api?.prefix ?? '/profiles';
121
+
89
122
  log('Starting profiles plugin');
90
123
 
91
124
  // Initialize the store (creates tables if needed)
92
- await config.store.initialize();
125
+ await store.initialize();
93
126
  log('Profiles plugin migrations complete');
94
127
 
95
128
  // Store references for helper access
96
- currentStore = config.store;
97
- currentConfig = config;
129
+ currentStore = store;
130
+ currentConfig = { ...config, store, debug, maxProfilesPerUser, defaultFilterLevel };
98
131
 
99
132
  // Register health check
100
133
  registry.registerHealthCheck({
@@ -102,7 +135,7 @@ export function createProfilesPlugin(config: ProfilesPluginConfig): Plugin {
102
135
  type: 'custom',
103
136
  check: async () => {
104
137
  try {
105
- await config.store.search({ limit: 1 });
138
+ await store.search({ limit: 1 });
106
139
  return {
107
140
  healthy: true,
108
141
  details: {
@@ -137,7 +170,7 @@ export function createProfilesPlugin(config: ProfilesPluginConfig): Plugin {
137
170
  sortOrder: (req.query.sortOrder as ProfileSearchParams['sortOrder']) || 'desc',
138
171
  };
139
172
 
140
- const result = await config.store.search(params);
173
+ const result = await store.search(params);
141
174
  res.json(result);
142
175
  } catch (error) {
143
176
  console.error('[ProfilesPlugin] Search error:', error);
@@ -153,7 +186,7 @@ export function createProfilesPlugin(config: ProfilesPluginConfig): Plugin {
153
186
  pluginId: 'profiles',
154
187
  handler: async (req: Request, res: Response) => {
155
188
  try {
156
- const profile = await config.store.getById(req.params.id);
189
+ const profile = await store.getById(req.params.id);
157
190
  if (!profile) {
158
191
  return res.status(404).json({ error: 'Profile not found' });
159
192
  }
@@ -196,14 +229,14 @@ export function createProfilesPlugin(config: ProfilesPluginConfig): Plugin {
196
229
  }
197
230
 
198
231
  // Check profile limit
199
- const currentCount = await config.store.getProfileCount(input.user_id);
232
+ const currentCount = await store.getProfileCount(input.user_id);
200
233
  if (currentCount >= maxProfilesPerUser) {
201
234
  return res.status(400).json({
202
235
  error: `Maximum profiles (${maxProfilesPerUser}) reached for this user`,
203
236
  });
204
237
  }
205
238
 
206
- const profile = await config.store.create(input);
239
+ const profile = await store.create(input);
207
240
  res.status(201).json(profile);
208
241
  } catch (error) {
209
242
  console.error('[ProfilesPlugin] Create profile error:', error);
@@ -235,7 +268,7 @@ export function createProfilesPlugin(config: ProfilesPluginConfig): Plugin {
235
268
  metadata: req.body.metadata,
236
269
  };
237
270
 
238
- const profile = await config.store.update(req.params.id, input);
271
+ const profile = await store.update(req.params.id, input);
239
272
  if (!profile) {
240
273
  return res.status(404).json({ error: 'Profile not found' });
241
274
  }
@@ -254,7 +287,7 @@ export function createProfilesPlugin(config: ProfilesPluginConfig): Plugin {
254
287
  pluginId: 'profiles',
255
288
  handler: async (req: Request, res: Response) => {
256
289
  try {
257
- const deleted = await config.store.delete(req.params.id);
290
+ const deleted = await store.delete(req.params.id);
258
291
  if (!deleted) {
259
292
  return res.status(404).json({ error: 'Profile not found' });
260
293
  }
@@ -273,7 +306,7 @@ export function createProfilesPlugin(config: ProfilesPluginConfig): Plugin {
273
306
  pluginId: 'profiles',
274
307
  handler: async (req: Request, res: Response) => {
275
308
  try {
276
- const profiles = await config.store.listByUser(req.params.userId);
309
+ const profiles = await store.listByUser(req.params.userId);
277
310
  res.json({ profiles });
278
311
  } catch (error) {
279
312
  console.error('[ProfilesPlugin] List user profiles error:', error);
@@ -289,7 +322,7 @@ export function createProfilesPlugin(config: ProfilesPluginConfig): Plugin {
289
322
  pluginId: 'profiles',
290
323
  handler: async (req: Request, res: Response) => {
291
324
  try {
292
- const profile = await config.store.getDefaultProfile(req.params.userId);
325
+ const profile = await store.getDefaultProfile(req.params.userId);
293
326
  if (!profile) {
294
327
  return res.status(404).json({ error: 'No default profile found' });
295
328
  }
@@ -308,17 +341,17 @@ export function createProfilesPlugin(config: ProfilesPluginConfig): Plugin {
308
341
  pluginId: 'profiles',
309
342
  handler: async (req: Request, res: Response) => {
310
343
  try {
311
- const profile = await config.store.getById(req.params.id);
344
+ const profile = await store.getById(req.params.id);
312
345
  if (!profile) {
313
346
  return res.status(404).json({ error: 'Profile not found' });
314
347
  }
315
348
 
316
- const success = await config.store.setDefaultProfile(req.params.id, profile.user_id);
349
+ const success = await store.setDefaultProfile(req.params.id, profile.user_id);
317
350
  if (!success) {
318
351
  return res.status(500).json({ error: 'Failed to set default profile' });
319
352
  }
320
353
 
321
- const updated = await config.store.getById(req.params.id);
354
+ const updated = await store.getById(req.params.id);
322
355
  res.json(updated);
323
356
  } catch (error) {
324
357
  console.error('[ProfilesPlugin] Set default profile error:', error);
@@ -334,7 +367,7 @@ export function createProfilesPlugin(config: ProfilesPluginConfig): Plugin {
334
367
  pluginId: 'profiles',
335
368
  handler: async (req: Request, res: Response) => {
336
369
  try {
337
- const profile = await config.store.getById(req.params.id);
370
+ const profile = await store.getById(req.params.id);
338
371
  if (!profile) {
339
372
  return res.status(404).json({ error: 'Profile not found' });
340
373
  }
@@ -354,7 +387,7 @@ export function createProfilesPlugin(config: ProfilesPluginConfig): Plugin {
354
387
 
355
388
  async onStop(): Promise<void> {
356
389
  log('Stopping profiles plugin');
357
- await config.store.shutdown();
390
+ if (currentStore) { await currentStore.shutdown(); };
358
391
  currentStore = null;
359
392
  currentConfig = null;
360
393
  log('Profiles plugin stopped');
@@ -289,10 +289,17 @@ export interface ProfilesApiConfig {
289
289
 
290
290
  /**
291
291
  * Profiles plugin configuration
292
+ *
293
+ * All properties are optional - plugin will use smart defaults:
294
+ * - store: Postgres profile store using registry's postgres instance
295
+ * - maxProfilesPerUser: 10
296
+ * - defaultFilterLevel: 'moderate'
297
+ * - api.prefix: '/profiles'
298
+ * - debug: false
292
299
  */
293
300
  export interface ProfilesPluginConfig {
294
- /** Profile storage backend */
295
- store: ProfileStore;
301
+ /** Profile storage backend (default: postgres profile store from registry) */
302
+ store?: ProfileStore;
296
303
  /** Maximum profiles per user (default: 10) */
297
304
  maxProfilesPerUser?: number;
298
305
  /** Default content filter level (default: 'moderate') */
@@ -32,8 +32,6 @@ export type {
32
32
  MCPRateLimitConfig,
33
33
  } from './types.js';
34
34
 
35
- // UI Components
36
- export { QwickbrainStatusWidget } from './QwickbrainStatusWidget.js';
37
- export { QwickbrainManagementPage } from './QwickbrainManagementPage.js';
38
- export type { QwickbrainStatusWidgetProps } from './QwickbrainStatusWidget.js';
39
- export type { QwickbrainManagementPageProps } from './QwickbrainManagementPage.js';
35
+ // UI Components are exported from main package index (@qwickapps/server)
36
+ // Do NOT export here to avoid loading UI dependencies when importing plugins
37
+