flagsmith-nodejs 6.0.1 → 6.1.0

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 (70) hide show
  1. package/.github/workflows/publish.yml +17 -17
  2. package/.github/workflows/pull_request.yaml +33 -33
  3. package/.husky/pre-commit +0 -0
  4. package/.prettierignore +2 -1
  5. package/README.md +2 -1
  6. package/build/cjs/flagsmith-engine/features/util.js +3 -3
  7. package/build/cjs/flagsmith-engine/index.d.ts +1 -1
  8. package/build/cjs/flagsmith-engine/index.js +2 -1
  9. package/build/cjs/flagsmith-engine/segments/models.js +7 -7
  10. package/build/cjs/flagsmith-engine/utils/hashing/index.js +1 -1
  11. package/build/cjs/index.d.ts +4 -4
  12. package/build/cjs/index.js +3 -1
  13. package/build/cjs/sdk/analytics.d.ts +1 -1
  14. package/build/cjs/sdk/index.d.ts +5 -5
  15. package/build/cjs/sdk/index.js +7 -5
  16. package/build/cjs/sdk/models.d.ts +25 -0
  17. package/build/cjs/sdk/models.js +25 -0
  18. package/build/cjs/sdk/types.d.ts +14 -4
  19. package/build/cjs/sdk/utils.d.ts +4 -4
  20. package/build/cjs/sdk/utils.js +2 -2
  21. package/build/esm/flagsmith-engine/features/models.js +1 -1
  22. package/build/esm/flagsmith-engine/features/util.js +3 -3
  23. package/build/esm/flagsmith-engine/index.d.ts +1 -1
  24. package/build/esm/flagsmith-engine/index.js +1 -1
  25. package/build/esm/flagsmith-engine/segments/models.js +7 -7
  26. package/build/esm/flagsmith-engine/utils/hashing/index.js +2 -2
  27. package/build/esm/flagsmith-engine/utils/index.js +1 -1
  28. package/build/esm/index.d.ts +4 -4
  29. package/build/esm/index.js +3 -3
  30. package/build/esm/sdk/analytics.d.ts +1 -1
  31. package/build/esm/sdk/index.d.ts +5 -5
  32. package/build/esm/sdk/index.js +6 -5
  33. package/build/esm/sdk/models.d.ts +25 -0
  34. package/build/esm/sdk/models.js +25 -0
  35. package/build/esm/sdk/types.d.ts +14 -4
  36. package/build/esm/sdk/utils.d.ts +4 -4
  37. package/build/esm/sdk/utils.js +2 -2
  38. package/flagsmith-engine/environments/util.ts +2 -2
  39. package/flagsmith-engine/features/models.ts +1 -1
  40. package/flagsmith-engine/features/util.ts +14 -14
  41. package/flagsmith-engine/identities/models.ts +1 -1
  42. package/flagsmith-engine/index.ts +1 -1
  43. package/flagsmith-engine/segments/evaluators.ts +2 -3
  44. package/flagsmith-engine/segments/models.ts +25 -15
  45. package/flagsmith-engine/utils/hashing/index.ts +3 -3
  46. package/flagsmith-engine/utils/index.ts +4 -2
  47. package/index.ts +19 -22
  48. package/package.json +1 -1
  49. package/sdk/analytics.ts +7 -5
  50. package/sdk/index.ts +38 -21
  51. package/sdk/models.ts +25 -0
  52. package/sdk/offline_handlers.ts +1 -1
  53. package/sdk/types.ts +17 -8
  54. package/sdk/utils.ts +8 -8
  55. package/tests/engine/e2e/engine.test.ts +2 -4
  56. package/tests/engine/unit/engine.test.ts +1 -5
  57. package/tests/engine/unit/features/models.test.ts +2 -2
  58. package/tests/engine/unit/identities/identities_builders.test.ts +1 -1
  59. package/tests/engine/unit/segments/segment_evaluators.test.ts +52 -23
  60. package/tests/engine/unit/segments/segments_model.test.ts +35 -37
  61. package/tests/engine/unit/utils/utils.test.ts +28 -30
  62. package/tests/sdk/analytics.test.ts +25 -26
  63. package/tests/sdk/flagsmith-cache.test.ts +84 -76
  64. package/tests/sdk/flagsmith-environment-flags.test.ts +93 -93
  65. package/tests/sdk/flagsmith-identity-flags.test.ts +146 -149
  66. package/tests/sdk/flagsmith.test.ts +40 -42
  67. package/tests/sdk/offline-handlers.test.ts +32 -32
  68. package/tests/sdk/polling.test.ts +0 -1
  69. package/tests/sdk/utils.ts +26 -18
  70. package/vitest.config.ts +10 -15
@@ -1,4 +1,4 @@
1
- import { createHash } from "node:crypto";
1
+ import { createHash } from 'node:crypto';
2
2
  const md5 = (data) => createHash('md5').update(data).digest('hex');
3
3
  const makeRepeated = (arr, repeats) => Array.from({ length: repeats }, () => arr).flat();
4
4
  // https://stackoverflow.com/questions/12532871/how-to-convert-a-very-large-hex-number-to-decimal-in-javascript
@@ -14,7 +14,7 @@ export function getHashedPercentateForObjIds(objectIds, iterations = 1) {
14
14
  let toHash = makeRepeated(objectIds, iterations).join(',');
15
15
  const hashedValue = md5(toHash);
16
16
  const hashedInt = BigInt('0x' + hashedValue);
17
- const value = (Number((hashedInt % 9999n)) / 9998.0) * 100;
17
+ const value = (Number(hashedInt % 9999n) / 9998.0) * 100;
18
18
  // we ignore this for it's nearly impossible use case to catch
19
19
  /* istanbul ignore next */
20
20
  if (value === 100) {
@@ -1,4 +1,4 @@
1
- import { removeSemverSuffix } from "../segments/util.js";
1
+ import { removeSemverSuffix } from '../segments/util.js';
2
2
  export function getCastingFunction(traitType) {
3
3
  switch (traitType) {
4
4
  case 'boolean':
@@ -1,4 +1,4 @@
1
- export { AnalyticsProcessor, AnalyticsProcessorOptions, FlagsmithAPIError, FlagsmithClientError, EnvironmentDataPollingManager, FlagsmithCache, DefaultFlag, Flags, Flagsmith, } from './sdk/index.js';
2
- export { BaseOfflineHandler, LocalFileHandler, } from './sdk/offline_handlers.js';
3
- export { FlagsmithConfig } from './sdk/types.js';
4
- export { EnvironmentModel, FeatureStateModel, IdentityModel, TraitModel, SegmentModel, OrganisationModel } from './flagsmith-engine/index.js';
1
+ export { AnalyticsProcessor, AnalyticsProcessorOptions, FlagsmithAPIError, FlagsmithClientError, EnvironmentDataPollingManager, FlagsmithCache, BaseFlag, DefaultFlag, Flags, Flagsmith } from './sdk/index.js';
2
+ export { BaseOfflineHandler, LocalFileHandler } from './sdk/offline_handlers.js';
3
+ export { FlagsmithConfig, FlagsmithValue, TraitConfig } from './sdk/types.js';
4
+ export { EnvironmentModel, FeatureModel, FeatureStateModel, IdentityModel, TraitModel, SegmentModel, OrganisationModel } from './flagsmith-engine/index.js';
@@ -1,3 +1,3 @@
1
- export { AnalyticsProcessor, FlagsmithAPIError, FlagsmithClientError, EnvironmentDataPollingManager, DefaultFlag, Flags, Flagsmith, } from './sdk/index.js';
2
- export { BaseOfflineHandler, LocalFileHandler, } from './sdk/offline_handlers.js';
3
- export { EnvironmentModel, FeatureStateModel, IdentityModel, TraitModel, SegmentModel, OrganisationModel } from './flagsmith-engine/index.js';
1
+ export { AnalyticsProcessor, FlagsmithAPIError, FlagsmithClientError, EnvironmentDataPollingManager, BaseFlag, DefaultFlag, Flags, Flagsmith } from './sdk/index.js';
2
+ export { BaseOfflineHandler, LocalFileHandler } from './sdk/offline_handlers.js';
3
+ export { EnvironmentModel, FeatureModel, FeatureStateModel, IdentityModel, TraitModel, SegmentModel, OrganisationModel } from './flagsmith-engine/index.js';
@@ -1,5 +1,5 @@
1
1
  import { Logger } from 'pino';
2
- import { Fetch } from "./types.js";
2
+ import { Fetch } from './types.js';
3
3
  export declare const ANALYTICS_ENDPOINT = "./analytics/flags/";
4
4
  export interface AnalyticsProcessorOptions {
5
5
  /** URL of the Flagsmith analytics events API endpoint
@@ -5,10 +5,10 @@ import { BaseOfflineHandler } from './offline_handlers.js';
5
5
  import { DefaultFlag, Flags } from './models.js';
6
6
  import { EnvironmentDataPollingManager } from './polling_manager.js';
7
7
  import { SegmentModel } from '../flagsmith-engine/index.js';
8
- import { FlagsmithConfig, FlagsmithTraitValue, ITraitConfig } from './types.js';
8
+ import { FlagsmithConfig, FlagsmithTraitValue, TraitConfig } from './types.js';
9
9
  export { AnalyticsProcessor, AnalyticsProcessorOptions } from './analytics.js';
10
10
  export { FlagsmithAPIError, FlagsmithClientError } from './errors.js';
11
- export { DefaultFlag, Flags } from './models.js';
11
+ export { BaseFlag, DefaultFlag, Flags } from './models.js';
12
12
  export { EnvironmentDataPollingManager } from './polling_manager.js';
13
13
  export { FlagsmithCache, FlagsmithConfig } from './types.js';
14
14
  /**
@@ -34,7 +34,7 @@ export { FlagsmithCache, FlagsmithConfig } from './types.js';
34
34
  * const bannerVariation: string = identityFlags.getFeatureValue('banner_flag')
35
35
  *
36
36
  * @see FlagsmithConfig
37
- */
37
+ */
38
38
  export declare class Flagsmith {
39
39
  environmentKey?: string;
40
40
  apiUrl?: string;
@@ -84,12 +84,12 @@ export declare class Flagsmith {
84
84
  *
85
85
  * @param {string} identifier a unique identifier for the identity in the current
86
86
  environment, e.g. email address, username, uuid
87
- * @param {{[key:string]:any | ITraitConfig}} traits? a dictionary of traits to add / update on the identity in
87
+ * @param {{[key:string]:any | TraitConfig}} traits? a dictionary of traits to add / update on the identity in
88
88
  Flagsmith, e.g. {"num_orders": 10} or {age: {value: 30, transient: true}}
89
89
  * @returns Flags object holding all the flags for the given identity.
90
90
  */
91
91
  getIdentityFlags(identifier: string, traits?: {
92
- [key: string]: FlagsmithTraitValue | ITraitConfig;
92
+ [key: string]: FlagsmithTraitValue | TraitConfig;
93
93
  }, transient?: boolean): Promise<Flags>;
94
94
  /**
95
95
  * Get the segments for the current environment for a given identity. Will also
@@ -11,7 +11,7 @@ import { getIdentitySegments } from '../flagsmith-engine/segments/evaluators.js'
11
11
  import { pino } from 'pino';
12
12
  export { AnalyticsProcessor } from './analytics.js';
13
13
  export { FlagsmithAPIError, FlagsmithClientError } from './errors.js';
14
- export { DefaultFlag, Flags } from './models.js';
14
+ export { BaseFlag, DefaultFlag, Flags } from './models.js';
15
15
  export { EnvironmentDataPollingManager } from './polling_manager.js';
16
16
  const DEFAULT_API_URL = 'https://edge.api.flagsmith.com/api/v1/';
17
17
  const DEFAULT_REQUEST_TIMEOUT_SECONDS = 10;
@@ -38,7 +38,7 @@ const DEFAULT_REQUEST_TIMEOUT_SECONDS = 10;
38
38
  * const bannerVariation: string = identityFlags.getFeatureValue('banner_flag')
39
39
  *
40
40
  * @see FlagsmithConfig
41
- */
41
+ */
42
42
  export class Flagsmith {
43
43
  environmentKey = undefined;
44
44
  apiUrl = undefined;
@@ -107,7 +107,8 @@ export class Flagsmith {
107
107
  }
108
108
  const apiUrl = data.apiUrl || DEFAULT_API_URL;
109
109
  this.apiUrl = apiUrl.endsWith('/') ? apiUrl : `${apiUrl}/`;
110
- this.analyticsUrl = this.analyticsUrl || new URL(ANALYTICS_ENDPOINT, new Request(this.apiUrl).url).href;
110
+ this.analyticsUrl =
111
+ this.analyticsUrl || new URL(ANALYTICS_ENDPOINT, new Request(this.apiUrl).url).href;
111
112
  this.environmentFlagsUrl = `${this.apiUrl}flags/`;
112
113
  this.identitiesUrl = `${this.apiUrl}identities/`;
113
114
  this.environmentUrl = `${this.apiUrl}environment-document/`;
@@ -125,7 +126,7 @@ export class Flagsmith {
125
126
  environmentKey: this.environmentKey,
126
127
  analyticsUrl: this.analyticsUrl,
127
128
  requestTimeoutMs: this.requestTimeoutMs,
128
- logger: this.logger,
129
+ logger: this.logger
129
130
  });
130
131
  }
131
132
  }
@@ -164,7 +165,7 @@ export class Flagsmith {
164
165
  *
165
166
  * @param {string} identifier a unique identifier for the identity in the current
166
167
  environment, e.g. email address, username, uuid
167
- * @param {{[key:string]:any | ITraitConfig}} traits? a dictionary of traits to add / update on the identity in
168
+ * @param {{[key:string]:any | TraitConfig}} traits? a dictionary of traits to add / update on the identity in
168
169
  Flagsmith, e.g. {"num_orders": 10} or {age: {value: 30, transient: true}}
169
170
  * @returns Flags object holding all the flags for the given identity.
170
171
  */
@@ -1,17 +1,42 @@
1
1
  import { FeatureStateModel } from '../flagsmith-engine/features/models.js';
2
2
  import { AnalyticsProcessor } from './analytics.js';
3
3
  type FlagValue = string | number | boolean | undefined;
4
+ /**
5
+ * A Flagsmith feature. It has an enabled/disabled state, and an optional {@link FlagValue}.
6
+ */
4
7
  export declare class BaseFlag {
8
+ /**
9
+ * Indicates whether this feature is enabled.
10
+ */
5
11
  enabled: boolean;
12
+ /**
13
+ * An optional {@link FlagValue} for this feature.
14
+ */
6
15
  value: FlagValue;
16
+ /**
17
+ * If true, the state for this feature was determined by a default flag handler. See {@link DefaultFlag}.
18
+ */
7
19
  isDefault: boolean;
8
20
  constructor(value: FlagValue, enabled: boolean, isDefault: boolean);
9
21
  }
22
+ /**
23
+ * A {@link BaseFlag} returned by a default flag handler when flag evaluation fails.
24
+ * @see FlagsmithConfig#defaultFlagHandler
25
+ */
10
26
  export declare class DefaultFlag extends BaseFlag {
11
27
  constructor(value: FlagValue, enabled: boolean);
12
28
  }
29
+ /**
30
+ * A Flagsmith feature retrieved from a successful flag evaluation.
31
+ */
13
32
  export declare class Flag extends BaseFlag {
33
+ /**
34
+ * An identifier for this feature, unique in a single Flagsmith installation.
35
+ */
14
36
  featureId: number;
37
+ /**
38
+ * The programmatic name for this feature, unique per Flagsmith project.
39
+ */
15
40
  featureName: string;
16
41
  constructor(params: {
17
42
  value: FlagValue;
@@ -1,6 +1,18 @@
1
+ /**
2
+ * A Flagsmith feature. It has an enabled/disabled state, and an optional {@link FlagValue}.
3
+ */
1
4
  export class BaseFlag {
5
+ /**
6
+ * Indicates whether this feature is enabled.
7
+ */
2
8
  enabled;
9
+ /**
10
+ * An optional {@link FlagValue} for this feature.
11
+ */
3
12
  value;
13
+ /**
14
+ * If true, the state for this feature was determined by a default flag handler. See {@link DefaultFlag}.
15
+ */
4
16
  isDefault;
5
17
  constructor(value, enabled, isDefault) {
6
18
  this.value = value;
@@ -8,13 +20,26 @@ export class BaseFlag {
8
20
  this.isDefault = isDefault;
9
21
  }
10
22
  }
23
+ /**
24
+ * A {@link BaseFlag} returned by a default flag handler when flag evaluation fails.
25
+ * @see FlagsmithConfig#defaultFlagHandler
26
+ */
11
27
  export class DefaultFlag extends BaseFlag {
12
28
  constructor(value, enabled) {
13
29
  super(value, enabled, true);
14
30
  }
15
31
  }
32
+ /**
33
+ * A Flagsmith feature retrieved from a successful flag evaluation.
34
+ */
16
35
  export class Flag extends BaseFlag {
36
+ /**
37
+ * An identifier for this feature, unique in a single Flagsmith installation.
38
+ */
17
39
  featureId;
40
+ /**
41
+ * The programmatic name for this feature, unique per Flagsmith project.
42
+ */
18
43
  featureName;
19
44
  constructor(params) {
20
45
  super(params.value, params.enabled, !!params.isDefault);
@@ -3,7 +3,10 @@ import { EnvironmentModel } from '../flagsmith-engine/index.js';
3
3
  import { Dispatcher } from 'undici-types';
4
4
  import { Logger } from 'pino';
5
5
  import { BaseOfflineHandler } from './offline_handlers.js';
6
- export type IFlagsmithValue<T = string | number | boolean | null> = T;
6
+ /**
7
+ * A concrete type for the possible values of a feature.
8
+ */
9
+ export type FlagsmithValue<T = string | number | boolean | null> = T;
7
10
  /**
8
11
  * Stores and retrieves {@link Flags} from a cache.
9
12
  */
@@ -89,7 +92,7 @@ export interface FlagsmithConfig {
89
92
  * const defaultHandler = () => new DefaultFlag(undefined, false)
90
93
  *
91
94
  * // Enable only VIP flags by default
92
- * const vipDefaultHandler = (key: string) => new Default(undefined, key.startsWith('vip_'))
95
+ * const vipDefaultHandler = (key: string) => new DefaultFlag(undefined, key.startsWith('vip_'))
93
96
  */
94
97
  defaultFlagHandler?: (flagKey: string) => DefaultFlag;
95
98
  cache?: FlagsmithCache;
@@ -109,8 +112,15 @@ export interface FlagsmithConfig {
109
112
  */
110
113
  offlineHandler?: BaseOfflineHandler;
111
114
  }
112
- export interface ITraitConfig {
115
+ /**
116
+ * Represents the configuration for a trait in Flagsmith.
117
+ *
118
+ * @property value The {@link FlagsmithTraitValue} for this trait.
119
+ * @property [transient] Indicates whether the trait should be persisted when used in a remote flag evaluation context.
120
+ * Defaults to false.
121
+ */
122
+ export interface TraitConfig {
113
123
  value: FlagsmithTraitValue;
114
124
  transient?: boolean;
115
125
  }
116
- export declare type FlagsmithTraitValue = IFlagsmithValue;
126
+ export declare type FlagsmithTraitValue = FlagsmithValue;
@@ -1,9 +1,9 @@
1
- import { Fetch, FlagsmithTraitValue, ITraitConfig } from './types.js';
2
- import { Dispatcher } from "undici-types";
1
+ import { Fetch, FlagsmithTraitValue, TraitConfig } from './types.js';
2
+ import { Dispatcher } from 'undici-types';
3
3
  type Traits = {
4
- [key: string]: ITraitConfig | FlagsmithTraitValue;
4
+ [key: string]: TraitConfig | FlagsmithTraitValue;
5
5
  };
6
- export declare function isTraitConfig(traitValue: ITraitConfig | FlagsmithTraitValue): traitValue is ITraitConfig;
6
+ export declare function isTraitConfig(traitValue: TraitConfig | FlagsmithTraitValue): traitValue is TraitConfig;
7
7
  export declare function generateIdentitiesData(identifier: string, traits: Traits, transient: boolean): {
8
8
  identifier: string;
9
9
  traits: ({
@@ -7,13 +7,13 @@ export function generateIdentitiesData(identifier, traits, transient) {
7
7
  return {
8
8
  trait_key: key,
9
9
  trait_value: value?.value,
10
- transient: value?.transient,
10
+ transient: value?.transient
11
11
  };
12
12
  }
13
13
  else {
14
14
  return {
15
15
  trait_key: key,
16
- trait_value: value,
16
+ trait_value: value
17
17
  };
18
18
  }
19
19
  });
@@ -15,8 +15,8 @@ export function buildEnvironmentModel(environmentJSON: any) {
15
15
  );
16
16
  environmentModel.featureStates = featureStates;
17
17
  if (!!environmentJSON.identity_overrides) {
18
- environmentModel.identityOverrides = environmentJSON.identity_overrides.map((identityData: any) =>
19
- buildIdentityModel(identityData)
18
+ environmentModel.identityOverrides = environmentJSON.identity_overrides.map(
19
+ (identityData: any) => buildIdentityModel(identityData)
20
20
  );
21
21
  }
22
22
  return environmentModel;
@@ -1,4 +1,4 @@
1
- import { randomUUID as uuidv4 } from "node:crypto";
1
+ import { randomUUID as uuidv4 } from 'node:crypto';
2
2
  import { getHashedPercentateForObjIds } from '../utils/hashing/index.js';
3
3
 
4
4
  export class FeatureModel {
@@ -19,23 +19,23 @@ export function buildFeatureStateModel(featuresStateModelJSON: any): FeatureStat
19
19
  featuresStateModelJSON.featurestate_uuid
20
20
  );
21
21
 
22
- featureStateModel.featureSegment = featuresStateModelJSON.feature_segment ?
23
- buildFeatureSegment(featuresStateModelJSON.feature_segment) :
24
- undefined;
22
+ featureStateModel.featureSegment = featuresStateModelJSON.feature_segment
23
+ ? buildFeatureSegment(featuresStateModelJSON.feature_segment)
24
+ : undefined;
25
25
 
26
26
  const multivariateFeatureStateValues = featuresStateModelJSON.multivariate_feature_state_values
27
27
  ? featuresStateModelJSON.multivariate_feature_state_values.map((fsv: any) => {
28
- const featureOption = new MultivariateFeatureOptionModel(
29
- fsv.multivariate_feature_option.value,
30
- fsv.multivariate_feature_option.id
31
- );
32
- return new MultivariateFeatureStateValueModel(
33
- featureOption,
34
- fsv.percentage_allocation,
35
- fsv.id,
36
- fsv.mv_fs_value_uuid
37
- );
38
- })
28
+ const featureOption = new MultivariateFeatureOptionModel(
29
+ fsv.multivariate_feature_option.value,
30
+ fsv.multivariate_feature_option.id
31
+ );
32
+ return new MultivariateFeatureStateValueModel(
33
+ featureOption,
34
+ fsv.percentage_allocation,
35
+ fsv.id,
36
+ fsv.mv_fs_value_uuid
37
+ );
38
+ })
39
39
  : [];
40
40
 
41
41
  featureStateModel.multivariateFeatureStateValues = multivariateFeatureStateValues;
@@ -19,7 +19,7 @@ export class IdentityModel {
19
19
  environmentApiKey: string,
20
20
  identifier: string,
21
21
  identityUuid?: string,
22
- djangoID?: number,
22
+ djangoID?: number
23
23
  ) {
24
24
  this.identityUuid = identityUuid || uuidv4();
25
25
  this.createdDate = Date.parse(created_date) || Date.now();
@@ -7,7 +7,7 @@ import { SegmentModel } from './segments/models.js';
7
7
  import { FeatureStateNotFound } from './utils/errors.js';
8
8
 
9
9
  export { EnvironmentModel } from './environments/models.js';
10
- export { FeatureStateModel } from './features/models.js';
10
+ export { FeatureModel, FeatureStateModel } from './features/models.js';
11
11
  export { IdentityModel } from './identities/models.js';
12
12
  export { TraitModel } from './identities/traits/models.js';
13
13
  export { SegmentModel } from './segments/models.js';
@@ -67,11 +67,10 @@ export function traitsMatchSegmentCondition(
67
67
  }
68
68
  const traits = identityTraits.filter(t => t.traitKey === condition.property_);
69
69
  const trait = traits.length > 0 ? traits[0] : undefined;
70
- if (condition.operator === IS_SET ) {
70
+ if (condition.operator === IS_SET) {
71
71
  return !!trait;
72
- } else if (condition.operator === IS_NOT_SET){
72
+ } else if (condition.operator === IS_NOT_SET) {
73
73
  return trait == undefined;
74
74
  }
75
75
  return trait ? condition.matchesTraitValue(trait.traitValue) : false;
76
-
77
76
  }
@@ -27,21 +27,25 @@ export const matchingFunctions = {
27
27
  thisValue >= otherValue,
28
28
  [CONDITION_OPERATORS.NOT_EQUAL]: (thisValue: any, otherValue: any) => thisValue != otherValue,
29
29
  [CONDITION_OPERATORS.CONTAINS]: (thisValue: any, otherValue: any) =>
30
- !!otherValue && otherValue.includes(thisValue),
30
+ !!otherValue && otherValue.includes(thisValue)
31
31
  };
32
32
 
33
33
  export const semverMatchingFunction = {
34
34
  ...matchingFunctions,
35
- [CONDITION_OPERATORS.EQUAL]: (thisValue: any, otherValue: any) => semver.eq(thisValue, otherValue),
36
- [CONDITION_OPERATORS.GREATER_THAN]: (thisValue: any, otherValue: any) => semver.gt(otherValue, thisValue),
35
+ [CONDITION_OPERATORS.EQUAL]: (thisValue: any, otherValue: any) =>
36
+ semver.eq(thisValue, otherValue),
37
+ [CONDITION_OPERATORS.GREATER_THAN]: (thisValue: any, otherValue: any) =>
38
+ semver.gt(otherValue, thisValue),
37
39
  [CONDITION_OPERATORS.GREATER_THAN_INCLUSIVE]: (thisValue: any, otherValue: any) =>
38
40
  semver.gte(otherValue, thisValue),
39
- [CONDITION_OPERATORS.LESS_THAN]: (thisValue: any, otherValue: any) => semver.gt(thisValue, otherValue),
41
+ [CONDITION_OPERATORS.LESS_THAN]: (thisValue: any, otherValue: any) =>
42
+ semver.gt(thisValue, otherValue),
40
43
  [CONDITION_OPERATORS.LESS_THAN_INCLUSIVE]: (thisValue: any, otherValue: any) =>
41
- semver.gte(thisValue, otherValue),
42
- }
44
+ semver.gte(thisValue, otherValue)
45
+ };
43
46
 
44
- export const getMatchingFunctions = (semver: boolean) => (semver ? semverMatchingFunction : matchingFunctions);
47
+ export const getMatchingFunctions = (semver: boolean) =>
48
+ semver ? semverMatchingFunction : matchingFunctions;
45
49
 
46
50
  export class SegmentConditionModel {
47
51
  EXCEPTION_OPERATOR_METHODS: { [key: string]: string } = {
@@ -55,7 +59,11 @@ export class SegmentConditionModel {
55
59
  value: string | null | undefined;
56
60
  property_: string | null | undefined;
57
61
 
58
- constructor(operator: string, value?: string | null | undefined, property?: string | null | undefined) {
62
+ constructor(
63
+ operator: string,
64
+ value?: string | null | undefined,
65
+ property?: string | null | undefined
66
+ ) {
59
67
  this.operator = operator;
60
68
  this.value = value;
61
69
  this.property_ = property;
@@ -64,24 +72,26 @@ export class SegmentConditionModel {
64
72
  matchesTraitValue(traitValue: any) {
65
73
  const evaluators: { [key: string]: CallableFunction } = {
66
74
  evaluateNotContains: (traitValue: any) => {
67
- return typeof traitValue == "string" &&
75
+ return (
76
+ typeof traitValue == 'string' &&
68
77
  !!this.value &&
69
- !traitValue.includes(this.value?.toString());
78
+ !traitValue.includes(this.value?.toString())
79
+ );
70
80
  },
71
81
  evaluateRegex: (traitValue: any) => {
72
82
  return !!this.value && !!traitValue?.toString().match(new RegExp(this.value));
73
83
  },
74
84
  evaluateModulo: (traitValue: any) => {
75
85
  if (isNaN(parseFloat(traitValue)) || !this.value) {
76
- return false
86
+ return false;
77
87
  }
78
- const parts = (this.value).split("|");
88
+ const parts = this.value.split('|');
79
89
  const [divisor, reminder] = [parseFloat(parts[0]), parseFloat(parts[1])];
80
- return traitValue % divisor === reminder
90
+ return traitValue % divisor === reminder;
81
91
  },
82
92
  evaluateIn: (traitValue: any) => {
83
- return this.value?.split(',').includes(traitValue.toString())
84
- },
93
+ return this.value?.split(',').includes(traitValue.toString());
94
+ }
85
95
  };
86
96
 
87
97
  // TODO: move this logic to the evaluator module
@@ -1,6 +1,6 @@
1
- import {BinaryLike, createHash} from "node:crypto";
1
+ import { BinaryLike, createHash } from 'node:crypto';
2
2
 
3
- const md5 = (data: BinaryLike) => createHash('md5').update(data).digest('hex')
3
+ const md5 = (data: BinaryLike) => createHash('md5').update(data).digest('hex');
4
4
 
5
5
  const makeRepeated = (arr: Array<any>, repeats: number) =>
6
6
  Array.from({ length: repeats }, () => arr).flat();
@@ -18,7 +18,7 @@ export function getHashedPercentateForObjIds(objectIds: Array<any>, iterations =
18
18
  let toHash = makeRepeated(objectIds, iterations).join(',');
19
19
  const hashedValue = md5(toHash);
20
20
  const hashedInt = BigInt('0x' + hashedValue);
21
- const value = (Number((hashedInt % 9999n)) / 9998.0) * 100;
21
+ const value = (Number(hashedInt % 9999n) / 9998.0) * 100;
22
22
 
23
23
  // we ignore this for it's nearly impossible use case to catch
24
24
  /* istanbul ignore next */
@@ -1,6 +1,8 @@
1
- import { removeSemverSuffix } from "../segments/util.js";
1
+ import { removeSemverSuffix } from '../segments/util.js';
2
2
 
3
- export function getCastingFunction(traitType: 'boolean' | 'string' | 'number' | 'semver' | any): CallableFunction {
3
+ export function getCastingFunction(
4
+ traitType: 'boolean' | 'string' | 'number' | 'semver' | any
5
+ ): CallableFunction {
4
6
  switch (traitType) {
5
7
  case 'boolean':
6
8
  return (x: any) => !['False', 'false'].includes(x);
package/index.ts CHANGED
@@ -1,29 +1,26 @@
1
1
  export {
2
- AnalyticsProcessor,
3
- AnalyticsProcessorOptions,
4
- FlagsmithAPIError,
5
- FlagsmithClientError,
6
- EnvironmentDataPollingManager,
7
- FlagsmithCache,
8
- DefaultFlag,
9
- Flags,
10
- Flagsmith,
2
+ AnalyticsProcessor,
3
+ AnalyticsProcessorOptions,
4
+ FlagsmithAPIError,
5
+ FlagsmithClientError,
6
+ EnvironmentDataPollingManager,
7
+ FlagsmithCache,
8
+ BaseFlag,
9
+ DefaultFlag,
10
+ Flags,
11
+ Flagsmith
11
12
  } from './sdk/index.js';
12
13
 
13
- export {
14
- BaseOfflineHandler,
15
- LocalFileHandler,
16
- } from './sdk/offline_handlers.js';
14
+ export { BaseOfflineHandler, LocalFileHandler } from './sdk/offline_handlers.js';
17
15
 
18
- export {
19
- FlagsmithConfig
20
- } from './sdk/types.js'
16
+ export { FlagsmithConfig, FlagsmithValue, TraitConfig } from './sdk/types.js';
21
17
 
22
18
  export {
23
- EnvironmentModel,
24
- FeatureStateModel,
25
- IdentityModel,
26
- TraitModel,
27
- SegmentModel,
28
- OrganisationModel
19
+ EnvironmentModel,
20
+ FeatureModel,
21
+ FeatureStateModel,
22
+ IdentityModel,
23
+ TraitModel,
24
+ SegmentModel,
25
+ OrganisationModel
29
26
  } from './flagsmith-engine/index.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flagsmith-nodejs",
3
- "version": "6.0.1",
3
+ "version": "6.1.0",
4
4
  "description": "Flagsmith lets you manage features flags and remote config across web, mobile and server side applications. Deliver true Continuous Integration. Get builds out faster. Control who has access to new features.",
5
5
  "main": "./build/cjs/index.js",
6
6
  "type": "module",
package/sdk/analytics.ts CHANGED
@@ -1,13 +1,13 @@
1
1
  import { pino, Logger } from 'pino';
2
- import { Fetch } from "./types.js";
3
- import { FlagsmithConfig } from "./types.js";
2
+ import { Fetch } from './types.js';
3
+ import { FlagsmithConfig } from './types.js';
4
4
 
5
5
  export const ANALYTICS_ENDPOINT = './analytics/flags/';
6
6
 
7
7
  /** Duration in seconds to wait before trying to flush collected data after {@link trackFeature} is called. **/
8
8
  const ANALYTICS_TIMER = 10;
9
9
 
10
- const DEFAULT_REQUEST_TIMEOUT_MS = 3000
10
+ const DEFAULT_REQUEST_TIMEOUT_MS = 3000;
11
11
 
12
12
  export interface AnalyticsProcessorOptions {
13
13
  /** URL of the Flagsmith analytics events API endpoint
@@ -20,7 +20,7 @@ export interface AnalyticsProcessorOptions {
20
20
  requestTimeoutMs?: number;
21
21
  logger?: Logger;
22
22
  /** Custom {@link fetch} implementation to use for API requests. **/
23
- fetch?: Fetch
23
+ fetch?: Fetch;
24
24
 
25
25
  /** @deprecated Use {@link analyticsUrl} instead. **/
26
26
  baseApiUrl?: string;
@@ -76,7 +76,9 @@ export class AnalyticsProcessor {
76
76
  } catch (error) {
77
77
  // We don't want failing to write analytics to cause any exceptions in the main
78
78
  // thread so we just swallow them here.
79
- this.logger.warn('Failed to post analytics to Flagsmith API. Not clearing data, will retry.')
79
+ this.logger.warn(
80
+ 'Failed to post analytics to Flagsmith API. Not clearing data, will retry.'
81
+ );
80
82
  return;
81
83
  } finally {
82
84
  this.currentFlush = undefined;