@flagship.io/react-sdk 2.2.0-beta.6 → 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,6 +36,7 @@ export const FlagshipProvider = ({
36
36
  initialBucketing,
37
37
  initialCampaigns,
38
38
  initialModifications,
39
+ initialFlagsData,
39
40
  synchronizeOnBucketingUpdated,
40
41
  activateDeduplicationTime,
41
42
  hitDeduplicationTime,
@@ -45,7 +46,11 @@ export const FlagshipProvider = ({
45
46
  }) => {
46
47
  let modifications = new Map();
47
48
 
48
- if (initialModifications) {
49
+ if (initialFlagsData && initialFlagsData.forEach) {
50
+ initialFlagsData.forEach(flag => {
51
+ modifications.set(flag.key, flag);
52
+ });
53
+ } else if (initialModifications && initialModifications.forEach) {
49
54
  initialModifications.forEach(modification => {
50
55
  modifications.set(modification.key, modification);
51
56
  });
@@ -63,7 +68,7 @@ export const FlagshipProvider = ({
63
68
  if (synchronizeOnBucketingUpdated) {
64
69
  var _state$visitor;
65
70
 
66
- (_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();
67
72
  }
68
73
  }, [lastModified]);
69
74
  useEffect(() => {
@@ -90,14 +95,14 @@ export const FlagshipProvider = ({
90
95
  if (state.visitor.anonymousId && !visitorData.isAuthenticated) {
91
96
  state.visitor.unauthenticate();
92
97
  } else if (!state.visitor.anonymousId && visitorData.isAuthenticated) {
93
- state.visitor.authenticate(visitorData.id);
98
+ state.visitor.authenticate(visitorData.id || uuidV4());
94
99
  }
95
100
 
96
101
  if (visitorData.id) {
97
102
  state.visitor.visitorId = visitorData.id;
98
103
  }
99
104
 
100
- state.visitor.synchronizeModifications();
105
+ state.visitor.fetchFlags();
101
106
  };
102
107
 
103
108
  function initializeState(param) {
@@ -163,7 +168,7 @@ export const FlagshipProvider = ({
163
168
  if ((_stateRef$current = stateRef.current) !== null && _stateRef$current !== void 0 && _stateRef$current.visitor) {
164
169
  var _stateRef$current2;
165
170
 
166
- (_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();
167
172
  } else {
168
173
  const fsVisitor = Flagship.newVisitor({
169
174
  visitorId: visitorData.id,
@@ -171,7 +176,8 @@ export const FlagshipProvider = ({
171
176
  isAuthenticated: visitorData.isAuthenticated,
172
177
  hasConsented: visitorData.hasConsented,
173
178
  initialCampaigns,
174
- initialModifications
179
+ initialModifications,
180
+ initialFlagsData
175
181
  });
176
182
  fsVisitor === null || fsVisitor === void 0 ? void 0 : fsVisitor.on('ready', error => {
177
183
  onVisitorReady(fsVisitor, error);
@@ -222,7 +228,7 @@ export const FlagshipProvider = ({
222
228
  const handleDisplay = () => {
223
229
  const isFirstInit = !state.visitor;
224
230
 
225
- if (state.status.isLoading && loadingComponent && isFirstInit) {
231
+ if (state.status.isLoading && loadingComponent && isFirstInit && fetchNow) {
226
232
  return /*#__PURE__*/React.createElement(React.Fragment, null, loadingComponent);
227
233
  }
228
234
 
@@ -237,7 +243,6 @@ export const FlagshipProvider = ({
237
243
  }, handleDisplay());
238
244
  };
239
245
  FlagshipProvider.defaultProps = {
240
- nodeEnv: 'production',
241
246
  activateDeduplicationTime: 10,
242
247
  hitDeduplicationTime: 10
243
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/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,6 +53,7 @@ export var FlagshipProvider = function FlagshipProvider(_ref) {
53
53
  initialBucketing = _ref.initialBucketing,
54
54
  initialCampaigns = _ref.initialCampaigns,
55
55
  initialModifications = _ref.initialModifications,
56
+ initialFlagsData = _ref.initialFlagsData,
56
57
  synchronizeOnBucketingUpdated = _ref.synchronizeOnBucketingUpdated,
57
58
  activateDeduplicationTime = _ref.activateDeduplicationTime,
58
59
  hitDeduplicationTime = _ref.hitDeduplicationTime,
@@ -61,7 +62,11 @@ export var FlagshipProvider = function FlagshipProvider(_ref) {
61
62
  disableCache = _ref.disableCache;
62
63
  var modifications = new Map();
63
64
 
64
- 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) {
65
70
  initialModifications.forEach(function (modification) {
66
71
  modifications.set(modification.key, modification);
67
72
  });
@@ -87,7 +92,7 @@ export var FlagshipProvider = function FlagshipProvider(_ref) {
87
92
  if (synchronizeOnBucketingUpdated) {
88
93
  var _state$visitor;
89
94
 
90
- (_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();
91
96
  }
92
97
  }, [lastModified]);
93
98
  useEffect(function () {
@@ -114,14 +119,14 @@ export var FlagshipProvider = function FlagshipProvider(_ref) {
114
119
  if (state.visitor.anonymousId && !visitorData.isAuthenticated) {
115
120
  state.visitor.unauthenticate();
116
121
  } else if (!state.visitor.anonymousId && visitorData.isAuthenticated) {
117
- state.visitor.authenticate(visitorData.id);
122
+ state.visitor.authenticate(visitorData.id || uuidV4());
118
123
  }
119
124
 
120
125
  if (visitorData.id) {
121
126
  state.visitor.visitorId = visitorData.id;
122
127
  }
123
128
 
124
- state.visitor.synchronizeModifications();
129
+ state.visitor.fetchFlags();
125
130
  };
126
131
 
127
132
  function initializeState(param) {
@@ -185,7 +190,7 @@ export var FlagshipProvider = function FlagshipProvider(_ref) {
185
190
  if ((_stateRef$current = stateRef.current) !== null && _stateRef$current !== void 0 && _stateRef$current.visitor) {
186
191
  var _stateRef$current2;
187
192
 
188
- (_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();
189
194
  } else {
190
195
  var fsVisitor = Flagship.newVisitor({
191
196
  visitorId: visitorData.id,
@@ -193,7 +198,8 @@ export var FlagshipProvider = function FlagshipProvider(_ref) {
193
198
  isAuthenticated: visitorData.isAuthenticated,
194
199
  hasConsented: visitorData.hasConsented,
195
200
  initialCampaigns: initialCampaigns,
196
- initialModifications: initialModifications
201
+ initialModifications: initialModifications,
202
+ initialFlagsData: initialFlagsData
197
203
  });
198
204
  fsVisitor === null || fsVisitor === void 0 ? void 0 : fsVisitor.on('ready', function (error) {
199
205
  onVisitorReady(fsVisitor, error);
@@ -244,7 +250,7 @@ export var FlagshipProvider = function FlagshipProvider(_ref) {
244
250
  var handleDisplay = function handleDisplay() {
245
251
  var isFirstInit = !state.visitor;
246
252
 
247
- if (state.status.isLoading && loadingComponent && isFirstInit) {
253
+ if (state.status.isLoading && loadingComponent && isFirstInit && fetchNow) {
248
254
  return /*#__PURE__*/React.createElement(React.Fragment, null, loadingComponent);
249
255
  }
250
256
 
@@ -259,7 +265,6 @@ export var FlagshipProvider = function FlagshipProvider(_ref) {
259
265
  }, handleDisplay());
260
266
  };
261
267
  FlagshipProvider.defaultProps = {
262
- nodeEnv: 'production',
263
268
  activateDeduplicationTime: 10,
264
269
  hitDeduplicationTime: 10
265
270
  };