@dynamic-labs/iframe-setup 4.8.6 → 4.9.1-preview.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 (41) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +224 -1
  3. package/_virtual/_tslib.cjs +36 -0
  4. package/_virtual/_tslib.js +32 -0
  5. package/package.cjs +1 -1
  6. package/package.js +1 -1
  7. package/package.json +5 -2
  8. package/src/index.cjs +7 -0
  9. package/src/index.d.ts +2 -1
  10. package/src/index.js +2 -0
  11. package/src/lib/setupIframe/index.d.ts +1 -0
  12. package/src/lib/setupIframe/setupIframe.cjs +105 -0
  13. package/src/lib/setupIframe/setupIframe.d.ts +28 -0
  14. package/src/lib/setupIframe/setupIframe.js +101 -0
  15. package/src/lib/setupInsideIframe/index.d.ts +1 -0
  16. package/src/lib/setupInsideIframe/setupInsideIframe.cjs +18 -0
  17. package/src/lib/setupInsideIframe/setupInsideIframe.d.ts +1 -0
  18. package/src/lib/setupInsideIframe/setupInsideIframe.js +14 -0
  19. package/src/lib/setupInsideIframe/utils/createMessageHandler/createMessageHandler.cjs +30 -0
  20. package/src/lib/setupInsideIframe/utils/createMessageHandler/createMessageHandler.d.ts +2 -0
  21. package/src/lib/setupInsideIframe/utils/createMessageHandler/createMessageHandler.js +26 -0
  22. package/src/lib/setupInsideIframe/utils/createMessageHandler/index.d.ts +1 -0
  23. package/src/lib/setupInsideIframe/utils/createMessageSender/createMessageSender.cjs +8 -0
  24. package/src/lib/setupInsideIframe/utils/createMessageSender/createMessageSender.d.ts +2 -0
  25. package/src/lib/setupInsideIframe/utils/createMessageSender/createMessageSender.js +4 -0
  26. package/src/lib/setupInsideIframe/utils/createMessageSender/index.d.ts +1 -0
  27. package/src/lib/setupInsideIframe/utils/getInitialParentURL/getInitialParentURL.cjs +14 -0
  28. package/src/lib/setupInsideIframe/utils/getInitialParentURL/getInitialParentURL.d.ts +1 -0
  29. package/src/lib/setupInsideIframe/utils/getInitialParentURL/getInitialParentURL.js +10 -0
  30. package/src/lib/setupInsideIframe/utils/getInitialParentURL/index.d.ts +1 -0
  31. package/src/lib/setupInsideIframe/utils/logger.cjs +10 -0
  32. package/src/lib/setupInsideIframe/utils/logger.d.ts +2 -0
  33. package/src/lib/setupInsideIframe/utils/logger.js +6 -0
  34. package/src/lib/setupInsideIframe/utils/setupPlatformEventsService/index.d.ts +1 -0
  35. package/src/lib/setupInsideIframe/utils/setupPlatformEventsService/setupPlatformEventsService.cjs +23 -0
  36. package/src/lib/setupInsideIframe/utils/setupPlatformEventsService/setupPlatformEventsService.d.ts +1 -0
  37. package/src/lib/setupInsideIframe/utils/setupPlatformEventsService/setupPlatformEventsService.js +15 -0
  38. package/src/lib/setupInsideIframe/utils/setupPlatformService/index.d.ts +1 -0
  39. package/src/lib/setupInsideIframe/utils/setupPlatformService/setupPlatformService.cjs +36 -0
  40. package/src/lib/setupInsideIframe/utils/setupPlatformService/setupPlatformService.d.ts +1 -0
  41. package/src/lib/setupInsideIframe/utils/setupPlatformService/setupPlatformService.js +32 -0
package/CHANGELOG.md CHANGED
@@ -1,4 +1,19 @@
1
1
 
2
+ ### [4.9.1-preview.0](https://github.com/dynamic-labs/dynamic-auth/compare/v4.9.0...v4.9.1-preview.0) (2025-03-07)
3
+
4
+
5
+ ### Bug Fixes
6
+
7
+ * 7702 on sepolia ([#8242](https://github.com/dynamic-labs/dynamic-auth/issues/8242)) ([8e1c63f](https://github.com/dynamic-labs/dynamic-auth/commit/8e1c63f240024f419e12787636dd2ebaacf8da94))
8
+ * embedded widget race condition that would show both embedded and non-embedded widgets at the same time ([8a52778](https://github.com/dynamic-labs/dynamic-auth/commit/8a5277888489e03871532331760c197aa6216495))
9
+
10
+ ## [4.9.0](https://github.com/dynamic-labs/dynamic-auth/compare/v4.8.6...v4.9.0) (2025-03-07)
11
+
12
+
13
+ ### Features
14
+
15
+ * add utility to use sdk-react-core in iframe ([#8219](https://github.com/dynamic-labs/dynamic-auth/issues/8219)) ([b7b0429](https://github.com/dynamic-labs/dynamic-auth/commit/b7b04292b18085d9cc95edae80100fd8dd667ed6))
16
+
2
17
  ### [4.8.6](https://github.com/dynamic-labs/dynamic-auth/compare/v4.8.5...v4.8.6) (2025-03-07)
3
18
 
4
19
 
package/README.md CHANGED
@@ -1,3 +1,226 @@
1
1
  # @dynamic-labs/iframe-setup
2
2
 
3
- Collection of utilities to use the Dynamic SDK in an iframe
3
+ A utility package that enables the Dynamic SDK (@dynamic-labs/sdk-react-core) to work seamlessly within an iframe environment.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @dynamic-labs/iframe-setup
9
+ ```
10
+
11
+ ## Features
12
+
13
+ This package provides two essential methods:
14
+
15
+ 1. `setupIframe`: Configures an iframe element with the necessary event listeners to support the SDK
16
+ 2. `setupInsideIframe`: Prepares the sdk-react-core services to operate within an iframe
17
+
18
+ ## Implementation Guide
19
+
20
+ ### Step 1: Parent Page Setup
21
+
22
+ Configure the parent page that will contain the iframe:
23
+
24
+ ```tsx
25
+ const iframeURL = new URL('https://iframe.com');
26
+
27
+ const App = () => {
28
+ const iframeRef = useRef<HTMLIFrameElement>(null);
29
+
30
+ useEffect(() => {
31
+ const cleanUp = setupIframe(iframeRef.current!, iframeURL.origin);
32
+
33
+ return () => {
34
+ cleanUp();
35
+ };
36
+ }, []);
37
+
38
+ return (
39
+ <div>
40
+ <iframe ref={iframeRef} src={iframeURL.toString()} />
41
+ </div>
42
+ );
43
+ };
44
+ ```
45
+
46
+ ### Step 2: Iframe Application Setup
47
+
48
+ Inside your iframe application, initialize the SDK:
49
+
50
+ ```tsx
51
+ import { DynamicContextProvider } from '@dynamic-labs/sdk-react-core';
52
+ import { setupInsideIframe } from '@dynamic-labs/iframe-setup';
53
+
54
+ // Initialize as early as possible in your iframe application
55
+ setupInsideIframe();
56
+
57
+ const App = () => {
58
+ return (
59
+ <DynamicContextProvider>{/* Your application */}</DynamicContextProvider>
60
+ );
61
+ };
62
+ ```
63
+
64
+ Once both steps are completed, the Dynamic SDK will be fully operational within your iframe environment.
65
+
66
+ ---
67
+
68
+ ## Alternative Implementation
69
+
70
+ ### Manual Setup (Without Package Installation in Parent App)
71
+
72
+ If you're unable to install the package in the parent application, you can directly implement the `setupIframe` functionality by copying the code below:
73
+
74
+ ```ts
75
+ /**
76
+ * Setup an iframe to comunicate with the Dynamic SDK
77
+ * running inside the iframe
78
+ *
79
+ * This file is self contained and should not import or dependend on any
80
+ * other file or package.
81
+ *
82
+ * @see https://www.npmjs.com/package/@dynamic-labs/iframe-setup
83
+ */
84
+ /* eslint no-restricted-syntax: ["error", "ImportDeclaration"] */
85
+
86
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
87
+ export type MESSAGE_HANDLER = (...params: any[]) => Promise<any> | void;
88
+
89
+ export type IFRAME_EVENTS = {
90
+ OPEN_URL: (args: {
91
+ url: string;
92
+ target?: 'self' | 'blank';
93
+ features?: string;
94
+ }) => void;
95
+ UPDATE_PARENT_URL: (args: { url: string }) => void;
96
+ APP_FOCUS: () => void;
97
+ };
98
+
99
+ /**
100
+ * Setup an iframe to comunicate with the Dynamic SDK
101
+ * running inside the iframe
102
+ *
103
+ * @returns a function to teardown the iframe setup
104
+ */
105
+ export const setupIframe = (
106
+ iframe: HTMLIFrameElement,
107
+ origin: string,
108
+ ): VoidFunction => {
109
+ const messageHandler = createMessageHandler<IFRAME_EVENTS>(window, origin);
110
+ const messageSender = createMessageSender<IFRAME_EVENTS>(iframe);
111
+
112
+ // Add initial parent url to iframe src
113
+ const applyInitialParentUrlToIframeSrc = () => {
114
+ const iframeURL = new URL(iframe.src);
115
+
116
+ iframeURL.searchParams.set('initial-parent-url', window.location.href);
117
+
118
+ iframe.src = iframeURL.toString();
119
+ };
120
+
121
+ // Add event listener to handle deeplink
122
+ const setupOpenUrlHandler = () =>
123
+ messageHandler('OPEN_URL', ({ url, target = 'self', features }) => {
124
+ if (target === 'blank') {
125
+ window.open(url, '_blank', features);
126
+ } else {
127
+ window.location.assign(url);
128
+ }
129
+ });
130
+
131
+ // Watch for url changes and update Dynamic SDK in iframe
132
+ const setupUrlUpdateHandler = (): VoidFunction => {
133
+ const onPopState = () => {
134
+ const url = window.location.href;
135
+
136
+ messageSender('UPDATE_PARENT_URL', { url });
137
+ };
138
+
139
+ window.addEventListener('popstate', onPopState);
140
+
141
+ return () => {
142
+ window.removeEventListener('popstate', onPopState);
143
+ };
144
+ };
145
+
146
+ /**
147
+ * Watch for app focus and send event to Dynamic SDK in iframe
148
+ */
149
+ const watchForAppVisibilityChange = (): VoidFunction => {
150
+ let lastFired = false;
151
+
152
+ const onVisibilityOrFocus = () => {
153
+ if (!lastFired && document.visibilityState === 'visible') {
154
+ lastFired = true;
155
+ messageSender('APP_FOCUS');
156
+
157
+ // Reset flag after a short delay to allow next valid trigger
158
+ setTimeout(() => (lastFired = false), 100);
159
+ }
160
+ };
161
+
162
+ document.addEventListener('visibilitychange', onVisibilityOrFocus);
163
+ window.addEventListener('focus', onVisibilityOrFocus);
164
+
165
+ return () => {
166
+ document.removeEventListener('visibilitychange', onVisibilityOrFocus);
167
+ window.removeEventListener('focus', onVisibilityOrFocus);
168
+ };
169
+ };
170
+
171
+ applyInitialParentUrlToIframeSrc();
172
+
173
+ // Holds all the cleanup handlers
174
+ const cleanupHandlers: VoidFunction[] = [];
175
+
176
+ cleanupHandlers.push(setupUrlUpdateHandler());
177
+ cleanupHandlers.push(setupOpenUrlHandler());
178
+ cleanupHandlers.push(watchForAppVisibilityChange());
179
+
180
+ return () => cleanupHandlers.forEach((offHandler) => offHandler());
181
+ };
182
+
183
+ // Utils
184
+
185
+ /**
186
+ * Create a message handler for the iframe
187
+ */
188
+ const createMessageHandler =
189
+ <T extends Record<string, MESSAGE_HANDLER>>(window: Window, origin: string) =>
190
+ <EVENT_NAME extends Extract<keyof T, string>>(
191
+ eventName: EVENT_NAME,
192
+ handler: T[EVENT_NAME],
193
+ ): VoidFunction => {
194
+ const messageHandler = (event: MessageEvent) => {
195
+ if (event.origin !== origin) return;
196
+
197
+ const { eventName: incomingEventName, args } = event.data;
198
+
199
+ if (eventName === incomingEventName) {
200
+ handler(...args);
201
+ }
202
+ };
203
+
204
+ window.addEventListener('message', messageHandler);
205
+
206
+ return () => {
207
+ window.removeEventListener('message', messageHandler);
208
+ };
209
+ };
210
+
211
+ /**
212
+ * Create a function to send messages to the iframe
213
+ */
214
+ const createMessageSender =
215
+ <T extends Record<string, MESSAGE_HANDLER>>(iframe: HTMLIFrameElement) =>
216
+ <EVENT_NAME extends Extract<keyof T, string>>(
217
+ eventName: EVENT_NAME,
218
+ ...args: Parameters<T[EVENT_NAME]>
219
+ ) => {
220
+ iframe.contentWindow?.postMessage(
221
+ { args, eventName },
222
+ new URL(iframe.src).origin,
223
+ );
224
+ };
225
+
226
+ ```
@@ -0,0 +1,36 @@
1
+ 'use client'
2
+ 'use strict';
3
+
4
+ Object.defineProperty(exports, '__esModule', { value: true });
5
+
6
+ /******************************************************************************
7
+ Copyright (c) Microsoft Corporation.
8
+
9
+ Permission to use, copy, modify, and/or distribute this software for any
10
+ purpose with or without fee is hereby granted.
11
+
12
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
13
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
14
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
15
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
16
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
17
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
18
+ PERFORMANCE OF THIS SOFTWARE.
19
+ ***************************************************************************** */
20
+
21
+ function __awaiter(thisArg, _arguments, P, generator) {
22
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
23
+ return new (P || (P = Promise))(function (resolve, reject) {
24
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
25
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
26
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
27
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
28
+ });
29
+ }
30
+
31
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
32
+ var e = new Error(message);
33
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
34
+ };
35
+
36
+ exports.__awaiter = __awaiter;
@@ -0,0 +1,32 @@
1
+ 'use client'
2
+ /******************************************************************************
3
+ Copyright (c) Microsoft Corporation.
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted.
7
+
8
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
9
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
13
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14
+ PERFORMANCE OF THIS SOFTWARE.
15
+ ***************************************************************************** */
16
+
17
+ function __awaiter(thisArg, _arguments, P, generator) {
18
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
19
+ return new (P || (P = Promise))(function (resolve, reject) {
20
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
21
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
22
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
23
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
24
+ });
25
+ }
26
+
27
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
28
+ var e = new Error(message);
29
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
30
+ };
31
+
32
+ export { __awaiter };
package/package.cjs CHANGED
@@ -3,6 +3,6 @@
3
3
 
4
4
  Object.defineProperty(exports, '__esModule', { value: true });
5
5
 
6
- var version = "4.8.6";
6
+ var version = "4.9.1-preview.0";
7
7
 
8
8
  exports.version = version;
package/package.js CHANGED
@@ -1,4 +1,4 @@
1
1
  'use client'
2
- var version = "4.8.6";
2
+ var version = "4.9.1-preview.0";
3
3
 
4
4
  export { version };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dynamic-labs/iframe-setup",
3
- "version": "4.8.6",
3
+ "version": "4.9.1-preview.0",
4
4
  "description": "Collection of utilities to use the Dynamic SDK in an iframe",
5
5
  "author": "Dynamic Labs, Inc.",
6
6
  "license": "MIT",
@@ -18,7 +18,10 @@
18
18
  },
19
19
  "homepage": "https://www.dynamic.xyz/",
20
20
  "dependencies": {
21
- "@dynamic-labs/assert-package-version": "4.8.6"
21
+ "@dynamic-labs/assert-package-version": "4.9.1-preview.0",
22
+ "@dynamic-labs/logger": "4.9.1-preview.0",
23
+ "@dynamic-labs/utils": "4.9.1-preview.0",
24
+ "eventemitter3": "5.0.1"
22
25
  },
23
26
  "peerDependencies": {}
24
27
  }
package/src/index.cjs CHANGED
@@ -1,7 +1,14 @@
1
1
  'use client'
2
2
  'use strict';
3
3
 
4
+ Object.defineProperty(exports, '__esModule', { value: true });
5
+
4
6
  var assertPackageVersion = require('@dynamic-labs/assert-package-version');
5
7
  var _package = require('../package.cjs');
8
+ var setupIframe = require('./lib/setupIframe/setupIframe.cjs');
9
+ var setupInsideIframe = require('./lib/setupInsideIframe/setupInsideIframe.cjs');
6
10
 
7
11
  assertPackageVersion.assertPackageVersion('@dynamic-labs/iframe-setup', _package.version);
12
+
13
+ exports.setupIframe = setupIframe.setupIframe;
14
+ exports.setupInsideIframe = setupInsideIframe.setupInsideIframe;
package/src/index.d.ts CHANGED
@@ -1 +1,2 @@
1
- export {};
1
+ export { setupIframe } from './lib/setupIframe';
2
+ export { setupInsideIframe } from './lib/setupInsideIframe';
package/src/index.js CHANGED
@@ -1,5 +1,7 @@
1
1
  'use client'
2
2
  import { assertPackageVersion } from '@dynamic-labs/assert-package-version';
3
3
  import { version } from '../package.js';
4
+ export { setupIframe } from './lib/setupIframe/setupIframe.js';
5
+ export { setupInsideIframe } from './lib/setupInsideIframe/setupInsideIframe.js';
4
6
 
5
7
  assertPackageVersion('@dynamic-labs/iframe-setup', version);
@@ -0,0 +1 @@
1
+ export { setupIframe } from './setupIframe';
@@ -0,0 +1,105 @@
1
+ 'use client'
2
+ 'use strict';
3
+
4
+ Object.defineProperty(exports, '__esModule', { value: true });
5
+
6
+ /**
7
+ * Setup an iframe to comunicate with the Dynamic SDK
8
+ * running inside the iframe
9
+ *
10
+ * This file is self contained and should not import or dependend on any
11
+ * other file or package.
12
+ *
13
+ * @see https://www.npmjs.com/package/@dynamic-labs/iframe-setup
14
+ */
15
+ /* eslint no-restricted-syntax: ["error", "ImportDeclaration"] */
16
+ /**
17
+ * Setup an iframe to comunicate with the Dynamic SDK
18
+ * running inside the iframe
19
+ *
20
+ * @returns a function to teardown the iframe setup
21
+ */
22
+ const setupIframe = (iframe, origin) => {
23
+ const messageHandler = createMessageHandler(window, origin);
24
+ const messageSender = createMessageSender(iframe);
25
+ // Add initial parent url to iframe src
26
+ const applyInitialParentUrlToIframeSrc = () => {
27
+ const iframeURL = new URL(iframe.src);
28
+ iframeURL.searchParams.set('initial-parent-url', window.location.href);
29
+ iframe.src = iframeURL.toString();
30
+ };
31
+ // Add event listener to handle deeplink
32
+ const setupOpenUrlHandler = () => messageHandler('OPEN_URL', ({ url, target = 'self', features }) => {
33
+ if (target === 'blank') {
34
+ window.open(url, '_blank', features);
35
+ }
36
+ else {
37
+ window.location.assign(url);
38
+ }
39
+ });
40
+ // Watch for url changes and update Dynamic SDK in iframe
41
+ const setupUrlUpdateHandler = () => {
42
+ const onPopState = () => {
43
+ const url = window.location.href;
44
+ messageSender('UPDATE_PARENT_URL', { url });
45
+ };
46
+ window.addEventListener('popstate', onPopState);
47
+ return () => {
48
+ window.removeEventListener('popstate', onPopState);
49
+ };
50
+ };
51
+ /**
52
+ * Watch for app focus and send event to Dynamic SDK in iframe
53
+ */
54
+ const watchForAppVisibilityChange = () => {
55
+ let lastFired = false;
56
+ const onVisibilityOrFocus = () => {
57
+ if (!lastFired && document.visibilityState === 'visible') {
58
+ lastFired = true;
59
+ messageSender('APP_FOCUS');
60
+ // Reset flag after a short delay to allow next valid trigger
61
+ setTimeout(() => (lastFired = false), 100);
62
+ }
63
+ };
64
+ document.addEventListener('visibilitychange', onVisibilityOrFocus);
65
+ window.addEventListener('focus', onVisibilityOrFocus);
66
+ return () => {
67
+ document.removeEventListener('visibilitychange', onVisibilityOrFocus);
68
+ window.removeEventListener('focus', onVisibilityOrFocus);
69
+ };
70
+ };
71
+ applyInitialParentUrlToIframeSrc();
72
+ // Holds all the cleanup handlers
73
+ const cleanupHandlers = [];
74
+ cleanupHandlers.push(setupUrlUpdateHandler());
75
+ cleanupHandlers.push(setupOpenUrlHandler());
76
+ cleanupHandlers.push(watchForAppVisibilityChange());
77
+ return () => cleanupHandlers.forEach((offHandler) => offHandler());
78
+ };
79
+ // Utils
80
+ /**
81
+ * Create a message handler for the iframe
82
+ */
83
+ const createMessageHandler = (window, origin) => (eventName, handler) => {
84
+ const messageHandler = (event) => {
85
+ if (event.origin !== origin)
86
+ return;
87
+ const { eventName: incomingEventName, args } = event.data;
88
+ if (eventName === incomingEventName) {
89
+ handler(...args);
90
+ }
91
+ };
92
+ window.addEventListener('message', messageHandler);
93
+ return () => {
94
+ window.removeEventListener('message', messageHandler);
95
+ };
96
+ };
97
+ /**
98
+ * Create a function to send messages to the iframe
99
+ */
100
+ const createMessageSender = (iframe) => (eventName, ...args) => {
101
+ var _a;
102
+ (_a = iframe.contentWindow) === null || _a === void 0 ? void 0 : _a.postMessage({ args, eventName }, new URL(iframe.src).origin);
103
+ };
104
+
105
+ exports.setupIframe = setupIframe;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Setup an iframe to comunicate with the Dynamic SDK
3
+ * running inside the iframe
4
+ *
5
+ * This file is self contained and should not import or dependend on any
6
+ * other file or package.
7
+ *
8
+ * @see https://www.npmjs.com/package/@dynamic-labs/iframe-setup
9
+ */
10
+ export type MESSAGE_HANDLER = (...params: any[]) => Promise<any> | void;
11
+ export type IFRAME_EVENTS = {
12
+ OPEN_URL: (args: {
13
+ url: string;
14
+ target?: 'self' | 'blank';
15
+ features?: string;
16
+ }) => void;
17
+ UPDATE_PARENT_URL: (args: {
18
+ url: string;
19
+ }) => void;
20
+ APP_FOCUS: () => void;
21
+ };
22
+ /**
23
+ * Setup an iframe to comunicate with the Dynamic SDK
24
+ * running inside the iframe
25
+ *
26
+ * @returns a function to teardown the iframe setup
27
+ */
28
+ export declare const setupIframe: (iframe: HTMLIFrameElement, origin: string) => VoidFunction;
@@ -0,0 +1,101 @@
1
+ 'use client'
2
+ /**
3
+ * Setup an iframe to comunicate with the Dynamic SDK
4
+ * running inside the iframe
5
+ *
6
+ * This file is self contained and should not import or dependend on any
7
+ * other file or package.
8
+ *
9
+ * @see https://www.npmjs.com/package/@dynamic-labs/iframe-setup
10
+ */
11
+ /* eslint no-restricted-syntax: ["error", "ImportDeclaration"] */
12
+ /**
13
+ * Setup an iframe to comunicate with the Dynamic SDK
14
+ * running inside the iframe
15
+ *
16
+ * @returns a function to teardown the iframe setup
17
+ */
18
+ const setupIframe = (iframe, origin) => {
19
+ const messageHandler = createMessageHandler(window, origin);
20
+ const messageSender = createMessageSender(iframe);
21
+ // Add initial parent url to iframe src
22
+ const applyInitialParentUrlToIframeSrc = () => {
23
+ const iframeURL = new URL(iframe.src);
24
+ iframeURL.searchParams.set('initial-parent-url', window.location.href);
25
+ iframe.src = iframeURL.toString();
26
+ };
27
+ // Add event listener to handle deeplink
28
+ const setupOpenUrlHandler = () => messageHandler('OPEN_URL', ({ url, target = 'self', features }) => {
29
+ if (target === 'blank') {
30
+ window.open(url, '_blank', features);
31
+ }
32
+ else {
33
+ window.location.assign(url);
34
+ }
35
+ });
36
+ // Watch for url changes and update Dynamic SDK in iframe
37
+ const setupUrlUpdateHandler = () => {
38
+ const onPopState = () => {
39
+ const url = window.location.href;
40
+ messageSender('UPDATE_PARENT_URL', { url });
41
+ };
42
+ window.addEventListener('popstate', onPopState);
43
+ return () => {
44
+ window.removeEventListener('popstate', onPopState);
45
+ };
46
+ };
47
+ /**
48
+ * Watch for app focus and send event to Dynamic SDK in iframe
49
+ */
50
+ const watchForAppVisibilityChange = () => {
51
+ let lastFired = false;
52
+ const onVisibilityOrFocus = () => {
53
+ if (!lastFired && document.visibilityState === 'visible') {
54
+ lastFired = true;
55
+ messageSender('APP_FOCUS');
56
+ // Reset flag after a short delay to allow next valid trigger
57
+ setTimeout(() => (lastFired = false), 100);
58
+ }
59
+ };
60
+ document.addEventListener('visibilitychange', onVisibilityOrFocus);
61
+ window.addEventListener('focus', onVisibilityOrFocus);
62
+ return () => {
63
+ document.removeEventListener('visibilitychange', onVisibilityOrFocus);
64
+ window.removeEventListener('focus', onVisibilityOrFocus);
65
+ };
66
+ };
67
+ applyInitialParentUrlToIframeSrc();
68
+ // Holds all the cleanup handlers
69
+ const cleanupHandlers = [];
70
+ cleanupHandlers.push(setupUrlUpdateHandler());
71
+ cleanupHandlers.push(setupOpenUrlHandler());
72
+ cleanupHandlers.push(watchForAppVisibilityChange());
73
+ return () => cleanupHandlers.forEach((offHandler) => offHandler());
74
+ };
75
+ // Utils
76
+ /**
77
+ * Create a message handler for the iframe
78
+ */
79
+ const createMessageHandler = (window, origin) => (eventName, handler) => {
80
+ const messageHandler = (event) => {
81
+ if (event.origin !== origin)
82
+ return;
83
+ const { eventName: incomingEventName, args } = event.data;
84
+ if (eventName === incomingEventName) {
85
+ handler(...args);
86
+ }
87
+ };
88
+ window.addEventListener('message', messageHandler);
89
+ return () => {
90
+ window.removeEventListener('message', messageHandler);
91
+ };
92
+ };
93
+ /**
94
+ * Create a function to send messages to the iframe
95
+ */
96
+ const createMessageSender = (iframe) => (eventName, ...args) => {
97
+ var _a;
98
+ (_a = iframe.contentWindow) === null || _a === void 0 ? void 0 : _a.postMessage({ args, eventName }, new URL(iframe.src).origin);
99
+ };
100
+
101
+ export { setupIframe };
@@ -0,0 +1 @@
1
+ export { setupInsideIframe } from './setupInsideIframe';
@@ -0,0 +1,18 @@
1
+ 'use client'
2
+ 'use strict';
3
+
4
+ Object.defineProperty(exports, '__esModule', { value: true });
5
+
6
+ var setupPlatformService = require('./utils/setupPlatformService/setupPlatformService.cjs');
7
+ var getInitialParentURL = require('./utils/getInitialParentURL/getInitialParentURL.cjs');
8
+ var setupPlatformEventsService = require('./utils/setupPlatformEventsService/setupPlatformEventsService.cjs');
9
+
10
+ const setupInsideIframe = () => {
11
+ // Get the initial parent URL
12
+ const initialParentURL = getInitialParentURL.getInitialParentURL();
13
+ // Setup services
14
+ setupPlatformService.setupPlatformService(initialParentURL);
15
+ setupPlatformEventsService.setupPlatformEventsService(initialParentURL);
16
+ };
17
+
18
+ exports.setupInsideIframe = setupInsideIframe;
@@ -0,0 +1 @@
1
+ export declare const setupInsideIframe: () => void;
@@ -0,0 +1,14 @@
1
+ 'use client'
2
+ import { setupPlatformService } from './utils/setupPlatformService/setupPlatformService.js';
3
+ import { getInitialParentURL } from './utils/getInitialParentURL/getInitialParentURL.js';
4
+ import { setupPlatformEventsService } from './utils/setupPlatformEventsService/setupPlatformEventsService.js';
5
+
6
+ const setupInsideIframe = () => {
7
+ // Get the initial parent URL
8
+ const initialParentURL = getInitialParentURL();
9
+ // Setup services
10
+ setupPlatformService(initialParentURL);
11
+ setupPlatformEventsService(initialParentURL);
12
+ };
13
+
14
+ export { setupInsideIframe };
@@ -0,0 +1,30 @@
1
+ 'use client'
2
+ 'use strict';
3
+
4
+ Object.defineProperty(exports, '__esModule', { value: true });
5
+
6
+ var logger = require('../logger.cjs');
7
+
8
+ const createMessageHandler = (parentOrigin) => (eventName, handler) => {
9
+ window.addEventListener('message', (event) => {
10
+ if (event.origin !== parentOrigin) {
11
+ return;
12
+ }
13
+ try {
14
+ if (!Object.prototype.hasOwnProperty.call(event.data, 'eventName') ||
15
+ !Object.prototype.hasOwnProperty.call(event.data, 'args') ||
16
+ !Array.isArray(event.data.args)) {
17
+ return;
18
+ }
19
+ const { eventName: incomingEventName, args } = event.data;
20
+ if (incomingEventName === eventName) {
21
+ handler(...args);
22
+ }
23
+ }
24
+ catch (error) {
25
+ logger.logger.error('Failed to parse message', error);
26
+ }
27
+ });
28
+ };
29
+
30
+ exports.createMessageHandler = createMessageHandler;
@@ -0,0 +1,2 @@
1
+ import { MESSAGE_HANDLER } from '../../../setupIframe/setupIframe';
2
+ export declare const createMessageHandler: <T extends Record<string, MESSAGE_HANDLER>>(parentOrigin: string) => <K extends Extract<keyof T, string>>(eventName: K, handler: T[K]) => void;
@@ -0,0 +1,26 @@
1
+ 'use client'
2
+ import { logger } from '../logger.js';
3
+
4
+ const createMessageHandler = (parentOrigin) => (eventName, handler) => {
5
+ window.addEventListener('message', (event) => {
6
+ if (event.origin !== parentOrigin) {
7
+ return;
8
+ }
9
+ try {
10
+ if (!Object.prototype.hasOwnProperty.call(event.data, 'eventName') ||
11
+ !Object.prototype.hasOwnProperty.call(event.data, 'args') ||
12
+ !Array.isArray(event.data.args)) {
13
+ return;
14
+ }
15
+ const { eventName: incomingEventName, args } = event.data;
16
+ if (incomingEventName === eventName) {
17
+ handler(...args);
18
+ }
19
+ }
20
+ catch (error) {
21
+ logger.error('Failed to parse message', error);
22
+ }
23
+ });
24
+ };
25
+
26
+ export { createMessageHandler };
@@ -0,0 +1 @@
1
+ export { createMessageHandler } from './createMessageHandler';
@@ -0,0 +1,8 @@
1
+ 'use client'
2
+ 'use strict';
3
+
4
+ Object.defineProperty(exports, '__esModule', { value: true });
5
+
6
+ const createMessageSender = (parentOrigin) => (eventName, ...args) => window.parent.postMessage({ args, eventName }, parentOrigin);
7
+
8
+ exports.createMessageSender = createMessageSender;
@@ -0,0 +1,2 @@
1
+ import { MESSAGE_HANDLER } from '../../../setupIframe/setupIframe';
2
+ export declare const createMessageSender: <T extends Record<string, MESSAGE_HANDLER>>(parentOrigin: string) => <EVENT_NAME extends Extract<keyof T, string>>(eventName: EVENT_NAME, ...args: Parameters<T[EVENT_NAME]>) => void;
@@ -0,0 +1,4 @@
1
+ 'use client'
2
+ const createMessageSender = (parentOrigin) => (eventName, ...args) => window.parent.postMessage({ args, eventName }, parentOrigin);
3
+
4
+ export { createMessageSender };
@@ -0,0 +1 @@
1
+ export { createMessageSender } from './createMessageSender';
@@ -0,0 +1,14 @@
1
+ 'use client'
2
+ 'use strict';
3
+
4
+ Object.defineProperty(exports, '__esModule', { value: true });
5
+
6
+ const getInitialParentURL = () => {
7
+ const initialParentURL = new URLSearchParams(window.location.search).get('initial-parent-url');
8
+ if (!initialParentURL) {
9
+ throw new Error('Parent URL is required');
10
+ }
11
+ return new URL(decodeURIComponent(initialParentURL));
12
+ };
13
+
14
+ exports.getInitialParentURL = getInitialParentURL;
@@ -0,0 +1 @@
1
+ export declare const getInitialParentURL: () => URL;
@@ -0,0 +1,10 @@
1
+ 'use client'
2
+ const getInitialParentURL = () => {
3
+ const initialParentURL = new URLSearchParams(window.location.search).get('initial-parent-url');
4
+ if (!initialParentURL) {
5
+ throw new Error('Parent URL is required');
6
+ }
7
+ return new URL(decodeURIComponent(initialParentURL));
8
+ };
9
+
10
+ export { getInitialParentURL };
@@ -0,0 +1 @@
1
+ export { getInitialParentURL } from './getInitialParentURL';
@@ -0,0 +1,10 @@
1
+ 'use client'
2
+ 'use strict';
3
+
4
+ Object.defineProperty(exports, '__esModule', { value: true });
5
+
6
+ var logger$1 = require('@dynamic-labs/logger');
7
+
8
+ const logger = new logger$1.Logger('@dynamic-labs/iframe-setup');
9
+
10
+ exports.logger = logger;
@@ -0,0 +1,2 @@
1
+ import { Logger } from '@dynamic-labs/logger';
2
+ export declare const logger: Logger;
@@ -0,0 +1,6 @@
1
+ 'use client'
2
+ import { Logger } from '@dynamic-labs/logger';
3
+
4
+ const logger = new Logger('@dynamic-labs/iframe-setup');
5
+
6
+ export { logger };
@@ -0,0 +1 @@
1
+ export { setupPlatformEventsService } from './setupPlatformEventsService';
@@ -0,0 +1,23 @@
1
+ 'use client'
2
+ 'use strict';
3
+
4
+ Object.defineProperty(exports, '__esModule', { value: true });
5
+
6
+ var EventEmitter = require('eventemitter3');
7
+ var utils = require('@dynamic-labs/utils');
8
+ var createMessageHandler = require('../createMessageHandler/createMessageHandler.cjs');
9
+
10
+ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
11
+
12
+ var EventEmitter__default = /*#__PURE__*/_interopDefaultLegacy(EventEmitter);
13
+
14
+ const setupPlatformEventsService = (initialParentURL) => {
15
+ const emitter = new EventEmitter__default["default"]();
16
+ const messageHandler = createMessageHandler.createMessageHandler(initialParentURL.origin);
17
+ utils.PlatformEventsService.implementation = emitter;
18
+ messageHandler('APP_FOCUS', () => {
19
+ emitter.emit('appFocused');
20
+ });
21
+ };
22
+
23
+ exports.setupPlatformEventsService = setupPlatformEventsService;
@@ -0,0 +1 @@
1
+ export declare const setupPlatformEventsService: (initialParentURL: URL) => void;
@@ -0,0 +1,15 @@
1
+ 'use client'
2
+ import EventEmitter from 'eventemitter3';
3
+ import { PlatformEventsService } from '@dynamic-labs/utils';
4
+ import { createMessageHandler } from '../createMessageHandler/createMessageHandler.js';
5
+
6
+ const setupPlatformEventsService = (initialParentURL) => {
7
+ const emitter = new EventEmitter();
8
+ const messageHandler = createMessageHandler(initialParentURL.origin);
9
+ PlatformEventsService.implementation = emitter;
10
+ messageHandler('APP_FOCUS', () => {
11
+ emitter.emit('appFocused');
12
+ });
13
+ };
14
+
15
+ export { setupPlatformEventsService };
@@ -0,0 +1 @@
1
+ export { setupPlatformService } from './setupPlatformService';
@@ -0,0 +1,36 @@
1
+ 'use client'
2
+ 'use strict';
3
+
4
+ Object.defineProperty(exports, '__esModule', { value: true });
5
+
6
+ var _tslib = require('../../../../../_virtual/_tslib.cjs');
7
+ var utils = require('@dynamic-labs/utils');
8
+ var createMessageSender = require('../createMessageSender/createMessageSender.cjs');
9
+ var createMessageHandler = require('../createMessageHandler/createMessageHandler.cjs');
10
+
11
+ const setupPlatformService = (initialParentURL) => {
12
+ let parentURL = new URL(initialParentURL);
13
+ const messageHandler = createMessageHandler.createMessageHandler(initialParentURL.origin);
14
+ const messageSender = createMessageSender.createMessageSender(initialParentURL.origin);
15
+ utils.PlatformService.implementation = {
16
+ getDisplayOrigin: () => parentURL.origin,
17
+ getHost: () => parentURL.host,
18
+ getHostname: () => parentURL.hostname,
19
+ getOrigin: () => parentURL.origin,
20
+ getTLD: () => parentURL.hostname,
21
+ getUrl: () => parentURL,
22
+ isNativeMobile: false,
23
+ openURL: (url_1, ...args_1) => _tslib.__awaiter(void 0, [url_1, ...args_1], void 0, function* (url, target = 'self', features = '') {
24
+ return messageSender('OPEN_URL', {
25
+ features,
26
+ target,
27
+ url,
28
+ });
29
+ }),
30
+ };
31
+ messageHandler('UPDATE_PARENT_URL', ({ url }) => {
32
+ parentURL = new URL(url);
33
+ });
34
+ };
35
+
36
+ exports.setupPlatformService = setupPlatformService;
@@ -0,0 +1 @@
1
+ export declare const setupPlatformService: (initialParentURL: URL) => void;
@@ -0,0 +1,32 @@
1
+ 'use client'
2
+ import { __awaiter } from '../../../../../_virtual/_tslib.js';
3
+ import { PlatformService } from '@dynamic-labs/utils';
4
+ import { createMessageSender } from '../createMessageSender/createMessageSender.js';
5
+ import { createMessageHandler } from '../createMessageHandler/createMessageHandler.js';
6
+
7
+ const setupPlatformService = (initialParentURL) => {
8
+ let parentURL = new URL(initialParentURL);
9
+ const messageHandler = createMessageHandler(initialParentURL.origin);
10
+ const messageSender = createMessageSender(initialParentURL.origin);
11
+ PlatformService.implementation = {
12
+ getDisplayOrigin: () => parentURL.origin,
13
+ getHost: () => parentURL.host,
14
+ getHostname: () => parentURL.hostname,
15
+ getOrigin: () => parentURL.origin,
16
+ getTLD: () => parentURL.hostname,
17
+ getUrl: () => parentURL,
18
+ isNativeMobile: false,
19
+ openURL: (url_1, ...args_1) => __awaiter(void 0, [url_1, ...args_1], void 0, function* (url, target = 'self', features = '') {
20
+ return messageSender('OPEN_URL', {
21
+ features,
22
+ target,
23
+ url,
24
+ });
25
+ }),
26
+ };
27
+ messageHandler('UPDATE_PARENT_URL', ({ url }) => {
28
+ parentURL = new URL(url);
29
+ });
30
+ };
31
+
32
+ export { setupPlatformService };