@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
@@ -0,0 +1,65 @@
1
+ import croct, {Configuration} from '@croct/plug';
2
+ import {croct as croctPolyfill, isSsr} from './ssr-polyfills';
3
+ import spyOn = jest.spyOn;
4
+
5
+ describe('Croct polyfill (CSR)', () => {
6
+ beforeAll(() => {
7
+ jest.clearAllMocks();
8
+ });
9
+
10
+ const config: Configuration = {appId: '00000000-0000-0000-0000-000000000000'};
11
+
12
+ it('should delay unplugging to avoid reconnections', async () => {
13
+ jest.useFakeTimers();
14
+
15
+ const unplug = spyOn(croct, 'unplug');
16
+
17
+ const plug = spyOn(croct, 'plug');
18
+
19
+ croctPolyfill.plug(config);
20
+
21
+ expect(plug).toHaveBeenCalledTimes(1);
22
+
23
+ // First attempt: cancelling
24
+
25
+ const firstAttempt = croctPolyfill.unplug();
26
+
27
+ expect(unplug).not.toHaveBeenCalled();
28
+
29
+ croctPolyfill.plug(config);
30
+
31
+ jest.runOnlyPendingTimers();
32
+
33
+ await expect(firstAttempt).rejects.toThrow('Unplug cancelled.');
34
+
35
+ expect(unplug).not.toHaveBeenCalled();
36
+
37
+ // Second attempt: failing
38
+
39
+ unplug.mockRejectedValueOnce(new Error('Unplug failed.'));
40
+
41
+ const secondAttempt = croct.unplug();
42
+
43
+ jest.runOnlyPendingTimers();
44
+
45
+ await expect(secondAttempt).rejects.toThrow('Unplug failed.');
46
+
47
+ // Third attempt: succeeding
48
+
49
+ unplug.mockResolvedValueOnce();
50
+
51
+ const thirdAttempt = croct.unplug();
52
+
53
+ jest.runOnlyPendingTimers();
54
+
55
+ await expect(thirdAttempt).resolves.toBeUndefined();
56
+
57
+ expect(unplug).toHaveBeenCalledTimes(2);
58
+ });
59
+ });
60
+
61
+ describe('isSsr', () => {
62
+ it('should always return false', () => {
63
+ expect(isSsr()).toBe(false);
64
+ });
65
+ });
@@ -0,0 +1,68 @@
1
+ import csrPlug, {Plug} from '@croct/plug';
2
+
3
+ export function isSsr(): boolean {
4
+ return typeof window === 'undefined'
5
+ || typeof window.document === 'undefined'
6
+ || typeof window.document.createElement === 'undefined';
7
+ }
8
+
9
+ export const croct: Plug = !isSsr()
10
+ ? (function factory(): Plug {
11
+ let timeoutId: ReturnType<typeof setTimeout>|null = null;
12
+ let resolveCallback: () => void;
13
+ let rejectCallback: (reason: any) => void;
14
+
15
+ return new Proxy(csrPlug, {
16
+ get: function getProperty(target, property: keyof Plug): any {
17
+ switch (property) {
18
+ case 'plug':
19
+ if (timeoutId !== null) {
20
+ clearTimeout(timeoutId);
21
+ timeoutId = null;
22
+ rejectCallback?.(new Error('Unplug cancelled.'));
23
+ }
24
+
25
+ break;
26
+
27
+ case 'unplug':
28
+ return () => {
29
+ // Delay unplugging to avoid reconnections between remounts (e.g. strict mode).
30
+ // It can be problematic when aiming to replug the SDK with a different configuration.
31
+ // However, since it is an unusual use case and there is a log message to warn about
32
+ // the plugin being already plugged, the trade-off is worth it.
33
+ timeoutId = setTimeout(() => target.unplug().then(resolveCallback, rejectCallback), 100);
34
+
35
+ return new Promise<void>((resolve, reject) => {
36
+ resolveCallback = resolve;
37
+ rejectCallback = reject;
38
+ });
39
+ };
40
+ }
41
+
42
+ return target[property];
43
+ },
44
+ });
45
+ }())
46
+ : new Proxy(csrPlug, {
47
+ get: function getProperty(_, property: keyof Plug): any {
48
+ switch (property) {
49
+ case 'initialized':
50
+ return false;
51
+
52
+ case 'plug':
53
+ return () => {
54
+ // no-op
55
+ };
56
+
57
+ case 'unplug':
58
+ return () => Promise.resolve();
59
+
60
+ default:
61
+ throw new Error(
62
+ `Property croct.${String(property)} is not supported on server-side (SSR). `
63
+ + 'Consider refactoring the logic as a side-effect (useEffect) or a client-side callback '
64
+ + '(onClick, onChange, etc).',
65
+ );
66
+ }
67
+ },
68
+ });
@@ -1,3 +1,3 @@
1
- import { Plug } from '@croct/plug';
2
- export declare function isSsr(): boolean;
3
- export declare const croct: Plug;
1
+ import { Plug } from '@croct/plug';
2
+ export declare function isSsr(): boolean;
3
+ export declare const croct: Plug;
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.croct = exports.isSsr = void 0;
7
+ const plug_1 = __importDefault(require("@croct/plug"));
8
+ function isSsr() {
9
+ return typeof window === 'undefined'
10
+ || typeof window.document === 'undefined'
11
+ || typeof window.document.createElement === 'undefined';
12
+ }
13
+ exports.isSsr = isSsr;
14
+ exports.croct = !isSsr()
15
+ ? (function factory() {
16
+ let timeoutId = null;
17
+ let resolveCallback;
18
+ let rejectCallback;
19
+ return new Proxy(plug_1.default, {
20
+ get: function getProperty(target, property) {
21
+ switch (property) {
22
+ case 'plug':
23
+ if (timeoutId !== null) {
24
+ clearTimeout(timeoutId);
25
+ timeoutId = null;
26
+ rejectCallback === null || rejectCallback === void 0 ? void 0 : rejectCallback(new Error('Unplug cancelled.'));
27
+ }
28
+ break;
29
+ case 'unplug':
30
+ return () => {
31
+ // Delay unplugging to avoid reconnections between remounts (e.g. strict mode).
32
+ // It can be problematic when aiming to replug the SDK with a different configuration.
33
+ // However, since it is an unusual use case and there is a log message to warn about
34
+ // the plugin being already plugged, the trade-off is worth it.
35
+ timeoutId = setTimeout(() => target.unplug().then(resolveCallback, rejectCallback), 100);
36
+ return new Promise((resolve, reject) => {
37
+ resolveCallback = resolve;
38
+ rejectCallback = reject;
39
+ });
40
+ };
41
+ }
42
+ return target[property];
43
+ },
44
+ });
45
+ }())
46
+ : new Proxy(plug_1.default, {
47
+ get: function getProperty(_, property) {
48
+ switch (property) {
49
+ case 'initialized':
50
+ return false;
51
+ case 'plug':
52
+ return () => {
53
+ // no-op
54
+ };
55
+ case 'unplug':
56
+ return () => Promise.resolve();
57
+ default:
58
+ throw new Error(`Property croct.${String(property)} is not supported on server-side (SSR). `
59
+ + 'Consider refactoring the logic as a side-effect (useEffect) or a client-side callback '
60
+ + '(onClick, onChange, etc).');
61
+ }
62
+ },
63
+ });
64
+ //# sourceMappingURL=ssr-polyfills.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssr-polyfills.js","sourceRoot":"","sources":["src/ssr-polyfills.ts"],"names":[],"mappings":";;;;;;AAAA,uDAA0C;AAE1C,SAAgB,KAAK;IACjB,OAAO,OAAO,MAAM,KAAK,WAAW;WAC7B,OAAO,MAAM,CAAC,QAAQ,KAAK,WAAW;WACtC,OAAO,MAAM,CAAC,QAAQ,CAAC,aAAa,KAAK,WAAW,CAAC;AAChE,CAAC;AAJD,sBAIC;AAEY,QAAA,KAAK,GAAS,CAAC,KAAK,EAAE;IAC/B,CAAC,CAAC,CAAC,SAAS,OAAO;QACf,IAAI,SAAS,GAAuC,IAAI,CAAC;QACzD,IAAI,eAA2B,CAAC;QAChC,IAAI,cAAqC,CAAC;QAE1C,OAAO,IAAI,KAAK,CAAC,cAAO,EAAE;YACtB,GAAG,EAAE,SAAS,WAAW,CAAC,MAAM,EAAE,QAAoB;gBAClD,QAAQ,QAAQ,EAAE;oBACd,KAAK,MAAM;wBACP,IAAI,SAAS,KAAK,IAAI,EAAE;4BACpB,YAAY,CAAC,SAAS,CAAC,CAAC;4BACxB,SAAS,GAAG,IAAI,CAAC;4BACjB,cAAc,aAAd,cAAc,uBAAd,cAAc,CAAG,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC,CAAC;yBACpD;wBAED,MAAM;oBAEV,KAAK,QAAQ;wBACT,OAAO,GAAG,EAAE;4BACR,+EAA+E;4BAC/E,sFAAsF;4BACtF,oFAAoF;4BACpF,+DAA+D;4BAC/D,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,eAAe,EAAE,cAAc,CAAC,EAAE,GAAG,CAAC,CAAC;4BAEzF,OAAO,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gCACzC,eAAe,GAAG,OAAO,CAAC;gCAC1B,cAAc,GAAG,MAAM,CAAC;4BAC5B,CAAC,CAAC,CAAC;wBACP,CAAC,CAAC;iBACT;gBAED,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC5B,CAAC;SACJ,CAAC,CAAC;IACP,CAAC,EAAE,CAAC;IACJ,CAAC,CAAC,IAAI,KAAK,CAAC,cAAO,EAAE;QACjB,GAAG,EAAE,SAAS,WAAW,CAAC,CAAC,EAAE,QAAoB;YAC7C,QAAQ,QAAQ,EAAE;gBACd,KAAK,aAAa;oBACd,OAAO,KAAK,CAAC;gBAEjB,KAAK,MAAM;oBACP,OAAO,GAAG,EAAE;wBACR,QAAQ;oBACZ,CAAC,CAAC;gBAEN,KAAK,QAAQ;oBACT,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;gBAEnC;oBACI,MAAM,IAAI,KAAK,CACX,kBAAkB,MAAM,CAAC,QAAQ,CAAC,0CAA0C;0BAC1E,yFAAyF;0BACzF,2BAA2B,CAChC,CAAC;aACT;QACL,CAAC;KACJ,CAAC,CAAC"}
@@ -1 +0,0 @@
1
- import '@testing-library/jest-dom/extend-expect';
@@ -1 +0,0 @@
1
- export {};
@@ -1,7 +0,0 @@
1
- import { Story, Meta } from '@storybook/react/types-6-0';
2
- import { PersonalizationProps } from './index';
3
- declare const _default: Meta<import("@storybook/react/types-6-0").Args>;
4
- export default _default;
5
- export declare const WithSuspense: Story<Omit<PersonalizationProps<string>, 'expression'>>;
6
- export declare const WithInitialState: Story<Omit<PersonalizationProps<string, null>, 'expression'>>;
7
- export declare const WithFallbackState: Story<Omit<PersonalizationProps<string>, 'expression'>>;
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1,17 +0,0 @@
1
- import { Story, Meta } from '@storybook/react/types-6-0';
2
- import { SlotProps } from './index';
3
- declare const _default: Meta<import("@storybook/react/types-6-0").Args>;
4
- export default _default;
5
- declare type HomeBannerProps = {
6
- loading?: true;
7
- title: string;
8
- subtitle: string;
9
- cta: {
10
- label: string;
11
- link: string;
12
- };
13
- };
14
- declare type HomeBannerSlotProps = SlotProps<HomeBannerProps>;
15
- export declare const WithSuspense: Story<HomeBannerSlotProps>;
16
- export declare const WithInitialState: Story<HomeBannerSlotProps>;
17
- export declare const WithFallbackState: Story<HomeBannerSlotProps>;
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1,19 +0,0 @@
1
- import { Story, Meta } from '@storybook/react/types-6-0';
2
- import { UseContentOptions } from './useContent';
3
- declare const _default: Meta<import("@storybook/react/types-6-0").Args>;
4
- export default _default;
5
- declare type HomeBannerProps = {
6
- loading?: true;
7
- title: string;
8
- subtitle: string;
9
- cta: {
10
- label: string;
11
- link: string;
12
- };
13
- };
14
- declare type HeroOptions = UseContentOptions<HomeBannerProps, HomeBannerProps> & {
15
- slotId?: 'home-banner';
16
- };
17
- export declare const WithSuspense: Story<HeroOptions>;
18
- export declare const WithInitialState: Story<HeroOptions>;
19
- export declare const WithFallbackState: Story<HeroOptions>;
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1,8 +0,0 @@
1
- import { Story, Meta } from '@storybook/react/types-6-0';
2
- import { UseEvaluationOptions } from './useEvaluation';
3
- declare const _default: Meta<import("@storybook/react/types-6-0").Args>;
4
- export default _default;
5
- declare type PersonalizedNewsWidgetProps = UseEvaluationOptions<string | null, string>;
6
- export declare const WithSuspense: Story<PersonalizedNewsWidgetProps>;
7
- export declare const WithInitialState: Story<PersonalizedNewsWidgetProps>;
8
- export declare const WithFallbackState: Story<PersonalizedNewsWidgetProps>;
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};