@powerhousedao/connect 6.2.2-dev.1 → 6.2.2-dev.11

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 (79) hide show
  1. package/assets/document-icon-192x192.png +0 -0
  2. package/assets/document-icon-512x512.png +0 -0
  3. package/assets/pwa-192x192.png +0 -0
  4. package/assets/pwa-512x512-maskable.png +0 -0
  5. package/assets/pwa-512x512.png +0 -0
  6. package/dist/{AddDriveModal-MMHlkJBJ.js → AddDriveModal-B_Oft9Cv.js} +4 -4
  7. package/dist/{AddDriveModal-MMHlkJBJ.js.map → AddDriveModal-B_Oft9Cv.js.map} +1 -1
  8. package/dist/{ClearStorageModal-BigtCV_M.js → ClearStorageModal-DKxn1Qxa.js} +4 -4
  9. package/dist/{ClearStorageModal-BigtCV_M.js.map → ClearStorageModal-DKxn1Qxa.js.map} +1 -1
  10. package/dist/{CookiesPolicyModal-CkcUKPLb.js → CookiesPolicyModal-CYFTfkEN.js} +3 -3
  11. package/dist/{CookiesPolicyModal-CkcUKPLb.js.map → CookiesPolicyModal-CYFTfkEN.js.map} +1 -1
  12. package/dist/{CreateDocumentModal-CvsTh0HM.js → CreateDocumentModal-Dmg3R-Vh.js} +3 -3
  13. package/dist/{CreateDocumentModal-CvsTh0HM.js.map → CreateDocumentModal-Dmg3R-Vh.js.map} +1 -1
  14. package/dist/{DebugSettingsModal-Bti38_qt.js → DebugSettingsModal-DUNPkZoc.js} +5 -5
  15. package/dist/{DebugSettingsModal-Bti38_qt.js.map → DebugSettingsModal-DUNPkZoc.js.map} +1 -1
  16. package/dist/{DeleteDriveModal-DSTK8FYk.js → DeleteDriveModal-CzRPqyMf.js} +4 -4
  17. package/dist/{DeleteDriveModal-DSTK8FYk.js.map → DeleteDriveModal-CzRPqyMf.js.map} +1 -1
  18. package/dist/{DeleteItemModal-B2nJmjsP.js → DeleteItemModal-CaCrmQOG.js} +4 -4
  19. package/dist/{DeleteItemModal-B2nJmjsP.js.map → DeleteItemModal-CaCrmQOG.js.map} +1 -1
  20. package/dist/{DisclaimerModal-D5FO34u9.js → DisclaimerModal-D5Jhefcc.js} +3 -3
  21. package/dist/{DisclaimerModal-D5FO34u9.js.map → DisclaimerModal-D5Jhefcc.js.map} +1 -1
  22. package/dist/{DownloadDocumentWithErrorsModal-tEr3bbtN.js → DownloadDocumentWithErrorsModal-ZuX8WDCC.js} +3 -3
  23. package/dist/{DownloadDocumentWithErrorsModal-tEr3bbtN.js.map → DownloadDocumentWithErrorsModal-ZuX8WDCC.js.map} +1 -1
  24. package/dist/{DriveAuthRequiredModal-BA2vS3oF.js → DriveAuthRequiredModal-CPV5uXnf.js} +3 -3
  25. package/dist/{DriveAuthRequiredModal-BA2vS3oF.js.map → DriveAuthRequiredModal-CPV5uXnf.js.map} +1 -1
  26. package/dist/{DriveSettingsModal-kR3hQnh4.js → DriveSettingsModal-VNpuhty1.js} +3 -3
  27. package/dist/{DriveSettingsModal-kR3hQnh4.js.map → DriveSettingsModal-VNpuhty1.js.map} +1 -1
  28. package/dist/{InspectorModal-B2Zbsa4l.js → InspectorModal-B7wmgMfE.js} +6 -6
  29. package/dist/{InspectorModal-B2Zbsa4l.js.map → InspectorModal-B7wmgMfE.js.map} +1 -1
  30. package/dist/{MissingPackageModal-BQcCQbOn.js → MissingPackageModal-D4V6oYzy.js} +18 -6
  31. package/dist/MissingPackageModal-D4V6oYzy.js.map +1 -0
  32. package/dist/OpenFileDocumentsModal-DCrZnA6c.js +293 -0
  33. package/dist/OpenFileDocumentsModal-DCrZnA6c.js.map +1 -0
  34. package/dist/{SettingsModal-BnHg4yeC.js → SettingsModal-BsYFJB2W.js} +25 -12
  35. package/dist/SettingsModal-BsYFJB2W.js.map +1 -0
  36. package/dist/{UpgradeDriveModal-BZGSE9_r.js → UpgradeDriveModal-Ul4tyz-Q.js} +3 -3
  37. package/dist/{UpgradeDriveModal-BZGSE9_r.js.map → UpgradeDriveModal-Ul4tyz-Q.js.map} +1 -1
  38. package/dist/{app-loader-CuYQDicM.js → app-loader-DG_ohYMb.js} +251 -34
  39. package/dist/app-loader-DG_ohYMb.js.map +1 -0
  40. package/dist/app-loader-aQ0Wk8uH.js +4 -0
  41. package/dist/{build-info-D0TYDOtW.js → build-info-Do0SMo9O.js} +5 -5
  42. package/dist/{build-info-D0TYDOtW.js.map → build-info-Do0SMo9O.js.map} +1 -1
  43. package/dist/components-BDpsXnOO.js +5 -0
  44. package/dist/{connection-state-DO_2lAEJ.js → connection-state-xPSbZ_4J.js} +3 -3
  45. package/dist/{connection-state-DO_2lAEJ.js.map → connection-state-xPSbZ_4J.js.map} +1 -1
  46. package/dist/{load-DajsG0zi.js → load-y7fD2Bfj.js} +9 -9
  47. package/dist/{load-DajsG0zi.js.map → load-y7fD2Bfj.js.map} +1 -1
  48. package/dist/main.js +1 -1
  49. package/dist/{package-CX2sgCBs.js → package-Bc_Nktb7.js} +4 -4
  50. package/dist/package-Bc_Nktb7.js.map +1 -0
  51. package/dist/{pglite-seed-z3B1JA38.js → pglite-seed-DRYYEWUq.js} +4 -4
  52. package/dist/{pglite-seed-z3B1JA38.js.map → pglite-seed-DRYYEWUq.js.map} +1 -1
  53. package/dist/pwa-manifest-link-CG8UajMz.js +34 -0
  54. package/dist/pwa-manifest-link-CG8UajMz.js.map +1 -0
  55. package/dist/{reactor-Bo6Lut7c.js → reactor-BzjtiHGa.js} +139 -12
  56. package/dist/reactor-BzjtiHGa.js.map +1 -0
  57. package/dist/reactor.worker.js +9 -5
  58. package/dist/reactor.worker.js.map +1 -1
  59. package/dist/{registerServiceWorker-nJIc0yEY.js → registerServiceWorker-uI4Gj6fl.js} +5 -3
  60. package/dist/registerServiceWorker-uI4Gj6fl.js.map +1 -0
  61. package/dist/{reload-connect-toast-D1Iqw9E_.js → reload-connect-toast-BkgP9i6_.js} +19 -3
  62. package/dist/{reload-connect-toast-D1Iqw9E_.js.map → reload-connect-toast-BkgP9i6_.js.map} +1 -1
  63. package/dist/start-connect.js +1 -1
  64. package/dist/style.css +16 -3
  65. package/dist/{toast-4t-VimvD.js → toast-BLv8rjmy.js} +3 -3
  66. package/dist/{toast-4t-VimvD.js.map → toast-BLv8rjmy.js.map} +1 -1
  67. package/dist/useRegistryPackages-DMhCvTWq.js +314 -0
  68. package/dist/useRegistryPackages-DMhCvTWq.js.map +1 -0
  69. package/package.json +11 -11
  70. package/dist/MissingPackageModal-BQcCQbOn.js.map +0 -1
  71. package/dist/SettingsModal-BnHg4yeC.js.map +0 -1
  72. package/dist/app-loader-B_HyriND.js +0 -4
  73. package/dist/app-loader-CuYQDicM.js.map +0 -1
  74. package/dist/components-xBFneZuJ.js +0 -5
  75. package/dist/package-CX2sgCBs.js.map +0 -1
  76. package/dist/reactor-Bo6Lut7c.js.map +0 -1
  77. package/dist/registerServiceWorker-nJIc0yEY.js.map +0 -1
  78. package/dist/useRegistryPackages-BaYtekjQ.js +0 -179
  79. package/dist/useRegistryPackages-BaYtekjQ.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"reactor.worker.js","sources":["../src/reactor.worker.ts"],"sourcesContent":["import {\n ChannelScheme,\n DocumentIntegrityService,\n DriveCollectionId,\n InMemoryQueue,\n ReactorBuilder,\n ReactorClientBuilder,\n type ChannelConfig,\n type Database,\n type ISyncManager,\n type JwtHandler,\n type Remote,\n type RemoteFilter,\n type RemoteOptions,\n} from \"@powerhousedao/reactor\";\nimport { baseDocumentModels } from \"@powerhousedao/reactor-browser/base-document-models\";\nimport {\n FORWARDED_EVENT_TYPES,\n ReactorHost,\n SYNC_STATUS_CHANGED_EVENT,\n WorkerPackageLoader,\n type ReactorIdentity,\n type WorkerMigrationState,\n} from \"@powerhousedao/reactor-browser/rpc\";\nimport type { DocumentModelModule } from \"@powerhousedao/shared/document-model\";\nimport {\n createRelationalDb,\n type IProcessorManager,\n type IRelationalDb,\n} from \"@powerhousedao/shared/processors\";\nimport * as commonDocumentModels from \"@powerhousedao/powerhouse-vetra-packages/document-models\";\nimport {\n BrowserKeyStorage,\n createSignatureVerifier,\n RenownCryptoBuilder,\n RenownCryptoSigner,\n} from \"@renown/sdk/crypto\";\nimport type * as PgLiveModuleNs from \"@electric-sql/pglite/live\";\nimport { Kysely } from \"kysely\";\nimport { PGliteDialect } from \"kysely-pglite-dialect\";\nimport { readPgVersionFile } from \"./utils/pglite-idb.js\";\nimport {\n coerceMajor,\n CURRENT_PG_MAJOR,\n type DetectedMajor,\n loadPGliteModule,\n resolvePgMajorForRuntime,\n type SupportedPgMajor,\n} from \"./utils/pglite-major.js\";\nimport {\n type BackupStrategy,\n type FileDataEntry,\n clearFileData,\n migrateIdb,\n readFileData,\n writeFileData,\n} from \"./utils/pglite-migrate-core.js\";\n\nconsole.info(\"[reactor.worker] module evaluating\");\n\n// Matches the main thread's RenownBuilder(\"connect\").\nconst RENOWN_APP_NAME = \"connect\";\n\n// Common models the tab bundles as a local package; not CDN-loadable, so the\n// worker imports them directly. Vetra is builder-only and lazy-loaded below.\nfunction toDocumentModelModules(candidates: unknown[]): DocumentModelModule[] {\n return candidates.filter(\n (m): m is DocumentModelModule =>\n typeof m === \"object\" &&\n m !== null &&\n \"documentModel\" in m &&\n \"reducer\" in m,\n );\n}\n\nconst commonBundledModels = toDocumentModelModules(\n Object.values(commonDocumentModels),\n);\n\n// Not CDN-loadable, so it can't ride the packageSpecs path; lazy-import the\n// bundled chunk only in studio mode.\nasync function loadVetraDocumentModels(): Promise<DocumentModelModule[]> {\n const vetraDocumentModels =\n await import(\"@powerhousedao/vetra/document-models\");\n return toDocumentModelModules(Object.values(vetraDocumentModels));\n}\n\ntype WorkerConstruct = {\n namespace: string;\n relationalNamespace: string;\n cdnUrl: string;\n packageSpecs: string[];\n studioMode?: boolean;\n};\n\ntype ModelRegistry = {\n registerModules: (...modules: DocumentModelModule[]) => void;\n};\n\nlet loader: WorkerPackageLoader | undefined;\nlet registry: ModelRegistry | undefined;\nlet signer: RenownCryptoSigner | undefined;\nlet syncManager: ISyncManager | undefined;\ntype RelationalState = {\n pg?: PgLiveModuleNs.PGliteWithLive;\n db?: IRelationalDb;\n};\nconst relational: RelationalState = {};\ntype OwnedStorage = {\n reactorPg?: {\n close: () => Promise<void>;\n query: (sql: string, params?: unknown[]) => Promise<{ rows: unknown[] }>;\n };\n reactorIdb?: string;\n relationalIdb?: string;\n};\nconst owned: OwnedStorage = {};\nlet inspectorQueue: InMemoryQueue | undefined;\nlet inspectorProcessors: IProcessorManager | undefined;\nlet inspectorIntegrity: DocumentIntegrityService | undefined;\nlet currentIdentity: ReactorIdentity | null = null;\nconst registeredKeys = new Set<string>();\n\nfunction modelKey(module: DocumentModelModule): string {\n return `${module.documentModel.global.id}@${module.version ?? 1}`;\n}\n\n// Cloneable projection of a Remote: meta (carries channelConfig) + connection snapshot.\nfunction toWireRemote(remote: Remote) {\n return {\n meta: remote.meta,\n connectionState: remote.channel.getConnectionState(),\n };\n}\n\n// Register only the delta; the registry rejects duplicate (type, version) pairs.\nfunction registerNewModules(): void {\n if (!loader || !registry) {\n return;\n }\n const fresh = loader.models.filter((m) => !registeredKeys.has(modelKey(m)));\n if (fresh.length === 0) {\n return;\n }\n registry.registerModules(...fresh);\n for (const m of fresh) {\n registeredKeys.add(modelKey(m));\n }\n}\n\n// Rebuild renown crypto from the shared renownKeyDB keypair (origin-scoped IndexedDB).\nasync function buildWorkerCrypto() {\n const keyStorage = await BrowserKeyStorage.create();\n return new RenownCryptoBuilder().withKeyPairStorage(keyStorage).build();\n}\n\n// Open against the major already on disk so a legacy PG16 dir isn't read by PG17.\nasync function openReactorPglite(namespace: string) {\n const detected = coerceMajor(await readPgVersionFile(`/pglite/${namespace}`));\n const major = resolvePgMajorForRuntime(detected);\n if (major !== 17) {\n console.warn(\n `[reactor.worker] Running against legacy PGlite data dir (Postgres ${major}). Migrate to PG17 from the Connect banner or the Inspector.`,\n );\n }\n const { PGlite } = await loadPGliteModule(major);\n const pg = new PGlite(`idb://${namespace}`, { relaxedDurability: true });\n return { pg, detected };\n}\n\ntype PgLiveModule = typeof PgLiveModuleNs;\n\nasync function loadPgLive(major: SupportedPgMajor): Promise<PgLiveModule> {\n if (major === 16) {\n return import(\"pglite-legacy-02/live\") as unknown as Promise<PgLiveModule>;\n }\n return import(\"@electric-sql/pglite/live\");\n}\n\nasync function openRelational(namespace: string): Promise<DetectedMajor> {\n try {\n const detected = coerceMajor(\n await readPgVersionFile(`/pglite/${namespace}`),\n );\n const major = resolvePgMajorForRuntime(detected);\n if (major !== 17) {\n console.warn(\n `[reactor.worker] Relational store opening legacy PGlite data dir (Postgres ${major}). Migrate to PG17 from the Connect banner or the Inspector.`,\n );\n }\n const [{ PGlite }, { live }] = await Promise.all([\n loadPGliteModule(major),\n loadPgLive(major),\n ]);\n const pg = new PGlite(`idb://${namespace}`, {\n relaxedDurability: true,\n extensions: { live },\n });\n relational.pg = pg as unknown as PgLiveModuleNs.PGliteWithLive;\n relational.db = createRelationalDb(\n new Kysely({ dialect: new PGliteDialect(pg) }),\n );\n console.info(\n `[reactor.worker] Relational store opened: idb://${namespace} (Postgres ${major}).`,\n );\n return detected;\n } catch (error) {\n console.error(\n \"[reactor.worker] Failed to open the relational store:\",\n error,\n );\n return null;\n }\n}\n\nlet migrationState: WorkerMigrationState = { status: \"idle\" };\n\nfunction setMigration(state: WorkerMigrationState): void {\n migrationState = state;\n host.setMigrationState(state);\n}\n\nconst inMemoryBackup: BackupStrategy = {\n snapshot: (idbName) => readFileData(idbName),\n rollback: (handle, idbName) =>\n writeFileData(idbName, handle as FileDataEntry[]),\n discard: () => Promise.resolve(),\n commit: () => Promise.resolve(),\n};\n\nconst workerName = (self as { name?: string }).name ?? \"\";\n\nconst host = new ReactorHost({\n namespace: workerName,\n onAdminRestart: () =>\n host.broadcastReload(\"admin restart\", crypto.randomUUID()),\n onAdminClearStorage: async () => {\n await relational.pg?.close();\n await owned.reactorPg?.close();\n for (const idbName of [owned.reactorIdb, owned.relationalIdb]) {\n if (idbName) {\n await clearFileData(idbName);\n }\n }\n host.broadcastReload(\"storage cleared\", crypto.randomUUID());\n },\n onAdminMigrate: async () => {\n setMigration({\n status: \"migrating\",\n legacyMajor: migrationState.legacyMajor,\n });\n if (relational.pg) await relational.pg.close().catch(() => undefined);\n if (owned.reactorPg) await owned.reactorPg.close().catch(() => undefined);\n try {\n for (const idbName of [owned.reactorIdb, owned.relationalIdb]) {\n if (idbName) {\n await migrateIdb(\n idbName,\n (phase) =>\n setMigration({\n status: \"migrating\",\n legacyMajor: migrationState.legacyMajor,\n phase,\n }),\n inMemoryBackup,\n );\n }\n }\n host.broadcastReload(\"migration complete\", crypto.randomUUID());\n } catch (error) {\n console.error(\"[reactor.worker] Migration failed:\", error);\n setMigration({\n status: \"failed\",\n error: error instanceof Error ? error.message : String(error),\n });\n host.broadcastReload(\"migration failed\", crypto.randomUUID());\n }\n },\n build: async (raw) => {\n let phase = \"init\";\n try {\n const construct = raw as WorkerConstruct;\n phase = \"loading packages\";\n console.info(`[reactor.worker] boot: ${phase}`);\n loader = new WorkerPackageLoader({\n cdnUrl: construct.cdnUrl,\n importPackage: (url) =>\n import(/* @vite-ignore */ url) as Promise<Record<string, unknown>>,\n });\n const loaded = await loader.loadPackages(construct.packageSpecs);\n const vetraModels = construct.studioMode\n ? await loadVetraDocumentModels()\n : [];\n const models = baseDocumentModels.concat(\n commonBundledModels,\n vetraModels,\n loaded,\n );\n phase = \"opening pglite stores\";\n console.info(`[reactor.worker] boot: ${phase}`);\n const [reactor, relationalMajor] = await Promise.all([\n openReactorPglite(construct.namespace),\n openRelational(construct.relationalNamespace),\n ]);\n const pg = reactor.pg;\n owned.reactorPg = pg;\n owned.reactorIdb = `/pglite/${construct.namespace}`;\n owned.relationalIdb = `/pglite/${construct.relationalNamespace}`;\n // A store is migratable when coerceMajor kept it (a supported legacy\n // major) and it is not the current one; openers already read PG_VERSION.\n const legacyMajor = [reactor.detected, relationalMajor].find(\n (m): m is SupportedPgMajor => m !== null && m !== CURRENT_PG_MAJOR,\n );\n if (legacyMajor !== undefined) {\n setMigration({ status: \"needed\", legacyMajor });\n }\n phase = \"building crypto\";\n console.info(`[reactor.worker] boot: ${phase}`);\n const crypto = await buildWorkerCrypto();\n signer = new RenownCryptoSigner(\n crypto,\n RENOWN_APP_NAME,\n currentIdentity ?? undefined,\n );\n const jwtHandler: JwtHandler = async () =>\n currentIdentity\n ? crypto.getBearerToken(currentIdentity.address, { expiresIn: 10 })\n : undefined;\n phase = \"building reactor module\";\n console.info(`[reactor.worker] boot: ${phase}`);\n const builder = new ReactorClientBuilder()\n .withSigner({ signer, verifier: createSignatureVerifier() })\n .withReactorBuilder(\n new ReactorBuilder()\n .withDocumentModels(models)\n .withChannelScheme(ChannelScheme.CONNECT)\n .withJwtHandler(jwtHandler)\n .withKysely(\n new Kysely<Database>({ dialect: new PGliteDialect(pg) }),\n ),\n );\n builder.withDocumentModelLoader(loader);\n const module = await builder.buildModule();\n registry = module.reactorModule?.documentModelRegistry;\n syncManager = module.reactorModule?.syncModule?.syncManager;\n const rm = module.reactorModule;\n if (rm) {\n inspectorQueue =\n rm.queue instanceof InMemoryQueue ? rm.queue : undefined;\n inspectorProcessors = rm.processorManager;\n inspectorIntegrity = new DocumentIntegrityService(\n rm.keyframeStore,\n rm.operationStore,\n rm.writeCache,\n rm.documentView,\n rm.documentModelRegistry,\n );\n }\n for (const m of models) {\n registeredKeys.add(modelKey(m));\n }\n for (const type of FORWARDED_EVENT_TYPES) {\n module.eventBus.subscribe(type, (forwardedType, event) =>\n host.broadcastBusEvent(forwardedType, event),\n );\n }\n syncManager?.onSyncStatusChange((documentId, status) =>\n host.broadcastBusEvent(SYNC_STATUS_CHANGED_EVENT, {\n documentId,\n status,\n }),\n );\n console.info(\"[reactor.worker] boot: complete\");\n return module.client;\n } catch (error) {\n console.error(`[reactor.worker] boot failed at phase \"${phase}\":`, error);\n throw error;\n }\n },\n registerPackages: async (specs) => {\n if (!loader) {\n return;\n }\n await loader.loadPackages(specs);\n registerNewModules();\n },\n onIdentity: (user) => {\n currentIdentity = user;\n if (signer) {\n signer.user = user ?? undefined;\n }\n },\n onSyncOp: async (method, args) => {\n if (!syncManager) {\n throw new Error(\"SyncManager not available\");\n }\n switch (method) {\n case \"list\":\n return syncManager.list().map(toWireRemote);\n case \"add\": {\n const [name, collectionIdKey, channelConfig, filter, options] =\n args as [\n string,\n string,\n ChannelConfig,\n RemoteFilter | undefined,\n RemoteOptions | undefined,\n ];\n const remote = await syncManager.add(\n name,\n DriveCollectionId.fromKey(collectionIdKey),\n channelConfig,\n filter,\n options,\n );\n return toWireRemote(remote);\n }\n case \"remove\":\n await syncManager.remove(args[0] as string);\n return undefined;\n case \"triggerPull\":\n syncManager.triggerPull(args[0] as string);\n return undefined;\n default:\n throw new Error(`Unknown sync op: ${method}`);\n }\n },\n onDbOp: async (method, args) => {\n if (!relational.pg) {\n throw new Error(\"Relational store not available\");\n }\n switch (method) {\n case \"query\": {\n const [sql, params] = args as [string, unknown[]];\n const result = await relational.pg.query(sql, params);\n return result.rows;\n }\n default:\n throw new Error(`Unknown db op: ${method}`);\n }\n },\n onLiveQuery: async (sql, params, onResults) => {\n if (!relational.pg) {\n throw new Error(\"Relational store not available\");\n }\n const live = await relational.pg.live.query(sql, params, (results) =>\n onResults(results),\n );\n return () => {\n void live.unsubscribe();\n };\n },\n onInspectorOp: async (method, args) => {\n switch (method) {\n case \"queue.getState\": {\n if (!inspectorQueue) {\n return {\n isPaused: false,\n pendingJobs: [],\n executingJobs: [],\n totalPending: 0,\n totalExecuting: 0,\n };\n }\n const pendingJobs = inspectorQueue.getPendingJobs();\n const executingJobs = [];\n for (const jobIds of inspectorQueue.getExecutingJobIds().values()) {\n for (const jobId of jobIds) {\n const job = inspectorQueue.getJob(jobId);\n if (job) {\n executingJobs.push(job);\n }\n }\n }\n return {\n isPaused: inspectorQueue.paused,\n pendingJobs,\n executingJobs,\n totalPending: pendingJobs.length,\n totalExecuting: executingJobs.length,\n };\n }\n case \"queue.pause\":\n inspectorQueue?.pause();\n return undefined;\n case \"queue.resume\":\n await inspectorQueue?.resume();\n return undefined;\n case \"processors.getAll\":\n return (inspectorProcessors?.getAll() ?? []).map((tracked) => ({\n processorId: tracked.processorId,\n factoryId: tracked.factoryId,\n driveId: tracked.driveId,\n processorIndex: tracked.processorIndex,\n lastOrdinal: tracked.lastOrdinal,\n status: tracked.status,\n lastError: tracked.lastError,\n lastErrorTimestamp: tracked.lastErrorTimestamp,\n }));\n case \"processors.retry\": {\n const [processorId] = args as [string];\n await inspectorProcessors?.get(processorId)?.retry();\n return undefined;\n }\n case \"integrity.validate\": {\n if (!inspectorIntegrity) {\n throw new Error(\"Integrity service not available\");\n }\n const [documentId, branch] = args as [string, string?];\n return inspectorIntegrity.validateDocument(documentId, branch);\n }\n case \"integrity.rebuildKeyframes\": {\n if (!inspectorIntegrity) {\n throw new Error(\"Integrity service not available\");\n }\n const [documentId, branch] = args as [string, string?];\n return inspectorIntegrity.rebuildKeyframes(documentId, branch);\n }\n case \"integrity.rebuildSnapshots\": {\n if (!inspectorIntegrity) {\n throw new Error(\"Integrity service not available\");\n }\n const [documentId, branch] = args as [string, string?];\n return inspectorIntegrity.rebuildSnapshots(documentId, branch);\n }\n case \"db.query\": {\n if (!owned.reactorPg) {\n throw new Error(\"Reactor store not available\");\n }\n const [sql, params] = args as [string, unknown[]];\n const result = await owned.reactorPg.query(sql, params);\n return result.rows;\n }\n default:\n throw new Error(`Unknown inspector op: ${method}`);\n }\n },\n});\n\ntype WorkerGlobalErrorEvent = {\n message?: string;\n error?: unknown;\n reason?: unknown;\n};\n\nconst globalScope = self as unknown as {\n addEventListener: (\n type: \"error\" | \"unhandledrejection\",\n listener: (event: WorkerGlobalErrorEvent) => void,\n ) => void;\n onconnect: ((event: MessageEvent) => void) | null;\n};\n\nglobalScope.addEventListener(\"error\", (event) => {\n console.error(\n \"[reactor.worker] uncaught error\",\n event.message ?? event.error ?? event,\n );\n});\nglobalScope.addEventListener(\"unhandledrejection\", (event) => {\n console.error(\"[reactor.worker] unhandled rejection\", event.reason);\n});\n\nglobalScope.onconnect = (event) => {\n const port = event.ports[0];\n if (port) {\n try {\n host.connectPort(port);\n } catch (error) {\n console.error(\"[reactor.worker] failed to connect port\", error);\n }\n }\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;AA0DA,QAAQ,KAAK,qCAAqC;AAGlD,MAAM,kBAAkB;AAIxB,SAAS,uBAAuB,YAA8C;AAC5E,QAAO,WAAW,QACf,MACC,OAAO,MAAM,YACb,MAAM,QACN,mBAAmB,KACnB,aAAa,EAChB;;AAGH,MAAM,sBAAsB,uBAC1B,OAAO,OAAO,qBAAqB,CACpC;AAID,eAAe,0BAA0D;CACvE,MAAM,sBACJ,MAAM,OAAO;AACf,QAAO,uBAAuB,OAAO,OAAO,oBAAoB,CAAC;;AAenE,IAAI;AACJ,IAAI;AACJ,IAAI;AACJ,IAAI;AAKJ,MAAM,aAA8B,EAAE;AAStC,MAAM,QAAsB,EAAE;AAC9B,IAAI;AACJ,IAAI;AACJ,IAAI;AACJ,IAAI,kBAA0C;AAC9C,MAAM,iCAAiB,IAAI,KAAa;AAExC,SAAS,SAAS,QAAqC;AACrD,QAAO,GAAG,OAAO,cAAc,OAAO,GAAG,GAAG,OAAO,WAAW;;AAIhE,SAAS,aAAa,QAAgB;AACpC,QAAO;EACL,MAAM,OAAO;EACb,iBAAiB,OAAO,QAAQ,oBAAoB;EACrD;;AAIH,SAAS,qBAA2B;AAClC,KAAI,CAAC,UAAU,CAAC,SACd;CAEF,MAAM,QAAQ,OAAO,OAAO,QAAQ,MAAM,CAAC,eAAe,IAAI,SAAS,EAAE,CAAC,CAAC;AAC3E,KAAI,MAAM,WAAW,EACnB;AAEF,UAAS,gBAAgB,GAAG,MAAM;AAClC,MAAK,MAAM,KAAK,MACd,gBAAe,IAAI,SAAS,EAAE,CAAC;;AAKnC,eAAe,oBAAoB;CACjC,MAAM,aAAa,MAAM,kBAAkB,QAAQ;AACnD,QAAO,IAAI,qBAAqB,CAAC,mBAAmB,WAAW,CAAC,OAAO;;AAIzE,eAAe,kBAAkB,WAAmB;CAClD,MAAM,WAAW,YAAY,MAAM,kBAAkB,WAAW,YAAY,CAAC;CAC7E,MAAM,QAAQ,yBAAyB,SAAS;AAChD,KAAI,UAAU,GACZ,SAAQ,KACN,qEAAqE,MAAM,8DAC5E;CAEH,MAAM,EAAE,WAAW,MAAM,iBAAiB,MAAM;AAEhD,QAAO;EAAE,IADE,IAAI,OAAO,SAAS,aAAa,EAAE,mBAAmB,MAAM,CAAC;EAC3D;EAAU;;AAKzB,eAAe,WAAW,OAAgD;AACxE,KAAI,UAAU,GACZ,QAAO,OAAO;AAEhB,QAAO,OAAO;;AAGhB,eAAe,eAAe,WAA2C;AACvE,KAAI;EACF,MAAM,WAAW,YACf,MAAM,kBAAkB,WAAW,YAAY,CAChD;EACD,MAAM,QAAQ,yBAAyB,SAAS;AAChD,MAAI,UAAU,GACZ,SAAQ,KACN,8EAA8E,MAAM,8DACrF;EAEH,MAAM,CAAC,EAAE,UAAU,EAAE,UAAU,MAAM,QAAQ,IAAI,CAC/C,iBAAiB,MAAM,EACvB,WAAW,MAAM,CAClB,CAAC;EACF,MAAM,KAAK,IAAI,OAAO,SAAS,aAAa;GAC1C,mBAAmB;GACnB,YAAY,EAAE,MAAM;GACrB,CAAC;AACF,aAAW,KAAK;AAChB,aAAW,KAAK,mBACd,IAAI,OAAO,EAAE,SAAS,IAAI,cAAc,GAAG,EAAE,CAAC,CAC/C;AACD,UAAQ,KACN,mDAAmD,UAAU,aAAa,MAAM,IACjF;AACD,SAAO;UACA,OAAO;AACd,UAAQ,MACN,yDACA,MACD;AACD,SAAO;;;AAIX,IAAI,iBAAuC,EAAE,QAAQ,QAAQ;AAE7D,SAAS,aAAa,OAAmC;AACvD,kBAAiB;AACjB,MAAK,kBAAkB,MAAM;;AAG/B,MAAM,iBAAiC;CACrC,WAAW,YAAY,aAAa,QAAQ;CAC5C,WAAW,QAAQ,YACjB,cAAc,SAAS,OAA0B;CACnD,eAAe,QAAQ,SAAS;CAChC,cAAc,QAAQ,SAAS;CAChC;AAID,MAAM,OAAO,IAAI,YAAY;CAC3B,WAHkB,KAA2B,QAAQ;CAIrD,sBACE,KAAK,gBAAgB,iBAAiB,OAAO,YAAY,CAAC;CAC5D,qBAAqB,YAAY;AAC/B,QAAM,WAAW,IAAI,OAAO;AAC5B,QAAM,MAAM,WAAW,OAAO;AAC9B,OAAK,MAAM,WAAW,CAAC,MAAM,YAAY,MAAM,cAAc,CAC3D,KAAI,QACF,OAAM,cAAc,QAAQ;AAGhC,OAAK,gBAAgB,mBAAmB,OAAO,YAAY,CAAC;;CAE9D,gBAAgB,YAAY;AAC1B,eAAa;GACX,QAAQ;GACR,aAAa,eAAe;GAC7B,CAAC;AACF,MAAI,WAAW,GAAI,OAAM,WAAW,GAAG,OAAO,CAAC,YAAY,KAAA,EAAU;AACrE,MAAI,MAAM,UAAW,OAAM,MAAM,UAAU,OAAO,CAAC,YAAY,KAAA,EAAU;AACzE,MAAI;AACF,QAAK,MAAM,WAAW,CAAC,MAAM,YAAY,MAAM,cAAc,CAC3D,KAAI,QACF,OAAM,WACJ,UACC,UACC,aAAa;IACX,QAAQ;IACR,aAAa,eAAe;IAC5B;IACD,CAAC,EACJ,eACD;AAGL,QAAK,gBAAgB,sBAAsB,OAAO,YAAY,CAAC;WACxD,OAAO;AACd,WAAQ,MAAM,sCAAsC,MAAM;AAC1D,gBAAa;IACX,QAAQ;IACR,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;IAC9D,CAAC;AACF,QAAK,gBAAgB,oBAAoB,OAAO,YAAY,CAAC;;;CAGjE,OAAO,OAAO,QAAQ;EACpB,IAAI,QAAQ;AACZ,MAAI;GACF,MAAM,YAAY;AAClB,WAAQ;AACR,WAAQ,KAAK,0BAA0B,QAAQ;AAC/C,YAAS,IAAI,oBAAoB;IAC/B,QAAQ,UAAU;IAClB,gBAAgB,QACd;;KAA0B;;IAC7B,CAAC;GACF,MAAM,SAAS,MAAM,OAAO,aAAa,UAAU,aAAa;GAChE,MAAM,cAAc,UAAU,aAC1B,MAAM,yBAAyB,GAC/B,EAAE;GACN,MAAM,SAAS,mBAAmB,OAChC,qBACA,aACA,OACD;AACD,WAAQ;AACR,WAAQ,KAAK,0BAA0B,QAAQ;GAC/C,MAAM,CAAC,SAAS,mBAAmB,MAAM,QAAQ,IAAI,CACnD,kBAAkB,UAAU,UAAU,EACtC,eAAe,UAAU,oBAAoB,CAC9C,CAAC;GACF,MAAM,KAAK,QAAQ;AACnB,SAAM,YAAY;AAClB,SAAM,aAAa,WAAW,UAAU;AACxC,SAAM,gBAAgB,WAAW,UAAU;GAG3C,MAAM,cAAc,CAAC,QAAQ,UAAU,gBAAgB,CAAC,MACrD,MAA6B,MAAM,QAAQ,MAAA,GAC7C;AACD,OAAI,gBAAgB,KAAA,EAClB,cAAa;IAAE,QAAQ;IAAU;IAAa,CAAC;AAEjD,WAAQ;AACR,WAAQ,KAAK,0BAA0B,QAAQ;GAC/C,MAAM,SAAS,MAAM,mBAAmB;AACxC,YAAS,IAAI,mBACX,QACA,iBACA,mBAAmB,KAAA,EACpB;GACD,MAAM,aAAyB,YAC7B,kBACI,OAAO,eAAe,gBAAgB,SAAS,EAAE,WAAW,IAAI,CAAC,GACjE,KAAA;AACN,WAAQ;AACR,WAAQ,KAAK,0BAA0B,QAAQ;GAC/C,MAAM,UAAU,IAAI,sBAAsB,CACvC,WAAW;IAAE;IAAQ,UAAU,yBAAyB;IAAE,CAAC,CAC3D,mBACC,IAAI,gBAAgB,CACjB,mBAAmB,OAAO,CAC1B,kBAAkB,cAAc,QAAQ,CACxC,eAAe,WAAW,CAC1B,WACC,IAAI,OAAiB,EAAE,SAAS,IAAI,cAAc,GAAG,EAAE,CAAC,CACzD,CACJ;AACH,WAAQ,wBAAwB,OAAO;GACvC,MAAM,SAAS,MAAM,QAAQ,aAAa;AAC1C,cAAW,OAAO,eAAe;AACjC,iBAAc,OAAO,eAAe,YAAY;GAChD,MAAM,KAAK,OAAO;AAClB,OAAI,IAAI;AACN,qBACE,GAAG,iBAAiB,gBAAgB,GAAG,QAAQ,KAAA;AACjD,0BAAsB,GAAG;AACzB,yBAAqB,IAAI,yBACvB,GAAG,eACH,GAAG,gBACH,GAAG,YACH,GAAG,cACH,GAAG,sBACJ;;AAEH,QAAK,MAAM,KAAK,OACd,gBAAe,IAAI,SAAS,EAAE,CAAC;AAEjC,QAAK,MAAM,QAAQ,sBACjB,QAAO,SAAS,UAAU,OAAO,eAAe,UAC9C,KAAK,kBAAkB,eAAe,MAAM,CAC7C;AAEH,gBAAa,oBAAoB,YAAY,WAC3C,KAAK,kBAAkB,2BAA2B;IAChD;IACA;IACD,CAAC,CACH;AACD,WAAQ,KAAK,kCAAkC;AAC/C,UAAO,OAAO;WACP,OAAO;AACd,WAAQ,MAAM,0CAA0C,MAAM,KAAK,MAAM;AACzE,SAAM;;;CAGV,kBAAkB,OAAO,UAAU;AACjC,MAAI,CAAC,OACH;AAEF,QAAM,OAAO,aAAa,MAAM;AAChC,sBAAoB;;CAEtB,aAAa,SAAS;AACpB,oBAAkB;AAClB,MAAI,OACF,QAAO,OAAO,QAAQ,KAAA;;CAG1B,UAAU,OAAO,QAAQ,SAAS;AAChC,MAAI,CAAC,YACH,OAAM,IAAI,MAAM,4BAA4B;AAE9C,UAAQ,QAAR;GACE,KAAK,OACH,QAAO,YAAY,MAAM,CAAC,IAAI,aAAa;GAC7C,KAAK,OAAO;IACV,MAAM,CAAC,MAAM,iBAAiB,eAAe,QAAQ,WACnD;AAcF,WAAO,aAPQ,MAAM,YAAY,IAC/B,MACA,kBAAkB,QAAQ,gBAAgB,EAC1C,eACA,QACA,QACD,CAC0B;;GAE7B,KAAK;AACH,UAAM,YAAY,OAAO,KAAK,GAAa;AAC3C;GACF,KAAK;AACH,gBAAY,YAAY,KAAK,GAAa;AAC1C;GACF,QACE,OAAM,IAAI,MAAM,oBAAoB,SAAS;;;CAGnD,QAAQ,OAAO,QAAQ,SAAS;AAC9B,MAAI,CAAC,WAAW,GACd,OAAM,IAAI,MAAM,iCAAiC;AAEnD,UAAQ,QAAR;GACE,KAAK,SAAS;IACZ,MAAM,CAAC,KAAK,UAAU;AAEtB,YADe,MAAM,WAAW,GAAG,MAAM,KAAK,OAAO,EACvC;;GAEhB,QACE,OAAM,IAAI,MAAM,kBAAkB,SAAS;;;CAGjD,aAAa,OAAO,KAAK,QAAQ,cAAc;AAC7C,MAAI,CAAC,WAAW,GACd,OAAM,IAAI,MAAM,iCAAiC;EAEnD,MAAM,OAAO,MAAM,WAAW,GAAG,KAAK,MAAM,KAAK,SAAS,YACxD,UAAU,QAAQ,CACnB;AACD,eAAa;AACN,QAAK,aAAa;;;CAG3B,eAAe,OAAO,QAAQ,SAAS;AACrC,UAAQ,QAAR;GACE,KAAK,kBAAkB;AACrB,QAAI,CAAC,eACH,QAAO;KACL,UAAU;KACV,aAAa,EAAE;KACf,eAAe,EAAE;KACjB,cAAc;KACd,gBAAgB;KACjB;IAEH,MAAM,cAAc,eAAe,gBAAgB;IACnD,MAAM,gBAAgB,EAAE;AACxB,SAAK,MAAM,UAAU,eAAe,oBAAoB,CAAC,QAAQ,CAC/D,MAAK,MAAM,SAAS,QAAQ;KAC1B,MAAM,MAAM,eAAe,OAAO,MAAM;AACxC,SAAI,IACF,eAAc,KAAK,IAAI;;AAI7B,WAAO;KACL,UAAU,eAAe;KACzB;KACA;KACA,cAAc,YAAY;KAC1B,gBAAgB,cAAc;KAC/B;;GAEH,KAAK;AACH,oBAAgB,OAAO;AACvB;GACF,KAAK;AACH,UAAM,gBAAgB,QAAQ;AAC9B;GACF,KAAK,oBACH,SAAQ,qBAAqB,QAAQ,IAAI,EAAE,EAAE,KAAK,aAAa;IAC7D,aAAa,QAAQ;IACrB,WAAW,QAAQ;IACnB,SAAS,QAAQ;IACjB,gBAAgB,QAAQ;IACxB,aAAa,QAAQ;IACrB,QAAQ,QAAQ;IAChB,WAAW,QAAQ;IACnB,oBAAoB,QAAQ;IAC7B,EAAE;GACL,KAAK,oBAAoB;IACvB,MAAM,CAAC,eAAe;AACtB,UAAM,qBAAqB,IAAI,YAAY,EAAE,OAAO;AACpD;;GAEF,KAAK,sBAAsB;AACzB,QAAI,CAAC,mBACH,OAAM,IAAI,MAAM,kCAAkC;IAEpD,MAAM,CAAC,YAAY,UAAU;AAC7B,WAAO,mBAAmB,iBAAiB,YAAY,OAAO;;GAEhE,KAAK,8BAA8B;AACjC,QAAI,CAAC,mBACH,OAAM,IAAI,MAAM,kCAAkC;IAEpD,MAAM,CAAC,YAAY,UAAU;AAC7B,WAAO,mBAAmB,iBAAiB,YAAY,OAAO;;GAEhE,KAAK,8BAA8B;AACjC,QAAI,CAAC,mBACH,OAAM,IAAI,MAAM,kCAAkC;IAEpD,MAAM,CAAC,YAAY,UAAU;AAC7B,WAAO,mBAAmB,iBAAiB,YAAY,OAAO;;GAEhE,KAAK,YAAY;AACf,QAAI,CAAC,MAAM,UACT,OAAM,IAAI,MAAM,8BAA8B;IAEhD,MAAM,CAAC,KAAK,UAAU;AAEtB,YADe,MAAM,MAAM,UAAU,MAAM,KAAK,OAAO,EACzC;;GAEhB,QACE,OAAM,IAAI,MAAM,yBAAyB,SAAS;;;CAGzD,CAAC;AAQF,MAAM,cAAc;AAQpB,YAAY,iBAAiB,UAAU,UAAU;AAC/C,SAAQ,MACN,mCACA,MAAM,WAAW,MAAM,SAAS,MACjC;EACD;AACF,YAAY,iBAAiB,uBAAuB,UAAU;AAC5D,SAAQ,MAAM,wCAAwC,MAAM,OAAO;EACnE;AAEF,YAAY,aAAa,UAAU;CACjC,MAAM,OAAO,MAAM,MAAM;AACzB,KAAI,KACF,KAAI;AACF,OAAK,YAAY,KAAK;UACf,OAAO;AACd,UAAQ,MAAM,2CAA2C,MAAM","debug_id":"f75dcc63-6708-5346-bc6d-2602d8321cd8"}
1
+ {"version":3,"file":"reactor.worker.js","sources":["../src/reactor.worker.ts"],"sourcesContent":["import {\n ChannelScheme,\n DocumentIntegrityService,\n DriveCollectionId,\n InMemoryQueue,\n ReactorBuilder,\n ReactorClientBuilder,\n type ChannelConfig,\n type Database,\n type ISyncManager,\n type JwtHandler,\n type Remote,\n type RemoteFilter,\n type RemoteOptions,\n} from \"@powerhousedao/reactor\";\nimport { baseDocumentModels } from \"@powerhousedao/reactor-browser/base-document-models\";\nimport {\n FORWARDED_EVENT_TYPES,\n ReactorHost,\n SYNC_STATUS_CHANGED_EVENT,\n WorkerPackageLoader,\n type ReactorIdentity,\n type WorkerMigrationState,\n} from \"@powerhousedao/reactor-browser/rpc\";\nimport type { DocumentModelModule } from \"@powerhousedao/shared/document-model\";\nimport {\n createRelationalDb,\n type IProcessorManager,\n type IRelationalDb,\n} from \"@powerhousedao/shared/processors\";\nimport * as commonDocumentModels from \"@powerhousedao/powerhouse-vetra-packages/document-models\";\nimport {\n BrowserKeyStorage,\n createSignatureVerifier,\n RenownCryptoBuilder,\n RenownCryptoSigner,\n} from \"@renown/sdk/crypto\";\nimport type * as PgLiveModuleNs from \"@electric-sql/pglite/live\";\nimport { Kysely } from \"kysely\";\nimport { PGliteDialect } from \"kysely-pglite-dialect\";\nimport { readPgVersionFile } from \"./utils/pglite-idb.js\";\nimport {\n coerceMajor,\n CURRENT_PG_MAJOR,\n type DetectedMajor,\n loadPGliteModule,\n resolvePgMajorForRuntime,\n type SupportedPgMajor,\n} from \"./utils/pglite-major.js\";\nimport {\n type BackupStrategy,\n type FileDataEntry,\n clearFileData,\n migrateIdb,\n readFileData,\n writeFileData,\n} from \"./utils/pglite-migrate-core.js\";\n\nconsole.info(\"[reactor.worker] module evaluating\");\n\n// Matches the main thread's RenownBuilder(\"connect\").\nconst RENOWN_APP_NAME = \"connect\";\n\n// Common models the tab bundles as a local package; not CDN-loadable, so the\n// worker imports them directly. Vetra is builder-only and lazy-loaded below.\nfunction toDocumentModelModules(candidates: unknown[]): DocumentModelModule[] {\n return candidates.filter(\n (m): m is DocumentModelModule =>\n typeof m === \"object\" &&\n m !== null &&\n \"documentModel\" in m &&\n \"reducer\" in m,\n );\n}\n\nconst commonBundledModels = toDocumentModelModules(\n Object.values(commonDocumentModels),\n);\n\n// Not CDN-loadable, so it can't ride the packageSpecs path; lazy-import the\n// bundled chunk only in studio mode.\nasync function loadVetraDocumentModels(): Promise<DocumentModelModule[]> {\n const vetraDocumentModels =\n await import(\"@powerhousedao/vetra/document-models\");\n return toDocumentModelModules(Object.values(vetraDocumentModels));\n}\n\ntype WorkerConstruct = {\n namespace: string;\n relationalNamespace: string;\n cdnUrl: string;\n packageSpecs: string[];\n studioMode?: boolean;\n};\n\ntype ModelRegistry = {\n registerModules: (...modules: DocumentModelModule[]) => void;\n};\n\nlet loader: WorkerPackageLoader | undefined;\nlet registry: ModelRegistry | undefined;\nlet signer: RenownCryptoSigner | undefined;\nlet syncManager: ISyncManager | undefined;\ntype RelationalState = {\n pg?: PgLiveModuleNs.PGliteWithLive;\n db?: IRelationalDb;\n};\nconst relational: RelationalState = {};\ntype OwnedStorage = {\n reactorPg?: {\n close: () => Promise<void>;\n query: (sql: string, params?: unknown[]) => Promise<{ rows: unknown[] }>;\n };\n reactorIdb?: string;\n relationalIdb?: string;\n};\nconst owned: OwnedStorage = {};\nlet inspectorQueue: InMemoryQueue | undefined;\nlet inspectorProcessors: IProcessorManager | undefined;\nlet inspectorIntegrity: DocumentIntegrityService | undefined;\nlet currentIdentity: ReactorIdentity | null = null;\nconst registeredKeys = new Set<string>();\n\nfunction modelKey(module: DocumentModelModule): string {\n return `${module.documentModel.global.id}@${module.version ?? 1}`;\n}\n\n// Cloneable projection of a Remote: meta (carries channelConfig) + connection snapshot.\nfunction toWireRemote(remote: Remote) {\n return {\n meta: remote.meta,\n connectionState: remote.channel.getConnectionState(),\n };\n}\n\n// Register only the delta; the registry rejects duplicate (type, version) pairs.\nfunction registerNewModules(): void {\n if (!loader || !registry) {\n return;\n }\n const fresh = loader.models.filter((m) => !registeredKeys.has(modelKey(m)));\n if (fresh.length === 0) {\n return;\n }\n registry.registerModules(...fresh);\n for (const m of fresh) {\n registeredKeys.add(modelKey(m));\n }\n}\n\n// Rebuild renown crypto from the shared renownKeyDB keypair (origin-scoped IndexedDB).\nasync function buildWorkerCrypto() {\n const keyStorage = await BrowserKeyStorage.create();\n return new RenownCryptoBuilder().withKeyPairStorage(keyStorage).build();\n}\n\n// Open against the major already on disk so a legacy PG16 dir isn't read by PG17.\nasync function openReactorPglite(namespace: string) {\n const detected = coerceMajor(await readPgVersionFile(`/pglite/${namespace}`));\n const major = resolvePgMajorForRuntime(detected);\n if (major !== 17) {\n console.warn(\n `[reactor.worker] Running against legacy PGlite data dir (Postgres ${major}). Migrate to PG17 from the Connect banner or the Inspector.`,\n );\n }\n const { PGlite } = await loadPGliteModule(major);\n const pg = new PGlite(`idb://${namespace}`, { relaxedDurability: true });\n await pg.waitReady;\n return { pg, detected };\n}\n\ntype PgLiveModule = typeof PgLiveModuleNs;\n\nasync function loadPgLive(major: SupportedPgMajor): Promise<PgLiveModule> {\n if (major === 16) {\n return import(\"pglite-legacy-02/live\") as unknown as Promise<PgLiveModule>;\n }\n return import(\"@electric-sql/pglite/live\");\n}\n\nasync function openRelational(namespace: string): Promise<DetectedMajor> {\n try {\n const detected = coerceMajor(\n await readPgVersionFile(`/pglite/${namespace}`),\n );\n const major = resolvePgMajorForRuntime(detected);\n if (major !== 17) {\n console.warn(\n `[reactor.worker] Relational store opening legacy PGlite data dir (Postgres ${major}). Migrate to PG17 from the Connect banner or the Inspector.`,\n );\n }\n const [{ PGlite }, { live }] = await Promise.all([\n loadPGliteModule(major),\n loadPgLive(major),\n ]);\n const pg = new PGlite(`idb://${namespace}`, {\n relaxedDurability: true,\n extensions: { live },\n });\n await pg.waitReady;\n relational.pg = pg as unknown as PgLiveModuleNs.PGliteWithLive;\n relational.db = createRelationalDb(\n new Kysely({ dialect: new PGliteDialect(pg) }),\n );\n console.info(\n `[reactor.worker] Relational store opened: idb://${namespace} (Postgres ${major}).`,\n );\n return detected;\n } catch (error) {\n console.error(\n \"[reactor.worker] Failed to open the relational store:\",\n error,\n );\n return null;\n }\n}\n\nlet migrationState: WorkerMigrationState = { status: \"idle\" };\n\nfunction setMigration(state: WorkerMigrationState): void {\n migrationState = state;\n host.setMigrationState(state);\n}\n\nconst inMemoryBackup: BackupStrategy = {\n snapshot: (idbName) => readFileData(idbName),\n rollback: (handle, idbName) =>\n writeFileData(idbName, handle as FileDataEntry[]),\n discard: () => Promise.resolve(),\n commit: () => Promise.resolve(),\n};\n\nconst workerName = (self as { name?: string }).name ?? \"\";\n\nconst host = new ReactorHost({\n namespace: workerName,\n onAdminRestart: () =>\n host.broadcastReload(\"admin restart\", crypto.randomUUID()),\n onAdminClearStorage: async () => {\n await relational.pg?.close();\n await owned.reactorPg?.close();\n for (const idbName of [owned.reactorIdb, owned.relationalIdb]) {\n if (idbName) {\n await clearFileData(idbName);\n }\n }\n host.broadcastReload(\"storage cleared\", crypto.randomUUID());\n },\n onAdminMigrate: async () => {\n setMigration({\n status: \"migrating\",\n legacyMajor: migrationState.legacyMajor,\n });\n if (relational.pg) await relational.pg.close().catch(() => undefined);\n if (owned.reactorPg) await owned.reactorPg.close().catch(() => undefined);\n try {\n for (const idbName of [owned.reactorIdb, owned.relationalIdb]) {\n if (idbName) {\n await migrateIdb(\n idbName,\n (phase) =>\n setMigration({\n status: \"migrating\",\n legacyMajor: migrationState.legacyMajor,\n phase,\n }),\n inMemoryBackup,\n );\n }\n }\n host.broadcastReload(\"migration complete\", crypto.randomUUID());\n } catch (error) {\n console.error(\"[reactor.worker] Migration failed:\", error);\n setMigration({\n status: \"failed\",\n error: error instanceof Error ? error.message : String(error),\n });\n host.broadcastReload(\"migration failed\", crypto.randomUUID());\n }\n },\n build: async (raw) => {\n let phase = \"init\";\n try {\n const construct = raw as WorkerConstruct;\n phase = \"loading packages\";\n console.info(`[reactor.worker] boot: ${phase}`);\n loader = new WorkerPackageLoader({\n cdnUrl: construct.cdnUrl,\n importPackage: (url) =>\n import(/* @vite-ignore */ url) as Promise<Record<string, unknown>>,\n });\n const loaded = await loader.loadPackages(construct.packageSpecs);\n const vetraModels = construct.studioMode\n ? await loadVetraDocumentModels()\n : [];\n const models = baseDocumentModels.concat(\n commonBundledModels,\n vetraModels,\n loaded,\n );\n phase = \"opening pglite stores\";\n console.info(`[reactor.worker] boot: ${phase}`);\n\n //this has to be serial: concurrent PGlite constructors consume the same\n // cached one-shot wasm \"Response\" object\n const reactor = await openReactorPglite(construct.namespace);\n const relationalMajor = await openRelational(\n construct.relationalNamespace,\n );\n const pg = reactor.pg;\n owned.reactorPg = pg;\n owned.reactorIdb = `/pglite/${construct.namespace}`;\n owned.relationalIdb = `/pglite/${construct.relationalNamespace}`;\n // A store is migratable when coerceMajor kept it (a supported legacy\n // major) and it is not the current one; openers already read PG_VERSION.\n const legacyMajor = [reactor.detected, relationalMajor].find(\n (m): m is SupportedPgMajor => m !== null && m !== CURRENT_PG_MAJOR,\n );\n if (legacyMajor !== undefined) {\n setMigration({ status: \"needed\", legacyMajor });\n }\n phase = \"building crypto\";\n console.info(`[reactor.worker] boot: ${phase}`);\n const crypto = await buildWorkerCrypto();\n signer = new RenownCryptoSigner(\n crypto,\n RENOWN_APP_NAME,\n currentIdentity ?? undefined,\n );\n const jwtHandler: JwtHandler = async () =>\n currentIdentity\n ? crypto.getBearerToken(currentIdentity.address, { expiresIn: 10 })\n : undefined;\n phase = \"building reactor module\";\n console.info(`[reactor.worker] boot: ${phase}`);\n const builder = new ReactorClientBuilder()\n .withSigner({ signer, verifier: createSignatureVerifier() })\n .withReactorBuilder(\n new ReactorBuilder()\n .withDocumentModelSources(models)\n .withChannelScheme(ChannelScheme.CONNECT)\n .withJwtHandler(jwtHandler)\n .withKysely(\n new Kysely<Database>({ dialect: new PGliteDialect(pg) }),\n ),\n );\n builder.withDocumentModelLoader(loader);\n const module = await builder.buildModule();\n registry = module.reactorModule?.documentModelRegistry;\n syncManager = module.reactorModule?.syncModule?.syncManager;\n const rm = module.reactorModule;\n if (rm) {\n inspectorQueue =\n rm.queue instanceof InMemoryQueue ? rm.queue : undefined;\n inspectorProcessors = rm.processorManager;\n inspectorIntegrity = new DocumentIntegrityService(\n rm.keyframeStore,\n rm.operationStore,\n rm.writeCache,\n rm.documentView,\n rm.documentModelRegistry,\n );\n }\n for (const m of models) {\n registeredKeys.add(modelKey(m));\n }\n for (const type of FORWARDED_EVENT_TYPES) {\n module.eventBus.subscribe(type, (forwardedType, event) =>\n host.broadcastBusEvent(forwardedType, event),\n );\n }\n syncManager?.onSyncStatusChange((documentId, status) =>\n host.broadcastBusEvent(SYNC_STATUS_CHANGED_EVENT, {\n documentId,\n status,\n }),\n );\n console.info(\"[reactor.worker] boot: complete\");\n return module.client;\n } catch (error) {\n console.error(`[reactor.worker] boot failed at phase \"${phase}\":`, error);\n throw error;\n }\n },\n registerPackages: async (specs) => {\n if (!loader) {\n return;\n }\n await loader.loadPackages(specs);\n registerNewModules();\n },\n onIdentity: (user) => {\n currentIdentity = user;\n if (signer) {\n signer.user = user ?? undefined;\n }\n },\n onSyncOp: async (method, args) => {\n if (!syncManager) {\n throw new Error(\"SyncManager not available\");\n }\n switch (method) {\n case \"list\":\n return syncManager.list().map(toWireRemote);\n case \"add\": {\n const [name, collectionIdKey, channelConfig, filter, options] =\n args as [\n string,\n string,\n ChannelConfig,\n RemoteFilter | undefined,\n RemoteOptions | undefined,\n ];\n const remote = await syncManager.add(\n name,\n DriveCollectionId.fromKey(collectionIdKey),\n channelConfig,\n filter,\n options,\n );\n return toWireRemote(remote);\n }\n case \"remove\":\n await syncManager.remove(args[0] as string);\n return undefined;\n case \"triggerPull\":\n syncManager.triggerPull(args[0] as string);\n return undefined;\n default:\n throw new Error(`Unknown sync op: ${method}`);\n }\n },\n onDbOp: async (method, args) => {\n if (!relational.pg) {\n throw new Error(\"Relational store not available\");\n }\n switch (method) {\n case \"query\": {\n const [sql, params] = args as [string, unknown[]];\n const result = await relational.pg.query(sql, params);\n return result.rows;\n }\n default:\n throw new Error(`Unknown db op: ${method}`);\n }\n },\n onLiveQuery: async (sql, params, onResults) => {\n if (!relational.pg) {\n throw new Error(\"Relational store not available\");\n }\n const live = await relational.pg.live.query(sql, params, (results) =>\n onResults(results),\n );\n return () => {\n void live.unsubscribe();\n };\n },\n onInspectorOp: async (method, args) => {\n switch (method) {\n case \"queue.getState\": {\n if (!inspectorQueue) {\n return {\n isPaused: false,\n pendingJobs: [],\n executingJobs: [],\n totalPending: 0,\n totalExecuting: 0,\n };\n }\n const pendingJobs = inspectorQueue.getPendingJobs();\n const executingJobs = [];\n for (const jobIds of inspectorQueue.getExecutingJobIds().values()) {\n for (const jobId of jobIds) {\n const job = inspectorQueue.getJob(jobId);\n if (job) {\n executingJobs.push(job);\n }\n }\n }\n return {\n isPaused: inspectorQueue.paused,\n pendingJobs,\n executingJobs,\n totalPending: pendingJobs.length,\n totalExecuting: executingJobs.length,\n };\n }\n case \"queue.pause\":\n inspectorQueue?.pause();\n return undefined;\n case \"queue.resume\":\n await inspectorQueue?.resume();\n return undefined;\n case \"processors.getAll\":\n return (inspectorProcessors?.getAll() ?? []).map((tracked) => ({\n processorId: tracked.processorId,\n factoryId: tracked.factoryId,\n driveId: tracked.driveId,\n processorIndex: tracked.processorIndex,\n lastOrdinal: tracked.lastOrdinal,\n status: tracked.status,\n lastError: tracked.lastError,\n lastErrorTimestamp: tracked.lastErrorTimestamp,\n }));\n case \"processors.retry\": {\n const [processorId] = args as [string];\n await inspectorProcessors?.get(processorId)?.retry();\n return undefined;\n }\n case \"integrity.validate\": {\n if (!inspectorIntegrity) {\n throw new Error(\"Integrity service not available\");\n }\n const [documentId, branch] = args as [string, string?];\n return inspectorIntegrity.validateDocument(documentId, branch);\n }\n case \"integrity.rebuildKeyframes\": {\n if (!inspectorIntegrity) {\n throw new Error(\"Integrity service not available\");\n }\n const [documentId, branch] = args as [string, string?];\n return inspectorIntegrity.rebuildKeyframes(documentId, branch);\n }\n case \"integrity.rebuildSnapshots\": {\n if (!inspectorIntegrity) {\n throw new Error(\"Integrity service not available\");\n }\n const [documentId, branch] = args as [string, string?];\n return inspectorIntegrity.rebuildSnapshots(documentId, branch);\n }\n case \"db.query\": {\n if (!owned.reactorPg) {\n throw new Error(\"Reactor store not available\");\n }\n const [sql, params] = args as [string, unknown[]];\n const result = await owned.reactorPg.query(sql, params);\n return result.rows;\n }\n default:\n throw new Error(`Unknown inspector op: ${method}`);\n }\n },\n});\n\ntype WorkerGlobalErrorEvent = {\n message?: string;\n error?: unknown;\n reason?: unknown;\n};\n\nconst globalScope = self as unknown as {\n addEventListener: (\n type: \"error\" | \"unhandledrejection\",\n listener: (event: WorkerGlobalErrorEvent) => void,\n ) => void;\n onconnect: ((event: MessageEvent) => void) | null;\n};\n\nglobalScope.addEventListener(\"error\", (event) => {\n console.error(\n \"[reactor.worker] uncaught error\",\n event.message ?? event.error ?? event,\n );\n});\nglobalScope.addEventListener(\"unhandledrejection\", (event) => {\n console.error(\"[reactor.worker] unhandled rejection\", event.reason);\n});\n\nglobalScope.onconnect = (event) => {\n const port = event.ports[0];\n if (port) {\n try {\n host.connectPort(port);\n } catch (error) {\n console.error(\"[reactor.worker] failed to connect port\", error);\n }\n }\n};\n"],"names":[],"mappings":"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","debug_id":"9866f4c8-6912-5222-805c-67cc9f4ac813"}
@@ -1,6 +1,7 @@
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]="9dd758a7-d4b4-55cf-8fad-8fc2791ec1b0")}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]="77ec84d9-1c39-5b92-a71b-ace95d8fe2d9")}catch(e){}}();
3
3
  import { r as connectConfig } from "./connect.config-vgUeFoNp.js";
4
+ import { t as refreshPwaManifestLink } from "./pwa-manifest-link-CG8UajMz.js";
4
5
  //#region src/utils/registerServiceWorker.ts
5
6
  const serviceWorkerScriptPath = [connectConfig.routerBasename, "service-worker.js"].join("/").replace(/\/{2,}/gm, "/");
6
7
  let updateAvailable = false;
@@ -57,6 +58,7 @@ var ServiceWorkerManager = class {
57
58
  try {
58
59
  navigator.serviceWorker.addEventListener("controllerchange", () => {
59
60
  this.#warmRuntimeConfigCache();
61
+ refreshPwaManifestLink();
60
62
  if (!this.#updateAccepted || this.#reloading) return;
61
63
  this.#reloading = true;
62
64
  window.location.reload();
@@ -123,5 +125,5 @@ const serviceWorkerManager = new ServiceWorkerManager();
123
125
  //#endregion
124
126
  export { serviceWorkerManager as n, subscribeServiceWorkerUpdate as r, getServiceWorkerUpdateAvailable as t };
125
127
 
126
- //# sourceMappingURL=registerServiceWorker-nJIc0yEY.js.map
127
- //# debugId=9dd758a7-d4b4-55cf-8fad-8fc2791ec1b0
128
+ //# sourceMappingURL=registerServiceWorker-uI4Gj6fl.js.map
129
+ //# debugId=77ec84d9-1c39-5b92-a71b-ace95d8fe2d9
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registerServiceWorker-uI4Gj6fl.js","sources":["../src/utils/registerServiceWorker.ts"],"sourcesContent":["import { connectConfig } from \"@powerhousedao/connect/config\";\nimport { refreshPwaManifestLink } from \"./pwa-manifest-link.js\";\n\nconst basePath = connectConfig.routerBasename;\n\nconst serviceWorkerScriptPath = [basePath, \"service-worker.js\"]\n .join(\"/\")\n .replace(/\\/{2,}/gm, \"/\");\n\n// External store backing the refresh prompt: our hand-written service worker\n// (injectManifest, registerType: prompt) parks a new worker as \"waiting\" by not\n// calling skipWaiting on install; we flag that here so\n// service-worker-update-prompt.tsx can offer a Refresh instead of reloading\n// from under the user.\nlet updateAvailable = false;\nconst updateListeners = new Set<() => void>();\n\nfunction setUpdateAvailable(value: boolean) {\n if (updateAvailable === value) return;\n updateAvailable = value;\n for (const listener of updateListeners) listener();\n}\n\nexport function subscribeServiceWorkerUpdate(cb: () => void): () => void {\n updateListeners.add(cb);\n return () => {\n updateListeners.delete(cb);\n };\n}\n\nexport function getServiceWorkerUpdateAvailable(): boolean {\n return updateAvailable;\n}\n\nclass ServiceWorkerManager {\n ready = false;\n debug = false;\n registration: ServiceWorkerRegistration | null = null;\n // Only reload on controllerchange when the user actually accepted an update.\n // clientsClaim fires controllerchange on the very first install too, and we\n // must not reload then.\n #updateAccepted = false;\n #reloading = false;\n\n constructor(debug = false) {\n this.debug = debug;\n }\n\n setDebug(debug: boolean) {\n this.debug = debug;\n }\n\n #log(...args: unknown[]) {\n if (this.debug) console.log(\"[ServiceWorker]\", ...args);\n }\n\n // Watch an installing worker; once it reaches \"installed\" while another\n // worker already controls the page, a new version is waiting → prompt.\n #trackInstalling(worker: ServiceWorker | null) {\n if (!worker) return;\n worker.addEventListener(\"statechange\", () => {\n if (worker.state === \"installed\" && navigator.serviceWorker.controller) {\n this.#log(\"New version installed and waiting\");\n setUpdateAvailable(true);\n }\n });\n }\n\n #handleRegistration(registration: ServiceWorkerRegistration) {\n this.registration = registration;\n this.ready = true;\n this.#log(\"registered\", registration);\n\n // A worker installed by a previous page load may already be waiting.\n if (registration.waiting && navigator.serviceWorker.controller) {\n setUpdateAvailable(true);\n }\n\n this.#trackInstalling(registration.installing);\n registration.addEventListener(\"updatefound\", () => {\n this.#trackInstalling(registration.installing);\n });\n }\n\n async #register() {\n try {\n navigator.serviceWorker.addEventListener(\"controllerchange\", () => {\n // First visit: boot fetches the runtime config before this SW controls\n // the page, so it never lands in the cache. Warm it now (clientsClaim\n // just gave us control) so a single online load is enough to go offline.\n this.#warmRuntimeConfigCache();\n // The SW only serves the dynamic manifest.webmanifest once it controls\n // the page. A package installed before that (its fragment already in\n // IndexedDB) was re-consumed against the static base manifest; now that\n // the dynamic route is live, re-attach the link so it picks up the\n // package's PWA config without a manual reload.\n refreshPwaManifestLink();\n // Reload once the worker we activated via applyUpdate() takes control.\n if (!this.#updateAccepted || this.#reloading) return;\n this.#reloading = true;\n window.location.reload();\n });\n\n const existing = await navigator.serviceWorker.getRegistration();\n if (existing) {\n this.#handleRegistration(existing);\n // Force an immediate check so a deploy that happened while the tab was\n // closed surfaces a prompt on the next load.\n await existing.update();\n } else {\n const registration = await navigator.serviceWorker.register(\n serviceWorkerScriptPath,\n );\n this.#handleRegistration(registration);\n }\n\n // Periodically poll for a new version while the tab stays open.\n const intervalId = setInterval(() => {\n void (async () => {\n const reg = await navigator.serviceWorker.getRegistration();\n if (!reg) {\n clearInterval(intervalId);\n return;\n }\n // Skip while a worker is mid-install or the browser is offline —\n // updating then would only fire a doomed network fetch (per the\n // vite-plugin-pwa periodic-update guidance).\n if (reg.installing || !navigator.onLine) return;\n await reg.update();\n })();\n }, connectConfig.appVersionCheckInterval);\n } catch (error) {\n console.error(\"ServiceWorker registration failed: \", error);\n }\n }\n\n registerServiceWorker(debug = false) {\n this.debug = debug;\n\n if (!(\"serviceWorker\" in navigator)) {\n console.warn(\"Service Worker not available\");\n return;\n }\n const start = () => {\n this.#register().catch(console.error);\n };\n // This runs from a React effect, which usually fires *after* the window\n // `load` event has already happened — so adding a load listener would never\n // fire. Register immediately when the page is already loaded; otherwise wait\n // for load to avoid contending with initial page resource fetches.\n if (document.readyState === \"complete\") {\n start();\n } else {\n window.addEventListener(\"load\", start, { once: true });\n }\n }\n\n // Fire-and-forget re-fetch so the controlling SW's NetworkFirst rule caches\n // the config (see controllerchange). The URL MUST match runtime-config.ts's\n // loader (`${import.meta.env.BASE_URL}powerhouse.config.json`) or the cache\n // keys won't line up.\n #warmRuntimeConfigCache() {\n void fetch(`${import.meta.env.BASE_URL}powerhouse.config.json`).catch(\n () => {},\n );\n }\n\n // Activate the waiting worker; the controllerchange handler then reloads.\n applyUpdate() {\n setUpdateAvailable(false);\n const waiting = this.registration?.waiting;\n if (!waiting) {\n // Nothing waiting (or already activated) — reload to pick up whatever\n // the active worker now serves.\n this.#reloading = true;\n window.location.reload();\n return;\n }\n this.#updateAccepted = true;\n waiting.postMessage({ type: \"SKIP_WAITING\" });\n }\n\n sendMessage(message: unknown) {\n const target =\n this.registration?.active ??\n this.registration?.waiting ??\n navigator.serviceWorker.controller;\n target?.postMessage(message);\n }\n\n // Drop any worker controlling this scope — used when offline support is\n // disabled (a disabled build also ships a self-destroying worker).\n async unregisterAll() {\n if (!(\"serviceWorker\" in navigator)) return;\n const registrations = await navigator.serviceWorker.getRegistrations();\n await Promise.all(registrations.map((r) => r.unregister()));\n }\n}\n\nexport const serviceWorkerManager = new ServiceWorkerManager();\n"],"names":["#log","#trackInstalling","#register","#warmRuntimeConfigCache","#updateAccepted","#reloading","#handleRegistration"],"mappings":"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","debug_id":"77ec84d9-1c39-5b92-a71b-ace95d8fe2d9"}
@@ -1,5 +1,5 @@
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]="0b5d030f-4d66-5a3e-abed-cda4a1fbbca6")}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]="be9976e1-6dff-5e0a-b857-091f6b5bbb32")}catch(e){}}();
3
3
  import { jsx, jsxs } from "react/jsx-runtime";
4
4
  import i18n from "i18next";
5
5
  import { initReactI18next, useTranslation } from "react-i18next";
@@ -80,6 +80,22 @@ i18n.use(initReactI18next).init({
80
80
  "title": "Your document contains errors",
81
81
  "body": "Your document contains structure errors. Do you want to export it anyway?"
82
82
  },
83
+ "openFileDocuments": {
84
+ "title_one": "Open document",
85
+ "title_other": "Open documents",
86
+ "body": "Choose the drive to import into:",
87
+ "noDrives": "No drives available yet — remote drives may still be loading. Create a drive to import into, or try again in a moment.",
88
+ "notAllowed": "Your account is not allowed to create documents in this reactor.",
89
+ "createDrive": "Create drive",
90
+ "import": "Import",
91
+ "renameAndImport": "Rename and import",
92
+ "checking": "Checking…",
93
+ "invalidFile": "File is not a valid Powerhouse document",
94
+ "unsupportedType": "Document type is not supported",
95
+ "duplicateHint": "Already in this drive — will be imported as \"{{name}}\"",
96
+ "duplicateCopyHint": "Already in this drive — a copy will be created",
97
+ "renamedHint": "Renamed to \"{{name}}\" to avoid a name clash"
98
+ },
83
99
  "disclaimer": {
84
100
  "title": "Disclaimer",
85
101
  "body": "All content provided herein our website, hyperlinked sites, associated applications, forums, blogs, social media accounts and other platforms (“Site”) is for your general information only, procured from third party sources. We make no warranties of any kind in relation to our content, including but not limited to accuracy and updatedness. No part of the content that we provide constitutes financial advice, legal advice or any other form of advice meant for your specific reliance for any purpose. Any use or reliance on our content is solely at your own risk and discretion. You should conduct your own research, review, analyse and verify our content before relying on them. Trading is a highly risky activity that can lead to major losses, please therefore consult your financial advisor before making any decision. No content on our Site is meant to be a solicitation or offer."
@@ -147,5 +163,5 @@ const ReloadConnectToast = () => {
147
163
  //#endregion
148
164
  export { i18n as i, setSentryModule as n, setUser as r, ReloadConnectToast as t };
149
165
 
150
- //# sourceMappingURL=reload-connect-toast-D1Iqw9E_.js.map
151
- //# debugId=0b5d030f-4d66-5a3e-abed-cda4a1fbbca6
166
+ //# sourceMappingURL=reload-connect-toast-BkgP9i6_.js.map
167
+ //# debugId=be9976e1-6dff-5e0a-b857-091f6b5bbb32
@@ -1 +1 @@
1
- {"version":3,"file":"reload-connect-toast-D1Iqw9E_.js","sources":["../src/i18n/locales/en.json","../src/i18n/index.ts","../src/services/sentry.ts","../src/components/reload-connect-toast.tsx"],"sourcesContent":["","import type { Resource } from \"i18next\";\nimport i18n from \"i18next\";\nimport { initReactI18next } from \"react-i18next\";\n\nimport translationEN from \"./locales/en.json\" with { type: \"json\" };\n\nconst resources: Resource = {\n en: {\n code: \"en\",\n name: \"English\",\n translation: translationEN,\n },\n};\n\ni18n\n .use(initReactI18next)\n .init({\n resources,\n fallbackLng: \"en\",\n debug: false,\n interpolation: {\n escapeValue: false,\n },\n })\n .catch((e: unknown) => {\n console.error(e);\n });\n\nexport { i18n };\nexport default i18n;\n","// Lazy Sentry accessors: the SDK (and rrweb replay) stays off the boot path\n// until useInitSentry dynamically loads it. No-ops while Sentry is disabled.\nimport type * as SentryModule from \"@sentry/react\";\n\nlet sentry: typeof SentryModule | undefined;\n\nexport function setSentryModule(mod: typeof SentryModule | undefined): void {\n sentry = mod;\n}\n\nexport function captureException(\n ...args: Parameters<typeof SentryModule.captureException>\n): void {\n sentry?.captureException(...args);\n}\n\nexport function setUser(\n ...args: Parameters<typeof SentryModule.setUser>\n): void {\n sentry?.setUser(...args);\n}\n","import { useTranslation } from \"react-i18next\";\n\nexport const ReloadConnectToast = () => {\n const { t } = useTranslation();\n\n return (\n <div>\n <p className=\"font-medium\">{t(\"notifications.reloadApp\")}</p>\n <button\n onClick={() => location.reload()}\n className=\"underline decoration-solid underline-offset-2\"\n >\n {t(\"common.reloadConnect\")} 🔄\n </button>\n </div>\n );\n};\n"],"names":["translationEN"],"mappings":";;;;;ACcA,KACG,IAAI,iBAAiB,CACrB,KAAK;CACJ,WAXwB,EAC1B,IAAI;EACF,MAAM;EACN,MAAM;EACN;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EACD,EACF;CAMG,aAAa;CACb,OAAO;CACP,eAAe,EACb,aAAa,OACd;CACF,CAAC,CACD,OAAO,MAAe;AACrB,SAAQ,MAAM,EAAE;EAChB;;;ACtBJ,IAAI;AAEJ,SAAgB,gBAAgB,KAA4C;AAC1E,UAAS;;AASX,SAAgB,QACd,GAAG,MACG;AACN,SAAQ,QAAQ,GAAG,KAAK;;;;ACjB1B,MAAa,2BAA2B;CACtC,MAAM,EAAE,MAAM,gBAAgB;AAE9B,QACE,qBAAC,OAAD,EAAA,UAAA,CACE,oBAAC,KAAD;EAAG,WAAU;YAAe,EAAE,0BAA0B;EAAK,CAAA,EAC7D,qBAAC,UAAD;EACE,eAAe,SAAS,QAAQ;EAChC,WAAU;YAFZ,CAIG,EAAE,uBAAuB,EAAC,MACpB;IACL,EAAA,CAAA","debug_id":"0b5d030f-4d66-5a3e-abed-cda4a1fbbca6"}
1
+ {"version":3,"file":"reload-connect-toast-BkgP9i6_.js","sources":["../src/i18n/locales/en.json","../src/i18n/index.ts","../src/services/sentry.ts","../src/components/reload-connect-toast.tsx"],"sourcesContent":["","import type { Resource } from \"i18next\";\nimport i18n from \"i18next\";\nimport { initReactI18next } from \"react-i18next\";\n\nimport translationEN from \"./locales/en.json\" with { type: \"json\" };\n\nconst resources: Resource = {\n en: {\n code: \"en\",\n name: \"English\",\n translation: translationEN,\n },\n};\n\ni18n\n .use(initReactI18next)\n .init({\n resources,\n fallbackLng: \"en\",\n debug: false,\n interpolation: {\n escapeValue: false,\n },\n })\n .catch((e: unknown) => {\n console.error(e);\n });\n\nexport { i18n };\nexport default i18n;\n","// Lazy Sentry accessors: the SDK (and rrweb replay) stays off the boot path\n// until useInitSentry dynamically loads it. No-ops while Sentry is disabled.\nimport type * as SentryModule from \"@sentry/react\";\n\nlet sentry: typeof SentryModule | undefined;\n\nexport function setSentryModule(mod: typeof SentryModule | undefined): void {\n sentry = mod;\n}\n\nexport function captureException(\n ...args: Parameters<typeof SentryModule.captureException>\n): void {\n sentry?.captureException(...args);\n}\n\nexport function setUser(\n ...args: Parameters<typeof SentryModule.setUser>\n): void {\n sentry?.setUser(...args);\n}\n","import { useTranslation } from \"react-i18next\";\n\nexport const ReloadConnectToast = () => {\n const { t } = useTranslation();\n\n return (\n <div>\n <p className=\"font-medium\">{t(\"notifications.reloadApp\")}</p>\n <button\n onClick={() => location.reload()}\n className=\"underline decoration-solid underline-offset-2\"\n >\n {t(\"common.reloadConnect\")} 🔄\n </button>\n </div>\n );\n};\n"],"names":["translationEN"],"mappings":";;;;;ACcA,KACG,IAAI,iBAAiB,CACrB,KAAK;CACJ,WAXwB,EAC1B,IAAI;EACF,MAAM;EACN,MAAM;EACN;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EACD,EACF;CAMG,aAAa;CACb,OAAO;CACP,eAAe,EACb,aAAa,OACd;CACF,CAAC,CACD,OAAO,MAAe;AACrB,SAAQ,MAAM,EAAE;EAChB;;;ACtBJ,IAAI;AAEJ,SAAgB,gBAAgB,KAA4C;AAC1E,UAAS;;AASX,SAAgB,QACd,GAAG,MACG;AACN,SAAQ,QAAQ,GAAG,KAAK;;;;ACjB1B,MAAa,2BAA2B;CACtC,MAAM,EAAE,MAAM,gBAAgB;AAE9B,QACE,qBAAC,OAAD,EAAA,UAAA,CACE,oBAAC,KAAD;EAAG,WAAU;YAAe,EAAE,0BAA0B;EAAK,CAAA,EAC7D,qBAAC,UAAD;EACE,eAAe,SAAS,QAAQ;EAChC,WAAU;YAFZ,CAIG,EAAE,uBAAuB,EAAC,MACpB;IACL,EAAA,CAAA","debug_id":"be9976e1-6dff-5e0a-b857-091f6b5bbb32"}
@@ -5,7 +5,7 @@ import { createRoot } from "react-dom/client";
5
5
  import { jsx } from "react/jsx-runtime";
6
6
  //#region start-connect.tsx
7
7
  await loadRuntimeConfig();
8
- const { AppLoader } = await import("./components-xBFneZuJ.js");
8
+ const { AppLoader } = await import("./components-BDpsXnOO.js");
9
9
  function updateLocalPackage(pkg) {
10
10
  window.ph?.vetraPackageManager?.updateLocalPackage(pkg);
11
11
  }
package/dist/style.css CHANGED
@@ -474,6 +474,9 @@
474
474
  .z-50 {
475
475
  z-index: 50;
476
476
  }
477
+ .z-200 {
478
+ z-index: 200;
479
+ }
477
480
  .z-1000 {
478
481
  z-index: 1000;
479
482
  }
@@ -858,9 +861,6 @@
858
861
  .h-\[420px\] {
859
862
  height: 420px;
860
863
  }
861
- .h-\[500px\] {
862
- height: 500px;
863
- }
864
864
  .h-\[600px\] {
865
865
  height: 600px;
866
866
  }
@@ -909,6 +909,9 @@
909
909
  .max-h-\[404px\] {
910
910
  max-height: 404px;
911
911
  }
912
+ .max-h-\[calc\(100dvh-14rem\)\] {
913
+ max-height: calc(100dvh - 14rem);
914
+ }
912
915
  .max-h-full {
913
916
  max-height: 100%;
914
917
  }
@@ -1638,6 +1641,9 @@
1638
1641
  .border-b-border {
1639
1642
  border-bottom-color: var(--border);
1640
1643
  }
1644
+ .bg-accent {
1645
+ background-color: var(--accent);
1646
+ }
1641
1647
  .bg-background {
1642
1648
  background-color: var(--background);
1643
1649
  }
@@ -2920,6 +2926,13 @@
2920
2926
  }
2921
2927
  }
2922
2928
  }
2929
+ .hover\:bg-accent {
2930
+ &:hover {
2931
+ @media (hover: hover) {
2932
+ background-color: var(--accent);
2933
+ }
2934
+ }
2935
+ }
2923
2936
  .hover\:bg-muted {
2924
2937
  &:hover {
2925
2938
  @media (hover: hover) {
@@ -1,5 +1,5 @@
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]="9ee5aa7b-b29e-5c77-bcea-8b57b1fbb493")}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]="70c9da16-68cb-54a4-9662-dd9a799742d5")}catch(e){}}();
3
3
  import { createElement } from "react";
4
4
  import { ToastContainer, toast } from "@powerhousedao/design-system/connect/toast";
5
5
  //#region src/services/toast.ts
@@ -19,5 +19,5 @@ function toast$1(content, options) {
19
19
  //#endregion
20
20
  export { toast$1 as n, ToastContainer$1 as t };
21
21
 
22
- //# sourceMappingURL=toast-4t-VimvD.js.map
23
- //# debugId=9ee5aa7b-b29e-5c77-bcea-8b57b1fbb493
22
+ //# sourceMappingURL=toast-BLv8rjmy.js.map
23
+ //# debugId=70c9da16-68cb-54a4-9662-dd9a799742d5
@@ -1 +1 @@
1
- {"version":3,"file":"toast-4t-VimvD.js","sources":["../src/services/toast.ts"],"sourcesContent":["import type { ConnectToastOptions } from \"@powerhousedao/design-system/connect/toast\";\nimport {\n ToastContainer as BaseToastContainer,\n toast as baseToast,\n} from \"@powerhousedao/design-system/connect/toast\";\nimport { createElement, type ComponentProps } from \"react\";\n\nexport const CONNECT_TOAST_CONTAINER_ID = \"connect\";\n\ntype BaseToastContainerProps = ComponentProps<typeof BaseToastContainer>;\n\nexport const ToastContainer = (\n props: Omit<BaseToastContainerProps, \"containerId\"> = {},\n) =>\n createElement(BaseToastContainer, {\n containerId: CONNECT_TOAST_CONTAINER_ID,\n ...props,\n });\n\ntype ToastArgs = Parameters<typeof baseToast>;\nexport function toast(content: ToastArgs[0], options?: ConnectToastOptions) {\n const {\n type = \"default\",\n containerId = CONNECT_TOAST_CONTAINER_ID,\n ...restOptions\n } = options || {};\n return baseToast(content, { type, containerId, ...restOptions });\n}\n"],"names":["ToastContainer","BaseToastContainer","toast","baseToast"],"mappings":";;;;;AAOA,MAAa,6BAA6B;AAI1C,MAAaA,oBACX,QAAsD,EAAE,KAExD,cAAcC,gBAAoB;CAChC,aAAa;CACb,GAAG;CACJ,CAAC;AAGJ,SAAgBC,QAAM,SAAuB,SAA+B;CAC1E,MAAM,EACJ,OAAO,WACP,cAAc,4BACd,GAAG,gBACD,WAAW,EAAE;AACjB,QAAOC,MAAU,SAAS;EAAE;EAAM;EAAa,GAAG;EAAa,CAAC","debug_id":"9ee5aa7b-b29e-5c77-bcea-8b57b1fbb493"}
1
+ {"version":3,"file":"toast-BLv8rjmy.js","sources":["../src/services/toast.ts"],"sourcesContent":["import type { ConnectToastOptions } from \"@powerhousedao/design-system/connect/toast\";\nimport {\n ToastContainer as BaseToastContainer,\n toast as baseToast,\n} from \"@powerhousedao/design-system/connect/toast\";\nimport { createElement, type ComponentProps } from \"react\";\n\nexport const CONNECT_TOAST_CONTAINER_ID = \"connect\";\n\ntype BaseToastContainerProps = ComponentProps<typeof BaseToastContainer>;\n\nexport const ToastContainer = (\n props: Omit<BaseToastContainerProps, \"containerId\"> = {},\n) =>\n createElement(BaseToastContainer, {\n containerId: CONNECT_TOAST_CONTAINER_ID,\n ...props,\n });\n\ntype ToastArgs = Parameters<typeof baseToast>;\nexport function toast(content: ToastArgs[0], options?: ConnectToastOptions) {\n const {\n type = \"default\",\n containerId = CONNECT_TOAST_CONTAINER_ID,\n ...restOptions\n } = options || {};\n return baseToast(content, { type, containerId, ...restOptions });\n}\n"],"names":["ToastContainer","BaseToastContainer","toast","baseToast"],"mappings":";;;;;AAOA,MAAa,6BAA6B;AAI1C,MAAaA,oBACX,QAAsD,EAAE,KAExD,cAAcC,gBAAoB;CAChC,aAAa;CACb,GAAG;CACJ,CAAC;AAGJ,SAAgBC,QAAM,SAAuB,SAA+B;CAC1E,MAAM,EACJ,OAAO,WACP,cAAc,4BACd,GAAG,gBACD,WAAW,EAAE;AACjB,QAAOC,MAAU,SAAS;EAAE;EAAM;EAAa,GAAG;EAAa,CAAC","debug_id":"70c9da16-68cb-54a4-9662-dd9a799742d5"}
@@ -0,0 +1,314 @@
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){}}();
3
+ import { n as getRuntimeConfig } from "./runtime-config-DL3QjcfM.js";
4
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
5
+ import { getPackagePage, getPackagesForDocumentType, trimTrailingSlash, useVetraPackageManager } from "@powerhousedao/reactor-browser";
6
+ import { slimManifest } from "@powerhousedao/shared/registry/manifest-slim";
7
+ //#region src/hooks/useRegistryPackages.ts
8
+ /** Page size for the paginated Available-packages listing. */
9
+ const AVAILABLE_PAGE_SIZE = 30;
10
+ function useRegistryPackages() {
11
+ const packageManager = useVetraPackageManager();
12
+ const packageManagerPackages = packageManager?.packages;
13
+ const registryUrl = getRuntimeConfig().packageRegistryUrl ?? null;
14
+ const [registryPackagesMap, setRegistryPackagesMap] = useBestEffortLocalStorage(`REGISTRY_PACKAGES:${registryUrl === null ? null : trimTrailingSlash(registryUrl)}`, {});
15
+ const registryPackageList = useMemo(() => {
16
+ return Array.from(Object.values(registryPackagesMap)).filter((p) => p !== void 0);
17
+ }, [registryPackagesMap]);
18
+ const installedPackages = useMemo(() => registryPackageList.filter((p) => p.status === "local-install" || p.status === "registry-install"), [registryPackageList]);
19
+ const [availableOrder, setAvailableOrder] = useState([]);
20
+ const [availableTotal, setAvailableTotal] = useState(null);
21
+ const [availableHasMore, setAvailableHasMore] = useState(false);
22
+ const [isLoadingAvailable, setIsLoadingAvailable] = useState(false);
23
+ const [isLoadingMoreAvailable, setIsLoadingMoreAvailable] = useState(false);
24
+ const [availableError, setAvailableError] = useState(false);
25
+ const availableQueryRef = useRef("");
26
+ const nextOffsetRef = useRef(0);
27
+ const requestGenerationRef = useRef(0);
28
+ const debounceRef = useRef(null);
29
+ const availablePackages = useMemo(() => availableOrder.map((name) => registryPackagesMap[name]).filter((p) => p !== void 0 && (p.status === "available" || p.status === "dismissed")), [availableOrder, registryPackagesMap]);
30
+ const fetchAvailablePage = useCallback(async ({ reset }) => {
31
+ if (registryUrl === null || !packageManager) return;
32
+ const generation = ++requestGenerationRef.current;
33
+ const offset = reset ? 0 : nextOffsetRef.current;
34
+ const search = availableQueryRef.current;
35
+ if (reset) setIsLoadingAvailable(true);
36
+ else setIsLoadingMoreAvailable(true);
37
+ setAvailableError(false);
38
+ try {
39
+ const page = await getPackagePage(registryUrl, {
40
+ limit: AVAILABLE_PAGE_SIZE,
41
+ offset,
42
+ search: search || void 0
43
+ });
44
+ if (generation !== requestGenerationRef.current) return;
45
+ setRegistryPackagesMap((oldPackages) => {
46
+ const next = { ...oldPackages };
47
+ for (const item of page.items) {
48
+ const existing = next[item.name];
49
+ if (!existing) {
50
+ const status = getPackageStatusFromPackageSource(packageManager.getPackageSource(item.name));
51
+ next[item.name] = makeRegistryPackageFromListItem(item, status);
52
+ } else next[item.name] = {
53
+ ...existing,
54
+ version: packageManager.getPackageVersion(item.name) ?? item.version ?? existing.version,
55
+ status: promoteStatus(existing.status, packageManager.getPackageSource(item.name))
56
+ };
57
+ }
58
+ return next;
59
+ });
60
+ setAvailableOrder((prev) => {
61
+ const base = reset ? [] : prev;
62
+ const seen = new Set(base);
63
+ const merged = [...base];
64
+ for (const item of page.items) if (!seen.has(item.name)) {
65
+ seen.add(item.name);
66
+ merged.push(item.name);
67
+ }
68
+ return merged;
69
+ });
70
+ nextOffsetRef.current = offset + page.items.length;
71
+ setAvailableTotal(page.total);
72
+ setAvailableHasMore(page.hasMore);
73
+ } catch (error) {
74
+ if (generation !== requestGenerationRef.current) return;
75
+ console.error(error);
76
+ setAvailableError(true);
77
+ } finally {
78
+ if (generation === requestGenerationRef.current) {
79
+ setIsLoadingAvailable(false);
80
+ setIsLoadingMoreAvailable(false);
81
+ }
82
+ }
83
+ }, [
84
+ registryUrl,
85
+ packageManager,
86
+ setRegistryPackagesMap
87
+ ]);
88
+ /** Debounced server search — resets to page 1 for the new query. */
89
+ const setAvailableSearch = useCallback((query) => {
90
+ availableQueryRef.current = query;
91
+ if (debounceRef.current) clearTimeout(debounceRef.current);
92
+ debounceRef.current = setTimeout(() => {
93
+ fetchAvailablePage({ reset: true });
94
+ }, 300);
95
+ }, [fetchAvailablePage]);
96
+ /** Load the next page (infinite scroll). No-op when exhausted/busy. */
97
+ const loadMoreAvailable = useCallback(() => {
98
+ if (!availableHasMore || isLoadingAvailable || isLoadingMoreAvailable) return;
99
+ fetchAvailablePage({ reset: false });
100
+ }, [
101
+ availableHasMore,
102
+ isLoadingAvailable,
103
+ isLoadingMoreAvailable,
104
+ fetchAvailablePage
105
+ ]);
106
+ /**
107
+ * Load page 1 the first time the Available tab is opened. Re-opening keeps
108
+ * the accumulated pages; a fetch error leaves the panel's Retry to re-fetch
109
+ * (this guard avoids auto-retry loops on tab re-open).
110
+ */
111
+ function ensureAvailableLoaded() {
112
+ if (availableOrder.length > 0 || isLoadingAvailable || availableError) return;
113
+ fetchAvailablePage({ reset: true });
114
+ }
115
+ /**
116
+ * Fetch full package info for a document type (via the legacy
117
+ * `?documentType=` filter) and merge into the map. Lets MissingPackageModal
118
+ * offer installs without loading the whole paginated listing.
119
+ */
120
+ const fetchPackagesByDocumentType = useCallback(async (documentType) => {
121
+ if (registryUrl === null || !packageManager) return [];
122
+ try {
123
+ const infos = await getPackagesForDocumentType(registryUrl, documentType);
124
+ setRegistryPackagesMap((oldPackages) => {
125
+ const next = { ...oldPackages };
126
+ for (const info of infos) {
127
+ const existing = next[info.name];
128
+ const status = getPackageStatusFromPackageSource(packageManager.getPackageSource(info.name));
129
+ next[info.name] = existing ? {
130
+ ...existing,
131
+ status: promoteStatus(existing.status, packageManager.getPackageSource(info.name))
132
+ } : makeRegistryPackageFromPackageInfo(info, status);
133
+ }
134
+ return next;
135
+ });
136
+ return infos.map((info) => makeRegistryPackageFromPackageInfo(info, getPackageStatusFromPackageSource(packageManager.getPackageSource(info.name))));
137
+ } catch (error) {
138
+ console.error(error);
139
+ return [];
140
+ }
141
+ }, [
142
+ registryUrl,
143
+ packageManager,
144
+ setRegistryPackagesMap
145
+ ]);
146
+ useEffect(() => () => {
147
+ if (debounceRef.current) clearTimeout(debounceRef.current);
148
+ }, []);
149
+ useEffect(() => {
150
+ if (!packageManager) return;
151
+ if (packageManagerPackages?.length) for (const packageManagerPackage of packageManagerPackages) setRegistryPackagesMap((existingRegistryPackages) => {
152
+ const packageName = packageManagerPackage.manifest.name;
153
+ const existingPackage = existingRegistryPackages[packageName];
154
+ const newRegistryPackages = { ...existingRegistryPackages };
155
+ const version = packageManager.getPackageVersion(packageName);
156
+ if (existingPackage) newRegistryPackages[packageName] = {
157
+ ...existingPackage,
158
+ version: version ?? existingPackage.version,
159
+ status: promoteStatus(existingPackage.status, packageManager.getPackageSource(packageName))
160
+ };
161
+ else newRegistryPackages[packageName] = makeRegistryPackageFromDocumentModelLib(packageManagerPackage, getPackageStatusFromPackageSource(packageManager.getPackageSource(packageName)), version);
162
+ return newRegistryPackages;
163
+ });
164
+ }, [packageManagerPackages]);
165
+ function updateRegistryPackageStatus(packageName, newStatus) {
166
+ setRegistryPackagesMap((oldRegistryPackages) => {
167
+ const newRegistryPackages = { ...oldRegistryPackages };
168
+ const newRegistryPackage = newRegistryPackages[packageName];
169
+ if (!newRegistryPackage) {
170
+ console.error("Attempting to update status for package that does not exist.");
171
+ return newRegistryPackages;
172
+ }
173
+ newRegistryPackages[packageName] = {
174
+ ...newRegistryPackage,
175
+ status: newStatus
176
+ };
177
+ return newRegistryPackages;
178
+ });
179
+ }
180
+ /**
181
+ * Register a freshly-installed package that came in via the npm-uplink
182
+ * fallback — the user typed a bare name, our local `/packages` didn't know
183
+ * it, but the install succeeded because verdaccio proxy-fetched the tarball.
184
+ *
185
+ * This is the one legitimate case where the status update runs against a
186
+ * name that wasn't in the registry map. We treat it as an insert rather
187
+ * than logging the "does not exist" error. Data is pulled from the loaded
188
+ * module so the UI card shows the real manifest immediately; the next
189
+ * `/packages` refresh will add `versions`/`distTags`.
190
+ */
191
+ function registerFallbackRegistryPackage(packageName, loadedPackage, version, status) {
192
+ setRegistryPackagesMap((oldRegistryPackages) => {
193
+ const newRegistryPackages = { ...oldRegistryPackages };
194
+ newRegistryPackages[packageName] = {
195
+ ...makeRegistryPackageFromDocumentModelLib(loadedPackage, status, version),
196
+ name: packageName
197
+ };
198
+ return newRegistryPackages;
199
+ });
200
+ }
201
+ return {
202
+ registryPackagesMap,
203
+ registryPackageList,
204
+ installedPackages,
205
+ availablePackages,
206
+ availableTotal,
207
+ availableHasMore,
208
+ isLoadingAvailable,
209
+ isLoadingMoreAvailable,
210
+ availableError,
211
+ ensureAvailableLoaded,
212
+ fetchAvailablePage,
213
+ loadMoreAvailable,
214
+ setAvailableSearch,
215
+ fetchPackagesByDocumentType,
216
+ updateRegistryPackageStatus,
217
+ registerFallbackRegistryPackage
218
+ };
219
+ }
220
+ /**
221
+ * Build a RegistryPackage from a trimmed paginated list item. Version metadata
222
+ * (distTags/versions) and documentTypes are absent — the row lazy-loads them.
223
+ */
224
+ function makeRegistryPackageFromListItem(item, status) {
225
+ return {
226
+ name: item.name,
227
+ path: item.path,
228
+ documentTypes: [],
229
+ version: item.version,
230
+ status,
231
+ manifest: {
232
+ name: item.name,
233
+ ...item.description !== void 0 ? { description: item.description } : {},
234
+ ...item.category !== void 0 ? { category: item.category } : {},
235
+ ...item.publisher !== void 0 ? { publisher: item.publisher } : {}
236
+ }
237
+ };
238
+ }
239
+ function makeRegistryPackageFromDocumentModelLib(documentModelLib, status, version) {
240
+ return {
241
+ name: documentModelLib.manifest.name,
242
+ path: "stub-path",
243
+ documentTypes: documentModelLib.documentModels.map((d) => d.documentModel.global.id),
244
+ status,
245
+ manifest: slimManifest(documentModelLib.manifest),
246
+ version
247
+ };
248
+ }
249
+ function makeRegistryPackageFromPackageInfo(packageInfo, status) {
250
+ return {
251
+ ...packageInfo,
252
+ manifest: slimManifest(packageInfo.manifest),
253
+ documentTypes: packageInfo.manifest?.documentModels?.map((d) => d.id) ?? [],
254
+ status
255
+ };
256
+ }
257
+ /**
258
+ * Like usehooks-ts' useLocalStorage, but persistence is best-effort: a failed
259
+ * `setItem` (e.g. QuotaExceededError on an oversized payload) keeps the
260
+ * in-memory state so the package manager still works for the session.
261
+ * useLocalStorage couples the state update to the write — when the write
262
+ * threw, the freshly fetched package list was discarded and the registry UI
263
+ * rendered (and searched) an empty list.
264
+ *
265
+ * The key is derived from the boot-time runtime config and never changes
266
+ * within a session, so no key-change rehydration is needed.
267
+ */
268
+ function useBestEffortLocalStorage(key, initialValue) {
269
+ const [value, setValue] = useState(() => readJsonFromStorage(key) ?? initialValue);
270
+ useEffect(() => {
271
+ try {
272
+ window.localStorage.setItem(key, JSON.stringify(value));
273
+ } catch (error) {
274
+ try {
275
+ window.localStorage.removeItem(key);
276
+ window.localStorage.setItem(key, JSON.stringify(value));
277
+ } catch {
278
+ console.warn(`Failed to persist "${key}" to localStorage; continuing with in-memory data.`, error);
279
+ }
280
+ }
281
+ }, [key, value]);
282
+ return [value, setValue];
283
+ }
284
+ function readJsonFromStorage(key) {
285
+ try {
286
+ const raw = window.localStorage.getItem(key);
287
+ return raw === null ? null : JSON.parse(raw);
288
+ } catch {
289
+ return null;
290
+ }
291
+ }
292
+ /**
293
+ * When refreshing a cached entry, promote `"available"` to whatever the
294
+ * packageManager now reports — the cached `"available"` was almost certainly
295
+ * recorded before `packageManager.addPackages()` finished on a prior session.
296
+ * Never downgrade an already-installed entry, and never overwrite a deliberate
297
+ * `"dismissed"` choice.
298
+ */
299
+ function promoteStatus(cachedStatus, packageSource) {
300
+ if (cachedStatus !== "available") return cachedStatus;
301
+ if (packageSource === null) return cachedStatus;
302
+ return getPackageStatusFromPackageSource(packageSource);
303
+ }
304
+ function getPackageStatusFromPackageSource(packageSource) {
305
+ if (packageSource === null) return "available";
306
+ if (packageSource === "local-install" || packageSource === "common" || packageSource === "project") return "local-install";
307
+ if (packageSource === "registry-install") return "registry-install";
308
+ return "available";
309
+ }
310
+ //#endregion
311
+ export { useRegistryPackages as t };
312
+
313
+ //# sourceMappingURL=useRegistryPackages-DMhCvTWq.js.map
314
+ //# debugId=a2bca0ce-adce-512d-a646-5adf41d1dd3f