@powerhousedao/connect 6.2.3-dev.25 → 6.2.3-dev.27

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 (33) hide show
  1. package/dist/{ClearStorageModal-InfiThmU.js → ClearStorageModal-DAwvUeA6.js} +4 -4
  2. package/dist/{ClearStorageModal-InfiThmU.js.map → ClearStorageModal-DAwvUeA6.js.map} +1 -1
  3. package/dist/{DebugSettingsModal-DGB3wq4y.js → DebugSettingsModal-CDxYzRy2.js} +4 -4
  4. package/dist/{DebugSettingsModal-DGB3wq4y.js.map → DebugSettingsModal-CDxYzRy2.js.map} +1 -1
  5. package/dist/{InspectorModal-CITS4ldi.js → InspectorModal-BBqyJlRq.js} +4 -4
  6. package/dist/{InspectorModal-CITS4ldi.js.map → InspectorModal-BBqyJlRq.js.map} +1 -1
  7. package/dist/{MissingPackageModal-Dmu03EX7.js → MissingPackageModal-HFUPQMML.js} +4 -4
  8. package/dist/{MissingPackageModal-Dmu03EX7.js.map → MissingPackageModal-HFUPQMML.js.map} +1 -1
  9. package/dist/{OpenFileDocumentsModal-Cym38LC9.js → OpenFileDocumentsModal-B93ExZJD.js} +4 -4
  10. package/dist/{OpenFileDocumentsModal-Cym38LC9.js.map → OpenFileDocumentsModal-B93ExZJD.js.map} +1 -1
  11. package/dist/{SettingsModal-Bqch-LlY.js → SettingsModal-DlGbz4td.js} +6 -9
  12. package/dist/{SettingsModal-Bqch-LlY.js.map → SettingsModal-DlGbz4td.js.map} +1 -1
  13. package/dist/{app-loader-k3McuyRp.js → app-loader-BDajB2de.js} +10 -10
  14. package/dist/{app-loader-k3McuyRp.js.map → app-loader-BDajB2de.js.map} +1 -1
  15. package/dist/app-loader-CS97dVv5.js +4 -0
  16. package/dist/{build-info-BW_vU5c0.js → build-info-D6qP4e7A.js} +5 -5
  17. package/dist/{build-info-BW_vU5c0.js.map → build-info-D6qP4e7A.js.map} +1 -1
  18. package/dist/{components-i7X_YR6e.js → components-BLLMXR_3.js} +3 -3
  19. package/dist/{load-C1kCFFvW.js → load-B1fTvURV.js} +5 -5
  20. package/dist/{load-C1kCFFvW.js.map → load-B1fTvURV.js.map} +1 -1
  21. package/dist/main.js +1 -1
  22. package/dist/{package-manager-Bw4hKQ3s.js → package-manager-BbzIV9aN.js} +13 -3
  23. package/dist/package-manager-BbzIV9aN.js.map +1 -0
  24. package/dist/{reactor-B9xdtXLQ.js → reactor-CST3s76t.js} +5 -5
  25. package/dist/{reactor-B9xdtXLQ.js.map → reactor-CST3s76t.js.map} +1 -1
  26. package/dist/start-connect.js +1 -1
  27. package/dist/style.css +1 -1
  28. package/dist/{useRegistryPackages-BcKgNT71.js → useRegistryPackages-DuoU75ap.js} +4 -4
  29. package/dist/{useRegistryPackages-BcKgNT71.js.map → useRegistryPackages-DuoU75ap.js.map} +1 -1
  30. package/package.json +15 -18
  31. package/style.css +3 -5
  32. package/dist/app-loader-DDaPW-Ky.js +0 -4
  33. package/dist/package-manager-Bw4hKQ3s.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"useRegistryPackages-BcKgNT71.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 { toCdnUrl } from \"@powerhousedao/shared/registry/urls\";\nimport type { PackageDeps } from \"@powerhousedao/shared/connect\";\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\";\nimport { sharedDepMismatchWarnings } from \"../package-manager.js\";\nimport { getSharedDeps } from \"../shared-deps.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 // The host's shared-deps version table, from the production vendor\n // (null in dev / vendor-off builds — nothing to compare against, so the\n // rows simply have no warnings).\n const [hostVersions, setHostVersions] = useState<Record<\n string,\n string\n > | null>(null);\n useEffect(() => {\n let cancelled = false;\n void getSharedDeps().then((deps) => {\n if (!cancelled) setHostVersions(deps?.versions ?? null);\n });\n return () => {\n cancelled = true;\n };\n }, []);\n\n // Shared-dependency compatibility per row: fetch each package's npm\n // package.json once from the CDN (session-cached), compare its declared\n // shared-dep ranges against the host table, and stamp any mismatch\n // warnings onto the row. Sequential on purpose — a page first load is a\n // burst of row fetches, and this keeps it to one in flight at a time.\n // Best-effort: a fetch failure or absent CDN means no warning, same as a\n // vendor-less host.\n const sharedDepAttemptedRef = useRef(new Set<string>());\n useEffect(() => {\n if (!registryUrl || !hostVersions) return;\n const cdnUrl = toCdnUrl(trimTrailingSlash(registryUrl));\n const pending = registryPackageList.filter(\n (p) =>\n !sharedDepAttemptedRef.current.has(p.name) &&\n p.sharedDepWarnings === undefined,\n );\n if (pending.length === 0) return;\n let cancelled = false;\n let index = 0;\n const runNext = () => {\n if (cancelled) return;\n const row: RegistryPackage | undefined = pending[index++];\n if (!row) return;\n sharedDepAttemptedRef.current.add(row.name);\n void (async () => {\n try {\n const res = await fetch(\n `${cdnUrl}/${encodeURIComponent(row.name)}/package.json`,\n );\n if (!res.ok) return;\n const pkgJson = (await res.json()) as PackageDeps;\n const warnings = sharedDepMismatchWarnings(pkgJson, hostVersions);\n if (warnings.length === 0) return;\n setRegistryPackagesMap((old) => {\n const current = old[row.name];\n if (!current) return old;\n return {\n ...old,\n [row.name]: { ...current, sharedDepWarnings: warnings },\n };\n });\n } catch {\n // no warning\n } finally {\n runNext();\n }\n })();\n };\n runNext();\n return () => {\n cancelled = true;\n };\n }, [registryUrl, hostVersions, registryPackageList, setRegistryPackagesMap]);\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":"8de840d3-ce67-51a9-9049-4993aafeab70"}
1
+ {"version":3,"file":"useRegistryPackages-DuoU75ap.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 { toCdnUrl } from \"@powerhousedao/shared/registry/urls\";\nimport type { PackageDeps } from \"@powerhousedao/shared/connect\";\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\";\nimport { sharedDepMismatchWarnings } from \"../package-manager.js\";\nimport { getSharedDeps } from \"../shared-deps.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 // The host's shared-deps version table, from the production vendor\n // (null in dev / vendor-off builds — nothing to compare against, so the\n // rows simply have no warnings).\n const [hostVersions, setHostVersions] = useState<Record<\n string,\n string\n > | null>(null);\n useEffect(() => {\n let cancelled = false;\n void getSharedDeps().then((deps) => {\n if (!cancelled) setHostVersions(deps?.versions ?? null);\n });\n return () => {\n cancelled = true;\n };\n }, []);\n\n // Shared-dependency compatibility per row: fetch each package's npm\n // package.json once from the CDN (session-cached), compare its declared\n // shared-dep ranges against the host table, and stamp any mismatch\n // warnings onto the row. Sequential on purpose — a page first load is a\n // burst of row fetches, and this keeps it to one in flight at a time.\n // Best-effort: a fetch failure or absent CDN means no warning, same as a\n // vendor-less host.\n const sharedDepAttemptedRef = useRef(new Set<string>());\n useEffect(() => {\n if (!registryUrl || !hostVersions) return;\n const cdnUrl = toCdnUrl(trimTrailingSlash(registryUrl));\n const pending = registryPackageList.filter(\n (p) =>\n !sharedDepAttemptedRef.current.has(p.name) &&\n p.sharedDepWarnings === undefined,\n );\n if (pending.length === 0) return;\n let cancelled = false;\n let index = 0;\n const runNext = () => {\n if (cancelled) return;\n const row: RegistryPackage | undefined = pending[index++];\n if (!row) return;\n sharedDepAttemptedRef.current.add(row.name);\n void (async () => {\n try {\n const res = await fetch(\n `${cdnUrl}/${encodeURIComponent(row.name)}/package.json`,\n );\n if (!res.ok) return;\n const pkgJson = (await res.json()) as PackageDeps;\n const warnings = sharedDepMismatchWarnings(pkgJson, hostVersions);\n if (warnings.length === 0) return;\n setRegistryPackagesMap((old) => {\n const current = old[row.name];\n if (!current) return old;\n return {\n ...old,\n [row.name]: { ...current, sharedDepWarnings: warnings },\n };\n });\n } catch {\n // no warning\n } finally {\n runNext();\n }\n })();\n };\n runNext();\n return () => {\n cancelled = true;\n };\n }, [registryUrl, hostVersions, registryPackageList, setRegistryPackagesMap]);\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":"16added8-50b3-5057-abe6-f39738bd0198"}
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.25",
4
+ "version": "6.2.3-dev.27",
5
5
  "description": "Powerhouse Connect",
6
6
  "main": "dist/index.html",
7
7
  "type": "module",
@@ -56,23 +56,23 @@
56
56
  "@openfeature/core": "1.9.1",
57
57
  "@openfeature/web-sdk": "1.6.2",
58
58
  "@openpanel/web": "^1.4.1",
59
- "@powerhousedao/config": "6.2.3-dev.25",
60
- "@powerhousedao/design-system": "6.2.3-dev.25",
59
+ "@powerhousedao/config": "6.2.3-dev.27",
60
+ "@powerhousedao/design-system": "6.2.3-dev.27",
61
61
  "@powerhousedao/document-engineering": "1.40.5",
62
- "@powerhousedao/powerhouse-vetra-packages": "6.2.3-dev.25",
63
- "@powerhousedao/reactor": "6.2.3-dev.25",
64
- "@powerhousedao/reactor-attachments": "6.2.3-dev.25",
65
- "@powerhousedao/reactor-browser": "6.2.3-dev.25",
66
- "@powerhousedao/reactor-mcp": "6.2.3-dev.25",
67
- "@powerhousedao/shared": "6.2.3-dev.25",
68
- "@powerhousedao/vetra": "6.2.3-dev.25",
69
- "@powerhousedao/workflow": "6.2.3-dev.25",
62
+ "@powerhousedao/powerhouse-vetra-packages": "6.2.3-dev.27",
63
+ "@powerhousedao/reactor": "6.2.3-dev.27",
64
+ "@powerhousedao/reactor-attachments": "6.2.3-dev.27",
65
+ "@powerhousedao/reactor-browser": "6.2.3-dev.27",
66
+ "@powerhousedao/reactor-mcp": "6.2.3-dev.27",
67
+ "@powerhousedao/shared": "6.2.3-dev.27",
68
+ "@powerhousedao/vetra": "6.2.3-dev.27",
69
+ "@powerhousedao/workflow": "6.2.3-dev.27",
70
70
  "@privy-io/react-auth": "3.35.0",
71
71
  "@rainbow-me/rainbowkit": "^2.2.11",
72
- "@renown/sdk": "6.2.3-dev.25",
72
+ "@renown/sdk": "6.2.3-dev.27",
73
73
  "@sentry/react": "^10.17.0",
74
74
  "@tanstack/react-query": "^5.90.2",
75
- "document-model": "6.2.3-dev.25",
75
+ "document-model": "6.2.3-dev.27",
76
76
  "i18next": "^25.5.3",
77
77
  "kysely": "0.28.16",
78
78
  "kysely-pglite-dialect": "1.2.0",
@@ -99,16 +99,14 @@
99
99
  "@types/react": "19.2.14",
100
100
  "@types/react-dom": "19.2.3",
101
101
  "@types/wicg-file-system-access": "^2023.10.7",
102
- "@vitejs/plugin-react": "6.0.1",
103
- "cypress": "^14.5.4",
102
+ "@vitejs/plugin-react": "6.1.1",
104
103
  "happy-dom": "^20.8.9",
105
104
  "react": "19.2.6",
106
105
  "react-dom": "19.2.6",
107
106
  "tailwindcss": "4.2.2",
108
107
  "tsdown": "0.23.0",
109
108
  "typescript": "7.0.2",
110
- "vite": "8.0.10",
111
- "vite-bundle-analyzer": "^1.3.6",
109
+ "vite": "8.3.0",
112
110
  "vite-tsconfig-paths": "6.1.1"
113
111
  },
114
112
  "peerDependencies": {
@@ -125,7 +123,6 @@
125
123
  "build:css": "pnpm exec tailwindcss -i style.css -o dist/style.css",
126
124
  "build:debug": "cross-env PH_DEBUG_BUILD=true vite build",
127
125
  "preview": "vite preview",
128
- "cy:open": "cypress open",
129
126
  "docker:build": "docker build -f ./Dockerfile --tag connect-test-dev --build-arg TAG=dev .",
130
127
  "docker:run": "docker run -it -p 4000:4000 -v $(realpath ../../../monorepo):/monorepo -v $(pwd)/nginx.conf:/etc/nginx/nginx.conf.template -e PH_CONNECT_BASE_PATH=/develop/powerhouse/connect -e PORT=4000 connect-test-dev"
131
128
  }
package/style.css CHANGED
@@ -1,8 +1,6 @@
1
- /* Declare the external-packages layer first so it has the lowest priority in the
2
- cascade. Any CSS injected by dynamically loaded packages (via the package
3
- manager) is placed into this layer, preventing it from overriding connect,
4
- design-system, vetra, or powerhouse-vetra-packages styles. */
5
- @layer external-packages;
1
+ /* Package CSS goes in external-packages: above the reset, below Connect's
2
+ utilities. Keep in sync with LAYER_ORDER in src/package-manager.ts. */
3
+ @layer theme, base, components, external-packages, utilities;
6
4
  /* Pull in the design-system's Tailwind theme extension (theme block with all
7
5
  color, font, and spacing tokens) so they are available before Tailwind
8
6
  generates utility classes below. Also defines the dark-mode custom variant. */
@@ -1,4 +0,0 @@
1
- import { t as AppLoader } from "./app-loader-k3McuyRp.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]="1a9e6d09-d75e-5c28-9fb2-e240a461d489")}catch(e){}}();
4
- //# debugId=1a9e6d09-d75e-5c28-9fb2-e240a461d489
@@ -1 +0,0 @@
1
- {"version":3,"file":"package-manager-Bw4hKQ3s.js","sources":["../src/shared-deps.ts","../src/utils/pwa-idb.ts","../src/package-manager.ts"],"sourcesContent":["import { DYNAMIC_BASE_PLACEHOLDER } from \"@powerhousedao/shared/connect\";\n\nexport type SharedDeps = {\n imports: Record<string, string>;\n versions: Record<string, string>;\n};\n\n/**\n * Resolve the vendor's import-map values to absolute URLs: the\n * dynamic-base placeholder (present in dynamic-base builds) is replaced\n * with the runtime base — which `import.meta.env.BASE_URL` already is,\n * since the dynamic-base plugin rewrites it to the resolved base — and\n * the result is made absolute against the page origin. Absolute URLs are\n * what the worker needs: its imports have no document context, so\n * relative or placeholder-based values would not resolve there.\n */\nexport function normalizeVendorImports(\n rawImports: Record<string, string>,\n runtimeBase: string,\n): Record<string, string> {\n // `location` is a browser global; the fallback keeps the helper usable\n // from node-based tests, where no origin exists.\n const origin =\n (globalThis as { location?: Location }).location?.origin ??\n \"http://localhost\";\n return Object.fromEntries(\n Object.entries(rawImports).map(([spec, value]) => [\n spec,\n new URL(value.replace(DYNAMIC_BASE_PLACEHOLDER, runtimeBase), origin)\n .href,\n ]),\n );\n}\n\nlet cached: Promise<SharedDeps | null> | null = null;\n\n/**\n * The production vendor's shared-deps table: import-map entries for the\n * shared dependency set plus the resolved version of every shared package\n * in this build. Fails soft (`null`) when the vendor is not present (dev,\n * or a `PH_CONNECT_VENDOR=0` build) — callers treat that as \"no sharing\".\n * The promise is cached: the vendor table is immutable per build.\n */\nexport function getSharedDeps(): Promise<SharedDeps | null> {\n cached ??= (async () => {\n try {\n const mod = (await import(\n /* @vite-ignore */ `${import.meta.env.BASE_URL}__vendor__/shared-deps.js`\n )) as {\n imports: Record<string, string>;\n versions: Record<string, string>;\n };\n return {\n imports: normalizeVendorImports(mod.imports, import.meta.env.BASE_URL),\n versions: mod.versions,\n };\n } catch {\n return null;\n }\n })();\n return cached;\n}\n","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 * 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 checkSharedDeps,\n formatSharedDepWarnings,\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 { getSharedDeps } from \"./shared-deps.js\";\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\" };\nimport workflowPkg from \"@powerhousedao/workflow/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\ntype FetchedPackageJson = {\n version?: string;\n dependencies?: Record<string, unknown>;\n peerDependencies?: Record<string, unknown>;\n};\n\nasync function fetchPackageJson(\n baseUrl: string,\n): Promise<FetchedPackageJson | null> {\n try {\n const res = await fetch(baseUrl);\n if (!res.ok) return null;\n const pkg = (await res.json()) as {\n version?: unknown;\n dependencies?: Record<string, unknown>;\n peerDependencies?: Record<string, unknown>;\n };\n return {\n version: typeof pkg.version === \"string\" ? pkg.version : undefined,\n dependencies: pkg.dependencies,\n peerDependencies: pkg.peerDependencies,\n };\n } catch {\n return null;\n }\n}\n\nasync function fetchPackageJsonVersion(\n baseUrl: string,\n): Promise<string | undefined> {\n return (await fetchPackageJson(baseUrl))?.version;\n}\n\n/**\n * Human-readable warnings for shared-dep mismatches between a package's npm\n * `package.json` (as served by the CDN) and the host's shared-deps version\n * table. Empty when either side is unavailable — a dev / vendor-off host has\n * no table to compare against, and a missing package.json means the check\n * can't run. Used by both the install flow and the package-manager UI.\n */\nexport function sharedDepMismatchWarnings(\n pkgJson: FetchedPackageJson | null,\n hostVersions: Record<string, string> | null | undefined,\n): string[] {\n if (!pkgJson || !hostVersions) return [];\n return formatSharedDepWarnings(checkSharedDeps(pkgJson, hostVersions));\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 workflowsEnabled?: 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 // Same shape for the workflow package, behind its own independent flag.\n // Only the package root: `./pieces` and `./reactor` are node-only.\n if (workflowsEnabled) {\n const workflow = await import(\"@powerhousedao/workflow\");\n this.addLocalPackage(\n workflow.manifest.name,\n workflow,\n workflowPkg.version,\n );\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 /**\n * The spec the user requested when this package was installed (e.g.\n * `name@dev` or `name@6.2.1`). Undefined for bare-name installs, legacy\n * entries, and local packages — the Package Manager treats that as the\n * `latest` stream when picking update targets.\n */\n getPackageSpec(packageName: string): string | undefined {\n return this.#storage.get(packageName)?.spec;\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 const pkgJson = await fetchPackageJson(\n `${this.#cdnUrl}/${name}/package.json`,\n );\n packageWithMeta.version = pkgJson?.version;\n\n // Non-blocking warning: a package that pins a shared dep at a version\n // the host's vendor was built without still installs, but the host's\n // copy is what runs — surface the mismatch before it surprises the\n // user at runtime.\n const warnings = sharedDepMismatchWarnings(\n pkgJson,\n (await getSharedDeps())?.versions,\n );\n if (warnings.length > 0) {\n console.error(\n `[package-manager] shared-deps mismatch for ${name}:\\n` +\n warnings.join(\"\\n\"),\n );\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"],"names":[],"mappings":"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","debug_id":"94b066d2-0761-52cc-83b9-6bc6a9bea57d"}