@zudojs/feature-flags 0.0.1

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 (127) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +40 -0
  3. package/dist/evaluator/evaluator.core.d.ts +20 -0
  4. package/dist/evaluator/evaluator.core.d.ts.map +1 -0
  5. package/dist/evaluator/evaluator.core.js +86 -0
  6. package/dist/evaluator/evaluator.core.js.map +1 -0
  7. package/dist/evaluator/evaluatorAttribute.d.ts +26 -0
  8. package/dist/evaluator/evaluatorAttribute.d.ts.map +1 -0
  9. package/dist/evaluator/evaluatorAttribute.js +84 -0
  10. package/dist/evaluator/evaluatorAttribute.js.map +1 -0
  11. package/dist/evaluator/evaluatorRule.core.d.ts +29 -0
  12. package/dist/evaluator/evaluatorRule.core.d.ts.map +1 -0
  13. package/dist/evaluator/evaluatorRule.core.js +73 -0
  14. package/dist/evaluator/evaluatorRule.core.js.map +1 -0
  15. package/dist/evaluator/index.d.ts +10 -0
  16. package/dist/evaluator/index.d.ts.map +1 -0
  17. package/dist/evaluator/index.js +9 -0
  18. package/dist/evaluator/index.js.map +1 -0
  19. package/dist/featureFlagErrors/featureFlagError.base.d.ts +24 -0
  20. package/dist/featureFlagErrors/featureFlagError.base.d.ts.map +1 -0
  21. package/dist/featureFlagErrors/featureFlagError.base.js +24 -0
  22. package/dist/featureFlagErrors/featureFlagError.base.js.map +1 -0
  23. package/dist/featureFlagErrors/featureFlagError.types.d.ts +38 -0
  24. package/dist/featureFlagErrors/featureFlagError.types.d.ts.map +1 -0
  25. package/dist/featureFlagErrors/featureFlagError.types.js +79 -0
  26. package/dist/featureFlagErrors/featureFlagError.types.js.map +1 -0
  27. package/dist/featureFlagErrors/index.d.ts +9 -0
  28. package/dist/featureFlagErrors/index.d.ts.map +1 -0
  29. package/dist/featureFlagErrors/index.js +8 -0
  30. package/dist/featureFlagErrors/index.js.map +1 -0
  31. package/dist/featureFlagTypes/featureFlag.interface.d.ts +50 -0
  32. package/dist/featureFlagTypes/featureFlag.interface.d.ts.map +1 -0
  33. package/dist/featureFlagTypes/featureFlag.interface.js +9 -0
  34. package/dist/featureFlagTypes/featureFlag.interface.js.map +1 -0
  35. package/dist/featureFlagTypes/featureFlagContext.d.ts +21 -0
  36. package/dist/featureFlagTypes/featureFlagContext.d.ts.map +1 -0
  37. package/dist/featureFlagTypes/featureFlagContext.js +9 -0
  38. package/dist/featureFlagTypes/featureFlagContext.js.map +1 -0
  39. package/dist/featureFlagTypes/featureFlagEvaluation.d.ts +26 -0
  40. package/dist/featureFlagTypes/featureFlagEvaluation.d.ts.map +1 -0
  41. package/dist/featureFlagTypes/featureFlagEvaluation.js +9 -0
  42. package/dist/featureFlagTypes/featureFlagEvaluation.js.map +1 -0
  43. package/dist/featureFlagTypes/featureFlagProvider.d.ts +24 -0
  44. package/dist/featureFlagTypes/featureFlagProvider.d.ts.map +1 -0
  45. package/dist/featureFlagTypes/featureFlagProvider.js +9 -0
  46. package/dist/featureFlagTypes/featureFlagProvider.js.map +1 -0
  47. package/dist/featureFlagTypes/featureFlagRule/featureFlagRule.type.d.ts +60 -0
  48. package/dist/featureFlagTypes/featureFlagRule/featureFlagRule.type.d.ts.map +1 -0
  49. package/dist/featureFlagTypes/featureFlagRule/featureFlagRule.type.js +9 -0
  50. package/dist/featureFlagTypes/featureFlagRule/featureFlagRule.type.js.map +1 -0
  51. package/dist/featureFlagTypes/featureFlagRule/featureFlagValue.type.d.ts +14 -0
  52. package/dist/featureFlagTypes/featureFlagRule/featureFlagValue.type.d.ts.map +1 -0
  53. package/dist/featureFlagTypes/featureFlagRule/featureFlagValue.type.js +9 -0
  54. package/dist/featureFlagTypes/featureFlagRule/featureFlagValue.type.js.map +1 -0
  55. package/dist/featureFlagTypes/featureFlagRule/index.d.ts +8 -0
  56. package/dist/featureFlagTypes/featureFlagRule/index.d.ts.map +1 -0
  57. package/dist/featureFlagTypes/featureFlagRule/index.js +8 -0
  58. package/dist/featureFlagTypes/featureFlagRule/index.js.map +1 -0
  59. package/dist/featureFlagTypes/index.d.ts +9 -0
  60. package/dist/featureFlagTypes/index.d.ts.map +1 -0
  61. package/dist/featureFlagTypes/index.js +5 -0
  62. package/dist/featureFlagTypes/index.js.map +1 -0
  63. package/dist/featureFlags/featureFlags.core.d.ts +37 -0
  64. package/dist/featureFlags/featureFlags.core.d.ts.map +1 -0
  65. package/dist/featureFlags/featureFlags.core.js +101 -0
  66. package/dist/featureFlags/featureFlags.core.js.map +1 -0
  67. package/dist/featureFlags/featureFlags.resolve.d.ts +21 -0
  68. package/dist/featureFlags/featureFlags.resolve.d.ts.map +1 -0
  69. package/dist/featureFlags/featureFlags.resolve.js +44 -0
  70. package/dist/featureFlags/featureFlags.resolve.js.map +1 -0
  71. package/dist/featureFlags/index.d.ts +8 -0
  72. package/dist/featureFlags/index.d.ts.map +1 -0
  73. package/dist/featureFlags/index.js +7 -0
  74. package/dist/featureFlags/index.js.map +1 -0
  75. package/dist/index.d.ts +29 -0
  76. package/dist/index.d.ts.map +1 -0
  77. package/dist/index.js +29 -0
  78. package/dist/index.js.map +1 -0
  79. package/dist/provider/index.d.ts +12 -0
  80. package/dist/provider/index.d.ts.map +1 -0
  81. package/dist/provider/index.js +10 -0
  82. package/dist/provider/index.js.map +1 -0
  83. package/dist/provider/providerCached.core.d.ts +22 -0
  84. package/dist/provider/providerCached.core.d.ts.map +1 -0
  85. package/dist/provider/providerCached.core.js +45 -0
  86. package/dist/provider/providerCached.core.js.map +1 -0
  87. package/dist/provider/providerComposite.core.d.ts +19 -0
  88. package/dist/provider/providerComposite.core.d.ts.map +1 -0
  89. package/dist/provider/providerComposite.core.js +48 -0
  90. package/dist/provider/providerComposite.core.js.map +1 -0
  91. package/dist/provider/providerEnvironment.core.d.ts +25 -0
  92. package/dist/provider/providerEnvironment.core.d.ts.map +1 -0
  93. package/dist/provider/providerEnvironment.core.js +63 -0
  94. package/dist/provider/providerEnvironment.core.js.map +1 -0
  95. package/dist/provider/providerMemory.core.d.ts +17 -0
  96. package/dist/provider/providerMemory.core.d.ts.map +1 -0
  97. package/dist/provider/providerMemory.core.js +36 -0
  98. package/dist/provider/providerMemory.core.js.map +1 -0
  99. package/dist/registry/index.d.ts +8 -0
  100. package/dist/registry/index.d.ts.map +1 -0
  101. package/dist/registry/index.js +7 -0
  102. package/dist/registry/index.js.map +1 -0
  103. package/dist/registry/registry.core.d.ts +35 -0
  104. package/dist/registry/registry.core.d.ts.map +1 -0
  105. package/dist/registry/registry.core.js +47 -0
  106. package/dist/registry/registry.core.js.map +1 -0
  107. package/dist/rollout/index.d.ts +8 -0
  108. package/dist/rollout/index.d.ts.map +1 -0
  109. package/dist/rollout/index.js +8 -0
  110. package/dist/rollout/index.js.map +1 -0
  111. package/dist/rollout/rolloutBucketing.d.ts +27 -0
  112. package/dist/rollout/rolloutBucketing.d.ts.map +1 -0
  113. package/dist/rollout/rolloutBucketing.js +42 -0
  114. package/dist/rollout/rolloutBucketing.js.map +1 -0
  115. package/dist/rollout/rolloutHashing.d.ts +15 -0
  116. package/dist/rollout/rolloutHashing.d.ts.map +1 -0
  117. package/dist/rollout/rolloutHashing.js +26 -0
  118. package/dist/rollout/rolloutHashing.js.map +1 -0
  119. package/dist/utils/index.d.ts +7 -0
  120. package/dist/utils/index.d.ts.map +1 -0
  121. package/dist/utils/index.js +7 -0
  122. package/dist/utils/index.js.map +1 -0
  123. package/dist/utils/utils.helper.d.ts +15 -0
  124. package/dist/utils/utils.helper.d.ts.map +1 -0
  125. package/dist/utils/utils.helper.js +27 -0
  126. package/dist/utils/utils.helper.js.map +1 -0
  127. package/package.json +49 -0
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Deterministic bucketing for percentage rollouts.
3
+ *
4
+ * Maps a (flag key, subject) pair to a bucket in [0, buckets).
5
+ * Supports sub-percent precision with 10,000 buckets.
6
+ *
7
+ * @module rollout/rolloutBucketing
8
+ */
9
+ import { hashString } from "./rolloutHashing.js";
10
+ /** Default number of buckets — 10,000 allows 0.01% precision. */
11
+ const DEFAULT_BUCKETS = 10_000;
12
+ /**
13
+ * Compute a deterministic bucket for a flag rollout.
14
+ *
15
+ * @param key - The feature flag key.
16
+ * @param subject - The subject identifier (e.g. userId, tenantId).
17
+ * @param buckets - Total number of buckets (default 10,000).
18
+ * @returns A bucket number in [0, buckets).
19
+ */
20
+ export function getBucket(key, subject, buckets = DEFAULT_BUCKETS) {
21
+ const hash = hashString(`${key}:${subject}`);
22
+ return hash % buckets;
23
+ }
24
+ /**
25
+ * Check whether a subject falls within a percentage rollout.
26
+ *
27
+ * @param key - The feature flag key.
28
+ * @param subject - The subject identifier.
29
+ * @param percentage - Percentage from 0 to 100 (supports decimals like 25.5).
30
+ * @returns Whether the subject is in the rollout.
31
+ */
32
+ export function isInRollout(key, subject, percentage) {
33
+ if (percentage <= 0)
34
+ return false;
35
+ if (percentage >= 100)
36
+ return true;
37
+ const buckets = 10_000;
38
+ const threshold = Math.round((percentage / 100) * buckets);
39
+ const bucket = getBucket(key, subject, buckets);
40
+ return bucket < threshold;
41
+ }
42
+ //# sourceMappingURL=rolloutBucketing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rolloutBucketing.js","sourceRoot":"","sources":["../../src/rollout/rolloutBucketing.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEjD,iEAAiE;AACjE,MAAM,eAAe,GAAG,MAAM,CAAC;AAE/B;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS,CACvB,GAAW,EACX,OAAe,EACf,OAAO,GAAW,eAAe;IAEjC,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,GAAG,IAAI,OAAO,EAAE,CAAC,CAAC;IAC7C,OAAO,IAAI,GAAG,OAAO,CAAC;AACxB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CACzB,GAAW,EACX,OAAe,EACf,UAAkB;IAElB,IAAI,UAAU,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAClC,IAAI,UAAU,IAAI,GAAG;QAAE,OAAO,IAAI,CAAC;IAEnC,MAAM,OAAO,GAAG,MAAM,CAAC;IACvB,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,UAAU,GAAG,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC;IAC3D,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAChD,OAAO,MAAM,GAAG,SAAS,CAAC;AAC5B,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Deterministic string hashing using FNV-1a.
3
+ *
4
+ * Used for sticky percentage rollouts — same input always produces the same bucket.
5
+ *
6
+ * @module rollout/rolloutHashing
7
+ */
8
+ /**
9
+ * Compute a deterministic 32-bit unsigned hash of a string using FNV-1a.
10
+ *
11
+ * @param value - The string to hash.
12
+ * @returns An unsigned 32-bit integer hash.
13
+ */
14
+ export declare function hashString(value: string): number;
15
+ //# sourceMappingURL=rolloutHashing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rolloutHashing.d.ts","sourceRoot":"","sources":["../../src/rollout/rolloutHashing.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAQH;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAShD"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Deterministic string hashing using FNV-1a.
3
+ *
4
+ * Used for sticky percentage rollouts — same input always produces the same bucket.
5
+ *
6
+ * @module rollout/rolloutHashing
7
+ */
8
+ /** FNV offset basis (32-bit). */
9
+ const FNV_OFFSET_BASIS = 2166136261;
10
+ /** FNV prime (32-bit). */
11
+ const FNV_PRIME = 16777619;
12
+ /**
13
+ * Compute a deterministic 32-bit unsigned hash of a string using FNV-1a.
14
+ *
15
+ * @param value - The string to hash.
16
+ * @returns An unsigned 32-bit integer hash.
17
+ */
18
+ export function hashString(value) {
19
+ let hash = FNV_OFFSET_BASIS;
20
+ for (let i = 0; i < value.length; i++) {
21
+ hash ^= value.charCodeAt(i);
22
+ hash = Math.imul(hash, FNV_PRIME);
23
+ }
24
+ return hash >>> 0;
25
+ }
26
+ //# sourceMappingURL=rolloutHashing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rolloutHashing.js","sourceRoot":"","sources":["../../src/rollout/rolloutHashing.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,iCAAiC;AACjC,MAAM,gBAAgB,GAAG,UAAU,CAAC;AAEpC,0BAA0B;AAC1B,MAAM,SAAS,GAAG,QAAQ,CAAC;AAE3B;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,KAAa;IACtC,IAAI,IAAI,GAAG,gBAAgB,CAAC;IAE5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,IAAI,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAC5B,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IACpC,CAAC;IAED,OAAO,IAAI,KAAK,CAAC,CAAC;AACpB,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Feature flag utility helpers.
3
+ *
4
+ * @module utils
5
+ */
6
+ export { isPlainObject, valuesEqual } from "./utils.helper.js";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Feature flag utility helpers.
3
+ *
4
+ * @module utils
5
+ */
6
+ export { isPlainObject, valuesEqual } from "./utils.helper.js";
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Utility helpers for feature flags.
3
+ *
4
+ * @module utils/utils
5
+ */
6
+ import type { FeatureFlagValue } from "../featureFlagTypes/featureFlagRule/featureFlagValue.type.js";
7
+ /**
8
+ * Check if a value is a plain object (not null, not array).
9
+ */
10
+ export declare function isPlainObject(value: unknown): value is Record<string, unknown>;
11
+ /**
12
+ * Check if two feature flag values are equal.
13
+ */
14
+ export declare function valuesEqual(a: FeatureFlagValue, b: FeatureFlagValue): boolean;
15
+ //# sourceMappingURL=utils.helper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.helper.d.ts","sourceRoot":"","sources":["../../src/utils/utils.helper.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8DAA8D,CAAC;AAErG;;GAEG;AACH,wBAAgB,aAAa,CAC3B,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAElC;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,gBAAgB,EAAE,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAQ7E"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Utility helpers for feature flags.
3
+ *
4
+ * @module utils/utils
5
+ */
6
+ /**
7
+ * Check if a value is a plain object (not null, not array).
8
+ */
9
+ export function isPlainObject(value) {
10
+ return typeof value === "object" && value !== null && !Array.isArray(value);
11
+ }
12
+ /**
13
+ * Check if two feature flag values are equal.
14
+ */
15
+ export function valuesEqual(a, b) {
16
+ if (a === b)
17
+ return true;
18
+ if (a === null || b === null)
19
+ return false;
20
+ if (typeof a !== typeof b)
21
+ return false;
22
+ if (typeof a === "object" && typeof b === "object") {
23
+ return JSON.stringify(a) === JSON.stringify(b);
24
+ }
25
+ return false;
26
+ }
27
+ //# sourceMappingURL=utils.helper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.helper.js","sourceRoot":"","sources":["../../src/utils/utils.helper.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;GAEG;AACH,MAAM,UAAU,aAAa,CAC3B,KAAc;IAEd,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,CAAmB,EAAE,CAAmB;IAClE,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACzB,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC3C,IAAI,OAAO,CAAC,KAAK,OAAO,CAAC;QAAE,OAAO,KAAK,CAAC;IACxC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;QACnD,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IACjD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@zudojs/feature-flags",
3
+ "version": "0.0.1",
4
+ "description": "Feature flag system with deterministic rollouts, rule engine, providers, variants, snapshots, and evaluation context.",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "import": "./dist/index.js",
10
+ "types": "./dist/index.d.ts"
11
+ }
12
+ },
13
+ "dependencies": {
14
+ "@zudojs/errors": "0.0.1"
15
+ },
16
+ "devDependencies": {
17
+ "typescript": "^7.0.2",
18
+ "vitest": "^4.1.11"
19
+ },
20
+ "license": "MIT",
21
+ "type": "module",
22
+ "files": [
23
+ "dist"
24
+ ],
25
+ "publishConfig": {
26
+ "access": "public"
27
+ },
28
+ "engines": {
29
+ "node": ">=24.0.0"
30
+ },
31
+ "module": "./dist/index.js",
32
+ "keywords": [
33
+ "zudojs",
34
+ "feature-flags",
35
+ "rollout",
36
+ "a-b-testing"
37
+ ],
38
+ "homepage": "https://github.com/oyinlola-tech/zudo#readme",
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "https://github.com/oyinlola-tech/zudo"
42
+ },
43
+ "scripts": {
44
+ "build": "tsc -p tsconfig.json",
45
+ "typecheck": "tsc -p tsconfig.json --noEmit",
46
+ "test": "vitest run",
47
+ "test:watch": "vitest"
48
+ }
49
+ }