flagsmith-nodejs 3.3.3 → 4.0.0-beta.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 (190) hide show
  1. package/.github/workflows/publish.yml +2 -2
  2. package/.github/workflows/pull_request.yaml +3 -4
  3. package/build/{flagsmith-engine → cjs/flagsmith-engine}/environments/models.d.ts +3 -3
  4. package/build/{flagsmith-engine → cjs/flagsmith-engine}/environments/models.js +20 -13
  5. package/build/{flagsmith-engine → cjs/flagsmith-engine}/environments/util.d.ts +1 -1
  6. package/build/cjs/flagsmith-engine/environments/util.js +23 -0
  7. package/build/cjs/flagsmith-engine/features/models.js +118 -0
  8. package/build/{flagsmith-engine → cjs/flagsmith-engine}/features/util.d.ts +1 -1
  9. package/build/cjs/flagsmith-engine/features/util.js +27 -0
  10. package/build/{flagsmith-engine → cjs/flagsmith-engine}/identities/models.d.ts +2 -2
  11. package/build/cjs/flagsmith-engine/identities/models.js +48 -0
  12. package/build/{flagsmith-engine → cjs/flagsmith-engine}/identities/traits/models.js +5 -4
  13. package/build/{flagsmith-engine → cjs/flagsmith-engine}/identities/util.d.ts +2 -2
  14. package/build/cjs/flagsmith-engine/identities/util.js +22 -0
  15. package/build/cjs/flagsmith-engine/index.d.ts +14 -0
  16. package/build/cjs/flagsmith-engine/index.js +75 -0
  17. package/build/cjs/flagsmith-engine/organisations/models.js +21 -0
  18. package/build/{flagsmith-engine → cjs/flagsmith-engine}/organisations/util.d.ts +1 -1
  19. package/build/cjs/flagsmith-engine/organisations/util.js +8 -0
  20. package/build/{flagsmith-engine → cjs/flagsmith-engine}/projects/models.d.ts +2 -2
  21. package/build/{flagsmith-engine → cjs/flagsmith-engine}/projects/models.js +8 -5
  22. package/build/{flagsmith-engine → cjs/flagsmith-engine}/projects/util.d.ts +1 -1
  23. package/build/cjs/flagsmith-engine/projects/util.js +15 -0
  24. package/build/{flagsmith-engine → cjs/flagsmith-engine}/segments/evaluators.d.ts +4 -4
  25. package/build/cjs/flagsmith-engine/segments/evaluators.js +37 -0
  26. package/build/{flagsmith-engine → cjs/flagsmith-engine}/segments/models.d.ts +1 -1
  27. package/build/cjs/flagsmith-engine/segments/models.js +114 -0
  28. package/build/{flagsmith-engine → cjs/flagsmith-engine}/segments/util.d.ts +1 -1
  29. package/build/{flagsmith-engine → cjs/flagsmith-engine}/segments/util.js +9 -11
  30. package/build/{flagsmith-engine → cjs/flagsmith-engine}/utils/collections.d.ts +1 -1
  31. package/build/cjs/flagsmith-engine/utils/collections.js +6 -0
  32. package/build/cjs/flagsmith-engine/utils/errors.js +6 -0
  33. package/build/{flagsmith-engine → cjs/flagsmith-engine}/utils/hashing/index.js +8 -11
  34. package/build/{flagsmith-engine → cjs/flagsmith-engine}/utils/index.js +5 -5
  35. package/build/{index.d.ts → cjs/index.d.ts} +3 -3
  36. package/build/{index.js → cjs/index.js} +17 -17
  37. package/build/cjs/package.json +1 -0
  38. package/build/{sdk → cjs/sdk}/analytics.d.ts +3 -0
  39. package/build/cjs/sdk/analytics.js +73 -0
  40. package/build/cjs/sdk/errors.js +9 -0
  41. package/build/{sdk → cjs/sdk}/index.d.ts +19 -18
  42. package/build/cjs/sdk/index.js +400 -0
  43. package/build/{sdk → cjs/sdk}/models.d.ts +2 -2
  44. package/build/cjs/sdk/models.js +101 -0
  45. package/build/{sdk → cjs/sdk}/offline_handlers.d.ts +1 -1
  46. package/build/cjs/sdk/offline_handlers.js +46 -0
  47. package/build/{sdk → cjs/sdk}/polling_manager.d.ts +1 -1
  48. package/build/cjs/sdk/polling_manager.js +29 -0
  49. package/build/{sdk → cjs/sdk}/types.d.ts +15 -7
  50. package/build/cjs/sdk/utils.d.ts +36 -0
  51. package/build/cjs/sdk/utils.js +63 -0
  52. package/build/esm/flagsmith-engine/environments/models.d.ts +22 -0
  53. package/build/esm/flagsmith-engine/environments/models.js +32 -0
  54. package/build/esm/flagsmith-engine/environments/util.d.ts +3 -0
  55. package/build/esm/flagsmith-engine/environments/util.js +18 -0
  56. package/build/esm/flagsmith-engine/features/constants.d.ts +4 -0
  57. package/build/esm/flagsmith-engine/features/constants.js +4 -0
  58. package/build/esm/flagsmith-engine/features/models.d.ts +37 -0
  59. package/build/esm/flagsmith-engine/features/models.js +110 -0
  60. package/build/esm/flagsmith-engine/features/util.d.ts +4 -0
  61. package/build/esm/flagsmith-engine/features/util.js +21 -0
  62. package/build/esm/flagsmith-engine/identities/models.d.ts +15 -0
  63. package/build/esm/flagsmith-engine/identities/models.js +44 -0
  64. package/build/esm/flagsmith-engine/identities/traits/models.d.ts +5 -0
  65. package/build/esm/flagsmith-engine/identities/traits/models.js +8 -0
  66. package/build/esm/flagsmith-engine/identities/util.d.ts +4 -0
  67. package/build/esm/flagsmith-engine/identities/util.js +17 -0
  68. package/build/esm/flagsmith-engine/index.d.ts +14 -0
  69. package/build/esm/flagsmith-engine/index.js +62 -0
  70. package/build/esm/flagsmith-engine/organisations/models.d.ts +9 -0
  71. package/build/esm/flagsmith-engine/organisations/models.js +17 -0
  72. package/build/esm/flagsmith-engine/organisations/util.d.ts +2 -0
  73. package/build/esm/flagsmith-engine/organisations/util.js +4 -0
  74. package/build/esm/flagsmith-engine/projects/models.d.ts +10 -0
  75. package/build/esm/flagsmith-engine/projects/models.js +13 -0
  76. package/build/esm/flagsmith-engine/projects/util.d.ts +2 -0
  77. package/build/esm/flagsmith-engine/projects/util.js +11 -0
  78. package/build/esm/flagsmith-engine/segments/constants.d.ts +34 -0
  79. package/build/esm/flagsmith-engine/segments/constants.js +36 -0
  80. package/build/esm/flagsmith-engine/segments/evaluators.d.ts +7 -0
  81. package/build/esm/flagsmith-engine/segments/evaluators.js +31 -0
  82. package/build/esm/flagsmith-engine/segments/models.d.ts +37 -0
  83. package/build/esm/flagsmith-engine/segments/models.js +102 -0
  84. package/build/esm/flagsmith-engine/segments/util.d.ts +6 -0
  85. package/build/esm/flagsmith-engine/segments/util.js +23 -0
  86. package/build/esm/flagsmith-engine/utils/collections.d.ts +3 -0
  87. package/build/esm/flagsmith-engine/utils/collections.js +2 -0
  88. package/build/esm/flagsmith-engine/utils/errors.d.ts +2 -0
  89. package/build/esm/flagsmith-engine/utils/errors.js +2 -0
  90. package/build/esm/flagsmith-engine/utils/hashing/index.d.ts +9 -0
  91. package/build/esm/flagsmith-engine/utils/hashing/index.js +50 -0
  92. package/build/esm/flagsmith-engine/utils/index.d.ts +1 -0
  93. package/build/esm/flagsmith-engine/utils/index.js +13 -0
  94. package/build/esm/index.d.ts +3 -0
  95. package/build/esm/index.js +4 -0
  96. package/build/esm/sdk/analytics.d.ts +35 -0
  97. package/build/esm/sdk/analytics.js +69 -0
  98. package/build/esm/sdk/errors.d.ts +4 -0
  99. package/build/esm/sdk/errors.js +4 -0
  100. package/build/esm/sdk/index.d.ts +131 -0
  101. package/build/esm/sdk/index.js +390 -0
  102. package/build/esm/sdk/models.d.ts +55 -0
  103. package/build/esm/sdk/models.js +94 -0
  104. package/build/esm/sdk/offline_handlers.d.ts +9 -0
  105. package/build/esm/sdk/offline_handlers.js +18 -0
  106. package/build/esm/sdk/polling_manager.d.ts +9 -0
  107. package/build/esm/sdk/polling_manager.js +25 -0
  108. package/build/esm/sdk/types.d.ts +38 -0
  109. package/build/esm/sdk/types.js +1 -0
  110. package/build/esm/sdk/utils.d.ts +36 -0
  111. package/build/esm/sdk/utils.js +56 -0
  112. package/flagsmith-engine/environments/models.ts +3 -3
  113. package/flagsmith-engine/environments/util.ts +4 -4
  114. package/flagsmith-engine/features/models.ts +1 -1
  115. package/flagsmith-engine/features/util.ts +1 -1
  116. package/flagsmith-engine/identities/models.ts +3 -4
  117. package/flagsmith-engine/identities/traits/models.ts +0 -1
  118. package/flagsmith-engine/identities/util.ts +4 -4
  119. package/flagsmith-engine/index.ts +13 -13
  120. package/flagsmith-engine/organisations/util.ts +1 -1
  121. package/flagsmith-engine/projects/models.ts +2 -2
  122. package/flagsmith-engine/projects/util.ts +4 -4
  123. package/flagsmith-engine/segments/evaluators.ts +6 -6
  124. package/flagsmith-engine/segments/models.ts +4 -4
  125. package/flagsmith-engine/segments/util.ts +3 -3
  126. package/flagsmith-engine/utils/collections.ts +1 -1
  127. package/flagsmith-engine/utils/index.ts +1 -1
  128. package/index.ts +4 -4
  129. package/package.json +21 -9
  130. package/sdk/analytics.ts +7 -5
  131. package/sdk/index.ts +55 -46
  132. package/sdk/models.ts +2 -3
  133. package/sdk/offline_handlers.ts +2 -2
  134. package/sdk/polling_manager.ts +2 -3
  135. package/sdk/types.ts +35 -24
  136. package/sdk/utils.ts +49 -37
  137. package/tests/engine/e2e/engine.test.ts +5 -5
  138. package/tests/engine/unit/engine.test.ts +5 -5
  139. package/tests/engine/unit/segments/segment_evaluators.test.ts +9 -9
  140. package/tests/engine/unit/utils/utils.test.ts +1 -1
  141. package/tests/sdk/analytics.test.ts +8 -13
  142. package/tests/sdk/data/identity-with-transient-traits.json +41 -0
  143. package/tests/sdk/data/transient-identity.json +29 -0
  144. package/tests/sdk/flagsmith-cache.test.ts +16 -32
  145. package/tests/sdk/flagsmith-environment-flags.test.ts +21 -36
  146. package/tests/sdk/flagsmith-identity-flags.test.ts +83 -32
  147. package/tests/sdk/flagsmith.test.ts +67 -99
  148. package/tests/sdk/offline-handlers.test.ts +4 -5
  149. package/tests/sdk/polling.test.ts +6 -8
  150. package/tests/sdk/utils.ts +19 -15
  151. package/tsconfig.cjs.json +7 -0
  152. package/tsconfig.esm.json +7 -0
  153. package/tsconfig.json +7 -3
  154. package/vitest.config.ts +17 -0
  155. package/build/flagsmith-engine/environments/util.js +0 -27
  156. package/build/flagsmith-engine/features/models.js +0 -132
  157. package/build/flagsmith-engine/features/util.js +0 -27
  158. package/build/flagsmith-engine/identities/models.js +0 -113
  159. package/build/flagsmith-engine/identities/util.js +0 -46
  160. package/build/flagsmith-engine/index.d.ts +0 -14
  161. package/build/flagsmith-engine/index.js +0 -127
  162. package/build/flagsmith-engine/organisations/models.js +0 -21
  163. package/build/flagsmith-engine/organisations/util.js +0 -8
  164. package/build/flagsmith-engine/projects/util.js +0 -15
  165. package/build/flagsmith-engine/segments/evaluators.js +0 -45
  166. package/build/flagsmith-engine/segments/models.js +0 -147
  167. package/build/flagsmith-engine/utils/collections.js +0 -26
  168. package/build/flagsmith-engine/utils/errors.js +0 -26
  169. package/build/sdk/analytics.js +0 -120
  170. package/build/sdk/errors.js +0 -34
  171. package/build/sdk/index.js +0 -594
  172. package/build/sdk/models.js +0 -149
  173. package/build/sdk/offline_handlers.js +0 -66
  174. package/build/sdk/polling_manager.js +0 -72
  175. package/build/sdk/utils.d.ts +0 -12
  176. package/build/sdk/utils.js +0 -107
  177. package/jest.config.js +0 -5
  178. package/tests/index.js +0 -0
  179. /package/build/{flagsmith-engine → cjs/flagsmith-engine}/features/constants.d.ts +0 -0
  180. /package/build/{flagsmith-engine → cjs/flagsmith-engine}/features/constants.js +0 -0
  181. /package/build/{flagsmith-engine → cjs/flagsmith-engine}/features/models.d.ts +0 -0
  182. /package/build/{flagsmith-engine → cjs/flagsmith-engine}/identities/traits/models.d.ts +0 -0
  183. /package/build/{flagsmith-engine → cjs/flagsmith-engine}/organisations/models.d.ts +0 -0
  184. /package/build/{flagsmith-engine → cjs/flagsmith-engine}/segments/constants.d.ts +0 -0
  185. /package/build/{flagsmith-engine → cjs/flagsmith-engine}/segments/constants.js +0 -0
  186. /package/build/{flagsmith-engine → cjs/flagsmith-engine}/utils/errors.d.ts +0 -0
  187. /package/build/{flagsmith-engine → cjs/flagsmith-engine}/utils/hashing/index.d.ts +0 -0
  188. /package/build/{flagsmith-engine → cjs/flagsmith-engine}/utils/index.d.ts +0 -0
  189. /package/build/{sdk → cjs/sdk}/errors.d.ts +0 -0
  190. /package/build/{sdk → cjs/sdk}/types.js +0 -0
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.retryFetch = exports.delay = exports.generateIdentitiesData = exports.isTraitConfig = void 0;
4
+ function isTraitConfig(traitValue) {
5
+ return !!traitValue && typeof traitValue == 'object' && traitValue.value !== undefined;
6
+ }
7
+ exports.isTraitConfig = isTraitConfig;
8
+ function generateIdentitiesData(identifier, traits, transient) {
9
+ const traitsGenerated = Object.entries(traits).map(([key, value]) => {
10
+ if (isTraitConfig(value)) {
11
+ return {
12
+ trait_key: key,
13
+ trait_value: value?.value,
14
+ transient: value?.transient,
15
+ };
16
+ }
17
+ else {
18
+ return {
19
+ trait_key: key,
20
+ trait_value: value,
21
+ };
22
+ }
23
+ });
24
+ if (transient) {
25
+ return {
26
+ identifier: identifier,
27
+ traits: traitsGenerated,
28
+ transient: true
29
+ };
30
+ }
31
+ return {
32
+ identifier: identifier,
33
+ traits: traitsGenerated
34
+ };
35
+ }
36
+ exports.generateIdentitiesData = generateIdentitiesData;
37
+ const delay = (ms) => new Promise(resolve => setTimeout(() => resolve(undefined), ms));
38
+ exports.delay = delay;
39
+ const retryFetch = (url,
40
+ // built-in RequestInit type doesn't have dispatcher/agent
41
+ fetchOptions, retries = 3, timeoutMs = 10, // set an overall timeout for this function
42
+ customFetch) => {
43
+ return new Promise((resolve, reject) => {
44
+ const retryWrapper = (n) => {
45
+ customFetch(url, {
46
+ ...fetchOptions,
47
+ signal: AbortSignal.timeout(timeoutMs)
48
+ })
49
+ .then(res => resolve(res))
50
+ .catch(async (err) => {
51
+ if (n > 0) {
52
+ await (0, exports.delay)(1000);
53
+ retryWrapper(--n);
54
+ }
55
+ else {
56
+ reject(err);
57
+ }
58
+ });
59
+ };
60
+ retryWrapper(retries);
61
+ });
62
+ };
63
+ exports.retryFetch = retryFetch;
@@ -0,0 +1,22 @@
1
+ import { FeatureStateModel } from '../features/models.js';
2
+ import { IdentityModel } from '../identities/models.js';
3
+ import { ProjectModel } from '../projects/models.js';
4
+ export declare class EnvironmentAPIKeyModel {
5
+ id: number;
6
+ key: string;
7
+ createdAt: number;
8
+ name: string;
9
+ clientApiKey: string;
10
+ expiresAt?: number;
11
+ active: boolean;
12
+ constructor(id: number, key: string, createdAt: number, name: string, clientApiKey: string, expiresAt?: number);
13
+ isValid(): boolean;
14
+ }
15
+ export declare class EnvironmentModel {
16
+ id: number;
17
+ apiKey: string;
18
+ project: ProjectModel;
19
+ featureStates: FeatureStateModel[];
20
+ identityOverrides: IdentityModel[];
21
+ constructor(id: number, apiKey: string, project: ProjectModel);
22
+ }
@@ -0,0 +1,32 @@
1
+ export class EnvironmentAPIKeyModel {
2
+ id;
3
+ key;
4
+ createdAt;
5
+ name;
6
+ clientApiKey;
7
+ expiresAt;
8
+ active = true;
9
+ constructor(id, key, createdAt, name, clientApiKey, expiresAt) {
10
+ this.id = id;
11
+ this.key = key;
12
+ this.createdAt = createdAt;
13
+ this.name = name;
14
+ this.clientApiKey = clientApiKey;
15
+ this.expiresAt = expiresAt;
16
+ }
17
+ isValid() {
18
+ return !!this.active && (!this.expiresAt || this.expiresAt > Date.now());
19
+ }
20
+ }
21
+ export class EnvironmentModel {
22
+ id;
23
+ apiKey;
24
+ project;
25
+ featureStates = [];
26
+ identityOverrides = [];
27
+ constructor(id, apiKey, project) {
28
+ this.id = id;
29
+ this.apiKey = apiKey;
30
+ this.project = project;
31
+ }
32
+ }
@@ -0,0 +1,3 @@
1
+ import { EnvironmentAPIKeyModel, EnvironmentModel } from './models.js';
2
+ export declare function buildEnvironmentModel(environmentJSON: any): EnvironmentModel;
3
+ export declare function buildEnvironmentAPIKeyModel(apiKeyJSON: any): EnvironmentAPIKeyModel;
@@ -0,0 +1,18 @@
1
+ import { buildFeatureStateModel } from '../features/util.js';
2
+ import { buildIdentityModel } from '../identities/util.js';
3
+ import { buildProjectModel } from '../projects/util.js';
4
+ import { EnvironmentAPIKeyModel, EnvironmentModel } from './models.js';
5
+ export function buildEnvironmentModel(environmentJSON) {
6
+ const project = buildProjectModel(environmentJSON.project);
7
+ const featureStates = environmentJSON.feature_states.map((fs) => buildFeatureStateModel(fs));
8
+ const environmentModel = new EnvironmentModel(environmentJSON.id, environmentJSON.api_key, project);
9
+ environmentModel.featureStates = featureStates;
10
+ if (!!environmentJSON.identity_overrides) {
11
+ environmentModel.identityOverrides = environmentJSON.identity_overrides.map((identityData) => buildIdentityModel(identityData));
12
+ }
13
+ return environmentModel;
14
+ }
15
+ export function buildEnvironmentAPIKeyModel(apiKeyJSON) {
16
+ const model = new EnvironmentAPIKeyModel(apiKeyJSON.id, apiKeyJSON.key, Date.parse(apiKeyJSON.created_at), apiKeyJSON.name, apiKeyJSON.client_api_key);
17
+ return model;
18
+ }
@@ -0,0 +1,4 @@
1
+ export declare const CONSTANTS: {
2
+ STANDARD: string;
3
+ MULTIVARIATE: string;
4
+ };
@@ -0,0 +1,4 @@
1
+ export const CONSTANTS = {
2
+ STANDARD: 'STANDARD',
3
+ MULTIVARIATE: 'MULTIVARIATE'
4
+ };
@@ -0,0 +1,37 @@
1
+ export declare class FeatureModel {
2
+ id: number;
3
+ name: string;
4
+ type: string;
5
+ constructor(id: number, name: string, type: string);
6
+ eq(other: FeatureModel): boolean;
7
+ }
8
+ export declare class MultivariateFeatureOptionModel {
9
+ value: any;
10
+ id: number | undefined;
11
+ constructor(value: any, id?: number);
12
+ }
13
+ export declare class MultivariateFeatureStateValueModel {
14
+ multivariateFeatureOption: MultivariateFeatureOptionModel;
15
+ percentageAllocation: number;
16
+ id: number;
17
+ mvFsValueUuid: string;
18
+ constructor(multivariate_feature_option: MultivariateFeatureOptionModel, percentage_allocation: number, id: number, mvFsValueUuid?: string);
19
+ }
20
+ export declare class FeatureStateModel {
21
+ feature: FeatureModel;
22
+ enabled: boolean;
23
+ djangoID: number;
24
+ featurestateUUID: string;
25
+ featureSegment?: FeatureSegment;
26
+ private value;
27
+ multivariateFeatureStateValues: MultivariateFeatureStateValueModel[];
28
+ constructor(feature: FeatureModel, enabled: boolean, djangoID: number, value?: any, featurestateUuid?: string);
29
+ setValue(value: any): void;
30
+ getValue(identityId?: number | string): any;
31
+ isHigherSegmentPriority(other: FeatureStateModel): boolean;
32
+ getMultivariateValue(identityID: number | string): any;
33
+ }
34
+ export declare class FeatureSegment {
35
+ priority: number;
36
+ constructor(priority: number);
37
+ }
@@ -0,0 +1,110 @@
1
+ import { v4 as uuidv4 } from 'uuid';
2
+ import { getHashedPercentateForObjIds } from '../utils/hashing/index.js';
3
+ export class FeatureModel {
4
+ id;
5
+ name;
6
+ type;
7
+ constructor(id, name, type) {
8
+ this.id = id;
9
+ this.name = name;
10
+ this.type = type;
11
+ }
12
+ eq(other) {
13
+ return !!other && this.id === other.id;
14
+ }
15
+ }
16
+ export class MultivariateFeatureOptionModel {
17
+ value;
18
+ id;
19
+ constructor(value, id) {
20
+ this.value = value;
21
+ this.id = id;
22
+ }
23
+ }
24
+ export class MultivariateFeatureStateValueModel {
25
+ multivariateFeatureOption;
26
+ percentageAllocation;
27
+ id;
28
+ mvFsValueUuid = uuidv4();
29
+ constructor(multivariate_feature_option, percentage_allocation, id, mvFsValueUuid) {
30
+ this.id = id;
31
+ this.percentageAllocation = percentage_allocation;
32
+ this.multivariateFeatureOption = multivariate_feature_option;
33
+ this.mvFsValueUuid = mvFsValueUuid || this.mvFsValueUuid;
34
+ }
35
+ }
36
+ export class FeatureStateModel {
37
+ feature;
38
+ enabled;
39
+ djangoID;
40
+ featurestateUUID = uuidv4();
41
+ featureSegment;
42
+ value;
43
+ multivariateFeatureStateValues = [];
44
+ constructor(feature, enabled, djangoID, value, featurestateUuid = uuidv4()) {
45
+ this.feature = feature;
46
+ this.enabled = enabled;
47
+ this.djangoID = djangoID;
48
+ this.value = value;
49
+ this.featurestateUUID = featurestateUuid;
50
+ }
51
+ setValue(value) {
52
+ this.value = value;
53
+ }
54
+ getValue(identityId) {
55
+ if (!!identityId && this.multivariateFeatureStateValues.length > 0) {
56
+ return this.getMultivariateValue(identityId);
57
+ }
58
+ return this.value;
59
+ }
60
+ /*
61
+ Returns `True` if `this` is higher segment priority than `other`
62
+ (i.e. has lower value for featureSegment.priority)
63
+ NOTE:
64
+ A segment will be considered higher priority only if:
65
+ 1. `other` does not have a feature segment(i.e: it is an environment feature state or it's a
66
+ feature state with feature segment but from an old document that does not have `featureSegment.priority`)
67
+ but `this` does.
68
+ 2. `other` have a feature segment with high priority
69
+ */
70
+ isHigherSegmentPriority(other) {
71
+ if (!other.featureSegment || !this.featureSegment) {
72
+ return !!this.featureSegment && !other.featureSegment;
73
+ }
74
+ return this.featureSegment.priority < other.featureSegment.priority;
75
+ }
76
+ getMultivariateValue(identityID) {
77
+ let percentageValue;
78
+ let startPercentage = 0;
79
+ const sortedF = this.multivariateFeatureStateValues.sort((a, b) => {
80
+ return a.id - b.id;
81
+ });
82
+ for (const myValue of sortedF) {
83
+ switch (myValue.percentageAllocation) {
84
+ case 0:
85
+ continue;
86
+ case 100:
87
+ return myValue.multivariateFeatureOption.value;
88
+ default:
89
+ if (percentageValue === undefined) {
90
+ percentageValue = getHashedPercentateForObjIds([
91
+ this.djangoID || this.featurestateUUID,
92
+ identityID
93
+ ]);
94
+ }
95
+ }
96
+ const limit = myValue.percentageAllocation + startPercentage;
97
+ if (startPercentage <= percentageValue && percentageValue < limit) {
98
+ return myValue.multivariateFeatureOption.value;
99
+ }
100
+ startPercentage = limit;
101
+ }
102
+ return this.value;
103
+ }
104
+ }
105
+ export class FeatureSegment {
106
+ priority;
107
+ constructor(priority) {
108
+ this.priority = priority;
109
+ }
110
+ }
@@ -0,0 +1,4 @@
1
+ import { FeatureModel, FeatureSegment, FeatureStateModel } from './models.js';
2
+ export declare function buildFeatureModel(featuresModelJSON: any): FeatureModel;
3
+ export declare function buildFeatureStateModel(featuresStateModelJSON: any): FeatureStateModel;
4
+ export declare function buildFeatureSegment(featureSegmentJSON: any): FeatureSegment;
@@ -0,0 +1,21 @@
1
+ import { FeatureModel, FeatureSegment, FeatureStateModel, MultivariateFeatureOptionModel, MultivariateFeatureStateValueModel } from './models.js';
2
+ export function buildFeatureModel(featuresModelJSON) {
3
+ return new FeatureModel(featuresModelJSON.id, featuresModelJSON.name, featuresModelJSON.type);
4
+ }
5
+ export function buildFeatureStateModel(featuresStateModelJSON) {
6
+ const featureStateModel = new FeatureStateModel(buildFeatureModel(featuresStateModelJSON.feature), featuresStateModelJSON.enabled, featuresStateModelJSON.django_id, featuresStateModelJSON.feature_state_value, featuresStateModelJSON.featurestate_uuid);
7
+ featureStateModel.featureSegment = featuresStateModelJSON.feature_segment ?
8
+ buildFeatureSegment(featuresStateModelJSON.feature_segment) :
9
+ undefined;
10
+ const multivariateFeatureStateValues = featuresStateModelJSON.multivariate_feature_state_values
11
+ ? featuresStateModelJSON.multivariate_feature_state_values.map((fsv) => {
12
+ const featureOption = new MultivariateFeatureOptionModel(fsv.multivariate_feature_option.value, fsv.multivariate_feature_option.id);
13
+ return new MultivariateFeatureStateValueModel(featureOption, fsv.percentage_allocation, fsv.id, fsv.mv_fs_value_uuid);
14
+ })
15
+ : [];
16
+ featureStateModel.multivariateFeatureStateValues = multivariateFeatureStateValues;
17
+ return featureStateModel;
18
+ }
19
+ export function buildFeatureSegment(featureSegmentJSON) {
20
+ return new FeatureSegment(featureSegmentJSON.priority);
21
+ }
@@ -0,0 +1,15 @@
1
+ import { IdentityFeaturesList } from '../utils/collections.js';
2
+ import { TraitModel } from './traits/models.js';
3
+ export declare class IdentityModel {
4
+ identifier: string;
5
+ environmentApiKey: string;
6
+ createdDate?: number;
7
+ identityFeatures: IdentityFeaturesList;
8
+ identityTraits: TraitModel[];
9
+ identityUuid: string;
10
+ djangoID: number | undefined;
11
+ constructor(created_date: string, identityTraits: TraitModel[], identityFeatures: IdentityFeaturesList, environmentApiKey: string, identifier: string, identityUuid?: string, djangoID?: number);
12
+ get compositeKey(): string;
13
+ static generateCompositeKey(env_key: string, identifier: string): string;
14
+ updateTraits(traits: TraitModel[]): void;
15
+ }
@@ -0,0 +1,44 @@
1
+ import { IdentityFeaturesList } from '../utils/collections.js';
2
+ const { v4: uuidv4 } = require('uuid');
3
+ export class IdentityModel {
4
+ identifier;
5
+ environmentApiKey;
6
+ createdDate;
7
+ identityFeatures;
8
+ identityTraits;
9
+ identityUuid;
10
+ djangoID;
11
+ constructor(created_date, identityTraits, identityFeatures, environmentApiKey, identifier, identityUuid, djangoID) {
12
+ this.identityUuid = identityUuid || uuidv4();
13
+ this.createdDate = Date.parse(created_date) || Date.now();
14
+ this.identityTraits = identityTraits;
15
+ this.identityFeatures = new IdentityFeaturesList(...identityFeatures);
16
+ this.environmentApiKey = environmentApiKey;
17
+ this.identifier = identifier;
18
+ this.djangoID = djangoID;
19
+ }
20
+ get compositeKey() {
21
+ return IdentityModel.generateCompositeKey(this.environmentApiKey, this.identifier);
22
+ }
23
+ static generateCompositeKey(env_key, identifier) {
24
+ return `${env_key}_${identifier}`;
25
+ }
26
+ updateTraits(traits) {
27
+ const existingTraits = new Map();
28
+ for (const trait of this.identityTraits) {
29
+ existingTraits.set(trait.traitKey, trait);
30
+ }
31
+ for (const trait of traits) {
32
+ if (!!trait.traitValue) {
33
+ existingTraits.set(trait.traitKey, trait);
34
+ }
35
+ else {
36
+ existingTraits.delete(trait.traitKey);
37
+ }
38
+ }
39
+ this.identityTraits = [];
40
+ for (const [k, v] of existingTraits.entries()) {
41
+ this.identityTraits.push(v);
42
+ }
43
+ }
44
+ }
@@ -0,0 +1,5 @@
1
+ export declare class TraitModel {
2
+ traitKey: string;
3
+ traitValue: any;
4
+ constructor(key: string, value: any);
5
+ }
@@ -0,0 +1,8 @@
1
+ export class TraitModel {
2
+ traitKey;
3
+ traitValue;
4
+ constructor(key, value) {
5
+ this.traitKey = key;
6
+ this.traitValue = value;
7
+ }
8
+ }
@@ -0,0 +1,4 @@
1
+ import { IdentityModel } from './models.js';
2
+ import { TraitModel } from './traits/models.js';
3
+ export declare function buildTraitModel(traitJSON: any): TraitModel;
4
+ export declare function buildIdentityModel(identityJSON: any): IdentityModel;
@@ -0,0 +1,17 @@
1
+ import { buildFeatureStateModel } from '../features/util.js';
2
+ import { IdentityFeaturesList } from '../utils/collections.js';
3
+ import { IdentityModel } from './models.js';
4
+ import { TraitModel } from './traits/models.js';
5
+ export function buildTraitModel(traitJSON) {
6
+ return new TraitModel(traitJSON.trait_key, traitJSON.trait_value);
7
+ }
8
+ export function buildIdentityModel(identityJSON) {
9
+ const featureList = identityJSON.identity_features
10
+ ? new IdentityFeaturesList(...identityJSON.identity_features.map((f) => buildFeatureStateModel(f)))
11
+ : [];
12
+ const model = new IdentityModel(identityJSON.created_date, identityJSON.identity_traits
13
+ ? identityJSON.identity_traits.map((trait) => buildTraitModel(trait))
14
+ : [], featureList, identityJSON.environment_api_key, identityJSON.identifier, identityJSON.identity_uuid);
15
+ model.djangoID = identityJSON.django_id;
16
+ return model;
17
+ }
@@ -0,0 +1,14 @@
1
+ import { EnvironmentModel } from './environments/models.js';
2
+ import { FeatureStateModel } from './features/models.js';
3
+ import { IdentityModel } from './identities/models.js';
4
+ import { TraitModel } from './identities/traits/models.js';
5
+ export { EnvironmentModel } from './environments/models.js';
6
+ export { FeatureStateModel } from './features/models.js';
7
+ export { IdentityModel } from './identities/models.js';
8
+ export { TraitModel } from './identities/traits/models.js';
9
+ export { SegmentModel } from './segments/models.js';
10
+ export { OrganisationModel } from './organisations/models.js';
11
+ export declare function getIdentityFeatureState(environment: EnvironmentModel, identity: IdentityModel, featureName: string, overrideTraits?: TraitModel[]): FeatureStateModel;
12
+ export declare function getIdentityFeatureStates(environment: EnvironmentModel, identity: IdentityModel, overrideTraits?: TraitModel[]): FeatureStateModel[];
13
+ export declare function getEnvironmentFeatureState(environment: EnvironmentModel, featureName: string): FeatureStateModel;
14
+ export declare function getEnvironmentFeatureStates(environment: EnvironmentModel): FeatureStateModel[];
@@ -0,0 +1,62 @@
1
+ import { getIdentitySegments } from './segments/evaluators.js';
2
+ import { FeatureStateNotFound } from './utils/errors.js';
3
+ export { EnvironmentModel } from './environments/models.js';
4
+ export { FeatureStateModel } from './features/models.js';
5
+ export { IdentityModel } from './identities/models.js';
6
+ export { TraitModel } from './identities/traits/models.js';
7
+ export { SegmentModel } from './segments/models.js';
8
+ export { OrganisationModel } from './organisations/models.js';
9
+ function getIdentityFeatureStatesDict(environment, identity, overrideTraits) {
10
+ // Get feature states from the environment
11
+ const featureStates = {};
12
+ for (const fs of environment.featureStates) {
13
+ featureStates[fs.feature.id] = fs;
14
+ }
15
+ // Override with any feature states defined by matching segments
16
+ const identitySegments = getIdentitySegments(environment, identity, overrideTraits);
17
+ for (const matchingSegment of identitySegments) {
18
+ for (const featureState of matchingSegment.featureStates) {
19
+ if (featureStates[featureState.feature.id]) {
20
+ if (featureStates[featureState.feature.id].isHigherSegmentPriority(featureState)) {
21
+ continue;
22
+ }
23
+ }
24
+ featureStates[featureState.feature.id] = featureState;
25
+ }
26
+ }
27
+ // Override with any feature states defined directly the identity
28
+ for (const fs of identity.identityFeatures) {
29
+ if (featureStates[fs.feature.id]) {
30
+ featureStates[fs.feature.id] = fs;
31
+ }
32
+ }
33
+ return featureStates;
34
+ }
35
+ export function getIdentityFeatureState(environment, identity, featureName, overrideTraits) {
36
+ const featureStates = getIdentityFeatureStatesDict(environment, identity, overrideTraits);
37
+ const matchingFeature = Object.values(featureStates).filter(f => f.feature.name === featureName);
38
+ if (matchingFeature.length === 0) {
39
+ throw new FeatureStateNotFound('Feature State Not Found');
40
+ }
41
+ return matchingFeature[0];
42
+ }
43
+ export function getIdentityFeatureStates(environment, identity, overrideTraits) {
44
+ const featureStates = Object.values(getIdentityFeatureStatesDict(environment, identity, overrideTraits));
45
+ if (environment.project.hideDisabledFlags) {
46
+ return featureStates.filter(fs => !!fs.enabled);
47
+ }
48
+ return featureStates;
49
+ }
50
+ export function getEnvironmentFeatureState(environment, featureName) {
51
+ const featuresStates = environment.featureStates.filter(f => f.feature.name === featureName);
52
+ if (featuresStates.length === 0) {
53
+ throw new FeatureStateNotFound('Feature State Not Found');
54
+ }
55
+ return featuresStates[0];
56
+ }
57
+ export function getEnvironmentFeatureStates(environment) {
58
+ if (environment.project.hideDisabledFlags) {
59
+ return environment.featureStates.filter(fs => !!fs.enabled);
60
+ }
61
+ return environment.featureStates;
62
+ }
@@ -0,0 +1,9 @@
1
+ export declare class OrganisationModel {
2
+ id: number;
3
+ name: string;
4
+ featureAnalytics: boolean;
5
+ stopServingFlags: boolean;
6
+ persistTraitData: boolean;
7
+ constructor(id: number, name: string, featureAnalytics: boolean, stopServingFlags: boolean, persistTraitData: boolean);
8
+ get uniqueSlug(): string;
9
+ }
@@ -0,0 +1,17 @@
1
+ export class OrganisationModel {
2
+ id;
3
+ name;
4
+ featureAnalytics;
5
+ stopServingFlags;
6
+ persistTraitData;
7
+ constructor(id, name, featureAnalytics, stopServingFlags, persistTraitData) {
8
+ this.id = id;
9
+ this.name = name;
10
+ this.featureAnalytics = featureAnalytics;
11
+ this.stopServingFlags = stopServingFlags;
12
+ this.persistTraitData = persistTraitData;
13
+ }
14
+ get uniqueSlug() {
15
+ return this.id.toString() + '-' + this.name;
16
+ }
17
+ }
@@ -0,0 +1,2 @@
1
+ import { OrganisationModel } from './models.js';
2
+ export declare function buildOrganizationModel(organizationJSON: any): OrganisationModel;
@@ -0,0 +1,4 @@
1
+ import { OrganisationModel } from './models.js';
2
+ export function buildOrganizationModel(organizationJSON) {
3
+ return new OrganisationModel(organizationJSON.id, organizationJSON.name, organizationJSON.feature_analytics, organizationJSON.stop_serving_flags, organizationJSON.persist_trait_data);
4
+ }
@@ -0,0 +1,10 @@
1
+ import { OrganisationModel } from '../organisations/models.js';
2
+ import { SegmentModel } from '../segments/models.js';
3
+ export declare class ProjectModel {
4
+ id: number;
5
+ name: string;
6
+ organisation: OrganisationModel;
7
+ hideDisabledFlags: boolean;
8
+ segments: SegmentModel[];
9
+ constructor(id: number, name: string, hideDisabledFlags: boolean, organization: OrganisationModel);
10
+ }
@@ -0,0 +1,13 @@
1
+ export class ProjectModel {
2
+ id;
3
+ name;
4
+ organisation;
5
+ hideDisabledFlags;
6
+ segments = [];
7
+ constructor(id, name, hideDisabledFlags, organization) {
8
+ this.id = id;
9
+ this.name = name;
10
+ this.hideDisabledFlags = hideDisabledFlags;
11
+ this.organisation = organization;
12
+ }
13
+ }
@@ -0,0 +1,2 @@
1
+ import { ProjectModel } from './models.js';
2
+ export declare function buildProjectModel(projectJSON: any): ProjectModel;
@@ -0,0 +1,11 @@
1
+ import { buildOrganizationModel } from '../organisations/util.js';
2
+ import { buildSegmentModel } from '../segments/util.js';
3
+ import { ProjectModel } from './models.js';
4
+ export function buildProjectModel(projectJSON) {
5
+ const segments = projectJSON['segments']
6
+ ? projectJSON['segments'].map((s) => buildSegmentModel(s))
7
+ : [];
8
+ const model = new ProjectModel(projectJSON.id, projectJSON.name, projectJSON.hide_disabled_flags, buildOrganizationModel(projectJSON.organisation));
9
+ model.segments = segments;
10
+ return model;
11
+ }
@@ -0,0 +1,34 @@
1
+ export declare const ALL_RULE = "ALL";
2
+ export declare const ANY_RULE = "ANY";
3
+ export declare const NONE_RULE = "NONE";
4
+ export declare const RULE_TYPES: string[];
5
+ export declare const EQUAL = "EQUAL";
6
+ export declare const GREATER_THAN = "GREATER_THAN";
7
+ export declare const LESS_THAN = "LESS_THAN";
8
+ export declare const LESS_THAN_INCLUSIVE = "LESS_THAN_INCLUSIVE";
9
+ export declare const CONTAINS = "CONTAINS";
10
+ export declare const GREATER_THAN_INCLUSIVE = "GREATER_THAN_INCLUSIVE";
11
+ export declare const NOT_CONTAINS = "NOT_CONTAINS";
12
+ export declare const NOT_EQUAL = "NOT_EQUAL";
13
+ export declare const REGEX = "REGEX";
14
+ export declare const PERCENTAGE_SPLIT = "PERCENTAGE_SPLIT";
15
+ export declare const IS_SET = "IS_SET";
16
+ export declare const IS_NOT_SET = "IS_NOT_SET";
17
+ export declare const MODULO = "MODULO";
18
+ export declare const IN = "IN";
19
+ export declare const CONDITION_OPERATORS: {
20
+ EQUAL: string;
21
+ GREATER_THAN: string;
22
+ LESS_THAN: string;
23
+ LESS_THAN_INCLUSIVE: string;
24
+ CONTAINS: string;
25
+ GREATER_THAN_INCLUSIVE: string;
26
+ NOT_CONTAINS: string;
27
+ NOT_EQUAL: string;
28
+ REGEX: string;
29
+ PERCENTAGE_SPLIT: string;
30
+ IS_SET: string;
31
+ IS_NOT_SET: string;
32
+ MODULO: string;
33
+ IN: string;
34
+ };