@powerhousedao/connect 6.2.3-dev.0 → 6.2.3-dev.1

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 (32) hide show
  1. package/dist/{ClearStorageModal-Dm2ztjgw.js → ClearStorageModal-DzAyAuVv.js} +4 -4
  2. package/dist/{ClearStorageModal-Dm2ztjgw.js.map → ClearStorageModal-DzAyAuVv.js.map} +1 -1
  3. package/dist/{DebugSettingsModal-BWOSNOw8.js → DebugSettingsModal-3CEMd9eu.js} +4 -4
  4. package/dist/{DebugSettingsModal-BWOSNOw8.js.map → DebugSettingsModal-3CEMd9eu.js.map} +1 -1
  5. package/dist/{InspectorModal-ChZE9QbX.js → InspectorModal-CYbjzlhG.js} +4 -4
  6. package/dist/{InspectorModal-ChZE9QbX.js.map → InspectorModal-CYbjzlhG.js.map} +1 -1
  7. package/dist/{MissingPackageModal-C7usWVHQ.js → MissingPackageModal-nBnExqO0.js} +4 -4
  8. package/dist/{MissingPackageModal-C7usWVHQ.js.map → MissingPackageModal-nBnExqO0.js.map} +1 -1
  9. package/dist/{OpenFileDocumentsModal-DOwweG6l.js → OpenFileDocumentsModal-B2_dmk3q.js} +4 -4
  10. package/dist/{OpenFileDocumentsModal-DOwweG6l.js.map → OpenFileDocumentsModal-B2_dmk3q.js.map} +1 -1
  11. package/dist/{SettingsModal-DzSC4sh8.js → SettingsModal-CJdzVm4U.js} +8 -7
  12. package/dist/{SettingsModal-DzSC4sh8.js.map → SettingsModal-CJdzVm4U.js.map} +1 -1
  13. package/dist/app-loader-B0ynDMSH.js +4 -0
  14. package/dist/{app-loader-Dkgf816o.js → app-loader-Bp60Ob5h.js} +10 -10
  15. package/dist/{app-loader-Dkgf816o.js.map → app-loader-Bp60Ob5h.js.map} +1 -1
  16. package/dist/{build-info-BvyVA-pf.js → build-info-D9cn1_DG.js} +5 -5
  17. package/dist/{build-info-BvyVA-pf.js.map → build-info-D9cn1_DG.js.map} +1 -1
  18. package/dist/components-DysHG9il.js +4 -0
  19. package/dist/{load-uFhW7yeN.js → load-Cfsve5IV.js} +5 -5
  20. package/dist/{load-uFhW7yeN.js.map → load-Cfsve5IV.js.map} +1 -1
  21. package/dist/main.js +1 -1
  22. package/dist/{reactor-DB1Qy6Ib.js → reactor-Dpy1zQbB.js} +13 -4
  23. package/dist/reactor-Dpy1zQbB.js.map +1 -0
  24. package/dist/start-connect.js +1 -1
  25. package/dist/style.css +3 -0
  26. package/dist/{useRegistryPackages-DMhCvTWq.js → useRegistryPackages-BnUcL_nZ.js} +81 -5
  27. package/dist/useRegistryPackages-BnUcL_nZ.js.map +1 -0
  28. package/package.json +12 -12
  29. package/dist/app-loader-BAbuTvzq.js +0 -4
  30. package/dist/components-VzbfpugJ.js +0 -4
  31. package/dist/reactor-DB1Qy6Ib.js.map +0 -1
  32. package/dist/useRegistryPackages-DMhCvTWq.js.map +0 -1
@@ -1,8 +1,8 @@
1
1
 
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="a2bca0ce-adce-512d-a646-5adf41d1dd3f")}catch(e){}}();
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="21abe13e-2169-5934-948c-42f35a52ef97")}catch(e){}}();
3
3
  import { n as getRuntimeConfig } from "./runtime-config-DL3QjcfM.js";
4
4
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
5
- import { getPackagePage, getPackagesForDocumentType, trimTrailingSlash, useVetraPackageManager } from "@powerhousedao/reactor-browser";
5
+ import { getPackageInfo, getPackagePage, getPackagesForDocumentType, trimTrailingSlash, useVetraPackageManager } from "@powerhousedao/reactor-browser";
6
6
  import { slimManifest } from "@powerhousedao/shared/registry/manifest-slim";
7
7
  //#region src/hooks/useRegistryPackages.ts
8
8
  /** Page size for the paginated Available-packages listing. */
@@ -52,6 +52,7 @@ function useRegistryPackages() {
52
52
  } else next[item.name] = {
53
53
  ...existing,
54
54
  version: packageManager.getPackageVersion(item.name) ?? item.version ?? existing.version,
55
+ latestVersion: item.version ?? existing.latestVersion,
55
56
  status: promoteStatus(existing.status, packageManager.getPackageSource(item.name))
56
57
  };
57
58
  }
@@ -128,6 +129,7 @@ function useRegistryPackages() {
128
129
  const status = getPackageStatusFromPackageSource(packageManager.getPackageSource(info.name));
129
130
  next[info.name] = existing ? {
130
131
  ...existing,
132
+ latestVersion: info.version ?? existing.latestVersion,
131
133
  status: promoteStatus(existing.status, packageManager.getPackageSource(info.name))
132
134
  } : makeRegistryPackageFromPackageInfo(info, status);
133
135
  }
@@ -153,12 +155,17 @@ function useRegistryPackages() {
153
155
  const existingPackage = existingRegistryPackages[packageName];
154
156
  const newRegistryPackages = { ...existingRegistryPackages };
155
157
  const version = packageManager.getPackageVersion(packageName);
158
+ const spec = packageManager.getPackageSpec(packageName);
156
159
  if (existingPackage) newRegistryPackages[packageName] = {
157
160
  ...existingPackage,
158
161
  version: version ?? existingPackage.version,
162
+ spec: spec ?? existingPackage.spec,
159
163
  status: promoteStatus(existingPackage.status, packageManager.getPackageSource(packageName))
160
164
  };
161
- else newRegistryPackages[packageName] = makeRegistryPackageFromDocumentModelLib(packageManagerPackage, getPackageStatusFromPackageSource(packageManager.getPackageSource(packageName)), version);
165
+ else newRegistryPackages[packageName] = {
166
+ ...makeRegistryPackageFromDocumentModelLib(packageManagerPackage, getPackageStatusFromPackageSource(packageManager.getPackageSource(packageName)), version),
167
+ ...spec !== void 0 ? { spec } : null
168
+ };
162
169
  return newRegistryPackages;
163
170
  });
164
171
  }, [packageManagerPackages]);
@@ -198,10 +205,77 @@ function useRegistryPackages() {
198
205
  return newRegistryPackages;
199
206
  });
200
207
  }
208
+ /**
209
+ * In-flight dedupe: the same row can be requested by the Installed-tab
210
+ * trigger and by runtime registration in the same tick — at most one
211
+ * fetch per row at a time.
212
+ */
213
+ const metadataInFlightRef = useRef(/* @__PURE__ */ new Set());
214
+ /**
215
+ * Fetch single-package info for the given rows and merge it into the
216
+ * map. The endpoint's `version` is the registry's newest release — the
217
+ * latest-stream target — and is stored as `latestVersion`, never
218
+ * overwriting the installed `version`, `spec`, or status. `distTags`/
219
+ * `versions` (the picker's data) merge in when the registry provides
220
+ * them. Per-row failures are logged and swallowed — a dead registry or
221
+ * one bad package must not blank the others.
222
+ */
223
+ const fetchInstalledRowData = useCallback((names) => {
224
+ if (registryUrl === null || names.length === 0) return;
225
+ const pending = names.filter((name) => !metadataInFlightRef.current.has(name));
226
+ if (pending.length === 0) return;
227
+ for (const name of pending) metadataInFlightRef.current.add(name);
228
+ Promise.all(pending.map(async (name) => {
229
+ try {
230
+ const info = await getPackageInfo(registryUrl, name);
231
+ if (!info || !info.version && !info.distTags && !info.versions) return;
232
+ setRegistryPackagesMap((oldPackages) => {
233
+ const existing = oldPackages[name];
234
+ if (!existing) return oldPackages;
235
+ return {
236
+ ...oldPackages,
237
+ [name]: {
238
+ ...existing,
239
+ latestVersion: info.version ?? existing.latestVersion,
240
+ distTags: info.distTags ?? existing.distTags,
241
+ versions: info.versions ?? existing.versions
242
+ }
243
+ };
244
+ });
245
+ } catch (error) {
246
+ console.error(error);
247
+ } finally {
248
+ metadataInFlightRef.current.delete(name);
249
+ }
250
+ }));
251
+ }, [registryUrl, setRegistryPackagesMap]);
252
+ /**
253
+ * Lazy refresh of installed-row version data — the Installed-tab trigger.
254
+ * Fetches rows missing `latestVersion` or the full `versions`/`distTags`
255
+ * metadata (the picker).
256
+ */
257
+ const ensureInstalledMetadataLoaded = useCallback(() => {
258
+ if (registryUrl === null || !packageManager) return;
259
+ fetchInstalledRowData(Object.values(registryPackagesMap).filter((p) => p !== void 0 && p.status === "registry-install" && (!p.latestVersion || !(p.distTags && Object.keys(p.distTags).length > 0 || (p.versions?.length ?? 0) > 0))).map((p) => p.name));
260
+ }, [
261
+ registryUrl,
262
+ packageManager,
263
+ registryPackagesMap,
264
+ fetchInstalledRowData
265
+ ]);
266
+ useEffect(() => {
267
+ if (!packageManagerPackages?.length || !packageManager) return;
268
+ fetchInstalledRowData(packageManagerPackages.filter((p) => packageManager.getPackageSource(p.manifest.name) === "registry-install").map((p) => p.manifest.name));
269
+ }, [
270
+ packageManagerPackages,
271
+ packageManager,
272
+ fetchInstalledRowData
273
+ ]);
201
274
  return {
202
275
  registryPackagesMap,
203
276
  registryPackageList,
204
277
  installedPackages,
278
+ ensureInstalledMetadataLoaded,
205
279
  availablePackages,
206
280
  availableTotal,
207
281
  availableHasMore,
@@ -227,6 +301,7 @@ function makeRegistryPackageFromListItem(item, status) {
227
301
  path: item.path,
228
302
  documentTypes: [],
229
303
  version: item.version,
304
+ latestVersion: item.version,
230
305
  status,
231
306
  manifest: {
232
307
  name: item.name,
@@ -249,6 +324,7 @@ function makeRegistryPackageFromDocumentModelLib(documentModelLib, status, versi
249
324
  function makeRegistryPackageFromPackageInfo(packageInfo, status) {
250
325
  return {
251
326
  ...packageInfo,
327
+ latestVersion: packageInfo.version,
252
328
  manifest: slimManifest(packageInfo.manifest),
253
329
  documentTypes: packageInfo.manifest?.documentModels?.map((d) => d.id) ?? [],
254
330
  status
@@ -310,5 +386,5 @@ function getPackageStatusFromPackageSource(packageSource) {
310
386
  //#endregion
311
387
  export { useRegistryPackages as t };
312
388
 
313
- //# sourceMappingURL=useRegistryPackages-DMhCvTWq.js.map
314
- //# debugId=a2bca0ce-adce-512d-a646-5adf41d1dd3f
389
+ //# sourceMappingURL=useRegistryPackages-BnUcL_nZ.js.map
390
+ //# debugId=21abe13e-2169-5934-948c-42f35a52ef97
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useRegistryPackages-BnUcL_nZ.js","sources":["../src/hooks/useRegistryPackages.ts"],"sourcesContent":["import {\n getPackageInfo,\n getPackagePage,\n getPackagesForDocumentType,\n trimTrailingSlash,\n useVetraPackageManager,\n} from \"@powerhousedao/reactor-browser\";\nimport type {\n PackageInfo,\n PackageListItem,\n RegistryPackage,\n RegistryPackageList,\n RegistryPackageMap,\n RegistryPackageSource,\n RegistryPackageStatus,\n} from \"@powerhousedao/shared/registry\";\nimport { slimManifest } from \"@powerhousedao/shared/registry/manifest-slim\";\nimport type { DocumentModelLib } from \"document-model\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { getRuntimeConfig } from \"../runtime-config.js\";\n\n/** Page size for the paginated Available-packages listing. */\nconst AVAILABLE_PAGE_SIZE = 30;\n\nexport function useRegistryPackages() {\n const packageManager = useVetraPackageManager();\n const packageManagerPackages = packageManager?.packages;\n const registryUrl = getRuntimeConfig().packageRegistryUrl ?? null;\n // Normalize so `http://host` and `http://host/` don't produce two separate\n // localStorage maps where the install/status flow reads from one while the\n // registry fetch writes to the other.\n const registryPackagesKey = `REGISTRY_PACKAGES:${registryUrl === null ? null : trimTrailingSlash(registryUrl)}`;\n const [registryPackagesMap, setRegistryPackagesMap] =\n useBestEffortLocalStorage<RegistryPackageMap>(registryPackagesKey, {});\n const registryPackageList: RegistryPackageList = useMemo(() => {\n return Array.from(Object.values(registryPackagesMap)).filter(\n (p) => p !== undefined,\n );\n }, [registryPackagesMap]);\n // Split for the two Package Manager tabs: installed is derivable from local\n // state alone (no network), available/dismissed come from the registry\n // fetch (or its localStorage cache).\n const installedPackages: RegistryPackageList = useMemo(\n () =>\n registryPackageList.filter(\n (p) => p.status === \"local-install\" || p.status === \"registry-install\",\n ),\n [registryPackageList],\n );\n // --- Available tab: paginated + server-searched, layered on the map ---\n //\n // The map above stays the single source of truth for each package's status,\n // version metadata and install state. `availableOrder` is the ordering layer\n // for the current search: a page-accumulated list of names. The rendered\n // available list looks each name up in the map and drops anything that is\n // now installed (it moves to the Installed tab) — so installing a row needs\n // no extra bookkeeping.\n const [availableOrder, setAvailableOrder] = useState<string[]>([]);\n const [availableTotal, setAvailableTotal] = useState<number | null>(null);\n const [availableHasMore, setAvailableHasMore] = useState(false);\n const [isLoadingAvailable, setIsLoadingAvailable] = useState(false);\n const [isLoadingMoreAvailable, setIsLoadingMoreAvailable] = useState(false);\n const [availableError, setAvailableError] = useState(false);\n\n // Latest search string (updated synchronously so a debounced fetch reads the\n // freshest query), the server offset for the next page, and a monotonic\n // request generation so out-of-order responses never clobber a newer query.\n const availableQueryRef = useRef(\"\");\n const nextOffsetRef = useRef(0);\n const requestGenerationRef = useRef(0);\n const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const availablePackages: RegistryPackageList = useMemo(\n () =>\n availableOrder\n .map((name) => registryPackagesMap[name])\n .filter(\n (p): p is RegistryPackage =>\n p !== undefined &&\n (p.status === \"available\" || p.status === \"dismissed\"),\n ),\n [availableOrder, registryPackagesMap],\n );\n\n const fetchAvailablePage = useCallback(\n async ({ reset }: { reset: boolean }): Promise<void> => {\n if (registryUrl === null || !packageManager) return;\n const generation = ++requestGenerationRef.current;\n const offset = reset ? 0 : nextOffsetRef.current;\n const search = availableQueryRef.current;\n if (reset) setIsLoadingAvailable(true);\n else setIsLoadingMoreAvailable(true);\n setAvailableError(false);\n\n try {\n const page = await getPackagePage(registryUrl, {\n limit: AVAILABLE_PAGE_SIZE,\n offset,\n search: search || undefined,\n });\n // A newer search/reset superseded this request — drop its result.\n if (generation !== requestGenerationRef.current) return;\n\n setRegistryPackagesMap((oldPackages) => {\n const next: RegistryPackageMap = { ...oldPackages };\n for (const item of page.items) {\n const existing = next[item.name];\n if (!existing) {\n const status = getPackageStatusFromPackageSource(\n packageManager.getPackageSource(item.name),\n );\n next[item.name] = makeRegistryPackageFromListItem(item, status);\n } else {\n // Keep the existing (possibly fuller) entry; just refresh the\n // installed version, the registry's newest version, and\n // re-promote status. Never downgrade an installed/dismissed\n // row from a trimmed list item.\n next[item.name] = {\n ...existing,\n version:\n packageManager.getPackageVersion(item.name) ??\n item.version ??\n existing.version,\n latestVersion: item.version ?? existing.latestVersion,\n status: promoteStatus(\n existing.status,\n packageManager.getPackageSource(item.name),\n ),\n };\n }\n }\n return next;\n });\n\n setAvailableOrder((prev) => {\n const base = reset ? [] : prev;\n const seen = new Set(base);\n const merged = [...base];\n for (const item of page.items) {\n if (!seen.has(item.name)) {\n seen.add(item.name);\n merged.push(item.name);\n }\n }\n return merged;\n });\n\n nextOffsetRef.current = offset + page.items.length;\n setAvailableTotal(page.total);\n setAvailableHasMore(page.hasMore);\n } catch (error: unknown) {\n if (generation !== requestGenerationRef.current) return;\n // Log the raw failure for debugging; the UI only gets a boolean so we\n // never surface generic API / network messages to the user.\n console.error(error);\n setAvailableError(true);\n } finally {\n // Only the newest request clears the spinners.\n if (generation === requestGenerationRef.current) {\n setIsLoadingAvailable(false);\n setIsLoadingMoreAvailable(false);\n }\n }\n },\n [registryUrl, packageManager, setRegistryPackagesMap],\n );\n\n /** Debounced server search — resets to page 1 for the new query. */\n const setAvailableSearch = useCallback(\n (query: string) => {\n availableQueryRef.current = query;\n if (debounceRef.current) clearTimeout(debounceRef.current);\n debounceRef.current = setTimeout(() => {\n void fetchAvailablePage({ reset: true });\n }, 300);\n },\n [fetchAvailablePage],\n );\n\n /** Load the next page (infinite scroll). No-op when exhausted/busy. */\n const loadMoreAvailable = useCallback(() => {\n if (!availableHasMore || isLoadingAvailable || isLoadingMoreAvailable) {\n return;\n }\n void fetchAvailablePage({ reset: false });\n }, [\n availableHasMore,\n isLoadingAvailable,\n isLoadingMoreAvailable,\n fetchAvailablePage,\n ]);\n\n /**\n * Load page 1 the first time the Available tab is opened. Re-opening keeps\n * the accumulated pages; a fetch error leaves the panel's Retry to re-fetch\n * (this guard avoids auto-retry loops on tab re-open).\n */\n function ensureAvailableLoaded() {\n if (availableOrder.length > 0 || isLoadingAvailable || availableError) {\n return;\n }\n void fetchAvailablePage({ reset: true });\n }\n\n /**\n * Fetch full package info for a document type (via the legacy\n * `?documentType=` filter) and merge into the map. Lets MissingPackageModal\n * offer installs without loading the whole paginated listing.\n */\n const fetchPackagesByDocumentType = useCallback(\n async (documentType: string): Promise<RegistryPackage[]> => {\n if (registryUrl === null || !packageManager) return [];\n try {\n const infos = await getPackagesForDocumentType(\n registryUrl,\n documentType,\n );\n setRegistryPackagesMap((oldPackages) => {\n const next: RegistryPackageMap = { ...oldPackages };\n for (const info of infos) {\n const existing = next[info.name];\n const status = getPackageStatusFromPackageSource(\n packageManager.getPackageSource(info.name),\n );\n next[info.name] = existing\n ? {\n ...existing,\n latestVersion: info.version ?? existing.latestVersion,\n status: promoteStatus(\n existing.status,\n packageManager.getPackageSource(info.name),\n ),\n }\n : makeRegistryPackageFromPackageInfo(info, status);\n }\n return next;\n });\n return infos.map((info) =>\n makeRegistryPackageFromPackageInfo(\n info,\n getPackageStatusFromPackageSource(\n packageManager.getPackageSource(info.name),\n ),\n ),\n );\n } catch (error: unknown) {\n console.error(error);\n return [];\n }\n },\n [registryUrl, packageManager, setRegistryPackagesMap],\n );\n\n // Clear any pending debounce on unmount.\n useEffect(\n () => () => {\n if (debounceRef.current) clearTimeout(debounceRef.current);\n },\n [],\n );\n\n useEffect(() => {\n if (!packageManager) return;\n\n if (packageManagerPackages?.length) {\n for (const packageManagerPackage of packageManagerPackages) {\n setRegistryPackagesMap((existingRegistryPackages) => {\n const packageName = packageManagerPackage.manifest.name;\n const existingPackage = existingRegistryPackages[packageName];\n const newRegistryPackages = { ...existingRegistryPackages };\n const version = packageManager.getPackageVersion(packageName);\n const spec = packageManager.getPackageSpec(packageName);\n if (existingPackage) {\n newRegistryPackages[packageName] = {\n ...existingPackage,\n version: version ?? existingPackage.version,\n spec: spec ?? existingPackage.spec,\n status: promoteStatus(\n existingPackage.status,\n packageManager.getPackageSource(packageName),\n ),\n };\n } else {\n const packageSource = packageManager.getPackageSource(packageName);\n const status = getPackageStatusFromPackageSource(packageSource);\n const newRegistryPackage = makeRegistryPackageFromDocumentModelLib(\n packageManagerPackage,\n status,\n version,\n );\n newRegistryPackages[packageName] = {\n ...newRegistryPackage,\n ...(spec !== undefined ? { spec } : null),\n };\n }\n return newRegistryPackages;\n });\n }\n }\n }, [packageManagerPackages]);\n\n function updateRegistryPackageStatus(\n packageName: string,\n newStatus: RegistryPackageStatus,\n ) {\n setRegistryPackagesMap((oldRegistryPackages) => {\n const newRegistryPackages = { ...oldRegistryPackages };\n const newRegistryPackage = newRegistryPackages[packageName];\n if (!newRegistryPackage) {\n console.error(\n \"Attempting to update status for package that does not exist.\",\n );\n return newRegistryPackages;\n }\n newRegistryPackages[packageName] = {\n ...newRegistryPackage,\n status: newStatus,\n };\n\n return newRegistryPackages;\n });\n }\n\n /**\n * Register a freshly-installed package that came in via the npm-uplink\n * fallback — the user typed a bare name, our local `/packages` didn't know\n * it, but the install succeeded because verdaccio proxy-fetched the tarball.\n *\n * This is the one legitimate case where the status update runs against a\n * name that wasn't in the registry map. We treat it as an insert rather\n * than logging the \"does not exist\" error. Data is pulled from the loaded\n * module so the UI card shows the real manifest immediately; the next\n * `/packages` refresh will add `versions`/`distTags`.\n */\n function registerFallbackRegistryPackage(\n packageName: string,\n loadedPackage: DocumentModelLib,\n version: string | undefined,\n status: RegistryPackageStatus,\n ) {\n setRegistryPackagesMap((oldRegistryPackages) => {\n const newRegistryPackages = { ...oldRegistryPackages };\n newRegistryPackages[packageName] = {\n ...makeRegistryPackageFromDocumentModelLib(\n loadedPackage,\n status,\n version,\n ),\n name: packageName,\n };\n return newRegistryPackages;\n });\n }\n\n /**\n * In-flight dedupe: the same row can be requested by the Installed-tab\n * trigger and by runtime registration in the same tick — at most one\n * fetch per row at a time.\n */\n const metadataInFlightRef = useRef(new Set<string>());\n\n /**\n * Fetch single-package info for the given rows and merge it into the\n * map. The endpoint's `version` is the registry's newest release — the\n * latest-stream target — and is stored as `latestVersion`, never\n * overwriting the installed `version`, `spec`, or status. `distTags`/\n * `versions` (the picker's data) merge in when the registry provides\n * them. Per-row failures are logged and swallowed — a dead registry or\n * one bad package must not blank the others.\n */\n const fetchInstalledRowData = useCallback(\n (names: string[]) => {\n if (registryUrl === null || names.length === 0) return;\n const pending = names.filter(\n (name) => !metadataInFlightRef.current.has(name),\n );\n if (pending.length === 0) return;\n for (const name of pending) metadataInFlightRef.current.add(name);\n void Promise.all(\n pending.map(async (name) => {\n try {\n const info = await getPackageInfo(registryUrl, name);\n if (!info || (!info.version && !info.distTags && !info.versions))\n return;\n setRegistryPackagesMap((oldPackages) => {\n const existing = oldPackages[name];\n if (!existing) return oldPackages;\n return {\n ...oldPackages,\n [name]: {\n ...existing,\n latestVersion: info.version ?? existing.latestVersion,\n distTags: info.distTags ?? existing.distTags,\n versions: info.versions ?? existing.versions,\n },\n };\n });\n } catch (error: unknown) {\n console.error(error);\n } finally {\n metadataInFlightRef.current.delete(name);\n }\n }),\n );\n },\n [registryUrl, setRegistryPackagesMap],\n );\n\n /**\n * Lazy refresh of installed-row version data — the Installed-tab trigger.\n * Fetches rows missing `latestVersion` or the full `versions`/`distTags`\n * metadata (the picker).\n */\n const ensureInstalledMetadataLoaded = useCallback(() => {\n if (registryUrl === null || !packageManager) return;\n const missing = Object.values(registryPackagesMap)\n .filter(\n (p): p is RegistryPackage =>\n p !== undefined &&\n p.status === \"registry-install\" &&\n (!p.latestVersion ||\n !(\n (p.distTags && Object.keys(p.distTags).length > 0) ||\n (p.versions?.length ?? 0) > 0\n )),\n )\n .map((p) => p.name);\n void fetchInstalledRowData(missing);\n }, [registryUrl, packageManager, registryPackagesMap, fetchInstalledRowData]);\n\n // Runtime registration can postdate the last Installed-tab activation\n // (boot-time registry packages resolve after the modal opened, or an\n // install lands while it is closed) — refresh the rows that were just\n // registered so their update data arrives without a manual re-open.\n useEffect(() => {\n if (!packageManagerPackages?.length || !packageManager) return;\n const names = packageManagerPackages\n .filter(\n (p) =>\n packageManager.getPackageSource(p.manifest.name) ===\n \"registry-install\",\n )\n .map((p) => p.manifest.name);\n void fetchInstalledRowData(names);\n }, [packageManagerPackages, packageManager, fetchInstalledRowData]);\n\n return {\n registryPackagesMap,\n registryPackageList,\n installedPackages,\n ensureInstalledMetadataLoaded,\n // Available tab (paginated + server search)\n availablePackages,\n availableTotal,\n availableHasMore,\n isLoadingAvailable,\n isLoadingMoreAvailable,\n availableError,\n ensureAvailableLoaded,\n fetchAvailablePage,\n loadMoreAvailable,\n setAvailableSearch,\n fetchPackagesByDocumentType,\n // Status mutations\n updateRegistryPackageStatus,\n registerFallbackRegistryPackage,\n };\n}\n\n/**\n * Build a RegistryPackage from a trimmed paginated list item. Version metadata\n * (distTags/versions) and documentTypes are absent — the row lazy-loads them.\n */\nfunction makeRegistryPackageFromListItem(\n item: PackageListItem,\n status: RegistryPackageStatus,\n): RegistryPackage {\n return {\n name: item.name,\n path: item.path,\n documentTypes: [],\n version: item.version,\n latestVersion: item.version,\n status,\n manifest: {\n name: item.name,\n ...(item.description !== undefined\n ? { description: item.description }\n : {}),\n ...(item.category !== undefined ? { category: item.category } : {}),\n ...(item.publisher !== undefined ? { publisher: item.publisher } : {}),\n },\n };\n}\n\nfunction makeRegistryPackageFromDocumentModelLib(\n documentModelLib: DocumentModelLib,\n status: RegistryPackageStatus,\n version?: string,\n): RegistryPackage {\n return {\n name: documentModelLib.manifest.name,\n path: \"stub-path\",\n documentTypes: documentModelLib.documentModels.map(\n (d) => d.documentModel.global.id,\n ),\n status,\n manifest: slimManifest(documentModelLib.manifest),\n version,\n };\n}\n\nfunction makeRegistryPackageFromPackageInfo(\n packageInfo: PackageInfo,\n status: RegistryPackageStatus,\n): RegistryPackage {\n return {\n ...packageInfo,\n // The full-info `version` is the registry's newest release — record it\n // as the latest-stream target even for installed rows (whose `version`\n // is then refreshed to the installed one by the map merge).\n latestVersion: packageInfo.version,\n // Slim before caching: registry manifests are unvalidated JSON and have\n // carried multi-megabyte junk fields that blew the localStorage quota\n // (and the UI only reads the summary fields anyway).\n manifest: slimManifest(packageInfo.manifest),\n documentTypes: packageInfo.manifest?.documentModels?.map((d) => d.id) ?? [],\n status,\n };\n}\n\n/**\n * Like usehooks-ts' useLocalStorage, but persistence is best-effort: a failed\n * `setItem` (e.g. QuotaExceededError on an oversized payload) keeps the\n * in-memory state so the package manager still works for the session.\n * useLocalStorage couples the state update to the write — when the write\n * threw, the freshly fetched package list was discarded and the registry UI\n * rendered (and searched) an empty list.\n *\n * The key is derived from the boot-time runtime config and never changes\n * within a session, so no key-change rehydration is needed.\n */\nfunction useBestEffortLocalStorage<T>(key: string, initialValue: T) {\n const [value, setValue] = useState<T>(\n () => readJsonFromStorage<T>(key) ?? initialValue,\n );\n\n useEffect(() => {\n try {\n window.localStorage.setItem(key, JSON.stringify(value));\n } catch (error) {\n // Free the key and retry once — a stale oversized entry from an older\n // session may be occupying the quota this write needs.\n try {\n window.localStorage.removeItem(key);\n window.localStorage.setItem(key, JSON.stringify(value));\n } catch {\n console.warn(\n `Failed to persist \"${key}\" to localStorage; continuing with in-memory data.`,\n error,\n );\n }\n }\n }, [key, value]);\n\n return [value, setValue] as const;\n}\n\nfunction readJsonFromStorage<T>(key: string): T | null {\n try {\n const raw = window.localStorage.getItem(key);\n return raw === null ? null : (JSON.parse(raw) as T);\n } catch {\n return null;\n }\n}\n\n/**\n * When refreshing a cached entry, promote `\"available\"` to whatever the\n * packageManager now reports — the cached `\"available\"` was almost certainly\n * recorded before `packageManager.addPackages()` finished on a prior session.\n * Never downgrade an already-installed entry, and never overwrite a deliberate\n * `\"dismissed\"` choice.\n */\nfunction promoteStatus(\n cachedStatus: RegistryPackageStatus,\n packageSource: RegistryPackageSource | null,\n): RegistryPackageStatus {\n if (cachedStatus !== \"available\") return cachedStatus;\n if (packageSource === null) return cachedStatus;\n return getPackageStatusFromPackageSource(packageSource);\n}\n\nfunction getPackageStatusFromPackageSource(\n packageSource: RegistryPackageSource | null,\n): RegistryPackageStatus {\n // if we check the package source for a package that came from the api and it doesn't exist yet,\n // then we know the package is available on the api but not installed\n if (packageSource === null) return \"available\";\n // show common package, local project package and locally installed packages as \"local-install\"\n if (\n packageSource === \"local-install\" ||\n packageSource === \"common\" ||\n packageSource === \"project\"\n )\n return \"local-install\";\n // show \"registry-install\" status for package source \"registry-install\"\n if (packageSource === \"registry-install\") return \"registry-install\";\n // fallback to available — we should probably do more checks here\n return \"available\";\n}\n"],"names":[],"mappings":"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","debug_id":"21abe13e-2169-5934-948c-42f35a52ef97"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@powerhousedao/connect",
3
3
  "productName": "Powerhouse-Connect",
4
- "version": "6.2.3-dev.0",
4
+ "version": "6.2.3-dev.1",
5
5
  "description": "Powerhouse Connect",
6
6
  "main": "dist/index.html",
7
7
  "type": "module",
@@ -55,22 +55,22 @@
55
55
  "@openfeature/core": "1.9.1",
56
56
  "@openfeature/web-sdk": "1.6.2",
57
57
  "@openpanel/web": "^1.4.1",
58
- "@powerhousedao/config": "6.2.3-dev.0",
59
- "@powerhousedao/design-system": "6.2.3-dev.0",
58
+ "@powerhousedao/config": "6.2.3-dev.1",
59
+ "@powerhousedao/design-system": "6.2.3-dev.1",
60
60
  "@powerhousedao/document-engineering": "1.40.5",
61
- "@powerhousedao/powerhouse-vetra-packages": "6.2.3-dev.0",
62
- "@powerhousedao/reactor": "6.2.3-dev.0",
63
- "@powerhousedao/reactor-attachments": "6.2.3-dev.0",
64
- "@powerhousedao/reactor-browser": "6.2.3-dev.0",
65
- "@powerhousedao/reactor-mcp": "6.2.3-dev.0",
66
- "@powerhousedao/shared": "6.2.3-dev.0",
67
- "@powerhousedao/vetra": "6.2.3-dev.0",
61
+ "@powerhousedao/powerhouse-vetra-packages": "6.2.3-dev.1",
62
+ "@powerhousedao/reactor": "6.2.3-dev.1",
63
+ "@powerhousedao/reactor-attachments": "6.2.3-dev.1",
64
+ "@powerhousedao/reactor-browser": "6.2.3-dev.1",
65
+ "@powerhousedao/reactor-mcp": "6.2.3-dev.1",
66
+ "@powerhousedao/shared": "6.2.3-dev.1",
67
+ "@powerhousedao/vetra": "6.2.3-dev.1",
68
68
  "@privy-io/react-auth": "3.35.0",
69
69
  "@rainbow-me/rainbowkit": "^2.2.11",
70
- "@renown/sdk": "6.2.3-dev.0",
70
+ "@renown/sdk": "6.2.3-dev.1",
71
71
  "@sentry/react": "^10.17.0",
72
72
  "@tanstack/react-query": "^5.90.2",
73
- "document-model": "6.2.3-dev.0",
73
+ "document-model": "6.2.3-dev.1",
74
74
  "i18next": "^25.5.3",
75
75
  "kysely": "0.28.16",
76
76
  "kysely-pglite-dialect": "1.2.0",
@@ -1,4 +0,0 @@
1
- import { t as AppLoader } from "./app-loader-Dkgf816o.js";
2
- export { AppLoader };
3
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="3e177e58-dea7-554b-96b1-e8d311e08f53")}catch(e){}}();
4
- //# debugId=3e177e58-dea7-554b-96b1-e8d311e08f53
@@ -1,4 +0,0 @@
1
- import { t as AppLoader } from "./app-loader-Dkgf816o.js";
2
- export { AppLoader };
3
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="3e177e58-dea7-554b-96b1-e8d311e08f53")}catch(e){}}();
4
- //# debugId=3e177e58-dea7-554b-96b1-e8d311e08f53
@@ -1 +0,0 @@
1
- {"version":3,"file":"reactor-DB1Qy6Ib.js","sources":["../src/utils/pwa-idb.ts","../src/pglite.db.ts","../src/utils/reactor.ts","../src/feature-flags.ts","../src/no-registry-discovery.ts","../src/package-discovery.ts","../src/package-manager.ts","../src/reactor-worker-name.ts","../src/reactor-worker-client.ts","../src/utils/reactor-worker-flag.ts","../src/store/processor-host-module.ts","../src/store/reactor.ts"],"sourcesContent":["import {\n PWA_IDB_KEY,\n PWA_IDB_NAME,\n PWA_IDB_STORE,\n PWA_IDB_VERSION,\n type PHConnectPwa,\n type PHConnectPwaIcon,\n} from \"@powerhousedao/shared/connect\";\n\n// The page-owned mirror of the effective PWA fragment contributed by the\n// currently-installed packages. The service worker reads this (read-only) to\n// serve a live web-app manifest — a SW cannot reach localStorage (where the\n// package list lives), so BrowserPackageManager writes the merged fragment\n// here on every package change. The db/store/key/version constants are the\n// SHARED source of truth in @powerhousedao/shared/connect, imported by both\n// this writer and the SW reader so the two cannot desync.\n\nexport type PwaFragmentRecord = {\n version: 1;\n fragment: PHConnectPwa;\n updatedAt: number;\n};\n\n// Self-contained IDB open (not reusing pglite-idb) so this module — and its\n// pure `resolveFragmentAssetUrls` — carries no dependency on connect.config,\n// keeping it importable in isolation.\nfunction openPwaIdb(): Promise<IDBDatabase> {\n return new Promise((resolve, reject) => {\n const req = indexedDB.open(PWA_IDB_NAME, PWA_IDB_VERSION);\n req.onupgradeneeded = () => {\n if (!req.result.objectStoreNames.contains(PWA_IDB_STORE)) {\n req.result.createObjectStore(PWA_IDB_STORE);\n }\n };\n req.onerror = () => reject(req.error ?? new Error(\"ph-pwa open failed\"));\n req.onblocked = () => reject(new Error(\"ph-pwa open blocked\"));\n req.onsuccess = () => resolve(req.result);\n });\n}\n\n/** Write (replace) the single merged fragment record. Best-effort: a failure to\n * mirror the manifest must never break package installation, so callers ignore\n * rejections. No-op when IndexedDB is unavailable (SSR/tests). */\nexport async function writeMergedPwaFragment(\n fragment: PHConnectPwa,\n): Promise<void> {\n if (typeof indexedDB === \"undefined\") return;\n const db = await openPwaIdb();\n try {\n await new Promise<void>((resolve, reject) => {\n const tx = db.transaction(PWA_IDB_STORE, \"readwrite\");\n tx.oncomplete = () => resolve();\n tx.onerror = () =>\n reject(tx.error ?? new Error(\"PWA fragment write failed\"));\n tx.objectStore(PWA_IDB_STORE).put(\n {\n version: 1,\n fragment,\n updatedAt: Date.now(),\n } satisfies PwaFragmentRecord,\n PWA_IDB_KEY,\n );\n });\n } finally {\n db.close();\n }\n}\n\n/** Resolve `src` against the package `baseUrl`, absolute srcs passing through.\n * `baseUrl` may itself be relative (e.g. a same-origin-proxied registry, or the\n * dev `/node_modules/…` path), so it is first made absolute against the app\n * origin — `new URL(src, relativeBase)` would otherwise throw and silently\n * leave the src unresolved. A malformed src is left untouched. */\nfunction toAbsoluteAssetUrl(src: string, baseUrl: string): string {\n try {\n const origin =\n typeof location !== \"undefined\" ? location.href : \"http://localhost/\";\n return new URL(src, new URL(baseUrl, origin)).toString();\n } catch {\n return src;\n }\n}\n\nfunction resolveIconSrc(\n icon: PHConnectPwaIcon,\n baseUrl: string,\n): PHConnectPwaIcon {\n return { ...icon, src: toAbsoluteAssetUrl(icon.src, baseUrl) };\n}\n\n/**\n * Rewrite a package fragment's relative asset srcs (manifest icons and\n * file-handler icons) to absolute URLs against the package's base — a runtime\n * package's assets live on the registry CDN, not the app origin, so the served\n * manifest must point there. `baseUrl` null (a local/bundled package whose\n * assets are app-origin-relative) leaves srcs untouched.\n */\nexport function resolveFragmentAssetUrls(\n config: PHConnectPwa,\n baseUrl: string | null,\n): PHConnectPwa {\n if (!baseUrl || !config.manifest) return config;\n const m = config.manifest;\n const resolveIcons = (icons?: PHConnectPwaIcon[]) =>\n icons?.map((icon) => resolveIconSrc(icon, baseUrl));\n return {\n ...config,\n manifest: {\n ...m,\n icons: resolveIcons(m.icons),\n file_handlers: m.file_handlers?.map((handler) => ({\n ...handler,\n icons: resolveIcons(handler.icons),\n })),\n },\n };\n}\n","import type { PGlite } from \"@electric-sql/pglite\";\nimport { createRelationalDb } from \"@powerhousedao/shared/processors\";\nimport { Kysely } from \"kysely\";\nimport { PGliteDialect } from \"kysely-pglite-dialect\";\nimport {\n detectReactorPgMajor,\n detectRelationalPgMajor,\n loadPGliteModule,\n resolvePgMajorForRuntime,\n type DetectedMajor,\n type SupportedPgMajor,\n} from \"./utils/pglite-runtime.js\";\nimport {\n REACTOR_PGLITE_NAME,\n RELATIONAL_PGLITE_NAME,\n} from \"./utils/storage-namespace.js\";\n\n// Separate reactor/relational instances so their transactions can't interleave\n// on one session; the wasm download is still shared — PGlite memoizes the\n// compiled module per JS realm.\n\n// Off by default: workers hide `Module.FS` (the Inspector needs it) and each\n// worker realm re-downloads the wasm.\nexport const PGLITE_USE_WORKER: boolean = false;\n\nasync function createMainThreadPGlite(\n major: SupportedPgMajor,\n dbName: string,\n): Promise<PGlite> {\n const { PGlite } = await loadPGliteModule(major);\n const { live } =\n major === 16\n ? await import(\"pglite-legacy-02/live\")\n : await import(\"@electric-sql/pglite/live\");\n return new PGlite(`idb://${dbName}`, {\n relaxedDurability: true,\n extensions: { live },\n }) as unknown as PGlite;\n}\n\nasync function createWorkerPGlite(\n major: SupportedPgMajor,\n dbName: string,\n): Promise<PGlite> {\n // dbName is owned here so the namespace matches the other origin-scoped stores.\n const meta = { dbName };\n if (major === 16) {\n const [legacyWorker, legacyLive] = await Promise.all([\n import(\"pglite-legacy-02/worker\"),\n import(\"pglite-legacy-02/live\"),\n ]);\n const worker = new Worker(\n new URL(\"./pglite.worker.legacy.js\", import.meta.url),\n { type: \"module\" },\n );\n return legacyWorker.PGliteWorker.create(worker, {\n meta,\n extensions: { live: legacyLive.live },\n }) as unknown as PGlite;\n }\n const [{ PGliteWorker }, { live }] = await Promise.all([\n import(\"@electric-sql/pglite/worker\"),\n import(\"@electric-sql/pglite/live\"),\n ]);\n const worker = new Worker(new URL(\"./pglite.worker.js\", import.meta.url), {\n type: \"module\",\n });\n return PGliteWorker.create(worker, {\n meta,\n extensions: { live },\n }) as unknown as PGlite;\n}\n\n// Overlapping cold boots race on PGlite's un-cloned wasm fetch Response and\n// re-fetch the fs bundle; chaining avoids both.\nlet bootChain: Promise<unknown> = Promise.resolve();\n\nfunction chainedCreate(create: () => Promise<PGlite>): Promise<PGlite> {\n const pending = bootChain.then(create, create);\n bootChain = pending.catch(() => undefined);\n return pending;\n}\n\nfunction pgliteSingleton(opts: {\n dbName: string;\n detectMajor: () => Promise<DetectedMajor>;\n label: string;\n}): () => Promise<PGlite> {\n let cached: Promise<PGlite> | undefined;\n return function getPGlite(): Promise<PGlite> {\n if (cached) return cached;\n const pending = chainedCreate(async () => {\n const major = resolvePgMajorForRuntime(await opts.detectMajor());\n if (major !== 17) {\n console.warn(\n `[${opts.label}] Opening legacy Postgres ${major} data dir. Migrate to PG17 from the banner or the Inspector → Debug tab.`,\n );\n }\n return PGLITE_USE_WORKER\n ? createWorkerPGlite(major, opts.dbName)\n : createMainThreadPGlite(major, opts.dbName);\n });\n // Don't cache a rejection: let a later call retry a transient IDB/wasm failure.\n cached = pending;\n pending.catch(() => {\n if (cached === pending) cached = undefined;\n });\n return pending;\n };\n}\n\nexport const getReactorPGlite = pgliteSingleton({\n dbName: REACTOR_PGLITE_NAME,\n detectMajor: detectReactorPgMajor,\n label: \"reactor\",\n});\n\nconst getRelationalPGlite = pgliteSingleton({\n dbName: RELATIONAL_PGLITE_NAME,\n detectMajor: detectRelationalPgMajor,\n label: \"relational\",\n});\n\nexport async function getDb() {\n const pgLite = await getRelationalPGlite();\n const relationalDb = createRelationalDb(\n new Kysely({\n dialect: new PGliteDialect(pgLite),\n }),\n );\n return { pgLite, relationalDb };\n}\n","import {\n addDrive,\n addRemoteDrive,\n ChannelScheme,\n isDriveAuthError,\n ReactorBuilder,\n ReactorClientBuilder,\n setDriveMetadata,\n waitForDocumentReady,\n type BrowserReactorClientModule,\n type Database,\n type IDocumentModelLoader,\n type JwtHandler,\n type ReactorFeatureFlags,\n type SignerConfig,\n} from \"@powerhousedao/reactor-browser\";\nimport type {\n PHConnectDefaultDrive,\n PHConnectDefaultDriveLocal,\n PHConnectDefaultDriveRemote,\n} from \"@powerhousedao/shared/clis\";\nimport type { RuntimePowerhouseConfig } from \"@powerhousedao/shared/connect\";\nimport type {\n DocumentModelModule,\n UpgradeManifest,\n} from \"@powerhousedao/shared/document-model\";\nimport { createSignatureVerifier, type IRenown } from \"@renown/sdk\";\nimport { ConsoleLogger } from \"document-model\";\nimport { Kysely } from \"kysely\";\nimport { PGliteDialect } from \"kysely-pglite-dialect\";\nimport { getReactorPGlite } from \"../pglite.db.js\";\n\n/**\n * Creates a Reactor that plugs into legacy storage but syncs through the new\n * Reactor GQL API.\n */\nexport async function createBrowserReactor(\n documentModelModules: DocumentModelModule[],\n upgradeManifests: UpgradeManifest<readonly number[]>[],\n renown: IRenown,\n featureFlags: Partial<ReactorFeatureFlags>,\n documentModelLoader?: IDocumentModelLoader,\n): Promise<BrowserReactorClientModule> {\n const signerConfig: SignerConfig = {\n signer: renown.signer,\n verifier: createSignatureVerifier(),\n };\n\n const jwtHandler: JwtHandler = async (_url: string) => {\n if (!renown.user) {\n return undefined;\n }\n // aud omitted: server verifies without an audience, so aud-bearing tokens\n // are rejected. Re-enable once both sides support audience restriction.\n return renown.getBearerToken({ expiresIn: 10 });\n };\n\n const pg = await getReactorPGlite();\n const logger = new ConsoleLogger([\"reactor-client\"]);\n const builder = new ReactorClientBuilder()\n .withLogger(logger)\n .withSigner(signerConfig)\n .withReactorBuilder(\n new ReactorBuilder()\n .withDocumentModelSources(documentModelModules)\n .withUpgradeManifests(upgradeManifests)\n .withChannelScheme(ChannelScheme.CONNECT)\n .withExecutorConfig({ featureFlags })\n .withJwtHandler(jwtHandler)\n .withKysely(\n new Kysely<Database>({\n dialect: new PGliteDialect(pg),\n }),\n ),\n );\n\n if (documentModelLoader) {\n builder.withDocumentModelLoader(documentModelLoader);\n }\n\n const module = await builder.buildModule();\n return {\n ...module,\n kind: \"browser\",\n reactorModule: module.reactorModule\n ? { ...module.reactorModule, pg }\n : undefined,\n };\n}\n\nexport function getDefaultDrives(\n runtimeConfig: RuntimePowerhouseConfig,\n): PHConnectDefaultDrive[] {\n return runtimeConfig.connect.drives?.defaultDrives ?? [];\n}\n\n/**\n * Add default drives for the new reactor via sync manager.\n *\n * Drives register concurrently so a slow or unreachable drive can't delay the\n * others — in particular the one the URL slug resolves to. Remote drives\n * retry with linear backoff to handle the common race where Connect's dev\n * server is ready before the switchboard has finished binding its port.\n *\n * Each entry is either a remote drive (a URL registered with the sync\n * manager, waited on for initial backfill) or a local drive (created once in\n * this browser's local reactor; its fixed id makes later boots skip it).\n *\n * @param drives - Array of default-drive entries\n */\nexport async function addDefaultDrivesForNewReactor(\n drives: PHConnectDefaultDrive[],\n): Promise<void> {\n await Promise.all(\n drives.map((drive) =>\n \"url\" in drive\n ? addRemoteDefaultDrive(drive)\n : addLocalDefaultDrive(drive),\n ),\n );\n}\n\nasync function addRemoteDefaultDrive(\n drive: PHConnectDefaultDriveRemote,\n): Promise<void> {\n const MAX_ATTEMPTS = 3;\n const BACKOFF_MS = 2000;\n\n let driveId: string | undefined;\n for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {\n try {\n driveId = await addRemoteDrive(drive.url);\n break;\n } catch (error) {\n if (isDriveAuthError(error)) {\n // addRemoteDrive already surfaces the login modal; auth failures\n // don't self-heal, so don't burn the remaining retries.\n break;\n }\n if (attempt === MAX_ATTEMPTS) {\n console.error(\n `Failed to add default drive ${drive.url} after ${MAX_ATTEMPTS} attempts:`,\n error,\n );\n } else {\n const delay = BACKOFF_MS * attempt;\n console.warn(\n `Default drive ${drive.url} not reachable (attempt ${attempt}/${MAX_ATTEMPTS}), retrying in ${delay}ms...`,\n );\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n }\n\n if (driveId && (drive.name || drive.icon)) {\n try {\n // setDriveMetadata dispatches against the local drive document, which\n // only exists once initial backfill delivers it — wait for it first\n // so the name/icon override isn't lost to a sync race.\n // waitForDocumentReady needs the full reactor client\n const reactorClient = window.ph?.reactorClientModule?.client;\n if (reactorClient) {\n await waitForDocumentReady(reactorClient, driveId, {\n timeoutMs: 15_000,\n });\n }\n await setDriveMetadata(driveId, {\n name: drive.name,\n icon: drive.icon,\n });\n } catch (error) {\n console.warn(\n `Default drive ${drive.url} was added but metadata update failed:`,\n error,\n );\n }\n }\n}\n\n/**\n * Create a configured local default drive in this browser's local reactor.\n * The drive is only created when the configured id is not already taken, so\n * repeated boots are idempotent and a drive the user deleted stays deleted.\n * Name and icon are written straight into the created document's global state\n * (no setDriveMetadata round-trip), and `app` maps to the drive's preferred\n * editor.\n */\nasync function addLocalDefaultDrive(\n drive: PHConnectDefaultDriveLocal,\n): Promise<void> {\n // The union is discriminated on `url`, so a hand-edited config entry with\n // neither `url` nor `id` lands here. Without an id addDrive would mint a\n // random one, creating another drive on every boot.\n if (!drive.id) {\n console.error(\n \"Ignoring local default drive with no id:\",\n JSON.stringify(drive),\n );\n return;\n }\n\n try {\n // isDocumentIdTaken() lives on the full reactor client, not the browser\n // client the interactive addDrive action uses. It asks what the create\n // path asks — is the id reserved, deleted or not — where find() reports\n // only live documents, so a deleted drive would look absent and be\n // re-created (and rejected) on every boot.\n const reactorClient = window.ph?.reactorClientModule?.client;\n if (reactorClient) {\n const taken = await reactorClient.isDocumentIdTaken(drive.id);\n if (taken) {\n return; // created on an earlier boot, or deleted since\n }\n }\n await addDrive(\n {\n id: drive.id,\n global: {\n name: drive.name ?? \"\",\n icon: drive.icon ?? null,\n },\n },\n drive.app,\n );\n } catch (error) {\n console.error(`Failed to create local default drive ${drive.id}:`, error);\n }\n}\n","import {\n OpenFeature,\n type ErrorCode,\n type JsonValue,\n type Provider,\n type ResolutionDetails,\n} from \"@openfeature/web-sdk\";\nimport { logger, setLogLevel, type ILogger } from \"document-model\";\n\n/**\n * QueryParamProvider reads feature flags from URL query parameters.\n *\n * Usage:\n * const params = new URLSearchParams(window.location.search);\n * const provider = new QueryParamProvider(params);\n * await OpenFeature.setProviderAndWait(provider);\n *\n * Query parameter format:\n * ?FEATURE_DUAL_ACTION_CREATE_ENABLED=true&FEATURE_FOO=false\n */\nexport class QueryParamProvider implements Provider {\n public readonly runsOn = \"client\" as const;\n\n readonly metadata = {\n name: \"QueryParamProvider\",\n } as const;\n\n private flags: Map<string, string>;\n\n constructor(searchParams: URLSearchParams) {\n this.flags = new Map();\n\n // Extract all query parameters that look like feature flags\n for (const [key, value] of searchParams.entries()) {\n this.flags.set(key, value);\n }\n }\n\n resolveBooleanEvaluation(\n flagKey: string,\n defaultValue: boolean,\n ): ResolutionDetails<boolean> {\n const value = this.flags.get(flagKey);\n\n if (value === undefined) {\n return {\n value: defaultValue,\n reason: \"DEFAULT\",\n };\n }\n\n // Parse boolean from string\n const boolValue = value.toLowerCase() === \"true\" || value === \"1\";\n\n return {\n value: boolValue,\n reason: \"STATIC\",\n variant: value,\n };\n }\n\n resolveStringEvaluation(\n flagKey: string,\n defaultValue: string,\n ): ResolutionDetails<string> {\n const value = this.flags.get(flagKey);\n\n if (value === undefined) {\n return {\n value: defaultValue,\n reason: \"DEFAULT\",\n };\n }\n\n return {\n value,\n reason: \"STATIC\",\n variant: value,\n };\n }\n\n resolveNumberEvaluation(\n flagKey: string,\n defaultValue: number,\n ): ResolutionDetails<number> {\n const value = this.flags.get(flagKey);\n\n if (value === undefined) {\n return {\n value: defaultValue,\n reason: \"DEFAULT\",\n };\n }\n\n const numValue = Number(value);\n\n if (isNaN(numValue)) {\n return {\n value: defaultValue,\n reason: \"ERROR\",\n errorCode: \"PARSE_ERROR\" as ErrorCode,\n errorMessage: `Failed to parse \"${value}\" as a number`,\n };\n }\n\n return {\n value: numValue,\n reason: \"STATIC\",\n variant: value,\n };\n }\n\n resolveObjectEvaluation<T extends JsonValue>(\n flagKey: string,\n defaultValue: T,\n ): ResolutionDetails<T> {\n const value = this.flags.get(flagKey);\n\n if (value === undefined) {\n return {\n value: defaultValue,\n reason: \"DEFAULT\",\n };\n }\n\n try {\n const objValue = JSON.parse(value) as T;\n return {\n value: objValue,\n reason: \"STATIC\",\n variant: value,\n };\n } catch (error) {\n return {\n value: defaultValue,\n reason: \"ERROR\",\n errorCode: \"PARSE_ERROR\" as ErrorCode,\n errorMessage: `Failed to parse JSON: ${error instanceof Error ? error.message : String(error)}`,\n };\n }\n }\n}\n\n/**\n * Initialize OpenFeature with the QueryParamProvider.\n * Reads feature flags from query parameters.\n */\nexport async function initFeatureFlags(\n searchParams?: URLSearchParams,\n): Promise<Map<string, boolean>> {\n const params =\n searchParams ??\n (typeof window !== \"undefined\"\n ? new URLSearchParams(window.location.search)\n : new URLSearchParams());\n const provider = new QueryParamProvider(params);\n await OpenFeature.setProviderAndWait(provider);\n\n const features = new Map<string, boolean>();\n\n // Handle LOG_LEVEL query param override\n const logLevelParam = params.get(\"LOG_LEVEL\");\n if (logLevelParam) {\n const validLogLevels = [\"verbose\", \"debug\", \"info\", \"warn\", \"error\"];\n if (validLogLevels.includes(logLevelParam.toLowerCase())) {\n setLogLevel(logLevelParam.toLowerCase() as ILogger[\"level\"]);\n logger.info(\n \"Log level set to @level via query param\",\n logLevelParam.toLowerCase(),\n );\n } else {\n logger.warn(\n \"Invalid LOG_LEVEL query param: @param. Valid values: @validLevels\",\n logLevelParam,\n validLogLevels.join(\", \"),\n );\n }\n }\n\n return features;\n}\n","import {\n type IDocumentModelLoader,\n type IPackageDiscoveryService,\n type DiscoveryEvent,\n type DiscoveryEventListener,\n type FailedInstallation,\n type PendingInstallation,\n} from \"@powerhousedao/reactor-browser\";\nimport type { DocumentModelModule } from \"@powerhousedao/shared/document-model\";\nimport type { BrowserPackageManager } from \"./package-manager.js\";\n\n/**\n * Discovery service used when no package registry is configured. Every load\n * for an unknown document type is recorded as a failure with reason\n * \"no-registry\" so the UI can surface the issue; the modal install flow is a\n * no-op because there is no registry to query.\n */\nexport class NoRegistryDiscoveryService\n implements IDocumentModelLoader, IPackageDiscoveryService\n{\n #packageManager: BrowserPackageManager;\n #failed = new Map<string, FailedInstallation>();\n #failedMemo: FailedInstallation[] = [];\n #failedSubscribers = new Set<() => void>();\n #eventSubscribers = new Set<DiscoveryEventListener>();\n\n constructor(packageManager: BrowserPackageManager) {\n this.#packageManager = packageManager;\n }\n\n load(documentType: string): Promise<DocumentModelModule<any>> {\n const existing = this.#findModuleInLoadedPackages(documentType);\n if (existing) {\n this.#clearFailed(documentType);\n return Promise.resolve(existing);\n }\n\n this.#recordFailure(documentType);\n return Promise.reject(\n new Error(\n `No package registry configured; cannot resolve \"${documentType}\"`,\n ),\n );\n }\n\n promptInstallation(): void {\n // no registry to query — nothing to prompt\n }\n\n approveInstallation(): Promise<void> {\n return Promise.resolve();\n }\n\n dismissInstallation(): void {\n // nothing to dismiss\n }\n\n getPendingInstallations(): PendingInstallation[] {\n return [];\n }\n\n subscribePending(): () => void {\n return () => {};\n }\n\n getFailedInstallations(): FailedInstallation[] {\n return this.#failedMemo;\n }\n\n subscribeFailed(listener: () => void): () => void {\n this.#failedSubscribers.add(listener);\n return () => {\n this.#failedSubscribers.delete(listener);\n };\n }\n\n subscribeEvents(listener: DiscoveryEventListener): () => void {\n this.#eventSubscribers.add(listener);\n return () => {\n this.#eventSubscribers.delete(listener);\n };\n }\n\n retryInstallation(documentType: string): Promise<void> {\n // Retry is a no-op without a registry, but re-emitting the failure lets\n // a UI that cleared the row know the underlying condition still holds.\n this.#recordFailure(documentType);\n return Promise.resolve();\n }\n\n #findModuleInLoadedPackages(\n documentType: string,\n ): DocumentModelModule<any> | undefined {\n return this.#packageManager.packages\n .flatMap((p) => p.documentModels)\n .find((m) => m.documentModel.global.id === documentType);\n }\n\n #recordFailure(documentType: string): void {\n this.#failed.set(documentType, {\n documentType,\n reason: \"no-registry\",\n packageNames: [],\n error: null,\n });\n this.#emitEvent({\n type: \"load-failed\",\n documentType,\n reason: \"no-registry\",\n });\n this.#notifyFailedChanged();\n }\n\n #clearFailed(documentType: string): void {\n if (this.#failed.delete(documentType)) {\n this.#notifyFailedChanged();\n }\n }\n\n #notifyFailedChanged(): void {\n this.#failedMemo = Array.from(this.#failed.values());\n for (const listener of this.#failedSubscribers) {\n listener();\n }\n }\n\n #emitEvent(event: DiscoveryEvent): void {\n for (const listener of this.#eventSubscribers) {\n listener(event);\n }\n }\n}\n","import {\n BrowserLocalStorage,\n type IDocumentModelLoader,\n type IPackageDiscoveryService,\n type DiscoveryEvent,\n type DiscoveryEventListener,\n type FailedInstallation,\n type FailedInstallationReason,\n type PendingInstallation,\n} from \"@powerhousedao/reactor-browser\";\nimport type { RegistryClient } from \"@powerhousedao/reactor-browser\";\nimport type { DocumentModelModule } from \"@powerhousedao/shared/document-model\";\nimport type { BrowserPackageManager } from \"./package-manager.js\";\n\nexport type DiscoveryMode = \"immediate\" | \"manual\";\n\ntype DeferredEntry = {\n packageNames: string[];\n resolve: (module: DocumentModelModule<any>) => void;\n reject: (reason: unknown) => void;\n promise: Promise<DocumentModelModule<any>>;\n};\n\nexport class PackageDiscoveryService\n implements IDocumentModelLoader, IPackageDiscoveryService\n{\n #packageManager: BrowserPackageManager;\n #registryClient: RegistryClient;\n #mode: DiscoveryMode;\n\n #deferred = new Map<string, DeferredEntry>();\n #pending = new Map<string, PendingInstallation>();\n #pendingMemo: PendingInstallation[] = [];\n #pendingSubscribers = new Set<() => void>();\n #failed = new Map<string, FailedInstallation>();\n #failedMemo: FailedInstallation[] = [];\n #failedSubscribers = new Set<() => void>();\n #eventSubscribers = new Set<DiscoveryEventListener>();\n #dismissedStorage: BrowserLocalStorage<boolean>;\n #discoveredTypes = new Map<string, string[]>();\n\n constructor(\n packageManager: BrowserPackageManager,\n registryClient: RegistryClient,\n options: { mode: DiscoveryMode; storageKey: string },\n ) {\n this.#packageManager = packageManager;\n this.#registryClient = registryClient;\n this.#mode = options.mode;\n this.#dismissedStorage = new BrowserLocalStorage<boolean>(\n options.storageKey + \":PH_DISMISSED_TYPES\",\n );\n }\n\n load(documentType: string): Promise<DocumentModelModule<any>> {\n const existing = this.#findModuleInLoadedPackages(documentType);\n if (existing) {\n this.#clearFailed(documentType);\n return Promise.resolve(existing);\n }\n\n if (this.#dismissedStorage.has(documentType)) {\n this.#recordFailure(documentType, \"dismissed\", [], null);\n return Promise.reject(\n new Error(`Document type \"${documentType}\" was dismissed`),\n );\n }\n\n const tracked = this.#deferred.get(documentType);\n if (tracked) {\n return tracked.promise;\n }\n\n return this.#discover(documentType);\n }\n\n promptInstallation(documentType: string): void {\n const packageNames = this.#discoveredTypes.get(documentType);\n if (!packageNames) return;\n if (this.#pending.has(documentType)) return;\n\n this.#discoveredTypes.delete(documentType);\n this.#addToPending(documentType, packageNames);\n }\n\n async approveInstallation(packageName: string): Promise<void> {\n const affectedTypes = this.#findTypesByPackage(packageName);\n if (affectedTypes.length === 0) return;\n\n const result = await this.#packageManager.addPackage(packageName);\n if (result.type === \"error\") {\n this.#emitEvent({\n type: \"installation-failed\",\n packageName,\n error: result.error,\n });\n for (const documentType of affectedTypes) {\n const entry = this.#deferred.get(documentType);\n if (entry) {\n entry.reject(result.error);\n this.#deferred.delete(documentType);\n this.#pending.delete(documentType);\n }\n this.#recordFailure(\n documentType,\n \"install-failed\",\n [packageName],\n result.error,\n );\n }\n this.#notifyPendingChanged();\n return;\n }\n\n this.#emitEvent({\n type: \"installation-approved\",\n packageName,\n documentTypes: affectedTypes,\n });\n\n for (const documentType of affectedTypes) {\n const entry = this.#deferred.get(documentType);\n if (!entry) continue;\n\n const module = this.#findModuleInLoadedPackages(documentType);\n if (module) {\n entry.resolve(module);\n this.#clearFailed(documentType);\n } else {\n const error = new Error(\n `Package \"${packageName}\" installed but module for \"${documentType}\" not found`,\n );\n entry.reject(error);\n this.#recordFailure(\n documentType,\n \"install-failed\",\n [packageName],\n error,\n );\n }\n this.#deferred.delete(documentType);\n this.#pending.delete(documentType);\n }\n this.#notifyPendingChanged();\n }\n\n dismissInstallation(packageName: string): void {\n const affectedTypes = this.#findTypesByPackage(packageName);\n if (affectedTypes.length === 0) return;\n\n for (const documentType of affectedTypes) {\n this.#dismissedStorage.set(documentType, true);\n const entry = this.#deferred.get(documentType);\n if (entry) {\n entry.reject(\n new Error(`Document type \"${documentType}\" was dismissed`),\n );\n }\n this.#deferred.delete(documentType);\n this.#pending.delete(documentType);\n this.#discoveredTypes.delete(documentType);\n this.#recordFailure(documentType, \"dismissed\", [packageName], null);\n }\n\n this.#emitEvent({\n type: \"installation-dismissed\",\n packageName,\n documentTypes: affectedTypes,\n });\n this.#notifyPendingChanged();\n }\n\n getPendingInstallations(): PendingInstallation[] {\n return this.#pendingMemo;\n }\n\n subscribePending(listener: () => void): () => void {\n this.#pendingSubscribers.add(listener);\n return () => {\n this.#pendingSubscribers.delete(listener);\n };\n }\n\n getFailedInstallations(): FailedInstallation[] {\n return this.#failedMemo;\n }\n\n subscribeFailed(listener: () => void): () => void {\n this.#failedSubscribers.add(listener);\n return () => {\n this.#failedSubscribers.delete(listener);\n };\n }\n\n subscribeEvents(listener: DiscoveryEventListener): () => void {\n this.#eventSubscribers.add(listener);\n return () => {\n this.#eventSubscribers.delete(listener);\n };\n }\n\n async retryInstallation(documentType: string): Promise<void> {\n this.#dismissedStorage.delete(documentType);\n this.#clearFailed(documentType);\n try {\n await this.#discover(documentType);\n } catch {\n // failure has been recorded via #recordFailure; swallow so the\n // caller (UI button) doesn't have to handle the rejection\n }\n }\n\n async #discover(documentType: string): Promise<DocumentModelModule<any>> {\n // Offline: skip the doomed registry lookup and record an \"offline\" failure\n // so the banner shows an accurate, retryable message (not a generic registry\n // error). Only never-installed types reach here; cached editors rehydrate\n // from the SW.\n if (typeof navigator !== \"undefined\" && navigator.onLine === false) {\n this.#recordFailure(documentType, \"offline\", [], null);\n return Promise.reject(\n new Error(`Offline: cannot discover document type \"${documentType}\"`),\n );\n }\n\n let packageNames: string[];\n try {\n packageNames =\n await this.#registryClient.getPackagesByDocumentType(documentType);\n } catch (error) {\n const normalized =\n error instanceof Error ? error : new Error(String(error));\n this.#emitEvent({\n type: \"registry-query-failed\",\n documentType,\n error: normalized,\n });\n this.#recordFailure(documentType, \"registry-error\", [], normalized);\n return Promise.reject(normalized);\n }\n\n if (packageNames.length === 0) {\n this.#recordFailure(documentType, \"not-in-registry\", [], null);\n return Promise.reject(\n new Error(`No packages found for document type \"${documentType}\"`),\n );\n }\n\n const entry = this.#createDeferredEntry(documentType, packageNames);\n\n this.#emitEvent({\n type: \"type-discovered\",\n documentType,\n packageNames,\n });\n\n if (this.#mode === \"immediate\") {\n this.#addToPending(documentType, packageNames);\n } else {\n this.#discoveredTypes.set(documentType, packageNames);\n }\n\n return entry.promise;\n }\n\n #createDeferredEntry(\n documentType: string,\n packageNames: string[],\n ): DeferredEntry {\n let resolve!: (module: DocumentModelModule<any>) => void;\n let reject!: (reason: unknown) => void;\n const promise = new Promise<DocumentModelModule<any>>((res, rej) => {\n resolve = res;\n reject = rej;\n });\n const entry: DeferredEntry = { packageNames, resolve, reject, promise };\n this.#deferred.set(documentType, entry);\n return entry;\n }\n\n #addToPending(documentType: string, packageNames: string[]): void {\n const installation: PendingInstallation = { documentType, packageNames };\n this.#pending.set(documentType, installation);\n this.#emitEvent({\n type: \"installation-prompted\",\n documentType,\n packageNames,\n });\n this.#notifyPendingChanged();\n }\n\n #findModuleInLoadedPackages(\n documentType: string,\n ): DocumentModelModule<any> | undefined {\n return this.#packageManager.packages\n .flatMap((p) => p.documentModels)\n .find((m) => m.documentModel.global.id === documentType);\n }\n\n #findTypesByPackage(packageName: string): string[] {\n const types: string[] = [];\n for (const [documentType, entry] of this.#deferred) {\n if (entry.packageNames.includes(packageName)) {\n types.push(documentType);\n }\n }\n return types;\n }\n\n #notifyPendingChanged(): void {\n this.#pendingMemo = Array.from(this.#pending.values());\n for (const listener of this.#pendingSubscribers) {\n listener();\n }\n }\n\n #notifyFailedChanged(): void {\n this.#failedMemo = Array.from(this.#failed.values());\n for (const listener of this.#failedSubscribers) {\n listener();\n }\n }\n\n #recordFailure(\n documentType: string,\n reason: FailedInstallationReason,\n packageNames: string[],\n error: Error | null,\n ): void {\n this.#failed.set(documentType, {\n documentType,\n reason,\n packageNames,\n error,\n });\n this.#emitEvent({ type: \"load-failed\", documentType, reason });\n this.#notifyFailedChanged();\n }\n\n #clearFailed(documentType: string): void {\n if (this.#failed.delete(documentType)) {\n this.#notifyFailedChanged();\n }\n }\n\n #emitEvent(event: DiscoveryEvent): void {\n for (const listener of this.#eventSubscribers) {\n listener(event);\n }\n }\n}\n","import * as common from \"@powerhousedao/powerhouse-vetra-packages\";\nimport commonPkg from \"@powerhousedao/powerhouse-vetra-packages/package.json\" with { type: \"json\" };\nimport type {\n IPackagesListener,\n PackageManagerInstallResult,\n} from \"@powerhousedao/reactor-browser\";\nimport {\n BrowserLocalStorage,\n type IPackageListerUnsubscribe,\n type IPackageManager,\n} from \"@powerhousedao/reactor-browser\";\nimport {\n mergePwaConfig,\n type PHConnectPwa,\n type PwaContribution,\n withInferredCategory,\n} from \"@powerhousedao/shared/connect\";\nimport {\n type DocumentModelLib,\n type DocumentModelModule,\n PwaConfigSchema,\n} from \"@powerhousedao/shared/document-model\";\nimport { toCdnUrl } from \"@powerhousedao/shared/registry/urls\";\nimport {\n resolveFragmentAssetUrls,\n writeMergedPwaFragment,\n} from \"./utils/pwa-idb.js\";\nimport { refreshPwaManifestLink } from \"./utils/pwa-manifest-link.js\";\nimport vetraPkg from \"@powerhousedao/vetra/package.json\" with { type: \"json\" };\n\ntype PackageMeta = {\n name: string;\n importUrl: string | null;\n stylesheetUrl: string | null;\n version?: string;\n /**\n * Full spec the user asked for (e.g. `@scope/pkg@2.0.0-beta.2`). Kept so a\n * reload re-installs exactly the tag/version originally picked rather than\n * sliding to `latest`. Absent for legacy entries and local packages.\n */\n spec?: string;\n};\n\n/**\n * Strip any `@tag` / `@version` suffix from a package spec, returning the bare\n * package name. Mirrors `parsePackageSpec` on the UI side.\n */\nfunction parseBareName(spec: string): string {\n const trimmed = spec.trim();\n const at = trimmed.startsWith(\"@\")\n ? trimmed.lastIndexOf(\"@\")\n : trimmed.indexOf(\"@\");\n return at > 0 ? trimmed.slice(0, at) : trimmed;\n}\n\ntype PackageWithMeta = PackageMeta & {\n loadedPackage: DocumentModelLib<any>;\n spec?: string;\n};\n\nasync function fetchPackageJsonVersion(\n baseUrl: string,\n): Promise<string | undefined> {\n try {\n const res = await fetch(baseUrl);\n if (!res.ok) return undefined;\n const pkg = (await res.json()) as { version?: unknown };\n return typeof pkg.version === \"string\" ? pkg.version : undefined;\n } catch {\n return undefined;\n }\n}\n\nconst LOCAL_PACKAGE_NAME = \"Local\" as const;\n\nexport class BrowserPackageManager implements IPackageManager {\n registryUrl: string | null;\n #storage: BrowserLocalStorage<PackageMeta>;\n #packages: Map<string, DocumentModelLib<any>> = new Map();\n #subscribers = new Set<IPackagesListener>();\n #packagesMemo: DocumentModelLib<any>[] = [];\n #stylesheets: Map<string, HTMLStyleElement> = new Map();\n #localPackage: DocumentModelLib<any> | undefined;\n\n #cdnUrl: string | null;\n #localPackageVersion: string | undefined;\n #localPackageNames: Set<string> = new Set([LOCAL_PACKAGE_NAME]);\n #pwaSyncTimer: ReturnType<typeof setTimeout> | undefined;\n /** Serialized last-mirrored PWA fragment; lets a sync skip the IndexedDB\n * write + manifest re-attach when nothing PWA-relevant changed. */\n #lastSyncedFragmentJson: string | undefined;\n\n constructor(namespace: string, registryUrl: string | null) {\n this.#storage = new BrowserLocalStorage<PackageMeta>(\n namespace + \":PH_PACKAGES\",\n );\n this.registryUrl = registryUrl;\n this.#cdnUrl = registryUrl !== null ? toCdnUrl(registryUrl) : null;\n }\n\n async init(\n localPackage?: DocumentModelLib<any>,\n localPackageVersion?: string,\n studioMode?: boolean,\n ) {\n this.addLocalPackage(common.manifest.name, common, commonPkg.version);\n // Vetra is builder-only and not CDN-loadable; lazy-load it (code-split\n // chunk, never fetched in production) only in studio mode.\n if (studioMode) {\n const vetra = await import(\"@powerhousedao/vetra\");\n this.addLocalPackage(vetra.manifest.name, vetra, vetraPkg.version);\n }\n if (localPackage) {\n this.updateLocalPackage(localPackage, localPackageVersion);\n }\n for (const packageName of this.#storage.keys()) {\n // Re-hydrate with the originally-requested spec so a tag/version pick\n // sticks across reloads. Fall back to the bare key for legacy entries\n // (pre-spec) and for entries that never had a tag.\n const existingMeta = this.#storage.get(packageName);\n const specForReload = existingMeta?.spec ?? packageName;\n console.debug(\n `[Connect][PackageManager] Rehydrating \"${packageName}\" via spec \"${specForReload}\"`,\n );\n const result = await this.addPackage(specForReload);\n // Previously-installed package that no longer resolves (version\n // withdrawn from npm, registry moved, etc.) would otherwise\n // 404-toast on every boot forever. Drop it from persistent storage\n // so the failure is one-shot instead of sticky.\n if (result.type === \"error\") {\n this.#storage.delete(packageName);\n }\n }\n }\n\n addLocalPackage(\n name: string,\n loadedPackage: DocumentModelLib<any>,\n version?: string,\n ) {\n this.#localPackageNames.add(name);\n this.#registerPackage({\n name,\n importUrl: null,\n stylesheetUrl: null,\n loadedPackage,\n version,\n });\n }\n\n updateLocalPackage(pkg: DocumentModelLib<any>, version?: string) {\n console.debug(\"Updating local package:\", pkg);\n this.#localPackage = pkg;\n this.#registerPackage({\n name: LOCAL_PACKAGE_NAME,\n stylesheetUrl: null,\n importUrl: null,\n loadedPackage: pkg,\n });\n if (version) {\n this.#localPackageVersion = version;\n this.#notifyPackagesChanged();\n return;\n }\n fetchPackageJsonVersion(\"/package.json\")\n .then((fetchedVersion) => {\n this.#localPackageVersion = fetchedVersion;\n if (fetchedVersion) this.#notifyPackagesChanged();\n })\n .catch(() => {});\n }\n\n get packages() {\n return this.#packagesMemo;\n }\n\n get cdnUrl(): string | null {\n return this.#cdnUrl;\n }\n\n getPackageSource(packageName: string) {\n // check vs packages registered as local (Common, Vetra, bundled packages...)\n if (this.#localPackageNames.has(packageName)) {\n return \"common\";\n }\n // check if the package has the same name as the local project\n if (packageName === this.#localPackage?.manifest.name) return \"project\";\n const packageMeta = this.#storage.get(packageName);\n // if meta does not exist the package is not installed\n if (!packageMeta) return null;\n // if imported from node_modules then the package is installed locally\n if (packageMeta.importUrl === `/node_modules/${packageName}`)\n return \"local-install\";\n // all other import urls point to a registry\n return \"registry-install\";\n }\n\n /**\n * Return the registry-installed packages keyed by their storage name (which\n * is the registry spec, e.g. \"@powerhousedao/clint-common\"), with the\n * installed version when known. Excludes bundled (common) packages, the\n * local project package, and packages resolved out of `/node_modules/`.\n */\n getRegistryPackages(): { name: string; version: string | undefined }[] {\n const out: { name: string; version: string | undefined }[] = [];\n for (const [name, meta] of this.#storage) {\n if (this.#localPackageNames.has(name)) continue;\n if (name === LOCAL_PACKAGE_NAME) continue;\n if (meta.importUrl === `/node_modules/${name}`) continue;\n out.push({ name, version: meta.version });\n }\n return out;\n }\n\n getPackageVersion(packageName: string): string | undefined {\n if (packageName === this.#localPackage?.manifest.name) {\n return this.#localPackageVersion;\n }\n return this.#storage.get(packageName)?.version;\n }\n\n async addPackage(packageSpec: string): Promise<PackageManagerInstallResult> {\n // `packageSpec` may include a `@tag` / `@version` suffix (e.g. user picked\n // a specific version in the package manager UI, or re-hydrated on reload\n // from the persisted spec). We always register/look up by the bare name so\n // status tracking, version lookups, and uninstall all go through a single\n // canonical key. The spec itself is kept on the meta so reloads re-fetch\n // the same tag.\n const bareName = parseBareName(packageSpec);\n const hasTagOrVersion = bareName !== packageSpec;\n console.debug(\n `[Connect][PackageManager] addPackage spec=\"${packageSpec}\" bareName=\"${bareName}\"`,\n );\n\n const existingPackage = this.#packages.get(bareName);\n if (existingPackage) {\n const requestedVersion = hasTagOrVersion\n ? packageSpec.slice(bareName.length + 1)\n : undefined;\n const currentVersion = this.#storage.get(bareName)?.version;\n const isLocal = this.#localPackageNames.has(bareName);\n const sameVersion =\n !requestedVersion ||\n !currentVersion ||\n requestedVersion === currentVersion;\n if (isLocal || sameVersion) {\n console.debug(\n `[Connect][PackageManager] \"${bareName}\" already loaded; skipping re-fetch`,\n );\n return {\n type: \"success\",\n package: existingPackage,\n };\n }\n console.debug(\n `[Connect][PackageManager] \"${bareName}\" version bump ${currentVersion} → ${requestedVersion}; refetching`,\n );\n }\n try {\n const packageWithMeta = await this.#loadPackage(packageSpec);\n // `#loadPackage*` set `name` to whatever spec it built the URL from.\n // Canonicalize to the bare name for the map/storage keys, and stash the\n // original spec separately so reloads re-use it.\n packageWithMeta.name = bareName;\n if (hasTagOrVersion) {\n packageWithMeta.spec = packageSpec;\n }\n // Swap stylesheets only once the new package is in hand. If `#loadPackage`\n // throws above, the old stylesheet stays mounted and the UI keeps\n // rendering the previous version instead of unstyled markup.\n if (existingPackage) {\n this.#unmountStylesheet(bareName);\n }\n this.#registerPackage(packageWithMeta);\n\n return {\n type: \"success\",\n package: packageWithMeta.loadedPackage,\n };\n } catch (error) {\n const normalized =\n error instanceof Error ? error : new Error(String(error));\n console.error(\n `[Connect][PackageManager] Failed to install package \"${packageSpec}\": ${normalized.message}`,\n normalized,\n );\n return {\n type: \"error\",\n error: normalized,\n };\n }\n }\n\n async addPackages(packageNames: string[]) {\n const results: PackageManagerInstallResult[] = [];\n for (const packageName of packageNames) {\n const result = await this.addPackage(packageName);\n results.push(result);\n }\n return results;\n }\n\n removePackage(name: string) {\n this.#packages.delete(name);\n this.#storage.delete(name);\n this.#unmountStylesheet(name);\n this.#notifyPackagesChanged();\n }\n\n subscribe(handler: IPackagesListener): IPackageListerUnsubscribe {\n this.#subscribers.add(handler);\n return () => {\n this.#subscribers.delete(handler);\n };\n }\n\n load(documentType: string): Promise<DocumentModelModule<any>> {\n const documentModelModule = Array.from(\n this.#packages.values().flatMap((p) => p.documentModels),\n ).find((m) => m.documentModel.global.id === documentType);\n\n if (documentModelModule) return Promise.resolve(documentModelModule);\n return Promise.reject(new Error(\"Model not available\"));\n }\n\n async #loadPackageFromNodeModules(name: string): Promise<PackageWithMeta> {\n const importUrl = `/node_modules/${name}/browser/index.js`;\n const stylesheetUrl = `/node_modules/${name}/style.css`;\n\n const packageWithMeta = await this.#importPackage({\n name,\n importUrl,\n stylesheetUrl,\n });\n packageWithMeta.version = await fetchPackageJsonVersion(\n `/node_modules/${name}/package.json`,\n );\n\n return packageWithMeta;\n }\n\n async #loadPackageFromRegistry(name: string): Promise<PackageWithMeta> {\n const importUrl = `${this.#cdnUrl}/${name}/browser/index.js`;\n const stylesheetUrl = `${this.#cdnUrl}/${name}/style.css`;\n const packageWithMeta = await this.#importPackage({\n name,\n importUrl,\n stylesheetUrl,\n });\n packageWithMeta.version = await fetchPackageJsonVersion(\n `${this.#cdnUrl}/${name}/package.json`,\n );\n\n return packageWithMeta;\n }\n\n async #importPackage(packageMeta: PackageMeta): Promise<PackageWithMeta> {\n const { name, importUrl, stylesheetUrl } = packageMeta;\n if (!importUrl) {\n throw new Error(`Import url not defined for package \"${name}\".`);\n }\n\n const loadedPackage = (await import(\n /* @vite-ignore */ importUrl\n )) as DocumentModelLib<any>;\n\n return {\n name,\n loadedPackage,\n importUrl,\n stylesheetUrl,\n };\n }\n\n async #loadPackage(packageName: string): Promise<PackageWithMeta> {\n if (this.#localPackageNames.has(packageName)) {\n throw new Error(\n `Package \"${packageName}\" is a local package and cannot be loaded dynamically.`,\n );\n }\n\n // only attemp to load from node_modules in dev mode\n if (!import.meta.env.PROD) {\n try {\n const packageWithMeta =\n await this.#loadPackageFromNodeModules(packageName);\n return packageWithMeta;\n } catch (error) {\n console.warn(\n `Failed to load package \"${packageName}\" from node_modules:`,\n error,\n );\n }\n }\n\n if (!this.registryUrl) {\n throw new Error(\"Registry url not defined.\");\n }\n\n return await this.#loadPackageFromRegistry(packageName);\n }\n\n #registerPackage(packageWithMeta: PackageWithMeta) {\n const { name, loadedPackage, importUrl, stylesheetUrl, version, spec } =\n packageWithMeta;\n\n if (stylesheetUrl !== null) {\n this.#mountStylesheet(name, stylesheetUrl);\n }\n this.#packages.set(name, loadedPackage);\n this.#storage.set(name, {\n name,\n importUrl,\n stylesheetUrl,\n version,\n ...(spec ? { spec } : {}),\n });\n console.debug(\n `[Connect][PackageManager] Registered \"${name}\" (version=${version ?? \"?\"}, spec=${spec ?? \"—\"})`,\n );\n\n this.#notifyPackagesChanged();\n }\n\n #mountStylesheet(name: string, href: string) {\n const existing = this.#stylesheets.get(name);\n if (existing) return existing;\n\n const style = document.createElement(\"style\");\n style.textContent = `@import url(\"${href}\") layer(external-packages);`;\n document.head.appendChild(style);\n\n this.#stylesheets.set(name, style);\n }\n\n #unmountStylesheet(name: string): void {\n const style = this.#stylesheets.get(name);\n if (!style) return;\n\n style.remove();\n this.#stylesheets.delete(name);\n }\n\n #notifyPackagesChanged() {\n this.#packagesMemo = Array.from(this.#packages.values());\n const packages = this.packages;\n this.#subscribers.forEach((handler) => {\n handler({ packages });\n });\n this.#schedulePwaSync();\n }\n\n /**\n * Debounced mirror of every loaded package's PWA fragment into IndexedDB, so\n * the service worker can serve a web-app manifest that reflects packages\n * installed AT RUNTIME (a SW can't read localStorage, where the package list\n * lives). Debounced because `init()` rehydrates many packages in a burst;\n * coalescing collapses that into a single write.\n */\n #schedulePwaSync() {\n if (typeof indexedDB === \"undefined\") return;\n clearTimeout(this.#pwaSyncTimer);\n this.#pwaSyncTimer = setTimeout(() => {\n void this.#syncPwaFragments();\n }, 50);\n }\n\n async #syncPwaFragments() {\n const contributions: PwaContribution[] = [];\n for (const [name, loadedPackage] of this.#packages) {\n const manifest = loadedPackage.manifest;\n let config: PHConnectPwa = {};\n if (manifest.pwa) {\n // Third-party package code must not inject arbitrary manifest fields the\n // SW will serve — validate strictly and skip (with a warning) on failure.\n const parsed = PwaConfigSchema.safeParse(manifest.pwa);\n if (parsed.success) {\n // A package's assets live at its base (CDN for registry installs);\n // make relative icon srcs absolute so the served manifest resolves.\n const importUrl = this.#storage.get(name)?.importUrl ?? null;\n const baseUrl = importUrl\n ? importUrl.replace(/browser\\/index\\.js$/, \"\")\n : null;\n config = resolveFragmentAssetUrls(parsed.data, baseUrl);\n } else {\n console.warn(\n `[Connect][PWA] \"${name}\" ships an invalid pwa fragment; skipped.`,\n parsed.error,\n );\n }\n }\n // `categories` is derived from the manifest's `category` field (not\n // authored under `pwa`); it unions into the SW-served manifest so a\n // runtime-installed package's category shows up like a build-time one.\n config = withInferredCategory(config, manifest.category);\n if (Object.keys(config).length === 0) continue;\n contributions.push({ source: name, config });\n }\n // Fold in load order (base-first ordering is preserved so a package cannot\n // hijack the built-in .phd/.phdm handler at merge time either).\n const merged = mergePwaConfig(contributions);\n // Most package operations don't touch PWA config; skip the write + manifest\n // re-attach (which forces a redundant manifest re-fetch) when unchanged.\n const mergedJson = JSON.stringify(merged);\n if (mergedJson === this.#lastSyncedFragmentJson) return;\n try {\n await writeMergedPwaFragment(merged);\n } catch (error) {\n // Leave #lastSyncedFragmentJson unset so a later sync retries the write.\n console.debug(\n \"[Connect][PWA] fragment mirror to IndexedDB failed:\",\n error,\n );\n return;\n }\n this.#lastSyncedFragmentJson = mergedJson;\n // The SW serves the manifest fresh from IndexedDB, but the browser only\n // parsed <link rel=\"manifest\"> at page load — re-attach it so it\n // re-consumes the now-updated manifest without a manual reload. (Kept out\n // of the write's try/catch so a DOM error isn't mislabeled as an IDB\n // failure; refreshPwaManifestLink is itself non-throwing.)\n refreshPwaManifestLink();\n }\n}\n","const GEN_KEY_PREFIX = \"ph-reactor-gen:\";\n\n// A persisted generation token, bumped on restart, is folded into the\n// SharedWorker name so a restart spawns a fresh worker instance while the\n// IndexedDB namespace (and its data) stays put.\nexport function reactorWorkerName(namespace: string): string {\n const gen = readWorkerGen(namespace);\n return gen ? `ph-reactor:${namespace}#${gen}` : `ph-reactor:${namespace}`;\n}\n\nexport function readWorkerGen(namespace: string): string | null {\n try {\n return localStorage.getItem(GEN_KEY_PREFIX + namespace);\n } catch {\n return null;\n }\n}\n\nexport function bumpWorkerGen(namespace: string, gen: string): void {\n try {\n localStorage.setItem(GEN_KEY_PREFIX + namespace, gen);\n } catch {\n // localStorage unavailable; the reload falls back to reusing the worker.\n }\n}\n","import {\n DocumentModelRegistry,\n DocumentModelResolver,\n ReactorEventTypes,\n type IDocumentModelLoader,\n type ModelLoadedEvent,\n type ReactorFeatureFlags,\n} from \"@powerhousedao/reactor\";\nimport {\n setPGliteDB,\n type WorkerReactorClientModule,\n} from \"@powerhousedao/reactor-browser\";\nimport {\n connectReactorClient,\n createInspectorProxy,\n createPortTransport,\n createReactorEventBusProxy,\n createRelationalPgliteProxy,\n createWorkerAdminClient,\n MessageRouter,\n postReactorIdentity,\n RPC_PROTOCOL_VERSION,\n SyncManagerProxy,\n type ReactorIdentity,\n} from \"@powerhousedao/reactor-browser/rpc\";\nimport type {\n DocumentModelModule,\n UpgradeManifest,\n} from \"@powerhousedao/shared/document-model\";\nimport type { IRenown, User } from \"@renown/sdk\";\nimport { setWorkerConnectionStatus } from \"./connection-state.js\";\nimport { reactorWorkerName } from \"./reactor-worker-name.js\";\nimport { getGitSha, getVersion } from \"./utils/build-info.js\";\n\nconst PING_INTERVAL_MS = 2000;\nconst PING_DEADLINE_MS = 3000;\nconst MAX_MISSED_PINGS = 2;\n\nexport type WorkerReactorClientArgs = {\n namespace: string;\n relationalNamespace: string;\n cdnUrl: string;\n packageSpecs: string[];\n studioMode?: boolean;\n /** Chain the worker's bearer tokens are scoped to; matches the main thread's Renown instance. */\n renownChainId?: number;\n /** Enforcement flags for the worker's reactor; it has no runtime config to read them from. */\n featureFlags: Partial<ReactorFeatureFlags>;\n documentModelModules: DocumentModelModule[];\n upgradeManifests: UpgradeManifest<readonly number[]>[];\n documentModelLoader: IDocumentModelLoader;\n renown: IRenown;\n onReload: (reason: string, workerGen?: string) => void;\n};\n\nexport type WorkerReactorClient = {\n reactorClientModule: WorkerReactorClientModule;\n syncManagerProxy: SyncManagerProxy;\n dispose: () => void;\n};\n\n/** Sorted so the same set always produces the same fingerprint. */\nfunction enabledFlagList(flags: Partial<ReactorFeatureFlags>): string {\n return Object.entries(flags)\n .filter(([, enabled]) => enabled)\n .map(([name]) => name)\n .sort()\n .join(\",\");\n}\n\nfunction toReactorIdentity(user: User | undefined): ReactorIdentity | null {\n if (!user) {\n return null;\n }\n return {\n address: user.address,\n chainId: user.chainId,\n networkId: user.networkId,\n };\n}\n\nexport function createWorkerReactorClientModule(\n args: WorkerReactorClientArgs,\n): WorkerReactorClient {\n const workerUrl = new URL(\"./reactor.worker.js\", import.meta.url);\n console.info(\n `[reactor-worker] constructing SharedWorker ${reactorWorkerName(\n args.namespace,\n )} from ${workerUrl.href}`,\n );\n const worker = new SharedWorker(workerUrl, {\n name: reactorWorkerName(args.namespace),\n type: \"module\",\n });\n worker.addEventListener(\"error\", (event) => {\n console.error(\n `[reactor-worker] SharedWorker failed to load from ${workerUrl.href}`,\n event.message || event,\n );\n });\n worker.port.onmessageerror = (event) => {\n console.error(\n \"[reactor-worker] port message could not be deserialized\",\n event,\n );\n };\n const transport = createPortTransport(worker.port);\n const router = new MessageRouter();\n router.attach(transport);\n\n const documentModelRegistry = new DocumentModelRegistry();\n documentModelRegistry.registerModules(...args.documentModelModules);\n documentModelRegistry.registerUpgradeManifests(...args.upgradeManifests);\n\n const gitSha = getGitSha();\n const clientProxy = connectReactorClient(\n router,\n {\n version: {\n appBuildId: gitSha !== \"unknown\" ? gitSha : getVersion(),\n rpcProtocolVersion: RPC_PROTOCOL_VERSION,\n models: args.documentModelModules.map((m) => ({\n id: m.documentModel.global.id,\n version: m.version ?? 1,\n })),\n featureFlags: enabledFlagList(args.featureFlags),\n },\n construct: {\n namespace: args.namespace,\n relationalNamespace: args.relationalNamespace,\n cdnUrl: args.cdnUrl,\n packageSpecs: args.packageSpecs,\n studioMode: args.studioMode,\n renownChainId: args.renownChainId,\n featureFlags: args.featureFlags,\n },\n packages: args.packageSpecs,\n },\n args.onReload,\n documentModelRegistry,\n );\n\n const busProxy = createReactorEventBusProxy(router);\n const syncManagerProxy = new SyncManagerProxy(router, busProxy);\n\n // Keep the tab registry synced with the worker's on-demand loads.\n const modelResolver = new DocumentModelResolver(\n documentModelRegistry,\n args.documentModelLoader,\n );\n busProxy.subscribe(ReactorEventTypes.MODEL_LOADED, (_type, event) => {\n const { documentType } = event as ModelLoadedEvent;\n void modelResolver.ensureModelLoaded(documentType).catch((error) => {\n console.error(\n `Failed to load model \"${documentType}\" into tab registry`,\n error,\n );\n });\n });\n\n // Seed the relational read surface the relational hooks read (SELECT + live, no raw PGlite).\n setPGliteDB({\n db: createRelationalPgliteProxy(router),\n isLoading: false,\n error: null,\n });\n\n postReactorIdentity(router, toReactorIdentity(args.renown.user));\n args.renown.on(\"user\", (user) =>\n postReactorIdentity(router, toReactorIdentity(user)),\n );\n\n const reactorClientModule: WorkerReactorClientModule = {\n kind: \"worker\",\n client: clientProxy,\n adminClient: createWorkerAdminClient(router),\n inspector: createInspectorProxy(router),\n reactorModule: {\n documentModelRegistry,\n syncModule: { syncManager: syncManagerProxy },\n eventBus: busProxy,\n },\n };\n\n let pingCounter = 0;\n let missedPings = 0;\n const pingDeadlines = new Map<string, ReturnType<typeof setTimeout>>();\n\n router.on(\"pong\", (msg) => {\n const timer = pingDeadlines.get(msg.id);\n if (timer === undefined) {\n return;\n }\n clearTimeout(timer);\n pingDeadlines.delete(msg.id);\n missedPings = 0;\n setWorkerConnectionStatus(\"connected\");\n });\n\n const pingInterval = setInterval(() => {\n const id = `ping${++pingCounter}`;\n const timer = setTimeout(() => {\n pingDeadlines.delete(id);\n missedPings += 1;\n if (missedPings >= MAX_MISSED_PINGS) {\n setWorkerConnectionStatus(\"lost\");\n }\n }, PING_DEADLINE_MS);\n pingDeadlines.set(id, timer);\n router.post({ k: \"ping\", id });\n }, PING_INTERVAL_MS);\n\n const dispose = () => {\n clearInterval(pingInterval);\n for (const timer of pingDeadlines.values()) {\n clearTimeout(timer);\n }\n pingDeadlines.clear();\n };\n\n return { reactorClientModule, syncManagerProxy, dispose };\n}\n","import { getRuntimeConfig } from \"../runtime-config.js\";\n\nexport const REACTOR_WORKER_QUERY_KEY = \"reactorWorker\";\nexport const REACTOR_WORKER_STORAGE_KEY = \"ph:reactorWorker\";\n\nexport type ReactorWorkerFlagInput = {\n configFlag: boolean;\n queryParam?: string | null;\n storedValue?: string | null;\n};\n\nexport function resolveReactorWorkerEnabled(\n input: ReactorWorkerFlagInput,\n): boolean {\n const fromQuery = parseFlag(input.queryParam);\n if (fromQuery !== undefined) {\n return fromQuery;\n }\n const fromStore = parseFlag(input.storedValue);\n if (fromStore !== undefined) {\n return fromStore;\n }\n return input.configFlag;\n}\n\n// Effective flag from config + dev override; a query-param override is persisted\n// to localStorage so it survives a refresh.\nexport function isReactorWorkerEnabled(): boolean {\n const configFlag =\n getRuntimeConfig().connect.instance?.reactorWorker ?? false;\n if (typeof window === \"undefined\") {\n return configFlag;\n }\n const queryParam = new URLSearchParams(window.location.search).get(\n REACTOR_WORKER_QUERY_KEY,\n );\n const storedValue = window.localStorage.getItem(REACTOR_WORKER_STORAGE_KEY);\n const enabled = resolveReactorWorkerEnabled({\n configFlag,\n queryParam,\n storedValue,\n });\n // Persist only an explicit override, not an unrecognized value.\n if (parseFlag(queryParam) !== undefined) {\n window.localStorage.setItem(\n REACTOR_WORKER_STORAGE_KEY,\n enabled ? \"true\" : \"false\",\n );\n }\n return enabled;\n}\n\nfunction parseFlag(value: string | null | undefined): boolean | undefined {\n if (value === null || value === undefined) {\n return undefined;\n }\n const normalized = value.trim().toLowerCase();\n if (normalized === \"true\" || normalized === \"1\") {\n return true;\n }\n if (normalized === \"false\" || normalized === \"0\") {\n return false;\n }\n // Unrecognized value (e.g. a typo): no override, fall through to store/config.\n return undefined;\n}\n","import {\n createReactorHostModuleBase,\n type IReadModel,\n} from \"@powerhousedao/reactor\";\nimport {\n createAttachmentClient,\n type AttachmentDownloadTarget,\n type AttachmentHeader,\n type AttachmentResponse,\n type IAttachmentService,\n} from \"@powerhousedao/reactor-attachments/client\";\nimport {\n createAnalyticsStore,\n type IProcessorHostModule,\n type IReactorClient,\n} from \"@powerhousedao/reactor-browser\";\nimport { getDb } from \"../pglite.db.js\";\n\n/** @deprecated Use IReactorClient from @powerhousedao/reactor-browser */\nexport type IReactorDispatch = IReactorClient;\n\nclass NullAttachmentService implements IAttachmentService {\n reserve(): Promise<never> {\n return Promise.reject(\n new Error(\"NullAttachmentService: no attachment service configured\"),\n );\n }\n stat(): Promise<AttachmentHeader> {\n return Promise.reject(\n new Error(\"NullAttachmentService: no attachment service configured\"),\n );\n }\n get(): Promise<AttachmentResponse> {\n return Promise.reject(\n new Error(\"NullAttachmentService: no attachment service configured\"),\n );\n }\n getDownloadTarget(): Promise<AttachmentDownloadTarget> {\n return Promise.reject(\n new Error(\"NullAttachmentService: no attachment service configured\"),\n );\n }\n}\n\nexport async function createProcessorHostModule(\n reactorClient: IReactorClient,\n readModels: ReadonlyArray<Pick<IReadModel, \"name\">>,\n attachmentService?: IAttachmentService,\n): Promise<IProcessorHostModule | undefined> {\n try {\n const { pgLite, relationalDb } = await getDb();\n const { store: analyticsStore } = await createAnalyticsStore({\n pgLite,\n });\n return {\n ...createReactorHostModuleBase({\n client: reactorClient,\n readModels,\n relationalDb,\n analyticsStore,\n processorApp: \"connect\",\n }),\n attachments: createAttachmentClient(\n attachmentService ?? new NullAttachmentService(),\n ),\n };\n } catch (error) {\n console.error(`Failed to initialize processor host module:`);\n console.error(error);\n }\n}\n","import {\n buildPHGlobalConfig,\n phGlobalConfig,\n} from \"@powerhousedao/connect/config\";\nimport { toast } from \"@powerhousedao/connect/services\";\nimport {\n addDefaultDrivesForNewReactor,\n createBrowserReactor,\n getDefaultDrives,\n} from \"@powerhousedao/connect/utils\";\nimport {\n createRemoteAttachmentService,\n createXhrUploadTransport,\n} from \"@powerhousedao/reactor-attachments/client\";\nimport {\n addPHEventHandlers,\n addRemoteDrive,\n DocumentCache,\n DocumentChangeType,\n DRIVE_DOCUMENT_TYPES,\n extractDriveSlugFromPath,\n extractNodeSlugFromPath,\n getDrives,\n login,\n refreshReactorDataClient,\n RegistryClient,\n setAttachmentService,\n setDefaultPHGlobalConfig,\n setDocumentCache,\n setDrives,\n setFeatures,\n setPackageDiscoveryService,\n setPHToast,\n setReactorClient,\n setReactorClientModule,\n setRenown,\n setSelectedDrive,\n setSelectedNode,\n setVetraPackageManager,\n type BrowserReactorClientModule,\n type IDocumentModelLoader,\n type IPackageManager,\n type PHToastFn,\n type ReactorFeatureFlags,\n type WorkerReactorClientModule,\n} from \"@powerhousedao/reactor-browser\";\nimport {\n BrowserKeyStorage,\n RenownBuilder,\n RenownCryptoBuilder,\n} from \"@renown/sdk\";\nimport {\n logger,\n type DocumentModelLib,\n type UpgradeManifest,\n} from \"document-model\";\nimport { initFeatureFlags } from \"../feature-flags.js\";\nimport { NoRegistryDiscoveryService } from \"../no-registry-discovery.js\";\nimport { PackageDiscoveryService } from \"../package-discovery.js\";\nimport { BrowserPackageManager } from \"../package-manager.js\";\nimport { createWorkerReactorClientModule } from \"../reactor-worker-client.js\";\nimport { bumpWorkerGen } from \"../reactor-worker-name.js\";\nimport { getRuntimeConfig } from \"../runtime-config.js\";\nimport { isReactorWorkerEnabled } from \"../utils/reactor-worker-flag.js\";\nimport {\n REACTOR_INSTANCE_NAMESPACE,\n RELATIONAL_PGLITE_NAME,\n} from \"../utils/storage-namespace.js\";\nimport { createProcessorHostModule } from \"./processor-host-module.js\";\n\n/**\n * Subscribe to ph-clint's `/__packages` SSE channel; each `packages-changed`\n * event sends the full live list, which we diff to add/remove packages.\n * Best-effort: no-ops when the endpoint is absent (e.g. vite dev).\n */\nfunction subscribeToPackagesChannel(packageManager: IPackageManager): void {\n if (typeof window === \"undefined\" || typeof EventSource === \"undefined\") {\n return;\n }\n let source: EventSource;\n try {\n source = new EventSource(\"/__packages\");\n } catch (err) {\n console.debug(\"[Connect] /__packages subscribe failed:\", err);\n return;\n }\n let firstEvent = true;\n source.addEventListener(\"packages-changed\", (event) => {\n try {\n const payload = JSON.parse((event as MessageEvent<string>).data) as {\n packages?: unknown;\n };\n if (!Array.isArray(payload.packages)) return;\n const next = payload.packages.filter(\n (p): p is string => typeof p === \"string\",\n );\n // Split a spec into (bareName, version). For scoped specs the leading\n // `@` is the scope, so the version `@` only counts when past index 0.\n const parseBare = (\n spec: string,\n ): { bareName: string; version?: string } => {\n const at = spec.startsWith(\"@\")\n ? spec.lastIndexOf(\"@\")\n : spec.indexOf(\"@\");\n if (at > 0) {\n return { bareName: spec.slice(0, at), version: spec.slice(at + 1) };\n }\n return { bareName: spec };\n };\n\n // Diff against registry packages only; bundled/local packages aren't in\n // the server list and removing them would break the drive editors.\n const currentByName = new Map(\n packageManager\n .getRegistryPackages()\n .map(({ name, version }) => [name, version]),\n );\n const nextByName = new Map<string, string | undefined>();\n for (const spec of next) {\n const { bareName, version } = parseBare(spec);\n nextByName.set(bareName, version);\n }\n\n const isFirst = firstEvent;\n firstEvent = false;\n\n for (const name of currentByName.keys()) {\n if (!nextByName.has(name)) {\n packageManager.removePackage(name);\n if (!isFirst) {\n toast(`Removed package ${name}`, { type: \"connect-deleted\" });\n }\n }\n }\n for (const spec of next) {\n const { bareName, version } = parseBare(spec);\n const currentVersion = currentByName.get(bareName);\n const isKnown = currentByName.has(bareName);\n if (\n isKnown &&\n (!version || !currentVersion || version === currentVersion)\n ) {\n continue;\n }\n const isUpdate = isKnown;\n Promise.resolve(packageManager.addPackage(spec)).then(\n (result) => {\n if (result.type === \"error\") {\n console.error(\n `[Connect] /__packages addPackage(${spec}) failed:`,\n result.error,\n );\n return;\n }\n if (isFirst) return;\n const name = result.package.manifest.name;\n toast(\n isUpdate\n ? `Updated package ${name}`\n : `Installed package ${name}`,\n { type: \"connect-success\" },\n );\n },\n (err: unknown) => {\n console.error(\n `[Connect] /__packages addPackage(${spec}) threw:`,\n err,\n );\n },\n );\n }\n } catch (err) {\n console.error(\"[Connect] /__packages event parse failed:\", err);\n }\n });\n source.addEventListener(\"error\", () => {\n // EventSource auto-reconnects.\n });\n}\n\nexport async function clearReactorStorage() {\n const module = window.ph?.reactorClientModule;\n if (module?.kind === \"worker\") {\n // The worker holds the PGlite handles open, so it must close + clear them.\n await module.adminClient.clearStorage();\n return;\n }\n if (module?.kind === \"browser\") {\n await module.reactorModule?.pg?.close();\n }\n\n // Dropping tables in PGlite with relaxedDurability can lose pending IDB\n // writes on reload; delete the whole DB so startup re-migrates from scratch.\n const dbs = await indexedDB.databases();\n const targets = dbs\n .map((d) => d.name)\n .filter(\n (n): n is string =>\n !!n && !n.startsWith(\"ph-pglite-backup::\") && /pglite|reactor/i.test(n),\n );\n\n await Promise.all(\n targets.map(\n (name) =>\n new Promise<void>((resolve) => {\n const req = indexedDB.deleteDatabase(name);\n req.onsuccess = req.onerror = req.onblocked = () => resolve();\n }),\n ),\n );\n}\n\nexport async function createReactor(localPackage?: DocumentModelLib) {\n if (!window.ph) {\n window.ph = {};\n }\n if (window.ph.loading) return;\n\n window.ph.loading = true;\n\n addPHEventHandlers();\n\n setPHToast(toast as PHToastFn);\n\n const features = await initFeatureFlags();\n\n logger.info(\n \"Features: @features\",\n JSON.stringify(Object.fromEntries(features), null, 2),\n );\n\n // Credentials and the bearer token must be scoped to the same chain, and the\n // worker mints its own tokens, so this value is passed to it too (see below).\n const renownChainId = getRuntimeConfig().connect.renown?.chainId;\n\n const keyPairStorage = await BrowserKeyStorage.create();\n const cryptoBuilder = new RenownCryptoBuilder().withKeyPairStorage(\n keyPairStorage,\n );\n if (renownChainId !== undefined) {\n cryptoBuilder.withChainId(renownChainId);\n }\n const renownCrypto = await cryptoBuilder.build();\n\n // Renown namespace is a boot-time constant, so read it from runtime config\n // rather than the PHGlobalConfig machinery; baseUrl stays in phGlobalConfig.\n const renown = await new RenownBuilder(\"connect\", {\n basename:\n getRuntimeConfig().connect.renown?.namespace ??\n phGlobalConfig.routerBasename,\n baseUrl: phGlobalConfig.renownUrl,\n switchboardUrl: phGlobalConfig.switchboardUrl,\n chainId: renownChainId,\n })\n .withCrypto(renownCrypto)\n .build();\n\n // Sync getter is safe: loadComponent() warmed the cache before createReactor,\n // and it throws loudly if a future caller violates that boot ordering.\n const runtimeConfig = getRuntimeConfig();\n\n const packageManager = new BrowserPackageManager(\n phGlobalConfig.routerBasename ?? \"\",\n runtimeConfig.packageRegistryUrl ?? null,\n );\n setVetraPackageManager(packageManager);\n await packageManager.init(\n localPackage,\n runtimeConfig.localPackage?.version,\n phGlobalConfig.studioMode,\n );\n // Register provider:\"local\" packages the vite plugin bundled in. The virtual\n // module only exists under phBundledPackagesPlugin (ph-cli), so a resolution\n // failure under plain vite dev is expected; the indirection + @vite-ignore\n // also stops Vite's dep scanner from pre-bundling the specifier.\n try {\n const bundledPackagesModule = \"ph-bundled-packages-virtual\";\n const { default: registerBundledPackages } = (await import(\n /* @vite-ignore */ bundledPackagesModule\n )) as { default: (pm: IPackageManager) => void };\n registerBundledPackages(packageManager);\n } catch {\n // no bundled packages in this build\n }\n const remotePackages = runtimeConfig.packages\n .filter((p) => p.provider !== \"local\")\n .map((p) => (p.version ? `${p.packageName}@${p.version}` : p.packageName));\n const packagesResult = await packageManager.addPackages(remotePackages);\n packagesResult.map((r) => {\n if (r.type === \"error\") console.error(r.error);\n });\n\n // Opt-in (connect.packages.liveReload): pick up live publishes without a\n // page reload via the static-mode `/__packages` SSE channel.\n if (runtimeConfig.connect?.packages?.liveReload) {\n subscribeToPackagesChannel(packageManager);\n }\n\n const documentModelModules = packageManager.packages\n .flatMap((pkg) => pkg.documentModels)\n .filter(\n (module, index, modules) =>\n // dedupe by documentType and version\n modules.findIndex(\n (m) =>\n m.documentModel.global.id === module.documentModel.global.id &&\n m.version === module.version,\n ) === index,\n );\n\n const upgradeManifests = packageManager.packages\n .flatMap((pkg) => pkg.upgradeManifests)\n .filter(\n (manifest, index, manifests) =>\n // dedupe by documentType\n manifest !== undefined &&\n manifests.findIndex(\n (m) => m && m.documentType === manifest.documentType,\n ) === index,\n ) as UpgradeManifest<readonly number[]>[];\n\n // auto-installs packages for unknown document types\n const discoveryService =\n packageManager.cdnUrl !== null\n ? new PackageDiscoveryService(\n packageManager,\n new RegistryClient(packageManager.cdnUrl),\n {\n mode: \"immediate\",\n storageKey: phGlobalConfig.routerBasename ?? \"\",\n },\n )\n : new NoRegistryDiscoveryService(packageManager);\n\n setPackageDiscoveryService(discoveryService);\n\n // Config alone, no per-tab override: these must match the fleet Connect syncs\n // with. The worker gets them in its construct message.\n const reactorFeatureFlags: Partial<ReactorFeatureFlags> =\n runtimeConfig.connect?.reactor?.featureFlags ?? {};\n const enabledReactorFlags = Object.entries(reactorFeatureFlags)\n .filter(([, enabled]) => enabled)\n .map(([name]) => name);\n if (enabledReactorFlags.length > 0) {\n logger.info(`Reactor feature flags: ${enabledReactorFlags.join(\", \")}`);\n }\n\n // create reactor v2 with all versions and upgrade manifests\n let reactorClientModule:\n | BrowserReactorClientModule\n | WorkerReactorClientModule;\n if (isReactorWorkerEnabled()) {\n const packageSpecs = packageManager\n .getRegistryPackages()\n .map((p) => (p.version ? `${p.name}@${p.version}` : p.name));\n // Silent tab loader (no install prompt; the worker already loaded the model).\n const registryClient = new RegistryClient(packageManager.cdnUrl ?? \"\");\n const documentModelLoader: IDocumentModelLoader = {\n async load(documentType) {\n const names = packageManager.cdnUrl\n ? await registryClient.getPackagesByDocumentType(documentType)\n : [];\n for (const name of names) {\n const result = await packageManager.addPackage(name);\n if (result.type === \"error\") {\n throw new Error(\n `Failed to install package \"${name}\" for document model: ${documentType}`,\n { cause: result.error },\n );\n }\n }\n const module = packageManager.packages\n .flatMap((p) => p.documentModels)\n .find((m) => m.documentModel.global.id === documentType);\n if (!module) {\n throw new Error(\n names.length > 0\n ? `Installed [${names.join(\", \")}] but document model not available: ${documentType}`\n : `No package found for document model: ${documentType} (cdnUrl: ${packageManager.cdnUrl ?? \"none\"})`,\n );\n }\n return module;\n },\n };\n const workerClient = createWorkerReactorClientModule({\n namespace: REACTOR_INSTANCE_NAMESPACE,\n relationalNamespace: RELATIONAL_PGLITE_NAME,\n cdnUrl: packageManager.cdnUrl ?? \"\",\n packageSpecs,\n studioMode: phGlobalConfig.studioMode,\n renownChainId,\n featureFlags: reactorFeatureFlags,\n documentModelModules,\n upgradeManifests,\n documentModelLoader,\n renown,\n onReload: (reason, workerGen) => {\n logger.warn(\"Reactor worker requested reload: @reason\", reason);\n if (workerGen) {\n bumpWorkerGen(REACTOR_INSTANCE_NAMESPACE, workerGen);\n }\n window.location.reload();\n },\n });\n reactorClientModule = workerClient.reactorClientModule;\n // Block boot until the sync manager seeds remotes from the worker, so\n // list()/connection state are warm before consumers first read them.\n try {\n await workerClient.syncManagerProxy.startup();\n } catch (error) {\n window.ph.loading = false;\n logger.error(\"Reactor worker failed to start: @error\", error);\n throw error;\n }\n } else {\n reactorClientModule = await createBrowserReactor(\n documentModelModules,\n upgradeManifests,\n renown,\n reactorFeatureFlags,\n discoveryService,\n );\n }\n\n const drives = await getDrives(reactorClientModule.client);\n\n const didFromUrl = getDidFromUrl();\n await login(didFromUrl, renown);\n\n const documentCache = new DocumentCache(reactorClientModule.client);\n\n const basePath = phGlobalConfig.basePath ?? \"/\";\n const routerBasename = phGlobalConfig.routerBasename ?? \"/\";\n const mergedGlobalConfig = buildPHGlobalConfig(\n basePath,\n routerBasename,\n runtimeConfig.connect ?? {},\n );\n setDefaultPHGlobalConfig(mergedGlobalConfig);\n\n // Slug extraction needs window.ph.basePath, published by\n // setDefaultPHGlobalConfig above.\n const path = window.location.pathname;\n const driveSlug = extractDriveSlugFromPath(path);\n const nodeSlug = extractNodeSlugFromPath(path);\n setReactorClientModule(reactorClientModule);\n setReactorClient(reactorClientModule.client);\n\n const _defaultDrivesUrl = phGlobalConfig.defaultDrivesUrl;\n if (_defaultDrivesUrl) {\n let switchboardOrigin: string | undefined;\n try {\n switchboardOrigin = new URL(_defaultDrivesUrl).origin;\n } catch {\n // malformed URL — skip attachment service construction\n }\n if (switchboardOrigin) {\n const attachmentJwtHandler = async (_url: string) => {\n if (!renown.user) return undefined;\n // aud omitted: server rejects aud-bearing tokens. Re-enable once both sides support it.\n return renown.getBearerToken({ expiresIn: 10 });\n };\n const attachmentService = createRemoteAttachmentService({\n remoteUrl: switchboardOrigin,\n jwtHandler: attachmentJwtHandler,\n // XMLHttpRequest is the only browser API that reports upload byte\n // progress; everything else about the request is unchanged.\n uploadTransport: createXhrUploadTransport(),\n });\n setAttachmentService(attachmentService);\n }\n }\n\n setDocumentCache(documentCache);\n setRenown(renown);\n setDrives(drives);\n setFeatures(features);\n\n // Add default/remote drives in the background so the app renders immediately;\n // setSelectedDrive defers selection until the URL-matched drive syncs in.\n const defaultDrivesConfig = getDefaultDrives(runtimeConfig);\n if (defaultDrivesConfig.length > 0) {\n void addDefaultDrivesForNewReactor(defaultDrivesConfig).catch((error) =>\n console.error(\"Failed to add default drives:\", error),\n );\n }\n\n const remoteUrl = getDriveUrl();\n if (remoteUrl) {\n void addRemoteDrive(remoteUrl, undefined).catch((error) =>\n console.error(`Failed to add remote drive from ${remoteUrl}:`, error),\n );\n }\n\n setSelectedDrive(driveSlug);\n setSelectedNode(nodeSlug);\n\n // Refresh the drive list on any drive-type change so async-added\n // default/remote drives surface on first load without a manual reload.\n const reactorClient = reactorClientModule.client;\n for (const driveType of DRIVE_DOCUMENT_TYPES) {\n reactorClient.subscribe({ type: driveType }, (event) => {\n logger.verbose(\"ReactorClient subscription event: @event\", event);\n refreshReactorDataClient(reactorClientModule.client).catch((e) =>\n logger.error(\"@error\", e),\n );\n });\n }\n\n // Redirect when a currently-viewed document or drive is deleted remotely\n reactorClient.subscribe({}, (event) => {\n if (event.type !== DocumentChangeType.Deleted) return;\n const deletedId = event.context?.childId;\n if (!deletedId) return;\n\n const selectedDriveId = window.ph?.selectedDriveId;\n const selectedNodeId = window.ph?.selectedNodeId;\n\n if (selectedDriveId && deletedId === selectedDriveId) {\n setSelectedDrive(undefined);\n toast(\"The drive you were viewing has been deleted\");\n return;\n }\n\n if (selectedNodeId && deletedId === selectedNodeId) {\n setSelectedNode(undefined);\n toast(\"The document you were editing has been deleted\");\n }\n });\n\n await refreshReactorDataClient(reactorClientModule.client);\n\n const packagesWithProcessorFactories = packageManager.packages.filter(\n (pkg) => pkg.processorFactory !== undefined,\n );\n\n // processorManager lives in the worker on the cutover path and is not yet\n // bridged, so surface the gap loudly rather than dropping factories silently.\n const reactorModule =\n reactorClientModule.kind === \"browser\"\n ? reactorClientModule.reactorModule\n : undefined;\n if (packagesWithProcessorFactories.length > 0 && !reactorModule) {\n for (const pkg of packagesWithProcessorFactories) {\n logger.warn(\n \"Skipping processor factory @name: processors are not supported on the worker reactor path yet\",\n pkg.manifest.name,\n );\n }\n } else if (packagesWithProcessorFactories.length > 0 && reactorModule) {\n const readModels = reactorModule.readModelCoordinator.readModels;\n const processorHostModule = await createProcessorHostModule(\n reactorClientModule.client,\n readModels,\n window.ph?.attachmentService,\n );\n if (processorHostModule !== undefined) {\n await Promise.all(\n packagesWithProcessorFactories.map(async (pkg) => {\n const { manifest, processorFactory } = pkg;\n const name = manifest.name;\n const id = manifest.name;\n const version = packageManager.getPackageVersion(name);\n const label = version ? `${name}@${version}` : name;\n logger.info(\"Loading processor factory: @label\", label);\n try {\n const factory = await processorFactory?.(processorHostModule);\n if (!factory) return;\n await reactorModule.processorManager.registerFactory(id, factory);\n } catch (error) {\n logger.error(`Error registering processor: @label`, label);\n logger.error(\"@error\", error);\n }\n }),\n );\n }\n }\n\n window.ph.loading = false;\n}\n\nfunction getDidFromUrl() {\n const searchParams = new URLSearchParams(window.location.search);\n const didComponent = searchParams.get(\"user\");\n const did = didComponent ? decodeURIComponent(didComponent) : undefined;\n return did;\n}\n\nfunction getDriveUrl() {\n const searchParams = new URLSearchParams(window.location.search);\n const driveUrl = searchParams.get(\"driveUrl\");\n const url = driveUrl ? decodeURIComponent(driveUrl) : undefined;\n return url;\n}\n"],"names":["ReactorClientBuilder","ReactorBuilder","ChannelScheme","#packageManager","#findModuleInLoadedPackages","#clearFailed","#recordFailure","#failedMemo","#failedSubscribers","#eventSubscribers","#failed","#emitEvent","#notifyFailedChanged","#packageManager","#registryClient","#mode","#dismissedStorage","#findModuleInLoadedPackages","#clearFailed","#recordFailure","#deferred","#discover","#discoveredTypes","#pending","#addToPending","#findTypesByPackage","#emitEvent","#notifyPendingChanged","#pendingMemo","#pendingSubscribers","#failedMemo","#failedSubscribers","#eventSubscribers","#createDeferredEntry","#failed","#notifyFailedChanged","#storage","#cdnUrl","#localPackageNames","#registerPackage","#localPackage","#localPackageVersion","#notifyPackagesChanged","#packagesMemo","#packages","#loadPackage","#unmountStylesheet","#subscribers","#loadPackageFromNodeModules","#importPackage","#loadPackageFromRegistry","#mountStylesheet","#stylesheets","#schedulePwaSync","#pwaSyncTimer","#syncPwaFragments","#lastSyncedFragmentJson"],"mappings":"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","debug_id":"202f8980-8fd2-5e6a-8696-5f81a9dd2b3b"}