@kameleoon/react-sdk 1.2.2 → 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.
Files changed (104) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +315 -43
  3. package/dist/Feature.js +2 -2
  4. package/dist/Feature.js.map +1 -1
  5. package/dist/KameleoonError.d.ts +5 -0
  6. package/dist/KameleoonError.js +31 -0
  7. package/dist/KameleoonError.js.map +1 -0
  8. package/dist/compose.d.ts +1 -1
  9. package/dist/compose.js +27 -2
  10. package/dist/compose.js.map +1 -1
  11. package/dist/constants.d.ts +11 -0
  12. package/dist/constants.js +13 -1
  13. package/dist/constants.js.map +1 -1
  14. package/dist/getKameleoonException.d.ts +2 -0
  15. package/dist/getKameleoonException.js +34 -0
  16. package/dist/getKameleoonException.js.map +1 -0
  17. package/dist/index.d.ts +6 -1
  18. package/dist/index.js +21 -1
  19. package/dist/index.js.map +1 -1
  20. package/dist/stories/Form.d.ts +13 -5
  21. package/dist/stories/Form.js +154 -36
  22. package/dist/stories/Form.js.map +1 -1
  23. package/dist/stories/FormHOC.js +12 -7
  24. package/dist/stories/FormHOC.js.map +1 -1
  25. package/dist/stories/FormHook.js +34 -21
  26. package/dist/stories/FormHook.js.map +1 -1
  27. package/dist/stories/constants.d.ts +5 -2
  28. package/dist/stories/constants.js +11 -8
  29. package/dist/stories/constants.js.map +1 -1
  30. package/dist/types.d.ts +24 -7
  31. package/dist/types.js.map +1 -1
  32. package/dist/useActivateFeature.d.ts +2 -0
  33. package/dist/useActivateFeature.js +11 -2
  34. package/dist/useActivateFeature.js.map +1 -1
  35. package/dist/useAddData.js +17 -1
  36. package/dist/useAddData.js.map +1 -1
  37. package/dist/useConversion.d.ts +1 -1
  38. package/dist/useError.d.ts +7 -0
  39. package/dist/useError.js +34 -0
  40. package/dist/useError.js.map +1 -0
  41. package/dist/useErrors.d.ts +7 -0
  42. package/dist/useErrors.js +42 -0
  43. package/dist/useErrors.js.map +1 -0
  44. package/dist/useFeature.d.ts +1 -1
  45. package/dist/useFeature.js +42 -13
  46. package/dist/useFeature.js.map +1 -1
  47. package/dist/useFeatureVariable.d.ts +2 -0
  48. package/dist/useFeatureVariable.js +11 -2
  49. package/dist/useFeatureVariable.js.map +1 -1
  50. package/dist/useRetrieveDataFromRemoteSource.d.ts +12 -0
  51. package/dist/useRetrieveDataFromRemoteSource.js +79 -0
  52. package/dist/useRetrieveDataFromRemoteSource.js.map +1 -0
  53. package/dist/useRunWhenReady.d.ts +14 -0
  54. package/dist/useRunWhenReady.js +23 -0
  55. package/dist/useRunWhenReady.js.map +1 -0
  56. package/dist/useTriggerExperiment.d.ts +2 -0
  57. package/dist/useTriggerExperiment.js +12 -2
  58. package/dist/useTriggerExperiment.js.map +1 -1
  59. package/dist/useVariationAssociatedData.d.ts +6 -4
  60. package/dist/useVariationAssociatedData.js +11 -2
  61. package/dist/useVariationAssociatedData.js.map +1 -1
  62. package/dist/withActivateFeature.d.ts +2 -0
  63. package/dist/withActivateFeature.js +3 -12
  64. package/dist/withActivateFeature.js.map +1 -1
  65. package/dist/withAddData.js +17 -2
  66. package/dist/withAddData.js.map +1 -1
  67. package/dist/withBrowser.js +0 -1
  68. package/dist/withBrowser.js.map +1 -1
  69. package/dist/withConversion.d.ts +1 -1
  70. package/dist/withConversion.js +0 -1
  71. package/dist/withConversion.js.map +1 -1
  72. package/dist/withCustomData.js +0 -1
  73. package/dist/withCustomData.js.map +1 -1
  74. package/dist/withFeature.js +2 -3
  75. package/dist/withFeature.js.map +1 -1
  76. package/dist/withFeatureVariable.d.ts +2 -0
  77. package/dist/withFeatureVariable.js +2 -2
  78. package/dist/withFeatureVariable.js.map +1 -1
  79. package/dist/withFlush.js +0 -1
  80. package/dist/withFlush.js.map +1 -1
  81. package/dist/withInterest.js +0 -1
  82. package/dist/withInterest.js.map +1 -1
  83. package/dist/withKameleoon.js +0 -1
  84. package/dist/withKameleoon.js.map +1 -1
  85. package/dist/withPageView.js +0 -1
  86. package/dist/withPageView.js.map +1 -1
  87. package/dist/withRetrieveDataFromRemoteSource.d.ts +14 -0
  88. package/dist/withRetrieveDataFromRemoteSource.js +28 -0
  89. package/dist/withRetrieveDataFromRemoteSource.js.map +1 -0
  90. package/dist/withRunWhenReady.d.ts +16 -0
  91. package/dist/withRunWhenReady.js +28 -0
  92. package/dist/withRunWhenReady.js.map +1 -0
  93. package/dist/withTrackingConversion.d.ts +1 -1
  94. package/dist/withTrackingConversion.js +4 -6
  95. package/dist/withTrackingConversion.js.map +1 -1
  96. package/dist/withTriggerExperiment.d.ts +3 -1
  97. package/dist/withTriggerExperiment.js +4 -13
  98. package/dist/withTriggerExperiment.js.map +1 -1
  99. package/dist/withVariationAssociatedData.d.ts +4 -2
  100. package/dist/withVariationAssociatedData.js +3 -11
  101. package/dist/withVariationAssociatedData.js.map +1 -1
  102. package/dist/withVisitorCode.js +0 -1
  103. package/dist/withVisitorCode.js.map +1 -1
  104. package/package.json +3 -2
package/CHANGELOG.md CHANGED
@@ -5,6 +5,35 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
5
5
 
6
6
  [Project Homepage](https://developers.kameleoon.com/react-js-sdk.html)
7
7
 
8
+ # 3.0.0 (2022-07-01)
9
+
10
+
11
+ ### Features
12
+
13
+ * error handling
14
+
15
+ ### Breaking change
16
+
17
+ * `useFeature` hook and `withFeature` high-order component can no longer be used the same way
18
+
19
+ # 2.1.0 (2022-04-18)
20
+
21
+
22
+ ### Features
23
+
24
+ * retrieve data from remote source
25
+
26
+ # 2.0.0 (2022-02-24)
27
+
28
+
29
+ ### Features
30
+
31
+ * add multi environment support
32
+
33
+ ### Breaking change
34
+
35
+ * variableKeys became an object and no longer can be used as an array or a string
36
+
8
37
  # 1.2.2 (2022-02-06)
9
38
 
10
39
 
package/README.md CHANGED
@@ -29,8 +29,11 @@ A `KameleoonClient` created using `createClient()` to run experiments and retriv
29
29
  - `siteCode: string` - code of the website on which experiments run. This unique code id can be found in our platform.
30
30
  - `visitorCode: string` (optional) - visitor code is an optional parameter, if it is used, it automatically create custom data to check if visitor is targeted.
31
31
  - `option: SDKConfiguration` (optional) - JSON object filled with configuration parameters.
32
- - `actions_configuration_refresh_interval: number` (optional) - this specifies the refresh interval, in minutes, of the configuration for experiments and feature flags (the active experiments and feature flags are fetched from the Kameleoon servers). It means that once you launch an experiment, pause it, or stop it the changes can take (at most) the duration of this interval to be propagated in production to your servers. If not specified, the **default interval is 60 minutes**.
33
- - `visitor_data_maximum_size: number` (optional) - this specifies the maximum amount of memory that [the map holding all the visitor data](https://developers.kameleoon.com/javascript-sdk.html#technical-considerations) (in particular custom data) can take (in MB on the browser LocalStorage). If specified, **max size is 5MB**. If not specified, the **default size is 1MB**.
32
+ - `actions_configuration_refresh_interval: number` (optional) - an option specifying the refresh interval, in minutes, of the configuration for experiments and feature flags (the active experiments and feature flags are fetched from the Kameleoon servers). It means that once you launch an experiment, pause it, or stop it the changes can take (at most) the duration of this interval to be propagated in production to your servers. If not specified, the **default interval is 60 minutes**.
33
+ - `visitor_data_maximum_size: number` (optional) - an option specifying the maximum amount of memory that [the map holding all the visitor data](https://developers.kameleoon.com/javascript-sdk.html#technical-considerations) (in particular custom data) can take (in MB on the browser LocalStorage). If specified, **max size is 5MB**. If not specified, the **default size is 1MB**.
34
+ - `environment: string` (optional) - an option specifying which feature flag configuration will be used, by default each feature flag is split into **production**, **staging**, **development**. If not specified, will be set to **default value** of **production**.
35
+
36
+ **NOTICE:** make sure not to use several client instances in one application with different `environment` as it is not fully supported yet and might lead to local storage configuration being overwritten and cause bugs.
34
37
 
35
38
  #### Returns
36
39
  - A `KameleoonClient` instance.
@@ -40,11 +43,12 @@ A `KameleoonClient` created using `createClient()` to run experiments and retriv
40
43
  import { createClient } from '@kameleoon/react-sdk';
41
44
 
42
45
  const client = createClient({
43
- siteCode: '0fpmcg34lg',
46
+ siteCode: 'dfl102d38e',
44
47
  visitorCode: '280295',
45
48
  options: {
46
49
  visitor_data_maximum_size: 1,
47
- actions_configuration_refresh_interval: 60
50
+ actions_configuration_refresh_interval: 60,
51
+ environment: 'staging'
48
52
  }
49
53
  });
50
54
  ```
@@ -61,11 +65,12 @@ Use this provider in root level by wrapping your app to gain an access to `Kamel
61
65
  import { KameleoonProvider, createClient } from '@kameleoon/react-sdk';
62
66
 
63
67
  const client = createClient({
64
- siteCode: '0fpmcg34lg'
68
+ siteCode: 'dfl102d38e'
65
69
  visitorCode: '280295',
66
70
  options: {
67
71
  visitor_data_maximum_size: 1,
68
- actions_configuration_refresh_interval: 60
72
+ actions_configuration_refresh_interval: 60,
73
+ environment: 'staging'
69
74
  }
70
75
  });
71
76
 
@@ -128,30 +133,47 @@ Returns the status of a feature flag and its variables.
128
133
  #### Arguments
129
134
  - `featureParams: IFeatureParams`
130
135
  - `featureKey: string | number` - unique identifier or key of the feature you want to expose to a user.
131
- - `variableKey: string | string[]` - key of the variable.
136
+ - `variableKeys: VariableKeysType` - keys for the variables on different environments.
132
137
  - `visitorCode: string` (optional) - unique identifier of the user.
133
138
 
134
139
  #### Returns
135
- - `featureResult: IFeature`
140
+ - `errors: KameleoonException[]` - an array of errors thrown as a result of getting variables or feature flag status.
141
+ - `feature` - an object containing feature flag status and variables
136
142
  - `isActive: boolean` - feature flag status.
137
143
  - `variables: FeatureVariableType[]` - feature flag variables.
138
144
 
145
+ #### Exceptions
146
+ - `KameleoonException.NotTargeted` - Exception indicating that the current visitor / user did not trigger the required targeting conditions for this feature. The targeting conditions are defined via Kameleoon's segment builder.
147
+ - `KameleoonException.FeatureConfigurationNotFound` - Exception indicating that the requested feature ID has not been found in the internal configuration of the SDK. This is usually normal and means that the feature flag has not yet been activated on Kameleoon's side (but code implementing the feature is already deployed on the web-application's side).
148
+
139
149
 
140
150
  In this examples, if the feature flag with the `red-button` key is enabled, theme of button will set to red.
141
151
  ### `useFeature`
142
152
  #### Example
143
153
  ```jsx
144
154
  import { Button } from '@kameleoon/ui';
145
- import { useFeature, useVisitorCode } from '@kameleoon/react-sdk';
155
+ import { useFeature, useVisitorCode, KameleoonException } from '@kameleoon/react-sdk';
146
156
 
147
157
  function MyComponent(): JSX.Element {
148
158
  const { getVisitorCode } = useVisitorCode();
149
- const { isActive } = useFeature({
159
+ const { feature, errors } = useFeature({
150
160
  featureKey: 'red-button',
151
- variableKey: 'red-button',
161
+ variableKeys: { production: 'red-button' },
152
162
  visitorCode: getVisitorCode('example.com'),
153
163
  });
154
164
 
165
+ for (const error of errors) {
166
+ if (error.type === KameleoonException.NotTargeted) {
167
+ // Handle error
168
+ }
169
+
170
+ if (error.type === KameleoonException.FeatureConfigurationNotFound) {
171
+ // Handle error
172
+ }
173
+ }
174
+
175
+ const { isActive, variables } = feature;
176
+
155
177
  return <Button theme={isActive ? 'red' : 'green'} />;
156
178
  }
157
179
  ```
@@ -160,18 +182,40 @@ function MyComponent(): JSX.Element {
160
182
  #### Example
161
183
  ```jsx
162
184
  import { Button } from '@kameleoon/ui';
163
- import { withFeature } from '@kameleoon/react-sdk';
185
+ import { withFeature, KameleoonException } from '@kameleoon/react-sdk';
164
186
 
165
187
  class MyComponent extends React.Component {
188
+ state = {
189
+ isActive: false,
190
+ variables: [],
191
+ }
192
+
193
+ componentDidMount() {
194
+ const { feature, errors } = this.props;
195
+
196
+ for (const error of errors) {
197
+ if (error.type === KameleoonException.NotTargeted) {
198
+ // Handle error
199
+ }
200
+
201
+ if (error.type === KameleoonException.FeatureConfigurationNotFound) {
202
+ // Handle error
203
+ }
204
+ }
205
+
206
+ const { isActive, variables } = feature;
207
+
208
+ this.setState({ isActive, variables });
209
+ }
210
+
166
211
  render() {
167
- const { isActive, variables } = this.props;
168
- return <Button theme={isActive ? 'red' : 'green'} />;
212
+ return <Button theme={this.isActive ? 'red' : 'green'} />;
169
213
  }
170
214
  }
171
215
 
172
216
  export default withFeature({
173
217
  featureKey: 'red-button',
174
- variableKey: 'red-button',
218
+ variableKeys: { production: 'red-button' },
175
219
  visitorCode: '280295'
176
220
  })(MyComponent);
177
221
  ```
@@ -180,11 +224,13 @@ export default withFeature({
180
224
  #### Props
181
225
  - `children: (featureResult: IFeature) => ReactNode` - child elements of `Feature`.
182
226
  - `featureKey: string | number` - unique identifier or key of the feature you want to expose to a user.
183
- - `variableKey: string` - key of the variable.
227
+ - `variableKeys: VariableKeysType` - keys for the variables on different environments.
184
228
  - `visitorCode: string` - unique identifier of the user.
185
229
 
186
230
  #### Returns
187
- - A wrapped component with the following props:
231
+ A wrapped component with the following props:
232
+ - `errors: KameleoonException[]` - an array of errors thrown as a result of getting variables or feature flag status.
233
+ - `feature` - an object containing feature flag status and variables
188
234
  - `isActive: boolean` - feature flag status.
189
235
  - `variables: FeatureVariableType[]` - feature flag variables.
190
236
 
@@ -194,18 +240,44 @@ import { Button } from '@kameleoon/ui';
194
240
  import { Feature } from '@kameleoon/react-sdk';
195
241
 
196
242
  class MyComponent extends React.Component {
243
+ state = {
244
+ isActive: false,
245
+ variables: [],
246
+ }
247
+
248
+ componentDidMount() {
249
+ const { feature, errors } = this.props;
250
+
251
+ for (const error of errors) {
252
+ if (error.type === KameleoonException.NotTargeted) {
253
+ // Handle error
254
+ }
255
+
256
+ if (error.type === KameleoonException.FeatureConfigurationNotFound) {
257
+ // Handle error
258
+ }
259
+ }
260
+
261
+ const { isActive, variables } = feature;
262
+
263
+ this.setState({ isActive, variables });
264
+ }
265
+
197
266
  render() {
198
- const { isActive, variables } = this.props;
199
- return <Button theme={isActive ? 'red' : 'green'} />;
267
+ return <Button theme={this.isActive ? 'red' : 'green'} />;
200
268
  }
201
269
  }
202
270
 
203
- class MyCompWrapper extends React.Component {
271
+ class MyComponentWrapper extends React.Component {
204
272
  render() {
205
273
  return(
206
- <Feature featureKey="red-button" variableKey="red-button" visitorCode="280295">
207
- (({isActive, variables}) => (
208
- <MyComponent isActive={isActive} variables={variables} />
274
+ <Feature
275
+ featureKey="red-button"
276
+ variableKeys={{production: "red-button"}}
277
+ visitorCode="280295"
278
+ >
279
+ (({ feature, errors }) => (
280
+ <MyComponent feature={feature} errors={errors} />
209
281
  ))
210
282
  </Feature>;
211
283
  )
@@ -299,7 +371,7 @@ You have to make sure that proper error handling is set up in your code as shown
299
371
  ##### Please Note:
300
372
  _By convention, the reference (original variation) always has an ID equal to **0**._
301
373
 
302
- #### Exceptions Thrown
374
+ #### Exceptions
303
375
  - `KameleoonException.NotTargeted` - Exception indicating that the current visitor / user did not trigger the required targeting conditions for this experiment. The targeting conditions are defined via Kameleoon's segment builder.
304
376
  - `KameleoonException.NotActivated` - Exception indicating that the current visitor / user triggered the experiment (met the targeting conditions), but did not activate it. The most common reason for that is that part of the traffic has been excluded from the experiment and should not be tracked.
305
377
  - `KameleoonException.ExperimentConfigurationNotFound` - Exception indicating that the requested experiment ID has not been found in the internal configuration of the SDK. This is usually normal and means that the experiment has not yet been started on Kameleoon's side (but code triggering / implementing variations is already deployed on the web-application's side).
@@ -315,20 +387,33 @@ _By convention, the reference (original variation) always has an ID equal to **0
315
387
  ### `useTriggerExperiment`
316
388
  #### Returns
317
389
  - A callback function `getVariationId()`.
390
+ - An `error` object containing `name`, `type` and `message` strings, certain type of exception can be handled using `error.type` and `KameleoonException`. If there is no errors on the client `error` will be `null`.
318
391
 
319
392
  #### Example
320
393
  ```jsx
321
394
  import { useEffect } from 'react';
322
- import { useTriggerExperiment, useVisitorCode } from '@kameleoon/react-sdk';
395
+ import { useTriggerExperiment, useVisitorCode, KameleoonException } from '@kameleoon/react-sdk';
323
396
 
324
397
  function MyComponent(): JSX.Element {
325
- const { getVariationId } = useTriggerExperiment();
398
+ const { getVariationId, error } = useTriggerExperiment();
326
399
  const { getVisitorCode } = useVisitorCode();
327
400
 
328
401
  useEffect(() => {
329
402
  const visitorCode = getVisitorCode('example.com');
330
403
  const experimentId = 12341;
331
404
 
405
+ if (error?.type === KameleoonException.ExperimentConfigurationNotFound) {
406
+ // Handle exception
407
+ }
408
+
409
+ if (error?.type === KameleoonException.NotTargeted) {
410
+ // Handle exception
411
+ }
412
+
413
+ if (error?.type === KameleoonException.NotActivated) {
414
+ // Handle exception
415
+ }
416
+
332
417
  const variationId = getVariationId(visitorCode, experimentId);
333
418
  }, []);
334
419
 
@@ -345,14 +430,26 @@ function MyComponent(): JSX.Element {
345
430
 
346
431
  #### Example
347
432
  ```jsx
348
- import { withVisitorCode, withTriggerExperiment, compose } from '@kameleoon/react-sdk';
433
+ import { withVisitorCode, withTriggerExperiment, compose, KameleoonException } from '@kameleoon/react-sdk';
349
434
 
350
435
  class MyComponent extends React.Component {
351
436
  componentDidMount() {
352
- const { getVisitorCode, getVariationId } = this.props;
437
+ const { getVisitorCode, getVariationId, triggerExperimentError } = this.props;
353
438
  const visitorCode = getVisitorCode('example.com');
354
439
  const experimentId = 230243;
355
440
 
441
+ if (triggerExperimentError?.type === KameleoonException.ExperimentConfigurationNotFound) {
442
+ // Handle exception
443
+ }
444
+
445
+ if (triggerExperimentError?.type === KameleoonException.NotTargeted) {
446
+ // Handle exception
447
+ }
448
+
449
+ if (triggerExperimentError?.type === KameleoonException.NotActivated) {
450
+ // Handle exception
451
+ }
452
+
356
453
  const variationId = getVariationId(visitorCode, experimentId);
357
454
  }
358
455
 
@@ -365,9 +462,9 @@ export default compose(withVisitorCode, withTriggerExperiment)(MyComponent);
365
462
  ## Activate feature
366
463
  A callback function `hasFeature()` which validates if user has been associated with this feature. If it is fails, callback returns value **false**, otherwise **true**.
367
464
 
368
- If feature flag is not activated, `KameleoonException.FeatureConfigurationNotFound` exception will be thrown. Please, make sure to handle properly the error.
465
+ If feature flag is not activated, `KameleoonException.FeatureConfigurationNotFound` exception will be thrown. Please, make sure to handle the error properly.
369
466
 
370
- #### Exceptions Thrown
467
+ #### Exceptions
371
468
  - `KameleoonException.NotTargeted` - Exception indicating that the current visitor / user did not trigger the required targeting conditions for this feature. The targeting conditions are defined via Kameleoon's segment builder.
372
469
  - `KameleoonException.FeatureConfigurationNotFound` - Exception indicating that the requested feature ID has not been found in the internal configuration of the SDK. This is usually normal and means that the feature flag has not yet been activated on Kameleoon's side (but code implementing the feature is already deployed on the web-application's side).
373
470
 
@@ -382,20 +479,29 @@ If feature flag is not activated, `KameleoonException.FeatureConfigurationNotFou
382
479
  ### `useActivateFeature`
383
480
  #### Returns
384
481
  - A callback function `hasFeature()`.
482
+ - An `error` object containing `name`, `type` and `message` strings, certain type of exception can be handled using `error.type` and `KameleoonException`. If there is no errors on the client `error` will be `null`.
385
483
 
386
484
  #### Example
387
485
  ```jsx
388
486
  import { useEffect } from 'react';
389
- import { useActivateFeature, useVisitorCode } from '@kameleoon/react-sdk';
487
+ import { useActivateFeature, useVisitorCode, KameleoonException } from '@kameleoon/react-sdk';
390
488
 
391
489
  function MyComponent(): JSX.Element {
392
- const { hasFeature } = useActivateFeature();
490
+ const { hasFeature, error } = useActivateFeature();
393
491
  const { getVisitorCode } = useVisitorCode();
394
492
 
395
493
  useEffect(() => {
396
494
  const visitorCode = getVisitorCode('example.com');
397
495
  const featureKey = 'example-feature-key';
398
496
 
497
+ if (error?.type === KameleoonException.FeatureConfigurationNotFound) {
498
+ // Handle exception
499
+ }
500
+
501
+ if (error?.type === KameleoonException.NotTargeted) {
502
+ // Handle exception
503
+ }
504
+
399
505
  const feature = hasFeature(visitorCode, featureKey);
400
506
  }, []);
401
507
 
@@ -405,21 +511,29 @@ function MyComponent(): JSX.Element {
405
511
 
406
512
  ### `withActivateFeature`
407
513
  #### Arguments
408
- - `Component: React.Component` - component which will be enhanced with the prop `hasFeature()`.
514
+ - `Component: React.Component` - component which will be enhanced with the prop `hasFeature()` and `activateFeatureError`.
409
515
 
410
516
  #### Returns
411
517
  - A wrapped component with additional props as described above.
412
518
 
413
519
  #### Example
414
520
  ```jsx
415
- import { withVisitorCode, withActivateFeature, compose } from '@kameleoon/react-sdk';
521
+ import { withVisitorCode, withActivateFeature, KameleoonException, compose } from '@kameleoon/react-sdk';
416
522
 
417
523
  class MyComponent extends React.Component {
418
524
  componentDidMount() {
419
- const { getVisitorCode, hasFeature } = this.props;
525
+ const { getVisitorCode, hasFeature, activateFeatureError } = this.props;
420
526
  const visitorCode = getVisitorCode('example.com');
421
527
  const featureKey = 'example-feature-key';
422
528
 
529
+ if (activateFeatureError?.type === KameleoonException.FeatureConfigurationNotFound) {
530
+ // Handle exception
531
+ }
532
+
533
+ if (activateFeatureError?.type === KameleoonException.NotTargeted) {
534
+ // Handle exception
535
+ }
536
+
423
537
  const feature = hasFeature(visitorCode, featureKey);
424
538
  }
425
539
 
@@ -430,11 +544,11 @@ export default compose(withVisitorCode, withActivateFeature)(MyComponent);
430
544
  ```
431
545
 
432
546
  ## Obtain variation associated data
433
- A callback function `getVariationAssociatedData()` which retrieves JSON data assiciated with a variation. The JSON data usually represents some metadata of the variation, and can be configured on our web application interface or via our Automation API.
547
+ A callback function `getVariationAssociatedData()` which retrieves JSON data associated with a variation. The JSON data usually represents some metadata of the variation, and can be configured on our web application interface or via our Automation API.
434
548
 
435
- This calllback function takes the `variationId` as a parameter and will return the data as a JavaScript object. It will throw an exception `(KameleoonException.VariationConfigurationNotFound)` if the `variationId` is wrong or corresponds to an experiment that is not yet online.
549
+ This callback function takes the `variationId` as a parameter and will return the data as a JavaScript object. It will throw an exception `(KameleoonException.VariationConfigurationNotFound)` if the `variationId` is wrong or corresponds to an experiment that is not yet online.
436
550
 
437
- #### Exceptions Thrown
551
+ #### Exceptions
438
552
  - `KameleoonException.VariationConfigurationNotFound` - Exception indicating that the requested variation ID has not been found in the internal configuration of the SDK. This is usually normal and means that the variation's corresponding experiment has not yet been activated on Kameleoon's side.
439
553
 
440
554
  #### `getVariationAssociatedData()`
@@ -448,17 +562,23 @@ This calllback function takes the `variationId` as a parameter and will return t
448
562
  ### `useVariationAssociatedData`
449
563
  #### Returns
450
564
  - A callback function `getVariationAssociatedData()`.
565
+ - An `error` object containing `name`, `type` and `message` strings, certain type of exception can be handled using `error.type` and `KameleoonException`. If there is no errors on the client `error` will be `null`.
451
566
 
452
567
  #### Example
453
568
  ```jsx
454
569
  import { useEffect } from 'react';
455
- import { useVariationAssociatedData } from '@kameleoon/react-sdk';
570
+ import { useVariationAssociatedData, KameleoonException } from '@kameleoon/react-sdk';
456
571
 
457
572
  function MyComponent(): JSX.Element {
458
- const { getVariationAssociatedData } = useVariationAssociatedData();
573
+ const { getVariationAssociatedData, error } = useVariationAssociatedData();
459
574
 
460
575
  useEffect(() => {
461
576
  const variationId = 280295;
577
+
578
+ if (error?.type === KameleoonException.VariationConfigurationNotFound) {
579
+ // Handle error
580
+ }
581
+
462
582
  const data = getVariationAssociatedData(variationId);
463
583
  }, []);
464
584
 
@@ -474,12 +594,17 @@ function MyComponent(): JSX.Element {
474
594
 
475
595
  #### Example
476
596
  ```jsx
477
- import { withVariationAssociatedData } from '@kameleoon/react-sdk';
597
+ import { withVariationAssociatedData, KameleoonException } from '@kameleoon/react-sdk';
478
598
 
479
599
  class MyComponent extends React.Component {
480
600
  componentDidMount() {
481
- const { getVariationAssociatedData } = this.props;
601
+ const { getVariationAssociatedData, variationAssociatedDataError } = this.props;
482
602
  const variationId = 280295;
603
+
604
+ if (variationAssociatedDataError?.type === KameleoonException.VariationConfigurationNotFound) {
605
+ // Handle error
606
+ }
607
+
483
608
  const data = getVariationAssociatedData(variationId);
484
609
  }
485
610
 
@@ -489,6 +614,74 @@ class MyComponent extends React.Component {
489
614
  export default withVariationAssociatedData(MyComponent);
490
615
  ```
491
616
 
617
+ ## Obtain data from remote source
618
+ An callback function `retrieveDataFromRemoteSource()` can be used to retrieve data using specific key and siteCode from Kameleoon provider. The Data is stored on a remote Kameleoon server. Usually data will be stored on our remote servers via the use of our Data API. This method, along with the availability of our highly scalable servers for this purpose, provides a convenient way to quickly store massive amounts of data that can be later retrieved for each of your visitors / users.
619
+
620
+ Note that since a server call is required, this mechanism is asynchronous, make sure to properly handle promise which will be returned from a function call.
621
+
622
+
623
+ #### Exceptions Thrown
624
+ - Local Error will be thrown if remote source data couldn't be accessed or retrieved data contains an empty JSON.
625
+
626
+ #### `retrieveDataFromRemoteSource()`
627
+
628
+ ##### Arguments
629
+ - `key: string` - unique key for the current siteCode used to store data on the remote source (can be created via `POST` request to Kameleoon Data API). This field is mandatory.
630
+
631
+ ##### Returns
632
+ - JSON object with the data posted to Kameleoon Data API.
633
+
634
+ #### Types
635
+ - `RemoteSourceDataType` can be used for handling data type.
636
+
637
+ ### `useRetrieveDataFromRemoteSource`
638
+ #### Returns
639
+ - A callback function `retrieveDataFromRemoteSource()`.
640
+
641
+ #### Example
642
+ ```jsx
643
+ import { useEffect, useCallback } from 'react';
644
+ import { useRetrieveDataFromRemoteSource, RemoteSourceDataType } from '@kameleoon/react-sdk';
645
+
646
+ function MyComponent(): JSX.Element {
647
+ const { retrieveDataFromRemoteSource } = useRetrieveDataFromRemoteSource();
648
+
649
+ const processRetrievedData = useCallback(async () => {
650
+ const data: RemoteSourceDataType = await retrieveDataFromRemoteSource('example-key');
651
+ // Your code
652
+ }, [retrieveDataFromRemoteSource]);
653
+
654
+ useEffect(() => {
655
+ processRetrievedData();
656
+ }, [processRetrievedData]);
657
+
658
+ ...
659
+ }
660
+ ```
661
+ ### `withRetrieveDataFromRemoteSource`
662
+ #### Arguments
663
+ - `Component: React.Component` - component which will be enhanced with the prop `retrieveDataFromRemoteSource()`.
664
+
665
+ #### Returns
666
+ - A wrapped component with additional props as described above.
667
+
668
+ #### Example
669
+ ```jsx
670
+ import { withRetrieveDataFromRemoteSource, RemoteSourceDataType } from '@kameleoon/react-sdk';
671
+
672
+ class MyComponent extends React.Component {
673
+ async componentDidMount() {
674
+ const { retrieveDataFromRemoteSource } = this.props;
675
+ const data: RemoteSourceDataType = await getVariationAssociatedData('example-key');
676
+ // Your code
677
+ }
678
+
679
+ ...
680
+ }
681
+
682
+ export default withRetrieveDataFromRemoteSource(MyComponent);
683
+ ```
684
+
492
685
  ## Obtain feature variable
493
686
  A callback function `getFeatureVariable()` which retrieves a feature variable.
494
687
 
@@ -725,7 +918,6 @@ The `flush()` callback function is non-blocking as the server call is made async
725
918
  #### Example
726
919
  ```jsx
727
920
  import { useEffect } from 'react';
728
- import { Button } from '@kameleoon/ui';
729
921
  import {
730
922
  useAddData,
731
923
  useBrowser,
@@ -789,6 +981,86 @@ export default compose(
789
981
  )(MyComponent);
790
982
  ```
791
983
 
984
+ ## Run when ready
985
+ In certain scenarios when working with Kameleoon API it's important to make sure that the client was initialized properly within the certain timeout. It's especially important while using `triggerExperiment()` or `trackConversion()`. For these cases it's possible to use `runWhenReady()` function, retrieved by `useRunWhenReady` hook or `withRunWhenReady` high-order component.
986
+
987
+ The `runWhenReady()` function makes sure that Kameleoon Client will be initialized properly using HTTP call withing the specified timeout.
988
+
989
+ #### `runWhenReady()`
990
+ ##### Arguments
991
+ - `successCallback: () => void` - callback which will be executed on successful client initialization.
992
+ - `errorCallback: () => void` - callback which will be executed if client wasn't able to initialize during the timeout.
993
+ - `timeout?: number` - timeout which is given to perform HTTP call for initialization in ms (by default: 2000 ms).
994
+
995
+ #### Example
996
+ ```jsx
997
+ import { useEffect, useCallback, useState } from 'react';
998
+ import { useRunWhenReady, useTriggerExperiment } from '@kameleoon/react-sdk';
999
+
1000
+ function MyComponent(): JSX.Element {
1001
+ const { runWhenReady } = useRunWhenReady();
1002
+ const { getVariationId } = useTriggerExperiment();
1003
+
1004
+ const [variationId, setVariationId] = useState<number>(0);
1005
+
1006
+ const getVariationSuccessCallback = useCallback(() => {
1007
+ const id = getVariationId('user_id', 12345);
1008
+ setVariationId(id);
1009
+ }, [getVariationId, isRenderProps]);
1010
+
1011
+ const getVariationErrorCallback = useCallback(() => {
1012
+ throw new Error(
1013
+ "Couldn't get server configuration from HTTP request in a specified time",
1014
+ );
1015
+ }, []);
1016
+
1017
+ useEffect(() => {
1018
+ runWhenReady(
1019
+ getVariationSuccessCallback,
1020
+ getVariationErrorCallback,
1021
+ 1000,
1022
+ );
1023
+ }, [runWhenReady, getVariationSuccessCallback, getVariationErrorCallback]);
1024
+
1025
+ ...
1026
+ }
1027
+ ```
1028
+
1029
+ ### `withRunWhenReady`
1030
+ #### Arguments
1031
+ - `Component: React.Component` - component which will be enhanced with the prop `runWhenReady()`.
1032
+
1033
+ #### Example
1034
+ ```jsx
1035
+ import { useEffect, useCallback, useState } from 'react';
1036
+ import { withRunWhenReady, withTriggerExperiment } from '@kameleoon/react-sdk';
1037
+
1038
+ class MyComponent extends React.Component {
1039
+ variationSuccessCallback(): void {
1040
+ const id = this.props.getVariationId('user_id', 12345);
1041
+ setVariationId(id);
1042
+ }
1043
+
1044
+ variationErrorCallback(): void {
1045
+ const id = this.props.getVariationId('user_id', 12345);
1046
+ setVariationId(id);
1047
+ }
1048
+
1049
+ componentDidMount() {
1050
+ this.props.runWhenReady(this.variationSuccessCallback, this.variationErrorCallback, 1000);
1051
+ }
1052
+
1053
+ ...
1054
+ }
1055
+
1056
+ export default compose(
1057
+ withRunWhenReady,
1058
+ withTriggerExperiment,
1059
+ )(MyComponent);
1060
+ ```
1061
+
1062
+ #### Returns
1063
+ - A wrapped component with additional props as described above.
792
1064
 
793
1065
  ## Browser
794
1066
  A callback function `addBrowser()` adds browser type.
package/dist/Feature.js CHANGED
@@ -19,8 +19,8 @@ var useFeature_1 = require("./useFeature");
19
19
  * to the status of a feature flag and its variables
20
20
  */
21
21
  function Feature(props) {
22
- var feature = (0, useFeature_1.useFeature)(__assign({}, props));
23
- return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: props.children(feature) }, void 0);
22
+ var result = (0, useFeature_1.useFeature)(__assign({}, props));
23
+ return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: props.children(result) }, void 0);
24
24
  }
25
25
  exports.Feature = Feature;
26
26
  //# sourceMappingURL=Feature.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Feature.js","sourceRoot":"","sources":["../src/Feature.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;AACA,2CAA0C;AAM1C;;;GAGG;AACH,SAAgB,OAAO,CAAC,KAAoB;IAC1C,IAAM,OAAO,GAAG,IAAA,uBAAU,eAAM,KAAK,EAAG,CAAC;IAEzC,OAAO,2DAAG,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,WAAI,CAAC;AACxC,CAAC;AAJD,0BAIC"}
1
+ {"version":3,"file":"Feature.js","sourceRoot":"","sources":["../src/Feature.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;AACA,2CAA0C;AAM1C;;;GAGG;AACH,SAAgB,OAAO,CAAC,KAAoB;IAC1C,IAAM,MAAM,GAAG,IAAA,uBAAU,eAAM,KAAK,EAAG,CAAC;IAExC,OAAO,2DAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAI,CAAC;AACvC,CAAC;AAJD,0BAIC"}
@@ -0,0 +1,5 @@
1
+ import { KameleoonException } from './constants';
2
+ export declare class KameleoonError extends Error {
3
+ type: KameleoonException;
4
+ constructor(type: KameleoonException);
5
+ }
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ var __extends = (this && this.__extends) || (function () {
3
+ var extendStatics = function (d, b) {
4
+ extendStatics = Object.setPrototypeOf ||
5
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7
+ return extendStatics(d, b);
8
+ };
9
+ return function (d, b) {
10
+ if (typeof b !== "function" && b !== null)
11
+ throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
12
+ extendStatics(d, b);
13
+ function __() { this.constructor = d; }
14
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
+ };
16
+ })();
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.KameleoonError = void 0;
19
+ var KameleoonError = /** @class */ (function (_super) {
20
+ __extends(KameleoonError, _super);
21
+ function KameleoonError(type) {
22
+ var _this = _super.call(this, "Error: ".concat(type)) || this;
23
+ _this.name = 'KameleoonError';
24
+ _this.message = "".concat(_this.name, ".").concat(type);
25
+ _this.type = type;
26
+ return _this;
27
+ }
28
+ return KameleoonError;
29
+ }(Error));
30
+ exports.KameleoonError = KameleoonError;
31
+ //# sourceMappingURL=KameleoonError.js.map