@flagship.io/react-sdk 2.2.0-beta.3 → 3.0.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.
package/README.md CHANGED
@@ -7,8 +7,8 @@
7
7
 
8
8
  ## Docs
9
9
 
10
- - coming soon
10
+ - [docs](https://docs.developers.flagship.io/docs/react-v3-0-x)
11
11
 
12
12
  ## Licence
13
13
 
14
- [Apache License.](https://github.com/abtasty/flagship-react-sdk/blob/master/LICENSE)
14
+ [Apache License.](https://github.com/flagship-io/flagship-react-sdk/blob/master/LICENSE)
@@ -0,0 +1,36 @@
1
+ import { FlagMetadata, LogLevel } from '@flagship.io/js-sdk';
2
+ import { noVisitorMessage } from './constants';
3
+ import { log } from './utils';
4
+ export class Flag {
5
+ constructor(defaultValue) {
6
+ log(LogLevel.ERROR, noVisitorMessage, 'GetFlag');
7
+ this._defaultValue = defaultValue;
8
+ }
9
+
10
+ getValue() {
11
+ log(LogLevel.ERROR, noVisitorMessage, 'exists');
12
+ return this._defaultValue;
13
+ }
14
+
15
+ exists() {
16
+ log(LogLevel.ERROR, noVisitorMessage, 'exists');
17
+ return false;
18
+ }
19
+
20
+ userExposed() {
21
+ log(LogLevel.ERROR, noVisitorMessage, 'userExposed');
22
+ return Promise.resolve();
23
+ }
24
+
25
+ get metadata() {
26
+ log(LogLevel.ERROR, noVisitorMessage, 'metadata');
27
+ return new FlagMetadata({
28
+ campaignId: '',
29
+ campaignType: '',
30
+ isReference: false,
31
+ variationGroupId: '',
32
+ variationId: ''
33
+ });
34
+ }
35
+
36
+ }
@@ -1,7 +1,7 @@
1
1
  // eslint-disable-next-line no-use-before-define
2
2
  import React, { useState, useEffect, createContext, useRef } from 'react';
3
3
  import { Flagship, FlagshipStatus } from '@flagship.io/js-sdk';
4
- import { getModificationsFromCampaigns, logError } from './utils';
4
+ import { getModificationsFromCampaigns, logError, uuidV4 } from './utils';
5
5
  const initStat = {
6
6
  status: {
7
7
  isLoading: true,
@@ -36,11 +36,21 @@ export const FlagshipProvider = ({
36
36
  initialBucketing,
37
37
  initialCampaigns,
38
38
  initialModifications,
39
- synchronizeOnBucketingUpdated
39
+ initialFlagsData,
40
+ synchronizeOnBucketingUpdated,
41
+ activateDeduplicationTime,
42
+ hitDeduplicationTime,
43
+ visitorCacheImplementation,
44
+ hitCacheImplementation,
45
+ disableCache
40
46
  }) => {
41
47
  let modifications = new Map();
42
48
 
43
- if (initialModifications) {
49
+ if (initialFlagsData && initialFlagsData.forEach) {
50
+ initialFlagsData.forEach(flag => {
51
+ modifications.set(flag.key, flag);
52
+ });
53
+ } else if (initialModifications && initialModifications.forEach) {
44
54
  initialModifications.forEach(modification => {
45
55
  modifications.set(modification.key, modification);
46
56
  });
@@ -58,7 +68,7 @@ export const FlagshipProvider = ({
58
68
  if (synchronizeOnBucketingUpdated) {
59
69
  var _state$visitor;
60
70
 
61
- (_state$visitor = state.visitor) === null || _state$visitor === void 0 ? void 0 : _state$visitor.synchronizeModifications();
71
+ (_state$visitor = state.visitor) === null || _state$visitor === void 0 ? void 0 : _state$visitor.fetchFlags();
62
72
  }
63
73
  }, [lastModified]);
64
74
  useEffect(() => {
@@ -85,14 +95,14 @@ export const FlagshipProvider = ({
85
95
  if (state.visitor.anonymousId && !visitorData.isAuthenticated) {
86
96
  state.visitor.unauthenticate();
87
97
  } else if (!state.visitor.anonymousId && visitorData.isAuthenticated) {
88
- state.visitor.authenticate(visitorData.id);
98
+ state.visitor.authenticate(visitorData.id || uuidV4());
89
99
  }
90
100
 
91
101
  if (visitorData.id) {
92
102
  state.visitor.visitorId = visitorData.id;
93
103
  }
94
104
 
95
- state.visitor.synchronizeModifications();
105
+ state.visitor.fetchFlags();
96
106
  };
97
107
 
98
108
  function initializeState(param) {
@@ -158,7 +168,7 @@ export const FlagshipProvider = ({
158
168
  if ((_stateRef$current = stateRef.current) !== null && _stateRef$current !== void 0 && _stateRef$current.visitor) {
159
169
  var _stateRef$current2;
160
170
 
161
- (_stateRef$current2 = stateRef.current) === null || _stateRef$current2 === void 0 ? void 0 : _stateRef$current2.visitor.synchronizeModifications();
171
+ (_stateRef$current2 = stateRef.current) === null || _stateRef$current2 === void 0 ? void 0 : _stateRef$current2.visitor.fetchFlags();
162
172
  } else {
163
173
  const fsVisitor = Flagship.newVisitor({
164
174
  visitorId: visitorData.id,
@@ -166,7 +176,8 @@ export const FlagshipProvider = ({
166
176
  isAuthenticated: visitorData.isAuthenticated,
167
177
  hasConsented: visitorData.hasConsented,
168
178
  initialCampaigns,
169
- initialModifications
179
+ initialModifications,
180
+ initialFlagsData
170
181
  });
171
182
  fsVisitor === null || fsVisitor === void 0 ? void 0 : fsVisitor.on('ready', error => {
172
183
  onVisitorReady(fsVisitor, error);
@@ -205,14 +216,19 @@ export const FlagshipProvider = ({
205
216
  enableClientCache,
206
217
  decisionApiUrl,
207
218
  onBucketingUpdated: onBucketingLastModified,
208
- initialBucketing
219
+ initialBucketing,
220
+ activateDeduplicationTime,
221
+ hitDeduplicationTime,
222
+ visitorCacheImplementation,
223
+ hitCacheImplementation,
224
+ disableCache
209
225
  });
210
226
  };
211
227
 
212
228
  const handleDisplay = () => {
213
229
  const isFirstInit = !state.visitor;
214
230
 
215
- if (state.status.isLoading && loadingComponent && isFirstInit) {
231
+ if (state.status.isLoading && loadingComponent && isFirstInit && fetchNow) {
216
232
  return /*#__PURE__*/React.createElement(React.Fragment, null, loadingComponent);
217
233
  }
218
234
 
@@ -227,5 +243,6 @@ export const FlagshipProvider = ({
227
243
  }, handleDisplay());
228
244
  };
229
245
  FlagshipProvider.defaultProps = {
230
- nodeEnv: 'production'
246
+ activateDeduplicationTime: 10,
247
+ hitDeduplicationTime: 10
231
248
  };
@@ -1,6 +1,8 @@
1
1
  import { useContext } from 'react';
2
2
  import { FlagshipContext } from './FlagshipContext';
3
3
  import { logError, logWarn } from './utils';
4
+ import { Flag } from './Flag';
5
+ import { noVisitorDefault, noVisitorMessage } from './constants';
4
6
 
5
7
  const checkType = (value, defaultValue) => typeof value === 'object' && typeof defaultValue === 'object' && Array.isArray(value) === Array.isArray(defaultValue) || typeof value === typeof defaultValue;
6
8
 
@@ -44,6 +46,7 @@ const fsModificationsSync = args => {
44
46
  };
45
47
  /**
46
48
  * Retrieve a modification value by its key. If no modification match the given key or if the stored value type and default value type do not match, default value will be returned.
49
+ * @deprecated use useFsGetFlag instead
47
50
  */
48
51
 
49
52
 
@@ -67,6 +70,7 @@ export const useFsModifications = (params, activateAll) => {
67
70
  };
68
71
  /**
69
72
  * Retrieve a modification value by its key. If no modification match the given key or if the stored value type and default value type do not match, default value will be returned.
73
+ * @deprecated use useFsGetFlag instead
70
74
  */
71
75
 
72
76
  export const useFsModification = params => {
@@ -119,6 +123,7 @@ const fsModificationInfoSync = args => {
119
123
  /**
120
124
  * Get the campaign modification information value matching the given key.
121
125
  * @param {string} key key which identify the modification.
126
+ * @deprecated use useFsGetFlag instead
122
127
  */
123
128
 
124
129
 
@@ -148,22 +153,6 @@ const fsSynchronizeModifications = async (functionName, visitor, config) => {
148
153
  logError(config, error.message || error, functionName);
149
154
  }
150
155
  };
151
- /**
152
- * This function calls the decision api and update all the campaigns modifications from the server according to the visitor context.
153
- */
154
-
155
-
156
- export const useFsSynchronizeModifications = async () => {
157
- const {
158
- state
159
- } = useContext(FlagshipContext);
160
- const {
161
- visitor,
162
- config
163
- } = state;
164
- const functionName = 'useFsSynchronizeModifications';
165
- await fsSynchronizeModifications(functionName, visitor, config);
166
- };
167
156
 
168
157
  const fsActivate = async (params, functionName, visitor, config) => {
169
158
  try {
@@ -177,13 +166,35 @@ const fsActivate = async (params, functionName, visitor, config) => {
177
166
  logWarn(config, error.message || error, functionName);
178
167
  }
179
168
  };
169
+ /**
170
+ * This hook returns a flag object by its key. If no flag match the given key an empty flag will be returned.
171
+ * @param key
172
+ * @param defaultValue
173
+ * @returns
174
+ */
175
+
176
+
177
+ export const useFsFlag = (key, defaultValue) => {
178
+ const {
179
+ state
180
+ } = useContext(FlagshipContext);
181
+ const {
182
+ visitor
183
+ } = state;
184
+
185
+ if (!visitor) {
186
+ return new Flag(defaultValue);
187
+ }
188
+
189
+ return visitor.getFlag(key, defaultValue);
190
+ };
180
191
  /**
181
192
  * Report this user has seen this modification. Report this user has seen these modifications.
182
193
  * @param params
194
+ * @deprecated use useFsGetFlag instead
183
195
  * @returns
184
196
  */
185
197
 
186
-
187
198
  export const useFsActivate = async params => {
188
199
  const {
189
200
  state
@@ -249,8 +260,8 @@ export const useFlagship = () => {
249
260
  visitor.unauthenticate();
250
261
  };
251
262
  /**
252
- * Send a Hit to Flagship servers for reporting.
253
- */
263
+ * Send a Hit to Flagship servers for reporting.
264
+ */
254
265
 
255
266
 
256
267
  const fsSendHit = hit => {
@@ -264,8 +275,8 @@ export const useFlagship = () => {
264
275
  return visitor.sendHit(hit);
265
276
  };
266
277
  /**
267
- * Send a Hit to Flagship servers for reporting.
268
- */
278
+ * Send a Hit to Flagship servers for reporting.
279
+ */
269
280
 
270
281
 
271
282
  const fsSendHits = hit => {
@@ -316,7 +327,39 @@ export const useFlagship = () => {
316
327
  });
317
328
  };
318
329
 
330
+ function getFlag(key, defaultValue) {
331
+ if (!visitor) {
332
+ return new Flag(defaultValue);
333
+ }
334
+
335
+ return visitor.getFlag(key, defaultValue);
336
+ }
337
+
338
+ function fetchFlags() {
339
+ if (!visitor) {
340
+ logWarn(config, noVisitorMessage, 'fetchFlags');
341
+ return Promise.resolve();
342
+ }
343
+
344
+ return visitor === null || visitor === void 0 ? void 0 : visitor.fetchFlags();
345
+ }
346
+
347
+ function setConsent(hasConsented) {
348
+ if (!visitor) {
349
+ logWarn(config, noVisitorMessage, 'setConsent');
350
+ return;
351
+ }
352
+
353
+ visitor.setConsent(hasConsented);
354
+ }
355
+
319
356
  return {
357
+ visitorId: visitor === null || visitor === void 0 ? void 0 : visitor.visitorId,
358
+ anonymousId: visitor === null || visitor === void 0 ? void 0 : visitor.anonymousId,
359
+ context: { ...(visitor === null || visitor === void 0 ? void 0 : visitor.context)
360
+ },
361
+ hasConsented: visitor === null || visitor === void 0 ? void 0 : visitor.hasConsented,
362
+ setConsent,
320
363
  updateContext: fsUpdateContext,
321
364
  clearContext: fsClearContext,
322
365
  authenticate: fsAuthenticate,
@@ -326,15 +369,16 @@ export const useFlagship = () => {
326
369
  synchronizeModifications,
327
370
  getModifications,
328
371
  modifications: modifications || [],
372
+ FlagsData: (visitor === null || visitor === void 0 ? void 0 : visitor.getFlagsDataArray()) || [],
329
373
  getModificationInfo,
330
374
  hit: {
331
375
  send: fsSendHit,
332
376
  sendMultiple: fsSendHits
333
- }
377
+ },
378
+ getFlag,
379
+ fetchFlags
334
380
  };
335
381
  };
336
- export const noVisitorMessage = 'sdk not correctly initialized... Make sure fsVisitor is ready.';
337
- export const noVisitorDefault = 'fsVisitor not initialized, returns default value';
338
382
 
339
383
  const reportNoVisitor = (config, tag) => {
340
384
  logError(config, noVisitorMessage, tag);
@@ -0,0 +1,2 @@
1
+ export const noVisitorMessage = 'sdk not correctly initialized... Make sure fsVisitor is ready.';
2
+ export const noVisitorDefault = 'fsVisitor not initialized, returns default value';
package/dist/es/index.js CHANGED
@@ -1,3 +1,3 @@
1
1
  export * from './FlagshipContext';
2
- export { DecisionMode } from '@flagship.io/js-sdk';
2
+ export * from '@flagship.io/js-sdk';
3
3
  export * from './FlagshipHooks';
package/dist/es/utils.js CHANGED
@@ -20,6 +20,16 @@ export function logWarn(config, message, tag) {
20
20
 
21
21
  config.logManager.warning(message, tag);
22
22
  }
23
+ export function log(level, message, tag) {
24
+ const now = new Date(); // eslint-disable-next-line @typescript-eslint/no-explicit-any
25
+
26
+ const getTwoDigit = value => {
27
+ return value.toString().length === 1 ? `0${value}` : value;
28
+ };
29
+
30
+ const out = `[${getTwoDigit(now.getFullYear())}-${getTwoDigit(now.getMonth())}-${getTwoDigit(now.getDay())} ${getTwoDigit(now.getHours())}:${getTwoDigit(now.getMinutes())}] [Flagship SDK] [${LogLevel[level]}] [${tag}] : ${message}`;
31
+ console.log(out);
32
+ }
23
33
  export const getModificationsFromCampaigns = campaigns => {
24
34
  const modifications = new Map();
25
35
 
@@ -43,4 +53,11 @@ export const getModificationsFromCampaigns = campaigns => {
43
53
  }
44
54
  });
45
55
  return modifications;
46
- };
56
+ };
57
+ export function uuidV4() {
58
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (char) {
59
+ const rand = Math.random() * 16 | 0;
60
+ const value = char === 'x' ? rand : rand & 0x3 | 0x8;
61
+ return value.toString(16);
62
+ });
63
+ }
@@ -0,0 +1,55 @@
1
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
2
+
3
+ function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
4
+
5
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
6
+
7
+ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
8
+
9
+ import { FlagMetadata, LogLevel } from '@flagship.io/js-sdk';
10
+ import { noVisitorMessage } from './constants';
11
+ import { log } from './utils';
12
+ export var Flag = /*#__PURE__*/function () {
13
+ function Flag(defaultValue) {
14
+ _classCallCheck(this, Flag);
15
+
16
+ _defineProperty(this, "_defaultValue", void 0);
17
+
18
+ log(LogLevel.ERROR, noVisitorMessage, 'GetFlag');
19
+ this._defaultValue = defaultValue;
20
+ }
21
+
22
+ _createClass(Flag, [{
23
+ key: "getValue",
24
+ value: function getValue() {
25
+ log(LogLevel.ERROR, noVisitorMessage, 'exists');
26
+ return this._defaultValue;
27
+ }
28
+ }, {
29
+ key: "exists",
30
+ value: function exists() {
31
+ log(LogLevel.ERROR, noVisitorMessage, 'exists');
32
+ return false;
33
+ }
34
+ }, {
35
+ key: "userExposed",
36
+ value: function userExposed() {
37
+ log(LogLevel.ERROR, noVisitorMessage, 'userExposed');
38
+ return Promise.resolve();
39
+ }
40
+ }, {
41
+ key: "metadata",
42
+ get: function get() {
43
+ log(LogLevel.ERROR, noVisitorMessage, 'metadata');
44
+ return new FlagMetadata({
45
+ campaignId: '',
46
+ campaignType: '',
47
+ isReference: false,
48
+ variationGroupId: '',
49
+ variationId: ''
50
+ });
51
+ }
52
+ }]);
53
+
54
+ return Flag;
55
+ }();
@@ -19,7 +19,7 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
19
19
  // eslint-disable-next-line no-use-before-define
20
20
  import React, { useState, useEffect, createContext, useRef } from 'react';
21
21
  import { Flagship, FlagshipStatus } from '@flagship.io/js-sdk';
22
- import { getModificationsFromCampaigns, logError } from './utils';
22
+ import { getModificationsFromCampaigns, logError, uuidV4 } from './utils';
23
23
  var initStat = {
24
24
  status: {
25
25
  isLoading: true,
@@ -53,10 +53,20 @@ export var FlagshipProvider = function FlagshipProvider(_ref) {
53
53
  initialBucketing = _ref.initialBucketing,
54
54
  initialCampaigns = _ref.initialCampaigns,
55
55
  initialModifications = _ref.initialModifications,
56
- synchronizeOnBucketingUpdated = _ref.synchronizeOnBucketingUpdated;
56
+ initialFlagsData = _ref.initialFlagsData,
57
+ synchronizeOnBucketingUpdated = _ref.synchronizeOnBucketingUpdated,
58
+ activateDeduplicationTime = _ref.activateDeduplicationTime,
59
+ hitDeduplicationTime = _ref.hitDeduplicationTime,
60
+ visitorCacheImplementation = _ref.visitorCacheImplementation,
61
+ hitCacheImplementation = _ref.hitCacheImplementation,
62
+ disableCache = _ref.disableCache;
57
63
  var modifications = new Map();
58
64
 
59
- if (initialModifications) {
65
+ if (initialFlagsData && initialFlagsData.forEach) {
66
+ initialFlagsData.forEach(function (flag) {
67
+ modifications.set(flag.key, flag);
68
+ });
69
+ } else if (initialModifications && initialModifications.forEach) {
60
70
  initialModifications.forEach(function (modification) {
61
71
  modifications.set(modification.key, modification);
62
72
  });
@@ -82,7 +92,7 @@ export var FlagshipProvider = function FlagshipProvider(_ref) {
82
92
  if (synchronizeOnBucketingUpdated) {
83
93
  var _state$visitor;
84
94
 
85
- (_state$visitor = state.visitor) === null || _state$visitor === void 0 ? void 0 : _state$visitor.synchronizeModifications();
95
+ (_state$visitor = state.visitor) === null || _state$visitor === void 0 ? void 0 : _state$visitor.fetchFlags();
86
96
  }
87
97
  }, [lastModified]);
88
98
  useEffect(function () {
@@ -109,14 +119,14 @@ export var FlagshipProvider = function FlagshipProvider(_ref) {
109
119
  if (state.visitor.anonymousId && !visitorData.isAuthenticated) {
110
120
  state.visitor.unauthenticate();
111
121
  } else if (!state.visitor.anonymousId && visitorData.isAuthenticated) {
112
- state.visitor.authenticate(visitorData.id);
122
+ state.visitor.authenticate(visitorData.id || uuidV4());
113
123
  }
114
124
 
115
125
  if (visitorData.id) {
116
126
  state.visitor.visitorId = visitorData.id;
117
127
  }
118
128
 
119
- state.visitor.synchronizeModifications();
129
+ state.visitor.fetchFlags();
120
130
  };
121
131
 
122
132
  function initializeState(param) {
@@ -180,7 +190,7 @@ export var FlagshipProvider = function FlagshipProvider(_ref) {
180
190
  if ((_stateRef$current = stateRef.current) !== null && _stateRef$current !== void 0 && _stateRef$current.visitor) {
181
191
  var _stateRef$current2;
182
192
 
183
- (_stateRef$current2 = stateRef.current) === null || _stateRef$current2 === void 0 ? void 0 : _stateRef$current2.visitor.synchronizeModifications();
193
+ (_stateRef$current2 = stateRef.current) === null || _stateRef$current2 === void 0 ? void 0 : _stateRef$current2.visitor.fetchFlags();
184
194
  } else {
185
195
  var fsVisitor = Flagship.newVisitor({
186
196
  visitorId: visitorData.id,
@@ -188,7 +198,8 @@ export var FlagshipProvider = function FlagshipProvider(_ref) {
188
198
  isAuthenticated: visitorData.isAuthenticated,
189
199
  hasConsented: visitorData.hasConsented,
190
200
  initialCampaigns: initialCampaigns,
191
- initialModifications: initialModifications
201
+ initialModifications: initialModifications,
202
+ initialFlagsData: initialFlagsData
192
203
  });
193
204
  fsVisitor === null || fsVisitor === void 0 ? void 0 : fsVisitor.on('ready', function (error) {
194
205
  onVisitorReady(fsVisitor, error);
@@ -227,14 +238,19 @@ export var FlagshipProvider = function FlagshipProvider(_ref) {
227
238
  enableClientCache: enableClientCache,
228
239
  decisionApiUrl: decisionApiUrl,
229
240
  onBucketingUpdated: onBucketingLastModified,
230
- initialBucketing: initialBucketing
241
+ initialBucketing: initialBucketing,
242
+ activateDeduplicationTime: activateDeduplicationTime,
243
+ hitDeduplicationTime: hitDeduplicationTime,
244
+ visitorCacheImplementation: visitorCacheImplementation,
245
+ hitCacheImplementation: hitCacheImplementation,
246
+ disableCache: disableCache
231
247
  });
232
248
  };
233
249
 
234
250
  var handleDisplay = function handleDisplay() {
235
251
  var isFirstInit = !state.visitor;
236
252
 
237
- if (state.status.isLoading && loadingComponent && isFirstInit) {
253
+ if (state.status.isLoading && loadingComponent && isFirstInit && fetchNow) {
238
254
  return /*#__PURE__*/React.createElement(React.Fragment, null, loadingComponent);
239
255
  }
240
256
 
@@ -249,5 +265,6 @@ export var FlagshipProvider = function FlagshipProvider(_ref) {
249
265
  }, handleDisplay());
250
266
  };
251
267
  FlagshipProvider.defaultProps = {
252
- nodeEnv: 'production'
268
+ activateDeduplicationTime: 10,
269
+ hitDeduplicationTime: 10
253
270
  };