unleash-server 7.6.2 → 7.6.4
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/dist/lib/db/client-applications-store.d.ts.map +1 -1
- package/dist/lib/db/client-applications-store.js +1 -0
- package/dist/lib/db/client-applications-store.js.map +1 -1
- package/dist/lib/db/client-applications-store.test.d.ts +2 -0
- package/dist/lib/db/client-applications-store.test.d.ts.map +1 -0
- package/dist/lib/db/client-applications-store.test.js +134 -0
- package/dist/lib/db/client-applications-store.test.js.map +1 -0
- package/dist/lib/db/index.js +2 -2
- package/dist/lib/db/index.js.map +1 -1
- package/dist/lib/events/index.d.ts +2 -1
- package/dist/lib/events/index.d.ts.map +1 -1
- package/dist/lib/events/index.js +2 -0
- package/dist/lib/events/index.js.map +1 -1
- package/dist/lib/features/client-feature-toggles/delta/client-feature-toggle-delta-types.d.ts +1 -1
- package/dist/lib/features/client-feature-toggles/delta/client-feature-toggle-delta-types.d.ts.map +1 -1
- package/dist/lib/features/client-feature-toggles/delta/client-feature-toggle-delta-types.js +2 -3
- package/dist/lib/features/client-feature-toggles/delta/client-feature-toggle-delta-types.js.map +1 -1
- package/dist/lib/features/client-feature-toggles/delta/client-feature-toggle-delta.d.ts +3 -3
- package/dist/lib/features/client-feature-toggles/delta/client-feature-toggle-delta.d.ts.map +1 -1
- package/dist/lib/features/client-feature-toggles/delta/client-feature-toggle-delta.js +77 -27
- package/dist/lib/features/client-feature-toggles/delta/client-feature-toggle-delta.js.map +1 -1
- package/dist/lib/features/client-feature-toggles/delta/client-feature-toggle-delta.test.js +566 -20
- package/dist/lib/features/client-feature-toggles/delta/client-feature-toggle-delta.test.js.map +1 -1
- package/dist/lib/features/client-feature-toggles/delta/visible-revision.d.ts +3 -1
- package/dist/lib/features/client-feature-toggles/delta/visible-revision.d.ts.map +1 -1
- package/dist/lib/features/client-feature-toggles/delta/visible-revision.js +26 -3
- package/dist/lib/features/client-feature-toggles/delta/visible-revision.js.map +1 -1
- package/dist/lib/features/client-feature-toggles/delta/visible-revision.test.js +9 -1
- package/dist/lib/features/client-feature-toggles/delta/visible-revision.test.js.map +1 -1
- package/dist/lib/features/events/event-store.d.ts +1 -1
- package/dist/lib/features/events/event-store.d.ts.map +1 -1
- package/dist/lib/features/events/event-store.js +26 -4
- package/dist/lib/features/events/event-store.js.map +1 -1
- package/dist/lib/features/frontend-api/createFrontendApiService.d.ts.map +1 -1
- package/dist/lib/features/frontend-api/createFrontendApiService.js +3 -10
- package/dist/lib/features/frontend-api/createFrontendApiService.js.map +1 -1
- package/dist/lib/features/index.d.ts +1 -0
- package/dist/lib/features/index.d.ts.map +1 -1
- package/dist/lib/features/index.js +1 -0
- package/dist/lib/features/index.js.map +1 -1
- package/dist/lib/features/instance-stats/createInstanceStatsService.js +2 -2
- package/dist/lib/features/instance-stats/createInstanceStatsService.js.map +1 -1
- package/dist/lib/features/maintenance/maintenance-service.d.ts +1 -1
- package/dist/lib/features/maintenance/maintenance-service.d.ts.map +1 -1
- package/dist/lib/features/maintenance/maintenance-service.test.js +2 -2
- package/dist/lib/features/maintenance/maintenance-service.test.js.map +1 -1
- package/dist/lib/features/onboarding/createOnboardingReadModel.d.ts +2 -3
- package/dist/lib/features/onboarding/createOnboardingReadModel.d.ts.map +1 -1
- package/dist/lib/features/onboarding/createOnboardingReadModel.js +2 -2
- package/dist/lib/features/onboarding/createOnboardingReadModel.js.map +1 -1
- package/dist/lib/features/onboarding/onboarding-read-model.d.ts +3 -1
- package/dist/lib/features/onboarding/onboarding-read-model.d.ts.map +1 -1
- package/dist/lib/features/onboarding/onboarding-read-model.js +17 -2
- package/dist/lib/features/onboarding/onboarding-read-model.js.map +1 -1
- package/dist/lib/features/personal-dashboard/createPersonalDashboardService.js +1 -1
- package/dist/lib/features/personal-dashboard/createPersonalDashboardService.js.map +1 -1
- package/dist/lib/features/project/createProjectService.js +1 -1
- package/dist/lib/features/project/createProjectService.js.map +1 -1
- package/dist/lib/features/project/projects.e2e.test.js +48 -0
- package/dist/lib/features/project/projects.e2e.test.js.map +1 -1
- package/dist/lib/features/scheduler/scheduler-service.test.js +2 -2
- package/dist/lib/features/scheduler/scheduler-service.test.js.map +1 -1
- package/dist/lib/features/settings/createSettingService.d.ts +6 -0
- package/dist/lib/features/settings/createSettingService.d.ts.map +1 -0
- package/dist/lib/features/settings/createSettingService.js +15 -0
- package/dist/lib/features/settings/createSettingService.js.map +1 -0
- package/dist/{test/fixtures → lib/features/settings}/fake-setting-store.d.ts +1 -1
- package/dist/lib/features/settings/fake-setting-store.d.ts.map +1 -0
- package/dist/lib/features/settings/fake-setting-store.js.map +1 -0
- package/dist/lib/{services → features/settings}/setting-service.d.ts +4 -4
- package/dist/lib/features/settings/setting-service.d.ts.map +1 -0
- package/dist/lib/features/settings/setting-service.e2e.test.d.ts +2 -0
- package/dist/lib/features/settings/setting-service.e2e.test.d.ts.map +1 -0
- package/dist/{test/e2e/services/setting-service.test.js → lib/features/settings/setting-service.e2e.test.js} +7 -7
- package/dist/lib/features/settings/setting-service.e2e.test.js.map +1 -0
- package/dist/lib/{services → features/settings}/setting-service.js +2 -2
- package/dist/lib/features/settings/setting-service.js.map +1 -0
- package/dist/lib/{db → features/settings}/setting-store.d.ts +3 -3
- package/dist/lib/features/settings/setting-store.d.ts.map +1 -0
- package/dist/lib/features/settings/setting-store.e2e.test.d.ts.map +1 -0
- package/dist/{test/e2e/stores → lib/features/settings}/setting-store.e2e.test.js +2 -2
- package/dist/lib/features/settings/setting-store.e2e.test.js.map +1 -0
- package/dist/lib/features/settings/setting-store.js.map +1 -0
- package/dist/lib/{types/stores/settings-store.d.ts → features/settings/settings-store-type.d.ts} +2 -2
- package/dist/lib/features/settings/settings-store-type.d.ts.map +1 -0
- package/dist/lib/features/settings/settings-store-type.js +2 -0
- package/dist/lib/features/settings/settings-store-type.js.map +1 -0
- package/dist/lib/features/users/createUserService.d.ts.map +1 -1
- package/dist/lib/features/users/createUserService.js +3 -4
- package/dist/lib/features/users/createUserService.js.map +1 -1
- package/dist/lib/middleware/cors-origin-middleware.test.js +1 -1
- package/dist/lib/middleware/cors-origin-middleware.test.js.map +1 -1
- package/dist/lib/openapi/spec/context-query-parameters.d.ts +1 -1
- package/dist/lib/openapi/spec/context-query-parameters.d.ts.map +1 -1
- package/dist/lib/openapi/spec/event-schema.d.ts +1 -1
- package/dist/lib/openapi/spec/event-search-response-schema.d.ts +1 -1
- package/dist/lib/openapi/spec/events-schema.d.ts +1 -1
- package/dist/lib/openapi/spec/feature-events-schema.d.ts +1 -1
- package/dist/lib/openapi/spec/integration-event-schema.d.ts +1 -1
- package/dist/lib/openapi/spec/integration-events-schema.d.ts +2 -2
- package/dist/lib/openapi/spec/personal-dashboard-project-details-schema.d.ts +1 -1
- package/dist/lib/openapi/spec/project-overview-schema.d.ts +1 -1
- package/dist/lib/openapi/spec/project-overview-schema.d.ts.map +1 -1
- package/dist/lib/openapi/spec/project-overview-schema.js +5 -1
- package/dist/lib/openapi/spec/project-overview-schema.js.map +1 -1
- package/dist/lib/server-impl.d.ts +4 -4
- package/dist/lib/server-impl.d.ts.map +1 -1
- package/dist/lib/server-impl.js +2 -2
- package/dist/lib/server-impl.js.map +1 -1
- package/dist/lib/services/index.d.ts +1 -1
- package/dist/lib/services/index.d.ts.map +1 -1
- package/dist/lib/services/index.js +1 -1
- package/dist/lib/services/index.js.map +1 -1
- package/dist/lib/services/scheduler-service.test.js +2 -2
- package/dist/lib/services/scheduler-service.test.js.map +1 -1
- package/dist/lib/services/user-service.d.ts +1 -1
- package/dist/lib/services/user-service.d.ts.map +1 -1
- package/dist/lib/services/user-service.test.js +2 -2
- package/dist/lib/services/user-service.test.js.map +1 -1
- package/dist/lib/types/experimental.d.ts +1 -1
- package/dist/lib/types/experimental.d.ts.map +1 -1
- package/dist/lib/types/experimental.js +4 -3
- package/dist/lib/types/experimental.js.map +1 -1
- package/dist/lib/types/model.d.ts +1 -1
- package/dist/lib/types/model.d.ts.map +1 -1
- package/dist/lib/types/stores/client-applications-store.d.ts +1 -0
- package/dist/lib/types/stores/client-applications-store.d.ts.map +1 -1
- package/dist/lib/types/stores/event-store.d.ts +3 -2
- package/dist/lib/types/stores/event-store.d.ts.map +1 -1
- package/dist/lib/types/stores.d.ts +1 -1
- package/dist/lib/types/stores.d.ts.map +1 -1
- package/dist/lib/util/postgres-version-checker.test.js +1 -1
- package/dist/lib/util/postgres-version-checker.test.js.map +1 -1
- package/dist/server-dev.js +1 -1
- package/dist/server-dev.js.map +1 -1
- package/dist/test/e2e/api/auth/reset-password-controller.e2e.test.js +2 -2
- package/dist/test/e2e/api/auth/reset-password-controller.e2e.test.js.map +1 -1
- package/dist/test/e2e/api/auth/simple-password-provider.e2e.test.js +1 -1
- package/dist/test/e2e/api/auth/simple-password-provider.e2e.test.js.map +1 -1
- package/dist/test/e2e/services/reset-token-service.e2e.test.js +2 -2
- package/dist/test/e2e/services/reset-token-service.e2e.test.js.map +1 -1
- package/dist/test/e2e/services/user-service.e2e.test.js +1 -1
- package/dist/test/e2e/services/user-service.e2e.test.js.map +1 -1
- package/dist/test/e2e/stores/event-store.e2e.test.js +28 -4
- package/dist/test/e2e/stores/event-store.e2e.test.js.map +1 -1
- package/dist/test/e2e/users/inactive/inactive-users-service.test.js +1 -1
- package/dist/test/e2e/users/inactive/inactive-users-service.test.js.map +1 -1
- package/dist/test/fixtures/fake-client-applications-store.d.ts +1 -0
- package/dist/test/fixtures/fake-client-applications-store.d.ts.map +1 -1
- package/dist/test/fixtures/fake-client-applications-store.js +3 -0
- package/dist/test/fixtures/fake-client-applications-store.js.map +1 -1
- package/dist/test/fixtures/fake-event-store.d.ts +3 -2
- package/dist/test/fixtures/fake-event-store.d.ts.map +1 -1
- package/dist/test/fixtures/fake-event-store.js +3 -2
- package/dist/test/fixtures/fake-event-store.js.map +1 -1
- package/dist/test/fixtures/fake-impact-metrics.d.ts +2 -7
- package/dist/test/fixtures/fake-impact-metrics.d.ts.map +1 -1
- package/dist/test/fixtures/fake-impact-metrics.js.map +1 -1
- package/dist/test/fixtures/store.js +1 -1
- package/dist/test/fixtures/store.js.map +1 -1
- package/dist/test-setup.d.ts.map +1 -1
- package/dist/test-setup.js +3 -1
- package/dist/test-setup.js.map +1 -1
- package/frontend/build/index.html +2 -2
- package/frontend/build/static/AdvancedPlayground-V8umnmfG.js +3 -0
- package/frontend/build/static/BackendConnections-Cnrrjtsn.js +1 -0
- package/frontend/build/static/CreateProject-e6oazDvk.js +1 -0
- package/frontend/build/static/EnterpriseEdge-DBAPcWwZ.js +6 -0
- package/frontend/build/static/FeatureMetricsChart-CKOQrO5t.js +2 -0
- package/frontend/build/static/FeatureStaleDialog-BfIPQAKa.js +689 -0
- package/frontend/build/static/FeatureViewLazyExport-TYU7Gf7Q.js +11 -0
- package/frontend/build/static/FlagMetricsChart-D1Fksr08.js +2 -0
- package/frontend/build/static/FrontendNetworkTrafficUsage-NjIKHiwN.js +1 -0
- package/frontend/build/static/GridLayoutWrapper-CN2Zeusb.js +3 -0
- package/frontend/build/static/ImpactMetricsPage-PU6tVGs8.js +1 -0
- package/frontend/build/static/LazyAdminExport-7jFrQoFr.js +38 -0
- package/frontend/build/static/LazyProjectExport-DUuBB2EA.js +46 -0
- package/frontend/build/static/LifecycleChartComponent-LoQvj2mM.js +2 -0
- package/frontend/build/static/LineChartComponent-C2nacZSy.js +1 -0
- package/frontend/build/static/MarkCompletedDialogue-x4B5vgpn.js +1 -0
- package/frontend/build/static/NetworkOverview-DRDwkRie.js +1 -0
- package/frontend/build/static/NetworkPrometheusAPIWarning-DxrGyF-4.js +1 -0
- package/frontend/build/static/NetworkTraffic-DBNI6tQ4.js +1 -0
- package/frontend/build/static/NetworkTrafficUsage-Cp7LXHBW.js +1 -0
- package/frontend/build/static/PercentageDonut-DxYx2sDT.js +1 -0
- package/frontend/build/static/ReactJSONEditor-EiPmcfsb.js +3846 -0
- package/frontend/build/static/RoleCell-DPCs9tBq.js +1 -0
- package/frontend/build/static/Safeguard-B2SRkWlK.js +1 -0
- package/frontend/build/static/aggregateFeatureMetrics-B--WhUm6.js +1 -0
- package/frontend/build/static/chart-BMc0j_v5.js +3 -0
- package/frontend/build/static/chartjs-plugin-annotation.esm-CII-nIyK.js +1 -0
- package/frontend/build/static/daysOrHours-CWsdHL8Z.js +1 -0
- package/frontend/build/static/dist-CYYjHgCS.js +12 -0
- package/frontend/build/static/enterpriseEdgeCloud-DI6o2DkU.js +1 -0
- package/frontend/build/static/formatTickValue-DHdXPo89.js +1 -0
- package/frontend/build/static/helpers-Dz6x6iMP.js +1 -0
- package/frontend/build/static/index-B0RbDPtk.js +403 -0
- package/frontend/build/static/jsx-runtime-ButemYzH.js +1 -0
- package/frontend/build/static/networkTrafficUsageHighlightPlugin-ecHJHisK.js +1 -0
- package/frontend/build/static/objectId-D7ukzTLu.js +1 -0
- package/frontend/build/static/style-D9DNbuD5.css +2 -0
- package/frontend/build/static/toDate-zSA17Csy.js +1 -0
- package/frontend/build/static/unknownify-D1gvOkgV.js +1 -0
- package/frontend/build/static/useApiTokens-Cl4y9yhp.js +1 -0
- package/frontend/build/static/useInstanceTrafficMetrics--5pof2Er.js +1 -0
- package/frontend/build/static/vanilla-picker-DhahMYgI.js +2 -0
- package/frontend/package.json +18 -15
- package/package.json +9 -9
- package/dist/lib/db/setting-store.d.ts.map +0 -1
- package/dist/lib/db/setting-store.js.map +0 -1
- package/dist/lib/services/setting-service.d.ts.map +0 -1
- package/dist/lib/services/setting-service.js.map +0 -1
- package/dist/lib/types/stores/settings-store.d.ts.map +0 -1
- package/dist/lib/types/stores/settings-store.js +0 -2
- package/dist/lib/types/stores/settings-store.js.map +0 -1
- package/dist/test/e2e/services/setting-service.test.d.ts +0 -2
- package/dist/test/e2e/services/setting-service.test.d.ts.map +0 -1
- package/dist/test/e2e/services/setting-service.test.js.map +0 -1
- package/dist/test/e2e/stores/setting-store.e2e.test.d.ts.map +0 -1
- package/dist/test/e2e/stores/setting-store.e2e.test.js.map +0 -1
- package/dist/test/fixtures/fake-setting-store.d.ts.map +0 -1
- package/dist/test/fixtures/fake-setting-store.js.map +0 -1
- package/frontend/build/static/24_Text format off-fTw1GZh5.svg +0 -3
- package/frontend/build/static/24_Text format-CsA8QQJI.svg +0 -3
- package/frontend/build/static/AdvancedPlayground-BTPrG6RW.js +0 -3
- package/frontend/build/static/BackendConnections-CRh8Vxoe.js +0 -1
- package/frontend/build/static/CreateProject-DEMalH1j.js +0 -1
- package/frontend/build/static/EnterpriseEdge-Cp-pGMa0.js +0 -6
- package/frontend/build/static/FeatureMetricsChart-DQOE71LA.js +0 -2
- package/frontend/build/static/FeatureStaleDialog-B6BfnDiQ.js +0 -689
- package/frontend/build/static/FeatureViewLazyExport-BkNTNFqK.js +0 -10
- package/frontend/build/static/FlagMetricsChart-zYDF9bet.js +0 -2
- package/frontend/build/static/FrontendNetworkTrafficUsage-CbxdFXH7.js +0 -1
- package/frontend/build/static/GridLayoutWrapper-Cq6Bzm36.js +0 -3
- package/frontend/build/static/ImpactMetricsPage-CFYXYXPb.js +0 -1
- package/frontend/build/static/LazyAdminExport-ByTh4iFa.js +0 -38
- package/frontend/build/static/LazyProjectExport-K12Xy3w9.js +0 -46
- package/frontend/build/static/LifecycleChartComponent-DHvlFNd2.js +0 -7
- package/frontend/build/static/LineChartComponent-BlhKm3cw.js +0 -1
- package/frontend/build/static/MarkCompletedDialogue-apmlFjVY.js +0 -1
- package/frontend/build/static/NetworkOverview-BiLOuQ4c.js +0 -1
- package/frontend/build/static/NetworkPrometheusAPIWarning-CYo3j2Tj.js +0 -1
- package/frontend/build/static/NetworkTraffic-DONL5oIx.js +0 -1
- package/frontend/build/static/NetworkTrafficUsage-DjQiYq0S.js +0 -1
- package/frontend/build/static/PercentageDonut-CA9hYg3v.js +0 -1
- package/frontend/build/static/ReactJSONEditor-9cJL1vJY.js +0 -3864
- package/frontend/build/static/RoleCell-ZzU5Oqy8.js +0 -1
- package/frontend/build/static/Safeguard-DY1N4aPz.js +0 -1
- package/frontend/build/static/aggregateFeatureMetrics-D6bHft_C.js +0 -1
- package/frontend/build/static/arrowLeft-CLDXfK18.svg +0 -10
- package/frontend/build/static/arrowRight-CPIADLBv.svg +0 -10
- package/frontend/build/static/case-insensitive-CuU5weZd.svg +0 -1
- package/frontend/build/static/case-sensitive-D19NntKP.svg +0 -1
- package/frontend/build/static/changeRequestProcessWithSchedule-BmvIIWQK.svg +0 -1
- package/frontend/build/static/constraint-equals-giGu3HWQ.svg +0 -1
- package/frontend/build/static/constraint-not-equals-CJGG9pRv.svg +0 -1
- package/frontend/build/static/docker-HG7DQx-Z.svg +0 -5
- package/frontend/build/static/email-D1NVbpvG.svg +0 -17
- package/frontend/build/static/enterpriseEdgeCloud-DzRtm8v6.svg +0 -58
- package/frontend/build/static/enterpriseEdgeSelfHosted-4bnmOQVF.svg +0 -44
- package/frontend/build/static/formatTickValue-BcLsqREh.js +0 -6
- package/frontend/build/static/heart-FRDdnX3J.svg +0 -3
- package/frontend/build/static/impact-metrics-icon-a6_57VN1.svg +0 -9
- package/frontend/build/static/import-zkumD9Zv.svg +0 -3
- package/frontend/build/static/index-B87DWXbl.js +0 -12
- package/frontend/build/static/index-CoLhlfXP.js +0 -565
- package/frontend/build/static/instance-health-BtMrnXEj.svg +0 -5
- package/frontend/build/static/isenabled-false-Bx8bRzGD.svg +0 -5
- package/frontend/build/static/isenabled-true-BARsh3fa.svg +0 -5
- package/frontend/build/static/lenovo-DIzNtfrT.svg +0 -3
- package/frontend/build/static/lloyds-DxlC9g3t.svg +0 -10
- package/frontend/build/static/logo-BpeRJ1SV.svg +0 -7
- package/frontend/build/static/logoBg-DDUbF9lh.svg +0 -1
- package/frontend/build/static/logoDark-CknUTJYV.svg +0 -1
- package/frontend/build/static/logoDarkWithText-D0ImZCxR.svg +0 -1
- package/frontend/build/static/logoWhiteBg-CwoWCg7m.svg +0 -1
- package/frontend/build/static/logoWhiteTransparentHorizontal-5xxVCWh8.svg +0 -1
- package/frontend/build/static/logoWithWhiteText-Dz7VvON3.svg +0 -1
- package/frontend/build/static/milestone-C0FnRl9y.svg +0 -3
- package/frontend/build/static/mobileGuidanceBg-D9dRgnhs.svg +0 -3
- package/frontend/build/static/networkTrafficUsageHighlightPlugin-CqEM-cK_.js +0 -1
- package/frontend/build/static/new-feature-badge-FwMmHlwT.svg +0 -7
- package/frontend/build/static/not_operator_selected-jLHDQXLO.svg +0 -5
- package/frontend/build/static/not_operator_unselected-C-130FKT.svg +0 -3
- package/frontend/build/static/pro-enterprise-feature-badge-PZ3Bfajk.svg +0 -7
- package/frontend/build/static/pro-enterprise-feature-badge-light-k8Z592E8.svg +0 -6
- package/frontend/build/static/projectIconSmall-USf1kO_6.svg +0 -5
- package/frontend/build/static/projectStatus-BQym9o3t.svg +0 -3
- package/frontend/build/static/releaseTemplates-GIHEC4g-.svg +0 -39
- package/frontend/build/static/rollout-DAvS9K1l.svg +0 -4
- package/frontend/build/static/samsung-DOytOsnV.svg +0 -10
- package/frontend/build/static/signals-Bg0cQEqp.svg +0 -21
- package/frontend/build/static/stage-archived-DVpSnWM_.svg +0 -12
- package/frontend/build/static/stage-completed-BqA7cOHN.svg +0 -10
- package/frontend/build/static/stage-created-IXXGyXPL.svg +0 -5
- package/frontend/build/static/stage-live-CnCQFmyK.svg +0 -9
- package/frontend/build/static/stage-prelive-BLsuhDY7.svg +0 -7
- package/frontend/build/static/stars-C5lq_xha.svg +0 -9
- package/frontend/build/static/strategyCustom-Db-ZtYWl.svg +0 -23
- package/frontend/build/static/strategyDefault-LnSyH2eZ.svg +0 -17
- package/frontend/build/static/strategyGradual-oCA99tj3.svg +0 -18
- package/frontend/build/static/strategyHosts-4lVYC2Bf.svg +0 -23
- package/frontend/build/static/strategyIPs-BHaXsOYV.svg +0 -24
- package/frontend/build/static/strategyOn-CX-xL0oK.svg +0 -18
- package/frontend/build/static/style-BfdqROT6.css +0 -1
- package/frontend/build/static/unknownify-B7hmSXnj.js +0 -1
- package/frontend/build/static/unleashHoliday-CQEG77-1.svg +0 -33
- package/frontend/build/static/unleashHolidayDark-B9sYfzSK.svg +0 -33
- package/frontend/build/static/usage-line-BHicDx-Y.svg +0 -3
- package/frontend/build/static/usage-rate-DnXQhqDI.svg +0 -3
- package/frontend/build/static/useApiTokens-ClWvohC9.js +0 -1
- package/frontend/build/static/vanilla-picker-B6E6ObS_.js +0 -8
- package/frontend/build/static/visa-CkneNM2O.svg +0 -10
- /package/dist/{test/fixtures → lib/features/settings}/fake-setting-store.js +0 -0
- /package/dist/{test/e2e/stores → lib/features/settings}/setting-store.e2e.test.d.ts +0 -0
- /package/dist/lib/{db → features/settings}/setting-store.js +0 -0
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
import { EventEmitter } from 'events';
|
|
2
|
+
import { register } from 'prom-client';
|
|
2
3
|
import { ClientFeatureToggleDelta, filterEventsByQuery, } from './client-feature-toggle-delta.js';
|
|
3
4
|
import { DeltaCache } from './delta-cache.js';
|
|
4
|
-
import { FEATURE_PROJECT_CHANGE } from '../../../events/index.js';
|
|
5
|
+
import { FEATURE_PROJECT_CHANGE, SEGMENT_DELETED, } from '../../../events/index.js';
|
|
6
|
+
const createLogger = () => ({
|
|
7
|
+
error: () => undefined,
|
|
8
|
+
info: () => undefined,
|
|
9
|
+
warn: () => undefined,
|
|
10
|
+
});
|
|
11
|
+
const createDeltaConfig = () => ({
|
|
12
|
+
eventBus: new EventEmitter(),
|
|
13
|
+
getLogger: () => createLogger(),
|
|
14
|
+
});
|
|
5
15
|
describe('filterEventsByQuery', () => {
|
|
6
16
|
const mockEvents = [
|
|
7
17
|
{
|
|
@@ -37,7 +47,7 @@ describe('filterEventsByQuery', () => {
|
|
|
37
47
|
];
|
|
38
48
|
test('filters events based on eventId', () => {
|
|
39
49
|
const requiredRevisionId = 2;
|
|
40
|
-
const result = filterEventsByQuery(mockEvents, requiredRevisionId, ['project3'], '');
|
|
50
|
+
const result = filterEventsByQuery(mockEvents, requiredRevisionId, ['project3'], '', new Set([1, 2]));
|
|
41
51
|
expect(result).toEqual([
|
|
42
52
|
{
|
|
43
53
|
eventId: 3,
|
|
@@ -54,11 +64,11 @@ describe('filterEventsByQuery', () => {
|
|
|
54
64
|
]);
|
|
55
65
|
});
|
|
56
66
|
test('returns all projects', () => {
|
|
57
|
-
const result = filterEventsByQuery(mockEvents, 0, ['*'], '');
|
|
67
|
+
const result = filterEventsByQuery(mockEvents, 0, ['*'], '', new Set([1]));
|
|
58
68
|
expect(result).toEqual(mockEvents);
|
|
59
69
|
});
|
|
60
70
|
test('filters by name prefix', () => {
|
|
61
|
-
const result = filterEventsByQuery(mockEvents, 0, ['project1', 'project2'], 'alpha');
|
|
71
|
+
const result = filterEventsByQuery(mockEvents, 0, ['project1', 'project2'], 'alpha', new Set([1, 2]));
|
|
62
72
|
expect(result).toEqual([
|
|
63
73
|
{
|
|
64
74
|
eventId: 2,
|
|
@@ -78,7 +88,8 @@ describe('filterEventsByQuery', () => {
|
|
|
78
88
|
]);
|
|
79
89
|
});
|
|
80
90
|
test('filters by project list', () => {
|
|
81
|
-
const
|
|
91
|
+
const referencedSegmentIds = new Set([1, 2]);
|
|
92
|
+
const result = filterEventsByQuery(mockEvents, 0, ['project3'], 'beta', referencedSegmentIds);
|
|
82
93
|
expect(result).toEqual([
|
|
83
94
|
{
|
|
84
95
|
eventId: 3,
|
|
@@ -91,6 +102,7 @@ describe('filterEventsByQuery', () => {
|
|
|
91
102
|
type: 'segment-updated',
|
|
92
103
|
segment: { id: 1, name: 'my-segment', constraints: [] },
|
|
93
104
|
},
|
|
105
|
+
// we propagate segment removed. Once dereferenced removing them should save memory
|
|
94
106
|
{ eventId: 5, type: 'segment-removed', segmentId: 2 },
|
|
95
107
|
]);
|
|
96
108
|
});
|
|
@@ -149,6 +161,457 @@ describe('DeltaCache hydration ordering', () => {
|
|
|
149
161
|
});
|
|
150
162
|
});
|
|
151
163
|
describe('ClientFeatureToggleDelta bootstrap behavior', () => {
|
|
164
|
+
test('segment-created alone does not advance visible revision for an environment where it is unused', async () => {
|
|
165
|
+
let currentRevisionId = 1;
|
|
166
|
+
const delta = new ClientFeatureToggleDelta({
|
|
167
|
+
getAll: async ({ environment, toggleNames = [], }) => {
|
|
168
|
+
const developmentFeature = {
|
|
169
|
+
name: 'first',
|
|
170
|
+
project: 'default',
|
|
171
|
+
enabled: false,
|
|
172
|
+
};
|
|
173
|
+
if (environment !== 'development') {
|
|
174
|
+
return [];
|
|
175
|
+
}
|
|
176
|
+
if (toggleNames.length === 0) {
|
|
177
|
+
return [developmentFeature];
|
|
178
|
+
}
|
|
179
|
+
return toggleNames.includes('first')
|
|
180
|
+
? [developmentFeature]
|
|
181
|
+
: [];
|
|
182
|
+
},
|
|
183
|
+
}, {
|
|
184
|
+
getAllForClientIds: async (ids) => ids?.includes(101)
|
|
185
|
+
? [{ id: 101, name: 'segment-a', constraints: [] }]
|
|
186
|
+
: [],
|
|
187
|
+
}, {
|
|
188
|
+
getDeltaRevisionState: async () => ({
|
|
189
|
+
projectRevisions: new Map([['default', 1]]),
|
|
190
|
+
maxReferencedSegmentRevision: 0,
|
|
191
|
+
segmentRevisions: new Map(),
|
|
192
|
+
}),
|
|
193
|
+
getRevisionRange: async () => [
|
|
194
|
+
{
|
|
195
|
+
id: 2,
|
|
196
|
+
type: 'segment-created',
|
|
197
|
+
data: { id: 101, name: 'segment-a' },
|
|
198
|
+
createdAt: new Date(),
|
|
199
|
+
},
|
|
200
|
+
],
|
|
201
|
+
getMaxRevisionId: async () => currentRevisionId,
|
|
202
|
+
}, {
|
|
203
|
+
on: () => undefined,
|
|
204
|
+
}, {
|
|
205
|
+
isEnabled: (name) => name === 'deltaApi',
|
|
206
|
+
}, createDeltaConfig());
|
|
207
|
+
const baseline = await delta.getDelta(undefined, {
|
|
208
|
+
environment: 'development',
|
|
209
|
+
project: ['default'],
|
|
210
|
+
});
|
|
211
|
+
currentRevisionId = 2;
|
|
212
|
+
await delta.onUpdateRevisionEvent();
|
|
213
|
+
const result = await delta.getDelta(1, {
|
|
214
|
+
environment: 'development',
|
|
215
|
+
project: ['default'],
|
|
216
|
+
});
|
|
217
|
+
expect(baseline?.events[0]?.eventId).toBe(1);
|
|
218
|
+
expect(result).toBeUndefined();
|
|
219
|
+
});
|
|
220
|
+
test('segment-created followed by unrelated environment change does not advance visible revision and hydration stays in parity', async () => {
|
|
221
|
+
const currentRevisionId = 1;
|
|
222
|
+
const createReadModel = () => ({
|
|
223
|
+
getAll: async ({ environment, toggleNames = [], }) => {
|
|
224
|
+
const featureByEnvironment = {
|
|
225
|
+
development: {
|
|
226
|
+
name: 'first',
|
|
227
|
+
project: 'default',
|
|
228
|
+
enabled: false,
|
|
229
|
+
},
|
|
230
|
+
production: {
|
|
231
|
+
name: 'first',
|
|
232
|
+
project: 'default',
|
|
233
|
+
enabled: true,
|
|
234
|
+
},
|
|
235
|
+
};
|
|
236
|
+
const feature = featureByEnvironment[environment];
|
|
237
|
+
if (!feature) {
|
|
238
|
+
return [];
|
|
239
|
+
}
|
|
240
|
+
if (toggleNames.length === 0) {
|
|
241
|
+
return [feature];
|
|
242
|
+
}
|
|
243
|
+
return toggleNames.includes('first') ? [feature] : [];
|
|
244
|
+
},
|
|
245
|
+
});
|
|
246
|
+
const createSegmentModel = () => ({
|
|
247
|
+
getAllForClientIds: async (ids) => ids?.includes(101)
|
|
248
|
+
? [{ id: 101, name: 'segment-a', constraints: [] }]
|
|
249
|
+
: [],
|
|
250
|
+
});
|
|
251
|
+
const createEventStore = () => ({
|
|
252
|
+
getDeltaRevisionState: async () => ({
|
|
253
|
+
projectRevisions: new Map([['default', 1]]),
|
|
254
|
+
maxReferencedSegmentRevision: 0,
|
|
255
|
+
segmentRevisions: new Map(),
|
|
256
|
+
}),
|
|
257
|
+
getRevisionRange: async () => [
|
|
258
|
+
{
|
|
259
|
+
id: 2,
|
|
260
|
+
type: 'segment-created',
|
|
261
|
+
data: { id: 101, name: 'segment-a' },
|
|
262
|
+
createdAt: new Date(),
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
id: 3,
|
|
266
|
+
type: 'feature-updated',
|
|
267
|
+
featureName: 'first',
|
|
268
|
+
project: 'default',
|
|
269
|
+
environment: 'production',
|
|
270
|
+
},
|
|
271
|
+
],
|
|
272
|
+
getMaxRevisionId: async () => currentRevisionId,
|
|
273
|
+
});
|
|
274
|
+
const liveDelta = new ClientFeatureToggleDelta(createReadModel(), createSegmentModel(), createEventStore(), {
|
|
275
|
+
on: () => undefined,
|
|
276
|
+
}, {
|
|
277
|
+
isEnabled: (name) => name === 'deltaApi',
|
|
278
|
+
}, createDeltaConfig());
|
|
279
|
+
const initialHydration = await liveDelta.getDelta(undefined, {
|
|
280
|
+
environment: 'development',
|
|
281
|
+
project: ['default'],
|
|
282
|
+
});
|
|
283
|
+
expect(initialHydration?.events[0]?.eventId).toBe(1);
|
|
284
|
+
await liveDelta.onUpdateRevisionEvent();
|
|
285
|
+
const liveResult = await liveDelta.getDelta(1, {
|
|
286
|
+
environment: 'development',
|
|
287
|
+
project: ['default'],
|
|
288
|
+
});
|
|
289
|
+
expect(liveResult).toBeUndefined();
|
|
290
|
+
const freshDelta = new ClientFeatureToggleDelta(createReadModel(), createSegmentModel(), createEventStore(), {
|
|
291
|
+
on: () => undefined,
|
|
292
|
+
}, {}, createDeltaConfig());
|
|
293
|
+
const freshHydration = await freshDelta.getDelta(undefined, {
|
|
294
|
+
environment: 'development',
|
|
295
|
+
project: ['default'],
|
|
296
|
+
});
|
|
297
|
+
expect(freshHydration?.events[0]?.eventId).toBe(1);
|
|
298
|
+
});
|
|
299
|
+
test('segment-updated only advances visible revision when the segment is referenced by a visible feature', async () => {
|
|
300
|
+
let currentRevisionId = 1;
|
|
301
|
+
const createEventStore = () => ({
|
|
302
|
+
getDeltaRevisionState: async () => ({
|
|
303
|
+
projectRevisions: new Map([['default', 1]]),
|
|
304
|
+
maxReferencedSegmentRevision: 1,
|
|
305
|
+
segmentRevisions: new Map(),
|
|
306
|
+
}),
|
|
307
|
+
getRevisionRange: async () => [
|
|
308
|
+
{
|
|
309
|
+
id: 2,
|
|
310
|
+
type: 'segment-updated',
|
|
311
|
+
data: { id: 101, name: 'segment-a' },
|
|
312
|
+
createdAt: new Date(),
|
|
313
|
+
},
|
|
314
|
+
],
|
|
315
|
+
getMaxRevisionId: async () => currentRevisionId,
|
|
316
|
+
});
|
|
317
|
+
const createSegmentModel = () => ({
|
|
318
|
+
getAllForClientIds: async (ids) => ids?.includes(101)
|
|
319
|
+
? [{ id: 101, name: 'segment-a', constraints: [] }]
|
|
320
|
+
: [],
|
|
321
|
+
});
|
|
322
|
+
const unreferencedSegment = new ClientFeatureToggleDelta({
|
|
323
|
+
getAll: async () => [
|
|
324
|
+
{
|
|
325
|
+
name: 'first',
|
|
326
|
+
project: 'default',
|
|
327
|
+
enabled: false,
|
|
328
|
+
},
|
|
329
|
+
],
|
|
330
|
+
}, createSegmentModel(), createEventStore(), {
|
|
331
|
+
on: () => undefined,
|
|
332
|
+
}, {
|
|
333
|
+
isEnabled: (name) => name === 'deltaApi',
|
|
334
|
+
}, createDeltaConfig());
|
|
335
|
+
await unreferencedSegment.getDelta(undefined, {
|
|
336
|
+
environment: 'development',
|
|
337
|
+
project: ['default'],
|
|
338
|
+
});
|
|
339
|
+
currentRevisionId = 2;
|
|
340
|
+
await unreferencedSegment.onUpdateRevisionEvent();
|
|
341
|
+
const unusedResult = await unreferencedSegment.getDelta(1, {
|
|
342
|
+
environment: 'development',
|
|
343
|
+
project: ['default'],
|
|
344
|
+
});
|
|
345
|
+
expect(unusedResult).toBeUndefined();
|
|
346
|
+
const usedDelta = new ClientFeatureToggleDelta({
|
|
347
|
+
getAll: async () => [
|
|
348
|
+
{
|
|
349
|
+
name: 'first',
|
|
350
|
+
project: 'default',
|
|
351
|
+
enabled: false,
|
|
352
|
+
strategies: [{ name: 'default', segments: [101] }],
|
|
353
|
+
},
|
|
354
|
+
],
|
|
355
|
+
}, createSegmentModel(), createEventStore(), {
|
|
356
|
+
on: () => undefined,
|
|
357
|
+
}, {
|
|
358
|
+
isEnabled: (name) => name === 'deltaApi',
|
|
359
|
+
}, createDeltaConfig());
|
|
360
|
+
await usedDelta.getDelta(undefined, {
|
|
361
|
+
environment: 'development',
|
|
362
|
+
project: ['default'],
|
|
363
|
+
});
|
|
364
|
+
currentRevisionId = 2;
|
|
365
|
+
await usedDelta.onUpdateRevisionEvent();
|
|
366
|
+
const usedResult = await usedDelta.getDelta(1, {
|
|
367
|
+
environment: 'development',
|
|
368
|
+
project: ['default'],
|
|
369
|
+
});
|
|
370
|
+
expect(usedResult).toEqual({
|
|
371
|
+
events: [
|
|
372
|
+
{
|
|
373
|
+
eventId: 2,
|
|
374
|
+
type: 'segment-updated',
|
|
375
|
+
segment: { id: 101, name: 'segment-a', constraints: [] },
|
|
376
|
+
},
|
|
377
|
+
],
|
|
378
|
+
});
|
|
379
|
+
});
|
|
380
|
+
test('segment-removed is delivered with the feature update that dereferences it', async () => {
|
|
381
|
+
let currentRevisionId = 1;
|
|
382
|
+
let featureReferencesSegment = true;
|
|
383
|
+
const delta = new ClientFeatureToggleDelta({
|
|
384
|
+
getAll: async () => [
|
|
385
|
+
{
|
|
386
|
+
name: 'first',
|
|
387
|
+
project: 'default',
|
|
388
|
+
enabled: false,
|
|
389
|
+
strategies: [
|
|
390
|
+
featureReferencesSegment
|
|
391
|
+
? { name: 'default', segments: [101] }
|
|
392
|
+
: { name: 'default' },
|
|
393
|
+
],
|
|
394
|
+
},
|
|
395
|
+
],
|
|
396
|
+
}, {
|
|
397
|
+
getAllForClientIds: async (ids) => ids === undefined || ids.includes(101)
|
|
398
|
+
? [{ id: 101, name: 'segment-a', constraints: [] }]
|
|
399
|
+
: [],
|
|
400
|
+
}, {
|
|
401
|
+
getDeltaRevisionState: async () => ({
|
|
402
|
+
projectRevisions: new Map([['default', 1]]),
|
|
403
|
+
maxReferencedSegmentRevision: 1,
|
|
404
|
+
segmentRevisions: new Map([[101, 1]]),
|
|
405
|
+
}),
|
|
406
|
+
getRevisionRange: async () => [
|
|
407
|
+
{
|
|
408
|
+
id: 2,
|
|
409
|
+
type: 'feature-updated',
|
|
410
|
+
featureName: 'first',
|
|
411
|
+
project: 'default',
|
|
412
|
+
environment: 'development',
|
|
413
|
+
createdAt: new Date(),
|
|
414
|
+
},
|
|
415
|
+
{
|
|
416
|
+
id: 3,
|
|
417
|
+
type: SEGMENT_DELETED,
|
|
418
|
+
preData: { id: 101, name: 'segment-a' },
|
|
419
|
+
createdAt: new Date(),
|
|
420
|
+
},
|
|
421
|
+
],
|
|
422
|
+
getMaxRevisionId: async () => currentRevisionId,
|
|
423
|
+
}, {
|
|
424
|
+
on: () => undefined,
|
|
425
|
+
}, {
|
|
426
|
+
isEnabled: (name) => name === 'deltaApi',
|
|
427
|
+
}, createDeltaConfig());
|
|
428
|
+
await delta.getDelta(undefined, {
|
|
429
|
+
environment: 'development',
|
|
430
|
+
project: ['default'],
|
|
431
|
+
});
|
|
432
|
+
featureReferencesSegment = false;
|
|
433
|
+
currentRevisionId = 3;
|
|
434
|
+
await delta.onUpdateRevisionEvent();
|
|
435
|
+
const result = await delta.getDelta(1, {
|
|
436
|
+
environment: 'development',
|
|
437
|
+
project: ['default'],
|
|
438
|
+
});
|
|
439
|
+
expect(result).toEqual({
|
|
440
|
+
events: [
|
|
441
|
+
{
|
|
442
|
+
eventId: 2,
|
|
443
|
+
type: 'feature-updated',
|
|
444
|
+
feature: {
|
|
445
|
+
name: 'first',
|
|
446
|
+
project: 'default',
|
|
447
|
+
enabled: false,
|
|
448
|
+
strategies: [{ name: 'default' }],
|
|
449
|
+
},
|
|
450
|
+
},
|
|
451
|
+
{
|
|
452
|
+
eventId: 3,
|
|
453
|
+
type: 'segment-removed',
|
|
454
|
+
segmentId: 101,
|
|
455
|
+
},
|
|
456
|
+
],
|
|
457
|
+
});
|
|
458
|
+
});
|
|
459
|
+
test('returns segment payload when a feature newly references a previously hidden segment update', async () => {
|
|
460
|
+
let currentRevisionId = 7;
|
|
461
|
+
const eventStore = {
|
|
462
|
+
getDeltaRevisionState: async () => ({
|
|
463
|
+
projectRevisions: new Map([['default', 7]]),
|
|
464
|
+
maxReferencedSegmentRevision: 7,
|
|
465
|
+
segmentRevisions: new Map(),
|
|
466
|
+
}),
|
|
467
|
+
getRevisionRange: async (from, to) => {
|
|
468
|
+
if (from === 7 && to === 14) {
|
|
469
|
+
return [
|
|
470
|
+
{
|
|
471
|
+
id: 12,
|
|
472
|
+
type: 'segment-updated',
|
|
473
|
+
data: { id: 1, name: 'segment-a' },
|
|
474
|
+
createdAt: new Date(),
|
|
475
|
+
},
|
|
476
|
+
{
|
|
477
|
+
id: 14,
|
|
478
|
+
type: 'feature-updated',
|
|
479
|
+
featureName: 'test-flag',
|
|
480
|
+
project: 'default',
|
|
481
|
+
environment: 'development',
|
|
482
|
+
data: { name: 'test-flag', enabled: true },
|
|
483
|
+
createdAt: new Date(),
|
|
484
|
+
},
|
|
485
|
+
];
|
|
486
|
+
}
|
|
487
|
+
return [
|
|
488
|
+
{
|
|
489
|
+
id: 15,
|
|
490
|
+
type: 'feature-updated',
|
|
491
|
+
featureName: 'test-flag',
|
|
492
|
+
project: 'default',
|
|
493
|
+
environment: 'development',
|
|
494
|
+
data: { name: 'test-flag', enabled: true },
|
|
495
|
+
createdAt: new Date(),
|
|
496
|
+
},
|
|
497
|
+
];
|
|
498
|
+
},
|
|
499
|
+
getMaxRevisionId: async () => currentRevisionId,
|
|
500
|
+
};
|
|
501
|
+
const readModel = {
|
|
502
|
+
getAll: async ({ toggleNames = [], }) => {
|
|
503
|
+
if (toggleNames.includes('test-flag') &&
|
|
504
|
+
currentRevisionId >= 15) {
|
|
505
|
+
return [
|
|
506
|
+
{
|
|
507
|
+
name: 'test-flag',
|
|
508
|
+
project: 'default',
|
|
509
|
+
enabled: true,
|
|
510
|
+
strategies: [{ name: 'default', segments: [1] }],
|
|
511
|
+
},
|
|
512
|
+
];
|
|
513
|
+
}
|
|
514
|
+
return [
|
|
515
|
+
{
|
|
516
|
+
name: 'test-flag',
|
|
517
|
+
project: 'default',
|
|
518
|
+
enabled: true,
|
|
519
|
+
strategies: [{ name: 'default' }],
|
|
520
|
+
},
|
|
521
|
+
];
|
|
522
|
+
},
|
|
523
|
+
};
|
|
524
|
+
const segmentReadModel = {
|
|
525
|
+
getAllForClientIds: async (ids) => ids?.includes(1)
|
|
526
|
+
? [{ id: 1, name: 'segment-a', constraints: [] }]
|
|
527
|
+
: [],
|
|
528
|
+
};
|
|
529
|
+
const delta = new ClientFeatureToggleDelta(readModel, segmentReadModel, eventStore, {
|
|
530
|
+
on: () => undefined,
|
|
531
|
+
}, {
|
|
532
|
+
isEnabled: (name) => name === 'deltaApi',
|
|
533
|
+
}, createDeltaConfig());
|
|
534
|
+
const hydration = await delta.getDelta(undefined, {
|
|
535
|
+
environment: 'development',
|
|
536
|
+
project: ['default'],
|
|
537
|
+
});
|
|
538
|
+
expect(hydration?.events[0]?.eventId).toBe(7);
|
|
539
|
+
currentRevisionId = 14;
|
|
540
|
+
await delta.onUpdateRevisionEvent();
|
|
541
|
+
const unrelatedUpdate = await delta.getDelta(7, {
|
|
542
|
+
environment: 'development',
|
|
543
|
+
project: ['default'],
|
|
544
|
+
});
|
|
545
|
+
expect(unrelatedUpdate).toEqual({
|
|
546
|
+
events: [
|
|
547
|
+
{
|
|
548
|
+
eventId: 14,
|
|
549
|
+
type: 'feature-updated',
|
|
550
|
+
feature: {
|
|
551
|
+
name: 'test-flag',
|
|
552
|
+
project: 'default',
|
|
553
|
+
enabled: true,
|
|
554
|
+
strategies: [{ name: 'default' }],
|
|
555
|
+
},
|
|
556
|
+
},
|
|
557
|
+
],
|
|
558
|
+
});
|
|
559
|
+
currentRevisionId = 15;
|
|
560
|
+
await delta.onUpdateRevisionEvent();
|
|
561
|
+
const newlyReferencedSegment = await delta.getDelta(14, {
|
|
562
|
+
environment: 'development',
|
|
563
|
+
project: ['default'],
|
|
564
|
+
});
|
|
565
|
+
expect(newlyReferencedSegment).toEqual({
|
|
566
|
+
events: [
|
|
567
|
+
{
|
|
568
|
+
eventId: 15,
|
|
569
|
+
type: 'segment-updated',
|
|
570
|
+
segment: { id: 1, name: 'segment-a', constraints: [] },
|
|
571
|
+
},
|
|
572
|
+
{
|
|
573
|
+
eventId: 15,
|
|
574
|
+
type: 'feature-updated',
|
|
575
|
+
feature: {
|
|
576
|
+
name: 'test-flag',
|
|
577
|
+
project: 'default',
|
|
578
|
+
enabled: true,
|
|
579
|
+
strategies: [{ name: 'default', segments: [1] }],
|
|
580
|
+
},
|
|
581
|
+
},
|
|
582
|
+
],
|
|
583
|
+
});
|
|
584
|
+
});
|
|
585
|
+
test('materializes delta_environment_revision_id on first hydration request', async () => {
|
|
586
|
+
const environment = 'metric-materialization-test';
|
|
587
|
+
const delta = new ClientFeatureToggleDelta({
|
|
588
|
+
getAll: async () => [
|
|
589
|
+
{
|
|
590
|
+
name: 'first',
|
|
591
|
+
project: 'default',
|
|
592
|
+
enabled: false,
|
|
593
|
+
},
|
|
594
|
+
],
|
|
595
|
+
}, {
|
|
596
|
+
getAllForClientIds: async () => [],
|
|
597
|
+
}, {
|
|
598
|
+
getDeltaRevisionState: async () => ({
|
|
599
|
+
projectRevisions: new Map([['default', 7]]),
|
|
600
|
+
maxReferencedSegmentRevision: 0,
|
|
601
|
+
segmentRevisions: new Map(),
|
|
602
|
+
}),
|
|
603
|
+
getMaxRevisionId: async () => 7,
|
|
604
|
+
}, {
|
|
605
|
+
on: () => undefined,
|
|
606
|
+
}, {}, createDeltaConfig());
|
|
607
|
+
const result = await delta.getDelta(undefined, {
|
|
608
|
+
environment,
|
|
609
|
+
project: ['default'],
|
|
610
|
+
});
|
|
611
|
+
const metrics = await register.metrics();
|
|
612
|
+
expect(result?.events[0]?.eventId).toBe(7);
|
|
613
|
+
expect(metrics).toMatch(new RegExp(`delta_environment_revision_id\\{environment="${environment}"\\} 7`));
|
|
614
|
+
});
|
|
152
615
|
test('returns the same wildcard hydration revision for identical environment state across pods', async () => {
|
|
153
616
|
const createDelta = (globalRevisionId) => new ClientFeatureToggleDelta({
|
|
154
617
|
getAll: async ({ environment, }) => environment === 'production'
|
|
@@ -165,7 +628,8 @@ describe('ClientFeatureToggleDelta bootstrap behavior', () => {
|
|
|
165
628
|
}, {
|
|
166
629
|
getDeltaRevisionState: async () => ({
|
|
167
630
|
projectRevisions: new Map([['default', 85815]]),
|
|
168
|
-
|
|
631
|
+
maxReferencedSegmentRevision: 0,
|
|
632
|
+
segmentRevisions: new Map(),
|
|
169
633
|
}),
|
|
170
634
|
getMaxRevisionId: async () => globalRevisionId,
|
|
171
635
|
}, {
|
|
@@ -199,7 +663,8 @@ describe('ClientFeatureToggleDelta bootstrap behavior', () => {
|
|
|
199
663
|
}, {
|
|
200
664
|
getDeltaRevisionState: async () => ({
|
|
201
665
|
projectRevisions: new Map(),
|
|
202
|
-
|
|
666
|
+
maxReferencedSegmentRevision: 0,
|
|
667
|
+
segmentRevisions: new Map(),
|
|
203
668
|
}),
|
|
204
669
|
getMaxRevisionId: async () => 0,
|
|
205
670
|
}, {
|
|
@@ -233,7 +698,8 @@ describe('ClientFeatureToggleDelta bootstrap behavior', () => {
|
|
|
233
698
|
}, {
|
|
234
699
|
getDeltaRevisionState: async () => ({
|
|
235
700
|
projectRevisions: new Map(),
|
|
236
|
-
|
|
701
|
+
maxReferencedSegmentRevision: 0,
|
|
702
|
+
segmentRevisions: new Map(),
|
|
237
703
|
}),
|
|
238
704
|
getMaxRevisionId: async () => 0,
|
|
239
705
|
}, {
|
|
@@ -253,7 +719,7 @@ describe('ClientFeatureToggleDelta bootstrap behavior', () => {
|
|
|
253
719
|
test('does not emit a no-op delta for an unrelated environment change', async () => {
|
|
254
720
|
let currentRevisionId = 1;
|
|
255
721
|
const delta = new ClientFeatureToggleDelta({
|
|
256
|
-
getAll: async ({ environment, toggleNames = [] }) => {
|
|
722
|
+
getAll: async ({ environment, toggleNames = [], }) => {
|
|
257
723
|
const developmentFeature = {
|
|
258
724
|
name: 'first',
|
|
259
725
|
project: 'default',
|
|
@@ -265,7 +731,6 @@ describe('ClientFeatureToggleDelta bootstrap behavior', () => {
|
|
|
265
731
|
if (toggleNames.length === 0) {
|
|
266
732
|
return [developmentFeature];
|
|
267
733
|
}
|
|
268
|
-
// @ts-expect-error - toggle name not defined
|
|
269
734
|
return toggleNames.includes('first')
|
|
270
735
|
? [developmentFeature]
|
|
271
736
|
: [];
|
|
@@ -275,7 +740,8 @@ describe('ClientFeatureToggleDelta bootstrap behavior', () => {
|
|
|
275
740
|
}, {
|
|
276
741
|
getDeltaRevisionState: async () => ({
|
|
277
742
|
projectRevisions: new Map([['default', 1]]),
|
|
278
|
-
|
|
743
|
+
maxReferencedSegmentRevision: 0,
|
|
744
|
+
segmentRevisions: new Map(),
|
|
279
745
|
}),
|
|
280
746
|
getRevisionRange: async () => [
|
|
281
747
|
{
|
|
@@ -313,7 +779,7 @@ describe('ClientFeatureToggleDelta bootstrap behavior', () => {
|
|
|
313
779
|
test('applies global events without environment to all initialized environments', async () => {
|
|
314
780
|
let currentRevisionId = 1;
|
|
315
781
|
const delta = new ClientFeatureToggleDelta({
|
|
316
|
-
getAll: async ({ environment, toggleNames = [] }) => {
|
|
782
|
+
getAll: async ({ environment, toggleNames = [], }) => {
|
|
317
783
|
const featuresByEnvironment = {
|
|
318
784
|
development: {
|
|
319
785
|
name: 'first',
|
|
@@ -333,7 +799,6 @@ describe('ClientFeatureToggleDelta bootstrap behavior', () => {
|
|
|
333
799
|
if (toggleNames.length === 0) {
|
|
334
800
|
return [feature];
|
|
335
801
|
}
|
|
336
|
-
// @ts-expect-error - toggle name not defined
|
|
337
802
|
return toggleNames.includes('first') ? [feature] : [];
|
|
338
803
|
},
|
|
339
804
|
}, {
|
|
@@ -341,7 +806,8 @@ describe('ClientFeatureToggleDelta bootstrap behavior', () => {
|
|
|
341
806
|
}, {
|
|
342
807
|
getDeltaRevisionState: async () => ({
|
|
343
808
|
projectRevisions: new Map([['default', 1]]),
|
|
344
|
-
|
|
809
|
+
maxReferencedSegmentRevision: 0,
|
|
810
|
+
segmentRevisions: new Map(),
|
|
345
811
|
}),
|
|
346
812
|
getRevisionRange: async () => [
|
|
347
813
|
{
|
|
@@ -412,7 +878,7 @@ describe('ClientFeatureToggleDelta bootstrap behavior', () => {
|
|
|
412
878
|
test('feature project move emits feature-removed for old project and feature-updated for new project', async () => {
|
|
413
879
|
let currentRevisionId = 1;
|
|
414
880
|
const delta = new ClientFeatureToggleDelta({
|
|
415
|
-
getAll: async ({ environment, toggleNames = [] }) => {
|
|
881
|
+
getAll: async ({ environment, toggleNames = [], }) => {
|
|
416
882
|
const feature = {
|
|
417
883
|
name: 'moved-feature',
|
|
418
884
|
project: 'new-project',
|
|
@@ -422,7 +888,6 @@ describe('ClientFeatureToggleDelta bootstrap behavior', () => {
|
|
|
422
888
|
return [];
|
|
423
889
|
if (toggleNames.length === 0)
|
|
424
890
|
return [feature];
|
|
425
|
-
// @ts-expect-error - toggle name not defined
|
|
426
891
|
return toggleNames.includes('moved-feature')
|
|
427
892
|
? [feature]
|
|
428
893
|
: [];
|
|
@@ -432,7 +897,8 @@ describe('ClientFeatureToggleDelta bootstrap behavior', () => {
|
|
|
432
897
|
}, {
|
|
433
898
|
getDeltaRevisionState: async () => ({
|
|
434
899
|
projectRevisions: new Map([['old-project', 1]]),
|
|
435
|
-
|
|
900
|
+
maxReferencedSegmentRevision: 0,
|
|
901
|
+
segmentRevisions: new Map(),
|
|
436
902
|
}),
|
|
437
903
|
getRevisionRange: async () => [
|
|
438
904
|
{
|
|
@@ -523,7 +989,7 @@ describe('ClientFeatureToggleDelta bootstrap behavior', () => {
|
|
|
523
989
|
test('bulk events pick the max revision id for the envelope', async () => {
|
|
524
990
|
let currentRevisionId = 1;
|
|
525
991
|
const delta = new ClientFeatureToggleDelta({
|
|
526
|
-
getAll: async ({ environment, toggleNames = [] }) => {
|
|
992
|
+
getAll: async ({ environment, toggleNames = [], }) => {
|
|
527
993
|
const featuresByEnvironment = {
|
|
528
994
|
development: {
|
|
529
995
|
name: 'first',
|
|
@@ -543,7 +1009,6 @@ describe('ClientFeatureToggleDelta bootstrap behavior', () => {
|
|
|
543
1009
|
if (toggleNames.length === 0) {
|
|
544
1010
|
return [feature];
|
|
545
1011
|
}
|
|
546
|
-
// @ts-expect-error - toggle name not defined
|
|
547
1012
|
return toggleNames.includes('first') ? [feature] : [];
|
|
548
1013
|
},
|
|
549
1014
|
}, {
|
|
@@ -551,7 +1016,8 @@ describe('ClientFeatureToggleDelta bootstrap behavior', () => {
|
|
|
551
1016
|
}, {
|
|
552
1017
|
getDeltaRevisionState: async () => ({
|
|
553
1018
|
projectRevisions: new Map([['default', 1]]),
|
|
554
|
-
|
|
1019
|
+
maxReferencedSegmentRevision: 0,
|
|
1020
|
+
segmentRevisions: new Map(),
|
|
555
1021
|
}),
|
|
556
1022
|
getRevisionRange: async () => [
|
|
557
1023
|
{
|
|
@@ -619,5 +1085,85 @@ describe('ClientFeatureToggleDelta bootstrap behavior', () => {
|
|
|
619
1085
|
],
|
|
620
1086
|
});
|
|
621
1087
|
});
|
|
1088
|
+
test('returns delta events in revision order even when cached by event type', async () => {
|
|
1089
|
+
let currentRevisionId = 24;
|
|
1090
|
+
const delta = new ClientFeatureToggleDelta({
|
|
1091
|
+
getAll: async ({ toggleNames = [], }) => {
|
|
1092
|
+
const feature = {
|
|
1093
|
+
name: 'first',
|
|
1094
|
+
project: 'default',
|
|
1095
|
+
enabled: false,
|
|
1096
|
+
strategies: currentRevisionId >= 26
|
|
1097
|
+
? [{ name: 'default', segments: [101] }]
|
|
1098
|
+
: [],
|
|
1099
|
+
};
|
|
1100
|
+
if (toggleNames.length === 0) {
|
|
1101
|
+
return [feature];
|
|
1102
|
+
}
|
|
1103
|
+
return toggleNames.includes('first') ? [feature] : [];
|
|
1104
|
+
},
|
|
1105
|
+
}, {
|
|
1106
|
+
getAllForClientIds: async (ids) => ids === undefined || ids.includes(101)
|
|
1107
|
+
? [{ id: 101, name: 'segment-a', constraints: [] }]
|
|
1108
|
+
: [],
|
|
1109
|
+
}, {
|
|
1110
|
+
getDeltaRevisionState: async () => ({
|
|
1111
|
+
projectRevisions: new Map([['default', 24]]),
|
|
1112
|
+
maxReferencedSegmentRevision: 0,
|
|
1113
|
+
segmentRevisions: new Map(),
|
|
1114
|
+
}),
|
|
1115
|
+
getRevisionRange: async () => [
|
|
1116
|
+
{
|
|
1117
|
+
id: 25,
|
|
1118
|
+
type: 'segment-created',
|
|
1119
|
+
data: { id: 101, name: 'segment-a' },
|
|
1120
|
+
createdAt: new Date(),
|
|
1121
|
+
},
|
|
1122
|
+
{
|
|
1123
|
+
id: 26,
|
|
1124
|
+
type: 'feature-updated',
|
|
1125
|
+
featureName: 'first',
|
|
1126
|
+
project: 'default',
|
|
1127
|
+
environment: 'development',
|
|
1128
|
+
createdAt: new Date(),
|
|
1129
|
+
},
|
|
1130
|
+
],
|
|
1131
|
+
getMaxRevisionId: async () => currentRevisionId,
|
|
1132
|
+
}, {
|
|
1133
|
+
on: () => undefined,
|
|
1134
|
+
}, {
|
|
1135
|
+
isEnabled: (name) => name === 'deltaApi',
|
|
1136
|
+
}, createDeltaConfig());
|
|
1137
|
+
await delta.getDelta(undefined, {
|
|
1138
|
+
environment: 'development',
|
|
1139
|
+
project: ['default'],
|
|
1140
|
+
});
|
|
1141
|
+
currentRevisionId = 26;
|
|
1142
|
+
await delta.onUpdateRevisionEvent();
|
|
1143
|
+
const result = await delta.getDelta(24, {
|
|
1144
|
+
environment: 'development',
|
|
1145
|
+
project: ['default'],
|
|
1146
|
+
});
|
|
1147
|
+
expect(result?.events.map((event) => event.eventId)).toEqual([25, 26]);
|
|
1148
|
+
expect(result).toEqual({
|
|
1149
|
+
events: [
|
|
1150
|
+
{
|
|
1151
|
+
eventId: 25,
|
|
1152
|
+
type: 'segment-updated',
|
|
1153
|
+
segment: { id: 101, name: 'segment-a', constraints: [] },
|
|
1154
|
+
},
|
|
1155
|
+
{
|
|
1156
|
+
eventId: 26,
|
|
1157
|
+
type: 'feature-updated',
|
|
1158
|
+
feature: {
|
|
1159
|
+
name: 'first',
|
|
1160
|
+
project: 'default',
|
|
1161
|
+
enabled: false,
|
|
1162
|
+
strategies: [{ name: 'default', segments: [101] }],
|
|
1163
|
+
},
|
|
1164
|
+
},
|
|
1165
|
+
],
|
|
1166
|
+
});
|
|
1167
|
+
});
|
|
622
1168
|
});
|
|
623
1169
|
//# sourceMappingURL=client-feature-toggle-delta.test.js.map
|