@inkandswitch/patchwork-pkg-base 0.0.73 → 0.0.74

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 (31) hide show
  1. package/module-settings-url +1 -1
  2. package/package.json +1 -1
  3. package/packages/chat/dist/{ChatRoot-BRiX2ym6.js → ChatRoot-BYmq4SXi.js} +3541 -6287
  4. package/packages/chat/dist/{context-tool-CAHkp64h.js → context-tool-Bob-FZ_T.js} +2 -2
  5. package/packages/chat/dist/{index-Bt9HfG9I.js → index-wkaHcVCz.js} +3 -3
  6. package/packages/chat/dist/index.js +1 -1
  7. package/packages/chat/dist/{tool-DoxHbcfW.js → tool-DCOdh_fx.js} +1 -1
  8. package/packages/chat/package.json +3 -3
  9. package/packages/isolation/dist/assets/{component-DA0d3480.js → component-Daum8ibW.js} +118 -240
  10. package/packages/isolation/dist/assets/component-Daum8ibW.js.map +1 -0
  11. package/packages/isolation/dist/index.js +1 -1
  12. package/packages/threepane/dist/IsolatedDocumentArea-54ZI7TNY.js +2 -0
  13. package/packages/threepane/dist/PatchworkFrame-REYVVXOP.js +2 -0
  14. package/packages/threepane/dist/PatchworkFrame-REYVVXOP.js.map +7 -0
  15. package/packages/threepane/dist/{chunk-FX3MJIE5.js → chunk-DV7PRUYR.js} +3 -3
  16. package/packages/threepane/dist/chunk-DV7PRUYR.js.map +7 -0
  17. package/packages/threepane/dist/chunk-ESMUVHPH.js +2 -0
  18. package/packages/threepane/dist/chunk-ESMUVHPH.js.map +7 -0
  19. package/packages/threepane/dist/{datatypes-WPL4KARJ.js → datatypes-5DFL6VIN.js} +2 -2
  20. package/packages/threepane/dist/index.js +1 -1
  21. package/plugin-registry-url +1 -1
  22. package/packages/chat/dist/assets/worker-CFUOJ0Hd.js +0 -9
  23. package/packages/isolation/dist/assets/component-DA0d3480.js.map +0 -1
  24. package/packages/threepane/dist/IsolatedDocumentArea-MSJE4GCW.js +0 -2
  25. package/packages/threepane/dist/PatchworkFrame-3XYJCU3F.js +0 -2
  26. package/packages/threepane/dist/PatchworkFrame-3XYJCU3F.js.map +0 -7
  27. package/packages/threepane/dist/chunk-2NJMYYSD.js +0 -2
  28. package/packages/threepane/dist/chunk-2NJMYYSD.js.map +0 -7
  29. package/packages/threepane/dist/chunk-FX3MJIE5.js.map +0 -7
  30. /package/packages/threepane/dist/{IsolatedDocumentArea-MSJE4GCW.js.map → IsolatedDocumentArea-54ZI7TNY.js.map} +0 -0
  31. /package/packages/threepane/dist/{datatypes-WPL4KARJ.js.map → datatypes-5DFL6VIN.js.map} +0 -0
@@ -1068,7 +1068,9 @@ function rewriteAutomergeDepsInSource(source, mapper) {
1068
1068
  }
1069
1069
  function markerNameFromUrl(url) {
1070
1070
  const { first } = splitFirstSegment(url);
1071
- return first.startsWith(REGISTRY_MARKER_PREFIX) ? first : null;
1071
+ if (!first.startsWith(REGISTRY_MARKER_PREFIX)) return null;
1072
+ const { pkg } = splitMarkerHeads(first.slice(REGISTRY_MARKER_PREFIX.length));
1073
+ return `${REGISTRY_MARKER_PREFIX}${pkg}`;
1072
1074
  }
1073
1075
  function resolvePackageRequest(url, mapper) {
1074
1076
  return mapper.resolveMarker(url) ?? url;
@@ -1637,27 +1639,46 @@ function startHostDragDropBridge(rpcPort, getIframe, allowlistDrop) {
1637
1639
  };
1638
1640
  }
1639
1641
 
1642
+ function resolveGatedAttribute(element, attribute, allowed, label = attribute) {
1643
+ const requested = (element.getAttribute(attribute) ?? "").split(",").map((s) => s.trim()).filter(Boolean);
1644
+ const granted = [];
1645
+ for (const entry of requested) {
1646
+ if (allowed.includes(entry)) {
1647
+ granted.push(entry);
1648
+ } else {
1649
+ console.warn(
1650
+ `[patchwork-isolation] ${label}: "${entry}" is not permitted. New entries need independent security analysis before being added.`
1651
+ );
1652
+ }
1653
+ }
1654
+ return granted;
1655
+ }
1656
+
1640
1657
  const ALLOWED_PROVIDERS = [
1641
1658
  "patchwork:contact",
1642
1659
  "patchwork:selected-doc",
1643
1660
  // The active theme id (a plain string). Carries no automerge URLs or user
1644
1661
  // identity, so it is safe to relay into the iframe; lets isolated tools
1645
1662
  // (e.g. the titlebar theme tool) mirror the host's active theme.
1646
- "patchwork:current-theme"
1663
+ "patchwork:current-theme",
1664
+ // A worker connection. The worker runs on the host and only its
1665
+ // `{readable, writable}` pair is transferred in, so its config and secrets
1666
+ // stay out here. This allows every worker kind, but each subscription has its
1667
+ // own port, so a tool only gets the streams for the worker it asked for.
1668
+ "patchwork:worker-channel"
1647
1669
  ];
1648
- function resolveBridgedProviders(element) {
1649
- const requested = (element.getAttribute("shared-providers") ?? "").split(",").map((s) => s.trim()).filter(Boolean);
1650
- const bridged = [];
1651
- for (const provider of requested) {
1652
- if (ALLOWED_PROVIDERS.includes(provider)) {
1653
- bridged.push(provider);
1654
- } else {
1655
- console.warn(
1656
- `[patchwork-isolation] shared-providers: "${provider}" is not in ALLOWED_PROVIDERS. New provider types need independent security analysis before being added.`
1657
- );
1670
+ function transferablesIn(value) {
1671
+ if (!value || typeof value !== "object") return [];
1672
+ const out = [];
1673
+ for (const candidate of Object.values(value)) {
1674
+ if (candidate instanceof ReadableStream || candidate instanceof WritableStream || candidate instanceof MessagePort || candidate instanceof ArrayBuffer) {
1675
+ out.push(candidate);
1658
1676
  }
1659
1677
  }
1660
- return bridged;
1678
+ return out;
1679
+ }
1680
+ function resolveBridgedProviders(element) {
1681
+ return resolveGatedAttribute(element, "shared-providers", ALLOWED_PROVIDERS);
1661
1682
  }
1662
1683
  function makeBridgedValueFilter(checks) {
1663
1684
  return async (selectorType, value) => {
@@ -1700,11 +1721,14 @@ function startHostProvidersBridge(rpcPort, hostElement, allowedTypes = [], value
1700
1721
  if (e.data?.type === "change") {
1701
1722
  const value = valueFilter ? await valueFilter(selector.type, e.data.value) : e.data.value;
1702
1723
  if (value === void 0) return;
1703
- rpcPort.postMessage({
1704
- type: "providers-bridge-change",
1705
- id,
1706
- value
1707
- });
1724
+ rpcPort.postMessage(
1725
+ {
1726
+ type: "providers-bridge-change",
1727
+ id,
1728
+ value
1729
+ },
1730
+ transferablesIn(value)
1731
+ );
1708
1732
  }
1709
1733
  });
1710
1734
  hostPort.start();
@@ -1744,6 +1768,36 @@ function startHostProvidersBridge(rpcPort, hostElement, allowedTypes = [], value
1744
1768
  };
1745
1769
  }
1746
1770
 
1771
+ const ALLOWED_OPEN_TOOLS = ["llm-config-tray"];
1772
+ function resolveSharedTools(element) {
1773
+ return resolveGatedAttribute(element, "shared-tools", ALLOWED_OPEN_TOOLS);
1774
+ }
1775
+ function startHostOpenToolBridge(rpcPort, hostElement, allowedComponents = []) {
1776
+ const allowed = new Set(allowedComponents);
1777
+ const onMessage = (event) => {
1778
+ const msg = event.data;
1779
+ if (msg?.type !== "open-tool") return;
1780
+ const detail = msg.detail;
1781
+ const component = detail?.component;
1782
+ if (!component || !allowed.has(component)) {
1783
+ log(`open-tool rejected: ${component}`);
1784
+ return;
1785
+ }
1786
+ log(`open-tool: ${component}`);
1787
+ hostElement.dispatchEvent(
1788
+ new CustomEvent("patchwork:open-tool", {
1789
+ detail,
1790
+ bubbles: true,
1791
+ composed: true
1792
+ })
1793
+ );
1794
+ };
1795
+ rpcPort.addEventListener("message", onMessage);
1796
+ return () => {
1797
+ rpcPort.removeEventListener("message", onMessage);
1798
+ };
1799
+ }
1800
+
1747
1801
  async function boot(deps) {
1748
1802
  const {
1749
1803
  installLocalStorageStub,
@@ -1752,8 +1806,6 @@ async function boot(deps) {
1752
1806
  createRpcClient,
1753
1807
  createProvidersBridge,
1754
1808
  setupEsModuleShims,
1755
- installWorkerShim,
1756
- workerBootstrapSource,
1757
1809
  createRegistry,
1758
1810
  createRootComponentData,
1759
1811
  createDragDrop
@@ -1808,7 +1860,11 @@ async function boot(deps) {
1808
1860
  });
1809
1861
  rpcPort = init.rpcPort;
1810
1862
  rpc = createRpcClient(rpcPort);
1811
- providers = createProvidersBridge(rpcPort, log);
1863
+ providers = createProvidersBridge(
1864
+ rpcPort,
1865
+ log,
1866
+ init.data.bridgedProviders ?? []
1867
+ );
1812
1868
  registry = createRegistry(log);
1813
1869
  rootComponentData = createRootComponentData(log);
1814
1870
  dragDrop = createDragDrop(log);
@@ -1821,6 +1877,13 @@ async function boot(deps) {
1821
1877
  }),
1822
1878
  true
1823
1879
  );
1880
+ document.addEventListener(
1881
+ "patchwork:open-tool",
1882
+ ((event) => {
1883
+ rpcPort.postMessage({ type: "open-tool", detail: event.detail });
1884
+ }),
1885
+ true
1886
+ );
1824
1887
  const d = init.data;
1825
1888
  log("init", { root: d.rootComponentId });
1826
1889
  if (d.hostStyles) {
@@ -1859,15 +1922,6 @@ async function boot(deps) {
1859
1922
  const hostOrigin = d.hostOrigin;
1860
1923
  installFetchProxy(hostOrigin, rpc.fetchResource, log);
1861
1924
  installLinkInterception(hostOrigin, log);
1862
- installWorkerShim({
1863
- fetchModule: rpc.fetchModule,
1864
- fetchResource: rpc.fetchResource,
1865
- esmsSource: d.esmsSource,
1866
- workerBootstrapSource,
1867
- importMap: d.importMap,
1868
- hostOrigin,
1869
- log
1870
- });
1871
1925
  const syncAdapter = new messagechannel.MessageChannelNetworkAdapter(
1872
1926
  init.syncPort
1873
1927
  );
@@ -2054,7 +2108,8 @@ function createRpcClient(port) {
2054
2108
  return { fetchModule, fetchResource, handle };
2055
2109
  }
2056
2110
 
2057
- function createProvidersBridge(rpcPort, log) {
2111
+ function createProvidersBridge(rpcPort, log, bridgedTypes = []) {
2112
+ const bridged = new Set(bridgedTypes);
2058
2113
  const bridgedSubscriptions = /* @__PURE__ */ new Map();
2059
2114
  let bridgeId = 0;
2060
2115
  function handle(event) {
@@ -2064,13 +2119,29 @@ function createProvidersBridge(rpcPort, log) {
2064
2119
  log("providers-bridge: received change for id:", msg.id, "value:", msg.value);
2065
2120
  const port = bridgedSubscriptions.get(msg.id);
2066
2121
  if (port) {
2067
- port.postMessage({ type: "change", value: msg.value });
2122
+ const transfer = [];
2123
+ const value = msg.value;
2124
+ if (value && typeof value === "object") {
2125
+ for (const candidate of Object.values(
2126
+ value
2127
+ )) {
2128
+ if (candidate instanceof ReadableStream || candidate instanceof WritableStream || candidate instanceof MessagePort || candidate instanceof ArrayBuffer) {
2129
+ transfer.push(candidate);
2130
+ }
2131
+ }
2132
+ }
2133
+ port.postMessage({ type: "change", value }, transfer);
2068
2134
  }
2069
2135
  return true;
2070
2136
  }
2071
2137
  if (msg.type === "providers-bridge-rejected") {
2072
2138
  log("providers-bridge: rejected by host for id:", msg.id);
2139
+ const port = bridgedSubscriptions.get(msg.id);
2073
2140
  bridgedSubscriptions.delete(msg.id);
2141
+ if (port) {
2142
+ port.postMessage({ type: "unavailable", reason: "rejected" });
2143
+ port.close();
2144
+ }
2074
2145
  return true;
2075
2146
  }
2076
2147
  return false;
@@ -2079,6 +2150,10 @@ function createProvidersBridge(rpcPort, log) {
2079
2150
  document.addEventListener("patchwork:subscribe", ((event) => {
2080
2151
  const detail = event.detail;
2081
2152
  if (!detail?.selector?.type || !detail?.port) return;
2153
+ if (!bridged.has(detail.selector.type)) {
2154
+ log("providers-bridge: not bridged, leaving unclaimed:", detail.selector.type);
2155
+ return;
2156
+ }
2082
2157
  log("providers-bridge: captured unclaimed subscription:", detail.selector.type, detail.selector);
2083
2158
  event.stopPropagation();
2084
2159
  const id = ++bridgeId;
@@ -2132,209 +2207,6 @@ async function setupEsModuleShims(config) {
2132
2207
  return importShim;
2133
2208
  }
2134
2209
 
2135
- function installWorkerShim(deps) {
2136
- const {
2137
- fetchModule,
2138
- fetchResource,
2139
- esmsSource,
2140
- workerBootstrapSource,
2141
- importMap,
2142
- hostOrigin,
2143
- log
2144
- } = deps;
2145
- const OriginalWorker = self.Worker;
2146
- function shouldIntercept(url, isModule) {
2147
- return isModule && (url.startsWith(hostOrigin + "/") || url.startsWith("blob:"));
2148
- }
2149
- self.Worker = function PatchedWorker(scriptURL, options) {
2150
- const url = typeof scriptURL === "string" ? scriptURL : scriptURL.toString();
2151
- if (!shouldIntercept(url, options?.type === "module")) {
2152
- return new OriginalWorker(scriptURL, options);
2153
- }
2154
- log("worker shim: intercepting", url.slice(0, 80));
2155
- const channel = new MessageChannel();
2156
- channel.port1.addEventListener("message", (event) => {
2157
- const m = event.data;
2158
- if (m?.type === "fetch-package")
2159
- relay(fetchModule(m.url), "fetch-package", m.id);
2160
- else if (m?.type === "fetch-resource")
2161
- relay(fetchResource(m.url), "fetch-resource", m.id);
2162
- });
2163
- channel.port1.start();
2164
- function relay(work, type, id) {
2165
- work.then(
2166
- (r) => {
2167
- const transfer = type === "fetch-resource" ? [r.body] : [];
2168
- channel.port1.postMessage(
2169
- { type: `${type}-response`, id, ...r },
2170
- transfer
2171
- );
2172
- },
2173
- (err) => channel.port1.postMessage({
2174
- type: `${type}-error`,
2175
- id,
2176
- error: err instanceof Error ? err.message : String(err)
2177
- })
2178
- );
2179
- }
2180
- const worker = buildHarnessWorker();
2181
- resolveEntry(url).then(
2182
- (entrySource) => worker.postMessage(
2183
- { type: "isolation-relay-port", entryUrl: url, entrySource },
2184
- [channel.port2]
2185
- ),
2186
- (err) => {
2187
- log("worker shim: failed to load entry source", err);
2188
- worker.postMessage({
2189
- type: "isolation-relay-error",
2190
- error: err instanceof Error ? err.message : String(err)
2191
- });
2192
- }
2193
- );
2194
- return worker;
2195
- };
2196
- async function resolveEntry(url) {
2197
- if (!url.startsWith("blob:")) return void 0;
2198
- return (await fetch(url)).text();
2199
- }
2200
- function buildHarnessWorker() {
2201
- const params = { importMap, hostOrigin };
2202
- const blobSource = [
2203
- `(${workerBootstrapSource})(${JSON.stringify(params)});`,
2204
- esmsSource,
2205
- `self.__isolationWorkerStart().catch((e) => { throw e; });`
2206
- ].join("\n");
2207
- const blobUrl = URL.createObjectURL(
2208
- new Blob([blobSource], { type: "text/javascript" })
2209
- );
2210
- const worker = new OriginalWorker(blobUrl);
2211
- setTimeout(() => URL.revokeObjectURL(blobUrl), 1e4);
2212
- return worker;
2213
- }
2214
- }
2215
-
2216
- function workerBootstrap(params) {
2217
- let appHandler = null;
2218
- const appBuffer = [];
2219
- try {
2220
- Object.defineProperty(self, "onmessage", {
2221
- configurable: true,
2222
- get: () => appHandler,
2223
- set(fn) {
2224
- appHandler = fn;
2225
- if (fn) for (const ev of appBuffer.splice(0)) fn(ev);
2226
- }
2227
- });
2228
- } catch {
2229
- }
2230
- let relayPort;
2231
- let reqId = 0;
2232
- const pending = /* @__PURE__ */ new Map();
2233
- const relayReady = new Promise((resolve, reject) => {
2234
- self.addEventListener("message", (event) => {
2235
- const m = event.data;
2236
- if (m && m.type === "isolation-relay-port") {
2237
- resolve({
2238
- port: event.ports[0],
2239
- entryUrl: m.entryUrl,
2240
- entrySource: m.entrySource
2241
- });
2242
- } else if (m && m.type === "isolation-relay-error") {
2243
- reject(new Error(m.error));
2244
- } else if (appHandler) {
2245
- appHandler(event);
2246
- } else {
2247
- appBuffer.push(event);
2248
- }
2249
- });
2250
- });
2251
- function request(type, url) {
2252
- return new Promise((resolve, reject) => {
2253
- const id = ++reqId;
2254
- pending.set(id, { resolve, reject });
2255
- relayPort.postMessage({ type, id, url });
2256
- });
2257
- }
2258
- function onRelayMessage(event) {
2259
- const m = event.data;
2260
- if (!m || typeof m.id !== "number") return;
2261
- const p = pending.get(m.id);
2262
- if (!p) return;
2263
- pending.delete(m.id);
2264
- if (m.type === "fetch-package-response")
2265
- p.resolve({ source: m.source, resolvedUrl: m.resolvedUrl });
2266
- else if (m.type === "fetch-resource-response")
2267
- p.resolve({ body: m.body, contentType: m.contentType });
2268
- else if (m.type.endsWith("-error")) p.reject(new Error(m.error));
2269
- }
2270
- function fixImportMethod(src) {
2271
- return src.replace(
2272
- /^(\s+)import\s*\(([^)]*)\)\s*\{/gm,
2273
- '$1["import"]($2) {'
2274
- );
2275
- }
2276
- let blobEntry;
2277
- self.esmsInitOptions = {
2278
- shimMode: true,
2279
- async source(url) {
2280
- if (blobEntry && url === blobEntry.url) {
2281
- return {
2282
- source: fixImportMethod(blobEntry.source),
2283
- url: blobEntry.url,
2284
- type: "js"
2285
- };
2286
- }
2287
- if (url.startsWith(params.hostOrigin + "/")) {
2288
- const r = await request(
2289
- "fetch-package",
2290
- url
2291
- );
2292
- return {
2293
- source: fixImportMethod(r.source),
2294
- url: r.resolvedUrl,
2295
- type: "js"
2296
- };
2297
- }
2298
- const res = await fetch(url);
2299
- if (!res.ok) throw new Error(`worker source ${url}: HTTP ${res.status}`);
2300
- return {
2301
- source: await res.text(),
2302
- url: res.url || url,
2303
- type: "js"
2304
- };
2305
- }
2306
- };
2307
- self.__isolationWorkerStart = async function start() {
2308
- const importShim = self.importShim;
2309
- if (!importShim)
2310
- throw new Error("worker: es-module-shims failed to initialize");
2311
- const init = await relayReady;
2312
- relayPort = init.port;
2313
- relayPort.addEventListener("message", onRelayMessage);
2314
- relayPort.start();
2315
- if (params.importMap) importShim.addImportMap(params.importMap);
2316
- const nativeFetch = self.fetch;
2317
- self.fetch = async (input, fetchInit) => {
2318
- const u = typeof input === "string" ? input : input.toString();
2319
- if (u.startsWith(params.hostOrigin)) {
2320
- const r = await request(
2321
- "fetch-resource",
2322
- u
2323
- );
2324
- return new Response(r.body, {
2325
- status: 200,
2326
- headers: { "Content-Type": r.contentType }
2327
- });
2328
- }
2329
- return nativeFetch(input, fetchInit);
2330
- };
2331
- if (init.entrySource !== void 0) {
2332
- blobEntry = { url: init.entryUrl, source: init.entrySource };
2333
- }
2334
- await importShim(init.entryUrl);
2335
- };
2336
- }
2337
-
2338
2210
  function createRegistry(log) {
2339
2211
  let pending = [];
2340
2212
  let importShim;
@@ -2499,8 +2371,6 @@ function generateIframeSrcdoc(appearance) {
2499
2371
  createRpcClient: ${createRpcClient.toString()},
2500
2372
  createProvidersBridge: ${createProvidersBridge.toString()},
2501
2373
  setupEsModuleShims: ${setupEsModuleShims.toString()},
2502
- installWorkerShim: ${installWorkerShim.toString()},
2503
- workerBootstrapSource: ${JSON.stringify(workerBootstrap.toString())},
2504
2374
  createRegistry: ${createRegistry.toString()},
2505
2375
  createRootComponentData: ${createRootComponentData.toString()},
2506
2376
  createDragDrop: ${createDragDrop.toString()},
@@ -2670,6 +2540,7 @@ function bootIsolation(host) {
2670
2540
  });
2671
2541
  log("intermediary repo and allowlist ready");
2672
2542
  const bridgedProviders = resolveBridgedProviders(host);
2543
+ const sharedTools = resolveSharedTools(host);
2673
2544
  const bridgedValueFilter = makeBridgedValueFilter({
2674
2545
  isAllowed: (url) => allowlist.hasUrl(url),
2675
2546
  requestAccess: (url) => requestBridgedUrlAccess(
@@ -2705,11 +2576,14 @@ function bootIsolation(host) {
2705
2576
  bridgedProviders,
2706
2577
  bridgedValueFilter
2707
2578
  ),
2579
+ // Lets an isolated tool open a host tool, like the LLM config tray.
2580
+ startHostOpenToolBridge(hostRpcPort, host, sharedTools),
2708
2581
  watchRegistries(hostRpcPort, mapper)
2709
2582
  );
2710
2583
  createIframe(rpcChannel.port2, intermediary.iframePort, mapper, assets, {
2711
2584
  rootComponentId,
2712
- importMap
2585
+ importMap,
2586
+ bridgedProviders
2713
2587
  });
2714
2588
  }
2715
2589
  function createIframe(rpcPort, syncPort, mapper, assets, config) {
@@ -2737,6 +2611,9 @@ function bootIsolation(host) {
2737
2611
  // initial boot rather than lost, since a pre-port push no-ops.
2738
2612
  rootComponentData: readRootComponentData(host),
2739
2613
  registryEntries,
2614
+ // The iframe only claims these, so other selectors can still reach a
2615
+ // provider inside the iframe.
2616
+ bridgedProviders: config.bridgedProviders,
2740
2617
  esmsSource: assets.esmsSource,
2741
2618
  hostStyles: assets.hostStyles,
2742
2619
  importMap: config.importMap,
@@ -2825,7 +2702,8 @@ const mountIsolation = (element) => {
2825
2702
  attributeFilter: [
2826
2703
  "root-component",
2827
2704
  "automerge-allowlist",
2828
- "shared-providers"
2705
+ "shared-providers",
2706
+ "shared-tools"
2829
2707
  ]
2830
2708
  });
2831
2709
  return () => {
@@ -2836,4 +2714,4 @@ const mountIsolation = (element) => {
2836
2714
  };
2837
2715
 
2838
2716
  export { mountIsolation };
2839
- //# sourceMappingURL=component-DA0d3480.js.map
2717
+ //# sourceMappingURL=component-Daum8ibW.js.map