@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.
- package/README.md +157 -0
- package/dist/core/control-panel.d.ts.map +1 -1
- package/dist/core/control-panel.js +114 -0
- package/dist/core/control-panel.js.map +1 -1
- package/dist/core/types.d.ts +19 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -3
- package/dist/index.js.map +1 -1
- package/dist/plugins/auth/adapter-wrapper.d.ts +47 -0
- package/dist/plugins/auth/adapter-wrapper.d.ts.map +1 -0
- package/dist/plugins/auth/adapter-wrapper.js +166 -0
- package/dist/plugins/auth/adapter-wrapper.js.map +1 -0
- package/dist/plugins/auth/adapter-wrapper.test.d.ts +7 -0
- package/dist/plugins/auth/adapter-wrapper.test.d.ts.map +1 -0
- package/dist/plugins/auth/adapter-wrapper.test.js +303 -0
- package/dist/plugins/auth/adapter-wrapper.test.js.map +1 -0
- package/dist/plugins/auth/config-store.d.ts +11 -0
- package/dist/plugins/auth/config-store.d.ts.map +1 -0
- package/dist/plugins/auth/config-store.js +232 -0
- package/dist/plugins/auth/config-store.js.map +1 -0
- package/dist/plugins/auth/config-store.test.d.ts +7 -0
- package/dist/plugins/auth/config-store.test.d.ts.map +1 -0
- package/dist/plugins/auth/config-store.test.js +299 -0
- package/dist/plugins/auth/config-store.test.js.map +1 -0
- package/dist/plugins/auth/env-config.d.ts +51 -1
- package/dist/plugins/auth/env-config.d.ts.map +1 -1
- package/dist/plugins/auth/env-config.js +640 -7
- package/dist/plugins/auth/env-config.js.map +1 -1
- package/dist/plugins/auth/index.d.ts +6 -2
- package/dist/plugins/auth/index.d.ts.map +1 -1
- package/dist/plugins/auth/index.js +5 -1
- package/dist/plugins/auth/index.js.map +1 -1
- package/dist/plugins/auth/types.d.ts +106 -0
- package/dist/plugins/auth/types.d.ts.map +1 -1
- package/dist/plugins/bans/bans-plugin.d.ts.map +1 -1
- package/dist/plugins/bans/bans-plugin.js +12 -3
- package/dist/plugins/bans/bans-plugin.js.map +1 -1
- package/dist/plugins/devices/__tests__/devices-plugin.test.d.ts +11 -0
- package/dist/plugins/devices/__tests__/devices-plugin.test.d.ts.map +1 -0
- package/dist/plugins/devices/__tests__/devices-plugin.test.js +410 -0
- package/dist/plugins/devices/__tests__/devices-plugin.test.js.map +1 -0
- package/dist/plugins/devices/__tests__/token-utils.test.d.ts +7 -0
- package/dist/plugins/devices/__tests__/token-utils.test.d.ts.map +1 -0
- package/dist/plugins/devices/__tests__/token-utils.test.js +197 -0
- package/dist/plugins/devices/__tests__/token-utils.test.js.map +1 -0
- package/dist/plugins/devices/adapters/compute-adapter.d.ts +36 -0
- package/dist/plugins/devices/adapters/compute-adapter.d.ts.map +1 -0
- package/dist/plugins/devices/adapters/compute-adapter.js +100 -0
- package/dist/plugins/devices/adapters/compute-adapter.js.map +1 -0
- package/dist/plugins/devices/adapters/index.d.ts +12 -0
- package/dist/plugins/devices/adapters/index.d.ts.map +1 -0
- package/dist/plugins/devices/adapters/index.js +10 -0
- package/dist/plugins/devices/adapters/index.js.map +1 -0
- package/dist/plugins/devices/adapters/mobile-adapter.d.ts +41 -0
- package/dist/plugins/devices/adapters/mobile-adapter.d.ts.map +1 -0
- package/dist/plugins/devices/adapters/mobile-adapter.js +131 -0
- package/dist/plugins/devices/adapters/mobile-adapter.js.map +1 -0
- package/dist/plugins/devices/devices-plugin.d.ts +70 -0
- package/dist/plugins/devices/devices-plugin.d.ts.map +1 -0
- package/dist/plugins/devices/devices-plugin.js +453 -0
- package/dist/plugins/devices/devices-plugin.js.map +1 -0
- package/dist/plugins/devices/index.d.ts +18 -0
- package/dist/plugins/devices/index.d.ts.map +1 -0
- package/dist/plugins/devices/index.js +18 -0
- package/dist/plugins/devices/index.js.map +1 -0
- package/dist/plugins/devices/stores/index.d.ts +9 -0
- package/dist/plugins/devices/stores/index.d.ts.map +1 -0
- package/dist/plugins/devices/stores/index.js +9 -0
- package/dist/plugins/devices/stores/index.js.map +1 -0
- package/dist/plugins/devices/stores/postgres-store.d.ts +26 -0
- package/dist/plugins/devices/stores/postgres-store.d.ts.map +1 -0
- package/dist/plugins/devices/stores/postgres-store.js +199 -0
- package/dist/plugins/devices/stores/postgres-store.js.map +1 -0
- package/dist/plugins/devices/token-utils.d.ts +100 -0
- package/dist/plugins/devices/token-utils.d.ts.map +1 -0
- package/dist/plugins/devices/token-utils.js +162 -0
- package/dist/plugins/devices/token-utils.js.map +1 -0
- package/dist/plugins/devices/types.d.ts +307 -0
- package/dist/plugins/devices/types.d.ts.map +1 -0
- package/dist/plugins/devices/types.js +10 -0
- package/dist/plugins/devices/types.js.map +1 -0
- package/dist/plugins/index.d.ts +18 -4
- package/dist/plugins/index.d.ts.map +1 -1
- package/dist/plugins/index.js +16 -2
- package/dist/plugins/index.js.map +1 -1
- package/dist/plugins/notifications/__tests__/notifications-manager.test.d.ts +5 -0
- package/dist/plugins/notifications/__tests__/notifications-manager.test.d.ts.map +1 -0
- package/dist/plugins/notifications/__tests__/notifications-manager.test.js +470 -0
- package/dist/plugins/notifications/__tests__/notifications-manager.test.js.map +1 -0
- package/dist/plugins/notifications/index.d.ts +71 -0
- package/dist/plugins/notifications/index.d.ts.map +1 -0
- package/dist/plugins/notifications/index.js +72 -0
- package/dist/plugins/notifications/index.js.map +1 -0
- package/dist/plugins/notifications/notifications-manager.d.ts +182 -0
- package/dist/plugins/notifications/notifications-manager.d.ts.map +1 -0
- package/dist/plugins/notifications/notifications-manager.js +610 -0
- package/dist/plugins/notifications/notifications-manager.js.map +1 -0
- package/dist/plugins/notifications/notifications-plugin.d.ts +83 -0
- package/dist/plugins/notifications/notifications-plugin.d.ts.map +1 -0
- package/dist/plugins/notifications/notifications-plugin.js +337 -0
- package/dist/plugins/notifications/notifications-plugin.js.map +1 -0
- package/dist/plugins/notifications/types.d.ts +164 -0
- package/dist/plugins/notifications/types.d.ts.map +1 -0
- package/dist/plugins/notifications/types.js +9 -0
- package/dist/plugins/notifications/types.js.map +1 -0
- package/dist/plugins/parental/__tests__/parental-plugin.test.d.ts +12 -0
- package/dist/plugins/parental/__tests__/parental-plugin.test.d.ts.map +1 -0
- package/dist/plugins/parental/__tests__/parental-plugin.test.js +349 -0
- package/dist/plugins/parental/__tests__/parental-plugin.test.js.map +1 -0
- package/dist/plugins/parental/adapters/index.d.ts +8 -0
- package/dist/plugins/parental/adapters/index.d.ts.map +1 -0
- package/dist/plugins/parental/adapters/index.js +7 -0
- package/dist/plugins/parental/adapters/index.js.map +1 -0
- package/dist/plugins/parental/adapters/kids-adapter.d.ts +24 -0
- package/dist/plugins/parental/adapters/kids-adapter.d.ts.map +1 -0
- package/dist/plugins/parental/adapters/kids-adapter.js +174 -0
- package/dist/plugins/parental/adapters/kids-adapter.js.map +1 -0
- package/dist/plugins/parental/index.d.ts +14 -0
- package/dist/plugins/parental/index.d.ts.map +1 -0
- package/dist/plugins/parental/index.js +15 -0
- package/dist/plugins/parental/index.js.map +1 -0
- package/dist/plugins/parental/parental-plugin.d.ts +88 -0
- package/dist/plugins/parental/parental-plugin.d.ts.map +1 -0
- package/dist/plugins/parental/parental-plugin.js +666 -0
- package/dist/plugins/parental/parental-plugin.js.map +1 -0
- package/dist/plugins/parental/stores/index.d.ts +7 -0
- package/dist/plugins/parental/stores/index.d.ts.map +1 -0
- package/dist/plugins/parental/stores/index.js +7 -0
- package/dist/plugins/parental/stores/index.js.map +1 -0
- package/dist/plugins/parental/stores/postgres-store.d.ts +10 -0
- package/dist/plugins/parental/stores/postgres-store.d.ts.map +1 -0
- package/dist/plugins/parental/stores/postgres-store.js +209 -0
- package/dist/plugins/parental/stores/postgres-store.js.map +1 -0
- package/dist/plugins/parental/types.d.ts +154 -0
- package/dist/plugins/parental/types.d.ts.map +1 -0
- package/dist/plugins/parental/types.js +10 -0
- package/dist/plugins/parental/types.js.map +1 -0
- package/dist/plugins/profiles/__tests__/profiles-plugin.test.d.ts +11 -0
- package/dist/plugins/profiles/__tests__/profiles-plugin.test.d.ts.map +1 -0
- package/dist/plugins/profiles/__tests__/profiles-plugin.test.js +243 -0
- package/dist/plugins/profiles/__tests__/profiles-plugin.test.js.map +1 -0
- package/dist/plugins/profiles/index.d.ts +12 -0
- package/dist/plugins/profiles/index.d.ts.map +1 -0
- package/dist/plugins/profiles/index.js +13 -0
- package/dist/plugins/profiles/index.js.map +1 -0
- package/dist/plugins/profiles/profiles-plugin.d.ts +71 -0
- package/dist/plugins/profiles/profiles-plugin.d.ts.map +1 -0
- package/dist/plugins/profiles/profiles-plugin.js +481 -0
- package/dist/plugins/profiles/profiles-plugin.js.map +1 -0
- package/dist/plugins/profiles/stores/index.d.ts +9 -0
- package/dist/plugins/profiles/stores/index.d.ts.map +1 -0
- package/dist/plugins/profiles/stores/index.js +9 -0
- package/dist/plugins/profiles/stores/index.js.map +1 -0
- package/dist/plugins/profiles/stores/postgres-store.d.ts +18 -0
- package/dist/plugins/profiles/stores/postgres-store.d.ts.map +1 -0
- package/dist/plugins/profiles/stores/postgres-store.js +310 -0
- package/dist/plugins/profiles/stores/postgres-store.js.map +1 -0
- package/dist/plugins/profiles/types.d.ts +289 -0
- package/dist/plugins/profiles/types.d.ts.map +1 -0
- package/dist/plugins/profiles/types.js +10 -0
- package/dist/plugins/profiles/types.js.map +1 -0
- package/dist/plugins/rate-limit/__tests__/rate-limit-plugin.test.d.ts +7 -0
- package/dist/plugins/rate-limit/__tests__/rate-limit-plugin.test.d.ts.map +1 -0
- package/dist/plugins/rate-limit/__tests__/rate-limit-plugin.test.js +220 -0
- package/dist/plugins/rate-limit/__tests__/rate-limit-plugin.test.js.map +1 -0
- package/dist/plugins/rate-limit/cleanup.d.ts +40 -0
- package/dist/plugins/rate-limit/cleanup.d.ts.map +1 -0
- package/dist/plugins/rate-limit/cleanup.js +72 -0
- package/dist/plugins/rate-limit/cleanup.js.map +1 -0
- package/dist/plugins/rate-limit/env-config.d.ts +91 -0
- package/dist/plugins/rate-limit/env-config.d.ts.map +1 -0
- package/dist/plugins/rate-limit/env-config.js +318 -0
- package/dist/plugins/rate-limit/env-config.js.map +1 -0
- package/dist/plugins/rate-limit/index.d.ts +76 -0
- package/dist/plugins/rate-limit/index.d.ts.map +1 -0
- package/dist/plugins/rate-limit/index.js +79 -0
- package/dist/plugins/rate-limit/index.js.map +1 -0
- package/dist/plugins/rate-limit/middleware.d.ts +40 -0
- package/dist/plugins/rate-limit/middleware.d.ts.map +1 -0
- package/dist/plugins/rate-limit/middleware.js +169 -0
- package/dist/plugins/rate-limit/middleware.js.map +1 -0
- package/dist/plugins/rate-limit/rate-limit-plugin.d.ts +44 -0
- package/dist/plugins/rate-limit/rate-limit-plugin.d.ts.map +1 -0
- package/dist/plugins/rate-limit/rate-limit-plugin.js +354 -0
- package/dist/plugins/rate-limit/rate-limit-plugin.js.map +1 -0
- package/dist/plugins/rate-limit/rate-limit-service.d.ts +110 -0
- package/dist/plugins/rate-limit/rate-limit-service.d.ts.map +1 -0
- package/dist/plugins/rate-limit/rate-limit-service.js +172 -0
- package/dist/plugins/rate-limit/rate-limit-service.js.map +1 -0
- package/dist/plugins/rate-limit/stores/cache-store.d.ts +33 -0
- package/dist/plugins/rate-limit/stores/cache-store.d.ts.map +1 -0
- package/dist/plugins/rate-limit/stores/cache-store.js +225 -0
- package/dist/plugins/rate-limit/stores/cache-store.js.map +1 -0
- package/dist/plugins/rate-limit/stores/index.d.ts +8 -0
- package/dist/plugins/rate-limit/stores/index.d.ts.map +1 -0
- package/dist/plugins/rate-limit/stores/index.js +8 -0
- package/dist/plugins/rate-limit/stores/index.js.map +1 -0
- package/dist/plugins/rate-limit/stores/postgres-store.d.ts +34 -0
- package/dist/plugins/rate-limit/stores/postgres-store.d.ts.map +1 -0
- package/dist/plugins/rate-limit/stores/postgres-store.js +320 -0
- package/dist/plugins/rate-limit/stores/postgres-store.js.map +1 -0
- package/dist/plugins/rate-limit/strategies/fixed-window.d.ts +21 -0
- package/dist/plugins/rate-limit/strategies/fixed-window.d.ts.map +1 -0
- package/dist/plugins/rate-limit/strategies/fixed-window.js +97 -0
- package/dist/plugins/rate-limit/strategies/fixed-window.js.map +1 -0
- package/dist/plugins/rate-limit/strategies/index.d.ts +14 -0
- package/dist/plugins/rate-limit/strategies/index.d.ts.map +1 -0
- package/dist/plugins/rate-limit/strategies/index.js +27 -0
- package/dist/plugins/rate-limit/strategies/index.js.map +1 -0
- package/dist/plugins/rate-limit/strategies/sliding-window.d.ts +22 -0
- package/dist/plugins/rate-limit/strategies/sliding-window.d.ts.map +1 -0
- package/dist/plugins/rate-limit/strategies/sliding-window.js +122 -0
- package/dist/plugins/rate-limit/strategies/sliding-window.js.map +1 -0
- package/dist/plugins/rate-limit/strategies/token-bucket.d.ts +28 -0
- package/dist/plugins/rate-limit/strategies/token-bucket.d.ts.map +1 -0
- package/dist/plugins/rate-limit/strategies/token-bucket.js +121 -0
- package/dist/plugins/rate-limit/strategies/token-bucket.js.map +1 -0
- package/dist/plugins/rate-limit/types.d.ts +265 -0
- package/dist/plugins/rate-limit/types.d.ts.map +1 -0
- package/dist/plugins/rate-limit/types.js +9 -0
- package/dist/plugins/rate-limit/types.js.map +1 -0
- package/dist/plugins/subscriptions/__tests__/subscriptions-plugin.test.d.ts +11 -0
- package/dist/plugins/subscriptions/__tests__/subscriptions-plugin.test.d.ts.map +1 -0
- package/dist/plugins/subscriptions/__tests__/subscriptions-plugin.test.js +305 -0
- package/dist/plugins/subscriptions/__tests__/subscriptions-plugin.test.js.map +1 -0
- package/dist/plugins/subscriptions/index.d.ts +12 -0
- package/dist/plugins/subscriptions/index.d.ts.map +1 -0
- package/dist/plugins/subscriptions/index.js +13 -0
- package/dist/plugins/subscriptions/index.js.map +1 -0
- package/dist/plugins/subscriptions/stores/index.d.ts +9 -0
- package/dist/plugins/subscriptions/stores/index.d.ts.map +1 -0
- package/dist/plugins/subscriptions/stores/index.js +9 -0
- package/dist/plugins/subscriptions/stores/index.js.map +1 -0
- package/dist/plugins/subscriptions/stores/postgres-store.d.ts +14 -0
- package/dist/plugins/subscriptions/stores/postgres-store.d.ts.map +1 -0
- package/dist/plugins/subscriptions/stores/postgres-store.js +359 -0
- package/dist/plugins/subscriptions/stores/postgres-store.js.map +1 -0
- package/dist/plugins/subscriptions/subscriptions-plugin.d.ts +82 -0
- package/dist/plugins/subscriptions/subscriptions-plugin.d.ts.map +1 -0
- package/dist/plugins/subscriptions/subscriptions-plugin.js +449 -0
- package/dist/plugins/subscriptions/subscriptions-plugin.js.map +1 -0
- package/dist/plugins/subscriptions/types.d.ts +308 -0
- package/dist/plugins/subscriptions/types.d.ts.map +1 -0
- package/dist/plugins/subscriptions/types.js +10 -0
- package/dist/plugins/subscriptions/types.js.map +1 -0
- package/dist/plugins/usage/__tests__/usage-plugin.test.d.ts +11 -0
- package/dist/plugins/usage/__tests__/usage-plugin.test.d.ts.map +1 -0
- package/dist/plugins/usage/__tests__/usage-plugin.test.js +218 -0
- package/dist/plugins/usage/__tests__/usage-plugin.test.js.map +1 -0
- package/dist/plugins/usage/index.d.ts +12 -0
- package/dist/plugins/usage/index.d.ts.map +1 -0
- package/dist/plugins/usage/index.js +13 -0
- package/dist/plugins/usage/index.js.map +1 -0
- package/dist/plugins/usage/stores/index.d.ts +9 -0
- package/dist/plugins/usage/stores/index.d.ts.map +1 -0
- package/dist/plugins/usage/stores/index.js +9 -0
- package/dist/plugins/usage/stores/index.js.map +1 -0
- package/dist/plugins/usage/stores/postgres-store.d.ts +14 -0
- package/dist/plugins/usage/stores/postgres-store.d.ts.map +1 -0
- package/dist/plugins/usage/stores/postgres-store.js +146 -0
- package/dist/plugins/usage/stores/postgres-store.js.map +1 -0
- package/dist/plugins/usage/types.d.ts +195 -0
- package/dist/plugins/usage/types.d.ts.map +1 -0
- package/dist/plugins/usage/types.js +10 -0
- package/dist/plugins/usage/types.js.map +1 -0
- package/dist/plugins/usage/usage-plugin.d.ts +51 -0
- package/dist/plugins/usage/usage-plugin.d.ts.map +1 -0
- package/dist/plugins/usage/usage-plugin.js +412 -0
- package/dist/plugins/usage/usage-plugin.js.map +1 -0
- package/dist/plugins/users/__tests__/postgres-store.test.d.ts +10 -0
- package/dist/plugins/users/__tests__/postgres-store.test.d.ts.map +1 -0
- package/dist/plugins/users/__tests__/postgres-store.test.js +229 -0
- package/dist/plugins/users/__tests__/postgres-store.test.js.map +1 -0
- package/dist/plugins/users/__tests__/users-plugin.test.js +3 -0
- package/dist/plugins/users/__tests__/users-plugin.test.js.map +1 -1
- package/dist/plugins/users/index.d.ts +2 -2
- package/dist/plugins/users/index.d.ts.map +1 -1
- package/dist/plugins/users/index.js +1 -1
- package/dist/plugins/users/index.js.map +1 -1
- package/dist/plugins/users/stores/postgres-store.d.ts.map +1 -1
- package/dist/plugins/users/stores/postgres-store.js +76 -0
- package/dist/plugins/users/stores/postgres-store.js.map +1 -1
- package/dist/plugins/users/types.d.ts +74 -6
- package/dist/plugins/users/types.d.ts.map +1 -1
- package/dist/plugins/users/users-plugin.d.ts +15 -1
- package/dist/plugins/users/users-plugin.d.ts.map +1 -1
- package/dist/plugins/users/users-plugin.js +29 -0
- package/dist/plugins/users/users-plugin.js.map +1 -1
- package/dist-ui/assets/index-CynOqPkb.js +469 -0
- package/dist-ui/assets/{index-BY8OxNgO.js.map → index-CynOqPkb.js.map} +1 -1
- package/dist-ui/index.html +1 -1
- package/dist-ui-lib/api/controlPanelApi.d.ts +187 -0
- package/dist-ui-lib/components/StatCard.d.ts +16 -0
- package/dist-ui-lib/dashboard/widgets/AuthStatusWidget.d.ts +9 -0
- package/dist-ui-lib/dashboard/widgets/IntegrationStatusWidget.d.ts +9 -0
- package/dist-ui-lib/dashboard/widgets/NotificationsStatsWidget.d.ts +12 -0
- package/dist-ui-lib/dashboard/widgets/index.d.ts +3 -0
- package/dist-ui-lib/index.js +3579 -2379
- package/dist-ui-lib/index.js.map +1 -1
- package/dist-ui-lib/pages/IntegrationsPage.d.ts +1 -0
- package/dist-ui-lib/pages/NotificationsPage.d.ts +9 -0
- package/dist-ui-lib/pages/RateLimitPage.d.ts +1 -0
- package/dist-ui-lib/utils/formatters.d.ts +19 -0
- package/package.json +1 -1
- package/src/core/control-panel.ts +128 -0
- package/src/core/types.ts +17 -0
- package/src/index.ts +216 -0
- package/src/plugins/auth/adapter-wrapper.test.ts +395 -0
- package/src/plugins/auth/adapter-wrapper.ts +205 -0
- package/src/plugins/auth/config-store.test.ts +417 -0
- package/src/plugins/auth/config-store.ts +305 -0
- package/src/plugins/auth/env-config.ts +714 -7
- package/src/plugins/auth/index.ts +22 -1
- package/src/plugins/auth/types.ts +138 -0
- package/src/plugins/bans/bans-plugin.ts +15 -3
- package/src/plugins/devices/__tests__/devices-plugin.test.ts +551 -0
- package/src/plugins/devices/__tests__/token-utils.test.ts +264 -0
- package/src/plugins/devices/adapters/compute-adapter.ts +139 -0
- package/src/plugins/devices/adapters/index.ts +13 -0
- package/src/plugins/devices/adapters/mobile-adapter.ts +179 -0
- package/src/plugins/devices/devices-plugin.ts +538 -0
- package/src/plugins/devices/index.ts +69 -0
- package/src/plugins/devices/stores/index.ts +9 -0
- package/src/plugins/devices/stores/postgres-store.ts +304 -0
- package/src/plugins/devices/token-utils.ts +213 -0
- package/src/plugins/devices/types.ts +351 -0
- package/src/plugins/index.ts +267 -0
- package/src/plugins/notifications/__tests__/notifications-manager.test.ts +637 -0
- package/src/plugins/notifications/index.ts +91 -0
- package/src/plugins/notifications/notifications-manager.ts +773 -0
- package/src/plugins/notifications/notifications-plugin.ts +398 -0
- package/src/plugins/notifications/types.ts +207 -0
- package/src/plugins/parental/__tests__/parental-plugin.test.ts +465 -0
- package/src/plugins/parental/adapters/index.ts +8 -0
- package/src/plugins/parental/adapters/kids-adapter.ts +206 -0
- package/src/plugins/parental/index.ts +55 -0
- package/src/plugins/parental/parental-plugin.ts +759 -0
- package/src/plugins/parental/stores/index.ts +7 -0
- package/src/plugins/parental/stores/postgres-store.ts +304 -0
- package/src/plugins/parental/types.ts +180 -0
- package/src/plugins/profiles/__tests__/profiles-plugin.test.ts +321 -0
- package/src/plugins/profiles/index.ts +49 -0
- package/src/plugins/profiles/profiles-plugin.ts +546 -0
- package/src/plugins/profiles/stores/index.ts +9 -0
- package/src/plugins/profiles/stores/postgres-store.ts +439 -0
- package/src/plugins/profiles/types.ts +338 -0
- package/src/plugins/rate-limit/__tests__/rate-limit-plugin.test.ts +259 -0
- package/src/plugins/rate-limit/cleanup.ts +117 -0
- package/src/plugins/rate-limit/env-config.ts +400 -0
- package/src/plugins/rate-limit/index.ts +128 -0
- package/src/plugins/rate-limit/middleware.ts +212 -0
- package/src/plugins/rate-limit/rate-limit-plugin.ts +400 -0
- package/src/plugins/rate-limit/rate-limit-service.ts +228 -0
- package/src/plugins/rate-limit/stores/cache-store.ts +261 -0
- package/src/plugins/rate-limit/stores/index.ts +8 -0
- package/src/plugins/rate-limit/stores/postgres-store.ts +402 -0
- package/src/plugins/rate-limit/strategies/fixed-window.ts +116 -0
- package/src/plugins/rate-limit/strategies/index.ts +30 -0
- package/src/plugins/rate-limit/strategies/sliding-window.ts +157 -0
- package/src/plugins/rate-limit/strategies/token-bucket.ts +154 -0
- package/src/plugins/rate-limit/types.ts +338 -0
- package/src/plugins/subscriptions/__tests__/subscriptions-plugin.test.ts +404 -0
- package/src/plugins/subscriptions/index.ts +51 -0
- package/src/plugins/subscriptions/stores/index.ts +9 -0
- package/src/plugins/subscriptions/stores/postgres-store.ts +482 -0
- package/src/plugins/subscriptions/subscriptions-plugin.ts +530 -0
- package/src/plugins/subscriptions/types.ts +355 -0
- package/src/plugins/usage/__tests__/usage-plugin.test.ts +288 -0
- package/src/plugins/usage/index.ts +39 -0
- package/src/plugins/usage/stores/index.ts +9 -0
- package/src/plugins/usage/stores/postgres-store.ts +213 -0
- package/src/plugins/usage/types.ts +222 -0
- package/src/plugins/usage/usage-plugin.ts +484 -0
- package/src/plugins/users/__tests__/postgres-store.test.ts +326 -0
- package/src/plugins/users/__tests__/users-plugin.test.ts +3 -0
- package/src/plugins/users/index.ts +6 -0
- package/src/plugins/users/stores/postgres-store.ts +104 -0
- package/src/plugins/users/types.ts +82 -6
- package/src/plugins/users/users-plugin.ts +37 -0
- package/ui/src/App.tsx +36 -14
- package/ui/src/api/controlPanelApi.ts +329 -6
- package/ui/src/components/StatCard.tsx +58 -0
- package/ui/src/dashboard/builtInWidgets.tsx +7 -1
- package/ui/src/dashboard/widgets/AuthStatusWidget.tsx +143 -0
- package/ui/src/dashboard/widgets/IntegrationStatusWidget.tsx +135 -0
- package/ui/src/dashboard/widgets/NotificationsStatsWidget.tsx +167 -0
- package/ui/src/dashboard/widgets/index.ts +3 -0
- package/ui/src/pages/AuthPage.tsx +986 -142
- package/ui/src/pages/IntegrationsPage.tsx +288 -0
- package/ui/src/pages/NotificationsPage.tsx +417 -0
- package/ui/src/pages/RateLimitPage.tsx +292 -0
- package/ui/src/utils/formatters.ts +33 -0
- package/dist-ui/assets/index-BY8OxNgO.js +0 -465
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subscriptions Plugin Types
|
|
3
|
+
*
|
|
4
|
+
* Type definitions for subscription tier management and feature entitlements.
|
|
5
|
+
* Supports Stripe integration for paid subscriptions.
|
|
6
|
+
*
|
|
7
|
+
* Copyright (c) 2025 QwickApps.com. All rights reserved.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Subscription status
|
|
12
|
+
*/
|
|
13
|
+
export type SubscriptionStatus = 'active' | 'canceled' | 'past_due' | 'trialing' | 'inactive';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Subscription tier definition (admin-managed)
|
|
17
|
+
*/
|
|
18
|
+
export interface SubscriptionTier {
|
|
19
|
+
/** Primary key - UUID */
|
|
20
|
+
id: string;
|
|
21
|
+
/** URL-safe identifier (e.g., 'free', 'premium', 'family') */
|
|
22
|
+
slug: string;
|
|
23
|
+
/** Display name */
|
|
24
|
+
name: string;
|
|
25
|
+
/** Description */
|
|
26
|
+
description?: string;
|
|
27
|
+
/** Monthly price in cents (null = free) */
|
|
28
|
+
price_monthly_cents?: number;
|
|
29
|
+
/** Yearly price in cents (null = free or monthly only) */
|
|
30
|
+
price_yearly_cents?: number;
|
|
31
|
+
/** Stripe price ID for monthly billing */
|
|
32
|
+
stripe_price_id_monthly?: string;
|
|
33
|
+
/** Stripe price ID for yearly billing */
|
|
34
|
+
stripe_price_id_yearly?: string;
|
|
35
|
+
/** Whether this tier is active (available for new subscriptions) */
|
|
36
|
+
is_active: boolean;
|
|
37
|
+
/** Sort order for display */
|
|
38
|
+
sort_order: number;
|
|
39
|
+
/** Additional metadata */
|
|
40
|
+
metadata: Record<string, unknown>;
|
|
41
|
+
/** When the tier was created */
|
|
42
|
+
created_at: Date;
|
|
43
|
+
/** When the tier was last updated */
|
|
44
|
+
updated_at: Date;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Feature entitlement per tier
|
|
49
|
+
*/
|
|
50
|
+
export interface SubscriptionEntitlement {
|
|
51
|
+
/** Primary key - UUID */
|
|
52
|
+
id: string;
|
|
53
|
+
/** Tier this entitlement belongs to */
|
|
54
|
+
tier_id: string;
|
|
55
|
+
/** Feature code (e.g., 'ai_messages_daily', 'vision_calls_daily') */
|
|
56
|
+
feature_code: string;
|
|
57
|
+
/** Limit value (-1 = unlimited, null = disabled, positive = limit) */
|
|
58
|
+
limit_value?: number;
|
|
59
|
+
/** Additional metadata */
|
|
60
|
+
metadata: Record<string, unknown>;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* User subscription record
|
|
65
|
+
*/
|
|
66
|
+
export interface UserSubscription {
|
|
67
|
+
/** Primary key - UUID */
|
|
68
|
+
id: string;
|
|
69
|
+
/** User ID */
|
|
70
|
+
user_id: string;
|
|
71
|
+
/** Tier ID */
|
|
72
|
+
tier_id: string;
|
|
73
|
+
/** Stripe customer ID */
|
|
74
|
+
stripe_customer_id?: string;
|
|
75
|
+
/** Stripe subscription ID */
|
|
76
|
+
stripe_subscription_id?: string;
|
|
77
|
+
/** Subscription status */
|
|
78
|
+
status: SubscriptionStatus;
|
|
79
|
+
/** Current billing period start */
|
|
80
|
+
current_period_start?: Date;
|
|
81
|
+
/** Current billing period end */
|
|
82
|
+
current_period_end?: Date;
|
|
83
|
+
/** Whether to cancel at period end */
|
|
84
|
+
cancel_at_period_end: boolean;
|
|
85
|
+
/** Additional metadata */
|
|
86
|
+
metadata: Record<string, unknown>;
|
|
87
|
+
/** When the subscription was created */
|
|
88
|
+
created_at: Date;
|
|
89
|
+
/** When the subscription was last updated */
|
|
90
|
+
updated_at: Date;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* User subscription with tier details
|
|
95
|
+
*/
|
|
96
|
+
export interface UserSubscriptionWithTier extends UserSubscription {
|
|
97
|
+
tier: SubscriptionTier;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Feature limit check result
|
|
102
|
+
*/
|
|
103
|
+
export interface FeatureLimitResult {
|
|
104
|
+
/** Whether the feature is available */
|
|
105
|
+
available: boolean;
|
|
106
|
+
/** Limit value (-1 = unlimited) */
|
|
107
|
+
limit?: number;
|
|
108
|
+
/** Current usage (if tracked) */
|
|
109
|
+
current?: number;
|
|
110
|
+
/** Remaining quota (if tracked) */
|
|
111
|
+
remaining?: number;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
115
|
+
// Input Types
|
|
116
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Tier creation payload
|
|
120
|
+
*/
|
|
121
|
+
export interface CreateTierInput {
|
|
122
|
+
slug: string;
|
|
123
|
+
name: string;
|
|
124
|
+
description?: string;
|
|
125
|
+
price_monthly_cents?: number;
|
|
126
|
+
price_yearly_cents?: number;
|
|
127
|
+
stripe_price_id_monthly?: string;
|
|
128
|
+
stripe_price_id_yearly?: string;
|
|
129
|
+
is_active?: boolean;
|
|
130
|
+
sort_order?: number;
|
|
131
|
+
metadata?: Record<string, unknown>;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Tier update payload
|
|
136
|
+
*/
|
|
137
|
+
export interface UpdateTierInput {
|
|
138
|
+
name?: string;
|
|
139
|
+
description?: string;
|
|
140
|
+
price_monthly_cents?: number;
|
|
141
|
+
price_yearly_cents?: number;
|
|
142
|
+
stripe_price_id_monthly?: string;
|
|
143
|
+
stripe_price_id_yearly?: string;
|
|
144
|
+
is_active?: boolean;
|
|
145
|
+
sort_order?: number;
|
|
146
|
+
metadata?: Record<string, unknown>;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Entitlement creation payload
|
|
151
|
+
*/
|
|
152
|
+
export interface CreateEntitlementInput {
|
|
153
|
+
tier_id: string;
|
|
154
|
+
feature_code: string;
|
|
155
|
+
limit_value?: number;
|
|
156
|
+
metadata?: Record<string, unknown>;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* User subscription creation payload
|
|
161
|
+
*/
|
|
162
|
+
export interface CreateUserSubscriptionInput {
|
|
163
|
+
user_id: string;
|
|
164
|
+
tier_id: string;
|
|
165
|
+
stripe_customer_id?: string;
|
|
166
|
+
stripe_subscription_id?: string;
|
|
167
|
+
status?: SubscriptionStatus;
|
|
168
|
+
current_period_start?: Date;
|
|
169
|
+
current_period_end?: Date;
|
|
170
|
+
metadata?: Record<string, unknown>;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* User subscription update payload
|
|
175
|
+
*/
|
|
176
|
+
export interface UpdateUserSubscriptionInput {
|
|
177
|
+
tier_id?: string;
|
|
178
|
+
stripe_customer_id?: string;
|
|
179
|
+
stripe_subscription_id?: string;
|
|
180
|
+
status?: SubscriptionStatus;
|
|
181
|
+
current_period_start?: Date;
|
|
182
|
+
current_period_end?: Date;
|
|
183
|
+
cancel_at_period_end?: boolean;
|
|
184
|
+
metadata?: Record<string, unknown>;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
188
|
+
// Store Interface
|
|
189
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Subscriptions store interface
|
|
193
|
+
*/
|
|
194
|
+
export interface SubscriptionsStore {
|
|
195
|
+
/** Store name (e.g., 'postgres') */
|
|
196
|
+
name: string;
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Initialize the store (create tables, etc.)
|
|
200
|
+
*/
|
|
201
|
+
initialize(): Promise<void>;
|
|
202
|
+
|
|
203
|
+
// Tiers
|
|
204
|
+
/**
|
|
205
|
+
* Create a subscription tier
|
|
206
|
+
*/
|
|
207
|
+
createTier(input: CreateTierInput): Promise<SubscriptionTier>;
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Get tier by ID
|
|
211
|
+
*/
|
|
212
|
+
getTierById(id: string): Promise<SubscriptionTier | null>;
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Get tier by slug
|
|
216
|
+
*/
|
|
217
|
+
getTierBySlug(slug: string): Promise<SubscriptionTier | null>;
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* List all tiers
|
|
221
|
+
*/
|
|
222
|
+
listTiers(activeOnly?: boolean): Promise<SubscriptionTier[]>;
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Update a tier
|
|
226
|
+
*/
|
|
227
|
+
updateTier(id: string, input: UpdateTierInput): Promise<SubscriptionTier | null>;
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Delete a tier (soft delete)
|
|
231
|
+
*/
|
|
232
|
+
deleteTier(id: string): Promise<boolean>;
|
|
233
|
+
|
|
234
|
+
// Entitlements
|
|
235
|
+
/**
|
|
236
|
+
* Create an entitlement
|
|
237
|
+
*/
|
|
238
|
+
createEntitlement(input: CreateEntitlementInput): Promise<SubscriptionEntitlement>;
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Get entitlements for a tier
|
|
242
|
+
*/
|
|
243
|
+
getEntitlementsByTier(tierId: string): Promise<SubscriptionEntitlement[]>;
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Update an entitlement
|
|
247
|
+
*/
|
|
248
|
+
updateEntitlement(id: string, limitValue: number | null): Promise<SubscriptionEntitlement | null>;
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Delete an entitlement
|
|
252
|
+
*/
|
|
253
|
+
deleteEntitlement(id: string): Promise<boolean>;
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Set multiple entitlements for a tier (upsert)
|
|
257
|
+
*/
|
|
258
|
+
setTierEntitlements(tierId: string, entitlements: Array<{ feature_code: string; limit_value?: number }>): Promise<void>;
|
|
259
|
+
|
|
260
|
+
// User Subscriptions
|
|
261
|
+
/**
|
|
262
|
+
* Create a user subscription
|
|
263
|
+
*/
|
|
264
|
+
createUserSubscription(input: CreateUserSubscriptionInput): Promise<UserSubscription>;
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Get user subscription by ID
|
|
268
|
+
*/
|
|
269
|
+
getUserSubscriptionById(id: string): Promise<UserSubscription | null>;
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Get active subscription for a user
|
|
273
|
+
*/
|
|
274
|
+
getActiveSubscription(userId: string): Promise<UserSubscriptionWithTier | null>;
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Get subscription by Stripe subscription ID
|
|
278
|
+
*/
|
|
279
|
+
getByStripeSubscriptionId(stripeSubId: string): Promise<UserSubscription | null>;
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Update user subscription
|
|
283
|
+
*/
|
|
284
|
+
updateUserSubscription(id: string, input: UpdateUserSubscriptionInput): Promise<UserSubscription | null>;
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Cancel subscription (sets cancel_at_period_end)
|
|
288
|
+
*/
|
|
289
|
+
cancelSubscription(id: string): Promise<boolean>;
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Get feature limit for a user
|
|
293
|
+
*/
|
|
294
|
+
getFeatureLimit(userId: string, featureCode: string): Promise<number | null>;
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Check if user has a feature
|
|
298
|
+
*/
|
|
299
|
+
hasFeature(userId: string, featureCode: string): Promise<boolean>;
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Shutdown the store
|
|
303
|
+
*/
|
|
304
|
+
shutdown(): Promise<void>;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
308
|
+
// Configuration Types
|
|
309
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* PostgreSQL subscriptions store configuration
|
|
313
|
+
*/
|
|
314
|
+
export interface PostgresSubscriptionsStoreConfig {
|
|
315
|
+
/** PostgreSQL pool instance or a function that returns one */
|
|
316
|
+
pool: unknown | (() => unknown);
|
|
317
|
+
/** Tiers table name (default: 'subscription_tiers') */
|
|
318
|
+
tiersTable?: string;
|
|
319
|
+
/** Entitlements table name (default: 'subscription_entitlements') */
|
|
320
|
+
entitlementsTable?: string;
|
|
321
|
+
/** User subscriptions table name (default: 'user_subscriptions') */
|
|
322
|
+
userSubscriptionsTable?: string;
|
|
323
|
+
/** Schema name (default: 'public') */
|
|
324
|
+
schema?: string;
|
|
325
|
+
/** Auto-create tables on init (default: true) */
|
|
326
|
+
autoCreateTables?: boolean;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* API configuration
|
|
331
|
+
*/
|
|
332
|
+
export interface SubscriptionsApiConfig {
|
|
333
|
+
/** API route prefix (default: '/subscriptions') */
|
|
334
|
+
prefix?: string;
|
|
335
|
+
/** Enable tier management endpoints */
|
|
336
|
+
tierManagement?: boolean;
|
|
337
|
+
/** Enable user subscription endpoints */
|
|
338
|
+
userSubscriptions?: boolean;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Subscriptions plugin configuration
|
|
343
|
+
*/
|
|
344
|
+
export interface SubscriptionsPluginConfig {
|
|
345
|
+
/** Subscriptions storage backend */
|
|
346
|
+
store: SubscriptionsStore;
|
|
347
|
+
/** Default tier slug for new users (default: 'free') */
|
|
348
|
+
defaultTierSlug?: string;
|
|
349
|
+
/** Whether to auto-create default subscription for new users */
|
|
350
|
+
autoCreateDefaultSubscription?: boolean;
|
|
351
|
+
/** API configuration */
|
|
352
|
+
api?: SubscriptionsApiConfig;
|
|
353
|
+
/** Enable debug logging */
|
|
354
|
+
debug?: boolean;
|
|
355
|
+
}
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Usage Plugin Tests
|
|
3
|
+
*
|
|
4
|
+
* Unit tests for the usage tracking plugin including:
|
|
5
|
+
* - Plugin lifecycle
|
|
6
|
+
* - Daily/monthly usage tracking
|
|
7
|
+
* - Increment and check limits
|
|
8
|
+
* - Cleanup operations
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
12
|
+
import {
|
|
13
|
+
createUsagePlugin,
|
|
14
|
+
getUsageStore,
|
|
15
|
+
getDailyUsage,
|
|
16
|
+
incrementUsage,
|
|
17
|
+
checkUsageLimit,
|
|
18
|
+
getDailyUsageSummary,
|
|
19
|
+
resetUsage,
|
|
20
|
+
} from '../usage-plugin.js';
|
|
21
|
+
import type { UsageStore, DailyUsage, MonthlyUsage } from '../types.js';
|
|
22
|
+
import type { PluginRegistry } from '../../../core/plugin-registry.js';
|
|
23
|
+
|
|
24
|
+
// Mock the subscriptions plugin (usage plugin depends on it for limits)
|
|
25
|
+
vi.mock('../../subscriptions/subscriptions-plugin.js', () => ({
|
|
26
|
+
getFeatureLimit: vi.fn().mockResolvedValue(-1), // unlimited by default
|
|
27
|
+
hasFeature: vi.fn().mockResolvedValue(true),
|
|
28
|
+
}));
|
|
29
|
+
|
|
30
|
+
import { getFeatureLimit } from '../../subscriptions/subscriptions-plugin.js';
|
|
31
|
+
|
|
32
|
+
describe('Usage Plugin', () => {
|
|
33
|
+
// Mock usage data
|
|
34
|
+
const mockDailyUsage: DailyUsage = {
|
|
35
|
+
id: 'usage-id-123',
|
|
36
|
+
user_id: 'user-123',
|
|
37
|
+
feature_code: 'ai_messages',
|
|
38
|
+
date: new Date().toISOString().split('T')[0],
|
|
39
|
+
count: 10,
|
|
40
|
+
metadata: {},
|
|
41
|
+
created_at: new Date(),
|
|
42
|
+
updated_at: new Date(),
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const mockMonthlyUsage: MonthlyUsage = {
|
|
46
|
+
id: 'monthly-id-123',
|
|
47
|
+
user_id: 'user-123',
|
|
48
|
+
feature_code: 'ai_messages',
|
|
49
|
+
year_month: new Date().toISOString().substring(0, 7),
|
|
50
|
+
count: 300,
|
|
51
|
+
metadata: {},
|
|
52
|
+
created_at: new Date(),
|
|
53
|
+
updated_at: new Date(),
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
// Mock store factory
|
|
57
|
+
const createMockStore = (): UsageStore => ({
|
|
58
|
+
name: 'mock',
|
|
59
|
+
initialize: vi.fn().mockResolvedValue(undefined),
|
|
60
|
+
getDailyUsage: vi.fn().mockResolvedValue(mockDailyUsage),
|
|
61
|
+
getMonthlyUsage: vi.fn().mockResolvedValue(mockMonthlyUsage),
|
|
62
|
+
incrementDaily: vi.fn().mockResolvedValue(11),
|
|
63
|
+
getAllDailyUsage: vi.fn().mockResolvedValue([mockDailyUsage]),
|
|
64
|
+
getAllMonthlyUsage: vi.fn().mockResolvedValue([mockMonthlyUsage]),
|
|
65
|
+
resetDailyUsage: vi.fn().mockResolvedValue(undefined),
|
|
66
|
+
cleanupOldDaily: vi.fn().mockResolvedValue(100),
|
|
67
|
+
cleanupOldMonthly: vi.fn().mockResolvedValue(12),
|
|
68
|
+
shutdown: vi.fn().mockResolvedValue(undefined),
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Mock registry factory
|
|
72
|
+
const createMockRegistry = (): PluginRegistry =>
|
|
73
|
+
({
|
|
74
|
+
hasPlugin: vi.fn().mockReturnValue(false),
|
|
75
|
+
getPlugin: vi.fn().mockReturnValue(null),
|
|
76
|
+
listPlugins: vi.fn().mockReturnValue([]),
|
|
77
|
+
addRoute: vi.fn(),
|
|
78
|
+
addMenuItem: vi.fn(),
|
|
79
|
+
addPage: vi.fn(),
|
|
80
|
+
addWidget: vi.fn(),
|
|
81
|
+
getRoutes: vi.fn().mockReturnValue([]),
|
|
82
|
+
getMenuItems: vi.fn().mockReturnValue([]),
|
|
83
|
+
getPages: vi.fn().mockReturnValue([]),
|
|
84
|
+
getWidgets: vi.fn().mockReturnValue([]),
|
|
85
|
+
getConfig: vi.fn().mockReturnValue({}),
|
|
86
|
+
setConfig: vi.fn().mockResolvedValue(undefined),
|
|
87
|
+
subscribe: vi.fn().mockReturnValue(() => {}),
|
|
88
|
+
emit: vi.fn(),
|
|
89
|
+
registerHealthCheck: vi.fn(),
|
|
90
|
+
getApp: vi.fn().mockReturnValue({} as any),
|
|
91
|
+
getRouter: vi.fn().mockReturnValue({} as any),
|
|
92
|
+
getLogger: vi.fn().mockReturnValue({
|
|
93
|
+
debug: vi.fn(),
|
|
94
|
+
info: vi.fn(),
|
|
95
|
+
warn: vi.fn(),
|
|
96
|
+
error: vi.fn(),
|
|
97
|
+
}),
|
|
98
|
+
}) as unknown as PluginRegistry;
|
|
99
|
+
|
|
100
|
+
let mockStore: UsageStore;
|
|
101
|
+
let mockRegistry: PluginRegistry;
|
|
102
|
+
|
|
103
|
+
beforeEach(() => {
|
|
104
|
+
vi.clearAllMocks();
|
|
105
|
+
mockStore = createMockStore();
|
|
106
|
+
mockRegistry = createMockRegistry();
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
afterEach(async () => {
|
|
110
|
+
// Clean up
|
|
111
|
+
const store = getUsageStore();
|
|
112
|
+
if (store) {
|
|
113
|
+
const plugin = createUsagePlugin({ store: mockStore });
|
|
114
|
+
await plugin.onStop?.();
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
describe('createUsagePlugin', () => {
|
|
119
|
+
it('should create a plugin with correct id', () => {
|
|
120
|
+
const plugin = createUsagePlugin({ store: mockStore });
|
|
121
|
+
expect(plugin.id).toBe('usage');
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it('should create a plugin with correct name', () => {
|
|
125
|
+
const plugin = createUsagePlugin({ store: mockStore });
|
|
126
|
+
expect(plugin.name).toBe('Usage');
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('should create a plugin with version', () => {
|
|
130
|
+
const plugin = createUsagePlugin({ store: mockStore });
|
|
131
|
+
expect(plugin.version).toBe('1.0.0');
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
describe('onStart', () => {
|
|
136
|
+
it('should initialize store on start', async () => {
|
|
137
|
+
const plugin = createUsagePlugin({ store: mockStore });
|
|
138
|
+
await plugin.onStart({}, mockRegistry);
|
|
139
|
+
|
|
140
|
+
expect(mockStore.initialize).toHaveBeenCalled();
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it('should register health check', async () => {
|
|
144
|
+
const plugin = createUsagePlugin({ store: mockStore });
|
|
145
|
+
await plugin.onStart({}, mockRegistry);
|
|
146
|
+
|
|
147
|
+
expect(mockRegistry.registerHealthCheck).toHaveBeenCalledWith(
|
|
148
|
+
expect.objectContaining({
|
|
149
|
+
name: 'usage-store',
|
|
150
|
+
type: 'custom',
|
|
151
|
+
})
|
|
152
|
+
);
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
describe('onStop', () => {
|
|
157
|
+
it('should shutdown store', async () => {
|
|
158
|
+
const plugin = createUsagePlugin({ store: mockStore });
|
|
159
|
+
await plugin.onStart({}, mockRegistry);
|
|
160
|
+
await plugin.onStop?.();
|
|
161
|
+
|
|
162
|
+
expect(mockStore.shutdown).toHaveBeenCalled();
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('should clear store reference', async () => {
|
|
166
|
+
const plugin = createUsagePlugin({ store: mockStore });
|
|
167
|
+
await plugin.onStart({}, mockRegistry);
|
|
168
|
+
await plugin.onStop?.();
|
|
169
|
+
|
|
170
|
+
expect(getUsageStore()).toBeNull();
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
describe('helper functions', () => {
|
|
175
|
+
describe('getUsageStore', () => {
|
|
176
|
+
it('should return null when plugin not started', () => {
|
|
177
|
+
expect(getUsageStore()).toBeNull();
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
it('should return store when plugin started', async () => {
|
|
181
|
+
const plugin = createUsagePlugin({ store: mockStore });
|
|
182
|
+
await plugin.onStart({}, mockRegistry);
|
|
183
|
+
|
|
184
|
+
expect(getUsageStore()).toBe(mockStore);
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
describe('getDailyUsage', () => {
|
|
189
|
+
it('should throw when plugin not initialized', async () => {
|
|
190
|
+
await expect(
|
|
191
|
+
getDailyUsage('user-id', 'ai_messages')
|
|
192
|
+
).rejects.toThrow('Usage plugin not initialized');
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it('should return daily usage count', async () => {
|
|
196
|
+
const plugin = createUsagePlugin({ store: mockStore });
|
|
197
|
+
await plugin.onStart({}, mockRegistry);
|
|
198
|
+
|
|
199
|
+
const result = await getDailyUsage('user-123', 'ai_messages');
|
|
200
|
+
expect(result).toBe(10); // count from mockDailyUsage
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it('should return 0 when no usage', async () => {
|
|
204
|
+
const plugin = createUsagePlugin({ store: mockStore });
|
|
205
|
+
await plugin.onStart({}, mockRegistry);
|
|
206
|
+
|
|
207
|
+
(mockStore.getDailyUsage as any).mockResolvedValue(null);
|
|
208
|
+
|
|
209
|
+
const result = await getDailyUsage('user-123', 'unused_feature');
|
|
210
|
+
expect(result).toBe(0);
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
describe('incrementUsage', () => {
|
|
215
|
+
it('should throw when plugin not initialized', async () => {
|
|
216
|
+
await expect(
|
|
217
|
+
incrementUsage('user-id', 'ai_messages')
|
|
218
|
+
).rejects.toThrow('Usage plugin not initialized');
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
it('should increment and return result', async () => {
|
|
222
|
+
const plugin = createUsagePlugin({ store: mockStore });
|
|
223
|
+
await plugin.onStart({}, mockRegistry);
|
|
224
|
+
|
|
225
|
+
const result = await incrementUsage('user-123', 'ai_messages');
|
|
226
|
+
|
|
227
|
+
expect(result.allowed).toBe(true);
|
|
228
|
+
expect(result.current_count).toBeDefined();
|
|
229
|
+
expect(mockStore.incrementDaily).toHaveBeenCalled();
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it('should increment by custom amount', async () => {
|
|
233
|
+
const plugin = createUsagePlugin({ store: mockStore });
|
|
234
|
+
await plugin.onStart({}, mockRegistry);
|
|
235
|
+
|
|
236
|
+
(mockStore.incrementDaily as any).mockResolvedValue(15);
|
|
237
|
+
|
|
238
|
+
const result = await incrementUsage('user-123', 'ai_messages', 5);
|
|
239
|
+
|
|
240
|
+
expect(result.allowed).toBe(true);
|
|
241
|
+
expect(result.current_count).toBe(15);
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
describe('checkUsageLimit', () => {
|
|
246
|
+
it('should throw when plugin not initialized', async () => {
|
|
247
|
+
await expect(
|
|
248
|
+
checkUsageLimit('user-id', 'ai_messages', 50)
|
|
249
|
+
).rejects.toThrow('Usage plugin not initialized');
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
it('should return usage limit result', async () => {
|
|
253
|
+
const plugin = createUsagePlugin({ store: mockStore });
|
|
254
|
+
await plugin.onStart({}, mockRegistry);
|
|
255
|
+
|
|
256
|
+
// Reset mock to return -1 (unlimited)
|
|
257
|
+
(getFeatureLimit as any).mockResolvedValue(-1);
|
|
258
|
+
|
|
259
|
+
const result = await checkUsageLimit('user-123', 'ai_messages', -1);
|
|
260
|
+
|
|
261
|
+
// Should return a result object with usage info
|
|
262
|
+
expect(result).toHaveProperty('allowed');
|
|
263
|
+
expect(result).toHaveProperty('current_count');
|
|
264
|
+
expect(result).toHaveProperty('limit');
|
|
265
|
+
});
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
describe('resetUsage', () => {
|
|
269
|
+
it('should throw when plugin not initialized', async () => {
|
|
270
|
+
await expect(
|
|
271
|
+
resetUsage('user-id', 'ai_messages')
|
|
272
|
+
).rejects.toThrow('Usage plugin not initialized');
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
it('should reset usage', async () => {
|
|
276
|
+
const plugin = createUsagePlugin({ store: mockStore });
|
|
277
|
+
await plugin.onStart({}, mockRegistry);
|
|
278
|
+
|
|
279
|
+
await resetUsage('user-123', 'ai_messages');
|
|
280
|
+
|
|
281
|
+
expect(mockStore.resetDailyUsage).toHaveBeenCalledWith(
|
|
282
|
+
'user-123',
|
|
283
|
+
'ai_messages'
|
|
284
|
+
);
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
});
|
|
288
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Usage Plugin
|
|
3
|
+
*
|
|
4
|
+
* Usage tracking with daily/monthly counters.
|
|
5
|
+
* Exports all usage-related functionality.
|
|
6
|
+
*
|
|
7
|
+
* Copyright (c) 2025 QwickApps.com. All rights reserved.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// Main plugin
|
|
11
|
+
export {
|
|
12
|
+
createUsagePlugin,
|
|
13
|
+
getUsageStore,
|
|
14
|
+
getDailyUsage,
|
|
15
|
+
incrementUsage,
|
|
16
|
+
checkUsageLimit,
|
|
17
|
+
getFeatureUsageStatus,
|
|
18
|
+
getDailyUsageSummary,
|
|
19
|
+
resetUsage,
|
|
20
|
+
getRemainingQuota,
|
|
21
|
+
canUseFeature,
|
|
22
|
+
} from './usage-plugin.js';
|
|
23
|
+
|
|
24
|
+
// Types
|
|
25
|
+
export type {
|
|
26
|
+
DailyUsage,
|
|
27
|
+
MonthlyUsage,
|
|
28
|
+
UsageIncrementResult,
|
|
29
|
+
UsageStatus,
|
|
30
|
+
UsageSummary,
|
|
31
|
+
UsageStore,
|
|
32
|
+
UsagePluginConfig,
|
|
33
|
+
UsageApiConfig,
|
|
34
|
+
UsageCleanupConfig,
|
|
35
|
+
PostgresUsageStoreConfig,
|
|
36
|
+
} from './types.js';
|
|
37
|
+
|
|
38
|
+
// Stores
|
|
39
|
+
export { postgresUsageStore } from './stores/index.js';
|