@lssm/lib.feature-flags 1.41.1 → 1.42.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +13 -0
  3. package/dist/contracts/index.d.ts +1010 -0
  4. package/dist/contracts/index.d.ts.map +1 -0
  5. package/dist/contracts/index.js +908 -1
  6. package/dist/contracts/index.js.map +1 -0
  7. package/dist/contracts/src/app-config/lifecycle.d.ts +1 -0
  8. package/dist/contracts/src/app-config/runtime.d.ts +13 -0
  9. package/dist/contracts/src/app-config/spec.d.ts +8 -0
  10. package/dist/contracts/src/app-config/validation.d.ts +8 -0
  11. package/dist/contracts/src/capabilities/capabilities.d.ts +19 -0
  12. package/dist/contracts/src/capabilities/capabilities.d.ts.map +1 -0
  13. package/dist/contracts/src/capabilities/index.d.ts +2 -0
  14. package/dist/contracts/src/capabilities/openbanking.d.ts +1 -0
  15. package/dist/contracts/src/client/index.d.ts +1 -0
  16. package/dist/contracts/src/client/react/drivers/rn-reusables.d.ts +1 -0
  17. package/dist/contracts/src/client/react/drivers/shadcn.d.ts +1 -0
  18. package/dist/contracts/src/client/react/feature-render.d.ts +3 -0
  19. package/dist/contracts/src/client/react/form-render.d.ts +4 -0
  20. package/dist/contracts/src/client/react/index.d.ts +4 -0
  21. package/dist/contracts/src/contract-registry/index.d.ts +2 -0
  22. package/dist/contracts/src/contract-registry/schemas.d.ts +2 -0
  23. package/dist/contracts/src/contract-registry/types.d.ts +1 -0
  24. package/dist/contracts/src/data-views/data-views.d.ts +4 -0
  25. package/dist/contracts/src/data-views/index.d.ts +3 -0
  26. package/dist/contracts/src/data-views/query-generator.d.ts +1 -0
  27. package/dist/contracts/src/data-views/runtime.d.ts +1 -0
  28. package/dist/contracts/src/docs/accessibility_wcag_compliance_specs.docblock.d.ts +1 -0
  29. package/dist/contracts/src/docs/index.d.ts +23 -0
  30. package/dist/contracts/src/docs/presentations.d.ts +2 -0
  31. package/dist/contracts/src/docs/registry.d.ts +10 -0
  32. package/dist/contracts/src/docs/registry.d.ts.map +1 -0
  33. package/dist/contracts/src/docs/tech/auth/better-auth-nextjs.docblock.d.ts +1 -0
  34. package/dist/contracts/src/docs/tech/contracts/openapi-export.docblock.d.ts +1 -0
  35. package/dist/contracts/src/docs/tech/lifecycle-stage-system.docblock.d.ts +1 -0
  36. package/dist/contracts/src/docs/tech/llm/llm-integration.docblock.d.ts +1 -0
  37. package/dist/contracts/src/docs/tech/mcp-endpoints.docblock.d.ts +1 -0
  38. package/dist/contracts/src/docs/tech/presentation-runtime.docblock.d.ts +1 -0
  39. package/dist/contracts/src/docs/tech/schema/README.docblock.d.ts +1 -0
  40. package/dist/contracts/src/docs/tech/studio/learning-events.docblock.d.ts +1 -0
  41. package/dist/contracts/src/docs/tech/studio/learning-journeys.docblock.d.ts +1 -0
  42. package/dist/contracts/src/docs/tech/studio/platform-admin-panel.docblock.d.ts +1 -0
  43. package/dist/contracts/src/docs/tech/studio/project-access-teams.docblock.d.ts +1 -0
  44. package/dist/contracts/src/docs/tech/studio/project-routing.docblock.d.ts +1 -0
  45. package/dist/contracts/src/docs/tech/studio/sandbox-unlogged.docblock.d.ts +1 -0
  46. package/dist/contracts/src/docs/tech/studio/team-invitations.docblock.d.ts +1 -0
  47. package/dist/contracts/src/docs/tech/studio/workspace-ops.docblock.d.ts +1 -0
  48. package/dist/contracts/src/docs/tech/studio/workspaces.docblock.d.ts +1 -0
  49. package/dist/contracts/src/docs/tech/telemetry-ingest.docblock.d.ts +1 -0
  50. package/dist/contracts/src/docs/tech/templates/runtime.docblock.d.ts +1 -0
  51. package/dist/contracts/src/docs/tech/vscode-extension.docblock.d.ts +1 -0
  52. package/dist/contracts/src/docs/tech/workflows/overview.docblock.d.ts +1 -0
  53. package/dist/contracts/src/events.d.ts +25 -0
  54. package/dist/contracts/src/events.d.ts.map +1 -0
  55. package/dist/contracts/src/experiments/evaluator.d.ts +2 -0
  56. package/dist/contracts/src/experiments/spec-resolver.d.ts +4 -0
  57. package/dist/contracts/src/experiments/spec.d.ts +12 -0
  58. package/dist/contracts/src/experiments/spec.d.ts.map +1 -0
  59. package/dist/contracts/src/features.d.ts +71 -0
  60. package/dist/contracts/src/features.d.ts.map +1 -0
  61. package/dist/contracts/src/forms/forms.d.ts +3 -0
  62. package/dist/contracts/src/forms/index.d.ts +1 -0
  63. package/dist/contracts/src/index.d.ts +48 -0
  64. package/dist/contracts/src/install.d.ts +7 -0
  65. package/dist/contracts/src/integrations/connection.d.ts +1 -0
  66. package/dist/contracts/src/integrations/index.d.ts +6 -0
  67. package/dist/contracts/src/integrations/openbanking/contracts/accounts.d.ts +4 -0
  68. package/dist/contracts/src/integrations/openbanking/contracts/balances.d.ts +4 -0
  69. package/dist/contracts/src/integrations/openbanking/contracts/index.d.ts +5 -0
  70. package/dist/contracts/src/integrations/openbanking/contracts/transactions.d.ts +4 -0
  71. package/dist/contracts/src/integrations/openbanking/guards.d.ts +1 -0
  72. package/dist/contracts/src/integrations/openbanking/models.d.ts +1 -0
  73. package/dist/contracts/src/integrations/openbanking/openbanking.feature.d.ts +1 -0
  74. package/dist/contracts/src/integrations/operations.d.ts +4 -0
  75. package/dist/contracts/src/integrations/providers/elevenlabs.d.ts +1 -0
  76. package/dist/contracts/src/integrations/providers/gcs-storage.d.ts +1 -0
  77. package/dist/contracts/src/integrations/providers/gmail.d.ts +1 -0
  78. package/dist/contracts/src/integrations/providers/google-calendar.d.ts +1 -0
  79. package/dist/contracts/src/integrations/providers/index.d.ts +11 -0
  80. package/dist/contracts/src/integrations/providers/mistral.d.ts +1 -0
  81. package/dist/contracts/src/integrations/providers/postmark.d.ts +1 -0
  82. package/dist/contracts/src/integrations/providers/powens.d.ts +1 -0
  83. package/dist/contracts/src/integrations/providers/qdrant.d.ts +1 -0
  84. package/dist/contracts/src/integrations/providers/registry.d.ts +1 -0
  85. package/dist/contracts/src/integrations/providers/stripe.d.ts +1 -0
  86. package/dist/contracts/src/integrations/providers/twilio-sms.d.ts +1 -0
  87. package/dist/contracts/src/integrations/spec.d.ts +2 -0
  88. package/dist/contracts/src/jsonschema.d.ts +4 -0
  89. package/dist/contracts/src/knowledge/index.d.ts +2 -0
  90. package/dist/contracts/src/knowledge/operations.d.ts +4 -0
  91. package/dist/contracts/src/knowledge/spaces/email-threads.d.ts +1 -0
  92. package/dist/contracts/src/knowledge/spaces/financial-docs.d.ts +1 -0
  93. package/dist/contracts/src/knowledge/spaces/financial-overview.d.ts +1 -0
  94. package/dist/contracts/src/knowledge/spaces/index.d.ts +6 -0
  95. package/dist/contracts/src/knowledge/spaces/product-canon.d.ts +1 -0
  96. package/dist/contracts/src/knowledge/spaces/support-faq.d.ts +1 -0
  97. package/dist/contracts/src/knowledge/spaces/uploaded-docs.d.ts +1 -0
  98. package/dist/contracts/src/knowledge/spec.d.ts +2 -0
  99. package/dist/contracts/src/llm/exporters.d.ts +7 -0
  100. package/dist/contracts/src/llm/index.d.ts +3 -0
  101. package/dist/contracts/src/llm/prompts.d.ts +2 -0
  102. package/dist/contracts/src/llm/types.d.ts +5 -0
  103. package/dist/contracts/src/migrations.d.ts +1 -0
  104. package/dist/contracts/src/onboarding-base.d.ts +2 -0
  105. package/dist/contracts/src/openapi.d.ts +1 -0
  106. package/dist/contracts/src/operations/index.d.ts +2 -0
  107. package/dist/contracts/src/operations/operation.d.ts +164 -0
  108. package/dist/contracts/src/operations/operation.d.ts.map +1 -0
  109. package/dist/contracts/src/operations/registry.d.ts +6 -0
  110. package/dist/contracts/src/ownership.d.ts +61 -0
  111. package/dist/contracts/src/ownership.d.ts.map +1 -0
  112. package/dist/contracts/src/policy/engine.d.ts +3 -0
  113. package/dist/contracts/src/policy/index.d.ts +4 -0
  114. package/dist/contracts/src/policy/opa-adapter.d.ts +3 -0
  115. package/dist/contracts/src/policy/registry.d.ts +2 -0
  116. package/dist/contracts/src/policy/spec.d.ts +11 -0
  117. package/dist/contracts/src/policy/spec.d.ts.map +1 -0
  118. package/dist/contracts/src/presentations/index.d.ts +3 -0
  119. package/dist/contracts/src/presentations/presentations.d.ts +9 -0
  120. package/dist/contracts/src/presentations/presentations.d.ts.map +1 -0
  121. package/dist/contracts/src/presentations/registry.d.ts +2 -0
  122. package/dist/contracts/src/presentations/transform-engine.d.ts +2 -0
  123. package/dist/contracts/src/prompt.d.ts +1 -0
  124. package/dist/contracts/src/promptRegistry.d.ts +2 -0
  125. package/dist/contracts/src/regenerator/adapters.d.ts +1 -0
  126. package/dist/contracts/src/regenerator/executor.d.ts +1 -0
  127. package/dist/contracts/src/regenerator/index.d.ts +6 -0
  128. package/dist/contracts/src/regenerator/service.d.ts +2 -0
  129. package/dist/contracts/src/regenerator/sinks.d.ts +2 -0
  130. package/dist/contracts/src/regenerator/types.d.ts +3 -0
  131. package/dist/contracts/src/regenerator/utils.d.ts +1 -0
  132. package/dist/contracts/src/registry-utils.d.ts +1 -0
  133. package/dist/contracts/src/registry.d.ts +3 -0
  134. package/dist/contracts/src/resources.d.ts +19 -0
  135. package/dist/contracts/src/resources.d.ts.map +1 -0
  136. package/dist/contracts/src/schema-to-markdown.d.ts +1 -0
  137. package/dist/contracts/src/server/graphql-pothos.d.ts +7 -0
  138. package/dist/contracts/src/server/index.d.ts +7 -0
  139. package/dist/contracts/src/server/mcp/createMcpServer.d.ts +5 -0
  140. package/dist/contracts/src/server/mcp/mcpTypes.d.ts +2 -0
  141. package/dist/contracts/src/server/provider-mcp.d.ts +1 -0
  142. package/dist/contracts/src/server/rest-elysia.d.ts +3 -0
  143. package/dist/contracts/src/server/rest-express.d.ts +3 -0
  144. package/dist/contracts/src/server/rest-generic.d.ts +2 -0
  145. package/dist/contracts/src/server/rest-next-app.d.ts +3 -0
  146. package/dist/contracts/src/server/rest-next-pages.d.ts +3 -0
  147. package/dist/contracts/src/telemetry/anomaly.d.ts +2 -0
  148. package/dist/contracts/src/telemetry/index.d.ts +3 -0
  149. package/dist/contracts/src/telemetry/spec.d.ts +1 -0
  150. package/dist/contracts/src/telemetry/tracker.d.ts +2 -0
  151. package/dist/contracts/src/tests/index.d.ts +2 -0
  152. package/dist/contracts/src/tests/runner.d.ts +3 -0
  153. package/dist/contracts/src/tests/spec.d.ts +11 -0
  154. package/dist/contracts/src/tests/spec.d.ts.map +1 -0
  155. package/dist/contracts/src/themes.d.ts +1 -0
  156. package/dist/contracts/src/types.d.ts +5 -0
  157. package/dist/contracts/src/workflow/adapters/db-adapter.d.ts +1 -0
  158. package/dist/contracts/src/workflow/adapters/file-adapter.d.ts +1 -0
  159. package/dist/contracts/src/workflow/adapters/index.d.ts +3 -0
  160. package/dist/contracts/src/workflow/adapters/memory-store.d.ts +1 -0
  161. package/dist/contracts/src/workflow/index.d.ts +5 -0
  162. package/dist/contracts/src/workflow/runner.d.ts +5 -0
  163. package/dist/contracts/src/workflow/spec.d.ts +5 -0
  164. package/dist/contracts/src/workflow/state.d.ts +1 -0
  165. package/dist/contracts/src/workflow/validation.d.ts +3 -0
  166. package/dist/contracts/src/workspace-config/contractsrc-schema.d.ts +1 -0
  167. package/dist/contracts/src/workspace-config/index.d.ts +1 -0
  168. package/dist/docs/feature-flags.docblock.d.ts +1 -0
  169. package/dist/docs/feature-flags.docblock.js +21 -2
  170. package/dist/docs/feature-flags.docblock.js.map +1 -0
  171. package/dist/docs/index.d.ts +1 -0
  172. package/dist/docs/index.js +1 -1
  173. package/dist/entities/index.d.ts +201 -0
  174. package/dist/entities/index.d.ts.map +1 -0
  175. package/dist/entities/index.js +325 -1
  176. package/dist/entities/index.js.map +1 -0
  177. package/dist/evaluation/index.d.ts +163 -0
  178. package/dist/evaluation/index.d.ts.map +1 -0
  179. package/dist/evaluation/index.js +221 -1
  180. package/dist/evaluation/index.js.map +1 -0
  181. package/dist/events.d.ts +628 -0
  182. package/dist/events.d.ts.map +1 -0
  183. package/dist/events.js +536 -1
  184. package/dist/events.js.map +1 -0
  185. package/dist/feature-flags.feature.d.ts +13 -0
  186. package/dist/feature-flags.feature.d.ts.map +1 -0
  187. package/dist/feature-flags.feature.js +141 -1
  188. package/dist/feature-flags.feature.js.map +1 -0
  189. package/dist/index.d.ts +6 -0
  190. package/dist/index.js +8 -1
  191. package/dist/schema/src/EnumType.d.ts +36 -0
  192. package/dist/schema/src/EnumType.d.ts.map +1 -0
  193. package/dist/schema/src/FieldType.d.ts +30 -0
  194. package/dist/schema/src/FieldType.d.ts.map +1 -0
  195. package/dist/schema/src/ScalarTypeEnum.d.ts +1 -0
  196. package/dist/schema/src/SchemaModel.d.ts +56 -0
  197. package/dist/schema/src/SchemaModel.d.ts.map +1 -0
  198. package/dist/schema/src/entity/defineEntity.d.ts +1 -0
  199. package/dist/schema/src/entity/generator.d.ts +1 -0
  200. package/dist/schema/src/entity/index.d.ts +3 -0
  201. package/dist/schema/src/entity/types.d.ts +146 -0
  202. package/dist/schema/src/entity/types.d.ts.map +1 -0
  203. package/dist/schema/src/index.d.ts +6 -0
  204. package/package.json +22 -15
@@ -0,0 +1,5 @@
1
+ import "../features.js";
2
+ import "./spec.js";
3
+ import "../app-config/runtime.js";
4
+ import "../types.js";
5
+ import "./state.js";
@@ -0,0 +1,5 @@
1
+ import "../ownership.js";
2
+ import "../registry-utils.js";
3
+ import "../capabilities/index.js";
4
+ import "../experiments/spec.js";
5
+ import "../features.js";
@@ -0,0 +1 @@
1
+ import "./spec.js";
@@ -0,0 +1,3 @@
1
+ import "../operations/registry.js";
2
+ import "./spec.js";
3
+ import "../forms/index.js";
@@ -0,0 +1 @@
1
+ import "./contractsrc-schema.js";
@@ -0,0 +1 @@
1
+ export { };
@@ -1,4 +1,19 @@
1
- import{registerDocBlocks as e}from"@lssm/lib.contracts/docs";e([{id:`docs.feature-flags.overview`,title:`Feature Flags & Experiments`,summary:`Reusable, spec-first feature flag and experiment module with targeting, gradual rollout, multivariate variants, and evaluation logging.`,kind:`reference`,visibility:`public`,route:`/docs/feature-flags/overview`,tags:[`feature-flags`,`experiments`,`progressive-delivery`],body:`## What this module provides
1
+ import { registerDocBlocks } from "@lssm/lib.contracts/docs";
2
+
3
+ //#region src/docs/feature-flags.docblock.ts
4
+ registerDocBlocks([{
5
+ id: "docs.feature-flags.overview",
6
+ title: "Feature Flags & Experiments",
7
+ summary: "Reusable, spec-first feature flag and experiment module with targeting, gradual rollout, multivariate variants, and evaluation logging.",
8
+ kind: "reference",
9
+ visibility: "public",
10
+ route: "/docs/feature-flags/overview",
11
+ tags: [
12
+ "feature-flags",
13
+ "experiments",
14
+ "progressive-delivery"
15
+ ],
16
+ body: `## What this module provides
2
17
 
3
18
  - **Entities**: FeatureFlag, FlagTargetingRule, Experiment, ExperimentAssignment, FlagEvaluation.
4
19
  - **Contracts**: create/update/delete/toggle/list/get flags; create/delete rules; evaluate flags; create/start/stop/get experiments.
@@ -54,4 +69,8 @@ if (result.enabled) {
54
69
  - Ensure experiments’ variant percentages sum to 100; default flag status to OFF.
55
70
  - Use org-scoped flags for multi-tenant isolation.
56
71
  - Log evaluations only when needed to control volume; prefer sampling for noisy paths.
57
- `}]);
72
+ `
73
+ }]);
74
+
75
+ //#endregion
76
+ //# sourceMappingURL=feature-flags.docblock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feature-flags.docblock.js","names":[],"sources":["../../src/docs/feature-flags.docblock.ts"],"sourcesContent":["import type { DocBlock } from '@lssm/lib.contracts/docs';\nimport { registerDocBlocks } from '@lssm/lib.contracts/docs';\n\nconst featureFlagsDocBlocks: DocBlock[] = [\n {\n id: 'docs.feature-flags.overview',\n title: 'Feature Flags & Experiments',\n summary:\n 'Reusable, spec-first feature flag and experiment module with targeting, gradual rollout, multivariate variants, and evaluation logging.',\n kind: 'reference',\n visibility: 'public',\n route: '/docs/feature-flags/overview',\n tags: ['feature-flags', 'experiments', 'progressive-delivery'],\n body: `## What this module provides\n\n- **Entities**: FeatureFlag, FlagTargetingRule, Experiment, ExperimentAssignment, FlagEvaluation.\n- **Contracts**: create/update/delete/toggle/list/get flags; create/delete rules; evaluate flags; create/start/stop/get experiments.\n- **Events**: flag.created/updated/deleted/toggled, rule.created/deleted, experiment.created/started/stopped, flag.evaluated, experiment.variant_assigned.\n- **Evaluation Engine**: Deterministic evaluator with gradual rollout, rule priority, audience filters, and experiment bucketing.\n\n## How to use\n\n1) Compose schema\n - Add \\`featureFlagsSchemaContribution\\` to your module composition.\n\n2) Register contracts/events\n - Import exports from \\`@lssm/lib.feature-flags\\` into your spec registry.\n\n3) Evaluate at runtime\n - Instantiate \\`FlagEvaluator\\` with a repository implementation and optional logger.\n - Evaluate with context attributes (userId, orgId, plan, segment, sessionId, attributes).\n\n4) Wire observability\n - Emit audit trail on config changes; emit \\`flag.evaluated\\` for analytics.\n\n## Usage example\n\n${'```'}ts\nimport {\n FlagEvaluator,\n InMemoryFlagRepository,\n} from '@lssm/lib.feature-flags';\n\nconst repo = new InMemoryFlagRepository();\nrepo.addFlag({\n id: 'flag-1',\n key: 'new_dashboard',\n status: 'GRADUAL',\n defaultValue: false,\n});\n\nconst evaluator = new FlagEvaluator({ repository: repo });\nconst result = await evaluator.evaluate('new_dashboard', {\n userId: 'user-123',\n orgId: 'org-456',\n plan: 'pro',\n});\n\nif (result.enabled) {\n // serve the new dashboard\n}\n${'```'},\n\n## Guardrails\n\n- Keep flag keys stable and human-readable; avoid PII in context.\n- Ensure experiments’ variant percentages sum to 100; default flag status to OFF.\n- Use org-scoped flags for multi-tenant isolation.\n- Log evaluations only when needed to control volume; prefer sampling for noisy paths.\n`,\n },\n];\n\nregisterDocBlocks(featureFlagsDocBlocks);\n"],"mappings":";;;AAyEA,kBAtE0C,CACxC;CACE,IAAI;CACJ,OAAO;CACP,SACE;CACF,MAAM;CACN,YAAY;CACZ,OAAO;CACP,MAAM;EAAC;EAAiB;EAAe;EAAuB;CAC9D,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyDP,CACF,CAEuC"}
@@ -0,0 +1 @@
1
+ export { };
@@ -1 +1 @@
1
- import"./feature-flags.docblock.js";
1
+ import "./feature-flags.docblock.js";
@@ -0,0 +1,201 @@
1
+ import { EntityEnumDef, EntityEnumField, EntityRelationField, EntityScalarField, EntitySpec, ModuleSchemaContribution } from "../schema/src/entity/types.js";
2
+ import "../schema/src/index.js";
3
+
4
+ //#region src/entities/index.d.ts
5
+ /**
6
+ * Feature flag status enum.
7
+ */
8
+ declare const FlagStatusEnum: EntityEnumDef;
9
+ /**
10
+ * Targeting rule operator enum.
11
+ */
12
+ declare const RuleOperatorEnum: EntityEnumDef;
13
+ /**
14
+ * Experiment status enum.
15
+ */
16
+ declare const ExperimentStatusEnum: EntityEnumDef;
17
+ /**
18
+ * FeatureFlag entity - defines a feature flag.
19
+ */
20
+ declare const FeatureFlagEntity: EntitySpec<{
21
+ id: EntityScalarField;
22
+ key: EntityScalarField;
23
+ name: EntityScalarField;
24
+ description: EntityScalarField;
25
+ status: EntityEnumField;
26
+ defaultValue: EntityScalarField;
27
+ variants: EntityScalarField;
28
+ orgId: EntityScalarField;
29
+ tags: EntityScalarField;
30
+ metadata: EntityScalarField;
31
+ createdAt: EntityScalarField;
32
+ updatedAt: EntityScalarField;
33
+ targetingRules: EntityRelationField;
34
+ experiments: EntityRelationField;
35
+ evaluations: EntityRelationField;
36
+ }>;
37
+ /**
38
+ * FlagTargetingRule entity - conditions for targeting.
39
+ */
40
+ declare const FlagTargetingRuleEntity: EntitySpec<{
41
+ id: EntityScalarField;
42
+ flagId: EntityScalarField;
43
+ name: EntityScalarField;
44
+ priority: EntityScalarField;
45
+ enabled: EntityScalarField;
46
+ attribute: EntityScalarField;
47
+ operator: EntityEnumField;
48
+ value: EntityScalarField;
49
+ rolloutPercentage: EntityScalarField;
50
+ serveValue: EntityScalarField;
51
+ serveVariant: EntityScalarField;
52
+ createdAt: EntityScalarField;
53
+ updatedAt: EntityScalarField;
54
+ flag: EntityRelationField;
55
+ }>;
56
+ /**
57
+ * Experiment entity - A/B test configuration.
58
+ */
59
+ declare const ExperimentEntity: EntitySpec<{
60
+ id: EntityScalarField;
61
+ key: EntityScalarField;
62
+ name: EntityScalarField;
63
+ description: EntityScalarField;
64
+ hypothesis: EntityScalarField;
65
+ flagId: EntityScalarField;
66
+ status: EntityEnumField;
67
+ variants: EntityScalarField;
68
+ metrics: EntityScalarField;
69
+ audiencePercentage: EntityScalarField;
70
+ audienceFilter: EntityScalarField;
71
+ scheduledStartAt: EntityScalarField;
72
+ scheduledEndAt: EntityScalarField;
73
+ startedAt: EntityScalarField;
74
+ endedAt: EntityScalarField;
75
+ winningVariant: EntityScalarField;
76
+ results: EntityScalarField;
77
+ orgId: EntityScalarField;
78
+ createdAt: EntityScalarField;
79
+ updatedAt: EntityScalarField;
80
+ flag: EntityRelationField;
81
+ assignments: EntityRelationField;
82
+ }>;
83
+ /**
84
+ * ExperimentAssignment entity - tracks which variant a subject is assigned to.
85
+ */
86
+ declare const ExperimentAssignmentEntity: EntitySpec<{
87
+ id: EntityScalarField;
88
+ experimentId: EntityScalarField;
89
+ subjectType: EntityScalarField;
90
+ subjectId: EntityScalarField;
91
+ variant: EntityScalarField;
92
+ bucket: EntityScalarField;
93
+ context: EntityScalarField;
94
+ assignedAt: EntityScalarField;
95
+ experiment: EntityRelationField;
96
+ }>;
97
+ /**
98
+ * FlagEvaluation entity - evaluation log for analytics.
99
+ */
100
+ declare const FlagEvaluationEntity: EntitySpec<{
101
+ id: EntityScalarField;
102
+ flagId: EntityScalarField;
103
+ flagKey: EntityScalarField;
104
+ subjectType: EntityScalarField;
105
+ subjectId: EntityScalarField;
106
+ result: EntityScalarField;
107
+ variant: EntityScalarField;
108
+ matchedRuleId: EntityScalarField;
109
+ reason: EntityScalarField;
110
+ context: EntityScalarField;
111
+ evaluatedAt: EntityScalarField;
112
+ flag: EntityRelationField;
113
+ }>;
114
+ /**
115
+ * All feature flag entities for schema composition.
116
+ */
117
+ declare const featureFlagEntities: (EntitySpec<{
118
+ id: EntityScalarField;
119
+ key: EntityScalarField;
120
+ name: EntityScalarField;
121
+ description: EntityScalarField;
122
+ status: EntityEnumField;
123
+ defaultValue: EntityScalarField;
124
+ variants: EntityScalarField;
125
+ orgId: EntityScalarField;
126
+ tags: EntityScalarField;
127
+ metadata: EntityScalarField;
128
+ createdAt: EntityScalarField;
129
+ updatedAt: EntityScalarField;
130
+ targetingRules: EntityRelationField;
131
+ experiments: EntityRelationField;
132
+ evaluations: EntityRelationField;
133
+ }> | EntitySpec<{
134
+ id: EntityScalarField;
135
+ flagId: EntityScalarField;
136
+ name: EntityScalarField;
137
+ priority: EntityScalarField;
138
+ enabled: EntityScalarField;
139
+ attribute: EntityScalarField;
140
+ operator: EntityEnumField;
141
+ value: EntityScalarField;
142
+ rolloutPercentage: EntityScalarField;
143
+ serveValue: EntityScalarField;
144
+ serveVariant: EntityScalarField;
145
+ createdAt: EntityScalarField;
146
+ updatedAt: EntityScalarField;
147
+ flag: EntityRelationField;
148
+ }> | EntitySpec<{
149
+ id: EntityScalarField;
150
+ key: EntityScalarField;
151
+ name: EntityScalarField;
152
+ description: EntityScalarField;
153
+ hypothesis: EntityScalarField;
154
+ flagId: EntityScalarField;
155
+ status: EntityEnumField;
156
+ variants: EntityScalarField;
157
+ metrics: EntityScalarField;
158
+ audiencePercentage: EntityScalarField;
159
+ audienceFilter: EntityScalarField;
160
+ scheduledStartAt: EntityScalarField;
161
+ scheduledEndAt: EntityScalarField;
162
+ startedAt: EntityScalarField;
163
+ endedAt: EntityScalarField;
164
+ winningVariant: EntityScalarField;
165
+ results: EntityScalarField;
166
+ orgId: EntityScalarField;
167
+ createdAt: EntityScalarField;
168
+ updatedAt: EntityScalarField;
169
+ flag: EntityRelationField;
170
+ assignments: EntityRelationField;
171
+ }> | EntitySpec<{
172
+ id: EntityScalarField;
173
+ experimentId: EntityScalarField;
174
+ subjectType: EntityScalarField;
175
+ subjectId: EntityScalarField;
176
+ variant: EntityScalarField;
177
+ bucket: EntityScalarField;
178
+ context: EntityScalarField;
179
+ assignedAt: EntityScalarField;
180
+ experiment: EntityRelationField;
181
+ }> | EntitySpec<{
182
+ id: EntityScalarField;
183
+ flagId: EntityScalarField;
184
+ flagKey: EntityScalarField;
185
+ subjectType: EntityScalarField;
186
+ subjectId: EntityScalarField;
187
+ result: EntityScalarField;
188
+ variant: EntityScalarField;
189
+ matchedRuleId: EntityScalarField;
190
+ reason: EntityScalarField;
191
+ context: EntityScalarField;
192
+ evaluatedAt: EntityScalarField;
193
+ flag: 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 };
201
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/entities/index.ts"],"sourcesContent":[],"mappings":";;;;;;;AAMa,cAAA,cAKX,EAAA,aAAA;AAKF;AAsBA;AAUA;AA4DE,cA5FW,gBA4FX,EA3EA,aA2EA;;;;cAtEW,sBAKX;;;;cAKW;MA4DX;;;;;;;EA5D4B,KAAA,mBAAA;EAiEjB,IAAA,mBAyDX;EAAA,QAAA,mBAAA;;;;;;;;;;cAzDW;MAyDX;;;;EAzDkC,OAAA,mBAAA;EA8DvB,SAAA,mBA2FX;EAAA,QAAA,iBAAA;;;;;;;;;;;;cA3FW;MA2FX;;;;;;;;;;EA3F2B,cAAA,mBAAA;EAgGhB,gBAAA,mBAuCX;EAAA,cAAA,mBAAA;;;;;;;;;;CAvCqC,CAAA;AA4CvC;;;cA5Ca;MAuCX;;;;;;;;;;;AA+DF;;cA1Da;MAqDX;;;;;;;;;;;;;;;;cAKW;MAMZ;;;;;;;;;;;;;;;;MAN+B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAWnB,MAAA,mBAAgC;;;;;;;;;;;;;;;;;;;;;cAAhC,gCAAgC"}
@@ -1 +1,325 @@
1
- import{defineEntity as e,defineEntityEnum as t,field as n,index as r}from"@lssm/lib.schema";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=e({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:[r.on([`orgId`,`key`]),r.on([`status`])],enums:[i]}),c=e({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:[r.on([`flagId`,`priority`]),r.on([`attribute`])],enums:[a]}),l=e({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:[r.on([`status`]),r.on([`orgId`,`status`]),r.on([`flagId`])],enums:[o]}),u=e({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:[r.unique([`experimentId`,`subjectType`,`subjectId`],{name:`experiment_assignment_unique`}),r.on([`subjectType`,`subjectId`])]}),d=e({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:[r.on([`flagKey`,`evaluatedAt`]),r.on([`subjectType`,`subjectId`,`evaluatedAt`]),r.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};
1
+ import { defineEntity, defineEntityEnum, field, index } from "@lssm/lib.schema";
2
+
3
+ //#region src/entities/index.ts
4
+ /**
5
+ * Feature flag status enum.
6
+ */
7
+ const FlagStatusEnum = defineEntityEnum({
8
+ name: "FlagStatus",
9
+ values: [
10
+ "OFF",
11
+ "ON",
12
+ "GRADUAL"
13
+ ],
14
+ schema: "lssm_feature_flags",
15
+ description: "Status of a feature flag."
16
+ });
17
+ /**
18
+ * Targeting rule operator enum.
19
+ */
20
+ const RuleOperatorEnum = defineEntityEnum({
21
+ name: "RuleOperator",
22
+ values: [
23
+ "EQ",
24
+ "NEQ",
25
+ "IN",
26
+ "NIN",
27
+ "CONTAINS",
28
+ "NOT_CONTAINS",
29
+ "GT",
30
+ "GTE",
31
+ "LT",
32
+ "LTE",
33
+ "PERCENTAGE"
34
+ ],
35
+ schema: "lssm_feature_flags",
36
+ description: "Operator for targeting rule conditions."
37
+ });
38
+ /**
39
+ * Experiment status enum.
40
+ */
41
+ const ExperimentStatusEnum = defineEntityEnum({
42
+ name: "ExperimentStatus",
43
+ values: [
44
+ "DRAFT",
45
+ "RUNNING",
46
+ "PAUSED",
47
+ "COMPLETED",
48
+ "CANCELLED"
49
+ ],
50
+ schema: "lssm_feature_flags",
51
+ description: "Status of an experiment."
52
+ });
53
+ /**
54
+ * FeatureFlag entity - defines a feature flag.
55
+ */
56
+ const FeatureFlagEntity = defineEntity({
57
+ name: "FeatureFlag",
58
+ description: "A feature flag for controlling feature availability.",
59
+ schema: "lssm_feature_flags",
60
+ map: "feature_flag",
61
+ fields: {
62
+ id: field.id({ description: "Unique flag identifier" }),
63
+ key: field.string({
64
+ isUnique: true,
65
+ description: "Flag key (e.g., new_dashboard)"
66
+ }),
67
+ name: field.string({ description: "Human-readable name" }),
68
+ description: field.string({
69
+ isOptional: true,
70
+ description: "Description of the flag"
71
+ }),
72
+ status: field.enum("FlagStatus", {
73
+ default: "OFF",
74
+ description: "Flag status"
75
+ }),
76
+ defaultValue: field.boolean({
77
+ default: false,
78
+ description: "Default value when no rules match"
79
+ }),
80
+ variants: field.json({
81
+ isOptional: true,
82
+ description: "Variant definitions for multivariate flags"
83
+ }),
84
+ orgId: field.string({
85
+ isOptional: true,
86
+ description: "Organization scope (null = global)"
87
+ }),
88
+ tags: field.json({
89
+ isOptional: true,
90
+ description: "Tags for categorization"
91
+ }),
92
+ metadata: field.json({
93
+ isOptional: true,
94
+ description: "Additional metadata"
95
+ }),
96
+ createdAt: field.createdAt(),
97
+ updatedAt: field.updatedAt(),
98
+ targetingRules: field.hasMany("FlagTargetingRule"),
99
+ experiments: field.hasMany("Experiment"),
100
+ evaluations: field.hasMany("FlagEvaluation")
101
+ },
102
+ indexes: [index.on(["orgId", "key"]), index.on(["status"])],
103
+ enums: [FlagStatusEnum]
104
+ });
105
+ /**
106
+ * FlagTargetingRule entity - conditions for targeting.
107
+ */
108
+ const FlagTargetingRuleEntity = defineEntity({
109
+ name: "FlagTargetingRule",
110
+ description: "A targeting rule for conditional flag evaluation.",
111
+ schema: "lssm_feature_flags",
112
+ map: "flag_targeting_rule",
113
+ fields: {
114
+ id: field.id({ description: "Unique rule identifier" }),
115
+ flagId: field.foreignKey({ description: "Parent feature flag" }),
116
+ name: field.string({
117
+ isOptional: true,
118
+ description: "Rule name for debugging"
119
+ }),
120
+ priority: field.int({
121
+ default: 0,
122
+ description: "Rule priority (lower = higher priority)"
123
+ }),
124
+ enabled: field.boolean({
125
+ default: true,
126
+ description: "Whether rule is active"
127
+ }),
128
+ attribute: field.string({ description: "Target attribute (userId, orgId, plan, segment, etc.)" }),
129
+ operator: field.enum("RuleOperator", { description: "Comparison operator" }),
130
+ value: field.json({ description: "Target value(s)" }),
131
+ rolloutPercentage: field.int({
132
+ isOptional: true,
133
+ description: "Percentage for gradual rollout (0-100)"
134
+ }),
135
+ serveValue: field.boolean({
136
+ isOptional: true,
137
+ description: "Boolean value to serve"
138
+ }),
139
+ serveVariant: field.string({
140
+ isOptional: true,
141
+ description: "Variant key to serve (for multivariate)"
142
+ }),
143
+ createdAt: field.createdAt(),
144
+ updatedAt: field.updatedAt(),
145
+ flag: field.belongsTo("FeatureFlag", ["flagId"], ["id"], { onDelete: "Cascade" })
146
+ },
147
+ indexes: [index.on(["flagId", "priority"]), index.on(["attribute"])],
148
+ enums: [RuleOperatorEnum]
149
+ });
150
+ /**
151
+ * Experiment entity - A/B test configuration.
152
+ */
153
+ const ExperimentEntity = defineEntity({
154
+ name: "Experiment",
155
+ description: "An A/B test experiment.",
156
+ schema: "lssm_feature_flags",
157
+ map: "experiment",
158
+ fields: {
159
+ id: field.id({ description: "Unique experiment identifier" }),
160
+ key: field.string({
161
+ isUnique: true,
162
+ description: "Experiment key"
163
+ }),
164
+ name: field.string({ description: "Human-readable name" }),
165
+ description: field.string({
166
+ isOptional: true,
167
+ description: "Experiment description"
168
+ }),
169
+ hypothesis: field.string({
170
+ isOptional: true,
171
+ description: "Experiment hypothesis"
172
+ }),
173
+ flagId: field.foreignKey({ description: "Associated feature flag" }),
174
+ status: field.enum("ExperimentStatus", {
175
+ default: "DRAFT",
176
+ description: "Experiment status"
177
+ }),
178
+ variants: field.json({ description: "Variant definitions with split ratios" }),
179
+ metrics: field.json({
180
+ isOptional: true,
181
+ description: "Metrics to track"
182
+ }),
183
+ audiencePercentage: field.int({
184
+ default: 100,
185
+ description: "Percentage of audience to include"
186
+ }),
187
+ audienceFilter: field.json({
188
+ isOptional: true,
189
+ description: "Audience filter criteria"
190
+ }),
191
+ scheduledStartAt: field.dateTime({
192
+ isOptional: true,
193
+ description: "Scheduled start time"
194
+ }),
195
+ scheduledEndAt: field.dateTime({
196
+ isOptional: true,
197
+ description: "Scheduled end time"
198
+ }),
199
+ startedAt: field.dateTime({
200
+ isOptional: true,
201
+ description: "Actual start time"
202
+ }),
203
+ endedAt: field.dateTime({
204
+ isOptional: true,
205
+ description: "Actual end time"
206
+ }),
207
+ winningVariant: field.string({
208
+ isOptional: true,
209
+ description: "Declared winning variant"
210
+ }),
211
+ results: field.json({
212
+ isOptional: true,
213
+ description: "Experiment results summary"
214
+ }),
215
+ orgId: field.string({
216
+ isOptional: true,
217
+ description: "Organization scope"
218
+ }),
219
+ createdAt: field.createdAt(),
220
+ updatedAt: field.updatedAt(),
221
+ flag: field.belongsTo("FeatureFlag", ["flagId"], ["id"], { onDelete: "Cascade" }),
222
+ assignments: field.hasMany("ExperimentAssignment")
223
+ },
224
+ indexes: [
225
+ index.on(["status"]),
226
+ index.on(["orgId", "status"]),
227
+ index.on(["flagId"])
228
+ ],
229
+ enums: [ExperimentStatusEnum]
230
+ });
231
+ /**
232
+ * ExperimentAssignment entity - tracks which variant a subject is assigned to.
233
+ */
234
+ const ExperimentAssignmentEntity = defineEntity({
235
+ name: "ExperimentAssignment",
236
+ description: "Tracks experiment variant assignments.",
237
+ schema: "lssm_feature_flags",
238
+ map: "experiment_assignment",
239
+ fields: {
240
+ id: field.id({ description: "Unique assignment identifier" }),
241
+ experimentId: field.foreignKey({ description: "Parent experiment" }),
242
+ subjectType: field.string({ description: "Subject type (user, org, session)" }),
243
+ subjectId: field.string({ description: "Subject identifier" }),
244
+ variant: field.string({ description: "Assigned variant key" }),
245
+ bucket: field.int({ description: "Hash bucket (0-99)" }),
246
+ context: field.json({
247
+ isOptional: true,
248
+ description: "Context at assignment time"
249
+ }),
250
+ assignedAt: field.dateTime({ description: "Assignment timestamp" }),
251
+ experiment: field.belongsTo("Experiment", ["experimentId"], ["id"], { onDelete: "Cascade" })
252
+ },
253
+ indexes: [index.unique([
254
+ "experimentId",
255
+ "subjectType",
256
+ "subjectId"
257
+ ], { name: "experiment_assignment_unique" }), index.on(["subjectType", "subjectId"])]
258
+ });
259
+ /**
260
+ * FlagEvaluation entity - evaluation log for analytics.
261
+ */
262
+ const FlagEvaluationEntity = defineEntity({
263
+ name: "FlagEvaluation",
264
+ description: "Log of flag evaluations for debugging and analytics.",
265
+ schema: "lssm_feature_flags",
266
+ map: "flag_evaluation",
267
+ fields: {
268
+ id: field.id({ description: "Unique evaluation identifier" }),
269
+ flagId: field.foreignKey({ description: "Evaluated flag" }),
270
+ flagKey: field.string({ description: "Flag key (denormalized for queries)" }),
271
+ subjectType: field.string({ description: "Subject type (user, org, anonymous)" }),
272
+ subjectId: field.string({ description: "Subject identifier" }),
273
+ result: field.boolean({ description: "Evaluation result" }),
274
+ variant: field.string({
275
+ isOptional: true,
276
+ description: "Served variant (for multivariate)"
277
+ }),
278
+ matchedRuleId: field.string({
279
+ isOptional: true,
280
+ description: "Rule that matched (if any)"
281
+ }),
282
+ reason: field.string({ description: "Evaluation reason (default, rule, experiment, etc.)" }),
283
+ context: field.json({
284
+ isOptional: true,
285
+ description: "Evaluation context"
286
+ }),
287
+ evaluatedAt: field.dateTime({ description: "Evaluation timestamp" }),
288
+ flag: field.belongsTo("FeatureFlag", ["flagId"], ["id"], { onDelete: "Cascade" })
289
+ },
290
+ indexes: [
291
+ index.on(["flagKey", "evaluatedAt"]),
292
+ index.on([
293
+ "subjectType",
294
+ "subjectId",
295
+ "evaluatedAt"
296
+ ]),
297
+ index.on(["flagId", "evaluatedAt"])
298
+ ]
299
+ });
300
+ /**
301
+ * All feature flag entities for schema composition.
302
+ */
303
+ const featureFlagEntities = [
304
+ FeatureFlagEntity,
305
+ FlagTargetingRuleEntity,
306
+ ExperimentEntity,
307
+ ExperimentAssignmentEntity,
308
+ FlagEvaluationEntity
309
+ ];
310
+ /**
311
+ * Module schema contribution for feature flags.
312
+ */
313
+ const featureFlagsSchemaContribution = {
314
+ moduleId: "@lssm/lib.feature-flags",
315
+ entities: featureFlagEntities,
316
+ enums: [
317
+ FlagStatusEnum,
318
+ RuleOperatorEnum,
319
+ ExperimentStatusEnum
320
+ ]
321
+ };
322
+
323
+ //#endregion
324
+ export { ExperimentAssignmentEntity, ExperimentEntity, ExperimentStatusEnum, FeatureFlagEntity, FlagEvaluationEntity, FlagStatusEnum, FlagTargetingRuleEntity, RuleOperatorEnum, featureFlagEntities, featureFlagsSchemaContribution };
325
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","names":["featureFlagsSchemaContribution: ModuleSchemaContribution"],"sources":["../../src/entities/index.ts"],"sourcesContent":["import { defineEntity, defineEntityEnum, field, index } from '@lssm/lib.schema';\nimport type { ModuleSchemaContribution } from '@lssm/lib.schema';\n\n/**\n * Feature flag status enum.\n */\nexport const FlagStatusEnum = defineEntityEnum({\n name: 'FlagStatus',\n values: ['OFF', 'ON', 'GRADUAL'] as const,\n schema: 'lssm_feature_flags',\n description: 'Status of a feature flag.',\n});\n\n/**\n * Targeting rule operator enum.\n */\nexport const RuleOperatorEnum = defineEntityEnum({\n name: 'RuleOperator',\n values: [\n 'EQ',\n 'NEQ',\n 'IN',\n 'NIN',\n 'CONTAINS',\n 'NOT_CONTAINS',\n 'GT',\n 'GTE',\n 'LT',\n 'LTE',\n 'PERCENTAGE',\n ] as const,\n schema: 'lssm_feature_flags',\n description: 'Operator for targeting rule conditions.',\n});\n\n/**\n * Experiment status enum.\n */\nexport const ExperimentStatusEnum = defineEntityEnum({\n name: 'ExperimentStatus',\n values: ['DRAFT', 'RUNNING', 'PAUSED', 'COMPLETED', 'CANCELLED'] as const,\n schema: 'lssm_feature_flags',\n description: 'Status of an experiment.',\n});\n\n/**\n * FeatureFlag entity - defines a feature flag.\n */\nexport const FeatureFlagEntity = defineEntity({\n name: 'FeatureFlag',\n description: 'A feature flag for controlling feature availability.',\n schema: 'lssm_feature_flags',\n map: 'feature_flag',\n fields: {\n id: field.id({ description: 'Unique flag identifier' }),\n key: field.string({\n isUnique: true,\n description: 'Flag key (e.g., new_dashboard)',\n }),\n name: field.string({ description: 'Human-readable name' }),\n description: field.string({\n isOptional: true,\n description: 'Description of the flag',\n }),\n\n // Status and default value\n status: field.enum('FlagStatus', {\n default: 'OFF',\n description: 'Flag status',\n }),\n defaultValue: field.boolean({\n default: false,\n description: 'Default value when no rules match',\n }),\n\n // Multivariate support\n variants: field.json({\n isOptional: true,\n description: 'Variant definitions for multivariate flags',\n }),\n\n // Scope\n orgId: field.string({\n isOptional: true,\n description: 'Organization scope (null = global)',\n }),\n\n // Metadata\n tags: field.json({\n isOptional: true,\n description: 'Tags for categorization',\n }),\n metadata: field.json({\n isOptional: true,\n description: 'Additional metadata',\n }),\n\n // Timestamps\n createdAt: field.createdAt(),\n updatedAt: field.updatedAt(),\n\n // Relations\n targetingRules: field.hasMany('FlagTargetingRule'),\n experiments: field.hasMany('Experiment'),\n evaluations: field.hasMany('FlagEvaluation'),\n },\n indexes: [index.on(['orgId', 'key']), index.on(['status'])],\n enums: [FlagStatusEnum],\n});\n\n/**\n * FlagTargetingRule entity - conditions for targeting.\n */\nexport const FlagTargetingRuleEntity = defineEntity({\n name: 'FlagTargetingRule',\n description: 'A targeting rule for conditional flag evaluation.',\n schema: 'lssm_feature_flags',\n map: 'flag_targeting_rule',\n fields: {\n id: field.id({ description: 'Unique rule identifier' }),\n flagId: field.foreignKey({ description: 'Parent feature flag' }),\n\n // Rule definition\n name: field.string({\n isOptional: true,\n description: 'Rule name for debugging',\n }),\n priority: field.int({\n default: 0,\n description: 'Rule priority (lower = higher priority)',\n }),\n enabled: field.boolean({\n default: true,\n description: 'Whether rule is active',\n }),\n\n // Condition\n attribute: field.string({\n description: 'Target attribute (userId, orgId, plan, segment, etc.)',\n }),\n operator: field.enum('RuleOperator', {\n description: 'Comparison operator',\n }),\n value: field.json({ description: 'Target value(s)' }),\n\n // Result\n rolloutPercentage: field.int({\n isOptional: true,\n description: 'Percentage for gradual rollout (0-100)',\n }),\n serveValue: field.boolean({\n isOptional: true,\n description: 'Boolean value to serve',\n }),\n serveVariant: field.string({\n isOptional: true,\n description: 'Variant key to serve (for multivariate)',\n }),\n\n // Timestamps\n createdAt: field.createdAt(),\n updatedAt: field.updatedAt(),\n\n // Relations\n flag: field.belongsTo('FeatureFlag', ['flagId'], ['id'], {\n onDelete: 'Cascade',\n }),\n },\n indexes: [index.on(['flagId', 'priority']), index.on(['attribute'])],\n enums: [RuleOperatorEnum],\n});\n\n/**\n * Experiment entity - A/B test configuration.\n */\nexport const ExperimentEntity = defineEntity({\n name: 'Experiment',\n description: 'An A/B test experiment.',\n schema: 'lssm_feature_flags',\n map: 'experiment',\n fields: {\n id: field.id({ description: 'Unique experiment identifier' }),\n key: field.string({ isUnique: true, description: 'Experiment key' }),\n name: field.string({ description: 'Human-readable name' }),\n description: field.string({\n isOptional: true,\n description: 'Experiment description',\n }),\n hypothesis: field.string({\n isOptional: true,\n description: 'Experiment hypothesis',\n }),\n\n // Associated flag\n flagId: field.foreignKey({ description: 'Associated feature flag' }),\n\n // Configuration\n status: field.enum('ExperimentStatus', {\n default: 'DRAFT',\n description: 'Experiment status',\n }),\n variants: field.json({\n description: 'Variant definitions with split ratios',\n }),\n metrics: field.json({ isOptional: true, description: 'Metrics to track' }),\n\n // Targeting\n audiencePercentage: field.int({\n default: 100,\n description: 'Percentage of audience to include',\n }),\n audienceFilter: field.json({\n isOptional: true,\n description: 'Audience filter criteria',\n }),\n\n // Timeline\n scheduledStartAt: field.dateTime({\n isOptional: true,\n description: 'Scheduled start time',\n }),\n scheduledEndAt: field.dateTime({\n isOptional: true,\n description: 'Scheduled end time',\n }),\n startedAt: field.dateTime({\n isOptional: true,\n description: 'Actual start time',\n }),\n endedAt: field.dateTime({\n isOptional: true,\n description: 'Actual end time',\n }),\n\n // Results\n winningVariant: field.string({\n isOptional: true,\n description: 'Declared winning variant',\n }),\n results: field.json({\n isOptional: true,\n description: 'Experiment results summary',\n }),\n\n // Scope\n orgId: field.string({\n isOptional: true,\n description: 'Organization scope',\n }),\n\n // Timestamps\n createdAt: field.createdAt(),\n updatedAt: field.updatedAt(),\n\n // Relations\n flag: field.belongsTo('FeatureFlag', ['flagId'], ['id'], {\n onDelete: 'Cascade',\n }),\n assignments: field.hasMany('ExperimentAssignment'),\n },\n indexes: [\n index.on(['status']),\n index.on(['orgId', 'status']),\n index.on(['flagId']),\n ],\n enums: [ExperimentStatusEnum],\n});\n\n/**\n * ExperimentAssignment entity - tracks which variant a subject is assigned to.\n */\nexport const ExperimentAssignmentEntity = defineEntity({\n name: 'ExperimentAssignment',\n description: 'Tracks experiment variant assignments.',\n schema: 'lssm_feature_flags',\n map: 'experiment_assignment',\n fields: {\n id: field.id({ description: 'Unique assignment identifier' }),\n experimentId: field.foreignKey({ description: 'Parent experiment' }),\n\n // Subject\n subjectType: field.string({\n description: 'Subject type (user, org, session)',\n }),\n subjectId: field.string({ description: 'Subject identifier' }),\n\n // Assignment\n variant: field.string({ description: 'Assigned variant key' }),\n bucket: field.int({ description: 'Hash bucket (0-99)' }),\n\n // Context\n context: field.json({\n isOptional: true,\n description: 'Context at assignment time',\n }),\n\n // Timestamps\n assignedAt: field.dateTime({ description: 'Assignment timestamp' }),\n\n // Relations\n experiment: field.belongsTo('Experiment', ['experimentId'], ['id'], {\n onDelete: 'Cascade',\n }),\n },\n indexes: [\n index.unique(['experimentId', 'subjectType', 'subjectId'], {\n name: 'experiment_assignment_unique',\n }),\n index.on(['subjectType', 'subjectId']),\n ],\n});\n\n/**\n * FlagEvaluation entity - evaluation log for analytics.\n */\nexport const FlagEvaluationEntity = defineEntity({\n name: 'FlagEvaluation',\n description: 'Log of flag evaluations for debugging and analytics.',\n schema: 'lssm_feature_flags',\n map: 'flag_evaluation',\n fields: {\n id: field.id({ description: 'Unique evaluation identifier' }),\n flagId: field.foreignKey({ description: 'Evaluated flag' }),\n flagKey: field.string({\n description: 'Flag key (denormalized for queries)',\n }),\n\n // Subject\n subjectType: field.string({\n description: 'Subject type (user, org, anonymous)',\n }),\n subjectId: field.string({ description: 'Subject identifier' }),\n\n // Result\n result: field.boolean({ description: 'Evaluation result' }),\n variant: field.string({\n isOptional: true,\n description: 'Served variant (for multivariate)',\n }),\n\n // Match info\n matchedRuleId: field.string({\n isOptional: true,\n description: 'Rule that matched (if any)',\n }),\n reason: field.string({\n description: 'Evaluation reason (default, rule, experiment, etc.)',\n }),\n\n // Context\n context: field.json({\n isOptional: true,\n description: 'Evaluation context',\n }),\n\n // Timestamps\n evaluatedAt: field.dateTime({ description: 'Evaluation timestamp' }),\n\n // Relations\n flag: field.belongsTo('FeatureFlag', ['flagId'], ['id'], {\n onDelete: 'Cascade',\n }),\n },\n indexes: [\n index.on(['flagKey', 'evaluatedAt']),\n index.on(['subjectType', 'subjectId', 'evaluatedAt']),\n index.on(['flagId', 'evaluatedAt']),\n ],\n});\n\n/**\n * All feature flag entities for schema composition.\n */\nexport const featureFlagEntities = [\n FeatureFlagEntity,\n FlagTargetingRuleEntity,\n ExperimentEntity,\n ExperimentAssignmentEntity,\n FlagEvaluationEntity,\n];\n\n/**\n * Module schema contribution for feature flags.\n */\nexport const featureFlagsSchemaContribution: ModuleSchemaContribution = {\n moduleId: '@lssm/lib.feature-flags',\n entities: featureFlagEntities,\n enums: [FlagStatusEnum, RuleOperatorEnum, ExperimentStatusEnum],\n};\n"],"mappings":"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"}