@lssm/lib.feature-flags 0.0.0-canary-20251206160926
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 +159 -0
- package/dist/contracts/dist/capabilities/openbanking.js +1 -0
- package/dist/contracts/dist/client/index.js +1 -0
- package/dist/contracts/dist/client/react/feature-render.js +1 -0
- package/dist/contracts/dist/client/react/form-render.js +1 -0
- package/dist/contracts/dist/client/react/index.js +1 -0
- package/dist/contracts/dist/events.js +1 -0
- package/dist/contracts/dist/experiments/evaluator.js +1 -0
- package/dist/contracts/dist/graphql-federation/dist/index.js +1 -0
- package/dist/contracts/dist/index.js +1 -0
- package/dist/contracts/dist/install.js +1 -0
- package/dist/contracts/dist/integrations/contracts.js +1 -0
- package/dist/contracts/dist/integrations/index.js +1 -0
- package/dist/contracts/dist/integrations/openbanking/contracts/accounts.js +1 -0
- package/dist/contracts/dist/integrations/openbanking/contracts/balances.js +1 -0
- package/dist/contracts/dist/integrations/openbanking/contracts/index.js +1 -0
- package/dist/contracts/dist/integrations/openbanking/contracts/transactions.js +1 -0
- package/dist/contracts/dist/integrations/openbanking/models.js +1 -0
- package/dist/contracts/dist/integrations/openbanking/telemetry.js +1 -0
- package/dist/contracts/dist/integrations/providers/elevenlabs.js +1 -0
- package/dist/contracts/dist/integrations/providers/gcs-storage.js +1 -0
- package/dist/contracts/dist/integrations/providers/gmail.js +1 -0
- package/dist/contracts/dist/integrations/providers/google-calendar.js +1 -0
- package/dist/contracts/dist/integrations/providers/impls/elevenlabs-voice.js +1 -0
- package/dist/contracts/dist/integrations/providers/impls/gcs-storage.js +1 -0
- package/dist/contracts/dist/integrations/providers/impls/gmail-inbound.js +1 -0
- package/dist/contracts/dist/integrations/providers/impls/gmail-outbound.js +1 -0
- package/dist/contracts/dist/integrations/providers/impls/google-calendar.js +1 -0
- package/dist/contracts/dist/integrations/providers/impls/index.js +1 -0
- package/dist/contracts/dist/integrations/providers/impls/mistral-embedding.js +1 -0
- package/dist/contracts/dist/integrations/providers/impls/mistral-llm.js +1 -0
- package/dist/contracts/dist/integrations/providers/impls/postmark-email.js +1 -0
- package/dist/contracts/dist/integrations/providers/impls/powens-client.js +1 -0
- package/dist/contracts/dist/integrations/providers/impls/powens-openbanking.js +1 -0
- package/dist/contracts/dist/integrations/providers/impls/provider-factory.js +1 -0
- package/dist/contracts/dist/integrations/providers/impls/qdrant-vector.js +1 -0
- package/dist/contracts/dist/integrations/providers/impls/stripe-payments.js +1 -0
- package/dist/contracts/dist/integrations/providers/impls/twilio-sms.js +1 -0
- package/dist/contracts/dist/integrations/providers/index.js +1 -0
- package/dist/contracts/dist/integrations/providers/mistral.js +1 -0
- package/dist/contracts/dist/integrations/providers/postmark.js +1 -0
- package/dist/contracts/dist/integrations/providers/powens.js +1 -0
- package/dist/contracts/dist/integrations/providers/qdrant.js +1 -0
- package/dist/contracts/dist/integrations/providers/stripe.js +1 -0
- package/dist/contracts/dist/integrations/providers/twilio-sms.js +1 -0
- package/dist/contracts/dist/integrations/runtime.js +1 -0
- package/dist/contracts/dist/integrations/secrets/env-secret-provider.js +1 -0
- package/dist/contracts/dist/integrations/secrets/gcp-secret-manager.js +1 -0
- package/dist/contracts/dist/integrations/secrets/index.js +1 -0
- package/dist/contracts/dist/integrations/secrets/manager.js +1 -0
- package/dist/contracts/dist/integrations/secrets/provider.js +1 -0
- package/dist/contracts/dist/jsonschema.js +1 -0
- package/dist/contracts/dist/knowledge/contracts.js +1 -0
- package/dist/contracts/dist/knowledge/index.js +1 -0
- package/dist/contracts/dist/knowledge/spaces/email-threads.js +1 -0
- package/dist/contracts/dist/knowledge/spaces/financial-docs.js +1 -0
- package/dist/contracts/dist/knowledge/spaces/financial-overview.js +1 -0
- package/dist/contracts/dist/knowledge/spaces/index.js +1 -0
- package/dist/contracts/dist/knowledge/spaces/product-canon.js +1 -0
- package/dist/contracts/dist/knowledge/spaces/support-faq.js +1 -0
- package/dist/contracts/dist/knowledge/spaces/uploaded-docs.js +1 -0
- package/dist/contracts/dist/onboarding-base.js +1 -0
- package/dist/contracts/dist/ownership.js +1 -0
- package/dist/contracts/dist/presentations.js +1 -0
- package/dist/contracts/dist/presentations.v2.js +1 -0
- package/dist/contracts/dist/prompt.js +1 -0
- package/dist/contracts/dist/promptRegistry.js +1 -0
- package/dist/contracts/dist/regenerator/index.js +1 -0
- package/dist/contracts/dist/regenerator/service.js +1 -0
- package/dist/contracts/dist/registry.js +1 -0
- package/dist/contracts/dist/resources.js +1 -0
- package/dist/contracts/dist/schema/dist/EnumType.js +1 -0
- package/dist/contracts/dist/schema/dist/FieldType.js +1 -0
- package/dist/contracts/dist/schema/dist/ScalarTypeEnum.js +1 -0
- package/dist/contracts/dist/schema/dist/SchemaModel.js +1 -0
- package/dist/contracts/dist/schema/dist/entity/defineEntity.js +1 -0
- package/dist/contracts/dist/schema/dist/entity/index.js +1 -0
- package/dist/contracts/dist/schema/dist/entity/types.js +1 -0
- package/dist/contracts/dist/schema/dist/index.js +1 -0
- package/dist/contracts/dist/server/graphql-pothos.js +1 -0
- package/dist/contracts/dist/server/graphql-schema-export.js +1 -0
- package/dist/contracts/dist/server/index.js +1 -0
- package/dist/contracts/dist/server/provider-mcp.js +1 -0
- package/dist/contracts/dist/server/rest-elysia.js +1 -0
- package/dist/contracts/dist/server/rest-express.js +1 -0
- package/dist/contracts/dist/server/rest-generic.js +1 -0
- package/dist/contracts/dist/server/rest-next-app.js +1 -0
- package/dist/contracts/dist/server/rest-next-pages.js +1 -0
- package/dist/contracts/dist/spec.js +1 -0
- package/dist/contracts/dist/telemetry/index.js +1 -0
- package/dist/contracts/dist/telemetry/tracker.js +1 -0
- package/dist/contracts/dist/tests/index.js +1 -0
- package/dist/contracts/dist/tests/runner.js +1 -0
- package/dist/contracts/dist/workflow/index.js +1 -0
- package/dist/contracts/dist/workflow/runner.js +1 -0
- package/dist/contracts/index.d.ts +1006 -0
- package/dist/contracts/index.js +1 -0
- package/dist/entities/index.d.ts +200 -0
- package/dist/entities/index.js +1 -0
- package/dist/evaluation/index.d.ts +162 -0
- package/dist/evaluation/index.js +1 -0
- package/dist/events.d.ts +624 -0
- package/dist/events.js +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +1 -0
- package/dist/schema/dist/EnumType.js +1 -0
- package/dist/schema/dist/FieldType.js +1 -0
- package/dist/schema/dist/ScalarTypeEnum.js +1 -0
- package/dist/schema/dist/SchemaModel.js +1 -0
- package/dist/schema/dist/entity/defineEntity.js +1 -0
- package/dist/schema/dist/entity/index.js +1 -0
- package/dist/schema/dist/entity/types.js +1 -0
- package/dist/schema/dist/index.js +1 -0
- package/package.json +45 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{l as e}from"../schema/dist/ScalarTypeEnum.js";import{n as t}from"../schema/dist/SchemaModel.js";import"../schema/dist/index.js";import{n,t as r}from"./dist/spec.js";import"./dist/index.js";const i=[`platform.feature-flags`],a=t({name:`FeatureFlag`,description:`Represents a feature flag`,fields:{id:{type:e.String_unsecure(),isOptional:!1},key:{type:e.String_unsecure(),isOptional:!1},name:{type:e.String_unsecure(),isOptional:!1},description:{type:e.String_unsecure(),isOptional:!0},status:{type:e.String_unsecure(),isOptional:!1},defaultValue:{type:e.Boolean(),isOptional:!1},variants:{type:e.JSON(),isOptional:!0},orgId:{type:e.String_unsecure(),isOptional:!0},tags:{type:e.JSON(),isOptional:!0},createdAt:{type:e.DateTime(),isOptional:!1},updatedAt:{type:e.DateTime(),isOptional:!1}}}),o=t({name:`TargetingRule`,description:`Represents a targeting rule`,fields:{id:{type:e.String_unsecure(),isOptional:!1},flagId:{type:e.String_unsecure(),isOptional:!1},name:{type:e.String_unsecure(),isOptional:!0},priority:{type:e.Int_unsecure(),isOptional:!1},enabled:{type:e.Boolean(),isOptional:!1},attribute:{type:e.String_unsecure(),isOptional:!1},operator:{type:e.String_unsecure(),isOptional:!1},value:{type:e.JSON(),isOptional:!1},rolloutPercentage:{type:e.Int_unsecure(),isOptional:!0},serveValue:{type:e.Boolean(),isOptional:!0},serveVariant:{type:e.String_unsecure(),isOptional:!0}}}),s=t({name:`Experiment`,description:`Represents an experiment`,fields:{id:{type:e.String_unsecure(),isOptional:!1},key:{type:e.String_unsecure(),isOptional:!1},name:{type:e.String_unsecure(),isOptional:!1},description:{type:e.String_unsecure(),isOptional:!0},hypothesis:{type:e.String_unsecure(),isOptional:!0},flagId:{type:e.String_unsecure(),isOptional:!1},status:{type:e.String_unsecure(),isOptional:!1},variants:{type:e.JSON(),isOptional:!1},metrics:{type:e.JSON(),isOptional:!0},audiencePercentage:{type:e.Int_unsecure(),isOptional:!1},startedAt:{type:e.DateTime(),isOptional:!0},endedAt:{type:e.DateTime(),isOptional:!0},winningVariant:{type:e.String_unsecure(),isOptional:!0},results:{type:e.JSON(),isOptional:!0},createdAt:{type:e.DateTime(),isOptional:!1}}}),c=t({name:`EvaluationResult`,description:`Result of flag evaluation`,fields:{enabled:{type:e.Boolean(),isOptional:!1},variant:{type:e.String_unsecure(),isOptional:!0},reason:{type:e.String_unsecure(),isOptional:!1},ruleId:{type:e.String_unsecure(),isOptional:!0},experimentId:{type:e.String_unsecure(),isOptional:!0}}}),l=t({name:`CreateFlagInput`,description:`Input for creating a feature flag`,fields:{key:{type:e.String_unsecure(),isOptional:!1},name:{type:e.String_unsecure(),isOptional:!1},description:{type:e.String_unsecure(),isOptional:!0},defaultValue:{type:e.Boolean(),isOptional:!0},variants:{type:e.JSON(),isOptional:!0},orgId:{type:e.String_unsecure(),isOptional:!0},tags:{type:e.JSON(),isOptional:!0}}}),u=t({name:`UpdateFlagInput`,description:`Input for updating a feature flag`,fields:{flagId:{type:e.String_unsecure(),isOptional:!1},name:{type:e.String_unsecure(),isOptional:!0},description:{type:e.String_unsecure(),isOptional:!0},defaultValue:{type:e.Boolean(),isOptional:!0},variants:{type:e.JSON(),isOptional:!0},tags:{type:e.JSON(),isOptional:!0}}}),d=t({name:`DeleteFlagInput`,description:`Input for deleting a feature flag`,fields:{flagId:{type:e.String_unsecure(),isOptional:!1}}}),f=t({name:`ToggleFlagInput`,description:`Input for toggling a feature flag`,fields:{flagId:{type:e.String_unsecure(),isOptional:!1},status:{type:e.String_unsecure(),isOptional:!1}}}),p=t({name:`GetFlagInput`,description:`Input for getting a feature flag`,fields:{key:{type:e.String_unsecure(),isOptional:!1},orgId:{type:e.String_unsecure(),isOptional:!0}}}),m=t({name:`ListFlagsInput`,description:`Input for listing feature flags`,fields:{orgId:{type:e.String_unsecure(),isOptional:!0},status:{type:e.String_unsecure(),isOptional:!0},tags:{type:e.JSON(),isOptional:!0},limit:{type:e.Int_unsecure(),isOptional:!0},offset:{type:e.Int_unsecure(),isOptional:!0}}}),h=t({name:`ListFlagsOutput`,description:`Output for listing feature flags`,fields:{flags:{type:a,isArray:!0,isOptional:!1},total:{type:e.Int_unsecure(),isOptional:!1}}}),g=t({name:`EvaluateFlagInput`,description:`Input for evaluating a feature flag`,fields:{key:{type:e.String_unsecure(),isOptional:!1},context:{type:e.JSON(),isOptional:!1}}}),_=t({name:`CreateRuleInput`,description:`Input for creating a targeting rule`,fields:{flagId:{type:e.String_unsecure(),isOptional:!1},name:{type:e.String_unsecure(),isOptional:!0},priority:{type:e.Int_unsecure(),isOptional:!0},attribute:{type:e.String_unsecure(),isOptional:!1},operator:{type:e.String_unsecure(),isOptional:!1},value:{type:e.JSON(),isOptional:!1},rolloutPercentage:{type:e.Int_unsecure(),isOptional:!0},serveValue:{type:e.Boolean(),isOptional:!0},serveVariant:{type:e.String_unsecure(),isOptional:!0}}}),v=t({name:`DeleteRuleInput`,description:`Input for deleting a targeting rule`,fields:{ruleId:{type:e.String_unsecure(),isOptional:!1}}}),y=t({name:`CreateExperimentInput`,description:`Input for creating an experiment`,fields:{key:{type:e.String_unsecure(),isOptional:!1},name:{type:e.String_unsecure(),isOptional:!1},description:{type:e.String_unsecure(),isOptional:!0},hypothesis:{type:e.String_unsecure(),isOptional:!0},flagId:{type:e.String_unsecure(),isOptional:!1},variants:{type:e.JSON(),isOptional:!1},metrics:{type:e.JSON(),isOptional:!0},audiencePercentage:{type:e.Int_unsecure(),isOptional:!0},scheduledStartAt:{type:e.DateTime(),isOptional:!0},scheduledEndAt:{type:e.DateTime(),isOptional:!0},orgId:{type:e.String_unsecure(),isOptional:!0}}}),b=t({name:`StartExperimentInput`,description:`Input for starting an experiment`,fields:{experimentId:{type:e.String_unsecure(),isOptional:!1}}}),x=t({name:`StopExperimentInput`,description:`Input for stopping an experiment`,fields:{experimentId:{type:e.String_unsecure(),isOptional:!1},reason:{type:e.String_unsecure(),isOptional:!1},winningVariant:{type:e.String_unsecure(),isOptional:!0}}}),S=t({name:`GetExperimentInput`,description:`Input for getting an experiment`,fields:{experimentId:{type:e.String_unsecure(),isOptional:!1}}}),C=t({name:`SuccessOutput`,description:`Generic success output`,fields:{success:{type:e.Boolean(),isOptional:!1}}}),w=r({meta:{name:`flag.create`,version:1,stability:`stable`,owners:[...i],tags:[`feature-flags`,`create`],description:`Create a new feature flag.`,goal:`Define a new feature flag for toggling features.`,context:`Called when setting up a new feature flag.`},io:{input:l,output:a,errors:{KEY_ALREADY_EXISTS:{description:`Flag key already exists`,http:409,gqlCode:`FLAG_KEY_EXISTS`,when:`A flag with this key already exists`}}},policy:{auth:`admin`}}),T=r({meta:{name:`flag.update`,version:1,stability:`stable`,owners:[...i],tags:[`feature-flags`,`update`],description:`Update an existing feature flag.`,goal:`Modify flag configuration.`,context:`Called when adjusting flag settings.`},io:{input:u,output:a,errors:{FLAG_NOT_FOUND:{description:`Flag does not exist`,http:404,gqlCode:`FLAG_NOT_FOUND`,when:`Flag ID is invalid`}}},policy:{auth:`admin`}}),E=r({meta:{name:`flag.delete`,version:1,stability:`stable`,owners:[...i],tags:[`feature-flags`,`delete`],description:`Delete a feature flag.`,goal:`Remove a feature flag and all its rules.`,context:`Called when a flag is no longer needed.`},io:{input:d,output:C,errors:{FLAG_NOT_FOUND:{description:`Flag does not exist`,http:404,gqlCode:`FLAG_NOT_FOUND`,when:`Flag ID is invalid`},FLAG_HAS_ACTIVE_EXPERIMENT:{description:`Flag has an active experiment`,http:409,gqlCode:`FLAG_HAS_ACTIVE_EXPERIMENT`,when:`Cannot delete flag with running experiment`}}},policy:{auth:`admin`}}),D=r({meta:{name:`flag.toggle`,version:1,stability:`stable`,owners:[...i],tags:[`feature-flags`,`toggle`],description:`Toggle a feature flag status.`,goal:`Quickly enable or disable a feature.`,context:`Called when turning a feature on or off.`},io:{input:f,output:a,errors:{FLAG_NOT_FOUND:{description:`Flag does not exist`,http:404,gqlCode:`FLAG_NOT_FOUND`,when:`Flag ID is invalid`},INVALID_STATUS:{description:`Invalid status value`,http:400,gqlCode:`INVALID_STATUS`,when:`Status must be OFF, ON, or GRADUAL`}}},policy:{auth:`admin`}}),O=n({meta:{name:`flag.get`,version:1,stability:`stable`,owners:[...i],tags:[`feature-flags`,`get`],description:`Get a feature flag by key.`,goal:`Retrieve flag configuration.`,context:`Called to inspect flag details.`},io:{input:p,output:a,errors:{FLAG_NOT_FOUND:{description:`Flag does not exist`,http:404,gqlCode:`FLAG_NOT_FOUND`,when:`Flag key is invalid`}}},policy:{auth:`user`}}),k=n({meta:{name:`flag.list`,version:1,stability:`stable`,owners:[...i],tags:[`feature-flags`,`list`],description:`List all feature flags.`,goal:`View all configured flags.`,context:`Admin dashboard.`},io:{input:m,output:h},policy:{auth:`admin`}}),A=n({meta:{name:`flag.evaluate`,version:1,stability:`stable`,owners:[...i],tags:[`feature-flags`,`evaluate`],description:`Evaluate a feature flag for a given context.`,goal:`Determine if a feature should be enabled.`,context:`Called at runtime to check feature availability.`},io:{input:g,output:c,errors:{FLAG_NOT_FOUND:{description:`Flag does not exist`,http:404,gqlCode:`FLAG_NOT_FOUND`,when:`Flag key is invalid`}}},policy:{auth:`anonymous`}}),j=r({meta:{name:`flag.rule.create`,version:1,stability:`stable`,owners:[...i],tags:[`feature-flags`,`rule`,`create`],description:`Create a targeting rule for a flag.`,goal:`Add conditional targeting to a flag.`,context:`Called when setting up targeting.`},io:{input:_,output:o,errors:{FLAG_NOT_FOUND:{description:`Flag does not exist`,http:404,gqlCode:`FLAG_NOT_FOUND`,when:`Flag ID is invalid`},INVALID_OPERATOR:{description:`Invalid operator`,http:400,gqlCode:`INVALID_OPERATOR`,when:`Operator is not supported`}}},policy:{auth:`admin`}}),M=r({meta:{name:`flag.rule.delete`,version:1,stability:`stable`,owners:[...i],tags:[`feature-flags`,`rule`,`delete`],description:`Delete a targeting rule.`,goal:`Remove a targeting rule from a flag.`,context:`Called when removing targeting conditions.`},io:{input:v,output:C,errors:{RULE_NOT_FOUND:{description:`Rule does not exist`,http:404,gqlCode:`RULE_NOT_FOUND`,when:`Rule ID is invalid`}}},policy:{auth:`admin`}}),N=r({meta:{name:`experiment.create`,version:1,stability:`stable`,owners:[...i],tags:[`feature-flags`,`experiment`,`create`],description:`Create an A/B test experiment.`,goal:`Set up an experiment with variants.`,context:`Called when setting up A/B testing.`},io:{input:y,output:s,errors:{FLAG_NOT_FOUND:{description:`Flag does not exist`,http:404,gqlCode:`FLAG_NOT_FOUND`,when:`Flag ID is invalid`},EXPERIMENT_KEY_EXISTS:{description:`Experiment key already exists`,http:409,gqlCode:`EXPERIMENT_KEY_EXISTS`,when:`An experiment with this key already exists`},INVALID_VARIANTS:{description:`Invalid variant configuration`,http:400,gqlCode:`INVALID_VARIANTS`,when:`Variant percentages must sum to 100`}}},policy:{auth:`admin`}}),P=r({meta:{name:`experiment.start`,version:1,stability:`stable`,owners:[...i],tags:[`feature-flags`,`experiment`,`start`],description:`Start an experiment.`,goal:`Begin collecting data for an experiment.`,context:`Called when ready to run an A/B test.`},io:{input:b,output:s,errors:{EXPERIMENT_NOT_FOUND:{description:`Experiment does not exist`,http:404,gqlCode:`EXPERIMENT_NOT_FOUND`,when:`Experiment ID is invalid`},EXPERIMENT_ALREADY_RUNNING:{description:`Experiment is already running`,http:409,gqlCode:`EXPERIMENT_ALREADY_RUNNING`,when:`Cannot start an experiment that is already running`}}},policy:{auth:`admin`}}),F=r({meta:{name:`experiment.stop`,version:1,stability:`stable`,owners:[...i],tags:[`feature-flags`,`experiment`,`stop`],description:`Stop an experiment.`,goal:`End an experiment and optionally declare a winner.`,context:`Called when concluding an A/B test.`},io:{input:x,output:s,errors:{EXPERIMENT_NOT_FOUND:{description:`Experiment does not exist`,http:404,gqlCode:`EXPERIMENT_NOT_FOUND`,when:`Experiment ID is invalid`},EXPERIMENT_NOT_RUNNING:{description:`Experiment is not running`,http:409,gqlCode:`EXPERIMENT_NOT_RUNNING`,when:`Cannot stop an experiment that is not running`}}},policy:{auth:`admin`}}),I=n({meta:{name:`experiment.get`,version:1,stability:`stable`,owners:[...i],tags:[`feature-flags`,`experiment`,`get`],description:`Get experiment details.`,goal:`View experiment configuration and results.`,context:`Called to inspect experiment status.`},io:{input:S,output:s,errors:{EXPERIMENT_NOT_FOUND:{description:`Experiment does not exist`,http:404,gqlCode:`EXPERIMENT_NOT_FOUND`,when:`Experiment ID is invalid`}}},policy:{auth:`user`}});export{N as CreateExperimentContract,w as CreateFlagContract,j as CreateRuleContract,E as DeleteFlagContract,M as DeleteRuleContract,A as EvaluateFlagContract,c as EvaluationResultModel,s as ExperimentModel,a as FeatureFlagModel,I as GetExperimentContract,O as GetFlagContract,k as ListFlagsContract,P as StartExperimentContract,F as StopExperimentContract,o as TargetingRuleModel,D as ToggleFlagContract,T as UpdateFlagContract};
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import * as _lssm_lib_schema155 from "@lssm/lib.schema";
|
|
2
|
+
import { ModuleSchemaContribution } from "@lssm/lib.schema";
|
|
3
|
+
|
|
4
|
+
//#region src/entities/index.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* Feature flag status enum.
|
|
7
|
+
*/
|
|
8
|
+
declare const FlagStatusEnum: _lssm_lib_schema155.EntityEnumDef;
|
|
9
|
+
/**
|
|
10
|
+
* Targeting rule operator enum.
|
|
11
|
+
*/
|
|
12
|
+
declare const RuleOperatorEnum: _lssm_lib_schema155.EntityEnumDef;
|
|
13
|
+
/**
|
|
14
|
+
* Experiment status enum.
|
|
15
|
+
*/
|
|
16
|
+
declare const ExperimentStatusEnum: _lssm_lib_schema155.EntityEnumDef;
|
|
17
|
+
/**
|
|
18
|
+
* FeatureFlag entity - defines a feature flag.
|
|
19
|
+
*/
|
|
20
|
+
declare const FeatureFlagEntity: _lssm_lib_schema155.EntitySpec<{
|
|
21
|
+
id: _lssm_lib_schema155.EntityScalarField;
|
|
22
|
+
key: _lssm_lib_schema155.EntityScalarField;
|
|
23
|
+
name: _lssm_lib_schema155.EntityScalarField;
|
|
24
|
+
description: _lssm_lib_schema155.EntityScalarField;
|
|
25
|
+
status: _lssm_lib_schema155.EntityEnumField;
|
|
26
|
+
defaultValue: _lssm_lib_schema155.EntityScalarField;
|
|
27
|
+
variants: _lssm_lib_schema155.EntityScalarField;
|
|
28
|
+
orgId: _lssm_lib_schema155.EntityScalarField;
|
|
29
|
+
tags: _lssm_lib_schema155.EntityScalarField;
|
|
30
|
+
metadata: _lssm_lib_schema155.EntityScalarField;
|
|
31
|
+
createdAt: _lssm_lib_schema155.EntityScalarField;
|
|
32
|
+
updatedAt: _lssm_lib_schema155.EntityScalarField;
|
|
33
|
+
targetingRules: _lssm_lib_schema155.EntityRelationField;
|
|
34
|
+
experiments: _lssm_lib_schema155.EntityRelationField;
|
|
35
|
+
evaluations: _lssm_lib_schema155.EntityRelationField;
|
|
36
|
+
}>;
|
|
37
|
+
/**
|
|
38
|
+
* FlagTargetingRule entity - conditions for targeting.
|
|
39
|
+
*/
|
|
40
|
+
declare const FlagTargetingRuleEntity: _lssm_lib_schema155.EntitySpec<{
|
|
41
|
+
id: _lssm_lib_schema155.EntityScalarField;
|
|
42
|
+
flagId: _lssm_lib_schema155.EntityScalarField;
|
|
43
|
+
name: _lssm_lib_schema155.EntityScalarField;
|
|
44
|
+
priority: _lssm_lib_schema155.EntityScalarField;
|
|
45
|
+
enabled: _lssm_lib_schema155.EntityScalarField;
|
|
46
|
+
attribute: _lssm_lib_schema155.EntityScalarField;
|
|
47
|
+
operator: _lssm_lib_schema155.EntityEnumField;
|
|
48
|
+
value: _lssm_lib_schema155.EntityScalarField;
|
|
49
|
+
rolloutPercentage: _lssm_lib_schema155.EntityScalarField;
|
|
50
|
+
serveValue: _lssm_lib_schema155.EntityScalarField;
|
|
51
|
+
serveVariant: _lssm_lib_schema155.EntityScalarField;
|
|
52
|
+
createdAt: _lssm_lib_schema155.EntityScalarField;
|
|
53
|
+
updatedAt: _lssm_lib_schema155.EntityScalarField;
|
|
54
|
+
flag: _lssm_lib_schema155.EntityRelationField;
|
|
55
|
+
}>;
|
|
56
|
+
/**
|
|
57
|
+
* Experiment entity - A/B test configuration.
|
|
58
|
+
*/
|
|
59
|
+
declare const ExperimentEntity: _lssm_lib_schema155.EntitySpec<{
|
|
60
|
+
id: _lssm_lib_schema155.EntityScalarField;
|
|
61
|
+
key: _lssm_lib_schema155.EntityScalarField;
|
|
62
|
+
name: _lssm_lib_schema155.EntityScalarField;
|
|
63
|
+
description: _lssm_lib_schema155.EntityScalarField;
|
|
64
|
+
hypothesis: _lssm_lib_schema155.EntityScalarField;
|
|
65
|
+
flagId: _lssm_lib_schema155.EntityScalarField;
|
|
66
|
+
status: _lssm_lib_schema155.EntityEnumField;
|
|
67
|
+
variants: _lssm_lib_schema155.EntityScalarField;
|
|
68
|
+
metrics: _lssm_lib_schema155.EntityScalarField;
|
|
69
|
+
audiencePercentage: _lssm_lib_schema155.EntityScalarField;
|
|
70
|
+
audienceFilter: _lssm_lib_schema155.EntityScalarField;
|
|
71
|
+
scheduledStartAt: _lssm_lib_schema155.EntityScalarField;
|
|
72
|
+
scheduledEndAt: _lssm_lib_schema155.EntityScalarField;
|
|
73
|
+
startedAt: _lssm_lib_schema155.EntityScalarField;
|
|
74
|
+
endedAt: _lssm_lib_schema155.EntityScalarField;
|
|
75
|
+
winningVariant: _lssm_lib_schema155.EntityScalarField;
|
|
76
|
+
results: _lssm_lib_schema155.EntityScalarField;
|
|
77
|
+
orgId: _lssm_lib_schema155.EntityScalarField;
|
|
78
|
+
createdAt: _lssm_lib_schema155.EntityScalarField;
|
|
79
|
+
updatedAt: _lssm_lib_schema155.EntityScalarField;
|
|
80
|
+
flag: _lssm_lib_schema155.EntityRelationField;
|
|
81
|
+
assignments: _lssm_lib_schema155.EntityRelationField;
|
|
82
|
+
}>;
|
|
83
|
+
/**
|
|
84
|
+
* ExperimentAssignment entity - tracks which variant a subject is assigned to.
|
|
85
|
+
*/
|
|
86
|
+
declare const ExperimentAssignmentEntity: _lssm_lib_schema155.EntitySpec<{
|
|
87
|
+
id: _lssm_lib_schema155.EntityScalarField;
|
|
88
|
+
experimentId: _lssm_lib_schema155.EntityScalarField;
|
|
89
|
+
subjectType: _lssm_lib_schema155.EntityScalarField;
|
|
90
|
+
subjectId: _lssm_lib_schema155.EntityScalarField;
|
|
91
|
+
variant: _lssm_lib_schema155.EntityScalarField;
|
|
92
|
+
bucket: _lssm_lib_schema155.EntityScalarField;
|
|
93
|
+
context: _lssm_lib_schema155.EntityScalarField;
|
|
94
|
+
assignedAt: _lssm_lib_schema155.EntityScalarField;
|
|
95
|
+
experiment: _lssm_lib_schema155.EntityRelationField;
|
|
96
|
+
}>;
|
|
97
|
+
/**
|
|
98
|
+
* FlagEvaluation entity - evaluation log for analytics.
|
|
99
|
+
*/
|
|
100
|
+
declare const FlagEvaluationEntity: _lssm_lib_schema155.EntitySpec<{
|
|
101
|
+
id: _lssm_lib_schema155.EntityScalarField;
|
|
102
|
+
flagId: _lssm_lib_schema155.EntityScalarField;
|
|
103
|
+
flagKey: _lssm_lib_schema155.EntityScalarField;
|
|
104
|
+
subjectType: _lssm_lib_schema155.EntityScalarField;
|
|
105
|
+
subjectId: _lssm_lib_schema155.EntityScalarField;
|
|
106
|
+
result: _lssm_lib_schema155.EntityScalarField;
|
|
107
|
+
variant: _lssm_lib_schema155.EntityScalarField;
|
|
108
|
+
matchedRuleId: _lssm_lib_schema155.EntityScalarField;
|
|
109
|
+
reason: _lssm_lib_schema155.EntityScalarField;
|
|
110
|
+
context: _lssm_lib_schema155.EntityScalarField;
|
|
111
|
+
evaluatedAt: _lssm_lib_schema155.EntityScalarField;
|
|
112
|
+
flag: _lssm_lib_schema155.EntityRelationField;
|
|
113
|
+
}>;
|
|
114
|
+
/**
|
|
115
|
+
* All feature flag entities for schema composition.
|
|
116
|
+
*/
|
|
117
|
+
declare const featureFlagEntities: (_lssm_lib_schema155.EntitySpec<{
|
|
118
|
+
id: _lssm_lib_schema155.EntityScalarField;
|
|
119
|
+
key: _lssm_lib_schema155.EntityScalarField;
|
|
120
|
+
name: _lssm_lib_schema155.EntityScalarField;
|
|
121
|
+
description: _lssm_lib_schema155.EntityScalarField;
|
|
122
|
+
status: _lssm_lib_schema155.EntityEnumField;
|
|
123
|
+
defaultValue: _lssm_lib_schema155.EntityScalarField;
|
|
124
|
+
variants: _lssm_lib_schema155.EntityScalarField;
|
|
125
|
+
orgId: _lssm_lib_schema155.EntityScalarField;
|
|
126
|
+
tags: _lssm_lib_schema155.EntityScalarField;
|
|
127
|
+
metadata: _lssm_lib_schema155.EntityScalarField;
|
|
128
|
+
createdAt: _lssm_lib_schema155.EntityScalarField;
|
|
129
|
+
updatedAt: _lssm_lib_schema155.EntityScalarField;
|
|
130
|
+
targetingRules: _lssm_lib_schema155.EntityRelationField;
|
|
131
|
+
experiments: _lssm_lib_schema155.EntityRelationField;
|
|
132
|
+
evaluations: _lssm_lib_schema155.EntityRelationField;
|
|
133
|
+
}> | _lssm_lib_schema155.EntitySpec<{
|
|
134
|
+
id: _lssm_lib_schema155.EntityScalarField;
|
|
135
|
+
flagId: _lssm_lib_schema155.EntityScalarField;
|
|
136
|
+
name: _lssm_lib_schema155.EntityScalarField;
|
|
137
|
+
priority: _lssm_lib_schema155.EntityScalarField;
|
|
138
|
+
enabled: _lssm_lib_schema155.EntityScalarField;
|
|
139
|
+
attribute: _lssm_lib_schema155.EntityScalarField;
|
|
140
|
+
operator: _lssm_lib_schema155.EntityEnumField;
|
|
141
|
+
value: _lssm_lib_schema155.EntityScalarField;
|
|
142
|
+
rolloutPercentage: _lssm_lib_schema155.EntityScalarField;
|
|
143
|
+
serveValue: _lssm_lib_schema155.EntityScalarField;
|
|
144
|
+
serveVariant: _lssm_lib_schema155.EntityScalarField;
|
|
145
|
+
createdAt: _lssm_lib_schema155.EntityScalarField;
|
|
146
|
+
updatedAt: _lssm_lib_schema155.EntityScalarField;
|
|
147
|
+
flag: _lssm_lib_schema155.EntityRelationField;
|
|
148
|
+
}> | _lssm_lib_schema155.EntitySpec<{
|
|
149
|
+
id: _lssm_lib_schema155.EntityScalarField;
|
|
150
|
+
key: _lssm_lib_schema155.EntityScalarField;
|
|
151
|
+
name: _lssm_lib_schema155.EntityScalarField;
|
|
152
|
+
description: _lssm_lib_schema155.EntityScalarField;
|
|
153
|
+
hypothesis: _lssm_lib_schema155.EntityScalarField;
|
|
154
|
+
flagId: _lssm_lib_schema155.EntityScalarField;
|
|
155
|
+
status: _lssm_lib_schema155.EntityEnumField;
|
|
156
|
+
variants: _lssm_lib_schema155.EntityScalarField;
|
|
157
|
+
metrics: _lssm_lib_schema155.EntityScalarField;
|
|
158
|
+
audiencePercentage: _lssm_lib_schema155.EntityScalarField;
|
|
159
|
+
audienceFilter: _lssm_lib_schema155.EntityScalarField;
|
|
160
|
+
scheduledStartAt: _lssm_lib_schema155.EntityScalarField;
|
|
161
|
+
scheduledEndAt: _lssm_lib_schema155.EntityScalarField;
|
|
162
|
+
startedAt: _lssm_lib_schema155.EntityScalarField;
|
|
163
|
+
endedAt: _lssm_lib_schema155.EntityScalarField;
|
|
164
|
+
winningVariant: _lssm_lib_schema155.EntityScalarField;
|
|
165
|
+
results: _lssm_lib_schema155.EntityScalarField;
|
|
166
|
+
orgId: _lssm_lib_schema155.EntityScalarField;
|
|
167
|
+
createdAt: _lssm_lib_schema155.EntityScalarField;
|
|
168
|
+
updatedAt: _lssm_lib_schema155.EntityScalarField;
|
|
169
|
+
flag: _lssm_lib_schema155.EntityRelationField;
|
|
170
|
+
assignments: _lssm_lib_schema155.EntityRelationField;
|
|
171
|
+
}> | _lssm_lib_schema155.EntitySpec<{
|
|
172
|
+
id: _lssm_lib_schema155.EntityScalarField;
|
|
173
|
+
experimentId: _lssm_lib_schema155.EntityScalarField;
|
|
174
|
+
subjectType: _lssm_lib_schema155.EntityScalarField;
|
|
175
|
+
subjectId: _lssm_lib_schema155.EntityScalarField;
|
|
176
|
+
variant: _lssm_lib_schema155.EntityScalarField;
|
|
177
|
+
bucket: _lssm_lib_schema155.EntityScalarField;
|
|
178
|
+
context: _lssm_lib_schema155.EntityScalarField;
|
|
179
|
+
assignedAt: _lssm_lib_schema155.EntityScalarField;
|
|
180
|
+
experiment: _lssm_lib_schema155.EntityRelationField;
|
|
181
|
+
}> | _lssm_lib_schema155.EntitySpec<{
|
|
182
|
+
id: _lssm_lib_schema155.EntityScalarField;
|
|
183
|
+
flagId: _lssm_lib_schema155.EntityScalarField;
|
|
184
|
+
flagKey: _lssm_lib_schema155.EntityScalarField;
|
|
185
|
+
subjectType: _lssm_lib_schema155.EntityScalarField;
|
|
186
|
+
subjectId: _lssm_lib_schema155.EntityScalarField;
|
|
187
|
+
result: _lssm_lib_schema155.EntityScalarField;
|
|
188
|
+
variant: _lssm_lib_schema155.EntityScalarField;
|
|
189
|
+
matchedRuleId: _lssm_lib_schema155.EntityScalarField;
|
|
190
|
+
reason: _lssm_lib_schema155.EntityScalarField;
|
|
191
|
+
context: _lssm_lib_schema155.EntityScalarField;
|
|
192
|
+
evaluatedAt: _lssm_lib_schema155.EntityScalarField;
|
|
193
|
+
flag: _lssm_lib_schema155.EntityRelationField;
|
|
194
|
+
}>)[];
|
|
195
|
+
/**
|
|
196
|
+
* Module schema contribution for feature flags.
|
|
197
|
+
*/
|
|
198
|
+
declare const featureFlagsSchemaContribution: ModuleSchemaContribution;
|
|
199
|
+
//#endregion
|
|
200
|
+
export { ExperimentAssignmentEntity, ExperimentEntity, ExperimentStatusEnum, FeatureFlagEntity, FlagEvaluationEntity, FlagStatusEnum, FlagTargetingRuleEntity, RuleOperatorEnum, featureFlagEntities, featureFlagsSchemaContribution };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{i as e,n as t,r as n,t as r}from"../schema/dist/entity/defineEntity.js";import"../schema/dist/index.js";const i=t({name:`FlagStatus`,values:[`OFF`,`ON`,`GRADUAL`],schema:`lssm_feature_flags`,description:`Status of a feature flag.`}),a=t({name:`RuleOperator`,values:[`EQ`,`NEQ`,`IN`,`NIN`,`CONTAINS`,`NOT_CONTAINS`,`GT`,`GTE`,`LT`,`LTE`,`PERCENTAGE`],schema:`lssm_feature_flags`,description:`Operator for targeting rule conditions.`}),o=t({name:`ExperimentStatus`,values:[`DRAFT`,`RUNNING`,`PAUSED`,`COMPLETED`,`CANCELLED`],schema:`lssm_feature_flags`,description:`Status of an experiment.`}),s=r({name:`FeatureFlag`,description:`A feature flag for controlling feature availability.`,schema:`lssm_feature_flags`,map:`feature_flag`,fields:{id:n.id({description:`Unique flag identifier`}),key:n.string({isUnique:!0,description:`Flag key (e.g., new_dashboard)`}),name:n.string({description:`Human-readable name`}),description:n.string({isOptional:!0,description:`Description of the flag`}),status:n.enum(`FlagStatus`,{default:`OFF`,description:`Flag status`}),defaultValue:n.boolean({default:!1,description:`Default value when no rules match`}),variants:n.json({isOptional:!0,description:`Variant definitions for multivariate flags`}),orgId:n.string({isOptional:!0,description:`Organization scope (null = global)`}),tags:n.json({isOptional:!0,description:`Tags for categorization`}),metadata:n.json({isOptional:!0,description:`Additional metadata`}),createdAt:n.createdAt(),updatedAt:n.updatedAt(),targetingRules:n.hasMany(`FlagTargetingRule`),experiments:n.hasMany(`Experiment`),evaluations:n.hasMany(`FlagEvaluation`)},indexes:[e.on([`orgId`,`key`]),e.on([`status`])],enums:[i]}),c=r({name:`FlagTargetingRule`,description:`A targeting rule for conditional flag evaluation.`,schema:`lssm_feature_flags`,map:`flag_targeting_rule`,fields:{id:n.id({description:`Unique rule identifier`}),flagId:n.foreignKey({description:`Parent feature flag`}),name:n.string({isOptional:!0,description:`Rule name for debugging`}),priority:n.int({default:0,description:`Rule priority (lower = higher priority)`}),enabled:n.boolean({default:!0,description:`Whether rule is active`}),attribute:n.string({description:`Target attribute (userId, orgId, plan, segment, etc.)`}),operator:n.enum(`RuleOperator`,{description:`Comparison operator`}),value:n.json({description:`Target value(s)`}),rolloutPercentage:n.int({isOptional:!0,description:`Percentage for gradual rollout (0-100)`}),serveValue:n.boolean({isOptional:!0,description:`Boolean value to serve`}),serveVariant:n.string({isOptional:!0,description:`Variant key to serve (for multivariate)`}),createdAt:n.createdAt(),updatedAt:n.updatedAt(),flag:n.belongsTo(`FeatureFlag`,[`flagId`],[`id`],{onDelete:`Cascade`})},indexes:[e.on([`flagId`,`priority`]),e.on([`attribute`])],enums:[a]}),l=r({name:`Experiment`,description:`An A/B test experiment.`,schema:`lssm_feature_flags`,map:`experiment`,fields:{id:n.id({description:`Unique experiment identifier`}),key:n.string({isUnique:!0,description:`Experiment key`}),name:n.string({description:`Human-readable name`}),description:n.string({isOptional:!0,description:`Experiment description`}),hypothesis:n.string({isOptional:!0,description:`Experiment hypothesis`}),flagId:n.foreignKey({description:`Associated feature flag`}),status:n.enum(`ExperimentStatus`,{default:`DRAFT`,description:`Experiment status`}),variants:n.json({description:`Variant definitions with split ratios`}),metrics:n.json({isOptional:!0,description:`Metrics to track`}),audiencePercentage:n.int({default:100,description:`Percentage of audience to include`}),audienceFilter:n.json({isOptional:!0,description:`Audience filter criteria`}),scheduledStartAt:n.dateTime({isOptional:!0,description:`Scheduled start time`}),scheduledEndAt:n.dateTime({isOptional:!0,description:`Scheduled end time`}),startedAt:n.dateTime({isOptional:!0,description:`Actual start time`}),endedAt:n.dateTime({isOptional:!0,description:`Actual end time`}),winningVariant:n.string({isOptional:!0,description:`Declared winning variant`}),results:n.json({isOptional:!0,description:`Experiment results summary`}),orgId:n.string({isOptional:!0,description:`Organization scope`}),createdAt:n.createdAt(),updatedAt:n.updatedAt(),flag:n.belongsTo(`FeatureFlag`,[`flagId`],[`id`],{onDelete:`Cascade`}),assignments:n.hasMany(`ExperimentAssignment`)},indexes:[e.on([`status`]),e.on([`orgId`,`status`]),e.on([`flagId`])],enums:[o]}),u=r({name:`ExperimentAssignment`,description:`Tracks experiment variant assignments.`,schema:`lssm_feature_flags`,map:`experiment_assignment`,fields:{id:n.id({description:`Unique assignment identifier`}),experimentId:n.foreignKey({description:`Parent experiment`}),subjectType:n.string({description:`Subject type (user, org, session)`}),subjectId:n.string({description:`Subject identifier`}),variant:n.string({description:`Assigned variant key`}),bucket:n.int({description:`Hash bucket (0-99)`}),context:n.json({isOptional:!0,description:`Context at assignment time`}),assignedAt:n.dateTime({description:`Assignment timestamp`}),experiment:n.belongsTo(`Experiment`,[`experimentId`],[`id`],{onDelete:`Cascade`})},indexes:[e.unique([`experimentId`,`subjectType`,`subjectId`],{name:`experiment_assignment_unique`}),e.on([`subjectType`,`subjectId`])]}),d=r({name:`FlagEvaluation`,description:`Log of flag evaluations for debugging and analytics.`,schema:`lssm_feature_flags`,map:`flag_evaluation`,fields:{id:n.id({description:`Unique evaluation identifier`}),flagId:n.foreignKey({description:`Evaluated flag`}),flagKey:n.string({description:`Flag key (denormalized for queries)`}),subjectType:n.string({description:`Subject type (user, org, anonymous)`}),subjectId:n.string({description:`Subject identifier`}),result:n.boolean({description:`Evaluation result`}),variant:n.string({isOptional:!0,description:`Served variant (for multivariate)`}),matchedRuleId:n.string({isOptional:!0,description:`Rule that matched (if any)`}),reason:n.string({description:`Evaluation reason (default, rule, experiment, etc.)`}),context:n.json({isOptional:!0,description:`Evaluation context`}),evaluatedAt:n.dateTime({description:`Evaluation timestamp`}),flag:n.belongsTo(`FeatureFlag`,[`flagId`],[`id`],{onDelete:`Cascade`})},indexes:[e.on([`flagKey`,`evaluatedAt`]),e.on([`subjectType`,`subjectId`,`evaluatedAt`]),e.on([`flagId`,`evaluatedAt`])]}),f=[s,c,l,u,d],p={moduleId:`@lssm/lib.feature-flags`,entities:f,enums:[i,a,o]};export{u as ExperimentAssignmentEntity,l as ExperimentEntity,o as ExperimentStatusEnum,s as FeatureFlagEntity,d as FlagEvaluationEntity,i as FlagStatusEnum,c as FlagTargetingRuleEntity,a as RuleOperatorEnum,f as featureFlagEntities,p as featureFlagsSchemaContribution};
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
//#region src/evaluation/index.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Feature flag evaluation engine.
|
|
4
|
+
*
|
|
5
|
+
* Provides deterministic evaluation of feature flags based on targeting rules
|
|
6
|
+
* and experiment assignments.
|
|
7
|
+
*/
|
|
8
|
+
interface EvaluationContext {
|
|
9
|
+
/** User identifier */
|
|
10
|
+
userId?: string;
|
|
11
|
+
/** Organization identifier */
|
|
12
|
+
orgId?: string;
|
|
13
|
+
/** User's plan (free, pro, enterprise, etc.) */
|
|
14
|
+
plan?: string;
|
|
15
|
+
/** User segment or cohort */
|
|
16
|
+
segment?: string;
|
|
17
|
+
/** Session identifier for anonymous users */
|
|
18
|
+
sessionId?: string;
|
|
19
|
+
/** Additional custom attributes */
|
|
20
|
+
attributes?: Record<string, unknown>;
|
|
21
|
+
}
|
|
22
|
+
interface FeatureFlag {
|
|
23
|
+
id: string;
|
|
24
|
+
key: string;
|
|
25
|
+
status: 'OFF' | 'ON' | 'GRADUAL';
|
|
26
|
+
defaultValue: boolean;
|
|
27
|
+
variants?: VariantConfig[];
|
|
28
|
+
}
|
|
29
|
+
interface TargetingRule {
|
|
30
|
+
id: string;
|
|
31
|
+
priority: number;
|
|
32
|
+
enabled: boolean;
|
|
33
|
+
attribute: string;
|
|
34
|
+
operator: RuleOperator;
|
|
35
|
+
value: unknown;
|
|
36
|
+
rolloutPercentage?: number;
|
|
37
|
+
serveValue?: boolean;
|
|
38
|
+
serveVariant?: string;
|
|
39
|
+
}
|
|
40
|
+
interface Experiment {
|
|
41
|
+
id: string;
|
|
42
|
+
key: string;
|
|
43
|
+
status: 'DRAFT' | 'RUNNING' | 'PAUSED' | 'COMPLETED' | 'CANCELLED';
|
|
44
|
+
variants: ExperimentVariant[];
|
|
45
|
+
audiencePercentage: number;
|
|
46
|
+
audienceFilter?: Record<string, unknown>;
|
|
47
|
+
}
|
|
48
|
+
interface VariantConfig {
|
|
49
|
+
key: string;
|
|
50
|
+
name: string;
|
|
51
|
+
description?: string;
|
|
52
|
+
weight?: number;
|
|
53
|
+
}
|
|
54
|
+
interface ExperimentVariant {
|
|
55
|
+
key: string;
|
|
56
|
+
name: string;
|
|
57
|
+
percentage: number;
|
|
58
|
+
}
|
|
59
|
+
interface EvaluationResult {
|
|
60
|
+
enabled: boolean;
|
|
61
|
+
variant?: string;
|
|
62
|
+
reason: EvaluationReason;
|
|
63
|
+
ruleId?: string;
|
|
64
|
+
experimentId?: string;
|
|
65
|
+
}
|
|
66
|
+
type EvaluationReason = 'FLAG_OFF' | 'FLAG_ON' | 'DEFAULT_VALUE' | 'RULE_MATCH' | 'PERCENTAGE_ROLLOUT' | 'EXPERIMENT_VARIANT' | 'FLAG_NOT_FOUND';
|
|
67
|
+
type RuleOperator = 'EQ' | 'NEQ' | 'IN' | 'NIN' | 'CONTAINS' | 'NOT_CONTAINS' | 'GT' | 'GTE' | 'LT' | 'LTE' | 'PERCENTAGE';
|
|
68
|
+
/**
|
|
69
|
+
* Simple hash function for consistent bucketing.
|
|
70
|
+
* Uses a deterministic algorithm so the same input always produces the same bucket.
|
|
71
|
+
*/
|
|
72
|
+
declare function hashToBucket(value: string, seed?: string): number;
|
|
73
|
+
/**
|
|
74
|
+
* Get subject identifier from context for consistent hashing.
|
|
75
|
+
*/
|
|
76
|
+
declare function getSubjectId(context: EvaluationContext): string;
|
|
77
|
+
/**
|
|
78
|
+
* Evaluate a single targeting rule condition.
|
|
79
|
+
*/
|
|
80
|
+
declare function evaluateRuleCondition(rule: TargetingRule, context: EvaluationContext): boolean;
|
|
81
|
+
interface FlagRepository {
|
|
82
|
+
getFlag(key: string, orgId?: string): Promise<FeatureFlag | null>;
|
|
83
|
+
getRules(flagId: string): Promise<TargetingRule[]>;
|
|
84
|
+
getActiveExperiment(flagId: string): Promise<Experiment | null>;
|
|
85
|
+
getExperimentAssignment(experimentId: string, subjectType: string, subjectId: string): Promise<string | null>;
|
|
86
|
+
saveExperimentAssignment(experimentId: string, subjectType: string, subjectId: string, variant: string, bucket: number): Promise<void>;
|
|
87
|
+
}
|
|
88
|
+
interface EvaluationLogger {
|
|
89
|
+
log(evaluation: {
|
|
90
|
+
flagId: string;
|
|
91
|
+
flagKey: string;
|
|
92
|
+
subjectType: string;
|
|
93
|
+
subjectId: string;
|
|
94
|
+
result: boolean;
|
|
95
|
+
variant?: string;
|
|
96
|
+
reason: string;
|
|
97
|
+
ruleId?: string;
|
|
98
|
+
experimentId?: string;
|
|
99
|
+
context?: EvaluationContext;
|
|
100
|
+
}): void;
|
|
101
|
+
}
|
|
102
|
+
interface FlagEvaluatorOptions {
|
|
103
|
+
repository: FlagRepository;
|
|
104
|
+
logger?: EvaluationLogger;
|
|
105
|
+
/** Whether to log evaluations (default: false for performance) */
|
|
106
|
+
logEvaluations?: boolean;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Feature flag evaluator.
|
|
110
|
+
*
|
|
111
|
+
* Evaluates flags based on:
|
|
112
|
+
* 1. Flag status (OFF/ON/GRADUAL)
|
|
113
|
+
* 2. Targeting rules (in priority order)
|
|
114
|
+
* 3. Experiments (if running)
|
|
115
|
+
* 4. Default value (fallback)
|
|
116
|
+
*/
|
|
117
|
+
declare class FlagEvaluator {
|
|
118
|
+
private repository;
|
|
119
|
+
private logger?;
|
|
120
|
+
private logEvaluations;
|
|
121
|
+
constructor(options: FlagEvaluatorOptions);
|
|
122
|
+
/**
|
|
123
|
+
* Evaluate a feature flag.
|
|
124
|
+
*/
|
|
125
|
+
evaluate(key: string, context: EvaluationContext): Promise<EvaluationResult>;
|
|
126
|
+
/**
|
|
127
|
+
* Evaluate experiment and assign variant.
|
|
128
|
+
*/
|
|
129
|
+
private evaluateExperiment;
|
|
130
|
+
/**
|
|
131
|
+
* Assign a variant based on bucket and variant percentages.
|
|
132
|
+
*/
|
|
133
|
+
private assignVariant;
|
|
134
|
+
/**
|
|
135
|
+
* Create evaluation result.
|
|
136
|
+
*/
|
|
137
|
+
private makeResult;
|
|
138
|
+
/**
|
|
139
|
+
* Log evaluation and return result.
|
|
140
|
+
*/
|
|
141
|
+
private logAndReturn;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* In-memory flag repository for testing and development.
|
|
145
|
+
*/
|
|
146
|
+
declare class InMemoryFlagRepository implements FlagRepository {
|
|
147
|
+
private flags;
|
|
148
|
+
private rules;
|
|
149
|
+
private experiments;
|
|
150
|
+
private assignments;
|
|
151
|
+
addFlag(flag: FeatureFlag): void;
|
|
152
|
+
addRule(flagId: string, rule: TargetingRule): void;
|
|
153
|
+
addExperiment(experiment: Experiment, flagId: string): void;
|
|
154
|
+
getFlag(key: string): Promise<FeatureFlag | null>;
|
|
155
|
+
getRules(flagId: string): Promise<TargetingRule[]>;
|
|
156
|
+
getActiveExperiment(flagId: string): Promise<Experiment | null>;
|
|
157
|
+
getExperimentAssignment(experimentId: string, subjectType: string, subjectId: string): Promise<string | null>;
|
|
158
|
+
saveExperimentAssignment(experimentId: string, subjectType: string, subjectId: string, variant: string): Promise<void>;
|
|
159
|
+
clear(): void;
|
|
160
|
+
}
|
|
161
|
+
//#endregion
|
|
162
|
+
export { EvaluationContext, EvaluationLogger, EvaluationReason, EvaluationResult, Experiment, ExperimentVariant, FeatureFlag, FlagEvaluator, FlagEvaluatorOptions, FlagRepository, InMemoryFlagRepository, RuleOperator, TargetingRule, VariantConfig, evaluateRuleCondition, getSubjectId, hashToBucket };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function e(e,t=``){let n=`${t}:${e}`,r=0;for(let e=0;e<n.length;e++){let t=n.charCodeAt(e);r=(r<<5)-r+t,r&=r}return Math.abs(r%100)}function t(e){return e.userId||e.sessionId||e.orgId||`anonymous`}function n(n,i){let a=r(n.attribute,i);switch(n.operator){case`EQ`:return a===n.value;case`NEQ`:return a!==n.value;case`IN`:return Array.isArray(n.value)?n.value.includes(a):!1;case`NIN`:return Array.isArray(n.value)?!n.value.includes(a):!0;case`CONTAINS`:return typeof a!=`string`||typeof n.value!=`string`?!1:a.includes(n.value);case`NOT_CONTAINS`:return typeof a!=`string`||typeof n.value!=`string`?!0:!a.includes(n.value);case`GT`:return typeof a!=`number`||typeof n.value!=`number`?!1:a>n.value;case`GTE`:return typeof a!=`number`||typeof n.value!=`number`?!1:a>=n.value;case`LT`:return typeof a!=`number`||typeof n.value!=`number`?!1:a<n.value;case`LTE`:return typeof a!=`number`||typeof n.value!=`number`?!1:a<=n.value;case`PERCENTAGE`:return e(t(i),n.attribute)<(typeof n.value==`number`?n.value:0);default:return!1}}function r(e,t){switch(e){case`userId`:return t.userId;case`orgId`:return t.orgId;case`plan`:return t.plan;case`segment`:return t.segment;case`sessionId`:return t.sessionId;default:return t.attributes?.[e]}}var i=class{repository;logger;logEvaluations;constructor(e){this.repository=e.repository,this.logger=e.logger,this.logEvaluations=e.logEvaluations??!1}async evaluate(r,i){let a=i.orgId,o=await this.repository.getFlag(r,a);if(!o)return this.makeResult(!1,`FLAG_NOT_FOUND`);if(o.status===`OFF`)return this.logAndReturn(o,i,this.makeResult(!1,`FLAG_OFF`));if(o.status===`ON`)return this.logAndReturn(o,i,this.makeResult(!0,`FLAG_ON`));let s=[...await this.repository.getRules(o.id)].filter(e=>e.enabled).sort((e,t)=>e.priority-t.priority);for(let r of s)if(n(r,i)){if(r.rolloutPercentage!==void 0&&r.rolloutPercentage!==null&&e(t(i),o.key)>=r.rolloutPercentage)continue;let n=r.serveValue??!0;return this.logAndReturn(o,i,this.makeResult(n,`RULE_MATCH`,r.serveVariant,r.id))}let c=await this.repository.getActiveExperiment(o.id);if(c&&c.status===`RUNNING`){let e=await this.evaluateExperiment(c,i);if(e)return this.logAndReturn(o,i,e)}return this.logAndReturn(o,i,this.makeResult(o.defaultValue,`DEFAULT_VALUE`))}async evaluateExperiment(n,r){let i=t(r),a=r.userId?`user`:r.orgId?`org`:`session`;if(e(i,`${n.key}:audience`)>=n.audiencePercentage)return null;let o=await this.repository.getExperimentAssignment(n.id,a,i);if(!o){let t=e(i,n.key);o=this.assignVariant(n.variants,t),await this.repository.saveExperimentAssignment(n.id,a,i,o,t)}let s=o!==`control`;return this.makeResult(s,`EXPERIMENT_VARIANT`,o,void 0,n.id)}assignVariant(e,t){let n=0;for(let r of e)if(n+=r.percentage,t<n)return r.key;return e[e.length-1]?.key??`control`}makeResult(e,t,n,r,i){return{enabled:e,variant:n,reason:t,ruleId:r,experimentId:i}}logAndReturn(e,n,r){if(this.logEvaluations&&this.logger){let i=t(n),a=n.userId?`user`:n.orgId?`org`:`session`;this.logger.log({flagId:e.id,flagKey:e.key,subjectType:a,subjectId:i,result:r.enabled,variant:r.variant,reason:r.reason,ruleId:r.ruleId,experimentId:r.experimentId,context:n})}return r}},a=class{flags=new Map;rules=new Map;experiments=new Map;assignments=new Map;addFlag(e){this.flags.set(e.key,e)}addRule(e,t){let n=this.rules.get(e)||[];n.push(t),this.rules.set(e,n)}addExperiment(e,t){this.experiments.set(t,e)}async getFlag(e){return this.flags.get(e)||null}async getRules(e){return this.rules.get(e)||[]}async getActiveExperiment(e){return this.experiments.get(e)||null}async getExperimentAssignment(e,t,n){let r=`${e}:${t}:${n}`;return this.assignments.get(r)||null}async saveExperimentAssignment(e,t,n,r){let i=`${e}:${t}:${n}`;this.assignments.set(i,r)}clear(){this.flags.clear(),this.rules.clear(),this.experiments.clear(),this.assignments.clear()}};export{i as FlagEvaluator,a as InMemoryFlagRepository,n as evaluateRuleCondition,t as getSubjectId,e as hashToBucket};
|