flagsmith-nodejs 2.5.2 → 3.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 (47) hide show
  1. package/.github/workflows/publish.yml +25 -0
  2. package/build/flagsmith-engine/identities/models.d.ts +1 -1
  3. package/build/flagsmith-engine/identities/models.js +2 -1
  4. package/build/flagsmith-engine/segments/evaluators.js +3 -2
  5. package/examples/README.md +3 -0
  6. package/flagsmith-engine/identities/models.ts +3 -1
  7. package/flagsmith-engine/segments/evaluators.ts +4 -3
  8. package/package.json +1 -1
  9. package/tests/engine/unit/segments/segment_evaluators.test.ts +46 -6
  10. package/.vscode/launch.json +0 -18
  11. package/examples/api-proxy/.babelrc +0 -3
  12. package/examples/api-proxy/.eslintrc +0 -8
  13. package/examples/api-proxy/README.md +0 -12
  14. package/examples/api-proxy/package-lock.json +0 -10889
  15. package/examples/api-proxy/package.json +0 -57
  16. package/examples/api-proxy/src/api/index.js +0 -42
  17. package/examples/api-proxy/src/index.js +0 -29
  18. package/examples/basic/.babelrc +0 -3
  19. package/examples/basic/.eslintrc +0 -8
  20. package/examples/basic/README.md +0 -10
  21. package/examples/basic/package-lock.json +0 -10779
  22. package/examples/basic/package.json +0 -56
  23. package/examples/basic/src/api/index.js +0 -33
  24. package/examples/basic/src/index.js +0 -29
  25. package/examples/caching/.babelrc +0 -3
  26. package/examples/caching/.eslintrc +0 -8
  27. package/examples/caching/README.md +0 -9
  28. package/examples/caching/package-lock.json +0 -6750
  29. package/examples/caching/package.json +0 -56
  30. package/examples/caching/src/api/index.js +0 -38
  31. package/examples/caching/src/index.js +0 -29
  32. package/examples/custom-fetch-agent/.babelrc +0 -3
  33. package/examples/custom-fetch-agent/.eslintrc +0 -8
  34. package/examples/custom-fetch-agent/README.md +0 -12
  35. package/examples/custom-fetch-agent/package-lock.json +0 -6750
  36. package/examples/custom-fetch-agent/package.json +0 -56
  37. package/examples/custom-fetch-agent/src/api/index.js +0 -34
  38. package/examples/custom-fetch-agent/src/index.js +0 -29
  39. package/examples/local-evaluation/.babelrc +0 -3
  40. package/examples/local-evaluation/.eslintrc +0 -8
  41. package/examples/local-evaluation/README.md +0 -18
  42. package/examples/local-evaluation/package-lock.json +0 -6668
  43. package/examples/local-evaluation/package.json +0 -56
  44. package/examples/local-evaluation/src/api/index.js +0 -39
  45. package/examples/local-evaluation/src/index.js +0 -29
  46. package/tests/engine/engine-tests/engine-test-data/data/environment_n9fbf9h3v4fFgH3U3ngWhb.json +0 -12591
  47. package/tests/engine/engine-tests/engine-test-data/readme.md +0 -30
@@ -0,0 +1,25 @@
1
+ name: Publish NPM Package
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - '*'
7
+
8
+ jobs:
9
+ package:
10
+ runs-on: ubuntu-latest
11
+ name: Publish NPM Package
12
+
13
+ steps:
14
+ - name: Cloning repo
15
+ uses: actions/checkout@v3
16
+
17
+ - uses: actions/setup-node@v3
18
+ with:
19
+ node-version: '16.x'
20
+ registry-url: 'https://registry.npmjs.org'
21
+
22
+ - run: npm ci
23
+ - run: npm run deploy
24
+ env:
25
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
@@ -8,7 +8,7 @@ export declare class IdentityModel {
8
8
  identityTraits: TraitModel[];
9
9
  identityUuid: string;
10
10
  djangoID: number | undefined;
11
- constructor(created_date: string, identityTraits: TraitModel[], identityFeatures: IdentityFeaturesList, environmentApiKey: string, identifier: string, identityUuid?: string);
11
+ constructor(created_date: string, identityTraits: TraitModel[], identityFeatures: IdentityFeaturesList, environmentApiKey: string, identifier: string, identityUuid?: string, djangoID?: number);
12
12
  get compositeKey(): string;
13
13
  static generateCompositeKey(env_key: string, identifier: string): string;
14
14
  updateTraits(traits: TraitModel[]): void;
@@ -40,13 +40,14 @@ exports.IdentityModel = void 0;
40
40
  var collections_1 = require("../utils/collections");
41
41
  var uuidv4 = require('uuid').v4;
42
42
  var IdentityModel = /** @class */ (function () {
43
- function IdentityModel(created_date, identityTraits, identityFeatures, environmentApiKey, identifier, identityUuid) {
43
+ function IdentityModel(created_date, identityTraits, identityFeatures, environmentApiKey, identifier, identityUuid, djangoID) {
44
44
  this.identityUuid = identityUuid || uuidv4();
45
45
  this.createdDate = Date.parse(created_date) || Date.now();
46
46
  this.identityTraits = identityTraits;
47
47
  this.identityFeatures = new (collections_1.IdentityFeaturesList.bind.apply(collections_1.IdentityFeaturesList, __spreadArray([void 0], __read(identityFeatures), false)))();
48
48
  this.environmentApiKey = environmentApiKey;
49
49
  this.identifier = identifier;
50
+ this.djangoID = djangoID;
50
51
  }
51
52
  Object.defineProperty(IdentityModel.prototype, "compositeKey", {
52
53
  get: function () {
@@ -12,7 +12,7 @@ exports.getIdentitySegments = getIdentitySegments;
12
12
  function evaluateIdentityInSegment(identity, segment, overrideTraits) {
13
13
  return (segment.rules.length > 0 &&
14
14
  segment.rules.filter(function (rule) {
15
- return traitsMatchSegmentRule(overrideTraits || identity.identityTraits, rule, segment.id, identity.compositeKey);
15
+ return traitsMatchSegmentRule(overrideTraits || identity.identityTraits, rule, segment.id, identity.djangoID || identity.compositeKey);
16
16
  }).length === segment.rules.length);
17
17
  }
18
18
  exports.evaluateIdentityInSegment = evaluateIdentityInSegment;
@@ -29,7 +29,8 @@ function traitsMatchSegmentRule(identityTraits, rule, segmentId, identityId) {
29
29
  }
30
30
  function traitsMatchSegmentCondition(identityTraits, condition, segmentId, identityId) {
31
31
  if (condition.operator == constants_1.PERCENTAGE_SPLIT) {
32
- return (0, hashing_1.getHashedPercentateForObjIds)([segmentId, identityId]) <= parseFloat(String(condition.value));
32
+ var hashedPercentage = (0, hashing_1.getHashedPercentateForObjIds)([segmentId, identityId]);
33
+ return hashedPercentage <= parseFloat(String(condition.value));
33
34
  }
34
35
  var traits = identityTraits.filter(function (t) { return t.traitKey === condition.property_; });
35
36
  var trait = traits.length > 0 ? traits[0] : undefined;
@@ -0,0 +1,3 @@
1
+ # Flagsmith NodeJS Examples
2
+
3
+ Check out our [NodeJS Examples repository](https://github.com/Flagsmith/flagsmith-nodejs-examples).
@@ -19,7 +19,8 @@ export class IdentityModel {
19
19
  identityFeatures: IdentityFeaturesList,
20
20
  environmentApiKey: string,
21
21
  identifier: string,
22
- identityUuid?: string
22
+ identityUuid?: string,
23
+ djangoID?: number
23
24
  ) {
24
25
  this.identityUuid = identityUuid || uuidv4();
25
26
  this.createdDate = Date.parse(created_date) || Date.now();
@@ -27,6 +28,7 @@ export class IdentityModel {
27
28
  this.identityFeatures = new IdentityFeaturesList(...identityFeatures);
28
29
  this.environmentApiKey = environmentApiKey;
29
30
  this.identifier = identifier;
31
+ this.djangoID = djangoID;
30
32
  }
31
33
 
32
34
  get compositeKey() {
@@ -27,7 +27,7 @@ export function evaluateIdentityInSegment(
27
27
  overrideTraits || identity.identityTraits,
28
28
  rule,
29
29
  segment.id,
30
- identity.compositeKey
30
+ identity.djangoID || identity.compositeKey
31
31
  )
32
32
  ).length === segment.rules.length
33
33
  );
@@ -62,7 +62,8 @@ export function traitsMatchSegmentCondition(
62
62
  identityId: number | string
63
63
  ): boolean {
64
64
  if (condition.operator == PERCENTAGE_SPLIT) {
65
- return getHashedPercentateForObjIds([segmentId, identityId]) <= parseFloat(String(condition.value));
65
+ var hashedPercentage = getHashedPercentateForObjIds([segmentId, identityId]);
66
+ return hashedPercentage <= parseFloat(String(condition.value));
66
67
  }
67
68
  const traits = identityTraits.filter(t => t.traitKey === condition.property_);
68
69
  const trait = traits.length > 0 ? traits[0] : undefined;
@@ -73,4 +74,4 @@ export function traitsMatchSegmentCondition(
73
74
  }
74
75
  return trait ? condition.matchesTraitValue(trait.traitValue) : false;
75
76
 
76
- }
77
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flagsmith-nodejs",
3
- "version": "2.5.2",
3
+ "version": "3.0.1",
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/index.js",
6
6
  "repository": {
@@ -1,11 +1,21 @@
1
1
  import {
2
+ ALL_RULE,
2
3
  CONDITION_OPERATORS,
4
+ PERCENTAGE_SPLIT,
3
5
  } from '../../../../flagsmith-engine/segments/constants';
4
- import {
5
- SegmentConditionModel,
6
- } from '../../../../flagsmith-engine/segments/models';
7
- import {traitsMatchSegmentCondition} from "../../../../flagsmith-engine/segments/evaluators";
8
- import {TraitModel} from "../../../../flagsmith-engine";
6
+ import {SegmentConditionModel} from '../../../../flagsmith-engine/segments/models';
7
+ import {traitsMatchSegmentCondition, evaluateIdentityInSegment} from "../../../../flagsmith-engine/segments/evaluators";
8
+ import {TraitModel, IdentityModel} from "../../../../flagsmith-engine";
9
+ import {environment} from "../utils";
10
+ import { buildSegmentModel } from '../../../../flagsmith-engine/segments/util';
11
+ import { getHashedPercentateForObjIds } from '../../../../flagsmith-engine/utils/hashing';
12
+
13
+
14
+ // todo: work out how to implement this in a test function or before hook
15
+ jest.mock('../../../../flagsmith-engine/utils/hashing', () => ({
16
+ getHashedPercentateForObjIds: jest.fn(() => 1)
17
+ }));
18
+
9
19
 
10
20
  let traitExistenceTestCases: [string, string | null | undefined, string | null | undefined, TraitModel [],boolean][] = [
11
21
  [CONDITION_OPERATORS.IS_SET,'foo', null,[] , false],
@@ -24,4 +34,34 @@ test('test_traits_match_segment_condition_for_trait_existence_operators', () =>
24
34
  traitsMatchSegmentCondition (traits, segmentModel, 'any','any')
25
35
  ).toBe(expectedResult);
26
36
  }
27
- });
37
+ });
38
+
39
+
40
+ test('evaluateIdentityInSegment uses django ID for hashed percentage when present', () => {
41
+ var identityModel = new IdentityModel(Date.now().toString(), [], [], environment().apiKey, 'identity_1', undefined, 1);
42
+ const segmentDefinition = {
43
+ id: 1,
44
+ name: 'percentage_split_segment',
45
+ rules: [
46
+ {
47
+ type: ALL_RULE,
48
+ conditions: [
49
+ {
50
+ operator: PERCENTAGE_SPLIT,
51
+ property_: null,
52
+ value: "10"
53
+ }
54
+ ],
55
+ rules: []
56
+ }
57
+ ],
58
+ feature_states: []
59
+ };
60
+ const segmentModel = buildSegmentModel(segmentDefinition);
61
+
62
+ var result = evaluateIdentityInSegment(identityModel, segmentModel);
63
+
64
+ expect(result).toBe(true);
65
+ expect(getHashedPercentateForObjIds).toHaveBeenCalledTimes(1)
66
+ expect(getHashedPercentateForObjIds).toHaveBeenCalledWith([segmentModel.id, identityModel.djangoID])
67
+ });
@@ -1,18 +0,0 @@
1
- {
2
- "version": "1.0.0",
3
- "configurations": [
4
- {
5
- "type": "node",
6
- "request": "launch",
7
- "name": "Jest: current file",
8
- //"env": { "NODE_ENV": "test" },
9
- "program": "${workspaceFolder}/node_modules/.bin/jest",
10
- "args": ["${file}", "--config", "jest.config.js"],
11
- "console": "integratedTerminal",
12
- "disableOptimisticBPs": true,
13
- "windows": {
14
- "program": "${workspaceFolder}/node_modules/jest/bin/jest"
15
- }
16
- }
17
- ]
18
- }
@@ -1,3 +0,0 @@
1
- {
2
- "presets": ["@babel/preset-env"]
3
- }
@@ -1,8 +0,0 @@
1
- {
2
- "extends": ["eslint:recommended", "prettier"],
3
- "parserOptions": {
4
- "ecmaVersion": 2018,
5
- "sourceType": "module"
6
- },
7
- "env": { "es6": true, "node": true }
8
- }
@@ -1,12 +0,0 @@
1
- <img width="100%" src="https://github.com/Flagsmith/flagsmith/raw/main/static-files/hero.png"/>
2
-
3
- # Flagsmith Node.js example with custom fetch agent
4
-
5
- This is a simple Flagsmith Node.js example in local evaluation modes with a custom fetch agent. Using a custom fetch agent lets allows you to specify networking related options such as keep alive and socket timeout, read more on this [here](https://github.com/node-fetch/node-fetch#custom-agent).
6
-
7
- ## Running the example
8
-
9
- ```shell
10
- npm i
11
- npm run dev
12
- ```