@croct/plug-react 0.4.2 → 0.5.0-next.2

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 (92) hide show
  1. package/CroctProvider.d.ts +7 -7
  2. package/CroctProvider.js +37 -0
  3. package/CroctProvider.js.map +1 -0
  4. package/README.md +245 -107
  5. package/api/evaluate.d.ts +7 -0
  6. package/api/evaluate.js +15 -0
  7. package/api/evaluate.js.map +1 -0
  8. package/api/fetchContent.d.ts +13 -0
  9. package/api/fetchContent.js +20 -0
  10. package/api/fetchContent.js.map +1 -0
  11. package/api/index.d.ts +2 -0
  12. package/api/index.js +19 -0
  13. package/api/index.js.map +1 -0
  14. package/components/Personalization/index.d.ts +10 -10
  15. package/components/Personalization/index.js +13 -0
  16. package/components/Personalization/index.js.map +1 -0
  17. package/components/Slot/index.d.ts +19 -19
  18. package/components/Slot/index.js +13 -0
  19. package/components/Slot/index.js.map +1 -0
  20. package/components/index.d.ts +2 -2
  21. package/components/index.js +19 -0
  22. package/components/index.js.map +1 -0
  23. package/hooks/Cache.d.ts +22 -22
  24. package/hooks/Cache.js +62 -0
  25. package/hooks/Cache.js.map +1 -0
  26. package/hooks/index.d.ts +3 -3
  27. package/hooks/index.js +20 -0
  28. package/hooks/index.js.map +1 -0
  29. package/hooks/useContent.d.ts +18 -17
  30. package/hooks/useContent.js +25 -0
  31. package/hooks/useContent.js.map +1 -0
  32. package/hooks/useCroct.d.ts +2 -2
  33. package/hooks/useCroct.js +14 -0
  34. package/hooks/useCroct.js.map +1 -0
  35. package/hooks/useEvaluation.d.ts +11 -11
  36. package/hooks/useEvaluation.js +35 -0
  37. package/hooks/useEvaluation.js.map +1 -0
  38. package/hooks/useLoader.d.ts +5 -5
  39. package/hooks/useLoader.js +41 -0
  40. package/hooks/useLoader.js.map +1 -0
  41. package/index.d.ts +5 -3
  42. package/index.js +20 -337
  43. package/index.js.map +1 -1
  44. package/package.json +33 -46
  45. package/src/api/evaluate.test.ts +59 -0
  46. package/src/api/evaluate.ts +19 -0
  47. package/src/api/fetchContent.test.ts +134 -0
  48. package/src/api/fetchContent.ts +47 -0
  49. package/src/api/index.ts +2 -0
  50. package/src/components/index.ts +2 -0
  51. package/src/global.d.ts +7 -0
  52. package/src/hooks/Cache.test.ts +280 -0
  53. package/src/hooks/Cache.ts +97 -0
  54. package/src/hooks/index.ts +3 -0
  55. package/src/hooks/useContent.ssr.test.ts +23 -0
  56. package/src/hooks/useContent.test.ts +66 -0
  57. package/src/hooks/useContent.ts +69 -0
  58. package/src/hooks/useCroct.ts +13 -0
  59. package/src/hooks/useEvaluation.ssr.test.ts +23 -0
  60. package/src/hooks/useEvaluation.test.ts +92 -0
  61. package/src/hooks/useEvaluation.ts +58 -0
  62. package/src/hooks/useLoader.test.ts +320 -0
  63. package/src/hooks/useLoader.ts +50 -0
  64. package/src/index.ts +5 -0
  65. package/src/react-app-env.d.ts +1 -0
  66. package/src/ssr-polyfills.ssr.test.ts +46 -0
  67. package/src/ssr-polyfills.test.ts +65 -0
  68. package/src/ssr-polyfills.ts +68 -0
  69. package/ssr-polyfills.d.ts +3 -3
  70. package/ssr-polyfills.js +64 -0
  71. package/ssr-polyfills.js.map +1 -0
  72. package/CroctProvider.test.d.ts +0 -1
  73. package/components/Personalization/index.d.test.d.ts +0 -1
  74. package/components/Personalization/index.stories.d.ts +0 -7
  75. package/components/Personalization/index.test.d.ts +0 -1
  76. package/components/Slot/index.d.test.d.ts +0 -1
  77. package/components/Slot/index.stories.d.ts +0 -17
  78. package/components/Slot/index.test.d.ts +0 -1
  79. package/hooks/Cache.test.d.ts +0 -1
  80. package/hooks/useContent.d.test.d.ts +0 -1
  81. package/hooks/useContent.ssr.test.d.ts +0 -1
  82. package/hooks/useContent.stories.d.ts +0 -19
  83. package/hooks/useContent.test.d.ts +0 -1
  84. package/hooks/useCroct.ssr.test.d.ts +0 -1
  85. package/hooks/useCroct.test.d.ts +0 -1
  86. package/hooks/useEvaluation.d.test.d.ts +0 -1
  87. package/hooks/useEvaluation.ssr.test.d.ts +0 -1
  88. package/hooks/useEvaluation.stories.d.ts +0 -8
  89. package/hooks/useEvaluation.test.d.ts +0 -1
  90. package/hooks/useLoader.test.d.ts +0 -1
  91. package/ssr-polyfills.ssr.test.d.ts +0 -1
  92. package/ssr-polyfills.test.d.ts +0 -1
package/README.md CHANGED
@@ -23,7 +23,8 @@
23
23
 
24
24
  ## Introduction
25
25
 
26
- The React Plug library provides components and hooks for personalizing applications in real-time that are easy for your marketing team to scale and maintain.
26
+ The React Plug library provides components and hooks for personalizing applications in real-time that are easy for your
27
+ marketing team to scale and maintain.
27
28
 
28
29
  - **Easy integration**: personalize existing components without touching their code.
29
30
  - **Suspense-ready**: take advantage of the latest React features to improve user experience.
@@ -68,32 +69,33 @@ import {render} from 'react-dom';
68
69
  import {CroctProvider} from '@croct/plug-react';
69
70
 
70
71
  function App() {
71
- return (
72
- <CroctProvider appId="<APP_ID>">
73
- <div>
74
- <h1>My first personalized app 🚀</h1>
75
- </div>
76
- </CroctProvider>
77
- );
72
+ return (
73
+ <CroctProvider appId="<APP_ID>">
74
+ <div>
75
+ <h1>My first personalized app 🚀</h1>
76
+ </div>
77
+ </CroctProvider>
78
+ );
78
79
  }
79
80
 
80
- render(<App />, document.getElementById('root'));
81
+ render(<App/>, document.getElementById('root'));
81
82
  ```
82
83
 
83
84
  > Replace `<APP_ID>` with your public app ID that you can find at Workspaces > Applications > Setup.
84
85
  > In case you don't have an account yet, you can use the sandbox application ID `00000000-0000-0000-0000-000000000000`
85
86
 
86
- ### Evaluating expressions
87
+ ### Evaluating queries
87
88
 
88
89
  Once your application is plugged in, you're ready to start personalizing your components using the `<Personalization />`
89
90
  component or the `useEvaluation` hook.
90
91
 
91
- We'll go through a simple example that shows how you can implement feature flags (also known as feature toggles)
92
+ We'll go through a simple example that shows how you can implement feature flags (also known as feature toggles)
92
93
  to conditionally renders a different button depending on the user's persona.
93
94
 
94
95
  ![Evaluation Example](https://user-images.githubusercontent.com/943036/116588852-6a114200-a8f2-11eb-9d88-c346f002e2a1.png)
95
96
 
96
- Let's first implement the use-case using the `<Personalization />` component. It takes an expression (e.g. `user's persona`)
97
+ Let's first implement the use-case using the `<Personalization />` component. It takes an query (
98
+ e.g. `user's persona`)
97
99
  and a render function, which tells the component how to render the UI, depending on the evaluation result.
98
100
 
99
101
  This is what our component would look like:
@@ -105,7 +107,7 @@ import {Personalization} from '@croct/plug-react';
105
107
  function OnboardingPage(): ReactElement {
106
108
  return (
107
109
  <Suspense fallback="✨ Personalizing...">
108
- <Personalization expression="user's persona is not 'developer'">
110
+ <Personalization query="user's persona is not 'developer'">
109
111
  {(isDeveloper: boolean) => isDeveloper
110
112
  ? <a href="/docs">View docs</a>
111
113
  : <a href="/share">Share with your developer</a>
@@ -124,7 +126,7 @@ import {Personalization} from '@croct/plug-react';
124
126
 
125
127
  function OnboardingPage(): ReactElement {
126
128
  return (
127
- <Personalization expression="user's persona is not 'developer'" initial={false}>
129
+ <Personalization query="user's persona is not 'developer'" initial={false}>
128
130
  {(isDeveloper: boolean) => isDeveloper
129
131
  ? <a href="/docs">View docs</a>
130
132
  : <a href="/share">Share with your developer</a>
@@ -153,7 +155,7 @@ function ViewDocsLink(): ReactElement {
153
155
  export default function OnboardingPage(): ReactElement {
154
156
  return (
155
157
  <Suspense fallback="✨ Personalizing...">
156
- <ViewDocsLink />
158
+ <ViewDocsLink/>
157
159
  </Suspense>
158
160
  )
159
161
  }
@@ -166,8 +168,8 @@ user's profile.
166
168
 
167
169
  #### Fault tolerance
168
170
 
169
- We strongly recommend specifying the `fallback` property in client-side rendered applications to ensure your app behaves
170
- the same way regardless of the personalization. In this way, the UI will still be fully functional even in maintenance
171
+ We strongly recommend specifying the `fallback` property in client-side rendered applications to ensure your app behaves
172
+ the same way regardless of the personalization. In this way, the UI will still be fully functional even in maintenance
171
173
  windows. **Specifying a `fallback` is required for server-side rendering (SSR).**
172
174
 
173
175
  The following example shows how you can specify a fallback behaviour for the docs link:
@@ -186,7 +188,7 @@ export default function OnboardingPage(): ReactElement {
186
188
  return (
187
189
  <Suspense fallback="✨ Personalizing...">
188
190
  {/* Using the <Personalization /> component */}
189
- <Personalization expression="user's persona is 'developer'" fallback={false}>
191
+ <Personalization query="user's persona is 'developer'" fallback={false}>
190
192
  {(isDeveloper: boolean) => (
191
193
  <Fragment>
192
194
  {isDeveloper && <a href="/docs">View docs</a>}
@@ -195,7 +197,7 @@ export default function OnboardingPage(): ReactElement {
195
197
  </Personalization>
196
198
 
197
199
  {/* Using useEvaluation hook */}
198
- <ViewDocsLink />
200
+ <ViewDocsLink/>
199
201
  </Suspense>
200
202
  )
201
203
  }
@@ -205,7 +207,7 @@ For a full list of the available options, please refer to the [API documentation
205
207
 
206
208
  ### Using slots
207
209
 
208
- Evaluating expression is a flexible and powerful way to customize your UI. However, for components whose content
210
+ Evaluating query is a flexible and powerful way to customize your UI. However, for components whose content
209
211
  changes too often, this approach can be overkill. For those cases, we encourage you to use the Slots feature instead.
210
212
  Using slots gives your team the flexibility to change the content or personalization rules whenever needed without
211
213
  touching the component code.
@@ -240,19 +242,23 @@ import {ReactElement, Suspense} from 'react';
240
242
  import {Slot} from '@croct/plug-react';
241
243
 
242
244
  type HomeBannerContent = {
243
- title: string,
244
- subtitle: string,
245
- cta: {
246
- label: string,
247
- link: string,
248
- },
245
+ title: string,
246
+ subtitle: string,
247
+ cta: {
248
+ label: string,
249
+ link: string,
250
+ },
249
251
  };
250
252
 
251
253
  export default function OnboardingPage(): ReactElement {
252
254
  return (
253
255
  <Suspense fallback="✨ Personalizing content...">
254
256
  <Slot id="home-banner">
255
- {({title, subtitle, cta}: HomeBannerContent) => (
257
+ {({
258
+ title,
259
+ subtitle,
260
+ cta
261
+ }: HomeBannerContent) => (
256
262
  <div>
257
263
  <strong>{title}</strong>
258
264
  <p>{subtitle}</p>
@@ -272,26 +278,26 @@ import {ReactElement} from 'react';
272
278
  import {Slot} from '@croct/plug-react';
273
279
 
274
280
  type HomeBannerContent = {
275
- title: string,
276
- subtitle: string,
277
- cta: {
278
- label: string,
279
- link: string,
280
- },
281
+ title: string,
282
+ subtitle: string,
283
+ cta: {
284
+ label: string,
285
+ link: string,
286
+ },
281
287
  };
282
288
 
283
289
  export default function OnboardingPage(): ReactElement {
284
290
  return (
285
291
  <Slot id="home-banner" initial={null}>
286
- {(props: HomeBannerContent|null) => (
287
- props === null
292
+ {(props: HomeBannerContent | null) => (
293
+ props === null
288
294
  ? '✨ Personalizing...'
289
295
  : (
290
296
  <div>
291
297
  <strong>{props.title}</strong>
292
298
  <p>{props.subtitle}</p>
293
299
  <a href={props.cta.link}>{props.cta.label}</a>
294
- </div>
300
+ </div>
295
301
  )
296
302
  )}
297
303
  </Slot>
@@ -306,16 +312,20 @@ import {ReactElement, Suspense} from 'react';
306
312
  import {useContent} from '@croct/plug-react';
307
313
 
308
314
  type HomeBannerContent = {
309
- title: string,
310
- subtitle: string,
311
- cta: {
312
- label: string,
313
- link: string,
314
- },
315
+ title: string,
316
+ subtitle: string,
317
+ cta: {
318
+ label: string,
319
+ link: string,
320
+ },
315
321
  };
316
322
 
317
323
  function HomeBanner(): ReactElement {
318
- const {title, subtitle, cta} = useContent<HomeBannerContent>('home-banner');
324
+ const {
325
+ title,
326
+ subtitle,
327
+ cta
328
+ } = useContent<HomeBannerContent>('home-banner');
319
329
 
320
330
  return (
321
331
  <div>
@@ -335,6 +345,15 @@ export default function HomePage(): ReactElement {
335
345
  }
336
346
  ```
337
347
 
348
+ You can specify the version of the slot by passing a versioned ID in the form `id@version`. For example,
349
+ passing `home-banner@1` will fetch the content for the `home-banner` slot in version 1. Not specifying a
350
+ version number is the same as passing `home-banner@latest`, which will load the latest version of the slot.
351
+
352
+ > ✅ Best practice
353
+ > It's strongly recommended to specify a slot version for production deployments.
354
+ > That way, you ensure the front end will always receive content with the expected
355
+ > schema while your team can freely evolve the content's schema in parallel.
356
+
338
357
  #### Fault tolerance
339
358
 
340
359
  The following example shows how you can specify a fallback state for the `home-banner` slot:
@@ -344,12 +363,12 @@ import {ReactElement, Suspense} from 'react';
344
363
  import {Slot, useContent} from '@croct/plug-react';
345
364
 
346
365
  type HomeBannerContent = {
347
- title: string,
348
- subtitle: string,
349
- cta: {
350
- label: string,
351
- link: string,
352
- },
366
+ title: string,
367
+ subtitle: string,
368
+ cta: {
369
+ label: string,
370
+ link: string,
371
+ },
353
372
  };
354
373
 
355
374
  const fallbackBanner: HomeBannerContent = {
@@ -362,7 +381,11 @@ const fallbackBanner: HomeBannerContent = {
362
381
  };
363
382
 
364
383
  function HomeBanner(): ReactElement {
365
- const {title, subtitle, cta} = useContent<HomeBannerContent>('home-banner', {fallback: fallbackBanner});
384
+ const {
385
+ title,
386
+ subtitle,
387
+ cta
388
+ } = useContent<HomeBannerContent>('home-banner', {fallback: fallbackBanner});
366
389
 
367
390
  return (
368
391
  <div>
@@ -378,7 +401,11 @@ export default function HomePage(): ReactElement {
378
401
  <Suspense fallback="Personalizing content...">
379
402
  {/* Using the <Slot /> component */}
380
403
  <Slot id="home-banner" fallback={fallbackBanner}>
381
- {({title, subtitle, cta}: HomeBannerContent) => (
404
+ {({
405
+ title,
406
+ subtitle,
407
+ cta
408
+ }: HomeBannerContent) => (
382
409
  <div>
383
410
  <strong>{title}</strong>
384
411
  <p>{subtitle}</p>
@@ -388,13 +415,14 @@ export default function HomePage(): ReactElement {
388
415
  </Slot>
389
416
 
390
417
  {/* Using the useContent hook */}
391
- <HomeBanner />
418
+ <HomeBanner/>
392
419
  </Suspense>
393
420
  )
394
421
  }
395
422
  ```
396
423
 
397
- Again, we strongly recommend always providing a value for the `fallback` property. For a full list of the available options,
424
+ Again, we strongly recommend always providing a value for the `fallback` property. For a full list of the available
425
+ options,
398
426
  please refer to the [API documentation](#component-api-reference).
399
427
 
400
428
  #### 💡 ProTip
@@ -407,11 +435,10 @@ using module augmentation as follows:
407
435
 
408
436
  ```ts
409
437
  // slots.d.ts
410
- import {NullableJsonObject} from '@croct/plug/sdk/json';
411
438
  import {HomeBanner} from './HomePage';
412
439
 
413
- declare module '@croct/plug/fetch' {
414
- interface SlotMap extends Record<string, NullableJsonObject> {
440
+ declare module '@croct/plug/slot' {
441
+ interface SlotMap {
415
442
  'home-banner': HomeBanner;
416
443
  }
417
444
  }
@@ -428,12 +455,15 @@ You can use the same components and hooks on the server-side by simply providing
428
455
  pre-render on the server - the personalization happens transparently on the client during the initial render.
429
456
  That means it's SEO friendly and can be cached with no performance overhead.
430
457
 
431
- Notice that the methods exposed by the Plug work only on the client-side. Therefore, if you are using [`useCroct`](#usecroct),
432
- the operations have to be executed inside the `useEffect` hook or client-side callbacks, such as `onClick` or `onChange`, for example.
458
+ Notice that the methods exposed by the Plug work only on the client-side. Therefore, if you are
459
+ using [`useCroct`](#usecroct),
460
+ the operations have to be executed inside the `useEffect` hook or client-side callbacks, such as `onClick` or `onChange`
461
+ , for example.
433
462
 
434
463
  ### Accessing the Plug instance
435
464
 
436
- This library is built on top of the PlugJS. You can access the Plug instance through the `useCroct` hook to track events,
465
+ This library is built on top of the PlugJS. You can access the Plug instance through the `useCroct` hook to track
466
+ events,
437
467
  login and logout users, and more.
438
468
 
439
469
  In the following example we use the `useCroct` to get the Plug instance and set an attribute to the user profile:
@@ -461,7 +491,7 @@ This reference documents all components available in the library.
461
491
 
462
492
  ### &lt;CroctProvider /&gt;
463
493
 
464
- The `<CroctProvider />` component leverages [React's Context API](https://reactjs.org/docs/context.html) to
494
+ The `<CroctProvider />` component leverages [React's Context API](https://reactjs.org/docs/context.html) to
465
495
  make a configured [Plug instance](https://github.com/croct-tech/plug-js/blob/master/docs/plug.md) available throughout
466
496
  a React component tree.
467
497
 
@@ -471,18 +501,19 @@ The component takes the followings properties:
471
501
 
472
502
  | Option | Type | Required | Default Value | Description |
473
503
  |-------------------------|--------------|----------|---------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
474
- | `appId` | string | Yes | None | The ID of the application you set up on Croct.
504
+ | `appId` | string | Yes | None | The ID of the application you set up on Croct. |
475
505
  | `debug` | boolean | No | `false` | If `true`, turns on debug mode, which logs helpful messages to the console. |
476
- | `track` | boolean | No | `true` | If `true`, enables the automatic event tracking on initialization.
477
- | `token` | string\|null | No | None | The JWT token issued by Croct. If `null`, clears any token specified on previous calls.
478
- | `userId` | string | No | None | The ID of the user logged into the application. Internally, the SDK will issue a token using the specified ID as the subject claim of the token. The `token` and `userId` options are mutually exclusive.
479
- | `tokenScope` | string | No | `global` | Defines how the SDK should synchronize the token across multiple tabs, see [token scopes](#token-scopes) for more details.
480
- | `eventMetadata` | JSON | No | None | Any additional information that may be useful to include as part of the event metadata. A common use case is to record the version of the application for future reference.
481
- | `logger` | object | No | None | A custom logger to handle log messages. By default, all logs are suppressed.
482
- | `urlSanitizer` | function | No | None | A function to sanitize URLs that allows removing sensitive information from URLs, such as tokens, that should not be sent to the platform.
483
- | `trackerEndpointUrl` | string | No | None | The URL of the tracker service, used by Croct's development team for testing purposes.
484
- | `evaluationEndpointUrl` | string | No | None | The URL of the evaluation service, used by Croct's development team for testing purposes.
485
- | `bootstrapEndpointUrl` | string | No | None | The URL of the bootstrap service, used by Croct's development team for testing purposes.
506
+ | `track` | boolean | No | `true` | If `true`, enables the automatic event tracking on initialization. |
507
+ | `clientId` | string | No | None | The ID of the client using the application. |
508
+ | `token` | string\|null | No | None | The JWT token issued by Croct. If `null`, clears any token specified on previous calls. |
509
+ | `userId` | string | No | None | The ID of the user logged into the application. Internally, the SDK will issue a token using the specified ID as the subject claim of the token. The `token` and `userId` options are mutually exclusive. |
510
+ | `tokenScope` | string | No | `global` | Defines how the SDK should synchronize the token across multiple tabs, see [token scopes](#token-scopes) for more details. |
511
+ | `eventMetadata` | JSON | No | None | Any additional information that may be useful to include as part of the event metadata. A common use case is to record the version of the application for future reference. |
512
+ | `logger` | object | No | None | A custom logger to handle log messages. By default, all logs are suppressed. |
513
+ | `urlSanitizer` | function | No | None | A function to sanitize URLs that allows removing sensitive information from URLs, such as tokens, that should not be sent to the platform. |
514
+ | `trackerEndpointUrl` | string | No | None | The URL of the tracker service, used by Croct's development team for testing purposes. |
515
+ | `evaluationEndpointUrl` | string | No | None | The URL of the evaluation service, used by Croct's development team for testing purposes. |
516
+ | `bootstrapEndpointUrl` | string | No | None | The URL of the bootstrap service, used by Croct's development team for testing purposes. |
486
517
 
487
518
  #### Code Sample
488
519
 
@@ -512,16 +543,16 @@ The `<Personalization />` component evaluates and renders a CQL query.
512
543
 
513
544
  The component takes the followings properties:
514
545
 
515
- | Option | Type | Required | Description
516
- |--------------|----------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
517
- | `expression` | string | Yes | The CQL query to evaluate.
518
- | `children` | Function | Yes | A callback to render the result.
519
- | `fallback` | Result | No | A value to render when the evaluation fails. If not specified, the hook will throw an exception in case of failures.
520
- | `initial` | Result | SSR only | A value to render while loading, required for server-side rendering. If not specified, the rendering will suspend.
521
- | `timeout` | number | No | The maximum evaluation time in milliseconds. Once reached, the evaluation will fail.
522
- | `attributes` | JSON | No | A map of attributes to inject in the evaluation context. For example, passing the attributes `{cities: ['New York', 'San Francisco']}` you can reference them in expressions like `context's cities include location's city`.
523
- | `cacheKey` | string | No | An identifier that allows keeping the cached result separate from other cached items. By default, the cache key is formed from the expression and attributes.
524
- | `expiration` | number | No | The cache expiration time in milliseconds, extended on every render. If negative, the cache never expires. By default, the cache lifespan is set to 60000 (1 minute).
546
+ | Option | Type | Required | Description |
547
+ |--------------|----------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
548
+ | `query` | string | Yes | The CQL query to evaluate. |
549
+ | `children` | Function | Yes | A callback to render the result. |
550
+ | `fallback` | Result | No | A value to render when the evaluation fails. If not specified, the hook will throw an exception in case of failures. |
551
+ | `initial` | Result | SSR only | A value to render while loading, required for server-side rendering. If not specified, the rendering will suspend. |
552
+ | `timeout` | number | No | The maximum evaluation time in milliseconds. Once reached, the evaluation will fail. |
553
+ | `attributes` | JSON | No | A map of attributes to inject in the evaluation context. For example, passing the attributes `{cities: ['New York', 'San Francisco']}` you can reference them in queries like `context's cities include location's city`. |
554
+ | `cacheKey` | string | No | An identifier that allows keeping the cached result separate from other cached items. By default, the cache key is formed from the query and attributes. |
555
+ | `expiration` | number | No | The cache expiration time in milliseconds, extended on every render. If negative, the cache never expires. By default, the cache lifespan is set to 60000 (1 minute). |
525
556
 
526
557
  #### Code Sample
527
558
 
@@ -533,7 +564,7 @@ import {Personalization} from '@croct/plug-react';
533
564
 
534
565
  function PersonaBadge(): ReactElement {
535
566
  return (
536
- <Personalization expression="user's persona or else 'unknown'">
567
+ <Personalization query="user's persona or else 'unknown'">
537
568
  {persona => (<span>{persona}</span>)}
538
569
  </Personalization>
539
570
  );
@@ -548,14 +579,15 @@ The `<Slot />` component fetches and renders a slot.
548
579
 
549
580
  The component takes the followings properties:
550
581
 
551
- | Option | Type | Required | Description
552
- |--------------|----------|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
553
- | `id` | string | Yes | The ID of the slot to fetch.
554
- | `children` | Function | Yes | A callback to render the result.
555
- | `fallback` | Result | No | A value to render when the fetch fails. If not specified, the hook will throw an exception in case of failures.
556
- | `initial` | Result | SSR only | A value to render while loading, required for server-side rendering. If not specified, the rendering will suspend.
557
- | `cacheKey` | string | No | An identifier that allows keeping the cached result separate from other cached items. By default, the cache key is formed from the expression and attributes.
558
- | `expiration` | number | No | The cache expiration time in milliseconds, extended on every render. If negative, the cache never expires. By default, the cache lifespan is set to 60000 (1 minute).
582
+ | Option | Type | Required | Description |
583
+ |-------------------|----------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
584
+ | `id` | string | Yes | The ID of the slot to fetch. |
585
+ | `children` | Function | Yes | A callback to render the result. |
586
+ | `fallback` | Result | No | A value to render when the fetch fails. If not specified, the hook will throw an exception in case of failures. |
587
+ | `preferredLocale` | string | No | The preferred locale to fetch. If not specified or not available, the hook will fetch the default locale. |
588
+ | `initial` | Result | SSR only | A value to render while loading, required for server-side rendering. If not specified, the rendering will suspend. |
589
+ | `cacheKey` | string | No | An identifier that allows keeping the cached result separate from other cached items. By default, the cache key is formed from the query and attributes. |
590
+ | `expiration` | number | No | The cache expiration time in milliseconds, extended on every render. If negative, the cache never expires. By default, the cache lifespan is set to 60000 (1 minute). |
559
591
 
560
592
  #### Code Sample
561
593
 
@@ -568,7 +600,10 @@ import {Slot} from '@croct/plug-react';
568
600
  function HeroBanner(): ReactElement {
569
601
  return (
570
602
  <Slot id="hero">
571
- {({title, subtitle}) => (
603
+ {({
604
+ title,
605
+ subtitle
606
+ }) => (
572
607
  <div>
573
608
  <h1>{title}</h1>
574
609
  <p>{subtitle}</p>
@@ -620,18 +655,18 @@ The `useEvaluation` hook evaluates a CQL query.
620
655
  The hook has the following signature:
621
656
 
622
657
  ```ts
623
- function useEvaluation<Result extends JsonValue>(expression: string, options: Options = {}): Result
658
+ function useEvaluation<Result extends JsonValue>(query: string, options: Options = {}): Result
624
659
  ```
625
660
 
626
661
  These are the currently supported options:
627
662
 
628
- | Option | Type | Description
629
- |--------------|---------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
630
- | `fallback` | Result | The value returned when the evaluation fails. If not specified, the hook will throw an exception in case of failures.
631
- | `timeout` | number | The maximum evaluation time in milliseconds. Once reached, the evaluation will fail.
632
- | `attributes` | JSON | The map of attributes to inject in the evaluation context. For example, passing the attributes `{cities: ['New York', 'San Francisco']}` you can reference them in expressions like `context's cities include location's city`.
633
- | `cacheKey` | string | An identifier that allows keeping the cached result separate from other cached items. By default, the cache key is formed from the expression and attributes.
634
- | `expiration` | number | The cache expiration time in milliseconds, extended on every render. If negative, the cache never expires. By default, the cache lifespan is set to 60000 (1 minute).
663
+ | Option | Type | Description |
664
+ |--------------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
665
+ | `fallback` | Result | The value returned when the evaluation fails. If not specified, the hook will throw an exception in case of failures. |
666
+ | `timeout` | number | The maximum evaluation time in milliseconds. Once reached, the evaluation will fail. |
667
+ | `attributes` | JSON | The map of attributes to inject in the evaluation context. For example, passing the attributes `{cities: ['New York', 'San Francisco']}` you can reference them in querys like `context's cities include location's city`. |
668
+ | `cacheKey` | string | An identifier that allows keeping the cached result separate from other cached items. By default, the cache key is formed from the query and attributes. |
669
+ | `expiration` | number | The cache expiration time in milliseconds, extended on every render. If negative, the cache never expires. By default, the cache lifespan is set to 60000 (1 minute). |
635
670
 
636
671
  #### Code Sample
637
672
 
@@ -657,16 +692,18 @@ The `useContent` hook fetches the content of a slot.
657
692
  The hook has the following signature:
658
693
 
659
694
  ```ts
660
- function useContent<Content extends NullableJsonObject>(slotId: string, options: Options = {}): Content
695
+ function useContent(slotId: string, options: Options = {}): JsonObject
661
696
  ```
662
697
 
663
698
  These are the currently supported options:
664
699
 
665
- | Option | Type | Description
666
- |--------------|---------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
667
- | `fallback` | Content | The content returned when the fetch fails. If not specified, the hook will throw an exception in case of failures.
668
- | `cacheKey` | string | An identifier that allows keeping the cached content separate from other cached items. By default, the cache key is formed from the slot ID.
669
- | `expiration` | number | The cache expiration time in milliseconds, extended on every render. If negative, the cache never expires. By default, the cache lifespan is set to 60000 (1 minute).
700
+ | Option | Type | Description |
701
+ |-------------------|---------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
702
+ | `fallback` | Content | The content returned when the fetch fails. If not specified, the hook will throw an exception in case of failures. |
703
+ | `preferredLocale` | string | The preferred locale to fetch. If not specified or not available, the hook will fetch the default locale. |
704
+ | `cacheKey` | string | An identifier that allows keeping the cached content separate from other cached items. By default, the cache key is formed from the slot ID. |
705
+ | `expiration` | number | The cache expiration time in milliseconds, extended on every render. If negative, the cache never expires. By default, the cache lifespan is set to 60000 (1 minute). |
706
+
670
707
 
671
708
  #### Code Sample
672
709
 
@@ -686,7 +723,10 @@ type HomeBannerContent = {
686
723
  };
687
724
 
688
725
  export default function HeroBanner(): ReactElement {
689
- const {title, subtitle} = useContent<HomeBannerContent>('hero');
726
+ const {
727
+ title,
728
+ subtitle
729
+ } = useContent<HomeBannerContent>('hero');
690
730
 
691
731
  return (
692
732
  <div>
@@ -697,6 +737,103 @@ export default function HeroBanner(): ReactElement {
697
737
  }
698
738
  ```
699
739
 
740
+ ## Standalone function reference
741
+
742
+ This reference documents all standalone functions available in the library.
743
+
744
+ ### evaluate
745
+
746
+ The `evaluate` function evaluates a CQL query on the server-side and returns the result.
747
+
748
+ #### Signature
749
+
750
+ The function has the following signature:
751
+
752
+ ```ts
753
+ function evaluate(query: string, options: EvaluationOptions): Promise<JsonValue>
754
+ ```
755
+
756
+ These are the currently supported options:
757
+
758
+ | Option | Type | Required | Description |
759
+ |----------------------------|--------|----------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
760
+ | `apiKey` | string | Yes | The private API key of the application. This is a private key that should never be exposed to the client-side. |
761
+ | `fallback` | JSON | No | The value returned when the evaluation fails. If not specified, the function will throw an exception in case of failures. |
762
+ | `timeout` | number | No | The maximum evaluation time in milliseconds. Once reached, the evaluation will fail. |
763
+ | `clientId` | string | No | A UUID v4 that uniquely identifies the client across multiple evaluations. You should generate this identifier on your server-side using a random, cryptographically secure generator and ensure it doesn't change throughout the user journey (e.g. store in cookies). If not specified, the evaluation will run in an anonymous context. |
764
+ | `clientIp` | string | No | The IP address of the client to determine the location. The IP is only used to determine the location and then discarded. |
765
+ | `userAgent` | string | No | The user agent of the client to determine the device. |
766
+ | `userToken` | string | No | The token that uniquely identifies the user. You can use this to provide consistent experiences across multiple channels. |
767
+ | `context` | JSON | No | The evaluation context. |
768
+ | `context.timeZone` | string | No | The time zone of the client. |
769
+ | `context.campaign` | JSON | No | The marketing campaign that brought the user to the application. |
770
+ | `context.campaign.name` | string | No | The name of the campaign. |
771
+ | `context.campaign.source` | string | No | The source of the campaign. For example, "google", "newsletter", "facebook". |
772
+ | `context.campaign.medium` | string | No | The marketing medium. For example, "cpc", "banner", "ads". |
773
+ | `context.campaign.term` | string | No | The campaign keywords. For example, "smartphone online sale". |
774
+ | `context.campaign.content` | string | No | The campaign content. For example, "top-banner", "cta", "sidebar". |
775
+ | `context.page` | JSON | No | The page the user is currently viewing. |
776
+ | `context.page.url` | string | Yes | The URL of the page. |
777
+ | `context.page.title` | string | No | The title of the page. |
778
+ | `context.page.referrer` | string | No | The URL of the page that referred the user to the current page. |
779
+ | `context.attributes` | JSON | No | The map of attributes to inject in the evaluation context. For example, passing the attributes `{cities: ['New York', 'San Francisco']}` you can reference them in querys like `context's cities include location's city`. |
780
+ | `extra` | JSON | No | Additional [options](https://developer.mozilla.org/en-US/docs/Web/API/fetch#parameters) to pass to the fetch function. |
781
+
782
+ #### Code Sample
783
+
784
+ Here's a simple example showing how to evaluate a CQL query:
785
+
786
+ ```ts
787
+ import {evaluate} from '@croct/plug/api';
788
+
789
+ const result = await evaluate("user's persona", {
790
+ apiKey: process.env.CROCT_API_KEY,
791
+ });
792
+ ```
793
+
794
+ ### fetchContent
795
+
796
+ The `fetchContent` function fetches the content for a slot on the server-side and returns the result.
797
+
798
+ #### Signature
799
+
800
+ The function has the following signature:
801
+
802
+ ```ts
803
+ function fetchContent(slotId: string, options: FetchOptions): Promise<{content: JsonValue}>
804
+ ```
805
+
806
+ These are the currently supported options:
807
+
808
+
809
+ | Option | Type | Required | Description |
810
+ |----------------------------|---------|----------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
811
+ | `apiKey` | string | Yes | The private API key of the application. This is a private key that should never be exposed to the client-side. |
812
+ | `fallback` | JSON | No | The value returned when the fetch fails. If not specified, the function will throw an exception in case of failures. |
813
+ | `static` | boolean | No | Whether to fetch the static content. If not specified, the function will fetch the dynamic content. |
814
+ | `timeout` | number | No | The maximum fetch time in milliseconds. Once reached, the fetch will fail. |
815
+ | `previewToken` | string | No | The token that enables preview mode. |
816
+ | `preferredLocale` | string | No | The preferred locale to fetch. If not specified or not available, the hook will fetch the default locale. |
817
+ | `clientId` | string | No | A UUID v4 that uniquely identifies the client across multiple evaluations. You should generate this identifier on your server-side using a random, cryptographically secure generator and ensure it doesn't change throughout the user journey (e.g. store in cookies). If not specified, the evaluation will run in an anonymous context. |
818
+ | `clientIp` | string | No | The IP address of the client to determine the location. The IP is only used to determine the location and then discarded. |
819
+ | `userAgent` | string | No | The user agent of the client to determine the device. |
820
+ | `userToken` | string | No | The token that uniquely identifies the user. You can use this to provide consistent experiences across multiple channels. |
821
+ | `context` | JSON | No | The evaluation context. |
822
+ | `context.timeZone` | string | No | The time zone of the client. |
823
+ | `context.campaign` | JSON | No | The marketing campaign that brought the user to the application. |
824
+ | `context.campaign.name` | string | No | The name of the campaign. |
825
+ | `context.campaign.source` | string | No | The source of the campaign. For example, "google", "newsletter", "facebook". |
826
+ | `context.campaign.medium` | string | No | The marketing medium. For example, "cpc", "banner", "ads". |
827
+ | `context.campaign.term` | string | No | The campaign keywords. For example, "smartphone online sale". |
828
+ | `context.campaign.content` | string | No | The campaign content. For example, "top-banner", "cta", "sidebar". |
829
+ | `context.page` | JSON | No | The page the user is currently viewing. |
830
+ | `context.page.url` | string | Yes | The URL of the page. |
831
+ | `context.page.title` | string | No | The title of the page. |
832
+ | `context.page.referrer` | string | No | The URL of the page that referred the user to the current page. |
833
+ | `context.attributes` | JSON | No | The map of attributes to inject in the evaluation context. For example, passing the attributes `{cities: ['New York', 'San Francisco']}` you can reference them in querys like `context's cities include location's city`. |
834
+ | `extra` | JSON | No | Additional [options](https://developer.mozilla.org/en-US/docs/Web/API/fetch#parameters) to pass to the fetch function. |
835
+
836
+
700
837
  ## Support
701
838
 
702
839
  If this documentation has not answered all your questions, don't worry.
@@ -714,7 +851,8 @@ please [ask a new one](https://stackoverflow.com/questions/ask?tags=croct%20plug
714
851
  If you have what looks like a bug, or you would like to make a feature request, please
715
852
  [open a new issue on GitHub](https://github.com/croct-tech/plug-react/issues/new/choose).
716
853
 
717
- Before you file an issue, a good practice is to search for issues to see whether others have the same or similar problems.
854
+ Before you file an issue, a good practice is to search for issues to see whether others have the same or similar
855
+ problems.
718
856
  If you are unable to find an open issue addressing the problem, then feel free to open a new one.
719
857
 
720
858
  ### Slack Channel