flagsmith-nodejs 2.0.0-beta.6 → 2.0.0-beta.7

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 (49) hide show
  1. package/.github/workflows/pull_request.yaml +37 -29
  2. package/README.md +7 -0
  3. package/build/flagsmith-engine/features/models.d.ts +0 -1
  4. package/build/flagsmith-engine/features/models.js +0 -3
  5. package/build/flagsmith-engine/identities/models.d.ts +1 -1
  6. package/build/flagsmith-engine/identities/models.js +1 -1
  7. package/build/flagsmith-engine/index.js +1 -1
  8. package/build/flagsmith-engine/organisations/models.d.ts +1 -1
  9. package/build/flagsmith-engine/organisations/models.js +1 -1
  10. package/build/flagsmith-engine/segments/models.js +0 -3
  11. package/build/flagsmith-engine/utils/collections.d.ts +0 -1
  12. package/build/flagsmith-engine/utils/collections.js +0 -71
  13. package/build/flagsmith-engine/utils/hashing/index.js +5 -2
  14. package/build/sdk/analytics.js +0 -1
  15. package/build/sdk/index.d.ts +5 -0
  16. package/build/sdk/index.js +152 -54
  17. package/build/sdk/polling_manager.js +0 -1
  18. package/build/sdk/types.d.ts +7 -0
  19. package/build/sdk/types.js +2 -0
  20. package/example/server/api/index.js +1 -1
  21. package/flagsmith-engine/features/models.ts +0 -4
  22. package/flagsmith-engine/identities/models.ts +1 -1
  23. package/flagsmith-engine/index.ts +1 -1
  24. package/flagsmith-engine/organisations/models.ts +1 -1
  25. package/flagsmith-engine/segments/models.ts +0 -2
  26. package/flagsmith-engine/utils/collections.ts +1 -12
  27. package/flagsmith-engine/utils/hashing/index.ts +5 -2
  28. package/package.json +2 -2
  29. package/sdk/analytics.ts +0 -2
  30. package/sdk/index.ts +83 -26
  31. package/sdk/polling_manager.ts +0 -1
  32. package/sdk/types.ts +8 -0
  33. package/tests/engine/unit/{egine.test.ts → engine.test.ts} +20 -0
  34. package/tests/engine/unit/features/models.test.ts +7 -3
  35. package/tests/engine/unit/identities/identities_builders.test.ts +13 -0
  36. package/tests/engine/unit/identities/identities_models.test.ts +3 -14
  37. package/tests/engine/unit/organization/models.test.ts +1 -1
  38. package/tests/engine/unit/segments/segments_model.test.ts +2 -1
  39. package/tests/engine/unit/utils.ts +1 -1
  40. package/tests/sdk/analytics.test.ts +11 -0
  41. package/tests/sdk/flagsmith-cache.test.ts +150 -0
  42. package/tests/sdk/flagsmith-environment-flags.test.ts +197 -0
  43. package/tests/sdk/flagsmith-identity-flags.test.ts +140 -0
  44. package/tests/sdk/flagsmith.test.ts +100 -85
  45. package/tests/sdk/polling.test.ts +25 -0
  46. package/tests/sdk/utils.ts +21 -2
  47. package/tsconfig.json +1 -1
  48. package/tests/engine/engine-tests/engine-test-data/data/environment_n9fbf9h3v4fFgH3U3ngWhb.json +0 -12393
  49. package/tests/engine/engine-tests/engine-test-data/readme.md +0 -30
@@ -1,33 +1,41 @@
1
1
  name: Unit/Integration Tests
2
2
 
3
3
  on:
4
- pull_request:
5
- types:
6
- - opened
7
- - synchronize
8
- - reopened
9
- - ready_for_review
10
- push:
11
- branches:
12
- - main
4
+ pull_request:
5
+ types:
6
+ - opened
7
+ - synchronize
8
+ - reopened
9
+ - ready_for_review
10
+ push:
11
+ branches:
12
+ - main
13
13
  jobs:
14
- build-and-test:
15
- runs-on: ubuntu-latest
16
- steps:
17
- - uses: actions/checkout@v2
18
- - uses: actions/setup-node@v1
19
- with:
20
- node-version: '15.x'
21
- - name: cache node modules
22
- uses: actions/cache@v1
23
- with:
24
- path: ~/.npm # npm cache files are stored in `~/.npm` on Linux/macOS
25
- key: npm-${{ hashFiles('package-lock.json') }}
26
- restore-keys: |
27
- npm-${{ hashFiles('package-lock.json') }}
28
- npm-
29
- - run: npm i -g npm@7.0.2
30
- - run: npm install
31
- - run: npm test
32
- env:
33
- CI: true
14
+ build-and-test:
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - uses: actions/checkout@v2
18
+ - name: Checkout submodules # checkout rest
19
+ shell: bash
20
+ run: |
21
+ # If your submodules are configured to use SSH instead of HTTPS please uncomment the following line
22
+ git config --global url."https://github.com/".insteadOf "git@github.com:"
23
+ auth_header="$(git config --local --get http.https://github.com/.extraheader)"
24
+ git submodule sync --recursive
25
+ git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1
26
+ - uses: actions/setup-node@v1
27
+ with:
28
+ node-version: "15.x"
29
+ - name: cache node modules
30
+ uses: actions/cache@v1
31
+ with:
32
+ path: ~/.npm # npm cache files are stored in `~/.npm` on Linux/macOS
33
+ key: npm-${{ hashFiles('package-lock.json') }}
34
+ restore-keys: |
35
+ npm-${{ hashFiles('package-lock.json') }}
36
+ npm-
37
+ - run: npm i -g npm@7.0.2
38
+ - run: npm install
39
+ - run: npm test
40
+ env:
41
+ CI: true
package/README.md CHANGED
@@ -19,6 +19,13 @@ Please read [CONTRIBUTING.md](https://gist.github.com/kyle-ssg/c36a03aebe492e45c
19
19
 
20
20
  If you encounter a bug or feature request we would like to hear about it. Before you submit an issue please search existing issues in order to prevent duplicates.
21
21
 
22
+ ## Testing
23
+
24
+ To run the local tests you need to run following command beforehand:
25
+ ```
26
+ git submodule add git@github.com:Flagsmith/engine-test-data.git tests/engine/engine-tests/engine-test-data/
27
+ ```
28
+
22
29
  ## Get in touch
23
30
 
24
31
  If you have any questions about our projects you can email <a href="mailto:support@flagsmith.com">support@flagsmith.com</a>.
@@ -27,6 +27,5 @@ export declare class FeatureStateModel {
27
27
  constructor(feature: FeatureModel, enabled: boolean, djangoID: number, value?: any, featurestateUuid?: string);
28
28
  setValue(value: any): void;
29
29
  getValue(identityId?: number | string): any;
30
- get_feature_state_value(): any;
31
30
  getMultivariateValue(identityID: number | string): any;
32
31
  }
@@ -65,9 +65,6 @@ var FeatureStateModel = /** @class */ (function () {
65
65
  }
66
66
  return this.value;
67
67
  };
68
- FeatureStateModel.prototype.get_feature_state_value = function () {
69
- return this.getValue();
70
- };
71
68
  FeatureStateModel.prototype.getMultivariateValue = function (identityID) {
72
69
  var e_1, _a;
73
70
  var percentageValue = (0, hashing_1.getHashedPercentateForObjIds)([
@@ -11,5 +11,5 @@ export declare class IdentityModel {
11
11
  constructor(created_date: string, identityTraits: TraitModel[], identityFeatures: IdentityFeaturesList, environmentApiKey: string, identifier: string, identityUuid?: string);
12
12
  get compositeKey(): string;
13
13
  static generateCompositeKey(env_key: string, identifier: string): string;
14
- update_traits(traits: TraitModel[]): void;
14
+ updateTraits(traits: TraitModel[]): void;
15
15
  }
@@ -58,7 +58,7 @@ var IdentityModel = /** @class */ (function () {
58
58
  IdentityModel.generateCompositeKey = function (env_key, identifier) {
59
59
  return "".concat(env_key, "_").concat(identifier);
60
60
  };
61
- IdentityModel.prototype.update_traits = function (traits) {
61
+ IdentityModel.prototype.updateTraits = function (traits) {
62
62
  var e_1, _a, e_2, _b, e_3, _c;
63
63
  var existingTraits = new Map();
64
64
  try {
@@ -99,7 +99,7 @@ exports.getIdentityFeatureStates = getIdentityFeatureStates;
99
99
  function getEnvironmentFeatureState(environment, featureName) {
100
100
  var featuresStates = environment.featureStates.filter(function (f) { return f.feature.name === featureName; });
101
101
  if (featuresStates.length === 0) {
102
- throw new Error('Feature State Not Found');
102
+ throw new errors_1.FeatureStateNotFound('Feature State Not Found');
103
103
  }
104
104
  return featuresStates[0];
105
105
  }
@@ -5,5 +5,5 @@ export declare class OrganisationModel {
5
5
  stopServingFlags: boolean;
6
6
  persistTraitData: boolean;
7
7
  constructor(id: number, name: string, featureAnalytics: boolean, stopServingFlags: boolean, persistTraitData: boolean);
8
- get unique_slug(): string;
8
+ get uniqueSlug(): string;
9
9
  }
@@ -9,7 +9,7 @@ var OrganisationModel = /** @class */ (function () {
9
9
  this.stopServingFlags = stopServingFlags;
10
10
  this.persistTraitData = persistTraitData;
11
11
  }
12
- Object.defineProperty(OrganisationModel.prototype, "unique_slug", {
12
+ Object.defineProperty(OrganisationModel.prototype, "uniqueSlug", {
13
13
  get: function () {
14
14
  return this.id.toString() + '-' + this.name;
15
15
  },
@@ -22,9 +22,6 @@ exports.matchingFunctions = (_a = {},
22
22
  _a[constants_1.CONDITION_OPERATORS.CONTAINS] = function (thisValue, otherValue) {
23
23
  return otherValue.includes(thisValue);
24
24
  },
25
- _a[constants_1.CONDITION_OPERATORS.NOT_CONTAINS] = function (thisValue, otherValue) {
26
- return !otherValue.includes(thisValue);
27
- },
28
25
  _a);
29
26
  var SegmentConditionModel = /** @class */ (function () {
30
27
  function SegmentConditionModel(operator, value, property) {
@@ -1,4 +1,3 @@
1
1
  import { FeatureStateModel } from '../features/models';
2
2
  export declare class IdentityFeaturesList extends Array<FeatureStateModel> {
3
- push(...e: FeatureStateModel[]): number;
4
3
  }
@@ -14,42 +14,6 @@ var __extends = (this && this.__extends) || (function () {
14
14
  d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
15
  };
16
16
  })();
17
- var __values = (this && this.__values) || function(o) {
18
- var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
19
- if (m) return m.call(o);
20
- if (o && typeof o.length === "number") return {
21
- next: function () {
22
- if (o && i >= o.length) o = void 0;
23
- return { value: o && o[i++], done: !o };
24
- }
25
- };
26
- throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
27
- };
28
- var __read = (this && this.__read) || function (o, n) {
29
- var m = typeof Symbol === "function" && o[Symbol.iterator];
30
- if (!m) return o;
31
- var i = m.call(o), r, ar = [], e;
32
- try {
33
- while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
34
- }
35
- catch (error) { e = { error: error }; }
36
- finally {
37
- try {
38
- if (r && !r.done && (m = i["return"])) m.call(i);
39
- }
40
- finally { if (e) throw e.error; }
41
- }
42
- return ar;
43
- };
44
- var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
45
- if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
46
- if (ar || !(i in from)) {
47
- if (!ar) ar = Array.prototype.slice.call(from, 0, i);
48
- ar[i] = from[i];
49
- }
50
- }
51
- return to.concat(ar || Array.prototype.slice.call(from));
52
- };
53
17
  Object.defineProperty(exports, "__esModule", { value: true });
54
18
  exports.IdentityFeaturesList = void 0;
55
19
  var IdentityFeaturesList = /** @class */ (function (_super) {
@@ -57,41 +21,6 @@ var IdentityFeaturesList = /** @class */ (function (_super) {
57
21
  function IdentityFeaturesList() {
58
22
  return _super !== null && _super.apply(this, arguments) || this;
59
23
  }
60
- IdentityFeaturesList.prototype.push = function () {
61
- var e_1, _a, e_2, _b;
62
- var e = [];
63
- for (var _i = 0; _i < arguments.length; _i++) {
64
- e[_i] = arguments[_i];
65
- }
66
- try {
67
- for (var _c = __values(e.entries()), _d = _c.next(); !_d.done; _d = _c.next()) {
68
- var _e = __read(_d.value, 2), _ = _e[0], item = _e[1];
69
- try {
70
- for (var _f = (e_2 = void 0, __values(this.entries())), _g = _f.next(); !_g.done; _g = _f.next()) {
71
- var _h = __read(_g.value, 2), k = _h[0], v = _h[1];
72
- if (v.djangoID === item.djangoID) {
73
- throw new Error('feature state for this feature already exists');
74
- }
75
- }
76
- }
77
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
78
- finally {
79
- try {
80
- if (_g && !_g.done && (_b = _f.return)) _b.call(_f);
81
- }
82
- finally { if (e_2) throw e_2.error; }
83
- }
84
- }
85
- }
86
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
87
- finally {
88
- try {
89
- if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
90
- }
91
- finally { if (e_1) throw e_1.error; }
92
- }
93
- return _super.prototype.push.apply(this, __spreadArray([], __read(e), false));
94
- };
95
24
  return IdentityFeaturesList;
96
25
  }(Array));
97
26
  exports.IdentityFeaturesList = IdentityFeaturesList;
@@ -45,11 +45,14 @@ function h2d(s) {
45
45
  */
46
46
  function getHashedPercentateForObjIds(objectIds, iterations) {
47
47
  if (iterations === void 0) { iterations = 1; }
48
- var to_hash = makeRepeated(objectIds, iterations).join(',');
49
- var hashedValue = (0, md5_1.default)(to_hash);
48
+ var toHash = makeRepeated(objectIds, iterations).join(',');
49
+ var hashedValue = (0, md5_1.default)(toHash);
50
50
  var hashedInt = (0, big_integer_1.default)(h2d(hashedValue));
51
51
  var value = (hashedInt.mod(9999).toJSNumber() / 9998) * 100;
52
+ // we ignore this for it's nearly impossible use case to catch
53
+ /* istanbul ignore next */
52
54
  if (value === 100) {
55
+ /* istanbul ignore next */
53
56
  return getHashedPercentateForObjIds(objectIds, iterations + 1);
54
57
  }
55
58
  return value;
@@ -44,7 +44,6 @@ var node_fetch_1 = __importDefault(require("node-fetch"));
44
44
  var ANALYTICS_ENDPOINT = 'analytics/flags/';
45
45
  // Used to control how often we send data(in seconds)
46
46
  var ANALYTICS_TIMER = 10;
47
- var delay = function (ms) { return new Promise(function (resolve) { return setTimeout(function () { return resolve(undefined); }, ms); }); };
48
47
  var AnalyticsProcessor = /** @class */ (function () {
49
48
  /**
50
49
  * AnalyticsProcessor is used to track how often individual Flags are evaluated within
@@ -2,6 +2,7 @@ import { EnvironmentModel } from '../flagsmith-engine/environments/models';
2
2
  import { DefaultFlag, Flags } from './models';
3
3
  import { EnvironmentDataPollingManager } from './polling_manager';
4
4
  import { SegmentModel } from '../flagsmith-engine/segments/models';
5
+ import { FlagsmithCache } from './types';
5
6
  export declare class Flagsmith {
6
7
  environmentKey?: string;
7
8
  apiUrl: string;
@@ -19,6 +20,8 @@ export declare class Flagsmith {
19
20
  environmentUrl: string;
20
21
  environmentDataPollingManager?: EnvironmentDataPollingManager;
21
22
  environment: EnvironmentModel;
23
+ private cache?;
24
+ private onEnvironmentChange?;
22
25
  private analyticsProcessor?;
23
26
  /**
24
27
  * A Flagsmith client.
@@ -62,6 +65,8 @@ export declare class Flagsmith {
62
65
  retries?: number;
63
66
  enableAnalytics?: boolean;
64
67
  defaultFlagHandler?: (featureName: string) => DefaultFlag;
68
+ cache?: FlagsmithCache;
69
+ onEnvironmentChange?: (error: Error | null, result: EnvironmentModel) => void;
65
70
  });
66
71
  /**
67
72
  * Get all the default for flags for the current environment.
@@ -124,6 +124,14 @@ var Flagsmith = /** @class */ (function () {
124
124
  this.environmentFlagsUrl = "".concat(this.apiUrl, "flags/");
125
125
  this.identitiesUrl = "".concat(this.apiUrl, "identities/");
126
126
  this.environmentUrl = "".concat(this.apiUrl, "environment-document/");
127
+ this.onEnvironmentChange = data.onEnvironmentChange;
128
+ if (!!data.cache) {
129
+ var missingMethods = ['has', 'get', 'set'].filter(function (method) { return data.cache && !data.cache[method]; });
130
+ if (missingMethods.length > 0) {
131
+ throw new Error("Please implement the following methods in your cache: ".concat(missingMethods.join(', ')));
132
+ }
133
+ this.cache = data.cache;
134
+ }
127
135
  if (this.enableLocalEvaluation) {
128
136
  if (!this.environmentKey.startsWith('ser.')) {
129
137
  console.error('In order to use local evaluation, please generate a server key in the environment settings page.');
@@ -147,12 +155,34 @@ var Flagsmith = /** @class */ (function () {
147
155
  */
148
156
  Flagsmith.prototype.getEnvironmentFlags = function () {
149
157
  return __awaiter(this, void 0, void 0, function () {
158
+ var cachedItem, _a;
150
159
  var _this = this;
151
- return __generator(this, function (_a) {
152
- if (this.environment) {
153
- return [2 /*return*/, new Promise(function (resolve) { return resolve(_this.getEnvironmentFlagsFromDocument()); })];
160
+ return __generator(this, function (_b) {
161
+ switch (_b.label) {
162
+ case 0:
163
+ _a = !!this.cache;
164
+ if (!_a) return [3 /*break*/, 2];
165
+ return [4 /*yield*/, this.cache.get("flags")];
166
+ case 1:
167
+ _a = (_b.sent());
168
+ _b.label = 2;
169
+ case 2:
170
+ cachedItem = _a;
171
+ if (!!cachedItem) {
172
+ return [2 /*return*/, cachedItem];
173
+ }
174
+ if (this.enableLocalEvaluation) {
175
+ return [2 /*return*/, new Promise(function (resolve) {
176
+ return _this.environmentPromise.then(function () {
177
+ resolve(_this.getEnvironmentFlagsFromDocument());
178
+ });
179
+ })];
180
+ }
181
+ if (this.environment) {
182
+ return [2 /*return*/, this.getEnvironmentFlagsFromDocument()];
183
+ }
184
+ return [2 /*return*/, this.getEnvironmentFlagsFromApi()];
154
185
  }
155
- return [2 /*return*/, this.getEnvironmentFlagsFromApi()];
156
186
  });
157
187
  });
158
188
  };
@@ -168,16 +198,35 @@ var Flagsmith = /** @class */ (function () {
168
198
  * @returns Flags object holding all the flags for the given identity.
169
199
  */
170
200
  Flagsmith.prototype.getIdentityFlags = function (identifier, traits) {
171
- var _this = this;
172
- traits = traits || {};
173
- if (this.enableLocalEvaluation) {
174
- return new Promise(function (resolve) {
175
- return _this.environmentPromise.then(function () {
176
- resolve(_this.getIdentityFlagsFromDocument(identifier, traits || {}));
177
- });
201
+ return __awaiter(this, void 0, void 0, function () {
202
+ var cachedItem, _a;
203
+ var _this = this;
204
+ return __generator(this, function (_b) {
205
+ switch (_b.label) {
206
+ case 0:
207
+ _a = !!this.cache;
208
+ if (!_a) return [3 /*break*/, 2];
209
+ return [4 /*yield*/, this.cache.get("flags-".concat(identifier))];
210
+ case 1:
211
+ _a = (_b.sent());
212
+ _b.label = 2;
213
+ case 2:
214
+ cachedItem = _a;
215
+ if (!!cachedItem) {
216
+ return [2 /*return*/, cachedItem];
217
+ }
218
+ traits = traits || {};
219
+ if (this.enableLocalEvaluation) {
220
+ return [2 /*return*/, new Promise(function (resolve) {
221
+ return _this.environmentPromise.then(function () {
222
+ resolve(_this.getIdentityFlagsFromDocument(identifier, traits || {}));
223
+ });
224
+ })];
225
+ }
226
+ return [2 /*return*/, this.getIdentityFlagsFromApi(identifier, traits)];
227
+ }
178
228
  });
179
- }
180
- return this.getIdentityFlagsFromApi(identifier, traits);
229
+ });
181
230
  };
182
231
  /**
183
232
  * Get the segments for the current environment for a given identity. Will also
@@ -215,11 +264,12 @@ var Flagsmith = /** @class */ (function () {
215
264
  */
216
265
  Flagsmith.prototype.updateEnvironment = function () {
217
266
  return __awaiter(this, void 0, void 0, function () {
218
- var request, _a;
267
+ var request, _a, e_1;
219
268
  var _this = this;
220
269
  return __generator(this, function (_b) {
221
270
  switch (_b.label) {
222
271
  case 0:
272
+ _b.trys.push([0, 5, , 6]);
223
273
  request = this.getEnvironmentFromApi();
224
274
  if (!!this.environmentPromise) return [3 /*break*/, 2];
225
275
  this.environmentPromise = request.then(function (res) {
@@ -235,7 +285,18 @@ var Flagsmith = /** @class */ (function () {
235
285
  case 3:
236
286
  _a.environment = _b.sent();
237
287
  _b.label = 4;
238
- case 4: return [2 /*return*/];
288
+ case 4:
289
+ if (this.onEnvironmentChange) {
290
+ this.onEnvironmentChange(null, this.environment);
291
+ }
292
+ return [3 /*break*/, 6];
293
+ case 5:
294
+ e_1 = _b.sent();
295
+ if (this.onEnvironmentChange) {
296
+ this.onEnvironmentChange(e_1, this.environment);
297
+ }
298
+ return [3 /*break*/, 6];
299
+ case 6: return [2 /*return*/];
239
300
  }
240
301
  });
241
302
  });
@@ -243,7 +304,7 @@ var Flagsmith = /** @class */ (function () {
243
304
  Flagsmith.prototype.getJSONResponse = function (url, method, body) {
244
305
  return __awaiter(this, void 0, void 0, function () {
245
306
  var headers, _a, _b, _c, k, v, data;
246
- var e_1, _d;
307
+ var e_2, _d;
247
308
  return __generator(this, function (_e) {
248
309
  switch (_e.label) {
249
310
  case 0:
@@ -258,12 +319,12 @@ var Flagsmith = /** @class */ (function () {
258
319
  headers[k] = v;
259
320
  }
260
321
  }
261
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
322
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
262
323
  finally {
263
324
  try {
264
325
  if (_b && !_b.done && (_d = _a.return)) _d.call(_a);
265
326
  }
266
- finally { if (e_1) throw e_1.error; }
327
+ finally { if (e_2) throw e_2.error; }
267
328
  }
268
329
  }
269
330
  return [4 /*yield*/, (0, utils_1.retryFetch)(url, {
@@ -296,87 +357,124 @@ var Flagsmith = /** @class */ (function () {
296
357
  });
297
358
  };
298
359
  Flagsmith.prototype.getEnvironmentFlagsFromDocument = function () {
299
- return models_3.Flags.fromFeatureStateModels({
300
- featureStates: (0, flagsmith_engine_1.getEnvironmentFeatureStates)(this.environment),
301
- analyticsProcessor: this.analyticsProcessor,
302
- defaultFlagHandler: this.defaultFlagHandler
360
+ return __awaiter(this, void 0, void 0, function () {
361
+ var flags;
362
+ return __generator(this, function (_a) {
363
+ switch (_a.label) {
364
+ case 0:
365
+ flags = models_3.Flags.fromFeatureStateModels({
366
+ featureStates: (0, flagsmith_engine_1.getEnvironmentFeatureStates)(this.environment),
367
+ analyticsProcessor: this.analyticsProcessor,
368
+ defaultFlagHandler: this.defaultFlagHandler
369
+ });
370
+ if (!!!this.cache) return [3 /*break*/, 2];
371
+ return [4 /*yield*/, this.cache.set('flags', flags)];
372
+ case 1:
373
+ _a.sent();
374
+ _a.label = 2;
375
+ case 2: return [2 /*return*/, flags];
376
+ }
377
+ });
303
378
  });
304
379
  };
305
380
  Flagsmith.prototype.getIdentityFlagsFromDocument = function (identifier, traits) {
306
- var identityModel = this.buildIdentityModel(identifier, Object.keys(traits).map(function (key) { return ({
307
- key: key,
308
- value: traits[key]
309
- }); }));
310
- var featureStates = (0, flagsmith_engine_1.getIdentityFeatureStates)(this.environment, identityModel);
311
- return models_3.Flags.fromFeatureStateModels({
312
- featureStates: featureStates,
313
- analyticsProcessor: this.analyticsProcessor,
314
- defaultFlagHandler: this.defaultFlagHandler
381
+ return __awaiter(this, void 0, void 0, function () {
382
+ var identityModel, featureStates, flags;
383
+ return __generator(this, function (_a) {
384
+ switch (_a.label) {
385
+ case 0:
386
+ identityModel = this.buildIdentityModel(identifier, Object.keys(traits).map(function (key) { return ({
387
+ key: key,
388
+ value: traits[key]
389
+ }); }));
390
+ featureStates = (0, flagsmith_engine_1.getIdentityFeatureStates)(this.environment, identityModel);
391
+ flags = models_3.Flags.fromFeatureStateModels({
392
+ featureStates: featureStates,
393
+ analyticsProcessor: this.analyticsProcessor,
394
+ defaultFlagHandler: this.defaultFlagHandler
395
+ });
396
+ if (!!!this.cache) return [3 /*break*/, 2];
397
+ return [4 /*yield*/, this.cache.set("flags-".concat(identifier), flags)];
398
+ case 1:
399
+ _a.sent();
400
+ _a.label = 2;
401
+ case 2: return [2 /*return*/, flags];
402
+ }
403
+ });
315
404
  });
316
405
  };
317
406
  Flagsmith.prototype.getEnvironmentFlagsFromApi = function () {
318
407
  return __awaiter(this, void 0, void 0, function () {
319
- var apiFlags, e_2;
408
+ var apiFlags, flags, e_3;
320
409
  return __generator(this, function (_a) {
321
410
  switch (_a.label) {
322
411
  case 0:
323
- _a.trys.push([0, 2, , 3]);
412
+ _a.trys.push([0, 4, , 5]);
324
413
  return [4 /*yield*/, this.getJSONResponse(this.environmentFlagsUrl, 'GET')];
325
414
  case 1:
326
415
  apiFlags = _a.sent();
327
- return [2 /*return*/, models_3.Flags.fromAPIFlags({
328
- apiFlags: apiFlags,
329
- analyticsProcessor: this.analyticsProcessor,
330
- defaultFlagHandler: this.defaultFlagHandler
331
- })];
416
+ flags = models_3.Flags.fromAPIFlags({
417
+ apiFlags: apiFlags,
418
+ analyticsProcessor: this.analyticsProcessor,
419
+ defaultFlagHandler: this.defaultFlagHandler
420
+ });
421
+ if (!!!this.cache) return [3 /*break*/, 3];
422
+ return [4 /*yield*/, this.cache.set('flags', flags)];
332
423
  case 2:
333
- e_2 = _a.sent();
424
+ _a.sent();
425
+ _a.label = 3;
426
+ case 3: return [2 /*return*/, flags];
427
+ case 4:
428
+ e_3 = _a.sent();
334
429
  if (this.defaultFlagHandler) {
335
430
  return [2 /*return*/, new models_3.Flags({
336
431
  flags: {},
337
432
  defaultFlagHandler: this.defaultFlagHandler
338
433
  })];
339
434
  }
340
- throw e_2;
341
- case 3: return [2 /*return*/];
435
+ throw e_3;
436
+ case 5: return [2 /*return*/];
342
437
  }
343
438
  });
344
439
  });
345
440
  };
346
441
  Flagsmith.prototype.getIdentityFlagsFromApi = function (identifier, traits) {
347
442
  return __awaiter(this, void 0, void 0, function () {
348
- var data, jsonResponse, e_3;
443
+ var data, jsonResponse, flags, e_4;
349
444
  return __generator(this, function (_a) {
350
445
  switch (_a.label) {
351
446
  case 0:
352
- _a.trys.push([0, 2, , 3]);
447
+ _a.trys.push([0, 4, , 5]);
353
448
  data = (0, utils_1.generateIdentitiesData)(identifier, traits);
354
449
  return [4 /*yield*/, this.getJSONResponse(this.identitiesUrl, 'POST', data)];
355
450
  case 1:
356
451
  jsonResponse = _a.sent();
357
- return [2 /*return*/, models_3.Flags.fromAPIFlags({
358
- apiFlags: jsonResponse['flags'],
359
- analyticsProcessor: this.analyticsProcessor,
360
- defaultFlagHandler: this.defaultFlagHandler
361
- })];
452
+ flags = models_3.Flags.fromAPIFlags({
453
+ apiFlags: jsonResponse['flags'],
454
+ analyticsProcessor: this.analyticsProcessor,
455
+ defaultFlagHandler: this.defaultFlagHandler
456
+ });
457
+ if (!!!this.cache) return [3 /*break*/, 3];
458
+ return [4 /*yield*/, this.cache.set("flags-".concat(identifier), flags)];
362
459
  case 2:
363
- e_3 = _a.sent();
460
+ _a.sent();
461
+ _a.label = 3;
462
+ case 3: return [2 /*return*/, flags];
463
+ case 4:
464
+ e_4 = _a.sent();
364
465
  if (this.defaultFlagHandler) {
365
466
  return [2 /*return*/, new models_3.Flags({
366
467
  flags: {},
367
468
  defaultFlagHandler: this.defaultFlagHandler
368
469
  })];
369
470
  }
370
- throw e_3;
371
- case 3: return [2 /*return*/];
471
+ throw e_4;
472
+ case 5: return [2 /*return*/];
372
473
  }
373
474
  });
374
475
  });
375
476
  };
376
477
  Flagsmith.prototype.buildIdentityModel = function (identifier, traits) {
377
- if (!this.environment) {
378
- throw new errors_1.FlagsmithClientError('Unable to build identity model when no local environment present.');
379
- }
380
478
  var traitModels = traits.map(function (trait) { return new models_2.TraitModel(trait.key, trait.value); });
381
479
  return new models_1.IdentityModel('0', traitModels, [], this.environment.apiKey, identifier);
382
480
  };
@@ -58,7 +58,6 @@ var EnvironmentDataPollingManager = /** @class */ (function () {
58
58
  });
59
59
  }); }, _this.refreshIntervalSeconds * 1000);
60
60
  };
61
- // todo: this call should be awaited for getIdentityFlags/getEnvironmentFlags when enableLocalEvaluation is true
62
61
  this.main.updateEnvironment();
63
62
  updateEnvironment();
64
63
  };
@@ -0,0 +1,7 @@
1
+ import { Flags } from "./models";
2
+ export interface FlagsmithCache {
3
+ get(key: string): Promise<Flags>;
4
+ set(key: string, value: Flags): Promise<void>;
5
+ has(key: string): Promise<boolean>;
6
+ [key: string]: any;
7
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });