@qwickapps/server 1.3.1 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (395) hide show
  1. package/README.md +157 -0
  2. package/dist/core/control-panel.d.ts.map +1 -1
  3. package/dist/core/control-panel.js +114 -0
  4. package/dist/core/control-panel.js.map +1 -1
  5. package/dist/core/types.d.ts +19 -0
  6. package/dist/core/types.d.ts.map +1 -1
  7. package/dist/index.d.ts +2 -2
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +15 -3
  10. package/dist/index.js.map +1 -1
  11. package/dist/plugins/auth/adapter-wrapper.d.ts +47 -0
  12. package/dist/plugins/auth/adapter-wrapper.d.ts.map +1 -0
  13. package/dist/plugins/auth/adapter-wrapper.js +166 -0
  14. package/dist/plugins/auth/adapter-wrapper.js.map +1 -0
  15. package/dist/plugins/auth/adapter-wrapper.test.d.ts +7 -0
  16. package/dist/plugins/auth/adapter-wrapper.test.d.ts.map +1 -0
  17. package/dist/plugins/auth/adapter-wrapper.test.js +303 -0
  18. package/dist/plugins/auth/adapter-wrapper.test.js.map +1 -0
  19. package/dist/plugins/auth/config-store.d.ts +11 -0
  20. package/dist/plugins/auth/config-store.d.ts.map +1 -0
  21. package/dist/plugins/auth/config-store.js +232 -0
  22. package/dist/plugins/auth/config-store.js.map +1 -0
  23. package/dist/plugins/auth/config-store.test.d.ts +7 -0
  24. package/dist/plugins/auth/config-store.test.d.ts.map +1 -0
  25. package/dist/plugins/auth/config-store.test.js +299 -0
  26. package/dist/plugins/auth/config-store.test.js.map +1 -0
  27. package/dist/plugins/auth/env-config.d.ts +51 -1
  28. package/dist/plugins/auth/env-config.d.ts.map +1 -1
  29. package/dist/plugins/auth/env-config.js +640 -7
  30. package/dist/plugins/auth/env-config.js.map +1 -1
  31. package/dist/plugins/auth/index.d.ts +6 -2
  32. package/dist/plugins/auth/index.d.ts.map +1 -1
  33. package/dist/plugins/auth/index.js +5 -1
  34. package/dist/plugins/auth/index.js.map +1 -1
  35. package/dist/plugins/auth/types.d.ts +106 -0
  36. package/dist/plugins/auth/types.d.ts.map +1 -1
  37. package/dist/plugins/bans/bans-plugin.d.ts.map +1 -1
  38. package/dist/plugins/bans/bans-plugin.js +12 -3
  39. package/dist/plugins/bans/bans-plugin.js.map +1 -1
  40. package/dist/plugins/devices/__tests__/devices-plugin.test.d.ts +11 -0
  41. package/dist/plugins/devices/__tests__/devices-plugin.test.d.ts.map +1 -0
  42. package/dist/plugins/devices/__tests__/devices-plugin.test.js +410 -0
  43. package/dist/plugins/devices/__tests__/devices-plugin.test.js.map +1 -0
  44. package/dist/plugins/devices/__tests__/token-utils.test.d.ts +7 -0
  45. package/dist/plugins/devices/__tests__/token-utils.test.d.ts.map +1 -0
  46. package/dist/plugins/devices/__tests__/token-utils.test.js +197 -0
  47. package/dist/plugins/devices/__tests__/token-utils.test.js.map +1 -0
  48. package/dist/plugins/devices/adapters/compute-adapter.d.ts +36 -0
  49. package/dist/plugins/devices/adapters/compute-adapter.d.ts.map +1 -0
  50. package/dist/plugins/devices/adapters/compute-adapter.js +100 -0
  51. package/dist/plugins/devices/adapters/compute-adapter.js.map +1 -0
  52. package/dist/plugins/devices/adapters/index.d.ts +12 -0
  53. package/dist/plugins/devices/adapters/index.d.ts.map +1 -0
  54. package/dist/plugins/devices/adapters/index.js +10 -0
  55. package/dist/plugins/devices/adapters/index.js.map +1 -0
  56. package/dist/plugins/devices/adapters/mobile-adapter.d.ts +41 -0
  57. package/dist/plugins/devices/adapters/mobile-adapter.d.ts.map +1 -0
  58. package/dist/plugins/devices/adapters/mobile-adapter.js +131 -0
  59. package/dist/plugins/devices/adapters/mobile-adapter.js.map +1 -0
  60. package/dist/plugins/devices/devices-plugin.d.ts +70 -0
  61. package/dist/plugins/devices/devices-plugin.d.ts.map +1 -0
  62. package/dist/plugins/devices/devices-plugin.js +453 -0
  63. package/dist/plugins/devices/devices-plugin.js.map +1 -0
  64. package/dist/plugins/devices/index.d.ts +18 -0
  65. package/dist/plugins/devices/index.d.ts.map +1 -0
  66. package/dist/plugins/devices/index.js +18 -0
  67. package/dist/plugins/devices/index.js.map +1 -0
  68. package/dist/plugins/devices/stores/index.d.ts +9 -0
  69. package/dist/plugins/devices/stores/index.d.ts.map +1 -0
  70. package/dist/plugins/devices/stores/index.js +9 -0
  71. package/dist/plugins/devices/stores/index.js.map +1 -0
  72. package/dist/plugins/devices/stores/postgres-store.d.ts +26 -0
  73. package/dist/plugins/devices/stores/postgres-store.d.ts.map +1 -0
  74. package/dist/plugins/devices/stores/postgres-store.js +199 -0
  75. package/dist/plugins/devices/stores/postgres-store.js.map +1 -0
  76. package/dist/plugins/devices/token-utils.d.ts +100 -0
  77. package/dist/plugins/devices/token-utils.d.ts.map +1 -0
  78. package/dist/plugins/devices/token-utils.js +162 -0
  79. package/dist/plugins/devices/token-utils.js.map +1 -0
  80. package/dist/plugins/devices/types.d.ts +307 -0
  81. package/dist/plugins/devices/types.d.ts.map +1 -0
  82. package/dist/plugins/devices/types.js +10 -0
  83. package/dist/plugins/devices/types.js.map +1 -0
  84. package/dist/plugins/index.d.ts +18 -4
  85. package/dist/plugins/index.d.ts.map +1 -1
  86. package/dist/plugins/index.js +16 -2
  87. package/dist/plugins/index.js.map +1 -1
  88. package/dist/plugins/notifications/__tests__/notifications-manager.test.d.ts +5 -0
  89. package/dist/plugins/notifications/__tests__/notifications-manager.test.d.ts.map +1 -0
  90. package/dist/plugins/notifications/__tests__/notifications-manager.test.js +470 -0
  91. package/dist/plugins/notifications/__tests__/notifications-manager.test.js.map +1 -0
  92. package/dist/plugins/notifications/index.d.ts +71 -0
  93. package/dist/plugins/notifications/index.d.ts.map +1 -0
  94. package/dist/plugins/notifications/index.js +72 -0
  95. package/dist/plugins/notifications/index.js.map +1 -0
  96. package/dist/plugins/notifications/notifications-manager.d.ts +182 -0
  97. package/dist/plugins/notifications/notifications-manager.d.ts.map +1 -0
  98. package/dist/plugins/notifications/notifications-manager.js +610 -0
  99. package/dist/plugins/notifications/notifications-manager.js.map +1 -0
  100. package/dist/plugins/notifications/notifications-plugin.d.ts +83 -0
  101. package/dist/plugins/notifications/notifications-plugin.d.ts.map +1 -0
  102. package/dist/plugins/notifications/notifications-plugin.js +337 -0
  103. package/dist/plugins/notifications/notifications-plugin.js.map +1 -0
  104. package/dist/plugins/notifications/types.d.ts +164 -0
  105. package/dist/plugins/notifications/types.d.ts.map +1 -0
  106. package/dist/plugins/notifications/types.js +9 -0
  107. package/dist/plugins/notifications/types.js.map +1 -0
  108. package/dist/plugins/parental/__tests__/parental-plugin.test.d.ts +12 -0
  109. package/dist/plugins/parental/__tests__/parental-plugin.test.d.ts.map +1 -0
  110. package/dist/plugins/parental/__tests__/parental-plugin.test.js +349 -0
  111. package/dist/plugins/parental/__tests__/parental-plugin.test.js.map +1 -0
  112. package/dist/plugins/parental/adapters/index.d.ts +8 -0
  113. package/dist/plugins/parental/adapters/index.d.ts.map +1 -0
  114. package/dist/plugins/parental/adapters/index.js +7 -0
  115. package/dist/plugins/parental/adapters/index.js.map +1 -0
  116. package/dist/plugins/parental/adapters/kids-adapter.d.ts +24 -0
  117. package/dist/plugins/parental/adapters/kids-adapter.d.ts.map +1 -0
  118. package/dist/plugins/parental/adapters/kids-adapter.js +174 -0
  119. package/dist/plugins/parental/adapters/kids-adapter.js.map +1 -0
  120. package/dist/plugins/parental/index.d.ts +14 -0
  121. package/dist/plugins/parental/index.d.ts.map +1 -0
  122. package/dist/plugins/parental/index.js +15 -0
  123. package/dist/plugins/parental/index.js.map +1 -0
  124. package/dist/plugins/parental/parental-plugin.d.ts +88 -0
  125. package/dist/plugins/parental/parental-plugin.d.ts.map +1 -0
  126. package/dist/plugins/parental/parental-plugin.js +666 -0
  127. package/dist/plugins/parental/parental-plugin.js.map +1 -0
  128. package/dist/plugins/parental/stores/index.d.ts +7 -0
  129. package/dist/plugins/parental/stores/index.d.ts.map +1 -0
  130. package/dist/plugins/parental/stores/index.js +7 -0
  131. package/dist/plugins/parental/stores/index.js.map +1 -0
  132. package/dist/plugins/parental/stores/postgres-store.d.ts +10 -0
  133. package/dist/plugins/parental/stores/postgres-store.d.ts.map +1 -0
  134. package/dist/plugins/parental/stores/postgres-store.js +209 -0
  135. package/dist/plugins/parental/stores/postgres-store.js.map +1 -0
  136. package/dist/plugins/parental/types.d.ts +154 -0
  137. package/dist/plugins/parental/types.d.ts.map +1 -0
  138. package/dist/plugins/parental/types.js +10 -0
  139. package/dist/plugins/parental/types.js.map +1 -0
  140. package/dist/plugins/profiles/__tests__/profiles-plugin.test.d.ts +11 -0
  141. package/dist/plugins/profiles/__tests__/profiles-plugin.test.d.ts.map +1 -0
  142. package/dist/plugins/profiles/__tests__/profiles-plugin.test.js +243 -0
  143. package/dist/plugins/profiles/__tests__/profiles-plugin.test.js.map +1 -0
  144. package/dist/plugins/profiles/index.d.ts +12 -0
  145. package/dist/plugins/profiles/index.d.ts.map +1 -0
  146. package/dist/plugins/profiles/index.js +13 -0
  147. package/dist/plugins/profiles/index.js.map +1 -0
  148. package/dist/plugins/profiles/profiles-plugin.d.ts +71 -0
  149. package/dist/plugins/profiles/profiles-plugin.d.ts.map +1 -0
  150. package/dist/plugins/profiles/profiles-plugin.js +481 -0
  151. package/dist/plugins/profiles/profiles-plugin.js.map +1 -0
  152. package/dist/plugins/profiles/stores/index.d.ts +9 -0
  153. package/dist/plugins/profiles/stores/index.d.ts.map +1 -0
  154. package/dist/plugins/profiles/stores/index.js +9 -0
  155. package/dist/plugins/profiles/stores/index.js.map +1 -0
  156. package/dist/plugins/profiles/stores/postgres-store.d.ts +18 -0
  157. package/dist/plugins/profiles/stores/postgres-store.d.ts.map +1 -0
  158. package/dist/plugins/profiles/stores/postgres-store.js +310 -0
  159. package/dist/plugins/profiles/stores/postgres-store.js.map +1 -0
  160. package/dist/plugins/profiles/types.d.ts +289 -0
  161. package/dist/plugins/profiles/types.d.ts.map +1 -0
  162. package/dist/plugins/profiles/types.js +10 -0
  163. package/dist/plugins/profiles/types.js.map +1 -0
  164. package/dist/plugins/rate-limit/__tests__/rate-limit-plugin.test.d.ts +7 -0
  165. package/dist/plugins/rate-limit/__tests__/rate-limit-plugin.test.d.ts.map +1 -0
  166. package/dist/plugins/rate-limit/__tests__/rate-limit-plugin.test.js +220 -0
  167. package/dist/plugins/rate-limit/__tests__/rate-limit-plugin.test.js.map +1 -0
  168. package/dist/plugins/rate-limit/cleanup.d.ts +40 -0
  169. package/dist/plugins/rate-limit/cleanup.d.ts.map +1 -0
  170. package/dist/plugins/rate-limit/cleanup.js +72 -0
  171. package/dist/plugins/rate-limit/cleanup.js.map +1 -0
  172. package/dist/plugins/rate-limit/env-config.d.ts +91 -0
  173. package/dist/plugins/rate-limit/env-config.d.ts.map +1 -0
  174. package/dist/plugins/rate-limit/env-config.js +318 -0
  175. package/dist/plugins/rate-limit/env-config.js.map +1 -0
  176. package/dist/plugins/rate-limit/index.d.ts +76 -0
  177. package/dist/plugins/rate-limit/index.d.ts.map +1 -0
  178. package/dist/plugins/rate-limit/index.js +79 -0
  179. package/dist/plugins/rate-limit/index.js.map +1 -0
  180. package/dist/plugins/rate-limit/middleware.d.ts +40 -0
  181. package/dist/plugins/rate-limit/middleware.d.ts.map +1 -0
  182. package/dist/plugins/rate-limit/middleware.js +169 -0
  183. package/dist/plugins/rate-limit/middleware.js.map +1 -0
  184. package/dist/plugins/rate-limit/rate-limit-plugin.d.ts +44 -0
  185. package/dist/plugins/rate-limit/rate-limit-plugin.d.ts.map +1 -0
  186. package/dist/plugins/rate-limit/rate-limit-plugin.js +354 -0
  187. package/dist/plugins/rate-limit/rate-limit-plugin.js.map +1 -0
  188. package/dist/plugins/rate-limit/rate-limit-service.d.ts +110 -0
  189. package/dist/plugins/rate-limit/rate-limit-service.d.ts.map +1 -0
  190. package/dist/plugins/rate-limit/rate-limit-service.js +172 -0
  191. package/dist/plugins/rate-limit/rate-limit-service.js.map +1 -0
  192. package/dist/plugins/rate-limit/stores/cache-store.d.ts +33 -0
  193. package/dist/plugins/rate-limit/stores/cache-store.d.ts.map +1 -0
  194. package/dist/plugins/rate-limit/stores/cache-store.js +225 -0
  195. package/dist/plugins/rate-limit/stores/cache-store.js.map +1 -0
  196. package/dist/plugins/rate-limit/stores/index.d.ts +8 -0
  197. package/dist/plugins/rate-limit/stores/index.d.ts.map +1 -0
  198. package/dist/plugins/rate-limit/stores/index.js +8 -0
  199. package/dist/plugins/rate-limit/stores/index.js.map +1 -0
  200. package/dist/plugins/rate-limit/stores/postgres-store.d.ts +34 -0
  201. package/dist/plugins/rate-limit/stores/postgres-store.d.ts.map +1 -0
  202. package/dist/plugins/rate-limit/stores/postgres-store.js +320 -0
  203. package/dist/plugins/rate-limit/stores/postgres-store.js.map +1 -0
  204. package/dist/plugins/rate-limit/strategies/fixed-window.d.ts +21 -0
  205. package/dist/plugins/rate-limit/strategies/fixed-window.d.ts.map +1 -0
  206. package/dist/plugins/rate-limit/strategies/fixed-window.js +97 -0
  207. package/dist/plugins/rate-limit/strategies/fixed-window.js.map +1 -0
  208. package/dist/plugins/rate-limit/strategies/index.d.ts +14 -0
  209. package/dist/plugins/rate-limit/strategies/index.d.ts.map +1 -0
  210. package/dist/plugins/rate-limit/strategies/index.js +27 -0
  211. package/dist/plugins/rate-limit/strategies/index.js.map +1 -0
  212. package/dist/plugins/rate-limit/strategies/sliding-window.d.ts +22 -0
  213. package/dist/plugins/rate-limit/strategies/sliding-window.d.ts.map +1 -0
  214. package/dist/plugins/rate-limit/strategies/sliding-window.js +122 -0
  215. package/dist/plugins/rate-limit/strategies/sliding-window.js.map +1 -0
  216. package/dist/plugins/rate-limit/strategies/token-bucket.d.ts +28 -0
  217. package/dist/plugins/rate-limit/strategies/token-bucket.d.ts.map +1 -0
  218. package/dist/plugins/rate-limit/strategies/token-bucket.js +121 -0
  219. package/dist/plugins/rate-limit/strategies/token-bucket.js.map +1 -0
  220. package/dist/plugins/rate-limit/types.d.ts +265 -0
  221. package/dist/plugins/rate-limit/types.d.ts.map +1 -0
  222. package/dist/plugins/rate-limit/types.js +9 -0
  223. package/dist/plugins/rate-limit/types.js.map +1 -0
  224. package/dist/plugins/subscriptions/__tests__/subscriptions-plugin.test.d.ts +11 -0
  225. package/dist/plugins/subscriptions/__tests__/subscriptions-plugin.test.d.ts.map +1 -0
  226. package/dist/plugins/subscriptions/__tests__/subscriptions-plugin.test.js +305 -0
  227. package/dist/plugins/subscriptions/__tests__/subscriptions-plugin.test.js.map +1 -0
  228. package/dist/plugins/subscriptions/index.d.ts +12 -0
  229. package/dist/plugins/subscriptions/index.d.ts.map +1 -0
  230. package/dist/plugins/subscriptions/index.js +13 -0
  231. package/dist/plugins/subscriptions/index.js.map +1 -0
  232. package/dist/plugins/subscriptions/stores/index.d.ts +9 -0
  233. package/dist/plugins/subscriptions/stores/index.d.ts.map +1 -0
  234. package/dist/plugins/subscriptions/stores/index.js +9 -0
  235. package/dist/plugins/subscriptions/stores/index.js.map +1 -0
  236. package/dist/plugins/subscriptions/stores/postgres-store.d.ts +14 -0
  237. package/dist/plugins/subscriptions/stores/postgres-store.d.ts.map +1 -0
  238. package/dist/plugins/subscriptions/stores/postgres-store.js +359 -0
  239. package/dist/plugins/subscriptions/stores/postgres-store.js.map +1 -0
  240. package/dist/plugins/subscriptions/subscriptions-plugin.d.ts +82 -0
  241. package/dist/plugins/subscriptions/subscriptions-plugin.d.ts.map +1 -0
  242. package/dist/plugins/subscriptions/subscriptions-plugin.js +449 -0
  243. package/dist/plugins/subscriptions/subscriptions-plugin.js.map +1 -0
  244. package/dist/plugins/subscriptions/types.d.ts +308 -0
  245. package/dist/plugins/subscriptions/types.d.ts.map +1 -0
  246. package/dist/plugins/subscriptions/types.js +10 -0
  247. package/dist/plugins/subscriptions/types.js.map +1 -0
  248. package/dist/plugins/usage/__tests__/usage-plugin.test.d.ts +11 -0
  249. package/dist/plugins/usage/__tests__/usage-plugin.test.d.ts.map +1 -0
  250. package/dist/plugins/usage/__tests__/usage-plugin.test.js +218 -0
  251. package/dist/plugins/usage/__tests__/usage-plugin.test.js.map +1 -0
  252. package/dist/plugins/usage/index.d.ts +12 -0
  253. package/dist/plugins/usage/index.d.ts.map +1 -0
  254. package/dist/plugins/usage/index.js +13 -0
  255. package/dist/plugins/usage/index.js.map +1 -0
  256. package/dist/plugins/usage/stores/index.d.ts +9 -0
  257. package/dist/plugins/usage/stores/index.d.ts.map +1 -0
  258. package/dist/plugins/usage/stores/index.js +9 -0
  259. package/dist/plugins/usage/stores/index.js.map +1 -0
  260. package/dist/plugins/usage/stores/postgres-store.d.ts +14 -0
  261. package/dist/plugins/usage/stores/postgres-store.d.ts.map +1 -0
  262. package/dist/plugins/usage/stores/postgres-store.js +146 -0
  263. package/dist/plugins/usage/stores/postgres-store.js.map +1 -0
  264. package/dist/plugins/usage/types.d.ts +195 -0
  265. package/dist/plugins/usage/types.d.ts.map +1 -0
  266. package/dist/plugins/usage/types.js +10 -0
  267. package/dist/plugins/usage/types.js.map +1 -0
  268. package/dist/plugins/usage/usage-plugin.d.ts +51 -0
  269. package/dist/plugins/usage/usage-plugin.d.ts.map +1 -0
  270. package/dist/plugins/usage/usage-plugin.js +412 -0
  271. package/dist/plugins/usage/usage-plugin.js.map +1 -0
  272. package/dist/plugins/users/__tests__/postgres-store.test.d.ts +10 -0
  273. package/dist/plugins/users/__tests__/postgres-store.test.d.ts.map +1 -0
  274. package/dist/plugins/users/__tests__/postgres-store.test.js +229 -0
  275. package/dist/plugins/users/__tests__/postgres-store.test.js.map +1 -0
  276. package/dist/plugins/users/__tests__/users-plugin.test.js +3 -0
  277. package/dist/plugins/users/__tests__/users-plugin.test.js.map +1 -1
  278. package/dist/plugins/users/index.d.ts +2 -2
  279. package/dist/plugins/users/index.d.ts.map +1 -1
  280. package/dist/plugins/users/index.js +1 -1
  281. package/dist/plugins/users/index.js.map +1 -1
  282. package/dist/plugins/users/stores/postgres-store.d.ts.map +1 -1
  283. package/dist/plugins/users/stores/postgres-store.js +76 -0
  284. package/dist/plugins/users/stores/postgres-store.js.map +1 -1
  285. package/dist/plugins/users/types.d.ts +74 -6
  286. package/dist/plugins/users/types.d.ts.map +1 -1
  287. package/dist/plugins/users/users-plugin.d.ts +15 -1
  288. package/dist/plugins/users/users-plugin.d.ts.map +1 -1
  289. package/dist/plugins/users/users-plugin.js +29 -0
  290. package/dist/plugins/users/users-plugin.js.map +1 -1
  291. package/dist-ui/assets/index-CynOqPkb.js +469 -0
  292. package/dist-ui/assets/{index-BY8OxNgO.js.map → index-CynOqPkb.js.map} +1 -1
  293. package/dist-ui/index.html +1 -1
  294. package/dist-ui-lib/api/controlPanelApi.d.ts +187 -0
  295. package/dist-ui-lib/components/StatCard.d.ts +16 -0
  296. package/dist-ui-lib/dashboard/widgets/AuthStatusWidget.d.ts +9 -0
  297. package/dist-ui-lib/dashboard/widgets/IntegrationStatusWidget.d.ts +9 -0
  298. package/dist-ui-lib/dashboard/widgets/NotificationsStatsWidget.d.ts +12 -0
  299. package/dist-ui-lib/dashboard/widgets/index.d.ts +3 -0
  300. package/dist-ui-lib/index.js +3579 -2379
  301. package/dist-ui-lib/index.js.map +1 -1
  302. package/dist-ui-lib/pages/IntegrationsPage.d.ts +1 -0
  303. package/dist-ui-lib/pages/NotificationsPage.d.ts +9 -0
  304. package/dist-ui-lib/pages/RateLimitPage.d.ts +1 -0
  305. package/dist-ui-lib/utils/formatters.d.ts +19 -0
  306. package/package.json +1 -1
  307. package/src/core/control-panel.ts +128 -0
  308. package/src/core/types.ts +17 -0
  309. package/src/index.ts +216 -0
  310. package/src/plugins/auth/adapter-wrapper.test.ts +395 -0
  311. package/src/plugins/auth/adapter-wrapper.ts +205 -0
  312. package/src/plugins/auth/config-store.test.ts +417 -0
  313. package/src/plugins/auth/config-store.ts +305 -0
  314. package/src/plugins/auth/env-config.ts +714 -7
  315. package/src/plugins/auth/index.ts +22 -1
  316. package/src/plugins/auth/types.ts +138 -0
  317. package/src/plugins/bans/bans-plugin.ts +15 -3
  318. package/src/plugins/devices/__tests__/devices-plugin.test.ts +551 -0
  319. package/src/plugins/devices/__tests__/token-utils.test.ts +264 -0
  320. package/src/plugins/devices/adapters/compute-adapter.ts +139 -0
  321. package/src/plugins/devices/adapters/index.ts +13 -0
  322. package/src/plugins/devices/adapters/mobile-adapter.ts +179 -0
  323. package/src/plugins/devices/devices-plugin.ts +538 -0
  324. package/src/plugins/devices/index.ts +69 -0
  325. package/src/plugins/devices/stores/index.ts +9 -0
  326. package/src/plugins/devices/stores/postgres-store.ts +304 -0
  327. package/src/plugins/devices/token-utils.ts +213 -0
  328. package/src/plugins/devices/types.ts +351 -0
  329. package/src/plugins/index.ts +267 -0
  330. package/src/plugins/notifications/__tests__/notifications-manager.test.ts +637 -0
  331. package/src/plugins/notifications/index.ts +91 -0
  332. package/src/plugins/notifications/notifications-manager.ts +773 -0
  333. package/src/plugins/notifications/notifications-plugin.ts +398 -0
  334. package/src/plugins/notifications/types.ts +207 -0
  335. package/src/plugins/parental/__tests__/parental-plugin.test.ts +465 -0
  336. package/src/plugins/parental/adapters/index.ts +8 -0
  337. package/src/plugins/parental/adapters/kids-adapter.ts +206 -0
  338. package/src/plugins/parental/index.ts +55 -0
  339. package/src/plugins/parental/parental-plugin.ts +759 -0
  340. package/src/plugins/parental/stores/index.ts +7 -0
  341. package/src/plugins/parental/stores/postgres-store.ts +304 -0
  342. package/src/plugins/parental/types.ts +180 -0
  343. package/src/plugins/profiles/__tests__/profiles-plugin.test.ts +321 -0
  344. package/src/plugins/profiles/index.ts +49 -0
  345. package/src/plugins/profiles/profiles-plugin.ts +546 -0
  346. package/src/plugins/profiles/stores/index.ts +9 -0
  347. package/src/plugins/profiles/stores/postgres-store.ts +439 -0
  348. package/src/plugins/profiles/types.ts +338 -0
  349. package/src/plugins/rate-limit/__tests__/rate-limit-plugin.test.ts +259 -0
  350. package/src/plugins/rate-limit/cleanup.ts +117 -0
  351. package/src/plugins/rate-limit/env-config.ts +400 -0
  352. package/src/plugins/rate-limit/index.ts +128 -0
  353. package/src/plugins/rate-limit/middleware.ts +212 -0
  354. package/src/plugins/rate-limit/rate-limit-plugin.ts +400 -0
  355. package/src/plugins/rate-limit/rate-limit-service.ts +228 -0
  356. package/src/plugins/rate-limit/stores/cache-store.ts +261 -0
  357. package/src/plugins/rate-limit/stores/index.ts +8 -0
  358. package/src/plugins/rate-limit/stores/postgres-store.ts +402 -0
  359. package/src/plugins/rate-limit/strategies/fixed-window.ts +116 -0
  360. package/src/plugins/rate-limit/strategies/index.ts +30 -0
  361. package/src/plugins/rate-limit/strategies/sliding-window.ts +157 -0
  362. package/src/plugins/rate-limit/strategies/token-bucket.ts +154 -0
  363. package/src/plugins/rate-limit/types.ts +338 -0
  364. package/src/plugins/subscriptions/__tests__/subscriptions-plugin.test.ts +404 -0
  365. package/src/plugins/subscriptions/index.ts +51 -0
  366. package/src/plugins/subscriptions/stores/index.ts +9 -0
  367. package/src/plugins/subscriptions/stores/postgres-store.ts +482 -0
  368. package/src/plugins/subscriptions/subscriptions-plugin.ts +530 -0
  369. package/src/plugins/subscriptions/types.ts +355 -0
  370. package/src/plugins/usage/__tests__/usage-plugin.test.ts +288 -0
  371. package/src/plugins/usage/index.ts +39 -0
  372. package/src/plugins/usage/stores/index.ts +9 -0
  373. package/src/plugins/usage/stores/postgres-store.ts +213 -0
  374. package/src/plugins/usage/types.ts +222 -0
  375. package/src/plugins/usage/usage-plugin.ts +484 -0
  376. package/src/plugins/users/__tests__/postgres-store.test.ts +326 -0
  377. package/src/plugins/users/__tests__/users-plugin.test.ts +3 -0
  378. package/src/plugins/users/index.ts +6 -0
  379. package/src/plugins/users/stores/postgres-store.ts +104 -0
  380. package/src/plugins/users/types.ts +82 -6
  381. package/src/plugins/users/users-plugin.ts +37 -0
  382. package/ui/src/App.tsx +36 -14
  383. package/ui/src/api/controlPanelApi.ts +329 -6
  384. package/ui/src/components/StatCard.tsx +58 -0
  385. package/ui/src/dashboard/builtInWidgets.tsx +7 -1
  386. package/ui/src/dashboard/widgets/AuthStatusWidget.tsx +143 -0
  387. package/ui/src/dashboard/widgets/IntegrationStatusWidget.tsx +135 -0
  388. package/ui/src/dashboard/widgets/NotificationsStatsWidget.tsx +167 -0
  389. package/ui/src/dashboard/widgets/index.ts +3 -0
  390. package/ui/src/pages/AuthPage.tsx +986 -142
  391. package/ui/src/pages/IntegrationsPage.tsx +288 -0
  392. package/ui/src/pages/NotificationsPage.tsx +417 -0
  393. package/ui/src/pages/RateLimitPage.tsx +292 -0
  394. package/ui/src/utils/formatters.ts +33 -0
  395. package/dist-ui/assets/index-BY8OxNgO.js +0 -465
package/ui/src/App.tsx CHANGED
@@ -3,13 +3,21 @@ import { BrowserRouter, Routes, Route } from 'react-router-dom';
3
3
  import { QwickApp, ProductLogo, Text } from '@qwickapps/react-framework';
4
4
  import { Link, Box } from '@mui/material';
5
5
  import { defaultConfig } from './config/AppConfig';
6
- import { DashboardWidgetProvider } from './dashboard';
6
+ import {
7
+ DashboardWidgetProvider,
8
+ WidgetComponentRegistryProvider,
9
+ getBuiltInWidgetComponents,
10
+ } from './dashboard';
7
11
  import { DashboardPage } from './pages/DashboardPage';
8
12
  import { LogsPage } from './pages/LogsPage';
9
13
  import { SystemPage } from './pages/SystemPage';
10
14
  import { PluginsPage } from './pages/PluginsPage';
11
15
  import { UsersPage } from './pages/UsersPage';
12
16
  import { EntitlementsPage } from './pages/EntitlementsPage';
17
+ import { AuthPage } from './pages/AuthPage';
18
+ import { RateLimitPage } from './pages/RateLimitPage';
19
+ import { NotificationsPage } from './pages/NotificationsPage';
20
+ import { IntegrationsPage } from './pages/IntegrationsPage';
13
21
  import { PluginPage } from './pages/PluginPage';
14
22
  import { NotFoundPage } from './pages/NotFoundPage';
15
23
  import { api, type MenuContribution } from './api/controlPanelApi';
@@ -36,7 +44,7 @@ const builtInPluginNavItems: Record<string, NavigationItem> = {
36
44
  };
37
45
 
38
46
  // Routes that have dedicated page components
39
- const dedicatedRoutes = new Set(['/', '/plugins', '/logs', '/system', '/users', '/entitlements']);
47
+ const dedicatedRoutes = new Set(['/', '/plugins', '/logs', '/system', '/users', '/entitlements', '/auth', '/rate-limits', '/notifications', '/integrations']);
40
48
 
41
49
  // Package version - injected at build time or fallback
42
50
  const SERVER_VERSION = '1.0.0';
@@ -177,16 +185,17 @@ export function App() {
177
185
 
178
186
  return (
179
187
  <BrowserRouter basename={basePath || undefined}>
180
- <DashboardWidgetProvider>
181
- <QwickApp
182
- config={defaultConfig}
183
- logo={logo}
184
- footerContent={footerContent}
185
- enableScaffolding={true}
186
- navigationItems={navigationItems}
187
- showThemeSwitcher={true}
188
- showPaletteSwitcher={true}
189
- >
188
+ <WidgetComponentRegistryProvider initialComponents={getBuiltInWidgetComponents()}>
189
+ <DashboardWidgetProvider>
190
+ <QwickApp
191
+ config={defaultConfig}
192
+ logo={logo}
193
+ footerContent={footerContent}
194
+ enableScaffolding={true}
195
+ navigationItems={navigationItems}
196
+ showThemeSwitcher={true}
197
+ showPaletteSwitcher={true}
198
+ >
190
199
  <Routes>
191
200
  {/* Core routes */}
192
201
  <Route path="/" element={<DashboardPage />} />
@@ -201,6 +210,18 @@ export function App() {
201
210
  {registeredPlugins.has('entitlements') && (
202
211
  <Route path="/entitlements" element={<EntitlementsPage />} />
203
212
  )}
213
+ {registeredPlugins.has('auth') && (
214
+ <Route path="/auth" element={<AuthPage />} />
215
+ )}
216
+ {registeredPlugins.has('rate-limit') && (
217
+ <Route path="/rate-limits" element={<RateLimitPage />} />
218
+ )}
219
+ {registeredPlugins.has('notifications') && (
220
+ <Route path="/notifications" element={<NotificationsPage />} />
221
+ )}
222
+ {registeredPlugins.has('ai-proxy') && (
223
+ <Route path="/integrations" element={<IntegrationsPage />} />
224
+ )}
204
225
 
205
226
  {/* Dynamic plugin routes - render generic PluginPage for non-dedicated routes */}
206
227
  {pluginMenuItems
@@ -215,8 +236,9 @@ export function App() {
215
236
 
216
237
  <Route path="*" element={<NotFoundPage />} />
217
238
  </Routes>
218
- </QwickApp>
219
- </DashboardWidgetProvider>
239
+ </QwickApp>
240
+ </DashboardWidgetProvider>
241
+ </WidgetComponentRegistryProvider>
220
242
  </BrowserRouter>
221
243
  );
222
244
  }
@@ -255,6 +255,7 @@ export interface PluginDetailResponse {
255
255
  // ==================
256
256
 
257
257
  export type AuthPluginState = 'disabled' | 'enabled' | 'error';
258
+ export type AuthAdapterType = 'auth0' | 'supabase' | 'supertokens' | 'basic';
258
259
 
259
260
  export interface AuthConfigStatus {
260
261
  state: AuthPluginState;
@@ -262,6 +263,163 @@ export interface AuthConfigStatus {
262
263
  error?: string;
263
264
  missingVars?: string[];
264
265
  config?: Record<string, string>;
266
+ /** Runtime config from database (if available) */
267
+ runtimeConfig?: RuntimeAuthConfig;
268
+ }
269
+
270
+ export interface RuntimeAuthConfig {
271
+ adapter: AuthAdapterType | null;
272
+ config: {
273
+ auth0?: Auth0AdapterConfig;
274
+ supabase?: SupabaseAdapterConfig;
275
+ supertokens?: SupertokensAdapterConfig;
276
+ basic?: BasicAdapterConfig;
277
+ };
278
+ settings: {
279
+ authRequired?: boolean;
280
+ excludePaths?: string[];
281
+ debug?: boolean;
282
+ };
283
+ updatedAt: string;
284
+ updatedBy?: string;
285
+ }
286
+
287
+ export interface Auth0AdapterConfig {
288
+ domain: string;
289
+ clientId: string;
290
+ clientSecret: string;
291
+ baseUrl: string;
292
+ secret: string;
293
+ audience?: string;
294
+ scopes?: string[];
295
+ allowedRoles?: string[];
296
+ allowedDomains?: string[];
297
+ }
298
+
299
+ export interface SupabaseAdapterConfig {
300
+ url: string;
301
+ anonKey: string;
302
+ }
303
+
304
+ export interface BasicAdapterConfig {
305
+ username: string;
306
+ password: string;
307
+ realm?: string;
308
+ }
309
+
310
+ export interface SupertokensAdapterConfig {
311
+ connectionUri: string;
312
+ apiKey?: string;
313
+ appName: string;
314
+ apiDomain: string;
315
+ websiteDomain: string;
316
+ apiBasePath?: string;
317
+ websiteBasePath?: string;
318
+ enableEmailPassword?: boolean;
319
+ socialProviders?: {
320
+ google?: { clientId: string; clientSecret: string };
321
+ apple?: { clientId: string; clientSecret: string; keyId: string; teamId: string };
322
+ github?: { clientId: string; clientSecret: string };
323
+ };
324
+ }
325
+
326
+ export interface UpdateAuthConfigRequest {
327
+ adapter: AuthAdapterType;
328
+ config: Record<string, unknown>;
329
+ settings?: {
330
+ authRequired?: boolean;
331
+ excludePaths?: string[];
332
+ };
333
+ }
334
+
335
+ export interface TestProviderRequest {
336
+ adapter: AuthAdapterType;
337
+ config: Record<string, unknown>;
338
+ provider?: 'google' | 'github' | 'apple';
339
+ }
340
+
341
+ export interface TestProviderResponse {
342
+ success: boolean;
343
+ message: string;
344
+ details?: {
345
+ latency?: number;
346
+ version?: string;
347
+ };
348
+ }
349
+
350
+ // ==================
351
+ // Notifications API Types
352
+ // ==================
353
+
354
+ export interface NotificationsConnectionHealth {
355
+ isConnected: boolean;
356
+ isHealthy: boolean;
357
+ lastEventAt: string | null;
358
+ timeSinceLastEvent: number;
359
+ channelCount: number;
360
+ isReconnecting: boolean;
361
+ reconnectAttempts: number;
362
+ }
363
+
364
+ export interface NotificationsStatsResponse {
365
+ totalConnections: number;
366
+ currentConnections: number;
367
+ eventsProcessed: number;
368
+ eventsRouted: number;
369
+ eventsParseFailed: number;
370
+ eventsDroppedNoClients: number;
371
+ reconnectionAttempts: number;
372
+ lastReconnectionAt?: string;
373
+ clientsByType: {
374
+ device: number;
375
+ user: number;
376
+ };
377
+ connectionHealth: NotificationsConnectionHealth;
378
+ channels: string[];
379
+ lastEventAt?: string;
380
+ }
381
+
382
+ export interface NotificationsClient {
383
+ id: string;
384
+ deviceId?: string;
385
+ userId?: string;
386
+ connectedAt: string;
387
+ durationMs: number;
388
+ }
389
+
390
+ export interface NotificationsClientsResponse {
391
+ clients: NotificationsClient[];
392
+ total: number;
393
+ }
394
+
395
+ // ==================
396
+ // Rate Limit Config Types
397
+ // ==================
398
+
399
+ export type RateLimitStrategy = 'sliding-window' | 'fixed-window' | 'token-bucket';
400
+
401
+ export interface RateLimitConfig {
402
+ windowMs: number;
403
+ maxRequests: number;
404
+ strategy: RateLimitStrategy;
405
+ cleanupEnabled: boolean;
406
+ cleanupIntervalMs: number;
407
+ store: string;
408
+ cache: string;
409
+ cacheAvailable: boolean;
410
+ }
411
+
412
+ export interface RateLimitConfigUpdateRequest {
413
+ windowMs?: number;
414
+ maxRequests?: number;
415
+ strategy?: RateLimitStrategy;
416
+ cleanupEnabled?: boolean;
417
+ cleanupIntervalMs?: number;
418
+ }
419
+
420
+ export interface RateLimitConfigUpdateResponse {
421
+ success: boolean;
422
+ config: RateLimitConfig;
265
423
  }
266
424
 
267
425
  class ControlPanelApi {
@@ -279,6 +437,33 @@ class ControlPanelApi {
279
437
  this.baseUrl = baseUrl;
280
438
  }
281
439
 
440
+ /**
441
+ * Get the base URL for API requests.
442
+ */
443
+ getBaseUrl(): string {
444
+ return this.baseUrl;
445
+ }
446
+
447
+ /**
448
+ * Generic fetch method for API requests.
449
+ * Automatically prepends the base URL and /api prefix.
450
+ */
451
+ async fetch<T = unknown>(path: string, options?: RequestInit): Promise<T> {
452
+ const url = `${this.baseUrl}/api${path.startsWith('/') ? path : `/${path}`}`;
453
+ const response = await fetch(url, {
454
+ ...options,
455
+ headers: {
456
+ 'Content-Type': 'application/json',
457
+ ...options?.headers,
458
+ },
459
+ });
460
+ if (!response.ok) {
461
+ const error = await response.json().catch(() => ({}));
462
+ throw new Error(error.error || error.message || `Request failed: ${response.statusText}`);
463
+ }
464
+ return response.json();
465
+ }
466
+
282
467
  // ==================
283
468
  // Plugin Feature Detection
284
469
  // ==================
@@ -330,7 +515,7 @@ class ControlPanelApi {
330
515
  const params = new URLSearchParams();
331
516
  if (options.limit) params.set('limit', options.limit.toString());
332
517
  if (options.page) params.set('page', options.page.toString());
333
- if (options.search) params.set('search', options.search);
518
+ if (options.search) params.set('q', options.search);
334
519
 
335
520
  const response = await fetch(`${this.baseUrl}/api/users?${params}`);
336
521
  if (!response.ok) {
@@ -360,10 +545,18 @@ class ControlPanelApi {
360
545
  }
361
546
 
362
547
  async banUser(email: string, reason: string, expiresAt?: string): Promise<void> {
363
- const response = await fetch(`${this.baseUrl}/api/bans`, {
548
+ // Convert expiresAt datetime to duration in seconds
549
+ let duration: number | undefined;
550
+ if (expiresAt) {
551
+ const expiresDate = new Date(expiresAt);
552
+ const now = new Date();
553
+ duration = Math.max(0, Math.floor((expiresDate.getTime() - now.getTime()) / 1000));
554
+ }
555
+
556
+ const response = await fetch(`${this.baseUrl}/api/bans/email/${encodeURIComponent(email)}`, {
364
557
  method: 'POST',
365
558
  headers: { 'Content-Type': 'application/json' },
366
- body: JSON.stringify({ email, reason, expiresAt }),
559
+ body: JSON.stringify({ reason, duration }),
367
560
  });
368
561
  if (!response.ok) {
369
562
  const error = await response.json().catch(() => ({}));
@@ -372,7 +565,7 @@ class ControlPanelApi {
372
565
  }
373
566
 
374
567
  async unbanUser(email: string): Promise<void> {
375
- const response = await fetch(`${this.baseUrl}/api/bans/${encodeURIComponent(email)}`, {
568
+ const response = await fetch(`${this.baseUrl}/api/bans/email/${encodeURIComponent(email)}`, {
376
569
  method: 'DELETE',
377
570
  });
378
571
  if (!response.ok) {
@@ -381,11 +574,13 @@ class ControlPanelApi {
381
574
  }
382
575
 
383
576
  async checkBan(email: string): Promise<{ banned: boolean; ban?: Ban }> {
384
- const response = await fetch(`${this.baseUrl}/api/bans/check/${encodeURIComponent(email)}`);
577
+ const response = await fetch(`${this.baseUrl}/api/bans/email/${encodeURIComponent(email)}`);
385
578
  if (!response.ok) {
386
579
  throw new Error(`Ban check failed: ${response.statusText}`);
387
580
  }
388
- return response.json();
581
+ const data = await response.json();
582
+ // Backend returns { email, isBanned }, transform to expected shape
583
+ return { banned: data.isBanned };
389
584
  }
390
585
 
391
586
  // ==================
@@ -595,6 +790,134 @@ class ControlPanelApi {
595
790
  }
596
791
  return response.json();
597
792
  }
793
+
794
+ /**
795
+ * Update auth configuration (save to database for hot-reload)
796
+ */
797
+ async updateAuthConfig(request: UpdateAuthConfigRequest): Promise<{ success: boolean; message: string }> {
798
+ const response = await fetch(`${this.baseUrl}/api/auth/config`, {
799
+ method: 'PUT',
800
+ headers: { 'Content-Type': 'application/json' },
801
+ body: JSON.stringify(request),
802
+ });
803
+ if (!response.ok) {
804
+ const error = await response.json().catch(() => ({}));
805
+ throw new Error(error.error || `Auth config update failed: ${response.statusText}`);
806
+ }
807
+ return response.json();
808
+ }
809
+
810
+ /**
811
+ * Delete auth configuration (revert to environment variables)
812
+ */
813
+ async deleteAuthConfig(): Promise<{ success: boolean; message: string }> {
814
+ const response = await fetch(`${this.baseUrl}/api/auth/config`, {
815
+ method: 'DELETE',
816
+ });
817
+ if (!response.ok) {
818
+ const error = await response.json().catch(() => ({}));
819
+ throw new Error(error.error || `Auth config delete failed: ${response.statusText}`);
820
+ }
821
+ return response.json();
822
+ }
823
+
824
+ /**
825
+ * Test auth provider connection without saving
826
+ */
827
+ async testAuthProvider(request: TestProviderRequest): Promise<TestProviderResponse> {
828
+ const response = await fetch(`${this.baseUrl}/api/auth/test-provider`, {
829
+ method: 'POST',
830
+ headers: { 'Content-Type': 'application/json' },
831
+ body: JSON.stringify(request),
832
+ });
833
+ if (!response.ok) {
834
+ const error = await response.json().catch(() => ({}));
835
+ throw new Error(error.error || `Provider test failed: ${response.statusText}`);
836
+ }
837
+ return response.json();
838
+ }
839
+
840
+ /**
841
+ * Test current auth provider connection (uses existing env/runtime config)
842
+ */
843
+ async testCurrentAuthProvider(): Promise<TestProviderResponse> {
844
+ const response = await fetch(`${this.baseUrl}/api/auth/test-current`, {
845
+ method: 'POST',
846
+ headers: { 'Content-Type': 'application/json' },
847
+ });
848
+ if (!response.ok) {
849
+ const error = await response.json().catch(() => ({}));
850
+ throw new Error(error.error || `Provider test failed: ${response.statusText}`);
851
+ }
852
+ return response.json();
853
+ }
854
+
855
+ // ==================
856
+ // Rate Limit Config API
857
+ // ==================
858
+
859
+ async getRateLimitConfig(): Promise<RateLimitConfig> {
860
+ const response = await fetch(`${this.baseUrl}/api/rate-limit/config`);
861
+ if (!response.ok) {
862
+ throw new Error(`Rate limit config request failed: ${response.statusText}`);
863
+ }
864
+ return response.json();
865
+ }
866
+
867
+ async updateRateLimitConfig(updates: RateLimitConfigUpdateRequest): Promise<RateLimitConfigUpdateResponse> {
868
+ const response = await fetch(`${this.baseUrl}/api/rate-limit/config`, {
869
+ method: 'PUT',
870
+ headers: { 'Content-Type': 'application/json' },
871
+ body: JSON.stringify(updates),
872
+ });
873
+ if (!response.ok) {
874
+ const error = await response.json().catch(() => ({}));
875
+ throw new Error(error.error || `Rate limit config update failed: ${response.statusText}`);
876
+ }
877
+ return response.json();
878
+ }
879
+
880
+ // ==================
881
+ // Notifications API
882
+ // ==================
883
+
884
+ async getNotificationsStats(): Promise<NotificationsStatsResponse> {
885
+ const response = await fetch(`${this.baseUrl}/api/notifications/stats`);
886
+ if (!response.ok) {
887
+ throw new Error(`Notifications stats request failed: ${response.statusText}`);
888
+ }
889
+ return response.json();
890
+ }
891
+
892
+ async getNotificationsClients(): Promise<NotificationsClientsResponse> {
893
+ const response = await fetch(`${this.baseUrl}/api/notifications/clients`);
894
+ if (!response.ok) {
895
+ throw new Error(`Notifications clients request failed: ${response.statusText}`);
896
+ }
897
+ return response.json();
898
+ }
899
+
900
+ async disconnectNotificationsClient(clientId: string): Promise<{ success: boolean }> {
901
+ const response = await fetch(`${this.baseUrl}/api/notifications/clients/${encodeURIComponent(clientId)}`, {
902
+ method: 'DELETE',
903
+ });
904
+ if (!response.ok) {
905
+ const error = await response.json().catch(() => ({}));
906
+ throw new Error(error.error || `Disconnect client failed: ${response.statusText}`);
907
+ }
908
+ return response.json();
909
+ }
910
+
911
+ async forceNotificationsReconnect(): Promise<{ success: boolean; message: string }> {
912
+ const response = await fetch(`${this.baseUrl}/api/notifications/reconnect`, {
913
+ method: 'POST',
914
+ });
915
+ if (!response.ok) {
916
+ const error = await response.json().catch(() => ({}));
917
+ throw new Error(error.error || `Force reconnect failed: ${response.statusText}`);
918
+ }
919
+ return response.json();
920
+ }
598
921
  }
599
922
 
600
923
  export const api = new ControlPanelApi();
@@ -0,0 +1,58 @@
1
+ /**
2
+ * StatCard Component
3
+ *
4
+ * A reusable card component for displaying statistics with an icon,
5
+ * value, label, and optional sub-value.
6
+ *
7
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
8
+ */
9
+
10
+ import { Box, Card, CardContent } from '@mui/material';
11
+ import { Text } from '@qwickapps/react-framework';
12
+
13
+ export interface StatCardProps {
14
+ icon: React.ReactNode;
15
+ label: string;
16
+ value: string | number;
17
+ subValue?: string;
18
+ color?: string;
19
+ }
20
+
21
+ export function StatCard({
22
+ icon,
23
+ label,
24
+ value,
25
+ subValue,
26
+ color = 'var(--theme-primary)',
27
+ }: StatCardProps) {
28
+ return (
29
+ <Card sx={{ bgcolor: 'var(--theme-surface)', height: '100%' }}>
30
+ <CardContent sx={{ py: 1.5, '&:last-child': { pb: 1.5 } }}>
31
+ <Box sx={{ display: 'flex', alignItems: 'center', gap: 1.5 }}>
32
+ <Box sx={{ color }}>{icon}</Box>
33
+ <Box sx={{ flex: 1, minWidth: 0 }}>
34
+ <Text
35
+ variant="h4"
36
+ content={String(value)}
37
+ customColor="var(--theme-text-primary)"
38
+ fontWeight="600"
39
+ />
40
+ <Text
41
+ variant="caption"
42
+ content={label}
43
+ customColor="var(--theme-text-secondary)"
44
+ />
45
+ {subValue && (
46
+ <Text
47
+ variant="caption"
48
+ content={subValue}
49
+ customColor="var(--theme-text-secondary)"
50
+ sx={{ display: 'block', mt: 0.25 }}
51
+ />
52
+ )}
53
+ </Box>
54
+ </Box>
55
+ </CardContent>
56
+ </Card>
57
+ );
58
+ }
@@ -10,7 +10,7 @@
10
10
  * Copyright (c) 2025 QwickApps.com. All rights reserved.
11
11
  */
12
12
 
13
- import { ServiceHealthWidget } from './widgets';
13
+ import { ServiceHealthWidget, IntegrationStatusWidget, AuthStatusWidget, NotificationsStatsWidget } from './widgets';
14
14
  import type { WidgetComponent } from './WidgetComponentRegistry';
15
15
 
16
16
  /**
@@ -19,6 +19,9 @@ import type { WidgetComponent } from './WidgetComponentRegistry';
19
19
  */
20
20
  export const builtInWidgetComponents: Record<string, React.ComponentType> = {
21
21
  ServiceHealthWidget: ServiceHealthWidget,
22
+ IntegrationStatusWidget: IntegrationStatusWidget,
23
+ AuthStatusWidget: AuthStatusWidget,
24
+ NotificationsStatsWidget: NotificationsStatsWidget,
22
25
  };
23
26
 
24
27
  /**
@@ -31,5 +34,8 @@ export const builtInWidgetComponents: Record<string, React.ComponentType> = {
31
34
  export function getBuiltInWidgetComponents(): WidgetComponent[] {
32
35
  return [
33
36
  { name: 'ServiceHealthWidget', component: ServiceHealthWidget },
37
+ { name: 'IntegrationStatusWidget', component: IntegrationStatusWidget },
38
+ { name: 'AuthStatusWidget', component: AuthStatusWidget },
39
+ { name: 'NotificationsStatsWidget', component: NotificationsStatsWidget },
34
40
  ];
35
41
  }