@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
@@ -0,0 +1,666 @@
1
+ /**
2
+ * Parental Plugin
3
+ *
4
+ * Generic parental/guardian controls for @qwickapps/server.
5
+ * Supports PIN protection, profile restrictions, schedules, and activity logging.
6
+ * Uses adapters for domain-specific behavior (kids, gaming, education).
7
+ *
8
+ * Copyright (c) 2025 QwickApps.com. All rights reserved.
9
+ */
10
+ import { createHash } from 'crypto';
11
+ // Store instances for helper access
12
+ let currentStore = null;
13
+ let currentAdapter = null;
14
+ let currentConfig = null;
15
+ /**
16
+ * Hash a PIN using SHA-256
17
+ */
18
+ function hashPin(pin) {
19
+ return createHash('sha256').update(pin).digest('hex');
20
+ }
21
+ /**
22
+ * Check if current time is within allowed schedule
23
+ */
24
+ function isWithinSchedule(schedule) {
25
+ const now = new Date();
26
+ const dayNames = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'];
27
+ const today = dayNames[now.getDay()];
28
+ const todaySchedule = schedule[today];
29
+ if (!todaySchedule)
30
+ return true; // No schedule for today = allowed
31
+ const currentTime = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}`;
32
+ return currentTime >= todaySchedule.start && currentTime <= todaySchedule.end;
33
+ }
34
+ /**
35
+ * Create the Parental plugin
36
+ */
37
+ export function createParentalPlugin(config) {
38
+ const debug = config.debug || false;
39
+ const apiPrefix = config.api?.prefix || '/parental';
40
+ const maxPinAttempts = config.maxPinAttempts || 5;
41
+ const pinLockoutMinutes = config.pinLockoutMinutes || 30;
42
+ function log(message, data) {
43
+ if (debug) {
44
+ console.log(`[ParentalPlugin] ${message}`, data || '');
45
+ }
46
+ }
47
+ return {
48
+ id: 'parental',
49
+ name: 'Parental',
50
+ version: '1.0.0',
51
+ async onStart(_pluginConfig, registry) {
52
+ log('Starting parental plugin');
53
+ // Initialize the store (creates tables if needed)
54
+ await config.store.initialize();
55
+ log('Parental store initialized');
56
+ // Store references for helper access
57
+ currentStore = config.store;
58
+ currentAdapter = config.adapter;
59
+ currentConfig = config;
60
+ // Register health check
61
+ registry.registerHealthCheck({
62
+ name: 'parental-store',
63
+ type: 'custom',
64
+ check: async () => {
65
+ try {
66
+ return { healthy: true };
67
+ }
68
+ catch {
69
+ return { healthy: false };
70
+ }
71
+ },
72
+ });
73
+ // Add API routes if enabled
74
+ if (config.api?.enabled !== false) {
75
+ // ═══════════════════════════════════════════════════════════════════════
76
+ // Guardian Settings Routes
77
+ // ═══════════════════════════════════════════════════════════════════════
78
+ // Get guardian settings
79
+ registry.addRoute({
80
+ method: 'get',
81
+ path: `${apiPrefix}/settings/:userId`,
82
+ pluginId: 'parental',
83
+ handler: async (req, res) => {
84
+ try {
85
+ const { userId } = req.params;
86
+ const settings = await getGuardianSettings(userId);
87
+ if (!settings) {
88
+ return res.status(404).json({ error: 'Settings not found' });
89
+ }
90
+ // Don't expose PIN hash
91
+ const { pin_hash: _pin, ...safeSettings } = settings;
92
+ res.json({ ...safeSettings, has_pin: !!_pin });
93
+ }
94
+ catch (error) {
95
+ console.error('[ParentalPlugin] Get settings error:', error);
96
+ res.status(500).json({ error: 'Failed to get settings' });
97
+ }
98
+ },
99
+ });
100
+ // Create guardian settings
101
+ registry.addRoute({
102
+ method: 'post',
103
+ path: `${apiPrefix}/settings`,
104
+ pluginId: 'parental',
105
+ handler: async (req, res) => {
106
+ try {
107
+ const input = req.body;
108
+ // Hash PIN if provided
109
+ const processedInput = {
110
+ ...input,
111
+ adapter_type: config.adapter.name,
112
+ pin: input.pin ? hashPin(input.pin) : undefined,
113
+ };
114
+ const settings = await createGuardianSettings(processedInput);
115
+ const { pin_hash: _pin, ...safeSettings } = settings;
116
+ res.status(201).json({ ...safeSettings, has_pin: !!_pin });
117
+ }
118
+ catch (error) {
119
+ console.error('[ParentalPlugin] Create settings error:', error);
120
+ res.status(500).json({ error: 'Failed to create settings' });
121
+ }
122
+ },
123
+ });
124
+ // Update guardian settings
125
+ registry.addRoute({
126
+ method: 'patch',
127
+ path: `${apiPrefix}/settings/:userId`,
128
+ pluginId: 'parental',
129
+ handler: async (req, res) => {
130
+ try {
131
+ const { userId } = req.params;
132
+ const input = req.body;
133
+ const settings = await updateGuardianSettings(userId, input);
134
+ if (!settings) {
135
+ return res.status(404).json({ error: 'Settings not found' });
136
+ }
137
+ const { pin_hash: _pin, ...safeSettings } = settings;
138
+ res.json({ ...safeSettings, has_pin: !!_pin });
139
+ }
140
+ catch (error) {
141
+ console.error('[ParentalPlugin] Update settings error:', error);
142
+ res.status(500).json({ error: 'Failed to update settings' });
143
+ }
144
+ },
145
+ });
146
+ // Set PIN
147
+ registry.addRoute({
148
+ method: 'post',
149
+ path: `${apiPrefix}/settings/:userId/pin`,
150
+ pluginId: 'parental',
151
+ handler: async (req, res) => {
152
+ try {
153
+ const { userId } = req.params;
154
+ const { pin, current_pin } = req.body;
155
+ if (!pin || pin.length < 4) {
156
+ return res.status(400).json({ error: 'PIN must be at least 4 characters' });
157
+ }
158
+ // If user already has PIN, verify current PIN
159
+ const settings = await getGuardianSettings(userId);
160
+ if (settings?.pin_hash) {
161
+ if (!current_pin) {
162
+ return res.status(400).json({ error: 'Current PIN required to change PIN' });
163
+ }
164
+ const isValid = await verifyPin(userId, current_pin);
165
+ if (!isValid) {
166
+ return res.status(401).json({ error: 'Invalid current PIN' });
167
+ }
168
+ }
169
+ await setPin(userId, pin);
170
+ res.json({ success: true });
171
+ }
172
+ catch (error) {
173
+ console.error('[ParentalPlugin] Set PIN error:', error);
174
+ res.status(500).json({ error: 'Failed to set PIN' });
175
+ }
176
+ },
177
+ });
178
+ // Verify PIN
179
+ registry.addRoute({
180
+ method: 'post',
181
+ path: `${apiPrefix}/settings/:userId/verify-pin`,
182
+ pluginId: 'parental',
183
+ handler: async (req, res) => {
184
+ try {
185
+ const { userId } = req.params;
186
+ const { pin } = req.body;
187
+ if (!pin) {
188
+ return res.status(400).json({ error: 'PIN required' });
189
+ }
190
+ const isValid = await verifyPin(userId, pin);
191
+ if (!isValid) {
192
+ // Increment failed attempts
193
+ const attempts = await incrementFailedPinAttempts(userId);
194
+ if (attempts >= maxPinAttempts) {
195
+ // Lock the account
196
+ const lockUntil = new Date(Date.now() + pinLockoutMinutes * 60 * 1000);
197
+ return res.status(423).json({
198
+ error: 'Account locked due to too many failed attempts',
199
+ locked_until: lockUntil,
200
+ attempts,
201
+ });
202
+ }
203
+ return res.status(401).json({
204
+ error: 'Invalid PIN',
205
+ attempts_remaining: maxPinAttempts - attempts,
206
+ });
207
+ }
208
+ // Reset failed attempts on success
209
+ await resetFailedPinAttempts(userId);
210
+ res.json({ success: true });
211
+ }
212
+ catch (error) {
213
+ console.error('[ParentalPlugin] Verify PIN error:', error);
214
+ res.status(500).json({ error: 'Failed to verify PIN' });
215
+ }
216
+ },
217
+ });
218
+ // ═══════════════════════════════════════════════════════════════════════
219
+ // Profile Restrictions Routes
220
+ // ═══════════════════════════════════════════════════════════════════════
221
+ // Get restrictions for a profile
222
+ registry.addRoute({
223
+ method: 'get',
224
+ path: `${apiPrefix}/restrictions/:profileId`,
225
+ pluginId: 'parental',
226
+ handler: async (req, res) => {
227
+ try {
228
+ const { profileId } = req.params;
229
+ const restrictions = await getRestrictions(profileId);
230
+ res.json(restrictions);
231
+ }
232
+ catch (error) {
233
+ console.error('[ParentalPlugin] Get restrictions error:', error);
234
+ res.status(500).json({ error: 'Failed to get restrictions' });
235
+ }
236
+ },
237
+ });
238
+ // Create restriction
239
+ registry.addRoute({
240
+ method: 'post',
241
+ path: `${apiPrefix}/restrictions`,
242
+ pluginId: 'parental',
243
+ handler: async (req, res) => {
244
+ try {
245
+ const input = req.body;
246
+ // Validate with adapter
247
+ if (config.adapter.validateRestriction) {
248
+ const validation = config.adapter.validateRestriction(input);
249
+ if (!validation.valid) {
250
+ return res.status(400).json({ error: 'Invalid restriction', errors: validation.errors });
251
+ }
252
+ }
253
+ const restriction = await createRestriction(input);
254
+ res.status(201).json(restriction);
255
+ }
256
+ catch (error) {
257
+ console.error('[ParentalPlugin] Create restriction error:', error);
258
+ res.status(500).json({ error: 'Failed to create restriction' });
259
+ }
260
+ },
261
+ });
262
+ // Update restriction
263
+ registry.addRoute({
264
+ method: 'patch',
265
+ path: `${apiPrefix}/restrictions/:id`,
266
+ pluginId: 'parental',
267
+ handler: async (req, res) => {
268
+ try {
269
+ const { id } = req.params;
270
+ const updates = req.body;
271
+ const restriction = await updateRestriction(id, updates);
272
+ if (!restriction) {
273
+ return res.status(404).json({ error: 'Restriction not found' });
274
+ }
275
+ res.json(restriction);
276
+ }
277
+ catch (error) {
278
+ console.error('[ParentalPlugin] Update restriction error:', error);
279
+ res.status(500).json({ error: 'Failed to update restriction' });
280
+ }
281
+ },
282
+ });
283
+ // Delete restriction
284
+ registry.addRoute({
285
+ method: 'delete',
286
+ path: `${apiPrefix}/restrictions/:id`,
287
+ pluginId: 'parental',
288
+ handler: async (req, res) => {
289
+ try {
290
+ const { id } = req.params;
291
+ const deleted = await deleteRestriction(id);
292
+ if (!deleted) {
293
+ return res.status(404).json({ error: 'Restriction not found' });
294
+ }
295
+ res.status(204).send();
296
+ }
297
+ catch (error) {
298
+ console.error('[ParentalPlugin] Delete restriction error:', error);
299
+ res.status(500).json({ error: 'Failed to delete restriction' });
300
+ }
301
+ },
302
+ });
303
+ // Pause profile
304
+ registry.addRoute({
305
+ method: 'post',
306
+ path: `${apiPrefix}/restrictions/:profileId/pause`,
307
+ pluginId: 'parental',
308
+ handler: async (req, res) => {
309
+ try {
310
+ const { profileId } = req.params;
311
+ const { until, reason } = req.body;
312
+ await pauseProfile(profileId, until ? new Date(until) : undefined, reason);
313
+ res.json({ success: true, paused: true });
314
+ }
315
+ catch (error) {
316
+ console.error('[ParentalPlugin] Pause profile error:', error);
317
+ res.status(500).json({ error: 'Failed to pause profile' });
318
+ }
319
+ },
320
+ });
321
+ // Resume profile
322
+ registry.addRoute({
323
+ method: 'post',
324
+ path: `${apiPrefix}/restrictions/:profileId/resume`,
325
+ pluginId: 'parental',
326
+ handler: async (req, res) => {
327
+ try {
328
+ const { profileId } = req.params;
329
+ await resumeProfile(profileId);
330
+ res.json({ success: true, paused: false });
331
+ }
332
+ catch (error) {
333
+ console.error('[ParentalPlugin] Resume profile error:', error);
334
+ res.status(500).json({ error: 'Failed to resume profile' });
335
+ }
336
+ },
337
+ });
338
+ // Check profile access
339
+ registry.addRoute({
340
+ method: 'get',
341
+ path: `${apiPrefix}/restrictions/:profileId/check`,
342
+ pluginId: 'parental',
343
+ handler: async (req, res) => {
344
+ try {
345
+ const { profileId } = req.params;
346
+ const result = await checkProfileAccess(profileId);
347
+ res.json(result);
348
+ }
349
+ catch (error) {
350
+ console.error('[ParentalPlugin] Check access error:', error);
351
+ res.status(500).json({ error: 'Failed to check access' });
352
+ }
353
+ },
354
+ });
355
+ // ═══════════════════════════════════════════════════════════════════════
356
+ // Activity Log Routes
357
+ // ═══════════════════════════════════════════════════════════════════════
358
+ // Log activity
359
+ registry.addRoute({
360
+ method: 'post',
361
+ path: `${apiPrefix}/activity`,
362
+ pluginId: 'parental',
363
+ handler: async (req, res) => {
364
+ try {
365
+ const input = req.body;
366
+ const activity = await logActivity({
367
+ ...input,
368
+ adapter_type: config.adapter.name,
369
+ });
370
+ res.status(201).json(activity);
371
+ }
372
+ catch (error) {
373
+ console.error('[ParentalPlugin] Log activity error:', error);
374
+ res.status(500).json({ error: 'Failed to log activity' });
375
+ }
376
+ },
377
+ });
378
+ // Get activity log
379
+ registry.addRoute({
380
+ method: 'get',
381
+ path: `${apiPrefix}/activity/:userId`,
382
+ pluginId: 'parental',
383
+ handler: async (req, res) => {
384
+ try {
385
+ const { userId } = req.params;
386
+ const limit = parseInt(req.query.limit) || 100;
387
+ const profileId = req.query.profileId;
388
+ const activities = await getActivityLog(userId, limit, profileId);
389
+ // Format details with adapter if available
390
+ const formattedActivities = activities.map((activity) => {
391
+ if (config.adapter.formatActivityDetails) {
392
+ return {
393
+ ...activity,
394
+ formatted_details: config.adapter.formatActivityDetails(activity),
395
+ };
396
+ }
397
+ return activity;
398
+ });
399
+ res.json(formattedActivities);
400
+ }
401
+ catch (error) {
402
+ console.error('[ParentalPlugin] Get activity error:', error);
403
+ res.status(500).json({ error: 'Failed to get activity log' });
404
+ }
405
+ },
406
+ });
407
+ // Get adapter info (activity types, defaults)
408
+ registry.addRoute({
409
+ method: 'get',
410
+ path: `${apiPrefix}/adapter-info`,
411
+ pluginId: 'parental',
412
+ handler: async (_req, res) => {
413
+ try {
414
+ res.json({
415
+ name: config.adapter.name,
416
+ activity_types: config.adapter.getActivityTypes(),
417
+ default_daily_limit: config.adapter.getDefaultDailyLimit(),
418
+ });
419
+ }
420
+ catch (error) {
421
+ console.error('[ParentalPlugin] Get adapter info error:', error);
422
+ res.status(500).json({ error: 'Failed to get adapter info' });
423
+ }
424
+ },
425
+ });
426
+ }
427
+ log('Parental plugin started');
428
+ },
429
+ async onStop() {
430
+ log('Stopping parental plugin');
431
+ await config.store.shutdown();
432
+ currentStore = null;
433
+ currentAdapter = null;
434
+ currentConfig = null;
435
+ log('Parental plugin stopped');
436
+ },
437
+ };
438
+ }
439
+ // ═══════════════════════════════════════════════════════════════════════════
440
+ // Helper Functions
441
+ // ═══════════════════════════════════════════════════════════════════════════
442
+ /**
443
+ * Get the current parental store instance
444
+ */
445
+ export function getParentalStore() {
446
+ return currentStore;
447
+ }
448
+ /**
449
+ * Get the current parental adapter instance
450
+ */
451
+ export function getParentalAdapter() {
452
+ return currentAdapter;
453
+ }
454
+ // ─────────────────────────────────────────────────────────────────────────────
455
+ // Guardian Settings Helpers
456
+ // ─────────────────────────────────────────────────────────────────────────────
457
+ /**
458
+ * Get guardian settings for a user
459
+ */
460
+ export async function getGuardianSettings(userId) {
461
+ if (!currentStore) {
462
+ throw new Error('Parental plugin not initialized');
463
+ }
464
+ return currentStore.getSettings(userId);
465
+ }
466
+ /**
467
+ * Create guardian settings
468
+ */
469
+ export async function createGuardianSettings(input) {
470
+ if (!currentStore) {
471
+ throw new Error('Parental plugin not initialized');
472
+ }
473
+ return currentStore.createSettings(input);
474
+ }
475
+ /**
476
+ * Update guardian settings
477
+ */
478
+ export async function updateGuardianSettings(userId, input) {
479
+ if (!currentStore) {
480
+ throw new Error('Parental plugin not initialized');
481
+ }
482
+ return currentStore.updateSettings(userId, input);
483
+ }
484
+ /**
485
+ * Set PIN for guardian
486
+ */
487
+ export async function setPin(userId, pin) {
488
+ if (!currentStore) {
489
+ throw new Error('Parental plugin not initialized');
490
+ }
491
+ const pinHash = hashPin(pin);
492
+ return currentStore.setPin(userId, pinHash);
493
+ }
494
+ /**
495
+ * Verify PIN
496
+ */
497
+ export async function verifyPin(userId, pin) {
498
+ if (!currentStore) {
499
+ throw new Error('Parental plugin not initialized');
500
+ }
501
+ const pinHash = hashPin(pin);
502
+ return currentStore.verifyPin(userId, pinHash);
503
+ }
504
+ /**
505
+ * Increment failed PIN attempts
506
+ */
507
+ export async function incrementFailedPinAttempts(userId) {
508
+ if (!currentStore) {
509
+ throw new Error('Parental plugin not initialized');
510
+ }
511
+ return currentStore.incrementFailedPinAttempts(userId);
512
+ }
513
+ /**
514
+ * Reset failed PIN attempts
515
+ */
516
+ export async function resetFailedPinAttempts(userId) {
517
+ if (!currentStore) {
518
+ throw new Error('Parental plugin not initialized');
519
+ }
520
+ return currentStore.resetFailedPinAttempts(userId);
521
+ }
522
+ // ─────────────────────────────────────────────────────────────────────────────
523
+ // Profile Restrictions Helpers
524
+ // ─────────────────────────────────────────────────────────────────────────────
525
+ /**
526
+ * Get restrictions for a profile
527
+ */
528
+ export async function getRestrictions(profileId) {
529
+ if (!currentStore) {
530
+ throw new Error('Parental plugin not initialized');
531
+ }
532
+ return currentStore.getRestrictions(profileId);
533
+ }
534
+ /**
535
+ * Create a restriction
536
+ */
537
+ export async function createRestriction(input) {
538
+ if (!currentStore) {
539
+ throw new Error('Parental plugin not initialized');
540
+ }
541
+ return currentStore.createRestriction(input);
542
+ }
543
+ /**
544
+ * Update a restriction
545
+ */
546
+ export async function updateRestriction(id, updates) {
547
+ if (!currentStore) {
548
+ throw new Error('Parental plugin not initialized');
549
+ }
550
+ return currentStore.updateRestriction(id, updates);
551
+ }
552
+ /**
553
+ * Delete a restriction (soft delete)
554
+ */
555
+ export async function deleteRestriction(id) {
556
+ if (!currentStore) {
557
+ throw new Error('Parental plugin not initialized');
558
+ }
559
+ return currentStore.deleteRestriction(id);
560
+ }
561
+ /**
562
+ * Pause a profile's access
563
+ */
564
+ export async function pauseProfile(profileId, until, reason) {
565
+ if (!currentStore) {
566
+ throw new Error('Parental plugin not initialized');
567
+ }
568
+ return currentStore.pauseProfile(profileId, until, reason);
569
+ }
570
+ /**
571
+ * Resume a profile's access
572
+ */
573
+ export async function resumeProfile(profileId) {
574
+ if (!currentStore) {
575
+ throw new Error('Parental plugin not initialized');
576
+ }
577
+ return currentStore.resumeProfile(profileId);
578
+ }
579
+ /**
580
+ * Check if a profile has access based on restrictions
581
+ */
582
+ export async function checkProfileAccess(profileId) {
583
+ if (!currentStore) {
584
+ throw new Error('Parental plugin not initialized');
585
+ }
586
+ const restrictions = await currentStore.getRestrictions(profileId);
587
+ // Check if any restrictions are paused
588
+ for (const restriction of restrictions) {
589
+ if (restriction.is_paused) {
590
+ // Check if pause has expired
591
+ if (restriction.pause_until && new Date() > restriction.pause_until) {
592
+ // Auto-resume (should be handled by cron, but check here too)
593
+ continue;
594
+ }
595
+ return {
596
+ allowed: false,
597
+ reason: restriction.pause_reason || 'Profile is paused',
598
+ };
599
+ }
600
+ // Check schedule restrictions
601
+ if (restriction.schedule) {
602
+ if (!isWithinSchedule(restriction.schedule)) {
603
+ // Find when access becomes available
604
+ const now = new Date();
605
+ const dayNames = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'];
606
+ const today = dayNames[now.getDay()];
607
+ const todaySchedule = restriction.schedule[today];
608
+ let availableAt;
609
+ if (todaySchedule) {
610
+ const [hours, minutes] = todaySchedule.start.split(':').map(Number);
611
+ availableAt = new Date(now);
612
+ availableAt.setHours(hours, minutes, 0, 0);
613
+ // If we're past today's start, set to tomorrow
614
+ if (now > availableAt) {
615
+ availableAt.setDate(availableAt.getDate() + 1);
616
+ }
617
+ }
618
+ return {
619
+ allowed: false,
620
+ reason: 'Outside allowed hours',
621
+ available_at: availableAt,
622
+ };
623
+ }
624
+ }
625
+ }
626
+ // Get time limit restriction and check remaining time
627
+ const timeLimitRestriction = restrictions.find((r) => r.restriction_type === 'time_limit');
628
+ if (timeLimitRestriction?.daily_limit_minutes) {
629
+ // Note: Actual time tracking would be done via usage-plugin
630
+ // This is a placeholder for the check result
631
+ return {
632
+ allowed: true,
633
+ minutes_remaining: timeLimitRestriction.daily_limit_minutes,
634
+ };
635
+ }
636
+ return { allowed: true };
637
+ }
638
+ // ─────────────────────────────────────────────────────────────────────────────
639
+ // Activity Log Helpers
640
+ // ─────────────────────────────────────────────────────────────────────────────
641
+ /**
642
+ * Log an activity
643
+ */
644
+ export async function logActivity(input) {
645
+ if (!currentStore) {
646
+ throw new Error('Parental plugin not initialized');
647
+ }
648
+ // Call adapter hook if available
649
+ if (currentAdapter?.onRestrictionViolation && input.activity_type === 'restriction_violation') {
650
+ await currentAdapter.onRestrictionViolation(input.profile_id || '', input.details?.reason || 'Unknown');
651
+ }
652
+ if (currentAdapter?.onDailyLimitReached && input.activity_type === 'time_limit_reached') {
653
+ await currentAdapter.onDailyLimitReached(input.profile_id || '');
654
+ }
655
+ return currentStore.logActivity(input);
656
+ }
657
+ /**
658
+ * Get activity log
659
+ */
660
+ export async function getActivityLog(userId, limit = 100, profileId) {
661
+ if (!currentStore) {
662
+ throw new Error('Parental plugin not initialized');
663
+ }
664
+ return currentStore.getActivityLog(userId, limit, profileId);
665
+ }
666
+ //# sourceMappingURL=parental-plugin.js.map