@flagship.io/react-sdk 3.0.3-alpha.0 → 3.0.3-alpha.3
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/dist/es/Flag.js +36 -0
- package/dist/es/FlagshipContext.js +229 -0
- package/dist/es/FlagshipHooks.js +372 -0
- package/dist/es/constants.js +2 -0
- package/dist/es/index.js +3 -0
- package/dist/es/utils.js +77 -0
- package/dist/esm/Flag.js +55 -0
- package/dist/esm/FlagshipContext.js +253 -0
- package/dist/esm/FlagshipHooks.js +474 -0
- package/dist/esm/constants.js +2 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/utils.js +77 -0
- package/dist/index.browser.js +2 -0
- package/dist/index.browser.js.map +1 -0
- package/dist/index.js +1 -14
- package/dist/index.js.map +1 -1
- package/dist/types/Flag.d.ts +9 -0
- package/dist/types/FlagshipContext.d.ts +97 -0
- package/dist/types/FlagshipHooks.d.ts +130 -0
- package/dist/types/constants.d.ts +2 -0
- package/dist/{index.d.ts → types/index.d.ts} +1 -0
- package/dist/types/utils.d.ts +9 -0
- package/package.json +2 -2
- package/dist/FlagshipContext.d.ts +0 -99
- package/dist/FlagshipContext.js +0 -312
- package/dist/FlagshipContext.js.map +0 -1
- package/dist/FlagshipErrorBoundary.d.ts +0 -34
- package/dist/FlagshipErrorBoundary.js +0 -95
- package/dist/FlagshipErrorBoundary.js.map +0 -1
- package/dist/FlagshipHooks.d.ts +0 -33
- package/dist/FlagshipHooks.js +0 -198
- package/dist/FlagshipHooks.js.map +0 -1
- package/dist/components/ReactErrorBoundaryContainer/index.d.ts +0 -10
- package/dist/components/ReactErrorBoundaryContainer/index.js +0 -65
- package/dist/components/ReactErrorBoundaryContainer/index.js.map +0 -1
- package/dist/lib/loggerHelper.d.ts +0 -5
- package/dist/lib/loggerHelper.js +0 -14
- package/dist/lib/loggerHelper.js.map +0 -1
- package/dist/lib/utils.d.ts +0 -1
- package/dist/lib/utils.js +0 -7
- package/dist/lib/utils.js.map +0 -1
- package/dist/setupTests.d.ts +0 -1
- package/dist/setupTests.js +0 -9
- package/dist/setupTests.js.map +0 -1
- package/dist/tests/mock/apiAnswers/oneModifInMoreThanOneCampaign.d.ts +0 -3
- package/dist/tests/mock/apiAnswers/oneModifInMoreThanOneCampaign.js +0 -51
- package/dist/tests/mock/apiAnswers/oneModifInMoreThanOneCampaign.js.map +0 -1
- package/dist/tests/mock/env.d.ts +0 -5
- package/dist/tests/mock/env.js +0 -8
- package/dist/tests/mock/env.js.map +0 -1
- package/dist/tests/mock/index.d.ts +0 -74
- package/dist/tests/mock/index.js +0 -90
- package/dist/tests/mock/index.js.map +0 -1
package/dist/es/Flag.js
ADDED
|
@@ -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.WARNING, noVisitorMessage, 'GetFlag');
|
|
7
|
+
this._defaultValue = defaultValue;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
getValue() {
|
|
11
|
+
log(LogLevel.WARNING, noVisitorMessage, 'getValue');
|
|
12
|
+
return this._defaultValue;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
exists() {
|
|
16
|
+
log(LogLevel.WARNING, noVisitorMessage, 'exists');
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
userExposed() {
|
|
21
|
+
log(LogLevel.WARNING, noVisitorMessage, 'userExposed');
|
|
22
|
+
return Promise.resolve();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
get metadata() {
|
|
26
|
+
log(LogLevel.WARNING, noVisitorMessage, 'metadata');
|
|
27
|
+
return new FlagMetadata({
|
|
28
|
+
campaignId: '',
|
|
29
|
+
campaignType: '',
|
|
30
|
+
isReference: false,
|
|
31
|
+
variationGroupId: '',
|
|
32
|
+
variationId: ''
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
// eslint-disable-next-line no-use-before-define
|
|
2
|
+
import React, { useState, useEffect, createContext, useRef } from "react";
|
|
3
|
+
import { Flagship, FlagshipStatus } from "@flagship.io/js-sdk";
|
|
4
|
+
import { getModificationsFromCampaigns, logError, useNonInitialEffect } from "./utils";
|
|
5
|
+
const initStat = {
|
|
6
|
+
status: {
|
|
7
|
+
isLoading: true,
|
|
8
|
+
isSdkReady: false
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
export const FlagshipContext = /*#__PURE__*/createContext({
|
|
12
|
+
state: { ...initStat
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
export const FlagshipProvider = ({
|
|
16
|
+
children,
|
|
17
|
+
fetchNow,
|
|
18
|
+
envId,
|
|
19
|
+
apiKey,
|
|
20
|
+
decisionMode,
|
|
21
|
+
decisionApiUrl,
|
|
22
|
+
timeout,
|
|
23
|
+
logLevel,
|
|
24
|
+
statusChangedCallback,
|
|
25
|
+
logManager,
|
|
26
|
+
pollingInterval,
|
|
27
|
+
visitorData,
|
|
28
|
+
onInitStart,
|
|
29
|
+
onInitDone,
|
|
30
|
+
onBucketingSuccess,
|
|
31
|
+
onBucketingFail,
|
|
32
|
+
loadingComponent,
|
|
33
|
+
onBucketingUpdated,
|
|
34
|
+
onUpdate,
|
|
35
|
+
enableClientCache,
|
|
36
|
+
initialBucketing,
|
|
37
|
+
initialCampaigns,
|
|
38
|
+
initialModifications,
|
|
39
|
+
initialFlagsData,
|
|
40
|
+
synchronizeOnBucketingUpdated,
|
|
41
|
+
activateDeduplicationTime,
|
|
42
|
+
hitDeduplicationTime,
|
|
43
|
+
visitorCacheImplementation,
|
|
44
|
+
hitCacheImplementation,
|
|
45
|
+
disableCache
|
|
46
|
+
}) => {
|
|
47
|
+
let modifications = new Map();
|
|
48
|
+
|
|
49
|
+
if (initialFlagsData && initialFlagsData.forEach) {
|
|
50
|
+
initialFlagsData.forEach(flag => {
|
|
51
|
+
modifications.set(flag.key, flag);
|
|
52
|
+
});
|
|
53
|
+
} else if (initialModifications && initialModifications.forEach) {
|
|
54
|
+
initialModifications.forEach(modification => {
|
|
55
|
+
modifications.set(modification.key, modification);
|
|
56
|
+
});
|
|
57
|
+
} else if (initialCampaigns) {
|
|
58
|
+
modifications = getModificationsFromCampaigns(initialCampaigns);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const [state, setState] = useState({ ...initStat,
|
|
62
|
+
modifications
|
|
63
|
+
});
|
|
64
|
+
const [lastModified, setLastModified] = useState();
|
|
65
|
+
const stateRef = useRef();
|
|
66
|
+
stateRef.current = state;
|
|
67
|
+
useNonInitialEffect(() => {
|
|
68
|
+
if (synchronizeOnBucketingUpdated) {
|
|
69
|
+
var _state$visitor;
|
|
70
|
+
|
|
71
|
+
(_state$visitor = state.visitor) === null || _state$visitor === void 0 ? void 0 : _state$visitor.fetchFlags();
|
|
72
|
+
}
|
|
73
|
+
}, [lastModified]);
|
|
74
|
+
useNonInitialEffect(() => {
|
|
75
|
+
createVisitor(true);
|
|
76
|
+
}, [JSON.stringify(visitorData)]);
|
|
77
|
+
useEffect(() => {
|
|
78
|
+
initSdk();
|
|
79
|
+
}, [envId, apiKey, decisionMode]);
|
|
80
|
+
|
|
81
|
+
function initializeState(param) {
|
|
82
|
+
const newStatus = {
|
|
83
|
+
isSdkReady: param.isSdkReady,
|
|
84
|
+
isLoading: param.isLoading,
|
|
85
|
+
isVisitorDefined: !!param.fsVisitor,
|
|
86
|
+
lastRefresh: new Date().toISOString()
|
|
87
|
+
};
|
|
88
|
+
setState(currentState => {
|
|
89
|
+
if (!currentState.status.firstInitSuccess) {
|
|
90
|
+
newStatus.firstInitSuccess = new Date().toISOString();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return { ...currentState,
|
|
94
|
+
visitor: param.fsVisitor,
|
|
95
|
+
modifications: param.fsVisitor.modifications,
|
|
96
|
+
config: Flagship.getConfig(),
|
|
97
|
+
status: { ...currentState.status,
|
|
98
|
+
...newStatus
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
});
|
|
102
|
+
return newStatus;
|
|
103
|
+
} // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
const onVisitorReady = (fsVisitor, error) => {
|
|
107
|
+
if (error) {
|
|
108
|
+
logError(Flagship.getConfig(), error.message || error, "onReady");
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const newStatus = initializeState({
|
|
113
|
+
fsVisitor,
|
|
114
|
+
isSdkReady: true,
|
|
115
|
+
isLoading: false
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
if (onUpdate) {
|
|
119
|
+
onUpdate({
|
|
120
|
+
fsModifications: fsVisitor.modifications,
|
|
121
|
+
config: Flagship.getConfig(),
|
|
122
|
+
status: newStatus
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const createVisitor = (fetchFlags = false) => {
|
|
128
|
+
if (!visitorData) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const fsVisitor = Flagship.newVisitor({
|
|
133
|
+
visitorId: visitorData.id,
|
|
134
|
+
context: visitorData.context,
|
|
135
|
+
isAuthenticated: visitorData.isAuthenticated,
|
|
136
|
+
hasConsented: visitorData.hasConsented,
|
|
137
|
+
initialCampaigns,
|
|
138
|
+
initialModifications,
|
|
139
|
+
initialFlagsData
|
|
140
|
+
});
|
|
141
|
+
fsVisitor === null || fsVisitor === void 0 ? void 0 : fsVisitor.on("ready", error => {
|
|
142
|
+
onVisitorReady(fsVisitor, error);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
if (!fetchNow && fsVisitor && !fetchFlags) {
|
|
146
|
+
initializeState({
|
|
147
|
+
fsVisitor,
|
|
148
|
+
isSdkReady: true,
|
|
149
|
+
isLoading: false
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (fetchFlags && !fetchNow) {
|
|
154
|
+
fsVisitor === null || fsVisitor === void 0 ? void 0 : fsVisitor.fetchFlags();
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
const statusChanged = status => {
|
|
159
|
+
if (statusChangedCallback) {
|
|
160
|
+
statusChangedCallback(status);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (status === FlagshipStatus.STARTING && onInitStart) {
|
|
164
|
+
onInitStart();
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (status === FlagshipStatus.READY_PANIC_ON || status === FlagshipStatus.READY) {
|
|
169
|
+
if (onInitDone) {
|
|
170
|
+
onInitDone();
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
createVisitor();
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
const onBucketingLastModified = lastUpdate => {
|
|
178
|
+
if (onBucketingUpdated) {
|
|
179
|
+
onBucketingUpdated(lastUpdate);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
setLastModified(lastUpdate);
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
const initSdk = () => {
|
|
186
|
+
Flagship.start(envId, apiKey, {
|
|
187
|
+
decisionMode,
|
|
188
|
+
fetchNow,
|
|
189
|
+
timeout,
|
|
190
|
+
logLevel,
|
|
191
|
+
statusChangedCallback: statusChanged,
|
|
192
|
+
logManager,
|
|
193
|
+
pollingInterval,
|
|
194
|
+
onBucketingFail,
|
|
195
|
+
onBucketingSuccess,
|
|
196
|
+
enableClientCache,
|
|
197
|
+
decisionApiUrl,
|
|
198
|
+
onBucketingUpdated: onBucketingLastModified,
|
|
199
|
+
initialBucketing,
|
|
200
|
+
activateDeduplicationTime,
|
|
201
|
+
hitDeduplicationTime,
|
|
202
|
+
visitorCacheImplementation,
|
|
203
|
+
hitCacheImplementation,
|
|
204
|
+
disableCache,
|
|
205
|
+
language: 1
|
|
206
|
+
});
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
const handleDisplay = () => {
|
|
210
|
+
const isFirstInit = !state.visitor;
|
|
211
|
+
|
|
212
|
+
if (state.status.isLoading && loadingComponent && isFirstInit && fetchNow) {
|
|
213
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, loadingComponent);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, children);
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
return /*#__PURE__*/React.createElement(FlagshipContext.Provider, {
|
|
220
|
+
value: {
|
|
221
|
+
state,
|
|
222
|
+
setState
|
|
223
|
+
}
|
|
224
|
+
}, handleDisplay());
|
|
225
|
+
};
|
|
226
|
+
FlagshipProvider.defaultProps = {
|
|
227
|
+
activateDeduplicationTime: 10,
|
|
228
|
+
hitDeduplicationTime: 10
|
|
229
|
+
};
|
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
import { useContext } from 'react';
|
|
2
|
+
import { FlagshipContext } from './FlagshipContext';
|
|
3
|
+
import { logError, logWarn } from './utils';
|
|
4
|
+
import { Flag } from './Flag';
|
|
5
|
+
import { noVisitorDefault, noVisitorMessage } from './constants';
|
|
6
|
+
|
|
7
|
+
const checkType = (value, defaultValue) => typeof value === 'object' && typeof defaultValue === 'object' && Array.isArray(value) === Array.isArray(defaultValue) || typeof value === typeof defaultValue;
|
|
8
|
+
|
|
9
|
+
const fsModificationsSync = args => {
|
|
10
|
+
const {
|
|
11
|
+
visitor,
|
|
12
|
+
params,
|
|
13
|
+
activateAll,
|
|
14
|
+
state,
|
|
15
|
+
functionName,
|
|
16
|
+
config
|
|
17
|
+
} = args;
|
|
18
|
+
|
|
19
|
+
if (visitor) {
|
|
20
|
+
return visitor.getModificationsSync(params, activateAll);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const check = !state.status.isSdkReady && !!state.modifications && state.modifications.size > 0;
|
|
24
|
+
const flags = {};
|
|
25
|
+
|
|
26
|
+
if (check) {
|
|
27
|
+
params.forEach(item => {
|
|
28
|
+
var _state$modifications;
|
|
29
|
+
|
|
30
|
+
const modification = (_state$modifications = state.modifications) === null || _state$modifications === void 0 ? void 0 : _state$modifications.get(item.key);
|
|
31
|
+
|
|
32
|
+
if (modification && checkType(modification === null || modification === void 0 ? void 0 : modification.value, item.defaultValue)) {
|
|
33
|
+
flags[item.key] = modification.value;
|
|
34
|
+
} else {
|
|
35
|
+
flags[item.key] = item.defaultValue;
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
return flags;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
logWarn(config, noVisitorDefault, functionName);
|
|
42
|
+
params.forEach(item => {
|
|
43
|
+
flags[item.key] = item.defaultValue;
|
|
44
|
+
});
|
|
45
|
+
return flags;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
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
|
|
50
|
+
*/
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
export const useFsModifications = (params, activateAll) => {
|
|
54
|
+
const {
|
|
55
|
+
state
|
|
56
|
+
} = useContext(FlagshipContext);
|
|
57
|
+
const {
|
|
58
|
+
visitor,
|
|
59
|
+
config
|
|
60
|
+
} = state;
|
|
61
|
+
const functionName = 'useFsModifications';
|
|
62
|
+
return fsModificationsSync({
|
|
63
|
+
functionName,
|
|
64
|
+
state,
|
|
65
|
+
visitor,
|
|
66
|
+
config,
|
|
67
|
+
params,
|
|
68
|
+
activateAll
|
|
69
|
+
});
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
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
|
|
74
|
+
*/
|
|
75
|
+
|
|
76
|
+
export const useFsModification = params => {
|
|
77
|
+
var _state$modifications2;
|
|
78
|
+
|
|
79
|
+
const {
|
|
80
|
+
state
|
|
81
|
+
} = useContext(FlagshipContext);
|
|
82
|
+
const {
|
|
83
|
+
visitor,
|
|
84
|
+
config
|
|
85
|
+
} = state;
|
|
86
|
+
const functionName = 'useFsModifications';
|
|
87
|
+
|
|
88
|
+
if (visitor) {
|
|
89
|
+
return visitor.getModificationSync(params);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const modification = (_state$modifications2 = state.modifications) === null || _state$modifications2 === void 0 ? void 0 : _state$modifications2.get(params.key);
|
|
93
|
+
|
|
94
|
+
if (!state.status.isSdkReady && modification && checkType(modification === null || modification === void 0 ? void 0 : modification.value, params.defaultValue)) {
|
|
95
|
+
return modification.value;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
logWarn(config, noVisitorDefault, functionName);
|
|
99
|
+
return params.defaultValue;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const fsModificationInfoSync = args => {
|
|
103
|
+
var _state$modifications3;
|
|
104
|
+
|
|
105
|
+
const {
|
|
106
|
+
key,
|
|
107
|
+
visitor,
|
|
108
|
+
state
|
|
109
|
+
} = args;
|
|
110
|
+
|
|
111
|
+
if (visitor) {
|
|
112
|
+
return visitor.getModificationInfoSync(key);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const modification = (_state$modifications3 = state.modifications) === null || _state$modifications3 === void 0 ? void 0 : _state$modifications3.get(key);
|
|
116
|
+
|
|
117
|
+
if (!state.status.isSdkReady && modification) {
|
|
118
|
+
return modification;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return null;
|
|
122
|
+
};
|
|
123
|
+
/**
|
|
124
|
+
* Get the campaign modification information value matching the given key.
|
|
125
|
+
* @param {string} key key which identify the modification.
|
|
126
|
+
* @deprecated use useFsGetFlag instead
|
|
127
|
+
*/
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
export const useFsModificationInfo = key => {
|
|
131
|
+
const {
|
|
132
|
+
state
|
|
133
|
+
} = useContext(FlagshipContext);
|
|
134
|
+
const {
|
|
135
|
+
visitor
|
|
136
|
+
} = state;
|
|
137
|
+
return fsModificationInfoSync({
|
|
138
|
+
key,
|
|
139
|
+
state,
|
|
140
|
+
visitor
|
|
141
|
+
});
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const fsActivate = async (params, functionName, visitor, config) => {
|
|
145
|
+
try {
|
|
146
|
+
if (!visitor) {
|
|
147
|
+
logWarn(config, noVisitorMessage, functionName);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
await visitor.activateModifications(params); // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
152
|
+
} catch (error) {
|
|
153
|
+
logWarn(config, error.message || error, functionName);
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
/**
|
|
157
|
+
* This hook returns a flag object by its key. If no flag match the given key an empty flag will be returned.
|
|
158
|
+
* @param key
|
|
159
|
+
* @param defaultValue
|
|
160
|
+
* @returns
|
|
161
|
+
*/
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
export const useFsFlag = (key, defaultValue) => {
|
|
165
|
+
const {
|
|
166
|
+
state
|
|
167
|
+
} = useContext(FlagshipContext);
|
|
168
|
+
const {
|
|
169
|
+
visitor
|
|
170
|
+
} = state;
|
|
171
|
+
|
|
172
|
+
if (!visitor) {
|
|
173
|
+
return new Flag(defaultValue);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return visitor.getFlag(key, defaultValue);
|
|
177
|
+
};
|
|
178
|
+
/**
|
|
179
|
+
* Report this user has seen this modification. Report this user has seen these modifications.
|
|
180
|
+
* @param params
|
|
181
|
+
* @deprecated use useFsGetFlag instead
|
|
182
|
+
* @returns
|
|
183
|
+
*/
|
|
184
|
+
|
|
185
|
+
export const useFsActivate = async params => {
|
|
186
|
+
const {
|
|
187
|
+
state
|
|
188
|
+
} = useContext(FlagshipContext);
|
|
189
|
+
const {
|
|
190
|
+
visitor,
|
|
191
|
+
config
|
|
192
|
+
} = state;
|
|
193
|
+
const functionName = 'useFsModifications';
|
|
194
|
+
await fsActivate(params, functionName, visitor, config);
|
|
195
|
+
};
|
|
196
|
+
export const useFlagship = () => {
|
|
197
|
+
const {
|
|
198
|
+
state
|
|
199
|
+
} = useContext(FlagshipContext);
|
|
200
|
+
const {
|
|
201
|
+
visitor,
|
|
202
|
+
config
|
|
203
|
+
} = state;
|
|
204
|
+
|
|
205
|
+
const fsUpdateContext = context => {
|
|
206
|
+
const functionName = 'updateContext';
|
|
207
|
+
|
|
208
|
+
if (!visitor) {
|
|
209
|
+
logError(config, noVisitorMessage, functionName);
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
visitor.clearContext();
|
|
214
|
+
visitor.updateContext(context);
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
const fsClearContext = () => {
|
|
218
|
+
const functionName = 'cleanContext';
|
|
219
|
+
|
|
220
|
+
if (!visitor) {
|
|
221
|
+
logError(config, noVisitorMessage, functionName);
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
visitor.clearContext();
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
const fsAuthenticate = visitorId => {
|
|
229
|
+
const functionName = 'authenticate';
|
|
230
|
+
|
|
231
|
+
if (!visitor) {
|
|
232
|
+
logError(config, noVisitorMessage, functionName);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
visitor.authenticate(visitorId);
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
const fsUnauthenticate = () => {
|
|
240
|
+
const functionName = 'unauthenticate';
|
|
241
|
+
|
|
242
|
+
if (!visitor) {
|
|
243
|
+
logError(config, noVisitorMessage, functionName);
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
visitor.unauthenticate();
|
|
248
|
+
};
|
|
249
|
+
/**
|
|
250
|
+
* Send a Hit to Flagship servers for reporting.
|
|
251
|
+
*/
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
const fsSendHit = hit => {
|
|
255
|
+
const functionName = 'sendHit';
|
|
256
|
+
|
|
257
|
+
if (!visitor) {
|
|
258
|
+
logError(config, noVisitorMessage, functionName);
|
|
259
|
+
return Promise.resolve();
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
return visitor.sendHit(hit);
|
|
263
|
+
};
|
|
264
|
+
/**
|
|
265
|
+
* Send a Hit to Flagship servers for reporting.
|
|
266
|
+
*/
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
const fsSendHits = hit => {
|
|
270
|
+
const functionName = 'sendHits';
|
|
271
|
+
|
|
272
|
+
if (!visitor) {
|
|
273
|
+
logError(config, noVisitorMessage, functionName);
|
|
274
|
+
return Promise.resolve();
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
return visitor.sendHits(hit);
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
let modifications = visitor === null || visitor === void 0 ? void 0 : visitor.getModificationsArray();
|
|
281
|
+
|
|
282
|
+
if (!state.status.isSdkReady && state.modifications) {
|
|
283
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
284
|
+
modifications = Array.from(state.modifications, ([_key, item]) => item);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const activateModification = async params => {
|
|
288
|
+
const functionName = 'activateModification';
|
|
289
|
+
await fsActivate(params, functionName, visitor, config);
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
const synchronizeModifications = async () => {
|
|
293
|
+
if (!visitor) {
|
|
294
|
+
logWarn(config, noVisitorMessage, 'synchronizeModifications');
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
await visitor.synchronizeModifications();
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
const getModifications = (params, activateAll) => {
|
|
302
|
+
const functionName = 'getModifications';
|
|
303
|
+
return fsModificationsSync({
|
|
304
|
+
functionName,
|
|
305
|
+
state,
|
|
306
|
+
visitor,
|
|
307
|
+
config,
|
|
308
|
+
params,
|
|
309
|
+
activateAll
|
|
310
|
+
});
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
const getModificationInfo = key => {
|
|
314
|
+
return fsModificationInfoSync({
|
|
315
|
+
key,
|
|
316
|
+
state,
|
|
317
|
+
visitor
|
|
318
|
+
});
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
function getFlag(key, defaultValue) {
|
|
322
|
+
if (!visitor) {
|
|
323
|
+
return new Flag(defaultValue);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
return visitor.getFlag(key, defaultValue);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
function fetchFlags() {
|
|
330
|
+
if (!visitor) {
|
|
331
|
+
logWarn(config, noVisitorMessage, 'fetchFlags');
|
|
332
|
+
return Promise.resolve();
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
return visitor.fetchFlags();
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
function setConsent(hasConsented) {
|
|
339
|
+
if (!visitor) {
|
|
340
|
+
logWarn(config, noVisitorMessage, 'setConsent');
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
visitor.setConsent(hasConsented);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
return {
|
|
348
|
+
visitorId: visitor === null || visitor === void 0 ? void 0 : visitor.visitorId,
|
|
349
|
+
anonymousId: visitor === null || visitor === void 0 ? void 0 : visitor.anonymousId,
|
|
350
|
+
context: { ...(visitor === null || visitor === void 0 ? void 0 : visitor.context)
|
|
351
|
+
},
|
|
352
|
+
hasConsented: visitor === null || visitor === void 0 ? void 0 : visitor.hasConsented,
|
|
353
|
+
setConsent,
|
|
354
|
+
updateContext: fsUpdateContext,
|
|
355
|
+
clearContext: fsClearContext,
|
|
356
|
+
authenticate: fsAuthenticate,
|
|
357
|
+
unauthenticate: fsUnauthenticate,
|
|
358
|
+
status: state.status,
|
|
359
|
+
activateModification,
|
|
360
|
+
synchronizeModifications,
|
|
361
|
+
getModifications,
|
|
362
|
+
modifications: modifications || [],
|
|
363
|
+
FlagsData: (visitor === null || visitor === void 0 ? void 0 : visitor.getFlagsDataArray()) || [],
|
|
364
|
+
getModificationInfo,
|
|
365
|
+
hit: {
|
|
366
|
+
send: fsSendHit,
|
|
367
|
+
sendMultiple: fsSendHits
|
|
368
|
+
},
|
|
369
|
+
getFlag,
|
|
370
|
+
fetchFlags
|
|
371
|
+
};
|
|
372
|
+
};
|
package/dist/es/index.js
ADDED
package/dist/es/utils.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { LogLevel } from '@flagship.io/js-sdk';
|
|
2
|
+
import { useEffect, useRef } from 'react';
|
|
3
|
+
export function logError(config, message, tag) {
|
|
4
|
+
if (!config || !config.logManager || typeof config.logManager.error !== 'function' || !config.logLevel || config.logLevel < LogLevel.ERROR) {
|
|
5
|
+
return;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
config.logManager.error(message, tag);
|
|
9
|
+
}
|
|
10
|
+
export function logInfo(config, message, tag) {
|
|
11
|
+
if (!config || !config.logManager || typeof config.logManager.info !== 'function' || !config.logLevel || config.logLevel < LogLevel.INFO) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
config.logManager.info(message, tag);
|
|
16
|
+
}
|
|
17
|
+
export function logWarn(config, message, tag) {
|
|
18
|
+
if (!config || !config.logManager || typeof config.logManager.warning !== 'function' || !config.logLevel || config.logLevel < LogLevel.WARNING) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
config.logManager.warning(message, tag);
|
|
23
|
+
}
|
|
24
|
+
export function log(level, message, tag) {
|
|
25
|
+
const now = new Date(); // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
26
|
+
|
|
27
|
+
const getTwoDigit = value => {
|
|
28
|
+
return value.toString().length === 1 ? `0${value}` : value;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const out = `[${getTwoDigit(now.getFullYear())}-${getTwoDigit(now.getMonth())}-${getTwoDigit(now.getDay())} ${getTwoDigit(now.getHours())}:${getTwoDigit(now.getMinutes())}] [Flagship SDK] [${LogLevel[level]}] [${tag}] : ${message}`;
|
|
32
|
+
console.log(out);
|
|
33
|
+
}
|
|
34
|
+
export const getModificationsFromCampaigns = campaigns => {
|
|
35
|
+
const modifications = new Map();
|
|
36
|
+
|
|
37
|
+
if (!campaigns || !Array.isArray(campaigns)) {
|
|
38
|
+
return modifications;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
campaigns.forEach(campaign => {
|
|
42
|
+
const object = campaign.variation.modifications.value;
|
|
43
|
+
|
|
44
|
+
for (const key in object) {
|
|
45
|
+
const value = object[key];
|
|
46
|
+
modifications.set(key, {
|
|
47
|
+
key,
|
|
48
|
+
campaignId: campaign.id,
|
|
49
|
+
variationGroupId: campaign.variationGroupId,
|
|
50
|
+
variationId: campaign.variation.id,
|
|
51
|
+
isReference: campaign.variation.reference,
|
|
52
|
+
value
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
return modifications;
|
|
57
|
+
};
|
|
58
|
+
export function uuidV4() {
|
|
59
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (char) {
|
|
60
|
+
const rand = Math.random() * 16 | 0;
|
|
61
|
+
const value = char === 'x' ? rand : rand & 0x3 | 0x8;
|
|
62
|
+
return value.toString(16);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
export function useNonInitialEffect(effect, deps) {
|
|
66
|
+
const initialRender = useRef(true);
|
|
67
|
+
useEffect(() => {
|
|
68
|
+
if (initialRender.current) {
|
|
69
|
+
initialRender.current = false;
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (typeof effect === 'function') {
|
|
74
|
+
return effect();
|
|
75
|
+
}
|
|
76
|
+
}, deps);
|
|
77
|
+
}
|