@myop/sdk 0.3.34 → 0.4.0-beta.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.
- package/dist/bundled-declarations.d.ts +408 -167
- package/dist/cjs/{_IframeSDK.c7926c56.js → _IframeSDK.096d8320.js} +1328 -917
- package/dist/cjs/_IframeSDK.096d8320.js.map +7 -0
- package/dist/cjs/_IframeSDK.8e791f92.min.js +1 -0
- package/dist/cjs/_MyopHelpers.91004b19.min.js +1 -0
- package/dist/cjs/{_MyopHelpers.08d1cf5d.js → _MyopHelpers.efed13e4.js} +362 -2
- package/dist/cjs/_MyopHelpers.efed13e4.js.map +7 -0
- package/dist/cjs/_WebComponentSDK.4a87f826.min.js +1 -0
- package/dist/cjs/{_WebComponentSDK.501a71f9.js → _WebComponentSDK.e9e877db.js} +886 -478
- package/dist/cjs/_WebComponentSDK.e9e877db.js.map +7 -0
- package/dist/cjs/{_hostSDK.cdbc1f60.js → _hostSDK.0c271647.js} +1349 -941
- package/dist/cjs/_hostSDK.0c271647.js.map +7 -0
- package/dist/cjs/_hostSDK.7d759290.min.js +1 -0
- package/dist/cjs/myop_sdk.js +35 -24
- package/dist/cjs/myop_sdk.js.map +2 -2
- package/dist/cjs/myop_sdk.min.js +1 -1
- package/dist/cjs-bundled/myop_sdk.bundled.js +1822 -1380
- package/dist/cjs-bundled/myop_sdk.bundled.js.map +4 -4
- package/dist/cjs-bundled/myop_sdk.bundled.min.js +1 -1
- package/dist/module/Iframe/index.js +1095 -672
- package/dist/module/Iframe/index.js.map +4 -4
- package/dist/module/SDK.d.ts +5 -1
- package/dist/module/SDK.js +1980 -1528
- package/dist/module/SDK.js.map +4 -4
- package/dist/module/embeddedSDK.js +1 -1
- package/dist/module/helpers/CloudRepository.d.ts +96 -0
- package/dist/module/helpers/cloudRepositoryHelpers.d.ts +99 -0
- package/dist/module/helpers/deliveryStore.d.ts +51 -0
- package/dist/module/helpers/index.js +370 -3
- package/dist/module/helpers/index.js.map +4 -4
- package/dist/module/host/components/myopIframeComponent.d.ts +6 -0
- package/dist/module/host/embeddedSDK.js +1 -1
- package/dist/module/host/hostSDK.d.ts +2 -0
- package/dist/module/host/index.js +1065 -645
- package/dist/module/host/index.js.map +4 -4
- package/dist/module/host/loaders/HTMLComponentLoader.d.ts +2 -1
- package/dist/module/webcomponent/index.js +1136 -716
- package/dist/module/webcomponent/index.js.map +4 -4
- package/package.json +1 -1
- package/dist/cjs/_IframeSDK.c2225e19.min.js +0 -1
- package/dist/cjs/_IframeSDK.c7926c56.js.map +0 -7
- package/dist/cjs/_MyopHelpers.08d1cf5d.js.map +0 -7
- package/dist/cjs/_MyopHelpers.59521d8f.min.js +0 -1
- package/dist/cjs/_WebComponentSDK.0caec562.min.js +0 -1
- package/dist/cjs/_WebComponentSDK.501a71f9.js.map +0 -7
- package/dist/cjs/_hostSDK.02edf3e2.min.js +0 -1
- package/dist/cjs/_hostSDK.cdbc1f60.js.map +0 -7
|
@@ -1674,9 +1674,7 @@ var MyopIframeComponent = class extends BaseMyopComponent {
|
|
|
1674
1674
|
const iframe = this.IframeElement;
|
|
1675
1675
|
const doc = iframe.contentDocument;
|
|
1676
1676
|
if (!doc) {
|
|
1677
|
-
|
|
1678
|
-
return () => {
|
|
1679
|
-
};
|
|
1677
|
+
return this.observeHeightViaBridge();
|
|
1680
1678
|
}
|
|
1681
1679
|
const clamp = (value, min, max) => {
|
|
1682
1680
|
if (min !== void 0 && value < min) return min;
|
|
@@ -1820,6 +1818,32 @@ var MyopIframeComponent = class extends BaseMyopComponent {
|
|
|
1820
1818
|
this._autoSizeCleanup = cleanup;
|
|
1821
1819
|
return cleanup;
|
|
1822
1820
|
});
|
|
1821
|
+
__publicField(this, "_bridgeSizeCleanup");
|
|
1822
|
+
/**
|
|
1823
|
+
* Auto-height for a frame the host can't read (cross-origin). Runs after the IframeSDK
|
|
1824
|
+
* handshake: the frame reports body resizes and the host re-reads the scroll height.
|
|
1825
|
+
*/
|
|
1826
|
+
__publicField(this, "observeHeightViaBridge", () => {
|
|
1827
|
+
if (this._bridgeSizeCleanup) return this._bridgeSizeCleanup;
|
|
1828
|
+
let observerCleanup;
|
|
1829
|
+
let stopped = false;
|
|
1830
|
+
const cleanup = () => {
|
|
1831
|
+
stopped = true;
|
|
1832
|
+
observerCleanup == null ? void 0 : observerCleanup();
|
|
1833
|
+
this._bridgeSizeCleanup = void 0;
|
|
1834
|
+
};
|
|
1835
|
+
this._bridgeSizeCleanup = cleanup;
|
|
1836
|
+
this.initiated().then(() => {
|
|
1837
|
+
if (stopped || this.markedForDisposed) return;
|
|
1838
|
+
this.IframeElement.style.position = "relative";
|
|
1839
|
+
this.IframeElement.style.inset = "auto";
|
|
1840
|
+
this.IframeElement.style.width = "100%";
|
|
1841
|
+
this.setHeightBasedOnScrollHeight();
|
|
1842
|
+
observerCleanup = this.send(new SetResizeObserverMessage());
|
|
1843
|
+
}).catch(() => {
|
|
1844
|
+
});
|
|
1845
|
+
return cleanup;
|
|
1846
|
+
});
|
|
1823
1847
|
__publicField(this, "setSizeBasedOnDocumentElement", () => {
|
|
1824
1848
|
const cleanupHandler = this.send(new ExecuteScriptMessage(() => {
|
|
1825
1849
|
const { height, width } = document.documentElement.getBoundingClientRect();
|
|
@@ -1865,6 +1889,8 @@ var MyopIframeComponent = class extends BaseMyopComponent {
|
|
|
1865
1889
|
return cleanupHandler;
|
|
1866
1890
|
});
|
|
1867
1891
|
__publicField(this, "dispose", () => {
|
|
1892
|
+
var _a;
|
|
1893
|
+
(_a = this._bridgeSizeCleanup) == null ? void 0 : _a.call(this);
|
|
1868
1894
|
if (this._autoSizeCleanup) {
|
|
1869
1895
|
this._autoSizeCleanup();
|
|
1870
1896
|
this._autoSizeCleanup = void 0;
|
|
@@ -2030,7 +2056,11 @@ var MyopIframeLoader = class extends BaseMyopLoader {
|
|
|
2030
2056
|
container.innerHTML = "";
|
|
2031
2057
|
IframeElement = this.appendChild(container, IframeElement, options);
|
|
2032
2058
|
}
|
|
2033
|
-
|
|
2059
|
+
const component = new MyopIframeComponent(componentDefinition, skin, container, IframeElement, options);
|
|
2060
|
+
if (typedLoaderConfig.autoHeight && (options == null ? void 0 : options.autoSize) !== false) {
|
|
2061
|
+
component.observeHeightViaBridge();
|
|
2062
|
+
}
|
|
2063
|
+
return component;
|
|
2034
2064
|
});
|
|
2035
2065
|
}
|
|
2036
2066
|
};
|
|
@@ -2139,364 +2169,161 @@ var WebcomponentLoader = class extends BaseMyopLoader {
|
|
|
2139
2169
|
};
|
|
2140
2170
|
|
|
2141
2171
|
// version:myop-sdk-version
|
|
2142
|
-
var myop_sdk_version_default = "0.
|
|
2143
|
-
|
|
2144
|
-
// src/host/embeddedSDK.ts
|
|
2145
|
-
var EMBEDDED_SDK_CONTENT = "";
|
|
2146
|
-
var HAS_EMBEDDED_SDK = false;
|
|
2172
|
+
var myop_sdk_version_default = "0.4.0-beta.0";
|
|
2147
2173
|
|
|
2148
|
-
// src/
|
|
2149
|
-
var
|
|
2150
|
-
var
|
|
2151
|
-
var
|
|
2152
|
-
var
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
shadow.innerHTML = htmlString;
|
|
2169
|
-
});
|
|
2174
|
+
// src/helpers/deliveryStore.ts
|
|
2175
|
+
var DB_NAME = "myop-delivery";
|
|
2176
|
+
var STORE = "components";
|
|
2177
|
+
var DB_VERSION = 1;
|
|
2178
|
+
var dbPromise = null;
|
|
2179
|
+
function openDb() {
|
|
2180
|
+
if (dbPromise) return dbPromise;
|
|
2181
|
+
dbPromise = new Promise((resolve) => {
|
|
2182
|
+
try {
|
|
2183
|
+
if (typeof indexedDB === "undefined") return resolve(null);
|
|
2184
|
+
const req = indexedDB.open(DB_NAME, DB_VERSION);
|
|
2185
|
+
req.onupgradeneeded = () => {
|
|
2186
|
+
const db = req.result;
|
|
2187
|
+
if (!db.objectStoreNames.contains(STORE)) db.createObjectStore(STORE, { keyPath: "key" });
|
|
2188
|
+
};
|
|
2189
|
+
req.onsuccess = () => resolve(req.result);
|
|
2190
|
+
req.onerror = () => resolve(null);
|
|
2191
|
+
req.onblocked = () => resolve(null);
|
|
2192
|
+
} catch (e) {
|
|
2193
|
+
resolve(null);
|
|
2170
2194
|
}
|
|
2171
|
-
};
|
|
2195
|
+
});
|
|
2196
|
+
return dbPromise;
|
|
2172
2197
|
}
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2198
|
+
function tx(mode, fn) {
|
|
2199
|
+
return openDb().then((db) => new Promise((resolve) => {
|
|
2200
|
+
if (!db) return resolve(null);
|
|
2201
|
+
try {
|
|
2202
|
+
const t = db.transaction(STORE, mode);
|
|
2203
|
+
const req = fn(t.objectStore(STORE));
|
|
2204
|
+
req.onsuccess = () => resolve(req.result);
|
|
2205
|
+
req.onerror = () => resolve(null);
|
|
2206
|
+
t.onabort = () => resolve(null);
|
|
2207
|
+
} catch (e) {
|
|
2208
|
+
resolve(null);
|
|
2209
|
+
}
|
|
2210
|
+
}));
|
|
2211
|
+
}
|
|
2212
|
+
var HINT_PREFIX = "myop.d.";
|
|
2213
|
+
function writeHint(key, tag, expiresAt) {
|
|
2214
|
+
try {
|
|
2215
|
+
localStorage.setItem(HINT_PREFIX + key, JSON.stringify({ t: tag, e: expiresAt }));
|
|
2216
|
+
} catch (e) {
|
|
2217
|
+
}
|
|
2218
|
+
}
|
|
2219
|
+
function clearHint(key) {
|
|
2220
|
+
try {
|
|
2221
|
+
localStorage.removeItem(HINT_PREFIX + key);
|
|
2222
|
+
} catch (e) {
|
|
2223
|
+
}
|
|
2224
|
+
}
|
|
2225
|
+
var memory = /* @__PURE__ */ new Map();
|
|
2226
|
+
var deliveryStore = {
|
|
2227
|
+
key(host, componentId, env, preview, opt) {
|
|
2228
|
+
return "".concat(host, "|").concat(componentId, "|").concat(env, "|").concat(preview ? "preview" : "live", "|").concat(opt || "raw");
|
|
2229
|
+
},
|
|
2230
|
+
async get(key) {
|
|
2231
|
+
const m = memory.get(key);
|
|
2232
|
+
if (m) return m;
|
|
2233
|
+
const e = await tx("readonly", (s) => s.get(key));
|
|
2234
|
+
if (e) {
|
|
2235
|
+
memory.set(key, e);
|
|
2236
|
+
writeHint(key, e.tag, e.storedAt + e.windowMs);
|
|
2237
|
+
}
|
|
2238
|
+
return e;
|
|
2239
|
+
},
|
|
2240
|
+
async put(entry) {
|
|
2241
|
+
memory.set(entry.key, entry);
|
|
2242
|
+
writeHint(entry.key, entry.tag, entry.storedAt + entry.windowMs);
|
|
2243
|
+
await tx("readwrite", (s) => s.put(entry));
|
|
2244
|
+
},
|
|
2245
|
+
async drop(key) {
|
|
2246
|
+
memory.delete(key);
|
|
2247
|
+
clearHint(key);
|
|
2248
|
+
await tx("readwrite", (s) => s.delete(key));
|
|
2249
|
+
},
|
|
2250
|
+
/** Still usable without asking the server? */
|
|
2251
|
+
fresh(e) {
|
|
2252
|
+
return !!e && Date.now() - e.storedAt < e.windowMs;
|
|
2253
|
+
},
|
|
2254
|
+
/**
|
|
2255
|
+
* The window this response licenses: the server's freshness minus what a CDN already
|
|
2256
|
+
* spent. Returns 0 when the server said nothing about caching, which means "do not
|
|
2257
|
+
* hold this" — the safe reading, and what production sends today.
|
|
2258
|
+
*/
|
|
2259
|
+
windowFrom(headers) {
|
|
2260
|
+
const cc = headers.get("cache-control") || "";
|
|
2261
|
+
if (/no-store|no-cache/i.test(cc)) return 0;
|
|
2262
|
+
const m = /s-maxage\s*=\s*(\d+)/i.exec(cc) || /max-age\s*=\s*(\d+)/i.exec(cc);
|
|
2263
|
+
if (!m) return 0;
|
|
2264
|
+
const total = Number(m[1]);
|
|
2265
|
+
const age = Number(headers.get("age") || 0);
|
|
2266
|
+
return Math.max(0, total - (isNaN(age) ? 0 : age)) * 1e3;
|
|
2267
|
+
},
|
|
2268
|
+
/** For tests and for `refresh()`: forget everything this browser holds. */
|
|
2269
|
+
async clear() {
|
|
2270
|
+
memory.clear();
|
|
2271
|
+
try {
|
|
2272
|
+
for (let i = localStorage.length - 1; i >= 0; i--) {
|
|
2273
|
+
const k = localStorage.key(i);
|
|
2274
|
+
if (k && k.startsWith(HINT_PREFIX)) localStorage.removeItem(k);
|
|
2275
|
+
}
|
|
2276
|
+
} catch (e) {
|
|
2277
|
+
}
|
|
2278
|
+
await tx("readwrite", (s) => s.clear());
|
|
2279
|
+
}
|
|
2183
2280
|
};
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
if (mode !== "webComponent") {
|
|
2197
|
-
throw new Error('[Myop] Web-component rendering denied by render policy for component "'.concat(componentDefinition.id, '"'));
|
|
2281
|
+
|
|
2282
|
+
// src/helpers/CloudRepository.ts
|
|
2283
|
+
var convertV2VariantToComponentConfig = (config) => {
|
|
2284
|
+
return {
|
|
2285
|
+
instance: {
|
|
2286
|
+
id: "auto",
|
|
2287
|
+
componentId: config.componentId,
|
|
2288
|
+
componentName: config.name,
|
|
2289
|
+
skinSelector: {
|
|
2290
|
+
type: "Dedicated",
|
|
2291
|
+
skin: {
|
|
2292
|
+
id: "skin_auto_v2_converted"
|
|
2198
2293
|
}
|
|
2199
|
-
return this.loadExtractedWebComponent(componentDefinition, skin, container, loaderConfig.HTML, options);
|
|
2200
2294
|
}
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
IframeElement.id = domId2;
|
|
2208
|
-
if (isolate) {
|
|
2209
|
-
IframeElement.setAttribute("sandbox", "allow-scripts allow-forms allow-popups");
|
|
2210
|
-
}
|
|
2211
|
-
IframeElement.style.cssText = "\n display: block;\n padding: 0;\n margin: 0;\n position: absolute;\n inset: 0;\n overflow: hidden;\n border: none;\n opacity: ".concat((options == null ? void 0 : options.hidden) ? "0" : "1", ";\n width: 100%;\n height: 100%;\n pointer-events: ").concat((options == null ? void 0 : options.hidden) ? "none" : "all", ";\n ");
|
|
2212
|
-
if (!container.querySelector('[id^="myop-comp-"]'))
|
|
2213
|
-
container.innerHTML = "";
|
|
2214
|
-
IframeElement = this.appendChild(container, IframeElement, options);
|
|
2215
|
-
const __srcParts = [];
|
|
2216
|
-
const doc = isolate ? {
|
|
2217
|
-
open() {
|
|
2218
|
-
},
|
|
2219
|
-
writeln(s) {
|
|
2220
|
-
__srcParts.push(s);
|
|
2221
|
-
},
|
|
2222
|
-
close() {
|
|
2223
|
-
IframeElement.srcdoc = __srcParts.join("\n");
|
|
2224
|
-
}
|
|
2225
|
-
} : (() => {
|
|
2226
|
-
const d = IframeElement.contentDocument || IframeElement.contentWindow.document;
|
|
2227
|
-
d.open();
|
|
2228
|
-
return d;
|
|
2229
|
-
})();
|
|
2230
|
-
let parsedSizeMeta = null;
|
|
2295
|
+
},
|
|
2296
|
+
type: {
|
|
2297
|
+
id: config.id,
|
|
2298
|
+
name: config.name,
|
|
2299
|
+
description: config.description,
|
|
2300
|
+
props: [
|
|
2231
2301
|
{
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
parsedSizeMeta = JSON.parse(sizeMeta.getAttribute("content") || "{}");
|
|
2238
|
-
} catch (e) {
|
|
2239
|
-
}
|
|
2240
|
-
}
|
|
2241
|
-
}
|
|
2242
|
-
let HTML2Render = loaderConfig.HTML;
|
|
2243
|
-
if (options == null ? void 0 : options._inspection) {
|
|
2244
|
-
const parser = new DOMParser();
|
|
2245
|
-
const _doc = parser.parseFromString(loaderConfig.HTML, "text/html");
|
|
2246
|
-
const myop_preview_script = _doc.getElementById("myop_preview");
|
|
2247
|
-
myop_preview_script == null ? void 0 : myop_preview_script.removeAttribute("type");
|
|
2248
|
-
const temp = _doc.implementation.createHTMLDocument();
|
|
2249
|
-
temp.body.innerHTML = "<script>\n const beforeKeysWindow = new Set(Object.keys(window));\n window.myopState = {\n beforeKeysWindow,\n };\n <\/script>";
|
|
2250
|
-
const node = temp.body.firstChild;
|
|
2251
|
-
if (node && _doc.head) {
|
|
2252
|
-
_doc.head.insertBefore(_doc.importNode(node, true), _doc.head.firstChild);
|
|
2302
|
+
id: "in_auto_v2_converted",
|
|
2303
|
+
name: "myop_init_interface",
|
|
2304
|
+
type: "any",
|
|
2305
|
+
behavior: {
|
|
2306
|
+
type: PropConfigBehaviorTypes.code
|
|
2253
2307
|
}
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
HTML2Render = "<!DOCTYPE html>" + _doc.documentElement.outerHTML;
|
|
2308
|
+
},
|
|
2309
|
+
{
|
|
2310
|
+
id: "out_auto_v2_converted",
|
|
2311
|
+
name: "myop_cta_handler",
|
|
2312
|
+
type: "any",
|
|
2313
|
+
behavior: {
|
|
2314
|
+
type: PropConfigBehaviorTypes.code
|
|
2262
2315
|
}
|
|
2263
2316
|
}
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
const sdkScript = HAS_EMBEDDED_SDK ? "<script>".concat(EMBEDDED_SDK_CONTENT, "<\/script>") : '<script src="'.concat(window.myop.__ROOT_SDK_PUBLIC_URL__, '"><\/script>');
|
|
2275
|
-
const initScript = HAS_EMBEDDED_SDK ? "<script>\n const __myop_init = async () => {\n const iframeModule = await MyopSDK.getIframeModule();\n const IframeSDK = iframeModule.IframeSDK;\n const sdk = new IframeSDK();\n sdk.init();\n }\n __myop_init().then();\n <\/script>" : "<script>\n window.__federation__.__public_path__ = window.__federation__.__public_path__;\n const __myop_init = async () => {\n const {IframeSDK} = (await window.myop.rootSDK.getIframeModule());\n const sdk = new IframeSDK();\n sdk.init();\n }\n __myop_init().then();\n <\/script>";
|
|
2276
|
-
if (!isolate) {
|
|
2277
|
-
doc.writeln("".concat(sdkScript).concat(initScript));
|
|
2278
|
-
}
|
|
2279
|
-
if (!isolate && (options == null ? void 0 : options.data) !== void 0) {
|
|
2280
|
-
const ctaQueueScript = "<script>\n window.__myop_cta_queue = [];\n window.myop_cta_handler = function(action, payload) {\n window.__myop_cta_queue.push({action: action, payload: payload});\n };\n <\/script>";
|
|
2281
|
-
const escapedData = JSON.stringify(options.data).replace(/<\/script/gi, "\\u003c/script");
|
|
2282
|
-
const dataScript = '<script id="__myop_init_data_script">\n (function() {\n var data = '.concat(escapedData, ";\n var scriptEl = document.getElementById('__myop_init_data_script');\n\n var callInitInterface = function(fn) {\n var startTime = performance.now();\n // Mark as pre-injected data call for extension tracking\n window.__myop_init_preinjected = true;\n try {\n fn(data);\n } finally {\n window.__myop_init_preinjected = false;\n }\n var duration = performance.now() - startTime;\n\n // Notify extension via postMessage (init* = pre-injected)\n try {\n window.parent.postMessage({\n type: 'MYOP_PREINJECTED_INIT',\n payload: {\n data: data,\n duration: duration,\n timestamp: Date.now()\n }\n }, '*');\n } catch (e) {}\n\n // Cleanup: remove script tag and stored data\n if (scriptEl && scriptEl.parentNode) {\n scriptEl.parentNode.removeChild(scriptEl);\n }\n delete window.__myop_init_data;\n };\n\n if (typeof window.myop_init_interface === 'function') {\n // Function already exists - call immediately\n callInitInterface(window.myop_init_interface);\n } else {\n // Function not yet defined - store data and watch for definition\n window.__myop_init_data = data;\n\n var _original;\n Object.defineProperty(window, 'myop_init_interface', {\n configurable: true,\n enumerable: true,\n set: function(fn) {\n _original = fn;\n if (window.__myop_init_data !== undefined) {\n var storedData = window.__myop_init_data;\n delete window.__myop_init_data;\n callInitInterface(fn);\n }\n },\n get: function() {\n return _original;\n }\n });\n }\n })();\n <\/script>");
|
|
2283
|
-
doc.writeln(ctaQueueScript + dataScript);
|
|
2284
|
-
}
|
|
2285
|
-
if (isolate) {
|
|
2286
|
-
const escapedData = (options == null ? void 0 : options.data) !== void 0 ? JSON.stringify(options.data).replace(/<\/script/gi, "\\u003c/script") : "undefined";
|
|
2287
|
-
doc.writeln(this.buildIsolationBridge(escapedData));
|
|
2288
|
-
}
|
|
2289
|
-
doc.close();
|
|
2290
|
-
const comp = new MyopIframeComponent(componentDefinition, skin, container, IframeElement, options);
|
|
2291
|
-
if (isolate) comp.enableIsolation();
|
|
2292
|
-
comp.sizeMeta = parsedSizeMeta;
|
|
2293
|
-
comp.initiated().then(() => {
|
|
2294
|
-
if ((options == null ? void 0 : options.autoSize) === false) {
|
|
2295
|
-
return;
|
|
2296
|
-
}
|
|
2297
|
-
let shown = false;
|
|
2298
|
-
comp.observeAutoSize({
|
|
2299
|
-
forceAutoSize: true,
|
|
2300
|
-
onSizeChange: () => {
|
|
2301
|
-
if (!shown && !(options == null ? void 0 : options.hidden)) {
|
|
2302
|
-
shown = true;
|
|
2303
|
-
comp.show();
|
|
2304
|
-
}
|
|
2305
|
-
}
|
|
2306
|
-
});
|
|
2307
|
-
});
|
|
2308
|
-
return comp;
|
|
2309
|
-
}
|
|
2310
|
-
if (loaderConfig.shadowRootMode === ShadowRootModeType.none) {
|
|
2311
|
-
const template = document.createElement("template");
|
|
2312
|
-
template.innerHTML = loaderConfig.HTML;
|
|
2313
|
-
element = template.content.firstElementChild;
|
|
2314
|
-
getInitiatedSdk().then((sdk2) => {
|
|
2315
|
-
sdk2.connectedCallback(element, element);
|
|
2316
|
-
});
|
|
2317
|
-
} else {
|
|
2318
|
-
const customElementName = toCustomElementName(componentDefinition.name + skin.id);
|
|
2319
|
-
if (!seen2.includes(customElementName)) {
|
|
2320
|
-
createCustomWebComponent(customElementName, loaderConfig.HTML, loaderConfig.shadowRootMode);
|
|
2321
|
-
seen2.push(customElementName);
|
|
2322
|
-
}
|
|
2323
|
-
element = document.createElement(customElementName);
|
|
2324
|
-
}
|
|
2325
|
-
if (!container.querySelector('[id^="myop-comp-"]'))
|
|
2326
|
-
container.innerHTML = "";
|
|
2327
|
-
element.id = domId;
|
|
2328
|
-
if (options == null ? void 0 : options.hidden) {
|
|
2329
|
-
element.style.opacity = "0";
|
|
2330
|
-
element.style.position = "absolute";
|
|
2331
|
-
element.style.height = "0";
|
|
2332
|
-
element.style.width = "0";
|
|
2333
|
-
element.style.pointerEvents = "none";
|
|
2334
|
-
element.style.visibility = "hidden";
|
|
2335
|
-
}
|
|
2336
|
-
this.appendChild(container, element, options);
|
|
2337
|
-
return new MyopWebComponent(componentDefinition, skin, container, element, options);
|
|
2338
|
-
});
|
|
2339
|
-
}
|
|
2340
|
-
/**
|
|
2341
|
-
* Detect if HTML is a Myop Web Component (starts with marker comment)
|
|
2342
|
-
*/
|
|
2343
|
-
isMyopWebComponent(html) {
|
|
2344
|
-
return html.trimStart().startsWith(MYOP_WEB_COMPONENT_MARKER);
|
|
2345
|
-
}
|
|
2346
|
-
/**
|
|
2347
|
-
* Resolve how this component should render, applying the host render policy.
|
|
2348
|
-
* Precedence: options.renderPolicy (per-call) fully replaces the global
|
|
2349
|
-
* hostSDK.setRenderPolicy — so an app can restrict globally and allow specifics.
|
|
2350
|
-
* With no policy set, behavior is unchanged from before (marker ⇒ web component).
|
|
2351
|
-
*/
|
|
2352
|
-
async resolveRenderMode(componentDefinition, skin, loaderConfig, isWebComponent, options) {
|
|
2353
|
-
var _a, _b, _c, _d;
|
|
2354
|
-
const requestedMode = isWebComponent ? "webComponent" : loaderConfig.isolation || (options == null ? void 0 : options.isolation) ? "isolatedIframe" : "iframe";
|
|
2355
|
-
const policy = (_d = options == null ? void 0 : options.renderPolicy) != null ? _d : (_c = (_b = (_a = window == null ? void 0 : window.myop) == null ? void 0 : _a.hostSDK) == null ? void 0 : _b.getRenderPolicy) == null ? void 0 : _c.call(_b);
|
|
2356
|
-
const mode = policy ? await policy({ componentDefinition, skin, requestedMode, isWebComponent }) : requestedMode;
|
|
2357
|
-
return { mode, isolate: mode === "isolatedIframe" };
|
|
2358
|
-
}
|
|
2359
|
-
/**
|
|
2360
|
-
* The in-frame bridge for isolated components. Runs inside the sandboxed
|
|
2361
|
-
* (opaque-origin) iframe, translating the same author-facing contract to/from
|
|
2362
|
-
* postMessage since the host has no same-origin access:
|
|
2363
|
-
* • data-in : parent posts {type:'myop:init'} → calls window.myop_init_interface
|
|
2364
|
-
* (plus a baked initial value for the first render)
|
|
2365
|
-
* • data-out: window.myop_cta_handler → parent.postMessage({type:'myop:cta'})
|
|
2366
|
-
* • resize : ResizeObserver → parent.postMessage({type:'myop:size'})
|
|
2367
|
-
*
|
|
2368
|
-
* TODO(dev-extension): the isolated path deliberately skips the same-origin
|
|
2369
|
-
* dataScript, so it never posts the `MYOP_PREINJECTED_INIT` message the Myop dev
|
|
2370
|
-
* extension listens for to log the INITIAL render (`init*`). Later init updates and
|
|
2371
|
-
* all CTAs are still tracked (the extension wraps `comp.props`, which our isolated
|
|
2372
|
-
* connectProps branch routes through), so only the first-render payload is missing
|
|
2373
|
-
* from the extension's activity log for isolated components. Closing this would be a
|
|
2374
|
-
* ~1-line `parent.postMessage({type:'MYOP_PREINJECTED_INIT', payload:{data}})` inside
|
|
2375
|
-
* flushInitial() below — intentionally NOT done for now to avoid adding extension-only
|
|
2376
|
-
* traffic to the component runtime. Web components have the same initial-init gap
|
|
2377
|
-
* (initWithData is called on the element, not via comp.props) and it predates this.
|
|
2378
|
-
*/
|
|
2379
|
-
buildIsolationBridge(initialDataLiteral) {
|
|
2380
|
-
return "<script>\n (function () {\n var __initial = ".concat(initialDataLiteral, ";\n var __pending;\n // data-out (cta)\n window.myop_cta_handler = function (action, payload) {\n try { parent.postMessage({ __myop: true, type: 'myop:cta', action: action, payload: payload }, '*'); } catch (e) {}\n };\n function callInit(data) {\n if (typeof window.myop_init_interface === 'function') { window.myop_init_interface(data); return true; }\n return false;\n }\n // data-in (init updates)\n window.addEventListener('message', function (e) {\n var d = e.data;\n if (!d || d.__myop !== true) return;\n if (d.type === 'myop:init') { if (!callInit(d.data)) __pending = d.data; }\n });\n // first render: use a pending update if one arrived, else the baked initial data\n (function flushInitial() {\n var data = (__pending !== undefined) ? __pending : __initial;\n if (data === undefined) return;\n if (callInit(data)) { __pending = undefined; __initial = undefined; }\n else requestAnimationFrame(flushInitial);\n })();\n // resize (report content size)\n function contentHeight() {\n // Measure the BODY (content box). documentElement.scrollHeight includes\n // the iframe viewport \u2014 which we're driving \u2014 so it would report the\n // current frame height, not the content, and never shrink.\n var b = document.body;\n if (b) return Math.max(b.scrollHeight, b.offsetHeight);\n return document.documentElement.scrollHeight;\n }\n function postSize() {\n try {\n parent.postMessage({\n __myop: true, type: 'myop:size',\n height: contentHeight(),\n width: document.documentElement.scrollWidth\n }, '*');\n } catch (e) {}\n }\n // Observe the BODY (reflows with content) \u2014 not documentElement, whose box is\n // the iframe viewport and would feed back into a resize loop. A MutationObserver\n // catches content swaps (e.g. innerHTML re-render) that don't change body's box.\n if (window.ResizeObserver) {\n try { var __ro = new ResizeObserver(postSize); if (document.body) __ro.observe(document.body); } catch (e) {}\n }\n if (window.MutationObserver && document.body) {\n try { new MutationObserver(postSize).observe(document.body, { childList: true, subtree: true, attributes: true, characterData: true }); } catch (e) {}\n }\n window.addEventListener('load', postSize);\n postSize();\n })();\n <\/script>");
|
|
2381
|
-
}
|
|
2382
|
-
/**
|
|
2383
|
-
* Extract the web component script content from HTML
|
|
2384
|
-
*/
|
|
2385
|
-
extractWebComponentScript(html) {
|
|
2386
|
-
const parser = new DOMParser();
|
|
2387
|
-
const doc = parser.parseFromString(html, "text/html");
|
|
2388
|
-
const script = doc.getElementById(MYOP_WEB_COMPONENT_SCRIPT_ID);
|
|
2389
|
-
return (script == null ? void 0 : script.textContent) || null;
|
|
2390
|
-
}
|
|
2391
|
-
/**
|
|
2392
|
-
* Execute the web component script on the host document
|
|
2393
|
-
*/
|
|
2394
|
-
executeWebComponentScript(scriptContent, scriptId) {
|
|
2395
|
-
if (extractedWebComponentScripts.has(scriptId)) {
|
|
2396
|
-
console.log("[MyopWebComponent] Script already executed for ".concat(scriptId, ", skipping"));
|
|
2397
|
-
return;
|
|
2398
|
-
}
|
|
2399
|
-
const script = document.createElement("script");
|
|
2400
|
-
script.textContent = scriptContent;
|
|
2401
|
-
script.id = "myop-extracted-".concat(scriptId);
|
|
2402
|
-
document.head.appendChild(script);
|
|
2403
|
-
extractedWebComponentScripts.add(scriptId);
|
|
2404
|
-
console.log("[MyopWebComponent] Executed web component script: ".concat(scriptId));
|
|
2405
|
-
}
|
|
2406
|
-
/**
|
|
2407
|
-
* Load a Myop Web Component (extracted and run on host document)
|
|
2408
|
-
*/
|
|
2409
|
-
async loadExtractedWebComponent(componentDefinition, skin, container, html, options) {
|
|
2410
|
-
const scriptContent = this.extractWebComponentScript(html);
|
|
2411
|
-
if (!scriptContent) {
|
|
2412
|
-
throw new Error('[MyopWebComponent] No <script id="myop-web-component"> found in HTML');
|
|
2413
|
-
}
|
|
2414
|
-
const scriptId = "".concat(componentDefinition.id, "-").concat(skin.id);
|
|
2415
|
-
const previousTagName = window.__MYOP_TAG_NAME__;
|
|
2416
|
-
this.executeWebComponentScript(scriptContent, scriptId);
|
|
2417
|
-
const tagName = window.__MYOP_TAG_NAME__;
|
|
2418
|
-
if (!tagName) {
|
|
2419
|
-
throw new Error("[MyopWebComponent] Script did not set window.__MYOP_TAG_NAME__");
|
|
2420
|
-
}
|
|
2421
|
-
if (previousTagName && previousTagName !== tagName) {
|
|
2422
|
-
console.warn("[MyopWebComponent] __MYOP_TAG_NAME__ changed from ".concat(previousTagName, " to ").concat(tagName));
|
|
2423
|
-
}
|
|
2424
|
-
const domId = "myop-comp-".concat(uuidv4());
|
|
2425
|
-
const element = document.createElement(tagName);
|
|
2426
|
-
element.id = domId;
|
|
2427
|
-
if (options == null ? void 0 : options.hidden) {
|
|
2428
|
-
element.style.opacity = "0";
|
|
2429
|
-
element.style.position = "absolute";
|
|
2430
|
-
element.style.height = "0";
|
|
2431
|
-
element.style.width = "0";
|
|
2432
|
-
element.style.pointerEvents = "none";
|
|
2433
|
-
element.style.visibility = "hidden";
|
|
2434
|
-
}
|
|
2435
|
-
if (!container.querySelector('[id^="myop-comp-"]')) {
|
|
2436
|
-
container.innerHTML = "";
|
|
2437
|
-
}
|
|
2438
|
-
this.appendChild(container, element, options);
|
|
2439
|
-
const component = new MyopExtractedWebComponent(
|
|
2440
|
-
componentDefinition,
|
|
2441
|
-
skin,
|
|
2442
|
-
container,
|
|
2443
|
-
element,
|
|
2444
|
-
tagName,
|
|
2445
|
-
options
|
|
2446
|
-
);
|
|
2447
|
-
if ((options == null ? void 0 : options.data) !== void 0) {
|
|
2448
|
-
component.initWithData(options.data);
|
|
2449
|
-
}
|
|
2450
|
-
console.log("[MyopWebComponent] Loaded <".concat(tagName, "> into container"));
|
|
2451
|
-
return component;
|
|
2452
|
-
}
|
|
2453
|
-
};
|
|
2454
|
-
|
|
2455
|
-
// src/helpers/CloudRepository.ts
|
|
2456
|
-
var convertV2VariantToComponentConfig = (config) => {
|
|
2457
|
-
return {
|
|
2458
|
-
instance: {
|
|
2459
|
-
id: "auto",
|
|
2460
|
-
componentId: config.componentId,
|
|
2461
|
-
componentName: config.name,
|
|
2462
|
-
skinSelector: {
|
|
2463
|
-
type: "Dedicated",
|
|
2464
|
-
skin: {
|
|
2465
|
-
id: "skin_auto_v2_converted"
|
|
2466
|
-
}
|
|
2467
|
-
}
|
|
2468
|
-
},
|
|
2469
|
-
type: {
|
|
2470
|
-
id: config.id,
|
|
2471
|
-
name: config.name,
|
|
2472
|
-
description: config.description,
|
|
2473
|
-
props: [
|
|
2474
|
-
{
|
|
2475
|
-
id: "in_auto_v2_converted",
|
|
2476
|
-
name: "myop_init_interface",
|
|
2477
|
-
type: "any",
|
|
2478
|
-
behavior: {
|
|
2479
|
-
type: PropConfigBehaviorTypes.code
|
|
2480
|
-
}
|
|
2481
|
-
},
|
|
2482
|
-
{
|
|
2483
|
-
id: "out_auto_v2_converted",
|
|
2484
|
-
name: "myop_cta_handler",
|
|
2485
|
-
type: "any",
|
|
2486
|
-
behavior: {
|
|
2487
|
-
type: PropConfigBehaviorTypes.code
|
|
2488
|
-
}
|
|
2489
|
-
}
|
|
2490
|
-
],
|
|
2491
|
-
refs: [],
|
|
2492
|
-
skins: [
|
|
2493
|
-
{
|
|
2494
|
-
id: "skin_auto_v2_converted",
|
|
2495
|
-
name: "auto_v2_converted",
|
|
2496
|
-
description: "",
|
|
2497
|
-
//TODO : handle empty :
|
|
2498
|
-
// @ts-ignore
|
|
2499
|
-
loader: config.consume_variant[0].loader
|
|
2317
|
+
],
|
|
2318
|
+
refs: [],
|
|
2319
|
+
skins: [
|
|
2320
|
+
{
|
|
2321
|
+
id: "skin_auto_v2_converted",
|
|
2322
|
+
name: "auto_v2_converted",
|
|
2323
|
+
description: "",
|
|
2324
|
+
//TODO : handle empty :
|
|
2325
|
+
// @ts-ignore
|
|
2326
|
+
loader: config.consume_variant[0].loader
|
|
2500
2327
|
}
|
|
2501
2328
|
],
|
|
2502
2329
|
defaultSkin: 0
|
|
@@ -2537,6 +2364,45 @@ var _CloudRepository = class _CloudRepository {
|
|
|
2537
2364
|
__publicField(this, "_envExplicitlySet", false);
|
|
2538
2365
|
__publicField(this, "_staticMode", false);
|
|
2539
2366
|
__publicField(this, "_queryParams", {});
|
|
2367
|
+
/**
|
|
2368
|
+
* Opt-in delivery settings, set by myop.delivery(). Off means: this file behaves
|
|
2369
|
+
* EXACTLY as it did before — same host, same URL, same everything.
|
|
2370
|
+
*/
|
|
2371
|
+
__publicField(this, "_delivery", { minify: false, host: null, cache: false });
|
|
2372
|
+
/**
|
|
2373
|
+
* What actually happened, for myop.delivery.stats(). `fellBack` is the number that
|
|
2374
|
+
* matters: it is how you find out the lane is unhealthy without waiting for a
|
|
2375
|
+
* bug report, because a fallback is INVISIBLE to the page (it still renders).
|
|
2376
|
+
*/
|
|
2377
|
+
__publicField(this, "_deliveryStats", {
|
|
2378
|
+
requests: 0,
|
|
2379
|
+
viaDelivery: 0,
|
|
2380
|
+
fellBack: 0,
|
|
2381
|
+
lastError: null,
|
|
2382
|
+
/** where the last loads were answered from — the number the client window exists to move */
|
|
2383
|
+
fromMemory: 0,
|
|
2384
|
+
fromStorage: 0,
|
|
2385
|
+
fromNetwork: 0,
|
|
2386
|
+
/** re-checks after the window ended, and how many were answered "nothing changed" */
|
|
2387
|
+
revalidations: 0,
|
|
2388
|
+
unchanged: 0,
|
|
2389
|
+
bytesSaved: 0
|
|
2390
|
+
});
|
|
2391
|
+
/**
|
|
2392
|
+
* Local serves waiting to be reported: componentId -> {env, count}.
|
|
2393
|
+
*
|
|
2394
|
+
* THE MEASUREMENT PROBLEM THIS SOLVES. The better this cache works, the more usage
|
|
2395
|
+
* vanishes: a visitor inside their freshness window renders the page with no request,
|
|
2396
|
+
* so neither the server nor the CDN can see them. Left alone, a successful rollout
|
|
2397
|
+
* looks in the ledger exactly like customers leaving.
|
|
2398
|
+
*
|
|
2399
|
+
* So local serves are counted here and reported afterwards, batched, on a path that
|
|
2400
|
+
* never blocks rendering: flushed when the page is hidden (keepalive, so it survives
|
|
2401
|
+
* the tab closing) and opportunistically whenever the SDK is talking to the server
|
|
2402
|
+
* anyway. Nothing is sent while the page is loading, which is the point of the window.
|
|
2403
|
+
*/
|
|
2404
|
+
__publicField(this, "_localServes", /* @__PURE__ */ new Map());
|
|
2405
|
+
__publicField(this, "_flushBound", false);
|
|
2540
2406
|
}
|
|
2541
2407
|
static get Main() {
|
|
2542
2408
|
const globalMain = getGlobalMain();
|
|
@@ -2549,6 +2415,120 @@ var _CloudRepository = class _CloudRepository {
|
|
|
2549
2415
|
}
|
|
2550
2416
|
return _CloudRepository._main;
|
|
2551
2417
|
}
|
|
2418
|
+
/**
|
|
2419
|
+
* How big the component we are NOT re-downloading is. Deliberately measured from what
|
|
2420
|
+
* we hold rather than from Content-Length: once a response is compressed the header is
|
|
2421
|
+
* not readable cross-origin, so reading it there reported 0 every single time.
|
|
2422
|
+
*/
|
|
2423
|
+
static sizeOfHeld(e) {
|
|
2424
|
+
var _a, _b, _c, _d, _e;
|
|
2425
|
+
try {
|
|
2426
|
+
return (((_e = (_d = (_c = (_b = (_a = e == null ? void 0 : e.config) == null ? void 0 : _a.type) == null ? void 0 : _b.skins) == null ? void 0 : _c[0]) == null ? void 0 : _d.loader) == null ? void 0 : _e.HTML) || "").length;
|
|
2427
|
+
} catch (e2) {
|
|
2428
|
+
return 0;
|
|
2429
|
+
}
|
|
2430
|
+
}
|
|
2431
|
+
/**
|
|
2432
|
+
* Turn on the opt-in delivery path.
|
|
2433
|
+
*
|
|
2434
|
+
* Opting in IS choosing the delivery stack: this points /consume at `host` (a second,
|
|
2435
|
+
* complete stack reading the same data) and asks for the minified artifact. Leave this
|
|
2436
|
+
* uncalled and nothing about the SDK changes.
|
|
2437
|
+
*
|
|
2438
|
+
* Deliberately mutates THIS instance rather than constructing a new repository:
|
|
2439
|
+
* CloudRepository.Main is a global singleton shared across bundles (see getGlobalMain),
|
|
2440
|
+
* so a second instance would be ignored by every component already using the first.
|
|
2441
|
+
*/
|
|
2442
|
+
setDelivery(opts = {}) {
|
|
2443
|
+
if (opts.minify !== void 0) this._delivery.minify = !!opts.minify;
|
|
2444
|
+
if (opts.host !== void 0) this._delivery.host = opts.host;
|
|
2445
|
+
if (opts.cache !== void 0) this._delivery.cache = !!opts.cache;
|
|
2446
|
+
}
|
|
2447
|
+
deliveryStats() {
|
|
2448
|
+
var _a;
|
|
2449
|
+
return __spreadProps(__spreadValues({}, this._deliveryStats), {
|
|
2450
|
+
host: (_a = this._delivery.host) != null ? _a : _CloudRepository.DEFAULT_HOST,
|
|
2451
|
+
minify: this._delivery.minify,
|
|
2452
|
+
cache: this._delivery.cache
|
|
2453
|
+
});
|
|
2454
|
+
}
|
|
2455
|
+
/**
|
|
2456
|
+
* Forget what this browser holds, so the next load asks the server.
|
|
2457
|
+
* `refresh()` with no ids drops everything; the counterpart to the window for the case
|
|
2458
|
+
* where a change has to be visible on THIS load — right after someone publishes.
|
|
2459
|
+
*/
|
|
2460
|
+
async refreshDelivery() {
|
|
2461
|
+
await deliveryStore.clear();
|
|
2462
|
+
}
|
|
2463
|
+
noteLocalServe(componentId, env) {
|
|
2464
|
+
const cur = this._localServes.get(componentId);
|
|
2465
|
+
if (cur) cur.count++;
|
|
2466
|
+
else this._localServes.set(componentId, { env, count: 1 });
|
|
2467
|
+
this.bindFlush();
|
|
2468
|
+
}
|
|
2469
|
+
/** Report on page-hide, which is the only event that reliably fires on mobile. */
|
|
2470
|
+
bindFlush() {
|
|
2471
|
+
if (this._flushBound || typeof document === "undefined") return;
|
|
2472
|
+
this._flushBound = true;
|
|
2473
|
+
const onHide = () => {
|
|
2474
|
+
if (document.visibilityState === "hidden") this.flushLocalServes();
|
|
2475
|
+
};
|
|
2476
|
+
document.addEventListener("visibilitychange", onHide);
|
|
2477
|
+
window.addEventListener("pagehide", () => this.flushLocalServes());
|
|
2478
|
+
}
|
|
2479
|
+
/**
|
|
2480
|
+
* Send what we have. `keepalive` is what makes this work at page-hide: the request
|
|
2481
|
+
* outlives the document. Failure is ignored — a lost usage report must never be
|
|
2482
|
+
* visible to a visitor, and the next page load will report its own.
|
|
2483
|
+
*/
|
|
2484
|
+
flushLocalServes() {
|
|
2485
|
+
if (!this._localServes.size) return;
|
|
2486
|
+
const batch = [...this._localServes.entries()].map(([id, v]) => "".concat(id, ":").concat(v.env, ":").concat(v.count)).join(",");
|
|
2487
|
+
this._localServes.clear();
|
|
2488
|
+
try {
|
|
2489
|
+
const url = "".concat(this.deliveryHost(), "/clientUsage?b=").concat(encodeURIComponent(batch));
|
|
2490
|
+
fetch(url, { keepalive: true, mode: "cors", credentials: "omit" }).catch(() => {
|
|
2491
|
+
});
|
|
2492
|
+
} catch (e) {
|
|
2493
|
+
}
|
|
2494
|
+
}
|
|
2495
|
+
/** Where /consume should be fetched from right now. */
|
|
2496
|
+
deliveryHost() {
|
|
2497
|
+
return this._delivery.host || this._baseUrl;
|
|
2498
|
+
}
|
|
2499
|
+
/**
|
|
2500
|
+
* Fetch a delivery URL with ONE fallback to the default host.
|
|
2501
|
+
*
|
|
2502
|
+
* The fallback is the kill switch: break or disable the lane and every client drifts
|
|
2503
|
+
* back to cloud.myop.dev on its own, with no customer deploy. It must therefore be
|
|
2504
|
+
* genuinely silent to the page and genuinely LOUD in stats() — a fallback that nobody
|
|
2505
|
+
* counts is an outage nobody notices.
|
|
2506
|
+
*
|
|
2507
|
+
* Only transport failures and 5xx fall back. A 404 is an answer: the component really
|
|
2508
|
+
* is missing, and retrying elsewhere would only hide it.
|
|
2509
|
+
*/
|
|
2510
|
+
async deliveryFetch(path) {
|
|
2511
|
+
var _a;
|
|
2512
|
+
if (this._localServes.size) this.flushLocalServes();
|
|
2513
|
+
const host = this.deliveryHost();
|
|
2514
|
+
const primary = "".concat(host).concat(path);
|
|
2515
|
+
this._deliveryStats.requests++;
|
|
2516
|
+
const usingLane = host !== this._baseUrl;
|
|
2517
|
+
try {
|
|
2518
|
+
const res = await fetch(primary);
|
|
2519
|
+
if (res.ok || res.status < 500 || !usingLane) {
|
|
2520
|
+
if (usingLane && res.ok) this._deliveryStats.viaDelivery++;
|
|
2521
|
+
return res;
|
|
2522
|
+
}
|
|
2523
|
+
this._deliveryStats.lastError = "HTTP ".concat(res.status, " from ").concat(host);
|
|
2524
|
+
} catch (e) {
|
|
2525
|
+
if (!usingLane) throw e;
|
|
2526
|
+
this._deliveryStats.lastError = String((_a = e == null ? void 0 : e.message) != null ? _a : e);
|
|
2527
|
+
}
|
|
2528
|
+
this._deliveryStats.fellBack++;
|
|
2529
|
+
console.warn("[myop] delivery host failed (".concat(this._deliveryStats.lastError, ") \u2014 falling back to ").concat(this._baseUrl));
|
|
2530
|
+
return await fetch("".concat(this._baseUrl).concat(path));
|
|
2531
|
+
}
|
|
2552
2532
|
/**
|
|
2553
2533
|
* Enable static mode for self-hosted component registries.
|
|
2554
2534
|
* In static mode, URLs are constructed as file paths instead of query params:
|
|
@@ -2644,12 +2624,68 @@ var _CloudRepository = class _CloudRepository {
|
|
|
2644
2624
|
const qs = new URLSearchParams(this._queryParams).toString();
|
|
2645
2625
|
if (qs) url += "?".concat(qs);
|
|
2646
2626
|
} else {
|
|
2647
|
-
url = "
|
|
2627
|
+
url = "/consume?id=".concat(componentId, "&env=").concat(env);
|
|
2648
2628
|
if (usePreview) {
|
|
2649
2629
|
url += "&preview=true";
|
|
2650
2630
|
}
|
|
2631
|
+
if (this._delivery.minify && !usePreview) {
|
|
2632
|
+
url += "&opt=min";
|
|
2633
|
+
}
|
|
2634
|
+
}
|
|
2635
|
+
const cacheable = this._delivery.cache && !this._staticMode && !usePreview;
|
|
2636
|
+
const storeKey = cacheable ? deliveryStore.key(
|
|
2637
|
+
this.deliveryHost(),
|
|
2638
|
+
componentId,
|
|
2639
|
+
env,
|
|
2640
|
+
usePreview,
|
|
2641
|
+
this._delivery.minify ? "min" : "raw"
|
|
2642
|
+
) : "";
|
|
2643
|
+
let held = cacheable ? await deliveryStore.get(storeKey) : null;
|
|
2644
|
+
if (held && deliveryStore.fresh(held)) {
|
|
2645
|
+
this._deliveryStats.fromStorage++;
|
|
2646
|
+
this.noteLocalServe(componentId, env);
|
|
2647
|
+
this.variants[cacheKey].resolved = held.config;
|
|
2648
|
+
resolve(held.config);
|
|
2649
|
+
return;
|
|
2650
|
+
}
|
|
2651
|
+
if (held && held.tag) {
|
|
2652
|
+
const checkUrl = "/consume?ids=".concat(componentId, "&env=").concat(env) + (this._delivery.minify ? "&opt=min" : "") + "&have=".concat(encodeURIComponent(held.tag));
|
|
2653
|
+
this._deliveryStats.revalidations++;
|
|
2654
|
+
try {
|
|
2655
|
+
const check = await this.deliveryFetch(checkUrl);
|
|
2656
|
+
if (check.ok) {
|
|
2657
|
+
const body = await check.json();
|
|
2658
|
+
if ((body.unchanged || []).includes(componentId)) {
|
|
2659
|
+
this._deliveryStats.unchanged++;
|
|
2660
|
+
this._deliveryStats.bytesSaved += _CloudRepository.sizeOfHeld(held);
|
|
2661
|
+
held.storedAt = Date.now();
|
|
2662
|
+
held.windowMs = deliveryStore.windowFrom(check.headers) || held.windowMs;
|
|
2663
|
+
await deliveryStore.put(held);
|
|
2664
|
+
this.variants[cacheKey].resolved = held.config;
|
|
2665
|
+
resolve(held.config);
|
|
2666
|
+
return;
|
|
2667
|
+
}
|
|
2668
|
+
const item = (body.items || [])[0];
|
|
2669
|
+
if (item) {
|
|
2670
|
+
const cfg = convertV2VariantToComponentConfig(item);
|
|
2671
|
+
this._deliveryStats.fromNetwork++;
|
|
2672
|
+
await deliveryStore.put({
|
|
2673
|
+
key: storeKey,
|
|
2674
|
+
config: cfg,
|
|
2675
|
+
tag: item.tag || null,
|
|
2676
|
+
storedAt: Date.now(),
|
|
2677
|
+
windowMs: deliveryStore.windowFrom(check.headers),
|
|
2678
|
+
host: this.deliveryHost()
|
|
2679
|
+
});
|
|
2680
|
+
this.variants[cacheKey].resolved = cfg;
|
|
2681
|
+
resolve(cfg);
|
|
2682
|
+
return;
|
|
2683
|
+
}
|
|
2684
|
+
}
|
|
2685
|
+
} catch (e) {
|
|
2686
|
+
}
|
|
2651
2687
|
}
|
|
2652
|
-
const res = await fetch(url);
|
|
2688
|
+
const res = this._staticMode ? await fetch(url) : await this.deliveryFetch(url);
|
|
2653
2689
|
if (!res.ok) {
|
|
2654
2690
|
reject(new Error('Failed to load component "'.concat(componentId, '" (').concat(res.status).concat(this._staticMode ? " from ".concat(url) : "", ")")));
|
|
2655
2691
|
return;
|
|
@@ -2665,6 +2701,17 @@ var _CloudRepository = class _CloudRepository {
|
|
|
2665
2701
|
return;
|
|
2666
2702
|
}
|
|
2667
2703
|
const componentConfig = convertV2VariantToComponentConfig(variant);
|
|
2704
|
+
this._deliveryStats.fromNetwork++;
|
|
2705
|
+
if (cacheable) {
|
|
2706
|
+
await deliveryStore.put({
|
|
2707
|
+
key: storeKey,
|
|
2708
|
+
config: componentConfig,
|
|
2709
|
+
tag: variant.tag || null,
|
|
2710
|
+
storedAt: Date.now(),
|
|
2711
|
+
windowMs: deliveryStore.windowFrom(res.headers),
|
|
2712
|
+
host: this.deliveryHost()
|
|
2713
|
+
});
|
|
2714
|
+
}
|
|
2668
2715
|
this.variants[cacheKey].resolved = componentConfig;
|
|
2669
2716
|
resolve(componentConfig);
|
|
2670
2717
|
} catch (e) {
|
|
@@ -2672,137 +2719,471 @@ var _CloudRepository = class _CloudRepository {
|
|
|
2672
2719
|
reject(e);
|
|
2673
2720
|
}
|
|
2674
2721
|
}
|
|
2675
|
-
);
|
|
2676
|
-
}
|
|
2677
|
-
return await this.variants[cacheKey];
|
|
2722
|
+
);
|
|
2723
|
+
}
|
|
2724
|
+
return await this.variants[cacheKey];
|
|
2725
|
+
}
|
|
2726
|
+
/**
|
|
2727
|
+
* Synchronous version of fetchComponentV2 — returns the config only if
|
|
2728
|
+
* the fetch already completed, null otherwise.
|
|
2729
|
+
*
|
|
2730
|
+
* Uses the same `this.variants` cache that fetchComponentV2/preloadComponents
|
|
2731
|
+
* populate. Each cached Promise is tagged with a `.resolved` property when
|
|
2732
|
+
* it settles — this method just reads that property. No separate cache.
|
|
2733
|
+
*
|
|
2734
|
+
* Why this exists: React Native needs the config at render time to embed it
|
|
2735
|
+
* in the WebView HTML (can't await in useState). If preloadComponents ran
|
|
2736
|
+
* earlier and the fetch completed, this returns the result synchronously,
|
|
2737
|
+
* skipping the WEBVIEW_READY → fetch → inject round trip entirely.
|
|
2738
|
+
*/
|
|
2739
|
+
getResolvedConfig(componentId, env, preview) {
|
|
2740
|
+
var _a;
|
|
2741
|
+
const { cacheKey } = this.resolveParams(componentId, env, preview);
|
|
2742
|
+
return ((_a = this.variants[cacheKey]) == null ? void 0 : _a.resolved) || null;
|
|
2743
|
+
}
|
|
2744
|
+
/**
|
|
2745
|
+
* Resolve which (env, preview) pair — and therefore which cache key — a call
|
|
2746
|
+
* for `componentId` refers to.
|
|
2747
|
+
*
|
|
2748
|
+
* Single source of truth for fetchComponentV2, getResolvedConfig and
|
|
2749
|
+
* hydrateComponent, so a hydrated config always lands on the key a later
|
|
2750
|
+
* fetch will look under.
|
|
2751
|
+
*/
|
|
2752
|
+
resolveParams(componentId, environmentIdentifier, preview) {
|
|
2753
|
+
const preloaded = this.preloadedComponents[componentId];
|
|
2754
|
+
const hasExplicitParams = environmentIdentifier !== void 0 || preview !== void 0;
|
|
2755
|
+
let env;
|
|
2756
|
+
let usePreview;
|
|
2757
|
+
if (!hasExplicitParams && preloaded) {
|
|
2758
|
+
env = preloaded.env;
|
|
2759
|
+
usePreview = preloaded.preview;
|
|
2760
|
+
} else {
|
|
2761
|
+
env = environmentIdentifier || this._defaultEnv;
|
|
2762
|
+
const hasEffectiveEnv = environmentIdentifier || this._envExplicitlySet;
|
|
2763
|
+
usePreview = preview === true ? true : preview === false ? false : !hasEffectiveEnv;
|
|
2764
|
+
}
|
|
2765
|
+
return { env, usePreview, cacheKey: "".concat(componentId, ":").concat(env, ":").concat(usePreview ? "preview" : "live") };
|
|
2766
|
+
}
|
|
2767
|
+
/**
|
|
2768
|
+
* Seed an already-resolved component config into the cache, without any
|
|
2769
|
+
* network request.
|
|
2770
|
+
*
|
|
2771
|
+
* The counterpart to {@link fetchComponentV2}: use it when the config was
|
|
2772
|
+
* resolved somewhere else — most often on a server, then embedded in the
|
|
2773
|
+
* page — so the browser can render the component with no round trip.
|
|
2774
|
+
*
|
|
2775
|
+
* After hydrating, `fetchComponentV2`, `getResolvedConfig` and `isPreloaded`
|
|
2776
|
+
* all answer for this component from memory.
|
|
2777
|
+
*
|
|
2778
|
+
* Pass the same `env` / `preview` the config was resolved with; the defaults
|
|
2779
|
+
* match what a plain `fetchComponentV2(componentId)` would have used.
|
|
2780
|
+
*/
|
|
2781
|
+
hydrateComponent(componentId, config, env, preview) {
|
|
2782
|
+
const { env: resolvedEnv, usePreview, cacheKey } = this.resolveParams(componentId, env, preview);
|
|
2783
|
+
const promise = Promise.resolve(config);
|
|
2784
|
+
promise.resolved = config;
|
|
2785
|
+
this.variants[cacheKey] = promise;
|
|
2786
|
+
this.preloadedComponents[componentId] = { env: resolvedEnv, preview: usePreview };
|
|
2787
|
+
}
|
|
2788
|
+
// ============ V1 Methods (Legacy) ============
|
|
2789
|
+
/**
|
|
2790
|
+
* Fetch a v1 component from a flow
|
|
2791
|
+
*/
|
|
2792
|
+
async fetchComponentV1(componentId, flowId) {
|
|
2793
|
+
if (flowId) {
|
|
2794
|
+
const flow = await this.fetchFlow(flowId);
|
|
2795
|
+
return flow.components.find((c) => c.type.id === componentId);
|
|
2796
|
+
} else {
|
|
2797
|
+
const flow = await this.fetchAutoFlow(componentId);
|
|
2798
|
+
return flow.components[0];
|
|
2799
|
+
}
|
|
2800
|
+
}
|
|
2801
|
+
async fetchAutoFlow(componentId) {
|
|
2802
|
+
if (!this.userFlows[componentId]) {
|
|
2803
|
+
this.userFlows[componentId] = new Promise(
|
|
2804
|
+
async (resolve, reject) => {
|
|
2805
|
+
try {
|
|
2806
|
+
const res = await fetch(
|
|
2807
|
+
"".concat(this._baseUrl, "/flow?id=").concat(componentId, "&auto=true")
|
|
2808
|
+
);
|
|
2809
|
+
const json = await res.json();
|
|
2810
|
+
resolve(json.item);
|
|
2811
|
+
} catch (e) {
|
|
2812
|
+
delete this.userFlows[componentId];
|
|
2813
|
+
reject(e);
|
|
2814
|
+
}
|
|
2815
|
+
}
|
|
2816
|
+
);
|
|
2817
|
+
}
|
|
2818
|
+
return await this.userFlows[componentId];
|
|
2819
|
+
}
|
|
2820
|
+
async fetchFlow(flowId) {
|
|
2821
|
+
if (!this.userFlows[flowId]) {
|
|
2822
|
+
this.userFlows[flowId] = new Promise(
|
|
2823
|
+
async (resolve, reject) => {
|
|
2824
|
+
try {
|
|
2825
|
+
const res = await fetch(
|
|
2826
|
+
"".concat(this._baseUrl, "/flow?id=").concat(flowId, "&resolve=components")
|
|
2827
|
+
);
|
|
2828
|
+
const json = await res.json();
|
|
2829
|
+
resolve(json.item);
|
|
2830
|
+
} catch (e) {
|
|
2831
|
+
delete this.userFlows[flowId];
|
|
2832
|
+
reject(e);
|
|
2833
|
+
}
|
|
2834
|
+
}
|
|
2835
|
+
);
|
|
2836
|
+
}
|
|
2837
|
+
return await this.userFlows[flowId];
|
|
2838
|
+
}
|
|
2839
|
+
// ============ Backward Compatibility ============
|
|
2840
|
+
/**
|
|
2841
|
+
* @deprecated Use fetchComponentV2 or fetchComponentV1 explicitly
|
|
2842
|
+
* Defaults to v1 behavior for backward compatibility with existing code
|
|
2843
|
+
*/
|
|
2844
|
+
async fetchComponent(componentId, flowId) {
|
|
2845
|
+
return this.fetchComponentV1(componentId, flowId);
|
|
2846
|
+
}
|
|
2847
|
+
};
|
|
2848
|
+
__publicField(_CloudRepository, "_main", null);
|
|
2849
|
+
/** The host every request goes to unless delivery() moved it. Never changes. */
|
|
2850
|
+
__publicField(_CloudRepository, "DEFAULT_HOST", "https://cloud.myop.dev");
|
|
2851
|
+
var CloudRepository = _CloudRepository;
|
|
2852
|
+
|
|
2853
|
+
// src/helpers/cloudRepositoryHelpers.ts
|
|
2854
|
+
var _cloudRepository = CloudRepository.Main;
|
|
2855
|
+
var DELIVERY_HOST = "https://delivery.myop.dev";
|
|
2856
|
+
var delivery = (opts = {}) => {
|
|
2857
|
+
var _a, _b;
|
|
2858
|
+
const wantsLane = opts.minify !== false || opts.cache === true;
|
|
2859
|
+
_cloudRepository.setDelivery({
|
|
2860
|
+
minify: (_a = opts.minify) != null ? _a : false,
|
|
2861
|
+
cache: (_b = opts.cache) != null ? _b : false,
|
|
2862
|
+
host: opts.host !== void 0 ? opts.host : wantsLane ? DELIVERY_HOST : null
|
|
2863
|
+
});
|
|
2864
|
+
return deliveryStats();
|
|
2865
|
+
};
|
|
2866
|
+
var deliveryRefresh = async () => {
|
|
2867
|
+
await _cloudRepository.refreshDelivery();
|
|
2868
|
+
return deliveryStats();
|
|
2869
|
+
};
|
|
2870
|
+
var deliveryStats = () => _cloudRepository.deliveryStats();
|
|
2871
|
+
var deliveryOff = () => {
|
|
2872
|
+
_cloudRepository.setDelivery({ minify: false, cache: false, host: null });
|
|
2873
|
+
return deliveryStats();
|
|
2874
|
+
};
|
|
2875
|
+
|
|
2876
|
+
// src/host/embeddedSDK.ts
|
|
2877
|
+
var EMBEDDED_SDK_CONTENT = "";
|
|
2878
|
+
var HAS_EMBEDDED_SDK = false;
|
|
2879
|
+
|
|
2880
|
+
// src/host/loaders/HTMLComponentLoader.ts
|
|
2881
|
+
var MYOP_WEB_COMPONENT_MARKER = "<!-- myop-web-component -->";
|
|
2882
|
+
var MYOP_WEB_COMPONENT_SCRIPT_ID = "myop-web-component";
|
|
2883
|
+
var extractedWebComponentScripts = /* @__PURE__ */ new Map();
|
|
2884
|
+
var seen2 = [];
|
|
2885
|
+
var sdk;
|
|
2886
|
+
var getInitiatedSdk = async () => {
|
|
2887
|
+
if (!sdk) {
|
|
2888
|
+
sdk = new WebComponentSDK();
|
|
2889
|
+
sdk.init();
|
|
2890
|
+
}
|
|
2891
|
+
return sdk;
|
|
2892
|
+
};
|
|
2893
|
+
function createHTMLElementConstructor(htmlString, ShadowRootMode) {
|
|
2894
|
+
return class extends HTMLElement {
|
|
2895
|
+
connectedCallback() {
|
|
2896
|
+
const mode = ShadowRootMode === ShadowRootModeType.open ? "open" : "closed";
|
|
2897
|
+
const shadow = this.attachShadow({ mode });
|
|
2898
|
+
getInitiatedSdk().then((sdk2) => {
|
|
2899
|
+
sdk2.connectedCallback(this, shadow);
|
|
2900
|
+
shadow.innerHTML = htmlString;
|
|
2901
|
+
});
|
|
2902
|
+
}
|
|
2903
|
+
};
|
|
2904
|
+
}
|
|
2905
|
+
var createCustomWebComponent = (componentName, html, ShadowRootMode) => {
|
|
2906
|
+
customElements.define(componentName, createHTMLElementConstructor(html, ShadowRootMode));
|
|
2907
|
+
console.log("define('".concat(componentName, "') was called, web component ready to use"));
|
|
2908
|
+
};
|
|
2909
|
+
var toWebComponentName = (str) => {
|
|
2910
|
+
return str.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/(\d+)/g, "-$1").toLowerCase();
|
|
2911
|
+
};
|
|
2912
|
+
var toCustomElementName = (name) => {
|
|
2913
|
+
name = toWebComponentName(name);
|
|
2914
|
+
return name.replace(/_/g, "-");
|
|
2915
|
+
};
|
|
2916
|
+
var HTMLComponentLoader = class extends BaseMyopLoader {
|
|
2917
|
+
constructor() {
|
|
2918
|
+
super(...arguments);
|
|
2919
|
+
__publicField(this, "type", SkinLoaders.HTMLLoader);
|
|
2920
|
+
__publicField(this, "load", async (componentDefinition, skin, container, options) => {
|
|
2921
|
+
const loaderConfig = skin.loader;
|
|
2922
|
+
const isWC = this.isMyopWebComponent(loaderConfig.HTML);
|
|
2923
|
+
const { mode, isolate } = await this.resolveRenderMode(componentDefinition, skin, loaderConfig, isWC, options);
|
|
2924
|
+
if (mode === false) {
|
|
2925
|
+
throw new Error('[Myop] Rendering blocked by render policy for component "'.concat(componentDefinition.id, '"'));
|
|
2926
|
+
}
|
|
2927
|
+
if (isWC) {
|
|
2928
|
+
if (mode !== "webComponent") {
|
|
2929
|
+
throw new Error('[Myop] Web-component rendering denied by render policy for component "'.concat(componentDefinition.id, '"'));
|
|
2930
|
+
}
|
|
2931
|
+
return this.loadExtractedWebComponent(componentDefinition, skin, container, loaderConfig.HTML, options);
|
|
2932
|
+
}
|
|
2933
|
+
let domId = "myop-comp-".concat(uuidv4());
|
|
2934
|
+
let element;
|
|
2935
|
+
if (loaderConfig.shadowRootMode === ShadowRootModeType.localFrame) {
|
|
2936
|
+
const uniqId = uuidv4();
|
|
2937
|
+
const domId2 = "myop-comp-".concat(uniqId);
|
|
2938
|
+
let IframeElement = document.createElement("iframe");
|
|
2939
|
+
IframeElement.id = domId2;
|
|
2940
|
+
if (isolate) {
|
|
2941
|
+
IframeElement.setAttribute("sandbox", "allow-scripts allow-forms allow-popups");
|
|
2942
|
+
}
|
|
2943
|
+
IframeElement.style.cssText = "\n display: block;\n padding: 0;\n margin: 0;\n position: absolute;\n inset: 0;\n overflow: hidden;\n border: none;\n opacity: ".concat((options == null ? void 0 : options.hidden) ? "0" : "1", ";\n width: 100%;\n height: 100%;\n pointer-events: ").concat((options == null ? void 0 : options.hidden) ? "none" : "all", ";\n ");
|
|
2944
|
+
if (!container.querySelector('[id^="myop-comp-"]'))
|
|
2945
|
+
container.innerHTML = "";
|
|
2946
|
+
IframeElement = this.appendChild(container, IframeElement, options);
|
|
2947
|
+
const __srcParts = [];
|
|
2948
|
+
const doc = isolate ? {
|
|
2949
|
+
open() {
|
|
2950
|
+
},
|
|
2951
|
+
writeln(s) {
|
|
2952
|
+
__srcParts.push(s);
|
|
2953
|
+
},
|
|
2954
|
+
close() {
|
|
2955
|
+
IframeElement.srcdoc = __srcParts.join("\n");
|
|
2956
|
+
}
|
|
2957
|
+
} : (() => {
|
|
2958
|
+
const d = IframeElement.contentDocument || IframeElement.contentWindow.document;
|
|
2959
|
+
d.open();
|
|
2960
|
+
return d;
|
|
2961
|
+
})();
|
|
2962
|
+
let parsedSizeMeta = null;
|
|
2963
|
+
{
|
|
2964
|
+
const _preParser = new DOMParser();
|
|
2965
|
+
const _preDoc = _preParser.parseFromString(loaderConfig.HTML, "text/html");
|
|
2966
|
+
const sizeMeta = _preDoc.querySelector('meta[name="myop:size"]');
|
|
2967
|
+
if (sizeMeta) {
|
|
2968
|
+
try {
|
|
2969
|
+
parsedSizeMeta = JSON.parse(sizeMeta.getAttribute("content") || "{}");
|
|
2970
|
+
} catch (e) {
|
|
2971
|
+
}
|
|
2972
|
+
}
|
|
2973
|
+
}
|
|
2974
|
+
let HTML2Render = loaderConfig.HTML;
|
|
2975
|
+
if (options == null ? void 0 : options._inspection) {
|
|
2976
|
+
const parser = new DOMParser();
|
|
2977
|
+
const _doc = parser.parseFromString(loaderConfig.HTML, "text/html");
|
|
2978
|
+
const myop_preview_script = _doc.getElementById("myop_preview");
|
|
2979
|
+
myop_preview_script == null ? void 0 : myop_preview_script.removeAttribute("type");
|
|
2980
|
+
const temp = _doc.implementation.createHTMLDocument();
|
|
2981
|
+
temp.body.innerHTML = "<script>\n const beforeKeysWindow = new Set(Object.keys(window));\n window.myopState = {\n beforeKeysWindow,\n };\n <\/script>";
|
|
2982
|
+
const node = temp.body.firstChild;
|
|
2983
|
+
if (node && _doc.head) {
|
|
2984
|
+
_doc.head.insertBefore(_doc.importNode(node, true), _doc.head.firstChild);
|
|
2985
|
+
}
|
|
2986
|
+
HTML2Render = "<!DOCTYPE html>" + _doc.documentElement.outerHTML;
|
|
2987
|
+
} else if ((options == null ? void 0 : options.data) !== void 0) {
|
|
2988
|
+
const parser = new DOMParser();
|
|
2989
|
+
const _doc = parser.parseFromString(loaderConfig.HTML, "text/html");
|
|
2990
|
+
const myop_preview_script = _doc.getElementById("myop_preview");
|
|
2991
|
+
if (myop_preview_script) {
|
|
2992
|
+
myop_preview_script.remove();
|
|
2993
|
+
HTML2Render = "<!DOCTYPE html>" + _doc.documentElement.outerHTML;
|
|
2994
|
+
}
|
|
2995
|
+
}
|
|
2996
|
+
if (options == null ? void 0 : options.injectCss) {
|
|
2997
|
+
const parser = new DOMParser();
|
|
2998
|
+
const _doc = parser.parseFromString(HTML2Render, "text/html");
|
|
2999
|
+
const styleTag = _doc.createElement("style");
|
|
3000
|
+
styleTag.setAttribute("data-myop-injected", "true");
|
|
3001
|
+
styleTag.textContent = options.injectCss.replace(/<\s*\/\s*style/gi, "<\\/style");
|
|
3002
|
+
(_doc.head || _doc.documentElement).appendChild(styleTag);
|
|
3003
|
+
HTML2Render = "<!DOCTYPE html>" + _doc.documentElement.outerHTML;
|
|
3004
|
+
}
|
|
3005
|
+
doc.writeln(HTML2Render);
|
|
3006
|
+
const sdkScript = HAS_EMBEDDED_SDK ? "<script>".concat(EMBEDDED_SDK_CONTENT, "<\/script>") : '<script src="'.concat(window.myop.__ROOT_SDK_PUBLIC_URL__, '"><\/script>');
|
|
3007
|
+
const initScript = HAS_EMBEDDED_SDK ? "<script>\n const __myop_init = async () => {\n const iframeModule = await MyopSDK.getIframeModule();\n const IframeSDK = iframeModule.IframeSDK;\n const sdk = new IframeSDK();\n sdk.init();\n }\n __myop_init().then();\n <\/script>" : "<script>\n window.__federation__.__public_path__ = window.__federation__.__public_path__;\n const __myop_init = async () => {\n const {IframeSDK} = (await window.myop.rootSDK.getIframeModule());\n const sdk = new IframeSDK();\n sdk.init();\n }\n __myop_init().then();\n <\/script>";
|
|
3008
|
+
if (!isolate) {
|
|
3009
|
+
doc.writeln("".concat(sdkScript).concat(initScript));
|
|
3010
|
+
}
|
|
3011
|
+
if (!isolate && (options == null ? void 0 : options.data) !== void 0) {
|
|
3012
|
+
const ctaQueueScript = "<script>\n window.__myop_cta_queue = [];\n window.myop_cta_handler = function(action, payload) {\n window.__myop_cta_queue.push({action: action, payload: payload});\n };\n <\/script>";
|
|
3013
|
+
const escapedData = JSON.stringify(options.data).replace(/<\/script/gi, "\\u003c/script");
|
|
3014
|
+
const dataScript = '<script id="__myop_init_data_script">\n (function() {\n var data = '.concat(escapedData, ";\n var scriptEl = document.getElementById('__myop_init_data_script');\n\n var callInitInterface = function(fn) {\n var startTime = performance.now();\n // Mark as pre-injected data call for extension tracking\n window.__myop_init_preinjected = true;\n try {\n fn(data);\n } finally {\n window.__myop_init_preinjected = false;\n }\n var duration = performance.now() - startTime;\n\n // Notify extension via postMessage (init* = pre-injected)\n try {\n window.parent.postMessage({\n type: 'MYOP_PREINJECTED_INIT',\n payload: {\n data: data,\n duration: duration,\n timestamp: Date.now()\n }\n }, '*');\n } catch (e) {}\n\n // Cleanup: remove script tag and stored data\n if (scriptEl && scriptEl.parentNode) {\n scriptEl.parentNode.removeChild(scriptEl);\n }\n delete window.__myop_init_data;\n };\n\n if (typeof window.myop_init_interface === 'function') {\n // Function already exists - call immediately\n callInitInterface(window.myop_init_interface);\n } else {\n // Function not yet defined - store data and watch for definition\n window.__myop_init_data = data;\n\n var _original;\n Object.defineProperty(window, 'myop_init_interface', {\n configurable: true,\n enumerable: true,\n set: function(fn) {\n _original = fn;\n if (window.__myop_init_data !== undefined) {\n var storedData = window.__myop_init_data;\n delete window.__myop_init_data;\n callInitInterface(fn);\n }\n },\n get: function() {\n return _original;\n }\n });\n }\n })();\n <\/script>");
|
|
3015
|
+
doc.writeln(ctaQueueScript + dataScript);
|
|
3016
|
+
}
|
|
3017
|
+
if (isolate) {
|
|
3018
|
+
const escapedData = (options == null ? void 0 : options.data) !== void 0 ? JSON.stringify(options.data).replace(/<\/script/gi, "\\u003c/script") : "undefined";
|
|
3019
|
+
doc.writeln(this.buildIsolationBridge(escapedData));
|
|
3020
|
+
}
|
|
3021
|
+
doc.close();
|
|
3022
|
+
const comp = new MyopIframeComponent(componentDefinition, skin, container, IframeElement, options);
|
|
3023
|
+
if (isolate) comp.enableIsolation();
|
|
3024
|
+
comp.sizeMeta = parsedSizeMeta;
|
|
3025
|
+
comp.initiated().then(() => {
|
|
3026
|
+
if ((options == null ? void 0 : options.autoSize) === false) {
|
|
3027
|
+
return;
|
|
3028
|
+
}
|
|
3029
|
+
let shown = false;
|
|
3030
|
+
comp.observeAutoSize({
|
|
3031
|
+
forceAutoSize: true,
|
|
3032
|
+
onSizeChange: () => {
|
|
3033
|
+
if (!shown && !(options == null ? void 0 : options.hidden)) {
|
|
3034
|
+
shown = true;
|
|
3035
|
+
comp.show();
|
|
3036
|
+
}
|
|
3037
|
+
}
|
|
3038
|
+
});
|
|
3039
|
+
});
|
|
3040
|
+
return comp;
|
|
3041
|
+
}
|
|
3042
|
+
if (loaderConfig.shadowRootMode === ShadowRootModeType.none) {
|
|
3043
|
+
const template = document.createElement("template");
|
|
3044
|
+
template.innerHTML = loaderConfig.HTML;
|
|
3045
|
+
element = template.content.firstElementChild;
|
|
3046
|
+
getInitiatedSdk().then((sdk2) => {
|
|
3047
|
+
sdk2.connectedCallback(element, element);
|
|
3048
|
+
});
|
|
3049
|
+
} else {
|
|
3050
|
+
const customElementName = toCustomElementName(componentDefinition.name + skin.id);
|
|
3051
|
+
if (!seen2.includes(customElementName)) {
|
|
3052
|
+
createCustomWebComponent(customElementName, loaderConfig.HTML, loaderConfig.shadowRootMode);
|
|
3053
|
+
seen2.push(customElementName);
|
|
3054
|
+
}
|
|
3055
|
+
element = document.createElement(customElementName);
|
|
3056
|
+
}
|
|
3057
|
+
if (!container.querySelector('[id^="myop-comp-"]'))
|
|
3058
|
+
container.innerHTML = "";
|
|
3059
|
+
element.id = domId;
|
|
3060
|
+
if (options == null ? void 0 : options.hidden) {
|
|
3061
|
+
element.style.opacity = "0";
|
|
3062
|
+
element.style.position = "absolute";
|
|
3063
|
+
element.style.height = "0";
|
|
3064
|
+
element.style.width = "0";
|
|
3065
|
+
element.style.pointerEvents = "none";
|
|
3066
|
+
element.style.visibility = "hidden";
|
|
3067
|
+
}
|
|
3068
|
+
this.appendChild(container, element, options);
|
|
3069
|
+
return new MyopWebComponent(componentDefinition, skin, container, element, options);
|
|
3070
|
+
});
|
|
2678
3071
|
}
|
|
2679
3072
|
/**
|
|
2680
|
-
*
|
|
2681
|
-
* the fetch already completed, null otherwise.
|
|
2682
|
-
*
|
|
2683
|
-
* Uses the same `this.variants` cache that fetchComponentV2/preloadComponents
|
|
2684
|
-
* populate. Each cached Promise is tagged with a `.resolved` property when
|
|
2685
|
-
* it settles — this method just reads that property. No separate cache.
|
|
2686
|
-
*
|
|
2687
|
-
* Why this exists: React Native needs the config at render time to embed it
|
|
2688
|
-
* in the WebView HTML (can't await in useState). If preloadComponents ran
|
|
2689
|
-
* earlier and the fetch completed, this returns the result synchronously,
|
|
2690
|
-
* skipping the WEBVIEW_READY → fetch → inject round trip entirely.
|
|
3073
|
+
* Detect if HTML is a Myop Web Component (starts with marker comment)
|
|
2691
3074
|
*/
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
const { cacheKey } = this.resolveParams(componentId, env, preview);
|
|
2695
|
-
return ((_a = this.variants[cacheKey]) == null ? void 0 : _a.resolved) || null;
|
|
3075
|
+
isMyopWebComponent(html) {
|
|
3076
|
+
return html.trimStart().startsWith(MYOP_WEB_COMPONENT_MARKER);
|
|
2696
3077
|
}
|
|
2697
3078
|
/**
|
|
2698
|
-
* Resolve
|
|
2699
|
-
*
|
|
2700
|
-
*
|
|
2701
|
-
*
|
|
2702
|
-
* hydrateComponent, so a hydrated config always lands on the key a later
|
|
2703
|
-
* fetch will look under.
|
|
3079
|
+
* Resolve how this component should render, applying the host render policy.
|
|
3080
|
+
* Precedence: options.renderPolicy (per-call) fully replaces the global
|
|
3081
|
+
* hostSDK.setRenderPolicy — so an app can restrict globally and allow specifics.
|
|
3082
|
+
* With no policy set, behavior is unchanged from before (marker ⇒ web component).
|
|
2704
3083
|
*/
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
const
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
env = preloaded.env;
|
|
2712
|
-
usePreview = preloaded.preview;
|
|
2713
|
-
} else {
|
|
2714
|
-
env = environmentIdentifier || this._defaultEnv;
|
|
2715
|
-
const hasEffectiveEnv = environmentIdentifier || this._envExplicitlySet;
|
|
2716
|
-
usePreview = preview === true ? true : preview === false ? false : !hasEffectiveEnv;
|
|
2717
|
-
}
|
|
2718
|
-
return { env, usePreview, cacheKey: "".concat(componentId, ":").concat(env, ":").concat(usePreview ? "preview" : "live") };
|
|
3084
|
+
async resolveRenderMode(componentDefinition, skin, loaderConfig, isWebComponent, options) {
|
|
3085
|
+
var _a, _b, _c, _d;
|
|
3086
|
+
const requestedMode = isWebComponent ? "webComponent" : loaderConfig.isolation || (options == null ? void 0 : options.isolation) ? "isolatedIframe" : "iframe";
|
|
3087
|
+
const policy = (_d = options == null ? void 0 : options.renderPolicy) != null ? _d : (_c = (_b = (_a = window == null ? void 0 : window.myop) == null ? void 0 : _a.hostSDK) == null ? void 0 : _b.getRenderPolicy) == null ? void 0 : _c.call(_b);
|
|
3088
|
+
const mode = policy ? await policy({ componentDefinition, skin, requestedMode, isWebComponent }) : requestedMode;
|
|
3089
|
+
return { mode, isolate: mode === "isolatedIframe" };
|
|
2719
3090
|
}
|
|
2720
3091
|
/**
|
|
2721
|
-
*
|
|
2722
|
-
*
|
|
2723
|
-
*
|
|
2724
|
-
*
|
|
2725
|
-
*
|
|
2726
|
-
*
|
|
2727
|
-
*
|
|
2728
|
-
* After hydrating, `fetchComponentV2`, `getResolvedConfig` and `isPreloaded`
|
|
2729
|
-
* all answer for this component from memory.
|
|
3092
|
+
* The in-frame bridge for isolated components. Runs inside the sandboxed
|
|
3093
|
+
* (opaque-origin) iframe, translating the same author-facing contract to/from
|
|
3094
|
+
* postMessage since the host has no same-origin access:
|
|
3095
|
+
* • data-in : parent posts {type:'myop:init'} → calls window.myop_init_interface
|
|
3096
|
+
* (plus a baked initial value for the first render)
|
|
3097
|
+
* • data-out: window.myop_cta_handler → parent.postMessage({type:'myop:cta'})
|
|
3098
|
+
* • resize : ResizeObserver → parent.postMessage({type:'myop:size'})
|
|
2730
3099
|
*
|
|
2731
|
-
*
|
|
2732
|
-
*
|
|
3100
|
+
* TODO(dev-extension): the isolated path deliberately skips the same-origin
|
|
3101
|
+
* dataScript, so it never posts the `MYOP_PREINJECTED_INIT` message the Myop dev
|
|
3102
|
+
* extension listens for to log the INITIAL render (`init*`). Later init updates and
|
|
3103
|
+
* all CTAs are still tracked (the extension wraps `comp.props`, which our isolated
|
|
3104
|
+
* connectProps branch routes through), so only the first-render payload is missing
|
|
3105
|
+
* from the extension's activity log for isolated components. Closing this would be a
|
|
3106
|
+
* ~1-line `parent.postMessage({type:'MYOP_PREINJECTED_INIT', payload:{data}})` inside
|
|
3107
|
+
* flushInitial() below — intentionally NOT done for now to avoid adding extension-only
|
|
3108
|
+
* traffic to the component runtime. Web components have the same initial-init gap
|
|
3109
|
+
* (initWithData is called on the element, not via comp.props) and it predates this.
|
|
2733
3110
|
*/
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
const promise = Promise.resolve(config);
|
|
2737
|
-
promise.resolved = config;
|
|
2738
|
-
this.variants[cacheKey] = promise;
|
|
2739
|
-
this.preloadedComponents[componentId] = { env: resolvedEnv, preview: usePreview };
|
|
3111
|
+
buildIsolationBridge(initialDataLiteral) {
|
|
3112
|
+
return "<script>\n (function () {\n var __initial = ".concat(initialDataLiteral, ";\n var __pending;\n // data-out (cta)\n window.myop_cta_handler = function (action, payload) {\n try { parent.postMessage({ __myop: true, type: 'myop:cta', action: action, payload: payload }, '*'); } catch (e) {}\n };\n function callInit(data) {\n if (typeof window.myop_init_interface === 'function') { window.myop_init_interface(data); return true; }\n return false;\n }\n // data-in (init updates)\n window.addEventListener('message', function (e) {\n var d = e.data;\n if (!d || d.__myop !== true) return;\n if (d.type === 'myop:init') { if (!callInit(d.data)) __pending = d.data; }\n });\n // first render: use a pending update if one arrived, else the baked initial data\n (function flushInitial() {\n var data = (__pending !== undefined) ? __pending : __initial;\n if (data === undefined) return;\n if (callInit(data)) { __pending = undefined; __initial = undefined; }\n else requestAnimationFrame(flushInitial);\n })();\n // resize (report content size)\n function contentHeight() {\n // Measure the BODY (content box). documentElement.scrollHeight includes\n // the iframe viewport \u2014 which we're driving \u2014 so it would report the\n // current frame height, not the content, and never shrink.\n var b = document.body;\n if (b) return Math.max(b.scrollHeight, b.offsetHeight);\n return document.documentElement.scrollHeight;\n }\n function postSize() {\n try {\n parent.postMessage({\n __myop: true, type: 'myop:size',\n height: contentHeight(),\n width: document.documentElement.scrollWidth\n }, '*');\n } catch (e) {}\n }\n // Observe the BODY (reflows with content) \u2014 not documentElement, whose box is\n // the iframe viewport and would feed back into a resize loop. A MutationObserver\n // catches content swaps (e.g. innerHTML re-render) that don't change body's box.\n if (window.ResizeObserver) {\n try { var __ro = new ResizeObserver(postSize); if (document.body) __ro.observe(document.body); } catch (e) {}\n }\n if (window.MutationObserver && document.body) {\n try { new MutationObserver(postSize).observe(document.body, { childList: true, subtree: true, attributes: true, characterData: true }); } catch (e) {}\n }\n window.addEventListener('load', postSize);\n postSize();\n })();\n <\/script>");
|
|
2740
3113
|
}
|
|
2741
|
-
// ============ V1 Methods (Legacy) ============
|
|
2742
3114
|
/**
|
|
2743
|
-
*
|
|
3115
|
+
* Extract the web component script content from HTML
|
|
2744
3116
|
*/
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
const flow = await this.fetchAutoFlow(componentId);
|
|
2751
|
-
return flow.components[0];
|
|
2752
|
-
}
|
|
3117
|
+
extractWebComponentScript(html) {
|
|
3118
|
+
const parser = new DOMParser();
|
|
3119
|
+
const doc = parser.parseFromString(html, "text/html");
|
|
3120
|
+
const script = doc.getElementById(MYOP_WEB_COMPONENT_SCRIPT_ID);
|
|
3121
|
+
return (script == null ? void 0 : script.textContent) || null;
|
|
2753
3122
|
}
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
resolve(json.item);
|
|
2764
|
-
} catch (e) {
|
|
2765
|
-
delete this.userFlows[componentId];
|
|
2766
|
-
reject(e);
|
|
2767
|
-
}
|
|
2768
|
-
}
|
|
2769
|
-
);
|
|
3123
|
+
/**
|
|
3124
|
+
* Execute the web component script on the host document.
|
|
3125
|
+
* Returns the custom element tag name this script registered.
|
|
3126
|
+
*/
|
|
3127
|
+
executeWebComponentScript(scriptContent, scriptId) {
|
|
3128
|
+
const cachedTagName = extractedWebComponentScripts.get(scriptId);
|
|
3129
|
+
if (cachedTagName) {
|
|
3130
|
+
console.log("[MyopWebComponent] Script already executed for ".concat(scriptId, ", reusing <").concat(cachedTagName, ">"));
|
|
3131
|
+
return cachedTagName;
|
|
2770
3132
|
}
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
const res = await fetch(
|
|
2779
|
-
"".concat(this._baseUrl, "/flow?id=").concat(flowId, "&resolve=components")
|
|
2780
|
-
);
|
|
2781
|
-
const json = await res.json();
|
|
2782
|
-
resolve(json.item);
|
|
2783
|
-
} catch (e) {
|
|
2784
|
-
delete this.userFlows[flowId];
|
|
2785
|
-
reject(e);
|
|
2786
|
-
}
|
|
2787
|
-
}
|
|
2788
|
-
);
|
|
3133
|
+
const script = document.createElement("script");
|
|
3134
|
+
script.textContent = scriptContent;
|
|
3135
|
+
script.id = "myop-extracted-".concat(scriptId);
|
|
3136
|
+
document.head.appendChild(script);
|
|
3137
|
+
const tagName = window.__MYOP_TAG_NAME__;
|
|
3138
|
+
if (tagName) {
|
|
3139
|
+
extractedWebComponentScripts.set(scriptId, tagName);
|
|
2789
3140
|
}
|
|
2790
|
-
|
|
3141
|
+
console.log("[MyopWebComponent] Executed web component script: ".concat(scriptId, " -> <").concat(tagName, ">"));
|
|
3142
|
+
return tagName;
|
|
2791
3143
|
}
|
|
2792
|
-
// ============ Backward Compatibility ============
|
|
2793
3144
|
/**
|
|
2794
|
-
*
|
|
2795
|
-
* Defaults to v1 behavior for backward compatibility with existing code
|
|
3145
|
+
* Load a Myop Web Component (extracted and run on host document)
|
|
2796
3146
|
*/
|
|
2797
|
-
async
|
|
2798
|
-
|
|
3147
|
+
async loadExtractedWebComponent(componentDefinition, skin, container, html, options) {
|
|
3148
|
+
const scriptContent = this.extractWebComponentScript(html);
|
|
3149
|
+
if (!scriptContent) {
|
|
3150
|
+
throw new Error('[MyopWebComponent] No <script id="myop-web-component"> found in HTML');
|
|
3151
|
+
}
|
|
3152
|
+
const scriptId = "".concat(componentDefinition.id, "-").concat(skin.id);
|
|
3153
|
+
const tagName = this.executeWebComponentScript(scriptContent, scriptId);
|
|
3154
|
+
if (!tagName) {
|
|
3155
|
+
throw new Error("[MyopWebComponent] Script did not set window.__MYOP_TAG_NAME__");
|
|
3156
|
+
}
|
|
3157
|
+
const domId = "myop-comp-".concat(uuidv4());
|
|
3158
|
+
const element = document.createElement(tagName);
|
|
3159
|
+
element.id = domId;
|
|
3160
|
+
if (options == null ? void 0 : options.hidden) {
|
|
3161
|
+
element.style.opacity = "0";
|
|
3162
|
+
element.style.position = "absolute";
|
|
3163
|
+
element.style.height = "0";
|
|
3164
|
+
element.style.width = "0";
|
|
3165
|
+
element.style.pointerEvents = "none";
|
|
3166
|
+
element.style.visibility = "hidden";
|
|
3167
|
+
}
|
|
3168
|
+
if (!container.querySelector('[id^="myop-comp-"]')) {
|
|
3169
|
+
container.innerHTML = "";
|
|
3170
|
+
}
|
|
3171
|
+
this.appendChild(container, element, options);
|
|
3172
|
+
const component = new MyopExtractedWebComponent(
|
|
3173
|
+
componentDefinition,
|
|
3174
|
+
skin,
|
|
3175
|
+
container,
|
|
3176
|
+
element,
|
|
3177
|
+
tagName,
|
|
3178
|
+
options
|
|
3179
|
+
);
|
|
3180
|
+
if ((options == null ? void 0 : options.data) !== void 0) {
|
|
3181
|
+
component.initWithData(options.data);
|
|
3182
|
+
}
|
|
3183
|
+
console.log("[MyopWebComponent] Loaded <".concat(tagName, "> into container"));
|
|
3184
|
+
return component;
|
|
2799
3185
|
}
|
|
2800
3186
|
};
|
|
2801
|
-
__publicField(_CloudRepository, "_main", null);
|
|
2802
|
-
var CloudRepository = _CloudRepository;
|
|
2803
|
-
|
|
2804
|
-
// src/helpers/cloudRepositoryHelpers.ts
|
|
2805
|
-
var _cloudRepository = CloudRepository.Main;
|
|
2806
3187
|
|
|
2807
3188
|
// src/host/myopOverride.ts
|
|
2808
3189
|
var checkMyopOverride = async (componentConfig) => {
|
|
@@ -2898,8 +3279,22 @@ var HostSDK = class {
|
|
|
2898
3279
|
}
|
|
2899
3280
|
});
|
|
2900
3281
|
});
|
|
3282
|
+
// A component's origin is whatever its iframe URL is, so an origin allowlist can't work here.
|
|
3283
|
+
// Instead only frames this SDK created (or adopted) may talk to it. `send()` dispatches
|
|
3284
|
+
// synthetic events, which have no source.
|
|
3285
|
+
__publicField(this, "isTrustedSource", (source) => {
|
|
3286
|
+
if (!source || source === window) return true;
|
|
3287
|
+
const isOwnFrame = (component) => {
|
|
3288
|
+
const element = component.element;
|
|
3289
|
+
return (element == null ? void 0 : element.nodeName) === "IFRAME" && element.contentWindow === source;
|
|
3290
|
+
};
|
|
3291
|
+
return this.components.some(isOwnFrame) || this.components2init.some(isOwnFrame);
|
|
3292
|
+
});
|
|
2901
3293
|
__publicField(this, "incomingMessageHandler", (event) => {
|
|
2902
|
-
|
|
3294
|
+
var _a;
|
|
3295
|
+
if (!((_a = event.data) == null ? void 0 : _a.myop)) return;
|
|
3296
|
+
if (!this.isTrustedSource(event.source)) {
|
|
3297
|
+
return;
|
|
2903
3298
|
}
|
|
2904
3299
|
if (event.data.myop) {
|
|
2905
3300
|
if (event.data.direction !== MessageDirection.up && event.data.messageType !== MyopMessages.EnvelopedMessage) {
|
|
@@ -2915,8 +3310,8 @@ var HostSDK = class {
|
|
|
2915
3310
|
if (myopMessage.messageType === MyopMessages.InitResponse) {
|
|
2916
3311
|
this.components2init = this.components2init.filter((component2) => component2.id !== myopMessage.content.id);
|
|
2917
3312
|
const initiatedComponent = this.components.find((component2) => {
|
|
2918
|
-
var
|
|
2919
|
-
return component2.id === ((
|
|
3313
|
+
var _a2;
|
|
3314
|
+
return component2.id === ((_a2 = myopMessage.content) == null ? void 0 : _a2.id);
|
|
2920
3315
|
});
|
|
2921
3316
|
initiatedComponent == null ? void 0 : initiatedComponent.setInitiated();
|
|
2922
3317
|
return;
|
|
@@ -2969,7 +3364,10 @@ var HostSDK = class {
|
|
|
2969
3364
|
});
|
|
2970
3365
|
__publicField(this, "init", (customComponentLoaderCreators) => {
|
|
2971
3366
|
if (this.initiated) {
|
|
2972
|
-
|
|
3367
|
+
if (customComponentLoaderCreators == null ? void 0 : customComponentLoaderCreators.length) {
|
|
3368
|
+
this._registerLoaders(customComponentLoaderCreators);
|
|
3369
|
+
}
|
|
3370
|
+
return;
|
|
2973
3371
|
}
|
|
2974
3372
|
const basicLoaders = [
|
|
2975
3373
|
new MyopIframeLoader(),
|
|
@@ -2980,16 +3378,7 @@ var HostSDK = class {
|
|
|
2980
3378
|
...basicLoaders
|
|
2981
3379
|
];
|
|
2982
3380
|
if (customComponentLoaderCreators) {
|
|
2983
|
-
|
|
2984
|
-
customComponentLoaderCreators.forEach((customComponentLoaderCreator) => {
|
|
2985
|
-
const customLoader = new customComponentLoaderCreator(this.componentsLoaders);
|
|
2986
|
-
loaderByType[customLoader.type] = customLoader;
|
|
2987
|
-
});
|
|
2988
|
-
this.componentsLoaders.forEach((loader) => {
|
|
2989
|
-
if (!loaderByType[loader.type])
|
|
2990
|
-
loaderByType[loader.type] = loader;
|
|
2991
|
-
});
|
|
2992
|
-
this.componentsLoaders = Object.values(loaderByType);
|
|
3381
|
+
this._registerLoaders(customComponentLoaderCreators);
|
|
2993
3382
|
}
|
|
2994
3383
|
window.addEventListener(
|
|
2995
3384
|
"message",
|
|
@@ -2999,6 +3388,18 @@ var HostSDK = class {
|
|
|
2999
3388
|
console.log("myop hostSDK initiated", document.location.href);
|
|
3000
3389
|
this.initiated = true;
|
|
3001
3390
|
});
|
|
3391
|
+
__publicField(this, "_registerLoaders", (customComponentLoaderCreators) => {
|
|
3392
|
+
const loaderByType = {};
|
|
3393
|
+
customComponentLoaderCreators.forEach((customComponentLoaderCreator) => {
|
|
3394
|
+
const customLoader = new customComponentLoaderCreator(this.componentsLoaders);
|
|
3395
|
+
loaderByType[customLoader.type] = customLoader;
|
|
3396
|
+
});
|
|
3397
|
+
this.componentsLoaders.forEach((loader) => {
|
|
3398
|
+
if (!loaderByType[loader.type])
|
|
3399
|
+
loaderByType[loader.type] = loader;
|
|
3400
|
+
});
|
|
3401
|
+
this.componentsLoaders = Object.values(loaderByType);
|
|
3402
|
+
});
|
|
3002
3403
|
__publicField(this, "_getSkinIdBySkinSelector", async (skinSelector, experiences = [], hooks) => {
|
|
3003
3404
|
var _a;
|
|
3004
3405
|
async function asyncFind(array, predicate) {
|
|
@@ -3179,6 +3580,13 @@ if (!window.myop.hostSDK) {
|
|
|
3179
3580
|
}
|
|
3180
3581
|
window.myop.hostSDK = _hostSDK;
|
|
3181
3582
|
}
|
|
3583
|
+
if (window.myop && !window.myop.delivery) {
|
|
3584
|
+
const api = (opts) => delivery(opts);
|
|
3585
|
+
api.stats = deliveryStats;
|
|
3586
|
+
api.off = deliveryOff;
|
|
3587
|
+
api.refresh = deliveryRefresh;
|
|
3588
|
+
window.myop.delivery = api;
|
|
3589
|
+
}
|
|
3182
3590
|
var hostSDK = window.myop.hostSDK;
|
|
3183
3591
|
defineDynamicImport("hostSDK", hostSDK);
|
|
3184
3592
|
|