@makeswift/runtime 0.27.0-canary.2 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/cjs/api-handler/handlers/manifest.js +1 -1
  2. package/dist/cjs/client/index.js +3 -3
  3. package/dist/cjs/runtimes/react/components/RuntimeProvider.js +0 -2
  4. package/dist/cjs/runtimes/react/components/RuntimeProvider.js.map +1 -1
  5. package/dist/cjs/runtimes/react/components/preview-switcher/preview-switcher.js +20 -11
  6. package/dist/cjs/runtimes/react/components/preview-switcher/preview-switcher.js.map +1 -1
  7. package/dist/cjs/state/actions/internal/read-write-actions.js +7 -1
  8. package/dist/cjs/state/actions/internal/read-write-actions.js.map +1 -1
  9. package/dist/cjs/state/builder-api/message-channel.js +32 -0
  10. package/dist/cjs/state/builder-api/message-channel.js.map +1 -1
  11. package/dist/cjs/state/makeswift-api-client.js +20 -1
  12. package/dist/cjs/state/makeswift-api-client.js.map +1 -1
  13. package/dist/cjs/state/modules/api-resources.js +3 -0
  14. package/dist/cjs/state/modules/api-resources.js.map +1 -1
  15. package/dist/cjs/state/modules/localized-resources-map.js +3 -0
  16. package/dist/cjs/state/modules/localized-resources-map.js.map +1 -1
  17. package/dist/esm/api-handler/handlers/manifest.js +1 -1
  18. package/dist/esm/client/index.js +3 -3
  19. package/dist/esm/runtimes/react/components/RuntimeProvider.js +0 -2
  20. package/dist/esm/runtimes/react/components/RuntimeProvider.js.map +1 -1
  21. package/dist/esm/runtimes/react/components/preview-switcher/preview-switcher.js +20 -11
  22. package/dist/esm/runtimes/react/components/preview-switcher/preview-switcher.js.map +1 -1
  23. package/dist/esm/state/actions/internal/read-write-actions.js +6 -1
  24. package/dist/esm/state/actions/internal/read-write-actions.js.map +1 -1
  25. package/dist/esm/state/builder-api/message-channel.js +32 -0
  26. package/dist/esm/state/builder-api/message-channel.js.map +1 -1
  27. package/dist/esm/state/makeswift-api-client.js +21 -2
  28. package/dist/esm/state/makeswift-api-client.js.map +1 -1
  29. package/dist/esm/state/modules/api-resources.js +3 -0
  30. package/dist/esm/state/modules/api-resources.js.map +1 -1
  31. package/dist/esm/state/modules/localized-resources-map.js +3 -0
  32. package/dist/esm/state/modules/localized-resources-map.js.map +1 -1
  33. package/dist/types/runtimes/react/components/RuntimeProvider.d.ts.map +1 -1
  34. package/dist/types/runtimes/react/components/preview-switcher/preview-switcher.d.ts.map +1 -1
  35. package/dist/types/state/actions/index.d.ts +1 -0
  36. package/dist/types/state/actions/index.d.ts.map +1 -1
  37. package/dist/types/state/actions/internal/index.d.ts +1 -0
  38. package/dist/types/state/actions/internal/index.d.ts.map +1 -1
  39. package/dist/types/state/actions/internal/read-write-actions.d.ts +6 -1
  40. package/dist/types/state/actions/internal/read-write-actions.d.ts.map +1 -1
  41. package/dist/types/state/builder-api/message-channel.d.ts +4 -0
  42. package/dist/types/state/builder-api/message-channel.d.ts.map +1 -1
  43. package/dist/types/state/makeswift-api-client.d.ts.map +1 -1
  44. package/dist/types/state/modules/api-resources.d.ts.map +1 -1
  45. package/dist/types/state/modules/localized-resources-map.d.ts.map +1 -1
  46. package/package.json +2 -2
  47. package/dist/cjs/runtimes/react/components/hooks/use-builder-connection-ping.js +0 -62
  48. package/dist/cjs/runtimes/react/components/hooks/use-builder-connection-ping.js.map +0 -1
  49. package/dist/esm/runtimes/react/components/hooks/use-builder-connection-ping.js +0 -38
  50. package/dist/esm/runtimes/react/components/hooks/use-builder-connection-ping.js.map +0 -1
  51. package/dist/types/runtimes/react/components/hooks/use-builder-connection-ping.d.ts +0 -4
  52. package/dist/types/runtimes/react/components/hooks/use-builder-connection-ping.d.ts.map +0 -1
@@ -28,7 +28,7 @@ async function manifestHandler(req, { apiKey, manifest }) {
28
28
  return import_request_response.ApiResponse.json({ message: "Unauthorized" }, { status: 401 });
29
29
  }
30
30
  return import_request_response.ApiResponse.json({
31
- version: "0.27.0-canary.2",
31
+ version: "0.27.0",
32
32
  interactionMode: true,
33
33
  clientSideNavigation: false,
34
34
  elementFromPoint: false,
@@ -204,7 +204,7 @@ Received "${apiKey}" instead.`
204
204
  }
205
205
  this.apiKey = apiKey;
206
206
  this.graphqlClient = new import_client.GraphQLClient(new URL("graphql", runtime.apiOrigin).href, {
207
- "makeswift-runtime-version": "0.27.0-canary.2"
207
+ "makeswift-runtime-version": "0.27.0"
208
208
  });
209
209
  this.runtime = runtime;
210
210
  }
@@ -216,7 +216,7 @@ Received "${apiKey}" instead.`
216
216
  const requestHeaders = new Headers({
217
217
  "x-api-key": this.apiKey,
218
218
  "makeswift-site-api-key": this.apiKey,
219
- "makeswift-runtime-version": "0.27.0-canary.2"
219
+ "makeswift-runtime-version": "0.27.0"
220
220
  });
221
221
  if (siteVersion?.token) {
222
222
  requestUrl.searchParams.set("version", siteVersion.version);
@@ -663,7 +663,7 @@ Received "${apiKey}" instead.`
663
663
  headers: {
664
664
  "x-api-key": this.apiKey,
665
665
  "makeswift-site-api-key": this.apiKey,
666
- "makeswift-runtime-version": "0.27.0-canary.2",
666
+ "makeswift-runtime-version": "0.27.0",
667
667
  "content-type": "application/json"
668
668
  },
669
669
  body: JSON.stringify({ token }),
@@ -26,7 +26,6 @@ var import_jsx_runtime = require("react/jsx-runtime");
26
26
  var import_react = require("react");
27
27
  var import_use_react_runtime = require("../hooks/use-react-runtime");
28
28
  var import_use_async_effect = require("../hooks/use-async-effect");
29
- var import_use_builder_connection_ping = require("./hooks/use-builder-connection-ping");
30
29
  var import_preview_switcher = require("./preview-switcher/preview-switcher");
31
30
  function RuntimeProvider({
32
31
  children,
@@ -41,7 +40,6 @@ function RuntimeProvider({
41
40
  () => runtime.setIdempotent({ siteVersion, isReadOnly, locale }),
42
41
  [runtime, siteVersion, isReadOnly, locale]
43
42
  );
44
- (0, import_use_builder_connection_ping.useBuilderConnectionPing)({ appOrigin: runtime.appOrigin });
45
43
  (0, import_use_async_effect.useAsyncEffect)(() => runtime.setupStore({ isReadOnly }), [runtime, isReadOnly]);
46
44
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_use_react_runtime.ReactRuntimeContext.Provider, { value: runtime, children: [
47
45
  children,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/runtimes/react/components/RuntimeProvider.tsx"],"sourcesContent":["'use client'\n\nimport { ReactNode, useMemo } from 'react'\n\nimport { type SiteVersion } from '../../../api/site-version'\n\nimport { ReactRuntimeContext } from '../hooks/use-react-runtime'\nimport { useAsyncEffect } from '../hooks/use-async-effect'\nimport { type ReactRuntimeCore } from '../react-runtime-core'\n\nimport { useBuilderConnectionPing } from './hooks/use-builder-connection-ping'\nimport { PreviewSwitcher } from './preview-switcher/preview-switcher'\n\nexport function RuntimeProvider({\n children,\n runtime,\n siteVersion: siteVersionProp,\n locale = undefined,\n}: {\n children: ReactNode\n runtime: ReactRuntimeCore\n siteVersion: SiteVersion | null | undefined\n locale?: string\n}) {\n const siteVersion = siteVersionProp ?? null\n const isPreview = siteVersion != null\n // TODO: we need to decouple editability from the site version; specifically, previewing\n // a draft version of the site should not lead to switching to the read-write state\n const isReadOnly = siteVersion == null\n\n // setting idempotent part of the state on render to have parity between server-side and\n // client-side rendering depending on this state; `useMemo` here is purely a performance\n // optimization; prior art for performing idempotent side effects on render:\n // https://github.com/TanStack/query/blob/8f9f183f11df3709a1a38c4efce1452788041f88/packages/react-query/src/HydrationBoundary.tsx#L41\n useMemo(\n () => runtime.setIdempotent({ siteVersion, isReadOnly, locale }),\n [runtime, siteVersion, isReadOnly, locale],\n )\n\n useBuilderConnectionPing({ appOrigin: runtime.appOrigin })\n\n useAsyncEffect(() => runtime.setupStore({ isReadOnly }), [runtime, isReadOnly])\n\n return (\n <ReactRuntimeContext.Provider value={runtime}>\n {children}\n <PreviewSwitcher isPreview={isPreview} />\n </ReactRuntimeContext.Provider>\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA4CI;AA1CJ,mBAAmC;AAInC,+BAAoC;AACpC,8BAA+B;AAG/B,yCAAyC;AACzC,8BAAgC;AAEzB,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA,aAAa;AAAA,EACb,SAAS;AACX,GAKG;AACD,QAAM,cAAc,mBAAmB;AACvC,QAAM,YAAY,eAAe;AAGjC,QAAM,aAAa,eAAe;AAMlC;AAAA,IACE,MAAM,QAAQ,cAAc,EAAE,aAAa,YAAY,OAAO,CAAC;AAAA,IAC/D,CAAC,SAAS,aAAa,YAAY,MAAM;AAAA,EAC3C;AAEA,mEAAyB,EAAE,WAAW,QAAQ,UAAU,CAAC;AAEzD,8CAAe,MAAM,QAAQ,WAAW,EAAE,WAAW,CAAC,GAAG,CAAC,SAAS,UAAU,CAAC;AAE9E,SACE,6CAAC,6CAAoB,UAApB,EAA6B,OAAO,SAClC;AAAA;AAAA,IACD,4CAAC,2CAAgB,WAAsB;AAAA,KACzC;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../../../src/runtimes/react/components/RuntimeProvider.tsx"],"sourcesContent":["'use client'\n\nimport { ReactNode, useMemo } from 'react'\n\nimport { type SiteVersion } from '../../../api/site-version'\n\nimport { ReactRuntimeContext } from '../hooks/use-react-runtime'\nimport { useAsyncEffect } from '../hooks/use-async-effect'\nimport { type ReactRuntimeCore } from '../react-runtime-core'\n\nimport { PreviewSwitcher } from './preview-switcher/preview-switcher'\n\nexport function RuntimeProvider({\n children,\n runtime,\n siteVersion: siteVersionProp,\n locale = undefined,\n}: {\n children: ReactNode\n runtime: ReactRuntimeCore\n siteVersion: SiteVersion | null | undefined\n locale?: string\n}) {\n const siteVersion = siteVersionProp ?? null\n const isPreview = siteVersion != null\n // TODO: we need to decouple editability from the site version; specifically, previewing\n // a draft version of the site should not lead to switching to the read-write state\n const isReadOnly = siteVersion == null\n\n // setting idempotent part of the state on render to have parity between server-side and\n // client-side rendering depending on this state; `useMemo` here is purely a performance\n // optimization; prior art for performing idempotent side effects on render:\n // https://github.com/TanStack/query/blob/8f9f183f11df3709a1a38c4efce1452788041f88/packages/react-query/src/HydrationBoundary.tsx#L41\n useMemo(\n () => runtime.setIdempotent({ siteVersion, isReadOnly, locale }),\n [runtime, siteVersion, isReadOnly, locale],\n )\n\n useAsyncEffect(() => runtime.setupStore({ isReadOnly }), [runtime, isReadOnly])\n\n return (\n <ReactRuntimeContext.Provider value={runtime}>\n {children}\n <PreviewSwitcher isPreview={isPreview} />\n </ReactRuntimeContext.Provider>\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAyCI;AAvCJ,mBAAmC;AAInC,+BAAoC;AACpC,8BAA+B;AAG/B,8BAAgC;AAEzB,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA,aAAa;AAAA,EACb,SAAS;AACX,GAKG;AACD,QAAM,cAAc,mBAAmB;AACvC,QAAM,YAAY,eAAe;AAGjC,QAAM,aAAa,eAAe;AAMlC;AAAA,IACE,MAAM,QAAQ,cAAc,EAAE,aAAa,YAAY,OAAO,CAAC;AAAA,IAC/D,CAAC,SAAS,aAAa,YAAY,MAAM;AAAA,EAC3C;AAEA,8CAAe,MAAM,QAAQ,WAAW,EAAE,WAAW,CAAC,GAAG,CAAC,SAAS,UAAU,CAAC;AAE9E,SACE,6CAAC,6CAAoB,UAApB,EAA6B,OAAO,SAClC;AAAA;AAAA,IACD,4CAAC,2CAAgB,WAAsB;AAAA,KACzC;AAEJ;","names":[]}
@@ -28,20 +28,10 @@ var import_head_tags = require("../page/head-tags");
28
28
  var import_use_is_in_builder = require("../../hooks/use-is-in-builder");
29
29
  var import_preview_toolbar = require("./preview-toolbar");
30
30
  function PreviewSwitcher({ isPreview }) {
31
- const shadowContainerRef = (0, import_react.useRef)(null);
32
- const [shadowRoot, setShadowRoot] = (0, import_react.useState)(null);
33
31
  const isInBuilder = (0, import_use_is_in_builder.useIsInBuilder)();
34
32
  const showToolbar = !isInBuilder && isPreview;
35
- (0, import_react.useEffect)(() => {
36
- if (!showToolbar)
37
- return;
38
- if (shadowContainerRef.current && shadowContainerRef.current.shadowRoot == null && shadowRoot == null) {
39
- const root = shadowContainerRef.current.attachShadow({ mode: "open" });
40
- setShadowRoot(root);
41
- }
42
- }, [showToolbar, shadowRoot, setShadowRoot]);
43
33
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
44
- showToolbar && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { id: "makeswift-preview-switcher", ref: shadowContainerRef, children: shadowRoot ? (0, import_react_dom.createPortal)(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_preview_toolbar.PreviewToolbar, {}), shadowRoot) : null }),
34
+ showToolbar && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PreviewToolbarSingleton, { id: "makeswift-preview-switcher" }),
45
35
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
46
36
  import_head_tags.PageMeta,
47
37
  {
@@ -51,6 +41,25 @@ function PreviewSwitcher({ isPreview }) {
51
41
  )
52
42
  ] });
53
43
  }
44
+ function PreviewToolbarSingleton({ id }) {
45
+ const [shadowRoot, setShadowRoot] = (0, import_react.useState)(null);
46
+ const containerRef = (0, import_react.useRef)(null);
47
+ (0, import_react.useEffect)(() => {
48
+ if (document.getElementById(id) != null) {
49
+ return;
50
+ }
51
+ const container = document.createElement("span");
52
+ container.id = id;
53
+ document.body.appendChild(container);
54
+ containerRef.current = container;
55
+ setShadowRoot(container.shadowRoot ?? container.attachShadow({ mode: "open" }));
56
+ return () => {
57
+ containerRef.current?.remove();
58
+ containerRef.current = null;
59
+ };
60
+ }, [id]);
61
+ return shadowRoot != null ? (0, import_react_dom.createPortal)(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_preview_toolbar.PreviewToolbar, {}), shadowRoot) : null;
62
+ }
54
63
  // Annotate the CommonJS export names for ESM import in node:
55
64
  0 && (module.exports = {
56
65
  PreviewSwitcher
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../src/runtimes/react/components/preview-switcher/preview-switcher.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\n\nimport { PageMeta } from '../page/head-tags'\nimport { useIsInBuilder } from '../../hooks/use-is-in-builder'\nimport { PreviewToolbar } from './preview-toolbar'\n\nexport function PreviewSwitcher({ isPreview }: { isPreview: boolean }) {\n const shadowContainerRef = useRef<HTMLSpanElement | null>(null)\n const [shadowRoot, setShadowRoot] = useState<ShadowRoot | null>(null)\n const isInBuilder = useIsInBuilder()\n\n const showToolbar = !isInBuilder && isPreview\n\n useEffect(() => {\n if (!showToolbar) return\n if (\n shadowContainerRef.current &&\n shadowContainerRef.current.shadowRoot == null &&\n shadowRoot == null\n ) {\n const root = shadowContainerRef.current.attachShadow({ mode: 'open' })\n setShadowRoot(root)\n }\n }, [showToolbar, shadowRoot, setShadowRoot])\n\n return (\n <>\n {showToolbar && (\n <span id=\"makeswift-preview-switcher\" ref={shadowContainerRef}>\n {shadowRoot ? createPortal(<PreviewToolbar />, shadowRoot) : null}\n </span>\n )}\n {/* Insert preview mode information into the DOM to make it easier to debug preview mode-related\n issues on production sites */}\n <PageMeta\n name=\"makeswift-preview-info\"\n content={JSON.stringify({ isPreview: isPreview, inBuilder: isInBuilder })}\n />\n </>\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AA2BI;AA3BJ,mBAA4C;AAC5C,uBAA6B;AAE7B,uBAAyB;AACzB,+BAA+B;AAC/B,6BAA+B;AAExB,SAAS,gBAAgB,EAAE,UAAU,GAA2B;AACrE,QAAM,yBAAqB,qBAA+B,IAAI;AAC9D,QAAM,CAAC,YAAY,aAAa,QAAI,uBAA4B,IAAI;AACpE,QAAM,kBAAc,yCAAe;AAEnC,QAAM,cAAc,CAAC,eAAe;AAEpC,8BAAU,MAAM;AACd,QAAI,CAAC;AAAa;AAClB,QACE,mBAAmB,WACnB,mBAAmB,QAAQ,cAAc,QACzC,cAAc,MACd;AACA,YAAM,OAAO,mBAAmB,QAAQ,aAAa,EAAE,MAAM,OAAO,CAAC;AACrE,oBAAc,IAAI;AAAA,IACpB;AAAA,EACF,GAAG,CAAC,aAAa,YAAY,aAAa,CAAC;AAE3C,SACE,4EACG;AAAA,mBACC,4CAAC,UAAK,IAAG,8BAA6B,KAAK,oBACxC,2BAAa,+BAAa,4CAAC,yCAAe,GAAI,UAAU,IAAI,MAC/D;AAAA,IAIF;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,KAAK,UAAU,EAAE,WAAsB,WAAW,YAAY,CAAC;AAAA;AAAA,IAC1E;AAAA,KACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../../../../src/runtimes/react/components/preview-switcher/preview-switcher.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\n\nimport { PageMeta } from '../page/head-tags'\nimport { useIsInBuilder } from '../../hooks/use-is-in-builder'\nimport { PreviewToolbar } from './preview-toolbar'\n\nexport function PreviewSwitcher({ isPreview }: { isPreview: boolean }) {\n const isInBuilder = useIsInBuilder()\n const showToolbar = !isInBuilder && isPreview\n return (\n <>\n {showToolbar && <PreviewToolbarSingleton id=\"makeswift-preview-switcher\" />}\n {/* Insert preview mode information into the DOM to make it easier to debug preview mode-related\n issues on production sites */}\n <PageMeta\n name=\"makeswift-preview-info\"\n content={JSON.stringify({ isPreview: isPreview, inBuilder: isInBuilder })}\n />\n </>\n )\n}\n\nfunction PreviewToolbarSingleton({ id }: { id: string }) {\n const [shadowRoot, setShadowRoot] = useState<ShadowRoot | null>(null)\n const containerRef = useRef<HTMLSpanElement | null>(null)\n\n useEffect(() => {\n if (document.getElementById(id) != null) {\n return\n }\n\n const container = document.createElement('span')\n container.id = id\n document.body.appendChild(container)\n\n containerRef.current = container\n setShadowRoot(container.shadowRoot ?? container.attachShadow({ mode: 'open' }))\n\n return () => {\n containerRef.current?.remove()\n containerRef.current = null\n }\n }, [id])\n\n return shadowRoot != null ? createPortal(<PreviewToolbar />, shadowRoot) : null\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAWI;AAXJ,mBAA4C;AAC5C,uBAA6B;AAE7B,uBAAyB;AACzB,+BAA+B;AAC/B,6BAA+B;AAExB,SAAS,gBAAgB,EAAE,UAAU,GAA2B;AACrE,QAAM,kBAAc,yCAAe;AACnC,QAAM,cAAc,CAAC,eAAe;AACpC,SACE,4EACG;AAAA,mBAAe,4CAAC,2BAAwB,IAAG,8BAA6B;AAAA,IAGzE;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,KAAK,UAAU,EAAE,WAAsB,WAAW,YAAY,CAAC;AAAA;AAAA,IAC1E;AAAA,KACF;AAEJ;AAEA,SAAS,wBAAwB,EAAE,GAAG,GAAmB;AACvD,QAAM,CAAC,YAAY,aAAa,QAAI,uBAA4B,IAAI;AACpE,QAAM,mBAAe,qBAA+B,IAAI;AAExD,8BAAU,MAAM;AACd,QAAI,SAAS,eAAe,EAAE,KAAK,MAAM;AACvC;AAAA,IACF;AAEA,UAAM,YAAY,SAAS,cAAc,MAAM;AAC/C,cAAU,KAAK;AACf,aAAS,KAAK,YAAY,SAAS;AAEnC,iBAAa,UAAU;AACvB,kBAAc,UAAU,cAAc,UAAU,aAAa,EAAE,MAAM,OAAO,CAAC,CAAC;AAE9E,WAAO,MAAM;AACX,mBAAa,SAAS,OAAO;AAC7B,mBAAa,UAAU;AAAA,IACzB;AAAA,EACF,GAAG,CAAC,EAAE,CAAC;AAEP,SAAO,cAAc,WAAO,+BAAa,4CAAC,yCAAe,GAAI,UAAU,IAAI;AAC7E;","names":[]}
@@ -20,6 +20,7 @@ var read_write_actions_exports = {};
20
20
  __export(read_write_actions_exports, {
21
21
  ReadWriteActionTypes: () => ReadWriteActionTypes,
22
22
  changeElementTree: () => changeElementTree,
23
+ clearAPIClientCache: () => clearAPIClientCache,
23
24
  registerMeasurable: () => registerMeasurable,
24
25
  registerMeasurableEffect: () => registerMeasurableEffect,
25
26
  unregisterMeasurable: () => unregisterMeasurable,
@@ -30,7 +31,8 @@ const ReadWriteActionTypes = {
30
31
  CHANGE_ELEMENT_TREE: "CHANGE_ELEMENT_TREE",
31
32
  REGISTER_MEASURABLE: "REGISTER_MEASURABLE",
32
33
  UNREGISTER_MEASURABLE: "UNREGISTER_MEASURABLE",
33
- UPDATE_API_CLIENT_CACHE: "UPDATE_API_CLIENT_CACHE"
34
+ UPDATE_API_CLIENT_CACHE: "UPDATE_API_CLIENT_CACHE",
35
+ CLEAR_API_CLIENT_CACHE: "CLEAR_API_CLIENT_CACHE"
34
36
  };
35
37
  function changeElementTree(payload) {
36
38
  return {
@@ -58,10 +60,14 @@ function registerMeasurableEffect(documentKey, elementKey, measurable) {
58
60
  function updateAPIClientCache(payload) {
59
61
  return { type: ReadWriteActionTypes.UPDATE_API_CLIENT_CACHE, payload };
60
62
  }
63
+ function clearAPIClientCache() {
64
+ return { type: ReadWriteActionTypes.CLEAR_API_CLIENT_CACHE };
65
+ }
61
66
  // Annotate the CommonJS export names for ESM import in node:
62
67
  0 && (module.exports = {
63
68
  ReadWriteActionTypes,
64
69
  changeElementTree,
70
+ clearAPIClientCache,
65
71
  registerMeasurable,
66
72
  registerMeasurableEffect,
67
73
  unregisterMeasurable,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/state/actions/internal/read-write-actions.ts"],"sourcesContent":["import { type Operation } from 'ot-json0'\nimport { type ThunkAction } from '@reduxjs/toolkit'\n\nimport { type Measurable } from '../../modules/read-write/box-models'\nimport { type DescriptorsByComponentType } from '../../modules/prop-controllers'\n\nimport { type DocumentPayload } from '../../shared-api'\nimport { type SerializedState as APIClientCache } from '../../makeswift-api-client'\n\nexport const ReadWriteActionTypes = {\n CHANGE_ELEMENT_TREE: 'CHANGE_ELEMENT_TREE',\n REGISTER_MEASURABLE: 'REGISTER_MEASURABLE',\n UNREGISTER_MEASURABLE: 'UNREGISTER_MEASURABLE',\n\n UPDATE_API_CLIENT_CACHE: 'UPDATE_API_CLIENT_CACHE',\n} as const\n\ntype ChangeElementTreeAction = {\n type: typeof ReadWriteActionTypes.CHANGE_ELEMENT_TREE\n payload: {\n oldDocument: DocumentPayload\n newDocument: DocumentPayload\n descriptors: DescriptorsByComponentType\n operation: Operation\n }\n}\n\ntype RegisterMeasurableAction = {\n type: typeof ReadWriteActionTypes.REGISTER_MEASURABLE\n payload: { documentKey: string; elementKey: string; measurable: Measurable }\n}\n\ntype UnregisterMeasurableAction = {\n type: typeof ReadWriteActionTypes.UNREGISTER_MEASURABLE\n payload: { documentKey: string; elementKey: string }\n}\n\ntype UpdateAPIClientCache = {\n type: typeof ReadWriteActionTypes.UPDATE_API_CLIENT_CACHE\n payload: APIClientCache\n}\n\nexport type ReadWriteAction =\n | ChangeElementTreeAction\n | RegisterMeasurableAction\n | UnregisterMeasurableAction\n | UpdateAPIClientCache\n\nexport function changeElementTree(\n payload: ChangeElementTreeAction['payload'],\n): ChangeElementTreeAction {\n return {\n type: ReadWriteActionTypes.CHANGE_ELEMENT_TREE,\n payload,\n }\n}\n\nexport function registerMeasurable(\n documentKey: string,\n elementKey: string,\n measurable: Measurable,\n): RegisterMeasurableAction {\n return {\n type: ReadWriteActionTypes.REGISTER_MEASURABLE,\n payload: { documentKey, elementKey, measurable },\n }\n}\n\nexport function unregisterMeasurable(\n documentKey: string,\n elementKey: string,\n): UnregisterMeasurableAction {\n return { type: ReadWriteActionTypes.UNREGISTER_MEASURABLE, payload: { documentKey, elementKey } }\n}\n\nexport function registerMeasurableEffect(\n documentKey: string,\n elementKey: string,\n measurable: Measurable,\n): ThunkAction<() => void, unknown, unknown, ReadWriteAction> {\n return dispatch => {\n dispatch(registerMeasurable(documentKey, elementKey, measurable))\n\n return () => {\n dispatch(unregisterMeasurable(documentKey, elementKey))\n }\n }\n}\n\nexport function updateAPIClientCache(payload: APIClientCache): UpdateAPIClientCache {\n return { type: ReadWriteActionTypes.UPDATE_API_CLIENT_CACHE, payload }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASO,MAAM,uBAAuB;AAAA,EAClC,qBAAqB;AAAA,EACrB,qBAAqB;AAAA,EACrB,uBAAuB;AAAA,EAEvB,yBAAyB;AAC3B;AAiCO,SAAS,kBACd,SACyB;AACzB,SAAO;AAAA,IACL,MAAM,qBAAqB;AAAA,IAC3B;AAAA,EACF;AACF;AAEO,SAAS,mBACd,aACA,YACA,YAC0B;AAC1B,SAAO;AAAA,IACL,MAAM,qBAAqB;AAAA,IAC3B,SAAS,EAAE,aAAa,YAAY,WAAW;AAAA,EACjD;AACF;AAEO,SAAS,qBACd,aACA,YAC4B;AAC5B,SAAO,EAAE,MAAM,qBAAqB,uBAAuB,SAAS,EAAE,aAAa,WAAW,EAAE;AAClG;AAEO,SAAS,yBACd,aACA,YACA,YAC4D;AAC5D,SAAO,cAAY;AACjB,aAAS,mBAAmB,aAAa,YAAY,UAAU,CAAC;AAEhE,WAAO,MAAM;AACX,eAAS,qBAAqB,aAAa,UAAU,CAAC;AAAA,IACxD;AAAA,EACF;AACF;AAEO,SAAS,qBAAqB,SAA+C;AAClF,SAAO,EAAE,MAAM,qBAAqB,yBAAyB,QAAQ;AACvE;","names":[]}
1
+ {"version":3,"sources":["../../../../../src/state/actions/internal/read-write-actions.ts"],"sourcesContent":["import { type Operation } from 'ot-json0'\nimport { type ThunkAction } from '@reduxjs/toolkit'\n\nimport { type Measurable } from '../../modules/read-write/box-models'\nimport { type DescriptorsByComponentType } from '../../modules/prop-controllers'\n\nimport { type DocumentPayload } from '../../shared-api'\nimport { type SerializedState as APIClientCache } from '../../makeswift-api-client'\n\nexport const ReadWriteActionTypes = {\n CHANGE_ELEMENT_TREE: 'CHANGE_ELEMENT_TREE',\n REGISTER_MEASURABLE: 'REGISTER_MEASURABLE',\n UNREGISTER_MEASURABLE: 'UNREGISTER_MEASURABLE',\n\n UPDATE_API_CLIENT_CACHE: 'UPDATE_API_CLIENT_CACHE',\n CLEAR_API_CLIENT_CACHE: 'CLEAR_API_CLIENT_CACHE',\n} as const\n\ntype ChangeElementTreeAction = {\n type: typeof ReadWriteActionTypes.CHANGE_ELEMENT_TREE\n payload: {\n oldDocument: DocumentPayload\n newDocument: DocumentPayload\n descriptors: DescriptorsByComponentType\n operation: Operation\n }\n}\n\ntype RegisterMeasurableAction = {\n type: typeof ReadWriteActionTypes.REGISTER_MEASURABLE\n payload: { documentKey: string; elementKey: string; measurable: Measurable }\n}\n\ntype UnregisterMeasurableAction = {\n type: typeof ReadWriteActionTypes.UNREGISTER_MEASURABLE\n payload: { documentKey: string; elementKey: string }\n}\n\ntype UpdateAPIClientCache = {\n type: typeof ReadWriteActionTypes.UPDATE_API_CLIENT_CACHE\n payload: APIClientCache\n}\n\ntype ClearAPIClientCache = {\n type: typeof ReadWriteActionTypes.CLEAR_API_CLIENT_CACHE\n}\n\nexport type ReadWriteAction =\n | ChangeElementTreeAction\n | RegisterMeasurableAction\n | UnregisterMeasurableAction\n | UpdateAPIClientCache\n | ClearAPIClientCache\n\nexport function changeElementTree(\n payload: ChangeElementTreeAction['payload'],\n): ChangeElementTreeAction {\n return {\n type: ReadWriteActionTypes.CHANGE_ELEMENT_TREE,\n payload,\n }\n}\n\nexport function registerMeasurable(\n documentKey: string,\n elementKey: string,\n measurable: Measurable,\n): RegisterMeasurableAction {\n return {\n type: ReadWriteActionTypes.REGISTER_MEASURABLE,\n payload: { documentKey, elementKey, measurable },\n }\n}\n\nexport function unregisterMeasurable(\n documentKey: string,\n elementKey: string,\n): UnregisterMeasurableAction {\n return { type: ReadWriteActionTypes.UNREGISTER_MEASURABLE, payload: { documentKey, elementKey } }\n}\n\nexport function registerMeasurableEffect(\n documentKey: string,\n elementKey: string,\n measurable: Measurable,\n): ThunkAction<() => void, unknown, unknown, ReadWriteAction> {\n return dispatch => {\n dispatch(registerMeasurable(documentKey, elementKey, measurable))\n\n return () => {\n dispatch(unregisterMeasurable(documentKey, elementKey))\n }\n }\n}\n\nexport function updateAPIClientCache(payload: APIClientCache): UpdateAPIClientCache {\n return { type: ReadWriteActionTypes.UPDATE_API_CLIENT_CACHE, payload }\n}\n\nexport function clearAPIClientCache(): ClearAPIClientCache {\n return { type: ReadWriteActionTypes.CLEAR_API_CLIENT_CACHE }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASO,MAAM,uBAAuB;AAAA,EAClC,qBAAqB;AAAA,EACrB,qBAAqB;AAAA,EACrB,uBAAuB;AAAA,EAEvB,yBAAyB;AAAA,EACzB,wBAAwB;AAC1B;AAsCO,SAAS,kBACd,SACyB;AACzB,SAAO;AAAA,IACL,MAAM,qBAAqB;AAAA,IAC3B;AAAA,EACF;AACF;AAEO,SAAS,mBACd,aACA,YACA,YAC0B;AAC1B,SAAO;AAAA,IACL,MAAM,qBAAqB;AAAA,IAC3B,SAAS,EAAE,aAAa,YAAY,WAAW;AAAA,EACjD;AACF;AAEO,SAAS,qBACd,aACA,YAC4B;AAC5B,SAAO,EAAE,MAAM,qBAAqB,uBAAuB,SAAS,EAAE,aAAa,WAAW,EAAE;AAClG;AAEO,SAAS,yBACd,aACA,YACA,YAC4D;AAC5D,SAAO,cAAY;AACjB,aAAS,mBAAmB,aAAa,YAAY,UAAU,CAAC;AAEhE,WAAO,MAAM;AACX,eAAS,qBAAqB,aAAa,UAAU,CAAC;AAAA,IACxD;AAAA,EACF;AACF;AAEO,SAAS,qBAAqB,SAA+C;AAClF,SAAO,EAAE,MAAM,qBAAqB,yBAAyB,QAAQ;AACvE;AAEO,SAAS,sBAA2C;AACzD,SAAO,EAAE,MAAM,qBAAqB,uBAAuB;AAC7D;","names":[]}
@@ -21,10 +21,14 @@ __export(message_channel_exports, {
21
21
  MessageChannel: () => MessageChannel
22
22
  });
23
23
  module.exports = __toCommonJS(message_channel_exports);
24
+ var import_shared_api = require("../shared-api");
25
+ var import_actions = require("./actions");
26
+ const CONNECTION_PING_INTERVAL_MS = 20;
24
27
  class MessageChannel {
25
28
  appOrigin;
26
29
  channel = null;
27
30
  bufferedMessages = [];
31
+ connectionCheckIntervalID = null;
28
32
  constructor({ appOrigin }) {
29
33
  this.appOrigin = appOrigin;
30
34
  }
@@ -36,6 +40,7 @@ class MessageChannel {
36
40
  }
37
41
  }
38
42
  setup(onMessage) {
43
+ this.setupConnectionCheck();
39
44
  const channel = new window.MessageChannel();
40
45
  channel.port1.onmessage = onMessage;
41
46
  window.parent.postMessage(channel.port2, this.appOrigin, [channel.port2]);
@@ -49,11 +54,38 @@ class MessageChannel {
49
54
  this.bufferedMessages = [];
50
55
  }
51
56
  teardown() {
57
+ this.teardownConnectionCheck();
52
58
  if (this.channel) {
53
59
  this.channel.onmessage = null;
54
60
  this.channel.close();
55
61
  }
56
62
  }
63
+ setupConnectionCheck() {
64
+ window.addEventListener("message", this.connectionCheckHandler);
65
+ window.parent.postMessage((0, import_shared_api.makeswiftConnectionInit)(), { targetOrigin: this.appOrigin });
66
+ }
67
+ teardownConnectionCheck() {
68
+ window.removeEventListener("message", this.connectionCheckHandler);
69
+ if (this.connectionCheckIntervalID != null) {
70
+ window.clearInterval(this.connectionCheckIntervalID);
71
+ this.connectionCheckIntervalID = null;
72
+ }
73
+ }
74
+ // use class field syntax to preserve the identity of the handler
75
+ // for adding and removing the event listener
76
+ connectionCheckHandler = (event) => {
77
+ if (event.origin === this.appOrigin && event.data.type === import_shared_api.SharedActionTypes.MAKESWIFT_CONNECTION_INIT) {
78
+ if (this.connectionCheckIntervalID != null) {
79
+ window.clearInterval(this.connectionCheckIntervalID);
80
+ this.connectionCheckIntervalID = null;
81
+ }
82
+ this.connectionCheckIntervalID = window.setInterval(() => {
83
+ window.parent.postMessage((0, import_actions.makeswiftConnectionCheck)({ currentUrl: window.location.href }), {
84
+ targetOrigin: this.appOrigin
85
+ });
86
+ }, CONNECTION_PING_INTERVAL_MS);
87
+ }
88
+ };
57
89
  }
58
90
  // Annotate the CommonJS export names for ESM import in node:
59
91
  0 && (module.exports = {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/state/builder-api/message-channel.ts"],"sourcesContent":["export class MessageChannel {\n private readonly appOrigin: string\n private channel: MessagePort | null = null\n private bufferedMessages: [any, Transferable[]?][] = []\n\n constructor({ appOrigin }: { appOrigin: string }) {\n this.appOrigin = appOrigin\n }\n\n public postMessage(message: any, transferables?: Transferable[]) {\n if (this.channel) {\n this.channel.postMessage(message, transferables ?? [])\n } else {\n this.bufferedMessages.push([message, transferables])\n }\n }\n\n public setup(onMessage: (event: MessageEvent) => void) {\n const channel = new window.MessageChannel()\n channel.port1.onmessage = onMessage\n\n // connect channel to the parent window, see\n // https://developer.mozilla.org/en-US/docs/Web/API/Channel_Messaging_API\n window.parent.postMessage(channel.port2, this.appOrigin, [channel.port2])\n\n this.channel = channel.port1\n }\n\n public dispatchBuffered() {\n console.assert(this.channel != null, 'channel is not setup')\n\n this.bufferedMessages.forEach(([message, transferables]) => {\n this.channel?.postMessage(message, transferables ?? [])\n })\n\n this.bufferedMessages = []\n }\n\n public teardown() {\n if (this.channel) {\n this.channel.onmessage = null\n this.channel.close()\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAO,MAAM,eAAe;AAAA,EACT;AAAA,EACT,UAA8B;AAAA,EAC9B,mBAA6C,CAAC;AAAA,EAEtD,YAAY,EAAE,UAAU,GAA0B;AAChD,SAAK,YAAY;AAAA,EACnB;AAAA,EAEO,YAAY,SAAc,eAAgC;AAC/D,QAAI,KAAK,SAAS;AAChB,WAAK,QAAQ,YAAY,SAAS,iBAAiB,CAAC,CAAC;AAAA,IACvD,OAAO;AACL,WAAK,iBAAiB,KAAK,CAAC,SAAS,aAAa,CAAC;AAAA,IACrD;AAAA,EACF;AAAA,EAEO,MAAM,WAA0C;AACrD,UAAM,UAAU,IAAI,OAAO,eAAe;AAC1C,YAAQ,MAAM,YAAY;AAI1B,WAAO,OAAO,YAAY,QAAQ,OAAO,KAAK,WAAW,CAAC,QAAQ,KAAK,CAAC;AAExE,SAAK,UAAU,QAAQ;AAAA,EACzB;AAAA,EAEO,mBAAmB;AACxB,YAAQ,OAAO,KAAK,WAAW,MAAM,sBAAsB;AAE3D,SAAK,iBAAiB,QAAQ,CAAC,CAAC,SAAS,aAAa,MAAM;AAC1D,WAAK,SAAS,YAAY,SAAS,iBAAiB,CAAC,CAAC;AAAA,IACxD,CAAC;AAED,SAAK,mBAAmB,CAAC;AAAA,EAC3B;AAAA,EAEO,WAAW;AAChB,QAAI,KAAK,SAAS;AAChB,WAAK,QAAQ,YAAY;AACzB,WAAK,QAAQ,MAAM;AAAA,IACrB;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../../src/state/builder-api/message-channel.ts"],"sourcesContent":["import { SharedActionTypes, makeswiftConnectionInit } from '../shared-api'\nimport { makeswiftConnectionCheck } from './actions'\n\nconst CONNECTION_PING_INTERVAL_MS = 20\n\nexport class MessageChannel {\n private readonly appOrigin: string\n private channel: MessagePort | null = null\n private bufferedMessages: [any, Transferable[]?][] = []\n private connectionCheckIntervalID: number | null = null\n\n constructor({ appOrigin }: { appOrigin: string }) {\n this.appOrigin = appOrigin\n }\n\n public postMessage(message: any, transferables?: Transferable[]) {\n if (this.channel) {\n this.channel.postMessage(message, transferables ?? [])\n } else {\n this.bufferedMessages.push([message, transferables])\n }\n }\n\n public setup(onMessage: (event: MessageEvent) => void) {\n this.setupConnectionCheck()\n\n const channel = new window.MessageChannel()\n channel.port1.onmessage = onMessage\n\n // connect channel to the parent window, see\n // https://developer.mozilla.org/en-US/docs/Web/API/Channel_Messaging_API\n window.parent.postMessage(channel.port2, this.appOrigin, [channel.port2])\n\n this.channel = channel.port1\n }\n\n public dispatchBuffered() {\n console.assert(this.channel != null, 'channel is not setup')\n\n this.bufferedMessages.forEach(([message, transferables]) => {\n this.channel?.postMessage(message, transferables ?? [])\n })\n\n this.bufferedMessages = []\n }\n\n public teardown() {\n this.teardownConnectionCheck()\n\n if (this.channel) {\n this.channel.onmessage = null\n this.channel.close()\n }\n }\n\n private setupConnectionCheck() {\n window.addEventListener('message', this.connectionCheckHandler)\n window.parent.postMessage(makeswiftConnectionInit(), { targetOrigin: this.appOrigin })\n }\n\n private teardownConnectionCheck() {\n window.removeEventListener('message', this.connectionCheckHandler)\n if (this.connectionCheckIntervalID != null) {\n window.clearInterval(this.connectionCheckIntervalID)\n this.connectionCheckIntervalID = null\n }\n }\n\n // use class field syntax to preserve the identity of the handler\n // for adding and removing the event listener\n private connectionCheckHandler = (event: MessageEvent) => {\n if (\n event.origin === this.appOrigin &&\n event.data.type === SharedActionTypes.MAKESWIFT_CONNECTION_INIT\n ) {\n if (this.connectionCheckIntervalID != null) {\n window.clearInterval(this.connectionCheckIntervalID)\n this.connectionCheckIntervalID = null\n }\n\n this.connectionCheckIntervalID = window.setInterval(() => {\n window.parent.postMessage(makeswiftConnectionCheck({ currentUrl: window.location.href }), {\n targetOrigin: this.appOrigin,\n })\n }, CONNECTION_PING_INTERVAL_MS)\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAA2D;AAC3D,qBAAyC;AAEzC,MAAM,8BAA8B;AAE7B,MAAM,eAAe;AAAA,EACT;AAAA,EACT,UAA8B;AAAA,EAC9B,mBAA6C,CAAC;AAAA,EAC9C,4BAA2C;AAAA,EAEnD,YAAY,EAAE,UAAU,GAA0B;AAChD,SAAK,YAAY;AAAA,EACnB;AAAA,EAEO,YAAY,SAAc,eAAgC;AAC/D,QAAI,KAAK,SAAS;AAChB,WAAK,QAAQ,YAAY,SAAS,iBAAiB,CAAC,CAAC;AAAA,IACvD,OAAO;AACL,WAAK,iBAAiB,KAAK,CAAC,SAAS,aAAa,CAAC;AAAA,IACrD;AAAA,EACF;AAAA,EAEO,MAAM,WAA0C;AACrD,SAAK,qBAAqB;AAE1B,UAAM,UAAU,IAAI,OAAO,eAAe;AAC1C,YAAQ,MAAM,YAAY;AAI1B,WAAO,OAAO,YAAY,QAAQ,OAAO,KAAK,WAAW,CAAC,QAAQ,KAAK,CAAC;AAExE,SAAK,UAAU,QAAQ;AAAA,EACzB;AAAA,EAEO,mBAAmB;AACxB,YAAQ,OAAO,KAAK,WAAW,MAAM,sBAAsB;AAE3D,SAAK,iBAAiB,QAAQ,CAAC,CAAC,SAAS,aAAa,MAAM;AAC1D,WAAK,SAAS,YAAY,SAAS,iBAAiB,CAAC,CAAC;AAAA,IACxD,CAAC;AAED,SAAK,mBAAmB,CAAC;AAAA,EAC3B;AAAA,EAEO,WAAW;AAChB,SAAK,wBAAwB;AAE7B,QAAI,KAAK,SAAS;AAChB,WAAK,QAAQ,YAAY;AACzB,WAAK,QAAQ,MAAM;AAAA,IACrB;AAAA,EACF;AAAA,EAEQ,uBAAuB;AAC7B,WAAO,iBAAiB,WAAW,KAAK,sBAAsB;AAC9D,WAAO,OAAO,gBAAY,2CAAwB,GAAG,EAAE,cAAc,KAAK,UAAU,CAAC;AAAA,EACvF;AAAA,EAEQ,0BAA0B;AAChC,WAAO,oBAAoB,WAAW,KAAK,sBAAsB;AACjE,QAAI,KAAK,6BAA6B,MAAM;AAC1C,aAAO,cAAc,KAAK,yBAAyB;AACnD,WAAK,4BAA4B;AAAA,IACnC;AAAA,EACF;AAAA;AAAA;AAAA,EAIQ,yBAAyB,CAAC,UAAwB;AACxD,QACE,MAAM,WAAW,KAAK,aACtB,MAAM,KAAK,SAAS,oCAAkB,2BACtC;AACA,UAAI,KAAK,6BAA6B,MAAM;AAC1C,eAAO,cAAc,KAAK,yBAAyB;AACnD,aAAK,4BAA4B;AAAA,MACnC;AAEA,WAAK,4BAA4B,OAAO,YAAY,MAAM;AACxD,eAAO,OAAO,gBAAY,yCAAyB,EAAE,YAAY,OAAO,SAAS,KAAK,CAAC,GAAG;AAAA,UACxF,cAAc,KAAK;AAAA,QACrB,CAAC;AAAA,MACH,GAAG,2BAA2B;AAAA,IAChC;AAAA,EACF;AACF;","names":[]}
@@ -42,6 +42,7 @@ var APIResources = __toESM(require("./modules/api-resources"));
42
42
  var LocalizedResourcesMap = __toESM(require("./modules/localized-resources-map"));
43
43
  var import_actions = require("./actions");
44
44
  var import_read_only_actions = require("./actions/internal/read-only-actions");
45
+ var import_read_write_actions = require("./actions/internal/read-write-actions");
45
46
  var import_host_api = require("./host-api");
46
47
  var import_toolkit2 = require("./toolkit");
47
48
  var import_api = require("../api");
@@ -186,6 +187,21 @@ function defaultLocaleMiddleware() {
186
187
  };
187
188
  });
188
189
  }
190
+ function cacheVersioningMiddleware() {
191
+ return (0, import_toolkit2.actionMiddleware)(({ getState, dispatch }) => (next) => {
192
+ return (action) => {
193
+ switch (action.type) {
194
+ case import_read_only_actions.ReadOnlyActionTypes.SET_SITE_VERSION: {
195
+ const cacheVersion = SiteVersionState.getSiteVersion(getState().siteVersion);
196
+ if (cacheVersion?.version !== action.payload?.version) {
197
+ dispatch((0, import_read_write_actions.clearAPIClientCache)());
198
+ }
199
+ }
200
+ }
201
+ return next(action);
202
+ };
203
+ });
204
+ }
189
205
  function configureStore({ serializedState }) {
190
206
  return (0, import_toolkit.configureStore)({
191
207
  reducer,
@@ -195,7 +211,10 @@ function configureStore({ serializedState }) {
195
211
  serializedState?.localizedResourcesMap
196
212
  )
197
213
  },
198
- middleware: (getDefaultMiddleware) => getDefaultMiddleware(import_toolkit2.middlewareOptions).concat(defaultLocaleMiddleware()),
214
+ middleware: (getDefaultMiddleware) => getDefaultMiddleware(import_toolkit2.middlewareOptions).concat(
215
+ defaultLocaleMiddleware(),
216
+ cacheVersioningMiddleware()
217
+ ),
199
218
  devTools: (0, import_toolkit2.devToolsConfig)({
200
219
  name: `API client store (${(/* @__PURE__ */ new Date()).toISOString()})`,
201
220
  actionsDenylist: [
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/state/makeswift-api-client.ts"],"sourcesContent":["import {\n configureStore as configureReduxStore,\n combineReducers,\n type ThunkAction,\n type ThunkMiddleware,\n type ThunkDispatch,\n UnknownAction,\n} from '@reduxjs/toolkit'\n\nimport { type SiteVersion, ApiHandlerHeaders, serializeSiteVersion } from '../api/site-version'\n\nimport * as SiteVersionState from './modules/site-version'\nimport * as LocaleState from './modules/locale'\nimport * as APIResources from './modules/api-resources'\nimport * as LocalizedResourcesMap from './modules/localized-resources-map'\n\nimport { type Action, ActionTypes } from './actions'\nimport { apiResourceFulfilled } from './actions/internal/read-only-actions'\nimport { setLocalizedResourceId } from './host-api'\nimport { actionMiddleware, middlewareOptions, devToolsConfig } from './toolkit'\n\nimport {\n APIResourceType,\n type APIResource,\n type Swatch,\n type File,\n type Typography,\n type GlobalElement,\n type PagePathnameSlice,\n type Table,\n type LocalizedGlobalElement,\n type APIResourceLocale,\n} from '../api'\n\nconst reducer = combineReducers({\n siteVersion: SiteVersionState.reducer,\n locale: LocaleState.reducer,\n apiResources: APIResources.reducer,\n localizedResourcesMap: LocalizedResourcesMap.reducer,\n})\n\nexport type State = ReturnType<typeof reducer>\nexport type Dispatch = ThunkDispatch<State, unknown, Action>\nexport type HttpFetch = (url: string | URL, init?: RequestInit) => Promise<Response>\n\nexport type SerializedState = {\n apiResources: APIResources.SerializedState\n localizedResourcesMap: LocalizedResourcesMap.SerializedState\n}\n\nfunction getLocalizedResourceId(\n state: State,\n locale: string,\n resourceId: string,\n): string | undefined | null {\n return LocalizedResourcesMap.getLocalizedResourceId(\n state.localizedResourcesMap,\n locale,\n resourceId,\n )\n}\n\nexport function getHasAPIResource<T extends APIResourceType>(\n state: State,\n resourceType: APIResourceType,\n resourceId: string,\n locale?: APIResourceLocale<T>,\n): boolean {\n switch (resourceType) {\n case APIResourceType.LocalizedGlobalElement:\n if (locale == null) {\n console.error(`Attempt to access ${resourceType} ${resourceId} without a locale`)\n return false\n }\n\n const localizedId = getLocalizedResourceId(state, locale, resourceId)\n return (\n localizedId != null &&\n APIResources.getHasAPIResource(state.apiResources, resourceType, localizedId, locale)\n )\n\n default:\n return APIResources.getHasAPIResource(state.apiResources, resourceType, resourceId, locale)\n }\n}\n\nexport function getAPIResource<T extends APIResourceType>(\n state: State,\n resourceType: T,\n resourceId: string,\n locale?: APIResourceLocale<T>,\n): Extract<APIResource, { __typename: T }> | null {\n switch (resourceType) {\n case APIResourceType.LocalizedGlobalElement:\n if (locale == null) {\n console.error(`Attempt to access ${resourceType} ${resourceId} without a locale`)\n return null\n }\n\n const localizedId = getLocalizedResourceId(state, locale, resourceId)\n return localizedId != null\n ? APIResources.getAPIResource(state.apiResources, resourceType, localizedId, locale)\n : null\n\n default:\n return APIResources.getAPIResource(state.apiResources, resourceType, resourceId, locale)\n }\n}\n\ntype Thunk<ReturnType> = ThunkAction<ReturnType, State, unknown, Action>\n\nexport function fetchAPIResource<T extends APIResourceType>(\n resourceType: T,\n resourceId: string,\n fetch: HttpFetch,\n locale?: APIResourceLocale<T>,\n): Thunk<Promise<Extract<APIResource, { __typename: T }> | null>> {\n const fetchVersioned = async <T>(url: string, version: SiteVersion | null): Promise<T | null> => {\n const response = await fetch(url, {\n headers: {\n 'Content-Type': 'application/json',\n ...(version != null\n ? { [ApiHandlerHeaders.SiteVersion]: serializeSiteVersion(version) }\n : {}),\n },\n })\n\n if (response.status === 404) return null\n if (!response.ok) throw new Error(response.statusText)\n\n if (response.headers.get('content-type')?.includes('application/json') !== true) {\n throw new Error(\n `Expected JSON response from \"${url}\" but got \"${response.headers.get('content-type')}\"`,\n )\n }\n\n return response.json()\n }\n\n return async (dispatch, getState) => {\n const state = getState()\n const version = SiteVersionState.getSiteVersion(state.siteVersion)\n\n if (getHasAPIResource(state, resourceType, resourceId, locale)) {\n return getAPIResource(state, resourceType, resourceId, locale)\n }\n\n let resource: APIResource | null\n\n switch (resourceType) {\n case APIResourceType.Swatch:\n resource = await fetchVersioned<Swatch>(`/api/makeswift/swatches/${resourceId}`, version)\n break\n\n case APIResourceType.File:\n resource = await fetchVersioned<File>(`/api/makeswift/files/${resourceId}`, version)\n break\n\n case APIResourceType.Typography:\n resource = await fetchVersioned<Typography>(\n `/api/makeswift/typographies/${resourceId}`,\n version,\n )\n break\n\n case APIResourceType.GlobalElement:\n resource = await fetchVersioned<GlobalElement>(\n `/api/makeswift/global-elements/${resourceId}`,\n version,\n )\n break\n\n case APIResourceType.LocalizedGlobalElement: {\n if (locale == null) throw new Error('Locale is required to fetch LocalizedGlobalElement')\n\n // If `getLocalizedResourceId` returns null, it means we have tried to fetch the resource,\n // but the resource is not available. If we haven't fetched it yet, it'll return undefined.\n if (getLocalizedResourceId(state, locale, resourceId) === null) {\n return null\n }\n\n resource = await fetchVersioned<LocalizedGlobalElement>(\n `/api/makeswift/localized-global-elements/${resourceId}/${locale}`,\n version,\n )\n\n dispatch(\n setLocalizedResourceId({\n locale,\n resourceId,\n localizedResourceId: resource?.id ?? null,\n }),\n )\n\n break\n }\n\n case APIResourceType.PagePathnameSlice: {\n const url = new URL(`/api/makeswift/page-pathname-slices/${resourceId}`, 'http://n')\n\n if (locale != null) url.searchParams.set('locale', locale)\n\n resource = await fetchVersioned<PagePathnameSlice>(url.pathname + url.search, version)\n break\n }\n\n case APIResourceType.Table:\n resource = await fetchVersioned<Table>(`/api/makeswift/tables/${resourceId}`, version)\n break\n\n default:\n resource = null\n }\n\n dispatch(apiResourceFulfilled(resourceType, resourceId, resource, locale))\n\n return resource as Extract<APIResource, { __typename: T }> | null\n }\n}\n\n// FIXME: this middleware can be removed once we've upgraded the builder\n// to always provide the locale when dispatching resource actions\nfunction defaultLocaleMiddleware(): ThunkMiddleware<State, UnknownAction> {\n return actionMiddleware(({ getState }) => next => {\n return (action: Action) => {\n switch (action.type) {\n case ActionTypes.CHANGE_API_RESOURCE:\n case ActionTypes.EVICT_API_RESOURCE:\n case ActionTypes.SET_LOCALIZED_RESOURCE_ID: {\n const { locale } = action.payload\n return next({\n ...action,\n payload: {\n ...action.payload,\n locale: locale ?? LocaleState.getLocale(getState().locale),\n },\n } as Action)\n }\n }\n\n return next(action)\n }\n })\n}\n\nexport function configureStore({ serializedState }: { serializedState?: SerializedState }) {\n return configureReduxStore({\n reducer,\n preloadedState: {\n apiResources: APIResources.getInitialState(serializedState?.apiResources),\n localizedResourcesMap: LocalizedResourcesMap.getInitialState(\n serializedState?.localizedResourcesMap,\n ),\n },\n\n middleware: getDefaultMiddleware =>\n getDefaultMiddleware(middlewareOptions).concat(defaultLocaleMiddleware()),\n\n devTools: devToolsConfig({\n name: `API client store (${new Date().toISOString()})`,\n actionsDenylist: [\n ActionTypes.BUILDER_POINTER_MOVE,\n ActionTypes.HANDLE_POINTER_MOVE,\n ActionTypes.ELEMENT_FROM_POINT_CHANGE,\n ],\n }),\n })\n}\n\nexport type Store = ReturnType<typeof configureStore>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAOO;AAEP,0BAA0E;AAE1E,uBAAkC;AAClC,kBAA6B;AAC7B,mBAA8B;AAC9B,4BAAuC;AAEvC,qBAAyC;AACzC,+BAAqC;AACrC,sBAAuC;AACvC,IAAAA,kBAAoE;AAEpE,iBAWO;AAEP,MAAM,cAAU,gCAAgB;AAAA,EAC9B,aAAa,iBAAiB;AAAA,EAC9B,QAAQ,YAAY;AAAA,EACpB,cAAc,aAAa;AAAA,EAC3B,uBAAuB,sBAAsB;AAC/C,CAAC;AAWD,SAAS,uBACP,OACA,QACA,YAC2B;AAC3B,SAAO,sBAAsB;AAAA,IAC3B,MAAM;AAAA,IACN;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,kBACd,OACA,cACA,YACA,QACS;AACT,UAAQ,cAAc;AAAA,IACpB,KAAK,2BAAgB;AACnB,UAAI,UAAU,MAAM;AAClB,gBAAQ,MAAM,qBAAqB,YAAY,IAAI,UAAU,mBAAmB;AAChF,eAAO;AAAA,MACT;AAEA,YAAM,cAAc,uBAAuB,OAAO,QAAQ,UAAU;AACpE,aACE,eAAe,QACf,aAAa,kBAAkB,MAAM,cAAc,cAAc,aAAa,MAAM;AAAA,IAGxF;AACE,aAAO,aAAa,kBAAkB,MAAM,cAAc,cAAc,YAAY,MAAM;AAAA,EAC9F;AACF;AAEO,SAAS,eACd,OACA,cACA,YACA,QACgD;AAChD,UAAQ,cAAc;AAAA,IACpB,KAAK,2BAAgB;AACnB,UAAI,UAAU,MAAM;AAClB,gBAAQ,MAAM,qBAAqB,YAAY,IAAI,UAAU,mBAAmB;AAChF,eAAO;AAAA,MACT;AAEA,YAAM,cAAc,uBAAuB,OAAO,QAAQ,UAAU;AACpE,aAAO,eAAe,OAClB,aAAa,eAAe,MAAM,cAAc,cAAc,aAAa,MAAM,IACjF;AAAA,IAEN;AACE,aAAO,aAAa,eAAe,MAAM,cAAc,cAAc,YAAY,MAAM;AAAA,EAC3F;AACF;AAIO,SAAS,iBACd,cACA,YACA,OACA,QACgE;AAChE,QAAM,iBAAiB,OAAU,KAAa,YAAmD;AAC/F,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,GAAI,WAAW,OACX,EAAE,CAAC,sCAAkB,WAAW,OAAG,0CAAqB,OAAO,EAAE,IACjE,CAAC;AAAA,MACP;AAAA,IACF,CAAC;AAED,QAAI,SAAS,WAAW;AAAK,aAAO;AACpC,QAAI,CAAC,SAAS;AAAI,YAAM,IAAI,MAAM,SAAS,UAAU;AAErD,QAAI,SAAS,QAAQ,IAAI,cAAc,GAAG,SAAS,kBAAkB,MAAM,MAAM;AAC/E,YAAM,IAAI;AAAA,QACR,gCAAgC,GAAG,cAAc,SAAS,QAAQ,IAAI,cAAc,CAAC;AAAA,MACvF;AAAA,IACF;AAEA,WAAO,SAAS,KAAK;AAAA,EACvB;AAEA,SAAO,OAAO,UAAU,aAAa;AACnC,UAAM,QAAQ,SAAS;AACvB,UAAM,UAAU,iBAAiB,eAAe,MAAM,WAAW;AAEjE,QAAI,kBAAkB,OAAO,cAAc,YAAY,MAAM,GAAG;AAC9D,aAAO,eAAe,OAAO,cAAc,YAAY,MAAM;AAAA,IAC/D;AAEA,QAAI;AAEJ,YAAQ,cAAc;AAAA,MACpB,KAAK,2BAAgB;AACnB,mBAAW,MAAM,eAAuB,2BAA2B,UAAU,IAAI,OAAO;AACxF;AAAA,MAEF,KAAK,2BAAgB;AACnB,mBAAW,MAAM,eAAqB,wBAAwB,UAAU,IAAI,OAAO;AACnF;AAAA,MAEF,KAAK,2BAAgB;AACnB,mBAAW,MAAM;AAAA,UACf,+BAA+B,UAAU;AAAA,UACzC;AAAA,QACF;AACA;AAAA,MAEF,KAAK,2BAAgB;AACnB,mBAAW,MAAM;AAAA,UACf,kCAAkC,UAAU;AAAA,UAC5C;AAAA,QACF;AACA;AAAA,MAEF,KAAK,2BAAgB,wBAAwB;AAC3C,YAAI,UAAU;AAAM,gBAAM,IAAI,MAAM,oDAAoD;AAIxF,YAAI,uBAAuB,OAAO,QAAQ,UAAU,MAAM,MAAM;AAC9D,iBAAO;AAAA,QACT;AAEA,mBAAW,MAAM;AAAA,UACf,4CAA4C,UAAU,IAAI,MAAM;AAAA,UAChE;AAAA,QACF;AAEA;AAAA,cACE,wCAAuB;AAAA,YACrB;AAAA,YACA;AAAA,YACA,qBAAqB,UAAU,MAAM;AAAA,UACvC,CAAC;AAAA,QACH;AAEA;AAAA,MACF;AAAA,MAEA,KAAK,2BAAgB,mBAAmB;AACtC,cAAM,MAAM,IAAI,IAAI,uCAAuC,UAAU,IAAI,UAAU;AAEnF,YAAI,UAAU;AAAM,cAAI,aAAa,IAAI,UAAU,MAAM;AAEzD,mBAAW,MAAM,eAAkC,IAAI,WAAW,IAAI,QAAQ,OAAO;AACrF;AAAA,MACF;AAAA,MAEA,KAAK,2BAAgB;AACnB,mBAAW,MAAM,eAAsB,yBAAyB,UAAU,IAAI,OAAO;AACrF;AAAA,MAEF;AACE,mBAAW;AAAA,IACf;AAEA,iBAAS,+CAAqB,cAAc,YAAY,UAAU,MAAM,CAAC;AAEzE,WAAO;AAAA,EACT;AACF;AAIA,SAAS,0BAAiE;AACxE,aAAO,kCAAiB,CAAC,EAAE,SAAS,MAAM,UAAQ;AAChD,WAAO,CAAC,WAAmB;AACzB,cAAQ,OAAO,MAAM;AAAA,QACnB,KAAK,2BAAY;AAAA,QACjB,KAAK,2BAAY;AAAA,QACjB,KAAK,2BAAY,2BAA2B;AAC1C,gBAAM,EAAE,OAAO,IAAI,OAAO;AAC1B,iBAAO,KAAK;AAAA,YACV,GAAG;AAAA,YACH,SAAS;AAAA,cACP,GAAG,OAAO;AAAA,cACV,QAAQ,UAAU,YAAY,UAAU,SAAS,EAAE,MAAM;AAAA,YAC3D;AAAA,UACF,CAAW;AAAA,QACb;AAAA,MACF;AAEA,aAAO,KAAK,MAAM;AAAA,IACpB;AAAA,EACF,CAAC;AACH;AAEO,SAAS,eAAe,EAAE,gBAAgB,GAA0C;AACzF,aAAO,eAAAC,gBAAoB;AAAA,IACzB;AAAA,IACA,gBAAgB;AAAA,MACd,cAAc,aAAa,gBAAgB,iBAAiB,YAAY;AAAA,MACxE,uBAAuB,sBAAsB;AAAA,QAC3C,iBAAiB;AAAA,MACnB;AAAA,IACF;AAAA,IAEA,YAAY,0BACV,qBAAqB,iCAAiB,EAAE,OAAO,wBAAwB,CAAC;AAAA,IAE1E,cAAU,gCAAe;AAAA,MACvB,MAAM,sBAAqB,oBAAI,KAAK,GAAE,YAAY,CAAC;AAAA,MACnD,iBAAiB;AAAA,QACf,2BAAY;AAAA,QACZ,2BAAY;AAAA,QACZ,2BAAY;AAAA,MACd;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AACH;","names":["import_toolkit","configureReduxStore"]}
1
+ {"version":3,"sources":["../../../src/state/makeswift-api-client.ts"],"sourcesContent":["import {\n configureStore as configureReduxStore,\n combineReducers,\n type ThunkAction,\n type ThunkMiddleware,\n type ThunkDispatch,\n UnknownAction,\n} from '@reduxjs/toolkit'\n\nimport { type SiteVersion, ApiHandlerHeaders, serializeSiteVersion } from '../api/site-version'\n\nimport * as SiteVersionState from './modules/site-version'\nimport * as LocaleState from './modules/locale'\nimport * as APIResources from './modules/api-resources'\nimport * as LocalizedResourcesMap from './modules/localized-resources-map'\n\nimport { type Action, ActionTypes } from './actions'\nimport { apiResourceFulfilled, ReadOnlyActionTypes } from './actions/internal/read-only-actions'\nimport { clearAPIClientCache } from './actions/internal/read-write-actions'\nimport { setLocalizedResourceId } from './host-api'\nimport { actionMiddleware, middlewareOptions, devToolsConfig } from './toolkit'\n\nimport {\n APIResourceType,\n type APIResource,\n type Swatch,\n type File,\n type Typography,\n type GlobalElement,\n type PagePathnameSlice,\n type Table,\n type LocalizedGlobalElement,\n type APIResourceLocale,\n} from '../api'\n\nconst reducer = combineReducers({\n siteVersion: SiteVersionState.reducer,\n locale: LocaleState.reducer,\n apiResources: APIResources.reducer,\n localizedResourcesMap: LocalizedResourcesMap.reducer,\n})\n\nexport type State = ReturnType<typeof reducer>\nexport type Dispatch = ThunkDispatch<State, unknown, Action>\nexport type HttpFetch = (url: string | URL, init?: RequestInit) => Promise<Response>\n\nexport type SerializedState = {\n apiResources: APIResources.SerializedState\n localizedResourcesMap: LocalizedResourcesMap.SerializedState\n}\n\nfunction getLocalizedResourceId(\n state: State,\n locale: string,\n resourceId: string,\n): string | undefined | null {\n return LocalizedResourcesMap.getLocalizedResourceId(\n state.localizedResourcesMap,\n locale,\n resourceId,\n )\n}\n\nexport function getHasAPIResource<T extends APIResourceType>(\n state: State,\n resourceType: APIResourceType,\n resourceId: string,\n locale?: APIResourceLocale<T>,\n): boolean {\n switch (resourceType) {\n case APIResourceType.LocalizedGlobalElement:\n if (locale == null) {\n console.error(`Attempt to access ${resourceType} ${resourceId} without a locale`)\n return false\n }\n\n const localizedId = getLocalizedResourceId(state, locale, resourceId)\n return (\n localizedId != null &&\n APIResources.getHasAPIResource(state.apiResources, resourceType, localizedId, locale)\n )\n\n default:\n return APIResources.getHasAPIResource(state.apiResources, resourceType, resourceId, locale)\n }\n}\n\nexport function getAPIResource<T extends APIResourceType>(\n state: State,\n resourceType: T,\n resourceId: string,\n locale?: APIResourceLocale<T>,\n): Extract<APIResource, { __typename: T }> | null {\n switch (resourceType) {\n case APIResourceType.LocalizedGlobalElement:\n if (locale == null) {\n console.error(`Attempt to access ${resourceType} ${resourceId} without a locale`)\n return null\n }\n\n const localizedId = getLocalizedResourceId(state, locale, resourceId)\n return localizedId != null\n ? APIResources.getAPIResource(state.apiResources, resourceType, localizedId, locale)\n : null\n\n default:\n return APIResources.getAPIResource(state.apiResources, resourceType, resourceId, locale)\n }\n}\n\ntype Thunk<ReturnType> = ThunkAction<ReturnType, State, unknown, Action>\n\nexport function fetchAPIResource<T extends APIResourceType>(\n resourceType: T,\n resourceId: string,\n fetch: HttpFetch,\n locale?: APIResourceLocale<T>,\n): Thunk<Promise<Extract<APIResource, { __typename: T }> | null>> {\n const fetchVersioned = async <T>(url: string, version: SiteVersion | null): Promise<T | null> => {\n const response = await fetch(url, {\n headers: {\n 'Content-Type': 'application/json',\n ...(version != null\n ? { [ApiHandlerHeaders.SiteVersion]: serializeSiteVersion(version) }\n : {}),\n },\n })\n\n if (response.status === 404) return null\n if (!response.ok) throw new Error(response.statusText)\n\n if (response.headers.get('content-type')?.includes('application/json') !== true) {\n throw new Error(\n `Expected JSON response from \"${url}\" but got \"${response.headers.get('content-type')}\"`,\n )\n }\n\n return response.json()\n }\n\n return async (dispatch, getState) => {\n const state = getState()\n const version = SiteVersionState.getSiteVersion(state.siteVersion)\n\n if (getHasAPIResource(state, resourceType, resourceId, locale)) {\n return getAPIResource(state, resourceType, resourceId, locale)\n }\n\n let resource: APIResource | null\n\n switch (resourceType) {\n case APIResourceType.Swatch:\n resource = await fetchVersioned<Swatch>(`/api/makeswift/swatches/${resourceId}`, version)\n break\n\n case APIResourceType.File:\n resource = await fetchVersioned<File>(`/api/makeswift/files/${resourceId}`, version)\n break\n\n case APIResourceType.Typography:\n resource = await fetchVersioned<Typography>(\n `/api/makeswift/typographies/${resourceId}`,\n version,\n )\n break\n\n case APIResourceType.GlobalElement:\n resource = await fetchVersioned<GlobalElement>(\n `/api/makeswift/global-elements/${resourceId}`,\n version,\n )\n break\n\n case APIResourceType.LocalizedGlobalElement: {\n if (locale == null) throw new Error('Locale is required to fetch LocalizedGlobalElement')\n\n // If `getLocalizedResourceId` returns null, it means we have tried to fetch the resource,\n // but the resource is not available. If we haven't fetched it yet, it'll return undefined.\n if (getLocalizedResourceId(state, locale, resourceId) === null) {\n return null\n }\n\n resource = await fetchVersioned<LocalizedGlobalElement>(\n `/api/makeswift/localized-global-elements/${resourceId}/${locale}`,\n version,\n )\n\n dispatch(\n setLocalizedResourceId({\n locale,\n resourceId,\n localizedResourceId: resource?.id ?? null,\n }),\n )\n\n break\n }\n\n case APIResourceType.PagePathnameSlice: {\n const url = new URL(`/api/makeswift/page-pathname-slices/${resourceId}`, 'http://n')\n\n if (locale != null) url.searchParams.set('locale', locale)\n\n resource = await fetchVersioned<PagePathnameSlice>(url.pathname + url.search, version)\n break\n }\n\n case APIResourceType.Table:\n resource = await fetchVersioned<Table>(`/api/makeswift/tables/${resourceId}`, version)\n break\n\n default:\n resource = null\n }\n\n dispatch(apiResourceFulfilled(resourceType, resourceId, resource, locale))\n\n return resource as Extract<APIResource, { __typename: T }> | null\n }\n}\n\n// FIXME: this middleware can be removed once we've upgraded the builder\n// to always provide the locale when dispatching resource actions\nfunction defaultLocaleMiddleware(): ThunkMiddleware<State, UnknownAction> {\n return actionMiddleware(({ getState }) => next => {\n return (action: Action) => {\n switch (action.type) {\n case ActionTypes.CHANGE_API_RESOURCE:\n case ActionTypes.EVICT_API_RESOURCE:\n case ActionTypes.SET_LOCALIZED_RESOURCE_ID: {\n const { locale } = action.payload\n return next({\n ...action,\n payload: {\n ...action.payload,\n locale: locale ?? LocaleState.getLocale(getState().locale),\n },\n } as Action)\n }\n }\n\n return next(action)\n }\n })\n}\n\nfunction cacheVersioningMiddleware(): ThunkMiddleware<State, UnknownAction> {\n return actionMiddleware(({ getState, dispatch }) => next => {\n return (action: Action) => {\n switch (action.type) {\n case ReadOnlyActionTypes.SET_SITE_VERSION: {\n const cacheVersion = SiteVersionState.getSiteVersion(getState().siteVersion)\n if (cacheVersion?.version !== action.payload?.version) {\n dispatch(clearAPIClientCache())\n }\n }\n }\n\n return next(action)\n }\n })\n}\n\nexport function configureStore({ serializedState }: { serializedState?: SerializedState }) {\n return configureReduxStore({\n reducer,\n preloadedState: {\n apiResources: APIResources.getInitialState(serializedState?.apiResources),\n localizedResourcesMap: LocalizedResourcesMap.getInitialState(\n serializedState?.localizedResourcesMap,\n ),\n },\n\n middleware: getDefaultMiddleware =>\n getDefaultMiddleware(middlewareOptions).concat(\n defaultLocaleMiddleware(),\n cacheVersioningMiddleware(),\n ),\n\n devTools: devToolsConfig({\n name: `API client store (${new Date().toISOString()})`,\n actionsDenylist: [\n ActionTypes.BUILDER_POINTER_MOVE,\n ActionTypes.HANDLE_POINTER_MOVE,\n ActionTypes.ELEMENT_FROM_POINT_CHANGE,\n ],\n }),\n })\n}\n\nexport type Store = ReturnType<typeof configureStore>\n"],"mappings":"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","names":["import_toolkit","configureReduxStore"]}
@@ -132,6 +132,9 @@ function reducer(state = getInitialState(), action) {
132
132
  return updated == null || updated === existing ? state2 : new Map(state2).set(resType, updated);
133
133
  }, state);
134
134
  }
135
+ case import_read_write_actions.ReadWriteActionTypes.CLEAR_API_CLIENT_CACHE: {
136
+ return getInitialState();
137
+ }
135
138
  case import_read_only_actions.ReadOnlyActionTypes.API_RESOURCE_FULFILLED: {
136
139
  const { resourceType, resourceId, resource, locale } = action.payload;
137
140
  return new Map(state).set(
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/state/modules/api-resources.ts"],"sourcesContent":["import {\n APIResourceType,\n APIResourceLocale,\n LocalizableAPIResourceType,\n type APIResource,\n} from '../../api'\n\nimport deepEqual from '../../utils/deepEqual'\nimport { Branded } from '../../utils/branded'\n\nimport { type Action, type UnknownAction, isKnownAction } from '../actions'\nimport { ReadOnlyActionTypes } from '../actions/internal/read-only-actions'\nimport { ReadWriteActionTypes } from '../actions/internal/read-write-actions'\nimport { HostActionTypes } from '../host-api'\n\ntype CompositeResourceId = Branded<string, 'CompositeResourceId'>\n\nfunction isValidAPIResourceType(resourceType: string): resourceType is APIResourceType {\n return resourceType in APIResourceType\n}\n\nfunction isLocalizableAPIResourceType(\n resourceType: APIResourceType,\n): resourceType is LocalizableAPIResourceType {\n return resourceType in LocalizableAPIResourceType\n}\n\nfunction compositeId(\n resourceId: string,\n resourceType: APIResourceType,\n locale?: string | null,\n): CompositeResourceId {\n return (\n locale != null && isLocalizableAPIResourceType(resourceType)\n ? `${resourceId}@${locale}`\n : resourceId\n ) as CompositeResourceId\n}\n\nfunction parseCompositeId(compositeId: CompositeResourceId): [string, string | null] {\n const [resourceId, locale] = compositeId.split('@')\n return [resourceId, locale ?? null]\n}\n\nexport type State = Map<APIResourceType, Map<CompositeResourceId, APIResource | null>>\n\nexport type SerializedState = {\n [key in APIResourceType]?: {\n id: string\n value: Extract<APIResource, { __typename: key }> | null\n locale?: APIResourceLocale<key>\n }[]\n}\n\nexport function getInitialState(\n serializedState: SerializedState = {\n Swatch: [],\n File: [],\n Typography: [],\n PagePathnameSlice: [],\n GlobalElement: [],\n Table: [],\n Snippet: [],\n Page: [],\n Site: [],\n LocalizedGlobalElement: [],\n },\n): State {\n return new Map(\n Object.entries(serializedState).map(([resourceType, resources]) => [\n resourceType,\n new Map(\n resources.map(({ id, value, locale }) => [\n compositeId(id, resourceType as APIResourceType, locale),\n value,\n ]),\n ),\n ]),\n ) as State\n}\n\nexport function getSerializedState(state: State): SerializedState {\n const resourceMap: SerializedState = {\n Swatch: [],\n File: [],\n Typography: [],\n PagePathnameSlice: [],\n GlobalElement: [],\n Table: [],\n Snippet: [],\n Page: [],\n Site: [],\n LocalizedGlobalElement: [],\n }\n\n Array.from(state.entries()).forEach(([resourceType, resources]) => {\n const particularResourceMap: { id: string; value: any; locale?: any }[] = []\n\n Array.from(resources.entries()).forEach(([compositeId, value]) => {\n if (value != null) {\n const [id, locale] = parseCompositeId(compositeId)\n console.assert(\n locale == null || isLocalizableAPIResourceType(resourceType),\n `Unexpected locale for non-localizable resource type ${resourceType}`,\n { id, locale },\n )\n\n particularResourceMap.push(locale != null ? { id, value, locale } : { id, value })\n }\n })\n\n resourceMap[resourceType] = particularResourceMap\n })\n\n return resourceMap\n}\n\nexport function getHasAPIResource<T extends APIResourceType>(\n state: State,\n resourceType: T,\n resourceId: string,\n locale?: APIResourceLocale<T>,\n): boolean {\n return state.get(resourceType)?.has(compositeId(resourceId, resourceType, locale)) ?? false\n}\n\nexport function getAPIResource<T extends APIResourceType>(\n state: State,\n resourceType: T,\n resourceId: string,\n locale?: APIResourceLocale<T>,\n): Extract<APIResource, { __typename: T }> | null {\n const resource = state.get(resourceType)?.get(compositeId(resourceId, resourceType, locale))\n\n return resource?.__typename === resourceType\n ? (resource as Extract<typeof resource, { __typename: T }>)\n : null\n}\n\nexport function reducer(state: State = getInitialState(), action: Action | UnknownAction): State {\n if (!isKnownAction(action)) return state\n\n switch (action.type) {\n case ReadWriteActionTypes.UPDATE_API_CLIENT_CACHE: {\n const { apiResources } = action.payload\n\n return Object.entries(apiResources).reduce((state, [resourceType, cachedResources]) => {\n const resType = resourceType as APIResourceType\n const cached:\n | { id: string; value: APIResource | null; locale?: string | null }[]\n | undefined = cachedResources\n\n const existing = state.get(resType) ?? new Map<CompositeResourceId, APIResource | null>()\n const updated = cached?.reduce((r, { id, value, locale }) => {\n const cid = compositeId(id, resType, locale)\n return r.get(cid) != null ? r : new Map(r).set(cid, value)\n }, existing)\n\n return updated == null || updated === existing\n ? state\n : new Map(state).set(resType, updated)\n }, state)\n }\n\n case ReadOnlyActionTypes.API_RESOURCE_FULFILLED: {\n const { resourceType, resourceId, resource, locale } = action.payload\n return new Map(state).set(\n resourceType,\n new Map(state.get(resourceType)!).set(\n compositeId(resourceId, resourceType, locale),\n resource,\n ),\n )\n }\n\n case HostActionTypes.CHANGE_API_RESOURCE: {\n const { resource, locale } = action.payload\n const existingApiResource = getAPIResource(state, resource.__typename, resource.id, locale)\n\n if (deepEqual(existingApiResource, resource)) return state\n\n return new Map(state).set(\n resource.__typename,\n new Map(state.get(resource.__typename)!).set(\n compositeId(resource.id, resource.__typename, locale),\n resource,\n ),\n )\n }\n\n case HostActionTypes.EVICT_API_RESOURCE: {\n const { id, locale } = action.payload\n const [resourceType, resourceId] = id.split(':')\n\n if (!isValidAPIResourceType(resourceType)) return state\n\n const resources = new Map(state.get(resourceType as APIResourceType)!)\n\n const deleted = resources.delete(compositeId(resourceId, resourceType, locale))\n\n return deleted ? new Map(state).set(resourceType as APIResourceType, resources) : state\n }\n\n default:\n return state\n }\n}\n"],"mappings":"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","names":["compositeId","state","deepEqual"]}
1
+ {"version":3,"sources":["../../../../src/state/modules/api-resources.ts"],"sourcesContent":["import {\n APIResourceType,\n APIResourceLocale,\n LocalizableAPIResourceType,\n type APIResource,\n} from '../../api'\n\nimport deepEqual from '../../utils/deepEqual'\nimport { Branded } from '../../utils/branded'\n\nimport { type Action, type UnknownAction, isKnownAction } from '../actions'\nimport { ReadOnlyActionTypes } from '../actions/internal/read-only-actions'\nimport { ReadWriteActionTypes } from '../actions/internal/read-write-actions'\nimport { HostActionTypes } from '../host-api'\n\ntype CompositeResourceId = Branded<string, 'CompositeResourceId'>\n\nfunction isValidAPIResourceType(resourceType: string): resourceType is APIResourceType {\n return resourceType in APIResourceType\n}\n\nfunction isLocalizableAPIResourceType(\n resourceType: APIResourceType,\n): resourceType is LocalizableAPIResourceType {\n return resourceType in LocalizableAPIResourceType\n}\n\nfunction compositeId(\n resourceId: string,\n resourceType: APIResourceType,\n locale?: string | null,\n): CompositeResourceId {\n return (\n locale != null && isLocalizableAPIResourceType(resourceType)\n ? `${resourceId}@${locale}`\n : resourceId\n ) as CompositeResourceId\n}\n\nfunction parseCompositeId(compositeId: CompositeResourceId): [string, string | null] {\n const [resourceId, locale] = compositeId.split('@')\n return [resourceId, locale ?? null]\n}\n\nexport type State = Map<APIResourceType, Map<CompositeResourceId, APIResource | null>>\n\nexport type SerializedState = {\n [key in APIResourceType]?: {\n id: string\n value: Extract<APIResource, { __typename: key }> | null\n locale?: APIResourceLocale<key>\n }[]\n}\n\nexport function getInitialState(\n serializedState: SerializedState = {\n Swatch: [],\n File: [],\n Typography: [],\n PagePathnameSlice: [],\n GlobalElement: [],\n Table: [],\n Snippet: [],\n Page: [],\n Site: [],\n LocalizedGlobalElement: [],\n },\n): State {\n return new Map(\n Object.entries(serializedState).map(([resourceType, resources]) => [\n resourceType,\n new Map(\n resources.map(({ id, value, locale }) => [\n compositeId(id, resourceType as APIResourceType, locale),\n value,\n ]),\n ),\n ]),\n ) as State\n}\n\nexport function getSerializedState(state: State): SerializedState {\n const resourceMap: SerializedState = {\n Swatch: [],\n File: [],\n Typography: [],\n PagePathnameSlice: [],\n GlobalElement: [],\n Table: [],\n Snippet: [],\n Page: [],\n Site: [],\n LocalizedGlobalElement: [],\n }\n\n Array.from(state.entries()).forEach(([resourceType, resources]) => {\n const particularResourceMap: { id: string; value: any; locale?: any }[] = []\n\n Array.from(resources.entries()).forEach(([compositeId, value]) => {\n if (value != null) {\n const [id, locale] = parseCompositeId(compositeId)\n console.assert(\n locale == null || isLocalizableAPIResourceType(resourceType),\n `Unexpected locale for non-localizable resource type ${resourceType}`,\n { id, locale },\n )\n\n particularResourceMap.push(locale != null ? { id, value, locale } : { id, value })\n }\n })\n\n resourceMap[resourceType] = particularResourceMap\n })\n\n return resourceMap\n}\n\nexport function getHasAPIResource<T extends APIResourceType>(\n state: State,\n resourceType: T,\n resourceId: string,\n locale?: APIResourceLocale<T>,\n): boolean {\n return state.get(resourceType)?.has(compositeId(resourceId, resourceType, locale)) ?? false\n}\n\nexport function getAPIResource<T extends APIResourceType>(\n state: State,\n resourceType: T,\n resourceId: string,\n locale?: APIResourceLocale<T>,\n): Extract<APIResource, { __typename: T }> | null {\n const resource = state.get(resourceType)?.get(compositeId(resourceId, resourceType, locale))\n\n return resource?.__typename === resourceType\n ? (resource as Extract<typeof resource, { __typename: T }>)\n : null\n}\n\nexport function reducer(state: State = getInitialState(), action: Action | UnknownAction): State {\n if (!isKnownAction(action)) return state\n\n switch (action.type) {\n case ReadWriteActionTypes.UPDATE_API_CLIENT_CACHE: {\n const { apiResources } = action.payload\n\n return Object.entries(apiResources).reduce((state, [resourceType, cachedResources]) => {\n const resType = resourceType as APIResourceType\n const cached:\n | { id: string; value: APIResource | null; locale?: string | null }[]\n | undefined = cachedResources\n\n const existing = state.get(resType) ?? new Map<CompositeResourceId, APIResource | null>()\n const updated = cached?.reduce((r, { id, value, locale }) => {\n const cid = compositeId(id, resType, locale)\n return r.get(cid) != null ? r : new Map(r).set(cid, value)\n }, existing)\n\n return updated == null || updated === existing\n ? state\n : new Map(state).set(resType, updated)\n }, state)\n }\n\n case ReadWriteActionTypes.CLEAR_API_CLIENT_CACHE: {\n return getInitialState()\n }\n\n case ReadOnlyActionTypes.API_RESOURCE_FULFILLED: {\n const { resourceType, resourceId, resource, locale } = action.payload\n return new Map(state).set(\n resourceType,\n new Map(state.get(resourceType)!).set(\n compositeId(resourceId, resourceType, locale),\n resource,\n ),\n )\n }\n\n case HostActionTypes.CHANGE_API_RESOURCE: {\n const { resource, locale } = action.payload\n const existingApiResource = getAPIResource(state, resource.__typename, resource.id, locale)\n\n if (deepEqual(existingApiResource, resource)) return state\n\n return new Map(state).set(\n resource.__typename,\n new Map(state.get(resource.__typename)!).set(\n compositeId(resource.id, resource.__typename, locale),\n resource,\n ),\n )\n }\n\n case HostActionTypes.EVICT_API_RESOURCE: {\n const { id, locale } = action.payload\n const [resourceType, resourceId] = id.split(':')\n\n if (!isValidAPIResourceType(resourceType)) return state\n\n const resources = new Map(state.get(resourceType as APIResourceType)!)\n\n const deleted = resources.delete(compositeId(resourceId, resourceType, locale))\n\n return deleted ? new Map(state).set(resourceType as APIResourceType, resources) : state\n }\n\n default:\n return state\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAKO;AAEP,uBAAsB;AAGtB,qBAA+D;AAC/D,+BAAoC;AACpC,gCAAqC;AACrC,sBAAgC;AAIhC,SAAS,uBAAuB,cAAuD;AACrF,SAAO,gBAAgB;AACzB;AAEA,SAAS,6BACP,cAC4C;AAC5C,SAAO,gBAAgB;AACzB;AAEA,SAAS,YACP,YACA,cACA,QACqB;AACrB,SACE,UAAU,QAAQ,6BAA6B,YAAY,IACvD,GAAG,UAAU,IAAI,MAAM,KACvB;AAER;AAEA,SAAS,iBAAiBA,cAA2D;AACnF,QAAM,CAAC,YAAY,MAAM,IAAIA,aAAY,MAAM,GAAG;AAClD,SAAO,CAAC,YAAY,UAAU,IAAI;AACpC;AAYO,SAAS,gBACd,kBAAmC;AAAA,EACjC,QAAQ,CAAC;AAAA,EACT,MAAM,CAAC;AAAA,EACP,YAAY,CAAC;AAAA,EACb,mBAAmB,CAAC;AAAA,EACpB,eAAe,CAAC;AAAA,EAChB,OAAO,CAAC;AAAA,EACR,SAAS,CAAC;AAAA,EACV,MAAM,CAAC;AAAA,EACP,MAAM,CAAC;AAAA,EACP,wBAAwB,CAAC;AAC3B,GACO;AACP,SAAO,IAAI;AAAA,IACT,OAAO,QAAQ,eAAe,EAAE,IAAI,CAAC,CAAC,cAAc,SAAS,MAAM;AAAA,MACjE;AAAA,MACA,IAAI;AAAA,QACF,UAAU,IAAI,CAAC,EAAE,IAAI,OAAO,OAAO,MAAM;AAAA,UACvC,YAAY,IAAI,cAAiC,MAAM;AAAA,UACvD;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAEO,SAAS,mBAAmB,OAA+B;AAChE,QAAM,cAA+B;AAAA,IACnC,QAAQ,CAAC;AAAA,IACT,MAAM,CAAC;AAAA,IACP,YAAY,CAAC;AAAA,IACb,mBAAmB,CAAC;AAAA,IACpB,eAAe,CAAC;AAAA,IAChB,OAAO,CAAC;AAAA,IACR,SAAS,CAAC;AAAA,IACV,MAAM,CAAC;AAAA,IACP,MAAM,CAAC;AAAA,IACP,wBAAwB,CAAC;AAAA,EAC3B;AAEA,QAAM,KAAK,MAAM,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC,cAAc,SAAS,MAAM;AACjE,UAAM,wBAAoE,CAAC;AAE3E,UAAM,KAAK,UAAU,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAACA,cAAa,KAAK,MAAM;AAChE,UAAI,SAAS,MAAM;AACjB,cAAM,CAAC,IAAI,MAAM,IAAI,iBAAiBA,YAAW;AACjD,gBAAQ;AAAA,UACN,UAAU,QAAQ,6BAA6B,YAAY;AAAA,UAC3D,uDAAuD,YAAY;AAAA,UACnE,EAAE,IAAI,OAAO;AAAA,QACf;AAEA,8BAAsB,KAAK,UAAU,OAAO,EAAE,IAAI,OAAO,OAAO,IAAI,EAAE,IAAI,MAAM,CAAC;AAAA,MACnF;AAAA,IACF,CAAC;AAED,gBAAY,YAAY,IAAI;AAAA,EAC9B,CAAC;AAED,SAAO;AACT;AAEO,SAAS,kBACd,OACA,cACA,YACA,QACS;AACT,SAAO,MAAM,IAAI,YAAY,GAAG,IAAI,YAAY,YAAY,cAAc,MAAM,CAAC,KAAK;AACxF;AAEO,SAAS,eACd,OACA,cACA,YACA,QACgD;AAChD,QAAM,WAAW,MAAM,IAAI,YAAY,GAAG,IAAI,YAAY,YAAY,cAAc,MAAM,CAAC;AAE3F,SAAO,UAAU,eAAe,eAC3B,WACD;AACN;AAEO,SAAS,QAAQ,QAAe,gBAAgB,GAAG,QAAuC;AAC/F,MAAI,KAAC,8BAAc,MAAM;AAAG,WAAO;AAEnC,UAAQ,OAAO,MAAM;AAAA,IACnB,KAAK,+CAAqB,yBAAyB;AACjD,YAAM,EAAE,aAAa,IAAI,OAAO;AAEhC,aAAO,OAAO,QAAQ,YAAY,EAAE,OAAO,CAACC,QAAO,CAAC,cAAc,eAAe,MAAM;AACrF,cAAM,UAAU;AAChB,cAAM,SAEU;AAEhB,cAAM,WAAWA,OAAM,IAAI,OAAO,KAAK,oBAAI,IAA6C;AACxF,cAAM,UAAU,QAAQ,OAAO,CAAC,GAAG,EAAE,IAAI,OAAO,OAAO,MAAM;AAC3D,gBAAM,MAAM,YAAY,IAAI,SAAS,MAAM;AAC3C,iBAAO,EAAE,IAAI,GAAG,KAAK,OAAO,IAAI,IAAI,IAAI,CAAC,EAAE,IAAI,KAAK,KAAK;AAAA,QAC3D,GAAG,QAAQ;AAEX,eAAO,WAAW,QAAQ,YAAY,WAClCA,SACA,IAAI,IAAIA,MAAK,EAAE,IAAI,SAAS,OAAO;AAAA,MACzC,GAAG,KAAK;AAAA,IACV;AAAA,IAEA,KAAK,+CAAqB,wBAAwB;AAChD,aAAO,gBAAgB;AAAA,IACzB;AAAA,IAEA,KAAK,6CAAoB,wBAAwB;AAC/C,YAAM,EAAE,cAAc,YAAY,UAAU,OAAO,IAAI,OAAO;AAC9D,aAAO,IAAI,IAAI,KAAK,EAAE;AAAA,QACpB;AAAA,QACA,IAAI,IAAI,MAAM,IAAI,YAAY,CAAE,EAAE;AAAA,UAChC,YAAY,YAAY,cAAc,MAAM;AAAA,UAC5C;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IAEA,KAAK,gCAAgB,qBAAqB;AACxC,YAAM,EAAE,UAAU,OAAO,IAAI,OAAO;AACpC,YAAM,sBAAsB,eAAe,OAAO,SAAS,YAAY,SAAS,IAAI,MAAM;AAE1F,cAAI,iBAAAC,SAAU,qBAAqB,QAAQ;AAAG,eAAO;AAErD,aAAO,IAAI,IAAI,KAAK,EAAE;AAAA,QACpB,SAAS;AAAA,QACT,IAAI,IAAI,MAAM,IAAI,SAAS,UAAU,CAAE,EAAE;AAAA,UACvC,YAAY,SAAS,IAAI,SAAS,YAAY,MAAM;AAAA,UACpD;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IAEA,KAAK,gCAAgB,oBAAoB;AACvC,YAAM,EAAE,IAAI,OAAO,IAAI,OAAO;AAC9B,YAAM,CAAC,cAAc,UAAU,IAAI,GAAG,MAAM,GAAG;AAE/C,UAAI,CAAC,uBAAuB,YAAY;AAAG,eAAO;AAElD,YAAM,YAAY,IAAI,IAAI,MAAM,IAAI,YAA+B,CAAE;AAErE,YAAM,UAAU,UAAU,OAAO,YAAY,YAAY,cAAc,MAAM,CAAC;AAE9E,aAAO,UAAU,IAAI,IAAI,KAAK,EAAE,IAAI,cAAiC,SAAS,IAAI;AAAA,IACpF;AAAA,IAEA;AACE,aAAO;AAAA,EACX;AACF;","names":["compositeId","state","deepEqual"]}
@@ -70,6 +70,9 @@ function reducer(state = getInitialState(), action) {
70
70
  return updated === existing ? state2 : new Map(state2).set(locale, updated);
71
71
  }, state);
72
72
  }
73
+ case import_read_write_actions.ReadWriteActionTypes.CLEAR_API_CLIENT_CACHE: {
74
+ return getInitialState();
75
+ }
73
76
  default:
74
77
  return state;
75
78
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/state/modules/localized-resources-map.ts"],"sourcesContent":["import { mapValues } from '@makeswift/controls'\nimport { type Action, type UnknownAction, isKnownAction } from '../actions'\nimport { ReadWriteActionTypes } from '../actions/internal/read-write-actions'\nimport { HostActionTypes } from '../host-api'\n\ntype State = Map<string, Map<string, string | null>>\n\nexport type SerializedState = {\n [locale: string]: {\n [resourceId: string]: string | null\n }\n}\n\nexport function getInitialState(serializedState: SerializedState = {}): State {\n return new Map(\n Object.entries(mapValues(serializedState, resources => new Map(Object.entries(resources)))),\n )\n}\n\nexport function getSerializedState(state: State): SerializedState {\n return mapValues(Object.fromEntries(state.entries()), resources =>\n Object.fromEntries(resources.entries()),\n )\n}\n\nexport function getLocalizedResourceId(\n state: State,\n locale: string,\n resourceId: string,\n): string | undefined | null {\n return state.get(locale)?.get(resourceId)\n}\n\nexport function reducer(state: State = getInitialState(), action: Action | UnknownAction): State {\n if (!isKnownAction(action)) return state\n\n switch (action.type) {\n case HostActionTypes.SET_LOCALIZED_RESOURCE_ID: {\n const { resourceId, localizedResourceId, locale } = action.payload\n\n if (locale == null) {\n console.error('Attempt to set a localized resource ID for a non-localized page', {\n resourceId,\n localizedResourceId,\n })\n\n return state\n }\n\n return new Map(state).set(\n locale,\n (state.get(locale) ?? new Map()).set(resourceId, localizedResourceId),\n )\n }\n\n case ReadWriteActionTypes.UPDATE_API_CLIENT_CACHE: {\n const { localizedResourcesMap } = action.payload\n\n return Object.entries(localizedResourcesMap).reduce((state, [locale, resources]) => {\n const existing = state.get(locale) ?? new Map<string, string | null>()\n const updated = Object.entries(resources).reduce((r, [id, localizedId]) => {\n return r.get(id) != null ? r : new Map(r).set(id, localizedId)\n }, existing)\n\n return updated === existing ? state : new Map(state).set(locale, updated)\n }, state)\n }\n\n default:\n return state\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAA0B;AAC1B,qBAA+D;AAC/D,gCAAqC;AACrC,sBAAgC;AAUzB,SAAS,gBAAgB,kBAAmC,CAAC,GAAU;AAC5E,SAAO,IAAI;AAAA,IACT,OAAO,YAAQ,2BAAU,iBAAiB,eAAa,IAAI,IAAI,OAAO,QAAQ,SAAS,CAAC,CAAC,CAAC;AAAA,EAC5F;AACF;AAEO,SAAS,mBAAmB,OAA+B;AAChE,aAAO;AAAA,IAAU,OAAO,YAAY,MAAM,QAAQ,CAAC;AAAA,IAAG,eACpD,OAAO,YAAY,UAAU,QAAQ,CAAC;AAAA,EACxC;AACF;AAEO,SAAS,uBACd,OACA,QACA,YAC2B;AAC3B,SAAO,MAAM,IAAI,MAAM,GAAG,IAAI,UAAU;AAC1C;AAEO,SAAS,QAAQ,QAAe,gBAAgB,GAAG,QAAuC;AAC/F,MAAI,KAAC,8BAAc,MAAM;AAAG,WAAO;AAEnC,UAAQ,OAAO,MAAM;AAAA,IACnB,KAAK,gCAAgB,2BAA2B;AAC9C,YAAM,EAAE,YAAY,qBAAqB,OAAO,IAAI,OAAO;AAE3D,UAAI,UAAU,MAAM;AAClB,gBAAQ,MAAM,mEAAmE;AAAA,UAC/E;AAAA,UACA;AAAA,QACF,CAAC;AAED,eAAO;AAAA,MACT;AAEA,aAAO,IAAI,IAAI,KAAK,EAAE;AAAA,QACpB;AAAA,SACC,MAAM,IAAI,MAAM,KAAK,oBAAI,IAAI,GAAG,IAAI,YAAY,mBAAmB;AAAA,MACtE;AAAA,IACF;AAAA,IAEA,KAAK,+CAAqB,yBAAyB;AACjD,YAAM,EAAE,sBAAsB,IAAI,OAAO;AAEzC,aAAO,OAAO,QAAQ,qBAAqB,EAAE,OAAO,CAACA,QAAO,CAAC,QAAQ,SAAS,MAAM;AAClF,cAAM,WAAWA,OAAM,IAAI,MAAM,KAAK,oBAAI,IAA2B;AACrE,cAAM,UAAU,OAAO,QAAQ,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,IAAI,WAAW,MAAM;AACzE,iBAAO,EAAE,IAAI,EAAE,KAAK,OAAO,IAAI,IAAI,IAAI,CAAC,EAAE,IAAI,IAAI,WAAW;AAAA,QAC/D,GAAG,QAAQ;AAEX,eAAO,YAAY,WAAWA,SAAQ,IAAI,IAAIA,MAAK,EAAE,IAAI,QAAQ,OAAO;AAAA,MAC1E,GAAG,KAAK;AAAA,IACV;AAAA,IAEA;AACE,aAAO;AAAA,EACX;AACF;","names":["state"]}
1
+ {"version":3,"sources":["../../../../src/state/modules/localized-resources-map.ts"],"sourcesContent":["import { mapValues } from '@makeswift/controls'\nimport { type Action, type UnknownAction, isKnownAction } from '../actions'\nimport { ReadWriteActionTypes } from '../actions/internal/read-write-actions'\nimport { HostActionTypes } from '../host-api'\n\ntype State = Map<string, Map<string, string | null>>\n\nexport type SerializedState = {\n [locale: string]: {\n [resourceId: string]: string | null\n }\n}\n\nexport function getInitialState(serializedState: SerializedState = {}): State {\n return new Map(\n Object.entries(mapValues(serializedState, resources => new Map(Object.entries(resources)))),\n )\n}\n\nexport function getSerializedState(state: State): SerializedState {\n return mapValues(Object.fromEntries(state.entries()), resources =>\n Object.fromEntries(resources.entries()),\n )\n}\n\nexport function getLocalizedResourceId(\n state: State,\n locale: string,\n resourceId: string,\n): string | undefined | null {\n return state.get(locale)?.get(resourceId)\n}\n\nexport function reducer(state: State = getInitialState(), action: Action | UnknownAction): State {\n if (!isKnownAction(action)) return state\n\n switch (action.type) {\n case HostActionTypes.SET_LOCALIZED_RESOURCE_ID: {\n const { resourceId, localizedResourceId, locale } = action.payload\n\n if (locale == null) {\n console.error('Attempt to set a localized resource ID for a non-localized page', {\n resourceId,\n localizedResourceId,\n })\n\n return state\n }\n\n return new Map(state).set(\n locale,\n (state.get(locale) ?? new Map()).set(resourceId, localizedResourceId),\n )\n }\n\n case ReadWriteActionTypes.UPDATE_API_CLIENT_CACHE: {\n const { localizedResourcesMap } = action.payload\n\n return Object.entries(localizedResourcesMap).reduce((state, [locale, resources]) => {\n const existing = state.get(locale) ?? new Map<string, string | null>()\n const updated = Object.entries(resources).reduce((r, [id, localizedId]) => {\n return r.get(id) != null ? r : new Map(r).set(id, localizedId)\n }, existing)\n\n return updated === existing ? state : new Map(state).set(locale, updated)\n }, state)\n }\n\n case ReadWriteActionTypes.CLEAR_API_CLIENT_CACHE: {\n return getInitialState()\n }\n\n default:\n return state\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAA0B;AAC1B,qBAA+D;AAC/D,gCAAqC;AACrC,sBAAgC;AAUzB,SAAS,gBAAgB,kBAAmC,CAAC,GAAU;AAC5E,SAAO,IAAI;AAAA,IACT,OAAO,YAAQ,2BAAU,iBAAiB,eAAa,IAAI,IAAI,OAAO,QAAQ,SAAS,CAAC,CAAC,CAAC;AAAA,EAC5F;AACF;AAEO,SAAS,mBAAmB,OAA+B;AAChE,aAAO;AAAA,IAAU,OAAO,YAAY,MAAM,QAAQ,CAAC;AAAA,IAAG,eACpD,OAAO,YAAY,UAAU,QAAQ,CAAC;AAAA,EACxC;AACF;AAEO,SAAS,uBACd,OACA,QACA,YAC2B;AAC3B,SAAO,MAAM,IAAI,MAAM,GAAG,IAAI,UAAU;AAC1C;AAEO,SAAS,QAAQ,QAAe,gBAAgB,GAAG,QAAuC;AAC/F,MAAI,KAAC,8BAAc,MAAM;AAAG,WAAO;AAEnC,UAAQ,OAAO,MAAM;AAAA,IACnB,KAAK,gCAAgB,2BAA2B;AAC9C,YAAM,EAAE,YAAY,qBAAqB,OAAO,IAAI,OAAO;AAE3D,UAAI,UAAU,MAAM;AAClB,gBAAQ,MAAM,mEAAmE;AAAA,UAC/E;AAAA,UACA;AAAA,QACF,CAAC;AAED,eAAO;AAAA,MACT;AAEA,aAAO,IAAI,IAAI,KAAK,EAAE;AAAA,QACpB;AAAA,SACC,MAAM,IAAI,MAAM,KAAK,oBAAI,IAAI,GAAG,IAAI,YAAY,mBAAmB;AAAA,MACtE;AAAA,IACF;AAAA,IAEA,KAAK,+CAAqB,yBAAyB;AACjD,YAAM,EAAE,sBAAsB,IAAI,OAAO;AAEzC,aAAO,OAAO,QAAQ,qBAAqB,EAAE,OAAO,CAACA,QAAO,CAAC,QAAQ,SAAS,MAAM;AAClF,cAAM,WAAWA,OAAM,IAAI,MAAM,KAAK,oBAAI,IAA2B;AACrE,cAAM,UAAU,OAAO,QAAQ,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,IAAI,WAAW,MAAM;AACzE,iBAAO,EAAE,IAAI,EAAE,KAAK,OAAO,IAAI,IAAI,IAAI,CAAC,EAAE,IAAI,IAAI,WAAW;AAAA,QAC/D,GAAG,QAAQ;AAEX,eAAO,YAAY,WAAWA,SAAQ,IAAI,IAAIA,MAAK,EAAE,IAAI,QAAQ,OAAO;AAAA,MAC1E,GAAG,KAAK;AAAA,IACV;AAAA,IAEA,KAAK,+CAAqB,wBAAwB;AAChD,aAAO,gBAAgB;AAAA,IACzB;AAAA,IAEA;AACE,aAAO;AAAA,EACX;AACF;","names":["state"]}
@@ -8,7 +8,7 @@ async function manifestHandler(req, { apiKey, manifest }) {
8
8
  return ApiResponse.json({ message: "Unauthorized" }, { status: 401 });
9
9
  }
10
10
  return ApiResponse.json({
11
- version: "0.27.0-canary.2",
11
+ version: "0.27.0",
12
12
  interactionMode: true,
13
13
  clientSideNavigation: false,
14
14
  elementFromPoint: false,
@@ -188,7 +188,7 @@ Received "${apiKey}" instead.`
188
188
  }
189
189
  this.apiKey = apiKey;
190
190
  this.graphqlClient = new GraphQLClient(new URL("graphql", runtime.apiOrigin).href, {
191
- "makeswift-runtime-version": "0.27.0-canary.2"
191
+ "makeswift-runtime-version": "0.27.0"
192
192
  });
193
193
  this.runtime = runtime;
194
194
  }
@@ -200,7 +200,7 @@ Received "${apiKey}" instead.`
200
200
  const requestHeaders = new Headers({
201
201
  "x-api-key": this.apiKey,
202
202
  "makeswift-site-api-key": this.apiKey,
203
- "makeswift-runtime-version": "0.27.0-canary.2"
203
+ "makeswift-runtime-version": "0.27.0"
204
204
  });
205
205
  if (siteVersion?.token) {
206
206
  requestUrl.searchParams.set("version", siteVersion.version);
@@ -647,7 +647,7 @@ Received "${apiKey}" instead.`
647
647
  headers: {
648
648
  "x-api-key": this.apiKey,
649
649
  "makeswift-site-api-key": this.apiKey,
650
- "makeswift-runtime-version": "0.27.0-canary.2",
650
+ "makeswift-runtime-version": "0.27.0",
651
651
  "content-type": "application/json"
652
652
  },
653
653
  body: JSON.stringify({ token }),
@@ -3,7 +3,6 @@ import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import { useMemo } from "react";
4
4
  import { ReactRuntimeContext } from "../hooks/use-react-runtime";
5
5
  import { useAsyncEffect } from "../hooks/use-async-effect";
6
- import { useBuilderConnectionPing } from "./hooks/use-builder-connection-ping";
7
6
  import { PreviewSwitcher } from "./preview-switcher/preview-switcher";
8
7
  function RuntimeProvider({
9
8
  children,
@@ -18,7 +17,6 @@ function RuntimeProvider({
18
17
  () => runtime.setIdempotent({ siteVersion, isReadOnly, locale }),
19
18
  [runtime, siteVersion, isReadOnly, locale]
20
19
  );
21
- useBuilderConnectionPing({ appOrigin: runtime.appOrigin });
22
20
  useAsyncEffect(() => runtime.setupStore({ isReadOnly }), [runtime, isReadOnly]);
23
21
  return /* @__PURE__ */ jsxs(ReactRuntimeContext.Provider, { value: runtime, children: [
24
22
  children,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/runtimes/react/components/RuntimeProvider.tsx"],"sourcesContent":["'use client'\n\nimport { ReactNode, useMemo } from 'react'\n\nimport { type SiteVersion } from '../../../api/site-version'\n\nimport { ReactRuntimeContext } from '../hooks/use-react-runtime'\nimport { useAsyncEffect } from '../hooks/use-async-effect'\nimport { type ReactRuntimeCore } from '../react-runtime-core'\n\nimport { useBuilderConnectionPing } from './hooks/use-builder-connection-ping'\nimport { PreviewSwitcher } from './preview-switcher/preview-switcher'\n\nexport function RuntimeProvider({\n children,\n runtime,\n siteVersion: siteVersionProp,\n locale = undefined,\n}: {\n children: ReactNode\n runtime: ReactRuntimeCore\n siteVersion: SiteVersion | null | undefined\n locale?: string\n}) {\n const siteVersion = siteVersionProp ?? null\n const isPreview = siteVersion != null\n // TODO: we need to decouple editability from the site version; specifically, previewing\n // a draft version of the site should not lead to switching to the read-write state\n const isReadOnly = siteVersion == null\n\n // setting idempotent part of the state on render to have parity between server-side and\n // client-side rendering depending on this state; `useMemo` here is purely a performance\n // optimization; prior art for performing idempotent side effects on render:\n // https://github.com/TanStack/query/blob/8f9f183f11df3709a1a38c4efce1452788041f88/packages/react-query/src/HydrationBoundary.tsx#L41\n useMemo(\n () => runtime.setIdempotent({ siteVersion, isReadOnly, locale }),\n [runtime, siteVersion, isReadOnly, locale],\n )\n\n useBuilderConnectionPing({ appOrigin: runtime.appOrigin })\n\n useAsyncEffect(() => runtime.setupStore({ isReadOnly }), [runtime, isReadOnly])\n\n return (\n <ReactRuntimeContext.Provider value={runtime}>\n {children}\n <PreviewSwitcher isPreview={isPreview} />\n </ReactRuntimeContext.Provider>\n )\n}\n"],"mappings":";AA4CI,SAEE,KAFF;AA1CJ,SAAoB,eAAe;AAInC,SAAS,2BAA2B;AACpC,SAAS,sBAAsB;AAG/B,SAAS,gCAAgC;AACzC,SAAS,uBAAuB;AAEzB,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA,aAAa;AAAA,EACb,SAAS;AACX,GAKG;AACD,QAAM,cAAc,mBAAmB;AACvC,QAAM,YAAY,eAAe;AAGjC,QAAM,aAAa,eAAe;AAMlC;AAAA,IACE,MAAM,QAAQ,cAAc,EAAE,aAAa,YAAY,OAAO,CAAC;AAAA,IAC/D,CAAC,SAAS,aAAa,YAAY,MAAM;AAAA,EAC3C;AAEA,2BAAyB,EAAE,WAAW,QAAQ,UAAU,CAAC;AAEzD,iBAAe,MAAM,QAAQ,WAAW,EAAE,WAAW,CAAC,GAAG,CAAC,SAAS,UAAU,CAAC;AAE9E,SACE,qBAAC,oBAAoB,UAApB,EAA6B,OAAO,SAClC;AAAA;AAAA,IACD,oBAAC,mBAAgB,WAAsB;AAAA,KACzC;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../../../src/runtimes/react/components/RuntimeProvider.tsx"],"sourcesContent":["'use client'\n\nimport { ReactNode, useMemo } from 'react'\n\nimport { type SiteVersion } from '../../../api/site-version'\n\nimport { ReactRuntimeContext } from '../hooks/use-react-runtime'\nimport { useAsyncEffect } from '../hooks/use-async-effect'\nimport { type ReactRuntimeCore } from '../react-runtime-core'\n\nimport { PreviewSwitcher } from './preview-switcher/preview-switcher'\n\nexport function RuntimeProvider({\n children,\n runtime,\n siteVersion: siteVersionProp,\n locale = undefined,\n}: {\n children: ReactNode\n runtime: ReactRuntimeCore\n siteVersion: SiteVersion | null | undefined\n locale?: string\n}) {\n const siteVersion = siteVersionProp ?? null\n const isPreview = siteVersion != null\n // TODO: we need to decouple editability from the site version; specifically, previewing\n // a draft version of the site should not lead to switching to the read-write state\n const isReadOnly = siteVersion == null\n\n // setting idempotent part of the state on render to have parity between server-side and\n // client-side rendering depending on this state; `useMemo` here is purely a performance\n // optimization; prior art for performing idempotent side effects on render:\n // https://github.com/TanStack/query/blob/8f9f183f11df3709a1a38c4efce1452788041f88/packages/react-query/src/HydrationBoundary.tsx#L41\n useMemo(\n () => runtime.setIdempotent({ siteVersion, isReadOnly, locale }),\n [runtime, siteVersion, isReadOnly, locale],\n )\n\n useAsyncEffect(() => runtime.setupStore({ isReadOnly }), [runtime, isReadOnly])\n\n return (\n <ReactRuntimeContext.Provider value={runtime}>\n {children}\n <PreviewSwitcher isPreview={isPreview} />\n </ReactRuntimeContext.Provider>\n )\n}\n"],"mappings":";AAyCI,SAEE,KAFF;AAvCJ,SAAoB,eAAe;AAInC,SAAS,2BAA2B;AACpC,SAAS,sBAAsB;AAG/B,SAAS,uBAAuB;AAEzB,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA,aAAa;AAAA,EACb,SAAS;AACX,GAKG;AACD,QAAM,cAAc,mBAAmB;AACvC,QAAM,YAAY,eAAe;AAGjC,QAAM,aAAa,eAAe;AAMlC;AAAA,IACE,MAAM,QAAQ,cAAc,EAAE,aAAa,YAAY,OAAO,CAAC;AAAA,IAC/D,CAAC,SAAS,aAAa,YAAY,MAAM;AAAA,EAC3C;AAEA,iBAAe,MAAM,QAAQ,WAAW,EAAE,WAAW,CAAC,GAAG,CAAC,SAAS,UAAU,CAAC;AAE9E,SACE,qBAAC,oBAAoB,UAApB,EAA6B,OAAO,SAClC;AAAA;AAAA,IACD,oBAAC,mBAAgB,WAAsB;AAAA,KACzC;AAEJ;","names":[]}
@@ -5,20 +5,10 @@ import { PageMeta } from "../page/head-tags";
5
5
  import { useIsInBuilder } from "../../hooks/use-is-in-builder";
6
6
  import { PreviewToolbar } from "./preview-toolbar";
7
7
  function PreviewSwitcher({ isPreview }) {
8
- const shadowContainerRef = useRef(null);
9
- const [shadowRoot, setShadowRoot] = useState(null);
10
8
  const isInBuilder = useIsInBuilder();
11
9
  const showToolbar = !isInBuilder && isPreview;
12
- useEffect(() => {
13
- if (!showToolbar)
14
- return;
15
- if (shadowContainerRef.current && shadowContainerRef.current.shadowRoot == null && shadowRoot == null) {
16
- const root = shadowContainerRef.current.attachShadow({ mode: "open" });
17
- setShadowRoot(root);
18
- }
19
- }, [showToolbar, shadowRoot, setShadowRoot]);
20
10
  return /* @__PURE__ */ jsxs(Fragment, { children: [
21
- showToolbar && /* @__PURE__ */ jsx("span", { id: "makeswift-preview-switcher", ref: shadowContainerRef, children: shadowRoot ? createPortal(/* @__PURE__ */ jsx(PreviewToolbar, {}), shadowRoot) : null }),
11
+ showToolbar && /* @__PURE__ */ jsx(PreviewToolbarSingleton, { id: "makeswift-preview-switcher" }),
22
12
  /* @__PURE__ */ jsx(
23
13
  PageMeta,
24
14
  {
@@ -28,6 +18,25 @@ function PreviewSwitcher({ isPreview }) {
28
18
  )
29
19
  ] });
30
20
  }
21
+ function PreviewToolbarSingleton({ id }) {
22
+ const [shadowRoot, setShadowRoot] = useState(null);
23
+ const containerRef = useRef(null);
24
+ useEffect(() => {
25
+ if (document.getElementById(id) != null) {
26
+ return;
27
+ }
28
+ const container = document.createElement("span");
29
+ container.id = id;
30
+ document.body.appendChild(container);
31
+ containerRef.current = container;
32
+ setShadowRoot(container.shadowRoot ?? container.attachShadow({ mode: "open" }));
33
+ return () => {
34
+ containerRef.current?.remove();
35
+ containerRef.current = null;
36
+ };
37
+ }, [id]);
38
+ return shadowRoot != null ? createPortal(/* @__PURE__ */ jsx(PreviewToolbar, {}), shadowRoot) : null;
39
+ }
31
40
  export {
32
41
  PreviewSwitcher
33
42
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../src/runtimes/react/components/preview-switcher/preview-switcher.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\n\nimport { PageMeta } from '../page/head-tags'\nimport { useIsInBuilder } from '../../hooks/use-is-in-builder'\nimport { PreviewToolbar } from './preview-toolbar'\n\nexport function PreviewSwitcher({ isPreview }: { isPreview: boolean }) {\n const shadowContainerRef = useRef<HTMLSpanElement | null>(null)\n const [shadowRoot, setShadowRoot] = useState<ShadowRoot | null>(null)\n const isInBuilder = useIsInBuilder()\n\n const showToolbar = !isInBuilder && isPreview\n\n useEffect(() => {\n if (!showToolbar) return\n if (\n shadowContainerRef.current &&\n shadowContainerRef.current.shadowRoot == null &&\n shadowRoot == null\n ) {\n const root = shadowContainerRef.current.attachShadow({ mode: 'open' })\n setShadowRoot(root)\n }\n }, [showToolbar, shadowRoot, setShadowRoot])\n\n return (\n <>\n {showToolbar && (\n <span id=\"makeswift-preview-switcher\" ref={shadowContainerRef}>\n {shadowRoot ? createPortal(<PreviewToolbar />, shadowRoot) : null}\n </span>\n )}\n {/* Insert preview mode information into the DOM to make it easier to debug preview mode-related\n issues on production sites */}\n <PageMeta\n name=\"makeswift-preview-info\"\n content={JSON.stringify({ isPreview: isPreview, inBuilder: isInBuilder })}\n />\n </>\n )\n}\n"],"mappings":"AA2BI,mBAGiC,KAHjC;AA3BJ,SAAS,WAAW,QAAQ,gBAAgB;AAC5C,SAAS,oBAAoB;AAE7B,SAAS,gBAAgB;AACzB,SAAS,sBAAsB;AAC/B,SAAS,sBAAsB;AAExB,SAAS,gBAAgB,EAAE,UAAU,GAA2B;AACrE,QAAM,qBAAqB,OAA+B,IAAI;AAC9D,QAAM,CAAC,YAAY,aAAa,IAAI,SAA4B,IAAI;AACpE,QAAM,cAAc,eAAe;AAEnC,QAAM,cAAc,CAAC,eAAe;AAEpC,YAAU,MAAM;AACd,QAAI,CAAC;AAAa;AAClB,QACE,mBAAmB,WACnB,mBAAmB,QAAQ,cAAc,QACzC,cAAc,MACd;AACA,YAAM,OAAO,mBAAmB,QAAQ,aAAa,EAAE,MAAM,OAAO,CAAC;AACrE,oBAAc,IAAI;AAAA,IACpB;AAAA,EACF,GAAG,CAAC,aAAa,YAAY,aAAa,CAAC;AAE3C,SACE,iCACG;AAAA,mBACC,oBAAC,UAAK,IAAG,8BAA6B,KAAK,oBACxC,uBAAa,aAAa,oBAAC,kBAAe,GAAI,UAAU,IAAI,MAC/D;AAAA,IAIF;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,KAAK,UAAU,EAAE,WAAsB,WAAW,YAAY,CAAC;AAAA;AAAA,IAC1E;AAAA,KACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../../../../src/runtimes/react/components/preview-switcher/preview-switcher.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from 'react'\nimport { createPortal } from 'react-dom'\n\nimport { PageMeta } from '../page/head-tags'\nimport { useIsInBuilder } from '../../hooks/use-is-in-builder'\nimport { PreviewToolbar } from './preview-toolbar'\n\nexport function PreviewSwitcher({ isPreview }: { isPreview: boolean }) {\n const isInBuilder = useIsInBuilder()\n const showToolbar = !isInBuilder && isPreview\n return (\n <>\n {showToolbar && <PreviewToolbarSingleton id=\"makeswift-preview-switcher\" />}\n {/* Insert preview mode information into the DOM to make it easier to debug preview mode-related\n issues on production sites */}\n <PageMeta\n name=\"makeswift-preview-info\"\n content={JSON.stringify({ isPreview: isPreview, inBuilder: isInBuilder })}\n />\n </>\n )\n}\n\nfunction PreviewToolbarSingleton({ id }: { id: string }) {\n const [shadowRoot, setShadowRoot] = useState<ShadowRoot | null>(null)\n const containerRef = useRef<HTMLSpanElement | null>(null)\n\n useEffect(() => {\n if (document.getElementById(id) != null) {\n return\n }\n\n const container = document.createElement('span')\n container.id = id\n document.body.appendChild(container)\n\n containerRef.current = container\n setShadowRoot(container.shadowRoot ?? container.attachShadow({ mode: 'open' }))\n\n return () => {\n containerRef.current?.remove()\n containerRef.current = null\n }\n }, [id])\n\n return shadowRoot != null ? createPortal(<PreviewToolbar />, shadowRoot) : null\n}\n"],"mappings":"AAWI,mBACkB,KADlB;AAXJ,SAAS,WAAW,QAAQ,gBAAgB;AAC5C,SAAS,oBAAoB;AAE7B,SAAS,gBAAgB;AACzB,SAAS,sBAAsB;AAC/B,SAAS,sBAAsB;AAExB,SAAS,gBAAgB,EAAE,UAAU,GAA2B;AACrE,QAAM,cAAc,eAAe;AACnC,QAAM,cAAc,CAAC,eAAe;AACpC,SACE,iCACG;AAAA,mBAAe,oBAAC,2BAAwB,IAAG,8BAA6B;AAAA,IAGzE;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,SAAS,KAAK,UAAU,EAAE,WAAsB,WAAW,YAAY,CAAC;AAAA;AAAA,IAC1E;AAAA,KACF;AAEJ;AAEA,SAAS,wBAAwB,EAAE,GAAG,GAAmB;AACvD,QAAM,CAAC,YAAY,aAAa,IAAI,SAA4B,IAAI;AACpE,QAAM,eAAe,OAA+B,IAAI;AAExD,YAAU,MAAM;AACd,QAAI,SAAS,eAAe,EAAE,KAAK,MAAM;AACvC;AAAA,IACF;AAEA,UAAM,YAAY,SAAS,cAAc,MAAM;AAC/C,cAAU,KAAK;AACf,aAAS,KAAK,YAAY,SAAS;AAEnC,iBAAa,UAAU;AACvB,kBAAc,UAAU,cAAc,UAAU,aAAa,EAAE,MAAM,OAAO,CAAC,CAAC;AAE9E,WAAO,MAAM;AACX,mBAAa,SAAS,OAAO;AAC7B,mBAAa,UAAU;AAAA,IACzB;AAAA,EACF,GAAG,CAAC,EAAE,CAAC;AAEP,SAAO,cAAc,OAAO,aAAa,oBAAC,kBAAe,GAAI,UAAU,IAAI;AAC7E;","names":[]}