@powerhousedao/reactor-browser 6.2.2-dev.53 → 6.2.2-dev.54

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/dist/{attachment-service-BaLIapiL.d.ts → attachment-service-DTFJRf5j.d.ts} +10 -9
  2. package/dist/attachment-service-DTFJRf5j.d.ts.map +1 -0
  3. package/dist/{client-s_ISz_Zs.js → client-DB8gP4hz.js} +50 -10
  4. package/dist/client-DB8gP4hz.js.map +1 -0
  5. package/dist/{client-BaHKLGy5.d.ts → client-DjkEpwu_.d.ts} +2 -2
  6. package/dist/{client-BaHKLGy5.d.ts.map → client-DjkEpwu_.d.ts.map} +1 -1
  7. package/dist/{document-operations-VigJPOEe.js → document-operations-C6nce9dH.js} +12 -26
  8. package/dist/document-operations-C6nce9dH.js.map +1 -0
  9. package/dist/{global-CbyAMlZd.d.ts → global-pg5gy2eZ.d.ts} +2 -2
  10. package/dist/{global-CbyAMlZd.d.ts.map → global-pg5gy2eZ.d.ts.map} +1 -1
  11. package/dist/{index-DPq1VjpB.d.ts → index-DjloxNSR.d.ts} +2 -2
  12. package/dist/{index-DPq1VjpB.d.ts.map → index-DjloxNSR.d.ts.map} +1 -1
  13. package/dist/index.d.ts +14 -8
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +12 -6
  16. package/dist/index.js.map +1 -1
  17. package/dist/src/graphql/client.d.ts +2 -2
  18. package/dist/src/graphql/client.js +1 -1
  19. package/dist/src/graphql-client/entry.d.ts +3 -3
  20. package/dist/src/graphql-client/entry.js +1 -1
  21. package/dist/src/renown/index.d.ts +1 -1
  22. package/dist/src/rpc/index.d.ts +1 -0
  23. package/dist/src/rpc/index.d.ts.map +1 -1
  24. package/dist/src/rpc/index.js +4 -0
  25. package/dist/src/rpc/index.js.map +1 -1
  26. package/dist/{types-Bitg5Z5j.d.ts → types-4rfAFZQd.d.ts} +64 -8
  27. package/dist/types-4rfAFZQd.d.ts.map +1 -0
  28. package/package.json +9 -9
  29. package/dist/attachment-service-BaLIapiL.d.ts.map +0 -1
  30. package/dist/client-s_ISz_Zs.js.map +0 -1
  31. package/dist/document-operations-VigJPOEe.js.map +0 -1
  32. package/dist/types-Bitg5Z5j.d.ts.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-operations-C6nce9dH.js","names":["addFolder","baseAddFolder","baseMoveNode","moveNode","copyNode","baseCopyNode","createClient","GqlDocumentChangeType","GqlPropagationMode"],"sources":["../src/errors.ts","../src/hooks/modals.ts","../src/utils/documents.ts","../src/utils/user.ts","../src/actions/document.ts","../src/remote-controller/utils.ts","../src/graphql-client/adapter.ts","../src/graphql-client/auth.ts","../src/graphql-client/operations.ts","../src/graphql-client/signing.ts","../src/graphql-client/static-package-manager.ts","../src/graphql-client/subgraph.ts","../src/graphql-client/subscriptions.ts","../src/graphql-client/graphql-reactor-client.ts","../src/hooks/config/editor.ts","../src/hooks/config/connect.ts","../src/hooks/attachment-service.ts","../src/hooks/features.ts","../src/utils/url.ts","../src/hooks/drives.ts","../src/hooks/set-selected-node.ts","../src/hooks/selected-drive.ts","../src/hooks/use-drop-target.ts","../src/hooks/node-drag-and-drop.ts","../src/hooks/graphql-reactor-client.ts","../src/hooks/package-discovery.ts","../src/hooks/reactor.ts","../src/hooks/revision-history.ts","../src/utils/nodes.ts","../src/hooks/items-in-selected-drive.ts","../src/hooks/selected-node.ts","../src/hooks/selected-timeline-item.ts","../src/hooks/timeline-revision.ts","../src/hooks/toast.ts","../src/hooks/vetra-packages.ts","../src/hooks/add-ph-event-handlers.ts","../src/graphql-client/graphql-reactor-provider.tsx","../src/hooks/document-model-modules.ts","../src/hooks/document-operations.ts"],"sourcesContent":["export class UnsupportedDocumentTypeError extends Error {\n constructor(documentType: string) {\n super(`Document type ${documentType} is not supported`);\n this.name = \"UnsupportedDocumentTypeError\";\n }\n\n static isError(error: unknown): error is UnsupportedDocumentTypeError {\n return (\n Error.isError(error) && error.name === \"UnsupportedDocumentTypeError\"\n );\n }\n}\n\nexport class DocumentNotFoundError extends Error {\n constructor(documentId: string) {\n super(`Document with id ${documentId} not found`);\n }\n}\n\nexport class DocumentModelNotFoundError extends Error {\n readonly documentType: string;\n readonly name = \"DocumentModelNotFoundError\";\n\n constructor(documentType: string) {\n super(`Document model module for type ${documentType} not found`);\n this.documentType = documentType;\n }\n\n static isError(error: unknown): error is DocumentModelNotFoundError {\n return Error.isError(error) && error.name === \"DocumentModelNotFoundError\";\n }\n}\n\nexport class DocumentTypeMismatchError extends Error {\n constructor(documentId: string, expectedType: string, actualType: string) {\n super(\n `Document ${documentId} is not of type ${expectedType}. Actual type: ${actualType}`,\n );\n }\n}\n\nexport class NoSelectedDocumentError extends Error {\n constructor() {\n super(\n \"There is no selected document. Did you mean to call 'useSelectedDocumentSafe' instead?\",\n );\n }\n}\n","import type { PHModal } from \"@powerhousedao/reactor-browser\";\nimport type { Node } from \"@powerhousedao/shared/document-drive\";\nimport { makePHEventFunctions } from \"./make-ph-event-functions.js\";\n\nconst modalEventFunctions = makePHEventFunctions(\"modal\");\n\n/** Returns the current modal */\nexport const usePHModal = modalEventFunctions.useValue;\n\n/** Sets the current modal */\nexport const setPHModal = modalEventFunctions.setValue;\n\n/** Adds an event handler for the modal */\nexport const addModalEventHandler = modalEventFunctions.addEventHandler;\n\n/** Shows a modal */\nexport function showPHModal(modal: PHModal) {\n setPHModal(modal);\n}\n\n/** Closes the current modal */\nexport function closePHModal() {\n setPHModal(undefined);\n}\n\n/** Shows the create document modal */\nexport function showCreateDocumentModal(\n documentType: string,\n documentModelVersion?: number,\n) {\n setPHModal({\n type: \"createDocument\",\n documentType,\n ...(documentModelVersion !== undefined && { documentModelVersion }),\n });\n}\n\n/** Shows the delete node modal */\nexport function showDeleteNodeModal(nodeOrId: Node | string) {\n const id = typeof nodeOrId === \"string\" ? nodeOrId : nodeOrId.id;\n setPHModal({ type: \"deleteItem\", id });\n}\n","export function isDocumentTypeSupported(\n documentType: string,\n supportedDocuments: string[] | null | undefined,\n): boolean {\n if (!supportedDocuments?.length) {\n return true;\n }\n\n return supportedDocuments.some((pattern) => {\n // Path wildcard: \"powerhouse/*\"\n if (pattern.endsWith(\"/*\")) {\n const prefix = pattern.slice(0, -2);\n return documentType.startsWith(prefix + \"/\");\n }\n\n // Prefix wildcard: \"power*\"\n if (pattern.endsWith(\"*\") && !pattern.endsWith(\"/*\")) {\n const prefix = pattern.slice(0, -1);\n return documentType.startsWith(prefix);\n }\n\n // Exact match\n return pattern === documentType;\n });\n}\n","export function getUserPermissions() {\n const user = window.ph?.renown?.user;\n const allowList = window.ph?.allowList;\n if (!allowList) {\n return {\n isAllowedToCreateDocuments: true,\n isAllowedToEditDocuments: true,\n };\n }\n return {\n isAllowedToCreateDocuments: allowList.includes(user?.address ?? \"\"),\n isAllowedToEditDocuments: allowList.includes(user?.address ?? \"\"),\n };\n}\n","import type { IReactorClient } from \"@powerhousedao/reactor\";\nimport type {\n ConflictResolution,\n DocumentTypeIcon,\n FileUploadProgressCallback,\n IReactorBrowserClient,\n} from \"@powerhousedao/reactor-browser\";\nimport type {\n DocumentDriveDocument,\n Node,\n} from \"@powerhousedao/shared/document-drive\";\nimport {\n addFolder as baseAddFolder,\n copyNode as baseCopyNode,\n moveNode as baseMoveNode,\n updateFile as baseUpdateFile,\n generateNodesCopy,\n handleTargetNameCollisions,\n isFileNode,\n isFolderNode,\n updateNode,\n} from \"@powerhousedao/shared/document-drive\";\nimport type {\n DocumentModelModule,\n DocumentOperations,\n Operation,\n PHBaseState,\n PHDocument,\n Reducer,\n VersionedReplayConfig,\n} from \"@powerhousedao/shared/document-model\";\nimport {\n assertAuthPreservedOnDuplicate,\n baseLoadFromInput,\n baseLoadFromInputVersioned,\n baseSaveToFileHandle,\n createPresignedHeader,\n createZip,\n documentModelDocumentType,\n generateId,\n replayDocumentVersioned,\n setName,\n setPreferredEditor,\n UnsupportedDocumentModelVersionError,\n type UpgradeDocumentActionInput,\n} from \"@powerhousedao/shared/document-model\";\nimport { logger } from \"document-model\";\nimport { conditional, constant, isDefined, isNot, isStrictEqual } from \"remeda\";\nimport {\n DocumentModelNotFoundError,\n UnsupportedDocumentTypeError,\n} from \"../errors.js\";\nimport { showPHModal } from \"../hooks/modals.js\";\nimport { isDocumentTypeSupported } from \"../utils/documents.js\";\nimport { getUserPermissions } from \"../utils/user.js\";\nimport { queueActions, queueOperations, uploadOperations } from \"./queue.js\";\n\nconst NON_DOMAIN_SCOPES = new Set([\"auth\", \"document\"]);\n\nasync function isDocumentInLocation(\n document: PHDocument,\n driveId: string,\n parentFolder?: string,\n): Promise<{\n isDuplicate: boolean;\n duplicateType?: \"id\" | \"name\";\n nodeId?: string;\n}> {\n const reactorClient = window.ph?.reactorClient;\n if (!reactorClient) {\n return { isDuplicate: false };\n }\n\n // Get the drive and check its nodes\n let drive;\n try {\n drive = await reactorClient.get<DocumentDriveDocument>(driveId);\n } catch {\n return { isDuplicate: false };\n }\n\n // Case 1: Check for duplicate by ID\n const nodeById = drive.state.global.nodes.find(\n (node: { id: string }) => node.id === document.header.id,\n );\n\n if (nodeById && nodeById.parentFolder === (parentFolder ?? null)) {\n return {\n isDuplicate: true,\n duplicateType: \"id\",\n nodeId: nodeById.id,\n };\n }\n\n // Case 2: Check for duplicate by name + type in same parent folder\n const nodeByNameAndType = drive.state.global.nodes.find(\n (node: Node) =>\n isFileNode(node) &&\n node.name === document.header.name &&\n node.documentType === document.header.documentType &&\n node.parentFolder === (parentFolder ?? null),\n );\n\n if (nodeByNameAndType) {\n return {\n isDuplicate: true,\n duplicateType: \"name\",\n nodeId: nodeByNameAndType.id,\n };\n }\n\n return { isDuplicate: false };\n}\n\nfunction getDocumentTypeIcon(\n document: PHDocument,\n): DocumentTypeIcon | undefined {\n const documentType = document.header.documentType;\n\n switch (documentType) {\n case \"powerhouse/document-model\":\n return \"document-model\";\n case \"powerhouse/app\":\n return \"app\";\n case \"powerhouse/document-editor\":\n return \"editor\";\n case \"powerhouse/subgraph\":\n return \"subgraph\";\n case \"powerhouse/package\":\n return \"package\";\n case \"powerhouse/processor\": {\n // Check the processor type from global state (safely)\n const globalState = (document.state as { global?: { type?: string } })\n .global;\n const processorType = globalState?.type;\n\n if (processorType === \"analytics\") return \"analytics-processor\";\n if (processorType === \"relational\") return \"relational-processor\";\n if (processorType === \"codegen\") return \"codegen-processor\";\n return undefined;\n }\n default:\n return undefined;\n }\n}\n\nexport async function downloadFile(document: PHDocument, fileName: string) {\n try {\n const data = await createZip(document);\n const blob = new Blob([new Uint8Array(data)], { type: \"application/zip\" });\n const link = window.document.createElement(\"a\");\n link.style.display = \"none\";\n link.href = URL.createObjectURL(blob);\n link.download = fileName;\n\n window.document.body.appendChild(link);\n link.click();\n\n window.document.body.removeChild(link);\n } catch (e) {\n logger.error(e instanceof Error ? e.message : String(e));\n }\n}\n\nasync function getDocumentExtension(document: PHDocument): Promise<string> {\n const documentType = document.header.documentType;\n\n let rawExtension: string | undefined;\n\n if (documentType === documentModelDocumentType) {\n const globalState = (document.state as { global?: { extension?: string } })\n .global;\n rawExtension = globalState?.extension;\n } else {\n // document model modules are only available on the full reactor client\n const reactorClient = window.ph?.reactorClientModule?.client;\n if (reactorClient) {\n const { results: documentModelModules } =\n await reactorClient.getDocumentModelModules();\n const module = documentModelModules.find(\n (m: DocumentModelModule) => m.documentModel.global.id === documentType,\n );\n rawExtension = module?.utils.fileExtension;\n }\n }\n\n return (rawExtension ?? \"\").replace(/^\\.+|\\.+$/g, \"\");\n}\n\n/**\n * Fetches all operations for a document using cursor-based pagination.\n * The reactor client handles multi-scope cursors transparently via\n * composite cursors, so all scopes are fetched in a single paginated stream.\n */\nexport async function fetchDocumentOperations(\n reactorClient: IReactorBrowserClient,\n document: PHDocument,\n pageSize = 100,\n): Promise<DocumentOperations> {\n // includes auth: an export must carry the policy history\n const scopes = Object.keys(document.state);\n const operations: DocumentOperations = {};\n for (const scope of scopes) {\n operations[scope] = [];\n }\n\n let cursor = \"\";\n\n do {\n const page = await reactorClient.getOperations(\n document.header.id,\n { scopes },\n undefined,\n { cursor, limit: pageSize },\n );\n\n for (const op of page.results) {\n const scope = op.action.scope ?? \"global\";\n if (operations[scope]) {\n operations[scope].push(op);\n }\n }\n\n cursor = page.nextCursor ?? \"\";\n } while (cursor);\n\n return operations;\n}\n\nexport function extractInitialState(\n documentScopeOps: Operation[],\n): PHBaseState {\n const upgradeOp = documentScopeOps.find(\n (op) => op.action.type === \"UPGRADE_DOCUMENT\",\n );\n if (!upgradeOp) {\n throw new Error(\n \"No UPGRADE_DOCUMENT operation found — document is invalid\",\n );\n }\n const input = upgradeOp.action.input as {\n initialState?: PHBaseState;\n state?: PHBaseState;\n };\n const initialState = input.initialState ?? input.state;\n if (!initialState) {\n throw new Error(\n \"UPGRADE_DOCUMENT operation has no initialState — document is invalid\",\n );\n }\n return initialState;\n}\n\nexport function filterDomainOperations(\n operations: DocumentOperations,\n): DocumentOperations {\n return Object.fromEntries(\n Object.entries(operations).filter(\n ([scope]) => !NON_DOMAIN_SCOPES.has(scope),\n ),\n );\n}\n\n/** Domain operations to replay, and the version to upgrade to afterwards. */\nexport interface ImportSegment {\n operations: DocumentOperations;\n /** Absent on the final segment. */\n upgradeTo?: number;\n}\n\nfunction countOperations(operations: DocumentOperations): number {\n let total = 0;\n for (const ops of Object.values(operations)) {\n total += ops?.length ?? 0;\n }\n return total;\n}\n\n/**\n * Split an imported document's domain operations at its mid-history upgrade\n * boundaries, so the caller can re-dispatch each upgrade between segments.\n *\n * The seed's CREATE_DOCUMENT and 0 -> N upgrade are replayed by the creation\n * path and must not be repeated. A later upgrade must be: it is where the\n * reducer version changes, and dropping it replays everything after it through\n * the module the document was created with.\n */\nexport function splitAtUpgradeBoundaries(\n operations: DocumentOperations,\n): ImportSegment[] {\n const upgrades = (operations.document ?? [])\n .filter((op) => op.action.type === \"UPGRADE_DOCUMENT\")\n .filter(\n (op) => (op.action.input as UpgradeDocumentActionInput).fromVersion > 0,\n )\n .sort((a, b) => a.index - b.index);\n\n const domain = filterDomainOperations(operations);\n if (upgrades.length === 0) {\n return [{ operations: domain }];\n }\n\n const segments: ImportSegment[] = [];\n const consumed = new Map<string, number>();\n\n const take = (until: (scope: string, ops: Operation[]) => number) => {\n const slice: DocumentOperations = {};\n for (const [scope, ops] of Object.entries(domain)) {\n if (!ops) continue;\n const from = consumed.get(scope) ?? 0;\n const stop = Math.max(from, until(scope, ops));\n const chunk = ops.slice(from, stop);\n if (chunk.length > 0) slice[scope] = chunk;\n consumed.set(scope, stop);\n }\n return slice;\n };\n\n for (const upgrade of upgrades) {\n const input = upgrade.action.input as UpgradeDocumentActionInput;\n const slice = take((scope, ops) => boundary(upgrade, scope, ops));\n segments.push({ operations: slice, upgradeTo: input.toVersion });\n }\n\n const tail = take((_scope, ops) => ops.length);\n if (countOperations(tail) > 0) {\n segments.push({ operations: tail });\n }\n\n return segments;\n}\n\n/**\n * How many of a scope's operations precede an upgrade. Must stay identical to\n * the boundary computation in `replayDocumentVersioned` — snapshots compare\n * against operation indices, not array positions, and the timestamp fallback\n * excludes the upgrade's own instant.\n */\nfunction boundary(upgrade: Operation, scope: string, ops: Operation[]): number {\n const snapshot = (upgrade.action.input as UpgradeDocumentActionInput)\n .revision;\n\n if (snapshot !== undefined) {\n const revision = snapshot[scope] ?? 0;\n let count = 0;\n for (let i = 0; i < ops.length; i++) {\n if (ops[i].index < revision) count = i + 1;\n }\n return count;\n }\n\n for (let i = 0; i < ops.length; i++) {\n if (ops[i].timestampUtcMs >= upgrade.timestampUtcMs) {\n return i;\n }\n }\n return ops.length;\n}\n\nexport async function exportFile(document: PHDocument, suggestedName?: string) {\n const reactorClient = window.ph?.reactorClient;\n if (!reactorClient) {\n throw new Error(\"ReactorClient not initialized\");\n }\n\n // Fetch operations page-by-page (document from reactor has operations: {})\n const operations = await fetchDocumentOperations(reactorClient, document);\n const initialState = extractInitialState(operations[\"document\"] ?? []);\n const documentWithOps = { ...document, operations, initialState };\n\n // Get the extension from the document model module\n const extension = await getDocumentExtension(documentWithOps);\n\n const baseName = suggestedName || documentWithOps.header.name || \"Untitled\";\n const name = extension ? `${baseName}.${extension}.phd` : `${baseName}.phd`;\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!window.showSaveFilePicker) {\n return await downloadFile(documentWithOps, name);\n }\n try {\n const fileHandle = await window.showSaveFilePicker({\n suggestedName: name,\n });\n\n await baseSaveToFileHandle(documentWithOps, fileHandle);\n return fileHandle;\n } catch (e) {\n // ignores error if user cancelled the file picker\n if (!(e instanceof DOMException && e.name === \"AbortError\")) {\n throw e;\n }\n }\n}\n\n/**\n * Loads a document file and replays it with version-aware reducers from the registry.\n * Falls back to single-version legacy replay when no upgrade manifest is registered for\n * the document type.\n */\nexport async function loadFile(path: string | File) {\n const baseDocument = await baseLoadFromInput(\n path,\n (state: PHDocument) => state,\n { checkHashes: true },\n );\n\n // document model modules are only available on the full reactor client\n const reactorClient = window.ph?.reactorClientModule?.client;\n if (!reactorClient) {\n throw new Error(\"ReactorClient not initialized\");\n }\n\n const documentType = baseDocument.header.documentType;\n const { results: documentModelModules } =\n await reactorClient.getDocumentModelModules();\n const modulesForType = documentModelModules.filter(\n (module) => module.documentModel.global.id === documentType,\n );\n if (modulesForType.length === 0) {\n throw new DocumentModelNotFoundError(documentType);\n }\n\n const reducers: VersionedReplayConfig[\"reducers\"] = {};\n for (const module of modulesForType) {\n reducers[module.version ?? 1] = module.reducer as Reducer<PHBaseState>;\n }\n\n const registry =\n window.ph?.reactorClientModule?.reactorModule?.documentModelRegistry;\n let upgradeManifest: VersionedReplayConfig[\"upgradeManifest\"] | undefined;\n if (registry) {\n try {\n upgradeManifest = registry.getUpgradeManifest(documentType);\n } catch {\n // intentionally empty — missing manifest is normal for single-version documents\n }\n }\n\n const config: VersionedReplayConfig = { reducers, upgradeManifest };\n return baseLoadFromInputVersioned(path, config);\n}\n\nexport async function addDocument(\n driveId: string,\n name: string,\n documentType: string,\n parentFolder?: string,\n document?: PHDocument,\n id?: string,\n preferredEditor?: string,\n documentModelVersion?: number,\n) {\n const { isAllowedToCreateDocuments } = getUserPermissions();\n if (!isAllowedToCreateDocuments) {\n throw new Error(\"User is not allowed to create documents\");\n }\n\n // document model modules and drive operations are only available on the full\n // reactor client\n const reactorClient = window.ph?.reactorClientModule?.client;\n if (!reactorClient) {\n throw new Error(\"ReactorClient not initialized\");\n }\n\n // get the module\n let documentModelModule: DocumentModelModule;\n if (documentModelVersion !== undefined) {\n const { results: documentModelModules } =\n await reactorClient.getDocumentModelModules();\n const module = documentModelModules.find(\n (m) =>\n m.documentModel.global.id === documentType &&\n (m.version ?? 1) === documentModelVersion,\n );\n if (!module) {\n throw new Error(\n `Document model not found for type: ${documentType} with version: ${documentModelVersion}`,\n );\n }\n documentModelModule = module;\n } else {\n documentModelModule =\n await reactorClient.getDocumentModelModule(documentType);\n }\n\n // create - use passed document's state if available\n const newDocument = document ?? documentModelModule.utils.createDocument();\n if (!document) {\n newDocument.state.document.version = documentModelModule.version ?? 1;\n }\n newDocument.header.name = name;\n if (preferredEditor) {\n newDocument.header.meta = {\n ...newDocument.header.meta,\n preferredEditor,\n };\n }\n\n // Create document using ReactorClient\n let newDoc: PHDocument;\n try {\n newDoc = await reactorClient.drives.addFile(\n driveId,\n newDocument,\n parentFolder,\n );\n } catch (e) {\n logger.error(\"Error adding document: @error\", e);\n throw new Error(\"There was an error adding document\", { cause: e });\n }\n\n // Return a file node structure for compatibility\n return {\n id: newDoc.header.id,\n name: newDoc.header.name,\n documentType,\n parentFolder: parentFolder ?? null,\n kind: \"file\" as const,\n };\n}\n\nexport async function addFile(\n file: string | File,\n driveId: string,\n name?: string,\n parentFolder?: string,\n) {\n logger.verbose(\n `addFile(drive: ${driveId}, name: ${name}, folder: ${parentFolder})`,\n );\n\n const { isAllowedToCreateDocuments } = getUserPermissions();\n if (!isAllowedToCreateDocuments) {\n throw new Error(\"User is not allowed to create files\");\n }\n\n const document = await loadFile(file);\n\n let duplicateId = false;\n\n const reactorClient = window.ph?.reactorClient;\n if (!reactorClient) {\n throw new Error(\"ReactorClient not initialized\");\n }\n\n try {\n await reactorClient.get(document.header.id);\n duplicateId = true;\n } catch {\n // document id not found\n }\n\n const documentId = duplicateId ? generateId() : document.header.id;\n const header = createPresignedHeader(\n documentId,\n document.header.documentType,\n );\n header.lastModifiedAtUtcIso = document.header.createdAtUtcIso;\n header.meta = document.header.meta;\n header.name = name || document.header.name;\n\n // copy the document at it's initial state\n const initialDocument = {\n ...document,\n header,\n state: document.initialState,\n operations: Object.keys(document.operations).reduce((acc, key) => {\n acc[key] = [];\n return acc;\n }, {} as DocumentOperations),\n };\n\n await addDocument(\n driveId,\n name || document.header.name,\n document.header.documentType,\n parentFolder,\n initialDocument,\n documentId,\n document.header.meta?.preferredEditor,\n );\n\n // then add all the operations in chunks, re-dispatching each mid-history\n // upgrade at its boundary\n for (const segment of splitAtUpgradeBoundaries(document.operations)) {\n await uploadOperations(documentId, segment.operations, queueOperations);\n if (segment.upgradeTo !== undefined) {\n await upgradeDocument(documentId, segment.upgradeTo);\n }\n }\n}\n\nexport async function addFileWithProgress(\n file: string | File,\n driveId: string,\n name?: string,\n parentFolder?: string,\n onProgress?: FileUploadProgressCallback,\n documentTypes?: string[],\n resolveConflict?: ConflictResolution,\n) {\n logger.verbose(\n `addFileWithProgress(drive: ${driveId}, name: ${name}, folder: ${parentFolder})`,\n );\n // importing a file into a drive is a full reactor client feature\n const reactor = window.ph?.reactorClientModule?.client;\n if (!reactor) {\n return;\n }\n\n const { isAllowedToCreateDocuments } = getUserPermissions();\n if (!isAllowedToCreateDocuments) {\n throw new Error(\"User is not allowed to create files\");\n }\n\n // Loading stage (0-10%)\n try {\n onProgress?.({ stage: \"loading\", progress: 0 });\n let document: PHDocument;\n try {\n document = await loadFile(file);\n } catch (loadError) {\n if (UnsupportedDocumentModelVersionError.isError(loadError)) {\n showPHModal({\n type: \"documentVersionUnsupported\",\n documentType: loadError.documentType,\n requiredVersion: loadError.requiredVersion,\n availableVersions: loadError.availableVersions,\n });\n onProgress?.({\n stage: \"failed\",\n progress: 100,\n error: loadError.message,\n });\n return;\n }\n\n // Only attempt discovery if the failure is specifically a missing\n // document model module, not for other errors like corrupt files.\n const discoveryService = window.ph?.packageDiscoveryService;\n if (discoveryService && DocumentModelNotFoundError.isError(loadError)) {\n // Trigger discovery and retry without blocking the drop handler\n void retryAfterDiscovery(\n discoveryService,\n loadError.documentType,\n file,\n driveId,\n name,\n parentFolder,\n onProgress,\n documentTypes,\n resolveConflict,\n );\n return;\n }\n throw loadError;\n }\n\n // Check for duplicate in same location\n const duplicateCheck = await isDocumentInLocation(\n document,\n driveId,\n parentFolder,\n );\n\n if (duplicateCheck.isDuplicate && !resolveConflict) {\n // Report conflict and return early\n onProgress?.({\n stage: \"conflict\",\n progress: 0,\n duplicateType: duplicateCheck.duplicateType,\n });\n return undefined;\n }\n\n // For \"duplicate\" resolution, we continue normally which creates a new document\n // with a different ID (the default behavior)\n\n // Send documentType info immediately after loading\n const documentType = getDocumentTypeIcon(document);\n if (documentType) {\n onProgress?.({ stage: \"loading\", progress: 10, documentType });\n } else {\n onProgress?.({ stage: \"loading\", progress: 10 });\n }\n\n if (!isDocumentTypeSupported(document.header.documentType, documentTypes)) {\n onProgress?.({\n stage: \"unsupported-document-type\",\n progress: 100,\n error: `Document type ${document.header.documentType} is not supported`,\n });\n throw new UnsupportedDocumentTypeError(document.header.documentType);\n }\n\n // ensure we have the module + can load it (throws if not found)\n await reactor.getDocumentModelModule(document.header.documentType);\n\n // Initializing stage (10-20%)\n onProgress?.({ stage: \"initializing\", progress: 10 });\n\n let duplicateId = false;\n try {\n await reactor.get(document.header.id);\n duplicateId = true;\n } catch {\n // document id not found\n }\n\n const documentId = duplicateId ? generateId() : document.header.id;\n const header = createPresignedHeader(\n documentId,\n document.header.documentType,\n );\n header.lastModifiedAtUtcIso = document.header.createdAtUtcIso;\n header.meta = document.header.meta;\n header.name = name || document.header.name;\n\n // copy the document at it's initial state\n const initialDocument = {\n ...document,\n header,\n state: document.initialState,\n operations: Object.keys(document.operations).reduce((acc, key) => {\n acc[key] = [];\n return acc;\n }, {} as DocumentOperations),\n };\n\n const fileNode = await addDocument(\n driveId,\n name || document.header.name,\n document.header.documentType,\n parentFolder,\n initialDocument,\n documentId,\n document.header.meta?.preferredEditor,\n );\n\n if (!fileNode) {\n throw new Error(\"There was an error adding file\");\n }\n\n onProgress?.({ stage: \"initializing\", progress: 20 });\n\n const _doc = await reactor.get(documentId);\n console.log(\"Document created, starting upload of operations\");\n\n // Uploading stage (20-100%), re-dispatching each mid-history upgrade at\n // its boundary\n const segments = splitAtUpgradeBoundaries(document.operations);\n const totalOperations = segments.reduce(\n (total, segment) => total + countOperations(segment.operations),\n 0,\n );\n let uploadedBefore = 0;\n\n for (const segment of segments) {\n await uploadOperations(documentId, segment.operations, queueOperations, {\n onProgress: (uploadProgress) => {\n if (uploadProgress.uploadedOperations === undefined) {\n return;\n }\n const uploaded = uploadedBefore + uploadProgress.uploadedOperations;\n const uploadPercent =\n totalOperations > 0 ? uploaded / totalOperations : 0;\n onProgress?.({\n stage: \"uploading\",\n progress: 20 + Math.round(uploadPercent * 80),\n totalOperations,\n uploadedOperations: uploaded,\n });\n },\n });\n\n uploadedBefore += countOperations(segment.operations);\n\n if (segment.upgradeTo !== undefined) {\n await reactor.upgradeDocument(documentId, segment.upgradeTo);\n }\n }\n\n onProgress?.({ stage: \"complete\", progress: 100, fileNode });\n\n return fileNode;\n } catch (error) {\n // Don't override unsupported-document-type status\n if (!UnsupportedDocumentTypeError.isError(error)) {\n const errorMessage =\n error instanceof Error ? error.message : \"Unknown error occurred\";\n onProgress?.({\n stage: \"failed\",\n progress: 100,\n error: errorMessage,\n });\n }\n throw error;\n }\n}\n\nasync function retryAfterDiscovery(\n discoveryService: NonNullable<typeof window.ph>[\"packageDiscoveryService\"],\n documentType: string,\n file: string | File,\n driveId: string,\n name?: string,\n parentFolder?: string,\n onProgress?: FileUploadProgressCallback,\n documentTypes?: string[],\n resolveConflict?: ConflictResolution,\n): Promise<void> {\n if (!discoveryService) return;\n try {\n await discoveryService.load(documentType);\n } catch {\n onProgress?.({\n stage: \"unsupported-document-type\",\n progress: 100,\n error: `Document type ${documentType} is not supported`,\n });\n return;\n }\n await addFileWithProgress(\n file,\n driveId,\n name,\n parentFolder,\n onProgress,\n documentTypes,\n resolveConflict,\n );\n}\n\nexport async function updateFile(\n driveId: string,\n nodeId: string,\n documentType?: string,\n name?: string,\n parentFolder?: string,\n) {\n const reactor = window.ph?.reactorClient;\n if (!reactor) {\n return;\n }\n const { isAllowedToCreateDocuments } = getUserPermissions();\n\n if (!isAllowedToCreateDocuments) {\n throw new Error(\"User is not allowed to update files\");\n }\n const drive = await reactor.get<DocumentDriveDocument>(driveId);\n const unsafeCastAsDrive = (await queueActions(\n drive,\n baseUpdateFile({\n id: nodeId,\n name: name ?? undefined,\n parentFolder,\n documentType,\n }),\n )) as DocumentDriveDocument;\n\n const node = unsafeCastAsDrive.state.global.nodes.find(\n (node) => node.id === nodeId,\n );\n if (!node || !isFileNode(node)) {\n throw new Error(\"There was an error updating document\");\n }\n return node;\n}\n\nexport async function addFolder(\n driveId: string,\n name: string,\n parentFolder?: string,\n) {\n const { isAllowedToCreateDocuments } = getUserPermissions();\n if (!isAllowedToCreateDocuments) {\n throw new Error(\"User is not allowed to create folders\");\n }\n\n const reactorClient = window.ph?.reactorClient;\n if (!reactorClient) {\n throw new Error(\"ReactorClient not initialized\");\n }\n\n // Get the drive document and add folder action\n const _drive = await reactorClient.get<DocumentDriveDocument>(driveId);\n const folderId = generateId();\n const updatedDrive = await reactorClient.execute<DocumentDriveDocument>(\n driveId,\n \"main\",\n [\n baseAddFolder({\n id: folderId,\n name,\n parentFolder,\n }),\n ],\n );\n\n const node = updatedDrive.state.global.nodes.find(\n (node) => node.id === folderId,\n );\n if (!node || !isFolderNode(node)) {\n throw new Error(\"There was an error adding folder\");\n }\n return node;\n}\n\nexport async function deleteNode(driveId: string, nodeId: string) {\n const { isAllowedToCreateDocuments } = getUserPermissions();\n if (!isAllowedToCreateDocuments) {\n throw new Error(\"User is not allowed to delete documents\");\n }\n\n // drive operations are only available on the full reactor client\n const reactorClient = window.ph?.reactorClientModule?.client;\n if (!reactorClient) {\n throw new Error(\"ReactorClient not initialized\");\n }\n\n await reactorClient.drives.removeNode(driveId, nodeId);\n}\n\nexport async function renameNode(\n driveId: string,\n nodeId: string,\n name: string,\n): Promise<Node | undefined> {\n const { isAllowedToCreateDocuments } = getUserPermissions();\n if (!isAllowedToCreateDocuments) {\n throw new Error(\"User is not allowed to rename documents\");\n }\n\n const reactorClient = window.ph?.reactorClient;\n if (!reactorClient) {\n throw new Error(\"ReactorClient not initialized\");\n }\n\n const renameNodeResult = await reactorClient.execute(nodeId, \"main\", [\n setName({ name }),\n ]);\n\n if (renameNodeResult.header.name !== name) {\n throw new Error(\"There was an error renaming the node\");\n }\n\n // Rename the node in the drive document using updateNode action\n const drive = await reactorClient.execute<DocumentDriveDocument>(\n driveId,\n \"main\",\n [updateNode({ id: nodeId, name })],\n );\n\n const node = drive.state.global.nodes.find((n) => n.id === nodeId);\n if (!node) {\n throw new Error(\"There was an error renaming node in the drive\");\n }\n return node;\n}\n\nexport async function renameDriveNode(\n driveId: string,\n nodeId: string,\n name: string,\n): Promise<Node | undefined> {\n const { isAllowedToCreateDocuments } = getUserPermissions();\n if (!isAllowedToCreateDocuments) {\n throw new Error(\"User is not allowed to rename documents\");\n }\n\n const reactorClient = window.ph?.reactorClient;\n if (!reactorClient) {\n throw new Error(\"ReactorClient not initialized\");\n }\n\n const renameNodeResult = await reactorClient.execute(nodeId, \"main\", [\n setName({ name }),\n ]);\n\n if (renameNodeResult.header.name !== name) {\n throw new Error(\"There was an error renaming the node\");\n }\n\n await reactorClient.execute(driveId, \"main\", [\n updateNode({ id: nodeId, name }),\n ]);\n\n const drive = await reactorClient.get<DocumentDriveDocument>(driveId);\n return drive.state.global.nodes.find((n: Node) => n.id === nodeId);\n}\n\nexport async function setPreferredEditorOnNode(\n nodeId: string,\n preferredEditor: string | null,\n) {\n const { isAllowedToCreateDocuments } = getUserPermissions();\n if (!isAllowedToCreateDocuments) {\n throw new Error(\"User is not allowed to modify documents\");\n }\n\n const reactorClient = window.ph?.reactorClient;\n if (!reactorClient) {\n throw new Error(\"ReactorClient not initialized\");\n }\n\n return reactorClient.execute(nodeId, \"main\", [\n setPreferredEditor(preferredEditor),\n ]);\n}\n\nexport async function moveNodeById(args: {\n driveId: string | undefined;\n srcId: string | undefined;\n targetId?: string;\n}) {\n const { driveId, srcId, targetId } = args;\n if (!driveId || !srcId) return;\n\n const { isAllowedToCreateDocuments } = getUserPermissions();\n if (!isAllowedToCreateDocuments) {\n throw new Error(\"User is not allowed to move documents\");\n }\n\n const reactorClient = window.ph?.reactorClient;\n if (!reactorClient) {\n throw new Error(\"ReactorClient not initialized\");\n }\n const targetParentFolder = conditional(\n targetId,\n [isNot(isDefined), constant(undefined)],\n [isStrictEqual(driveId), constant(undefined)],\n constant(targetId),\n );\n\n if (isStrictEqual(targetParentFolder, srcId)) return;\n\n return await reactorClient.execute(driveId, \"main\", [\n baseMoveNode({\n srcFolder: srcId,\n targetParentFolder,\n }),\n ]);\n}\n\nexport async function moveNode(\n driveId: string,\n src: Node,\n target: Node | undefined,\n) {\n const { isAllowedToCreateDocuments } = getUserPermissions();\n if (!isAllowedToCreateDocuments) {\n throw new Error(\"User is not allowed to move documents\");\n }\n\n const reactorClient = window.ph?.reactorClient;\n if (!reactorClient) {\n throw new Error(\"ReactorClient not initialized\");\n }\n return await reactorClient.execute(driveId, \"main\", [\n baseMoveNode({\n srcFolder: src.id,\n targetParentFolder: target?.id,\n }),\n ]);\n}\n\n/**\n * Duplicates a document under a new id using version-aware replay.\n * Falls back gracefully when no upgrade manifest is registered for the document type.\n */\nasync function _duplicateDocument(\n reactor: IReactorClient,\n document: PHDocument,\n newId = generateId(),\n) {\n const documentType = document.header.documentType;\n const { results: allModules } = await reactor.getDocumentModelModules();\n const modulesForType = allModules.filter(\n (m) => m.documentModel.global.id === documentType,\n );\n\n const reducers: VersionedReplayConfig[\"reducers\"] = {};\n for (const m of modulesForType) {\n reducers[m.version ?? 1] = m.reducer as Reducer<PHBaseState>;\n }\n\n if (Object.keys(reducers).length === 0) {\n throw new Error(\n `Document model module not found for type: ${documentType}`,\n );\n }\n\n const registry =\n window.ph?.reactorClientModule?.reactorModule?.documentModelRegistry;\n let upgradeManifest: VersionedReplayConfig[\"upgradeManifest\"] | undefined;\n if (registry) {\n try {\n upgradeManifest = registry.getUpgradeManifest(documentType);\n } catch {\n // intentionally empty — missing manifest is normal for single-version documents\n }\n }\n\n const config: VersionedReplayConfig = { reducers, upgradeManifest };\n const header = createPresignedHeader(newId, documentType);\n\n const duplicated = replayDocumentVersioned(\n document.initialState,\n document.operations,\n config,\n header,\n );\n assertAuthPreservedOnDuplicate(\n document.header.id,\n document.state.auth,\n duplicated.state.auth,\n );\n return duplicated;\n}\n\nexport async function copyNode(\n driveId: string,\n src: Node,\n target: Node | undefined,\n) {\n // copying nodes duplicates documents and adds drive files, both of which are\n // only available on the full reactor client\n const reactor = window.ph?.reactorClientModule?.client;\n if (!reactor) {\n return;\n }\n const { isAllowedToCreateDocuments } = getUserPermissions();\n\n if (!isAllowedToCreateDocuments) {\n throw new Error(\"User is not allowed to copy documents\");\n }\n\n const drive = await reactor.get<DocumentDriveDocument>(driveId);\n\n const copyNodesInput = generateNodesCopy(\n {\n srcId: src.id,\n targetParentFolder: target?.id,\n targetName: src.name,\n },\n () => generateId(),\n drive.state.global.nodes,\n );\n\n // Pre-calculate collision-resolved names for all nodes to be copied\n const resolvedNamesMap = new Map<string, string>();\n for (const copyNodeInput of copyNodesInput) {\n const node = drive.state.global.nodes.find(\n (n) => n.id === copyNodeInput.srcId,\n );\n if (node) {\n const resolvedName = handleTargetNameCollisions({\n nodes: drive.state.global.nodes,\n srcName: copyNodeInput.targetName || node.name,\n srcKind: isFileNode(node) ? \"file\" : \"folder\",\n targetParentFolder: copyNodeInput.targetParentFolder || null,\n });\n resolvedNamesMap.set(copyNodeInput.targetId, resolvedName);\n }\n }\n\n const fileNodesToCopy = copyNodesInput.filter((copyNodeInput) => {\n const node = drive.state.global.nodes.find(\n (node) => node.id === copyNodeInput.srcId,\n );\n return node !== undefined && isFileNode(node);\n });\n\n for (const fileNodeToCopy of fileNodesToCopy) {\n try {\n const document = await reactor.get(fileNodeToCopy.srcId);\n\n const duplicatedDocument = await _duplicateDocument(\n reactor,\n document,\n fileNodeToCopy.targetId,\n );\n\n // Set the header name to match the collision-resolved node name\n const resolvedName = resolvedNamesMap.get(fileNodeToCopy.targetId);\n if (resolvedName) {\n duplicatedDocument.header.name = resolvedName;\n }\n\n await reactor.drives.addFile(driveId, duplicatedDocument, target?.id);\n } catch (e) {\n logger.error(\n `Error copying document ${fileNodeToCopy.srcId}: ${String(e)}`,\n );\n }\n }\n\n const copyActions = copyNodesInput.map((copyNodeInput) =>\n baseCopyNode(copyNodeInput),\n );\n return await queueActions(drive, copyActions);\n}\n\n/**\n * Upgrades a document to a newer document model version. Defaults to the\n * latest registered version for the document's type.\n */\nexport async function upgradeDocument(documentId: string, toVersion?: number) {\n const reactorClient = window.ph?.reactorClientModule?.client;\n if (!reactorClient) {\n throw new Error(\"ReactorClient not initialized\");\n }\n return reactorClient.upgradeDocument(documentId, toVersion);\n}\n","import type {\n DocumentOperations,\n Operation,\n PHBaseState,\n PHDocument,\n} from \"@powerhousedao/shared/document-model\";\nimport { deserializeSignature } from \"@powerhousedao/shared/document-model\";\nimport type {\n ConflictInfo,\n RemoteDocumentData,\n RemoteOperation,\n} from \"./types.js\";\n\n/** Convert SCREAMING_SNAKE_CASE to camelCase (e.g. \"SET_MODEL_NAME\" → \"setModelName\"). */\nexport function screamingSnakeToCamel(s: string): string {\n return s\n .toLowerCase()\n .replace(/_([a-z])/g, (_, c: string) => c.toUpperCase());\n}\n\n/** Error thrown when a push conflict is detected with the \"reject\" strategy. */\nexport class ConflictError extends Error {\n constructor(public readonly conflict: ConflictInfo) {\n super(\"Push conflict: remote has new operations since last pull\");\n this.name = \"ConflictError\";\n }\n}\n\n/** Convert a remote operation to the local Operation type. */\nexport function remoteOperationToLocal(remote: RemoteOperation): Operation {\n return {\n id: remote.id ?? \"\",\n index: remote.index,\n skip: remote.skip,\n timestampUtcMs: remote.timestampUtcMs,\n hash: remote.hash,\n error: remote.error ?? undefined,\n deniedReason: remote.deniedReason ?? undefined,\n action: {\n id: remote.action.id,\n type: remote.action.type,\n timestampUtcMs: remote.action.timestampUtcMs,\n input: remote.action.input,\n scope: remote.action.scope,\n context: remote.action.context?.signer\n ? {\n signer: {\n user: remote.action.context.signer.user ?? {\n address: \"\",\n networkId: \"\",\n chainId: 0,\n },\n app: remote.action.context.signer.app ?? {\n name: \"\",\n key: \"\",\n },\n signatures: remote.action.context.signer.signatures.map((s) =>\n deserializeSignature(s),\n ),\n },\n }\n : undefined,\n },\n };\n}\n\n/**\n * Re-exported from shared, where it sits beside the serializer it has to agree\n * with. Kept exported here because this module's consumers import it from here.\n */\nexport { deserializeSignature };\n\n/** Convert remote operations to local DocumentOperations format. */\nexport function convertRemoteOperations(\n operationsByScope: Record<string, RemoteOperation[]>,\n): DocumentOperations {\n const operations: DocumentOperations = {};\n for (const [scope, remoteOps] of Object.entries(operationsByScope)) {\n operations[scope] = remoteOps.map((op) => remoteOperationToLocal(op));\n }\n return operations;\n}\n\n/** Reconstruct a PHDocument from remote document data and operations. */\nexport function buildPulledDocument(\n remoteDoc: RemoteDocumentData,\n operations: DocumentOperations,\n initialDoc: PHDocument<PHBaseState>,\n branch: string,\n): PHDocument<PHBaseState> {\n return {\n header: {\n ...initialDoc.header,\n id: remoteDoc.id,\n name: remoteDoc.name,\n slug: remoteDoc.slug ?? \"\",\n documentType: remoteDoc.documentType,\n createdAtUtcIso:\n typeof remoteDoc.createdAtUtcIso === \"string\"\n ? remoteDoc.createdAtUtcIso\n : remoteDoc.createdAtUtcIso.toISOString(),\n lastModifiedAtUtcIso:\n typeof remoteDoc.lastModifiedAtUtcIso === \"string\"\n ? remoteDoc.lastModifiedAtUtcIso\n : remoteDoc.lastModifiedAtUtcIso.toISOString(),\n revision: Object.fromEntries(\n remoteDoc.revisionsList.map((r) => [r.scope, r.revision]),\n ),\n branch,\n },\n state: remoteDoc.state as PHBaseState,\n initialState: initialDoc.initialState,\n operations,\n clipboard: [],\n };\n}\n\n/** Extract revision map from a remote document's revisionsList. */\nexport function extractRevisionMap(\n revisionsList: RemoteDocumentData[\"revisionsList\"],\n): Record<string, number> {\n return Object.fromEntries(revisionsList.map((r) => [r.scope, r.revision]));\n}\n\n/**\n * Check if any scope in currentRevision is ahead of knownRevision.\n * When `scopes` is provided, only those scopes are checked.\n */\nexport function hasRevisionConflict(\n currentRevision: Record<string, number>,\n knownRevision: Record<string, number>,\n scopes?: ReadonlySet<string>,\n): boolean {\n for (const scope in currentRevision) {\n if (scopes && !scopes.has(scope)) continue;\n if ((currentRevision[scope] ?? 0) > (knownRevision[scope] ?? 0)) {\n return true;\n }\n }\n return false;\n}\n","import type {\n DocumentOperations,\n PHBaseState,\n PHDocument,\n PHDocumentHeader,\n} from \"document-model\";\nimport type { GetDocumentQuery } from \"../graphql/gen/schema.js\";\nimport type { RemoteOperation } from \"../remote-controller/types.js\";\nimport { remoteOperationToLocal } from \"../remote-controller/utils.js\";\n\n/** The `document` payload of a `GetDocument` query, once the null case is handled. */\nexport type GetDocumentQueryResult = NonNullable<GetDocumentQuery[\"document\"]>;\n\n/** The `PHDocumentFields` fragment as returned by `GetDocument`. */\nexport type GetDocumentQueryFields = GetDocumentQueryResult[\"document\"];\n\n/** The `revisionsList` selection of the `PHDocumentFields` fragment. */\nexport type RevisionsListSelection = GetDocumentQueryFields[\"revisionsList\"];\n\n/**\n * Converts a `GetDocument` result into a `PHDocument`.\n *\n * Unlike the legacy `src/graphql/adapters.ts` this preserves the per-scope\n * revision map, which the write path needs to compute the `prevOpIndex` of a\n * signed action. `sig` is filled with the empty shape used by\n * `createPresignedHeader`: the creation signature is not fetchable over\n * GraphQL and is not part of the operation signing payload.\n *\n * The read path never fetches operation history, so `operations` is a map of\n * the document's known scopes to empty arrays.\n *\n * `branch` is the branch the document was read from. The GraphQL type does not\n * carry it, so it has to be passed back in by the caller; it defaults to the\n * server's own default branch.\n */\nexport function phDocumentFromGetDocument<\n TDocument extends PHDocument = PHDocument,\n>(document: GetDocumentQueryFields, branch?: string): TDocument {\n const state = document.state as PHBaseState;\n const phDocument: PHDocument = {\n header: phDocumentHeaderFromGetDocument(document, branch),\n state,\n initialState: state,\n operations: emptyOperationsForScopes(document.revisionsList),\n clipboard: [],\n };\n return phDocument as TDocument;\n}\n\n/**\n * Converts a mutation result into a `PHDocument`, carrying the operations the\n * mutation produced.\n *\n * `dispatchActions` reads per-action failures out of `operations[scope]`, so\n * unlike the read path this one must not return empty operation lists.\n */\nexport function phDocumentFromMutation<\n TDocument extends PHDocument = PHDocument,\n>(\n document: GetDocumentQueryFields,\n operations: readonly RemoteOperation[],\n branch?: string,\n): TDocument {\n const phDocument = phDocumentFromGetDocument<TDocument>(document, branch);\n const operationsByScope: DocumentOperations = { ...phDocument.operations };\n\n for (const remote of operations) {\n const operation = remoteOperationToLocal(remote);\n const scope = operation.action.scope;\n const scopeOperations = operationsByScope[scope] ?? [];\n scopeOperations.push(operation);\n operationsByScope[scope] = scopeOperations;\n }\n\n phDocument.operations = operationsByScope;\n return phDocument;\n}\n\n/** Turns a `revisionsList` selection into the header's per-scope revision map. */\nexport function revisionMapFromRevisionsList(\n revisionsList: RevisionsListSelection,\n): Record<string, number> {\n return Object.fromEntries(revisionsList.map((r) => [r.scope, r.revision]));\n}\n\n/** The branch the server reads and writes when none is asked for. */\nconst defaultBranch = \"main\";\n\nfunction phDocumentHeaderFromGetDocument(\n document: GetDocumentQueryFields,\n branch?: string,\n): PHDocumentHeader {\n return {\n id: document.id,\n sig: {\n publicKey: {},\n nonce: \"\",\n },\n documentType: document.documentType,\n createdAtUtcIso: isoStringFromDateTime(document.createdAtUtcIso),\n slug: document.slug ?? \"\",\n name: document.name,\n branch: branch ?? defaultBranch,\n revision: revisionMapFromRevisionsList(document.revisionsList),\n lastModifiedAtUtcIso: isoStringFromDateTime(document.lastModifiedAtUtcIso),\n };\n}\n\nfunction emptyOperationsForScopes(\n revisionsList: RevisionsListSelection,\n): DocumentOperations {\n return Object.fromEntries(revisionsList.map((r) => [r.scope, []]));\n}\n\n/** The `DateTime` scalar deserializes as either an ISO string or a `Date`. */\nfunction isoStringFromDateTime(value: string | Date): string {\n return value instanceof Date ? value.toISOString() : value;\n}\n","import type { SdkFunctionWrapper } from \"../graphql/gen/schema.js\";\n\n/**\n * Resolves the bearer token to send with a request.\n *\n * Returning `undefined` (or an empty string) means \"send this request\n * anonymously\": open Switchboards must keep serving reads to logged-out users.\n */\nexport type BearerTokenProvider = () => Promise<string | undefined>;\n\n/** Lifetime requested for an ambient Renown token, in seconds. */\nconst ambientTokenExpiresInSeconds = 600;\n\n/**\n * The default token provider: the token of the currently logged-in Renown user.\n *\n * It is deliberately resolved from `window.ph` on every call rather than\n * captured at construction time, so a client built before login starts sending\n * the token as soon as there is one.\n *\n * The token is requested WITHOUT an `aud` claim - the Switchboard verifier\n * rejects tokens that carry an audience.\n */\nexport async function ambientRenownTokenProvider(): Promise<\n string | undefined\n> {\n if (typeof window === \"undefined\") {\n return undefined;\n }\n\n const renown = window.ph?.renown;\n if (!renown?.user) {\n return undefined;\n }\n\n return renown.getBearerToken({ expiresIn: ambientTokenExpiresInSeconds });\n}\n\n/**\n * Builds the SDK middleware that authenticates every request.\n *\n * The token is resolved per request and never cached, so a login, a logout or\n * an expiry between two calls is picked up by the next one. When no token is\n * available the request goes out unauthenticated.\n */\nexport function makeAuthMiddleware(\n tokenProvider: BearerTokenProvider,\n): SdkFunctionWrapper {\n return async (action) => {\n const token = await tokenProvider();\n if (!token) {\n return action();\n }\n\n return action({ authorization: `Bearer ${token}` });\n };\n}\n","import { gql } from \"graphql-tag\";\nimport {\n PhDocumentFieldsFragmentDoc,\n type ActionInput,\n type PhDocumentFieldsFragment,\n type Scalars,\n} from \"../graphql/gen/schema.js\";\nimport type { RemoteOperation } from \"../remote-controller/types.js\";\n\n/**\n * The operation selection of `GetDocumentOperations`, lifted into a fragment so\n * the write path can reuse `remoteOperationToLocal` on the items it selects.\n */\nexport const ReactorOperationFieldsFragmentDoc = gql`\n fragment ReactorOperationFields on ReactorOperation {\n index\n timestampUtcMs\n hash\n skip\n error\n deniedReason\n id\n action {\n id\n type\n timestampUtcMs\n input\n scope\n context {\n signer {\n user {\n address\n networkId\n chainId\n }\n app {\n name\n key\n }\n signatures\n }\n }\n }\n }\n`;\n\n/**\n * `mutateDocument` plus the operations the mutation produced.\n *\n * The generated `MutateDocument` only selects the document fields, but\n * `dispatchActions` reads per-action failures out of `result.operations[scope]`\n * (`src/actions/dispatch.ts`), so the reducer-level errors would be lost.\n *\n * The operations filter keeps the extra selection to the operations this call\n * could have appended rather than the whole history. All three of its fields\n * matter:\n * - `sinceRevision` is the lowest head revision across the targeted scopes, so\n * it is only a safe window when the selection is scope-limited as well;\n * - `scopes` limits the response to the scopes the pushed actions target,\n * without it the server walks every scope of the document\n * (`packages/reactor/src/core/reactor.ts` `getOperations`);\n * - `branch` selects the branch the operations are read from, and is the same\n * variable the mutation writes to. It used to be two - the write went through\n * a `view`, the filter took its own `branch` - and they had to be kept equal\n * by hand or the operations came from `main` while the actions were applied\n * elsewhere. One variable cannot disagree with itself.\n */\nexport const MutateDocumentWithOperationsDocument = gql`\n mutation MutateDocumentWithOperations(\n $documentIdentifier: String!\n $actions: [ActionInput!]!\n $sinceRevision: Int\n $scopes: [String!]\n $branch: String\n ) {\n mutateDocument: execute(\n documentIdentifier: $documentIdentifier\n actions: $actions\n branch: $branch\n ) {\n ...PHDocumentFields\n operations(\n filter: {\n sinceRevision: $sinceRevision\n scopes: $scopes\n branch: $branch\n }\n ) {\n items {\n ...ReactorOperationFields\n }\n }\n }\n }\n ${PhDocumentFieldsFragmentDoc}\n ${ReactorOperationFieldsFragmentDoc}\n`;\n\nexport type MutateDocumentWithOperationsVariables = {\n documentIdentifier: Scalars[\"String\"][\"input\"];\n actions: ReadonlyArray<ActionInput>;\n sinceRevision?: Scalars[\"Int\"][\"input\"];\n scopes?: ReadonlyArray<Scalars[\"String\"][\"input\"]>;\n branch?: Scalars[\"String\"][\"input\"];\n};\n\nexport type MutateDocumentWithOperationsResult = {\n readonly mutateDocument: PhDocumentFieldsFragment & {\n readonly operations?: {\n readonly items: ReadonlyArray<RemoteOperation>;\n } | null;\n };\n};\n","import type {\n Action,\n DocumentModelModule,\n ISigner,\n Operation,\n PHDocument,\n} from \"@powerhousedao/shared/document-model\";\nimport { hashDocumentStateForScope } from \"@powerhousedao/shared/document-model\";\n\n/**\n * Stamps an action with the head of the scope it targets.\n *\n * `prevOpHash` is the hash of the scope state the action is meant to apply to;\n * for a document at head that is the hash of the last operation in the scope,\n * which the read path cannot fetch, so it is recomputed from the state.\n * `prevOpIndex` is the index of that last operation: revisions count\n * operations and indices are zero based, so an empty scope stamps `-1`, which\n * matches what the remote controller records.\n *\n * `revision` overrides the scope revision the index is derived from. Only a\n * batch needs it - {@link prepareSignedActions} stamps action N at the revision\n * the N actions before it will have produced, which the document itself does\n * not know yet. `prevOpHash` always comes from the supplied document's state.\n */\nexport function stampAction(\n action: Action,\n document: PHDocument,\n revision = document.header.revision[action.scope] ?? 0,\n): Action {\n return {\n ...action,\n context: {\n ...action.context,\n prevOpHash: hashDocumentStateForScope(document, action.scope),\n prevOpIndex: revision - 1,\n },\n };\n}\n\n/**\n * Signs a stamped action, preserving any signatures it already carries.\n *\n * The signer reads `context.prevOpHash` off the action, so this must run after\n * {@link stampAction}.\n */\nexport async function signStampedAction(\n action: Action,\n signer: ISigner,\n signal?: AbortSignal,\n): Promise<Action> {\n const actionSigner = action.context?.signer;\n const user = actionSigner?.user ?? signer.user;\n const app = actionSigner?.app ?? signer.app;\n if (!user || !app) {\n throw new Error(\n \"cannot sign an action: the signer has no user or app identity\",\n );\n }\n\n const signature = await signer.signAction(action, signal);\n return {\n ...action,\n context: {\n ...action.context,\n signer: {\n user,\n app,\n signatures: [...(actionSigner?.signatures ?? []), signature],\n },\n },\n };\n}\n\n/**\n * Actions a snapshot batch cannot predict the next state for.\n *\n * `UNDO`, `REDO` and `PRUNE` rewrite history the light read path never fetched\n * (and the reducer appends no operation for them); `NOOP` is only ever produced\n * by an undo chain; the document-scope actions run through the reactor's\n * document-action handler rather than a document-model reducer\n * (`DOCUMENT_SCOPE_ACTIONS` in packages/reactor/src/executor/util.ts) and\n * `UPGRADE_DOCUMENT` changes which reducer applies mid-batch.\n */\nconst unsupportedBatchActions: ReadonlySet<string> = new Set([\n \"UNDO\",\n \"REDO\",\n \"PRUNE\",\n \"NOOP\",\n \"CREATE_DOCUMENT\",\n \"DELETE_DOCUMENT\",\n \"UPGRADE_DOCUMENT\",\n \"ADD_RELATIONSHIP\",\n \"REMOVE_RELATIONSHIP\",\n \"UPDATE_RELATIONSHIP\",\n]);\n\n/**\n * The base-reducer protocol version to predict with when the snapshot's header\n * carries none.\n *\n * `baseReducer` reads `baseReducerVersion(document.header)` for every action and\n * throws when the header has no `protocolVersions` - and a header built by\n * {@link phDocumentFromGetDocument} never has one, because the GraphQL\n * `PHDocument` type does not expose it. The version only selects between the v1\n * and v2 UNDO/NOOP branches, and every action reaching the prediction loop is an\n * ordinary append-only one, so it cannot change the predicted state here; it is\n * passed purely so the lookup does not throw.\n */\nconst predictionProtocolVersion = 2;\n\n/**\n * Stamps and signs a batch of actions against one document snapshot, so every\n * action carries the head its predecessor will leave behind.\n *\n * The server executes the array in order, each action against the state the one\n * before it produced. The snapshot the light client reads has correct state and\n * per-scope revisions but NO operation history (see `adapter.ts`), so the chain\n * is predicted here: reduce action N over the working document to get the state\n * action N+1 hashes, and carry a virtual revision alongside it. The revision has\n * to be tracked separately because the reducer derives operation indices from\n * the last stored operation, and with an empty history that counts from zero\n * rather than from the document's real revision.\n *\n * A single action needs no prediction and therefore no `module`, which keeps\n * today's callers working unchanged. Two or more require the document's exact\n * reducer, one shared scope (the reactor rejects mixed-scope jobs) and only\n * append-only actions. Anything else rejects: a batch that cannot be predicted\n * must fail before the mutation, never be downgraded to unsigned.\n */\nexport async function prepareSignedActions(\n actions: readonly Action[],\n snapshot: PHDocument,\n signer: ISigner,\n module?: DocumentModelModule<any>,\n signal?: AbortSignal,\n): Promise<Action[]> {\n if (actions.length === 0) {\n return [];\n }\n\n if (actions.length === 1) {\n return [\n await signStampedAction(\n stampAction(actions[0], snapshot),\n signer,\n signal,\n ),\n ];\n }\n\n const scope = sharedScope(actions);\n assertSupportedBatch(actions);\n\n if (!module) {\n throw new Error(\n `cannot sign ${actions.length} actions: no document model module for ${snapshot.header.documentType} was supplied, so the batch state cannot be predicted`,\n );\n }\n\n // A working copy: the reducer never writes to its input, but the scope's\n // operation list is read back below, so it must exist even for a scope the\n // snapshot's `revisionsList` did not mention.\n let working: PHDocument = {\n ...snapshot,\n operations: {\n ...snapshot.operations,\n [scope]: [...(snapshot.operations[scope] ?? [])],\n },\n };\n let revision = snapshot.header.revision[scope] ?? 0;\n\n const signed: Action[] = [];\n for (const [index, action] of actions.entries()) {\n throwIfAborted(signal, index);\n\n const stamped = stampAction(action, working, revision);\n const signedAction = await signStampedAction(stamped, signer, signal);\n signed.push(signedAction);\n\n // The last action's state is never hashed by anything, but reducing it\n // anyway is what proves the whole batch is applicable before it is sent.\n const before = scopeOperationCount(working, scope);\n let next: PHDocument;\n try {\n next = module.reducer(working, signedAction, undefined, {\n protocolVersion:\n working.header.protocolVersions?.[\"base-reducer\"] ??\n predictionProtocolVersion,\n });\n } catch (error) {\n throw new Error(\n `cannot sign action ${index} (${action.type}): the ${snapshot.header.documentType} reducer rejected it, so the rest of the batch cannot be predicted`,\n { cause: error },\n );\n }\n\n const after = scopeOperationCount(next, scope);\n if (after !== before + 1) {\n throw new Error(\n `cannot sign action ${index} (${action.type}): the reducer appended ${after - before} operations to ${scope}, expected exactly 1`,\n );\n }\n\n working = next;\n // Deliberately not `next.operations[scope].at(-1).index`: those indices\n // count from the snapshot's empty history, not from the document's head.\n revision += 1;\n }\n\n return signed;\n}\n\n/**\n * How many operations a scope holds.\n *\n * The index signature types the array as always present, but a module's reducer\n * is arbitrary code: one that hands back a document without the scope should\n * produce the actionable error above, not a `TypeError` on `.length`.\n */\nfunction scopeOperationCount(document: PHDocument, scope: string): number {\n const operations: Record<string, Operation[] | undefined> =\n document.operations;\n return operations[scope]?.length ?? 0;\n}\n\n/** The one scope a reactor job may span (`getSharedActionScope`). */\nfunction sharedScope(actions: readonly Action[]): string {\n const scope = actions[0].scope;\n const mixed = actions.find((action) => action.scope !== scope);\n if (mixed) {\n throw new Error(\n `cannot sign a batch spanning scopes \"${scope}\" and \"${mixed.scope}\": every action in one request must share a scope`,\n );\n }\n return scope;\n}\n\nfunction assertSupportedBatch(actions: readonly Action[]): void {\n const unsupported = actions.find((action) =>\n unsupportedBatchActions.has(action.type),\n );\n if (unsupported) {\n throw new Error(\n `cannot sign a batch containing ${unsupported.type}: it needs operation history or an alternate executor path, so send it as a single action`,\n );\n }\n}\n\nfunction throwIfAborted(signal: AbortSignal | undefined, index: number): void {\n if (signal?.aborted) {\n throw new Error(`signing aborted before action ${index}`, {\n cause: signal.reason as unknown,\n });\n }\n}\n","import type { DocumentModelSource } from \"@powerhousedao/reactor\";\nimport type { RegistryPackageSource } from \"@powerhousedao/shared\";\nimport type { DocumentModelLib, DocumentModelModule } from \"document-model\";\nimport type {\n IPackageManager,\n IPackageListerUnsubscribe,\n IPackagesListener,\n PackageManagerInstallResult,\n} from \"../types/vetra.js\";\n\n/**\n * A fixed set of packages presented through the `IPackageManager` interface,\n * so the package-derived hooks - `useDocumentModelModules`,\n * `useDocumentModelModuleById`, `useEditorModules`, `useVetraPackages` - work\n * below `GraphQLReactorProvider` exactly as they do below Connect.\n *\n * Connect's package manager installs, updates and removes packages at runtime.\n * A light app instead declares its packages once, as code it imports itself\n * (every generated package root exports `manifest`, `documentModels`, `editors`\n * and `upgradeManifests` by name), so every mutating member throws and\n * `subscribe` never emits. For hand-picked modules without package artifacts,\n * {@link packageFromDocumentModels} wraps them in one synthetic package.\n */\nexport class StaticPackageManager implements IPackageManager {\n readonly registryUrl = null;\n readonly packages: DocumentModelLib[];\n\n // DocumentModelLib<any>: a real package's concrete modules are invariant in\n // their state generic, so the boundary needs the same escape the reactor\n // core uses for DocumentModelSource (packages/reactor/src/core/model-sources.ts).\n constructor(packages: readonly DocumentModelLib<any>[]) {\n this.packages = [...packages];\n }\n\n /**\n * Resolves a module by document type across all packages. Mirrors the\n * registry's semantics (`IDocumentModelRegistry.getModule`): the LATEST\n * version wins, with `version ?? 1` as each module's default.\n */\n load(documentType: string): Promise<DocumentModelSource> {\n const modules = this.packages.flatMap((pkg) => pkg.documentModels);\n try {\n return Promise.resolve(resolveDocumentModelModule(modules, documentType));\n } catch (error) {\n return Promise.reject(error as Error);\n }\n }\n\n subscribe(_handler: IPackagesListener): IPackageListerUnsubscribe {\n return () => {};\n }\n\n getPackageSource(_packageName: string): RegistryPackageSource | null {\n return null;\n }\n\n getPackageVersion(_packageName: string): string | undefined {\n return undefined;\n }\n\n getRegistryPackages(): { name: string; version: string | undefined }[] {\n return [];\n }\n\n addPackage(_packageName: string): PackageManagerInstallResult {\n throw staticPackageManagerError(\"addPackage\");\n }\n\n addPackages(_packageNames: string[]): PackageManagerInstallResult[] {\n throw staticPackageManagerError(\"addPackages\");\n }\n\n removePackage(_name: string): void {\n throw staticPackageManagerError(\"removePackage\");\n }\n\n updateLocalPackage(_pkg: DocumentModelLib, _version?: string): void {\n throw staticPackageManagerError(\"updateLocalPackage\");\n }\n\n addLocalPackage(\n _name: string,\n _loadedPackage: DocumentModelLib,\n _version?: string,\n ): void {\n throw staticPackageManagerError(\"addLocalPackage\");\n }\n}\n\n/**\n * Resolves one document-model module out of a flat module list, with the same\n * rule the reactor registry uses (`IDocumentModelRegistry.getModule`, at\n * packages/reactor/src/registry/implementation.ts): with a `version`, only an\n * EXACT `version ?? 1` match resolves; without one, the LATEST version wins.\n *\n * Signing an existing document needs the exact rule. A document carries the\n * model version it was written with in `state.document.version`, and its\n * reducer is the only one whose operations that document's history can accept -\n * so \"latest\" is correct only when no version is asked for.\n *\n * Pure and dependency-free on purpose: this is reachable from the browser\n * entry, so it must not pull the reactor registry in as a value.\n */\nexport function resolveDocumentModelModule(\n modules: readonly DocumentModelModule<any>[],\n documentType: string,\n version?: number,\n): DocumentModelModule<any> {\n let latestModule: DocumentModelModule<any> | undefined;\n let latestVersion = -1;\n\n for (const module of modules) {\n if (module.documentModel.global.id !== documentType) {\n continue;\n }\n const moduleVersion = module.version ?? 1;\n if (version !== undefined && moduleVersion === version) {\n return module;\n }\n if (moduleVersion > latestVersion) {\n latestVersion = moduleVersion;\n latestModule = module;\n }\n }\n\n if (version === undefined && latestModule) {\n return latestModule;\n }\n\n throw new Error(\n version === undefined\n ? `Unknown document type: ${documentType}`\n : `Unknown document model version: ${documentType} v${version}` +\n (latestModule\n ? ` (available: ${availableVersions(modules, documentType).join(\", \")})`\n : \" (no module for this document type)\"),\n );\n}\n\nfunction availableVersions(\n modules: readonly DocumentModelModule<any>[],\n documentType: string,\n): number[] {\n return modules\n .filter((module) => module.documentModel.global.id === documentType)\n .map((module) => module.version ?? 1)\n .sort((a, b) => a - b);\n}\n\nfunction staticPackageManagerError(member: string): Error {\n return new Error(\n `${member} is not supported: StaticPackageManager holds a fixed set of packages`,\n );\n}\n\n/**\n * Wraps hand-picked modules in one synthetic `DocumentModelLib`, for apps that\n * assemble their model list from mixed sources instead of passing whole\n * packages. The manifest is fabricated - loose modules carry none - so prefer\n * the `packages` prop with the real package exports when you have them: a real\n * package also carries `editors`, which makes the editor hooks work.\n */\nexport function packageFromDocumentModels(\n documentModels: readonly DocumentModelModule<any>[],\n): DocumentModelLib {\n return {\n manifest: {\n name: \"graphql-reactor-provider\",\n description: \"Document models passed to GraphQLReactorProvider\",\n },\n documentModels,\n editors: [],\n };\n}\n","import { Kind, type DocumentNode } from \"graphql\";\nimport { GraphQLClient } from \"graphql-request\";\nimport type { SdkFunctionWrapper } from \"../graphql/gen/schema.js\";\n\n/**\n * The factory a GraphQL code generator produces for a schema.\n *\n * It is the signature of `getSdk` emitted by the `typescript-graphql-request`\n * plugin - the generated `getSdk` in `src/graphql/gen/schema.ts` is the\n * canonical example - so a project can hand its own generated function straight\n * to {@link SubgraphSdkRegistry.get} and keep every operation typed.\n */\nexport type SubgraphSdkFactory<TSdk> = (\n client: GraphQLClient,\n withWrapper?: SdkFunctionWrapper,\n) => TSdk;\n\n/**\n * The middleware a subgraph SDK is bound with. Re-exported here because a\n * hand-written SDK has to name it, while a generated one declares its own.\n */\nexport type { SdkFunctionWrapper };\n\n/**\n * A GraphQL document that carries its result and variable types.\n *\n * This is the shape a code generator gives a document (`TypedDocumentNode`),\n * declared structurally so that reactor-browser needs no dependency on\n * `@graphql-typed-document-node/core`. A plain `DocumentNode` satisfies it too,\n * with the result type falling back to whatever the caller passes explicitly.\n */\nexport type TypedGraphQLDocument<TResult, TVariables> = DocumentNode & {\n __apiType?: (variables: TVariables) => TResult;\n};\n\n/** Extras for a one-off request. */\nexport type GraphQLRequestOptions = {\n /**\n * The operation name reported to the auth and logging middleware. Read off\n * the document when it is not given.\n */\n operationName?: string;\n\n /**\n * The operation type reported to the middleware, e.g. `\"mutation\"`. Read off\n * the document when it is not given.\n */\n operationType?: string;\n\n signal?: AbortSignal;\n};\n\n/** What {@link describeGraphQLDocument} could not read off a document. */\nconst unnamedOperation = \"AnonymousOperation\";\nconst defaultOperationType = \"query\";\n\n/**\n * Derives a subgraph's endpoint from the Switchboard's GraphQL endpoint.\n *\n * Subgraphs are served next to the supergraph, at `<graphql base>/<name>`, so\n * `http://localhost:4001/graphql` plus `statements` is\n * `http://localhost:4001/graphql/statements`.\n */\nexport function subgraphUrlFromGraphqlUrl(url: string, name: string): string {\n const trimmed = name.trim();\n if (trimmed === \"\") {\n throw new Error(\"a subgraph name is required\");\n }\n return `${url.replace(/\\/+$/, \"\")}/${trimmed}`;\n}\n\n/**\n * Reads the operation name and type off a document, for the middleware.\n *\n * Nothing depends on getting this right - it is reported to the middleware, not\n * sent to the server - so an unreadable document falls back to an anonymous\n * query rather than throwing.\n */\nexport function describeGraphQLDocument(document: string | DocumentNode): {\n operationName: string;\n operationType: string;\n} {\n if (typeof document !== \"string\") {\n const operation = document.definitions.find(\n (definition) => definition.kind === Kind.OPERATION_DEFINITION,\n );\n if (!operation || operation.kind !== Kind.OPERATION_DEFINITION) {\n return {\n operationName: unnamedOperation,\n operationType: defaultOperationType,\n };\n }\n return {\n operationName: operation.name?.value ?? unnamedOperation,\n operationType: operation.operation,\n };\n }\n\n const match =\n /\\b(query|mutation|subscription)\\s+([_A-Za-z][_0-9A-Za-z]*)/.exec(document);\n if (!match) {\n return {\n operationName: unnamedOperation,\n operationType: /\\bmutation\\b/.test(document)\n ? \"mutation\"\n : defaultOperationType,\n };\n }\n return { operationName: match[2], operationType: match[1] };\n}\n\n/** A subgraph transport and the SDK last bound to it. */\ntype SubgraphBinding = {\n transport: GraphQLClient;\n factory?: SubgraphSdkFactory<unknown>;\n sdk?: unknown;\n};\n\n/**\n * Binds typed subgraph SDKs to one Switchboard's transport and auth.\n *\n * Every capability a Switchboard exposes lives behind the same base URL, so an\n * app should not have to build a second client - with a second copy of the auth\n * configuration - to reach a project's own subgraph. The registry derives the\n * endpoint, reuses one transport per subgraph and hands the code generator's\n * `getSdk` the very middleware the reactor operations already go through.\n *\n * Transport and typing only: subgraph results are not cached and produce no\n * change events.\n */\nexport class SubgraphSdkRegistry {\n private readonly url: string;\n private readonly middleware: SdkFunctionWrapper | undefined;\n private readonly bindings = new Map<string, SubgraphBinding>();\n\n constructor(url: string, middleware?: SdkFunctionWrapper) {\n this.url = url;\n this.middleware = middleware;\n }\n\n /**\n * Returns the subgraph's SDK, building it on first use.\n *\n * The transport is kept per subgraph name, so repeated calls do not rebuild\n * it. The SDK itself is only reused when the same factory is passed again -\n * two different generated SDKs over one subgraph each get their own, rather\n * than the second call being handed the first one's methods.\n */\n get<TSdk>(name: string, getSdk: SubgraphSdkFactory<TSdk>): TSdk {\n const binding = this.binding(name);\n if (binding.factory === getSdk) {\n return binding.sdk as TSdk;\n }\n\n const sdk = getSdk(binding.transport, this.middleware);\n binding.factory = getSdk as SubgraphSdkFactory<unknown>;\n binding.sdk = sdk;\n return sdk;\n }\n\n /** Returns the subgraph's endpoint, for diagnostics and tests. */\n urlFor(name: string): string {\n return subgraphUrlFromGraphqlUrl(this.url, name);\n }\n\n private binding(name: string): SubgraphBinding {\n const existing = this.bindings.get(name);\n if (existing) {\n return existing;\n }\n\n const binding: SubgraphBinding = {\n transport: new GraphQLClient(this.urlFor(name)),\n };\n this.bindings.set(name, binding);\n return binding;\n }\n}\n","import { print } from \"graphql\";\nimport { createClient } from \"graphql-ws/client\";\nimport {\n DocumentChangesDocument,\n type DocumentChangesSubscription,\n} from \"../graphql/gen/schema.js\";\nimport type { BearerTokenProvider } from \"./auth.js\";\n\n/** The `documentChanges` payload, exactly as the Switchboard sends it. */\nexport type DocumentChangesEventPayload =\n DocumentChangesSubscription[\"documentChanges\"];\n\n/** The connection payload sent with the `ConnectionInit` message. */\nexport type ConnectionParams = Record<string, string>;\n\nexport type DocumentChangesSubscriptionOptions = {\n /** The websocket endpoint, e.g. `ws://localhost:4001/graphql/subscriptions`. */\n wsUrl: string;\n\n /**\n * Resolves the `ConnectionInit` payload. Called again on every reconnect, so\n * a token that expired while the socket was down is refreshed on the way back\n * up.\n */\n connectionParams?: () => Promise<ConnectionParams>;\n\n /** Called once per server event. */\n onEvent: (event: DocumentChangesEventPayload) => void;\n\n /**\n * Called when the socket gives up: the retries built into `graphql-ws` are\n * exhausted, or the server rejected the subscription. Realtime is an\n * enhancement, so callers are expected to log and carry on.\n */\n onError: (error: unknown) => void;\n};\n\n/**\n * Opens one `documentChanges` subscription and feeds every event to `onEvent`.\n *\n * The subscription is a firehose: no `search` argument, so the server sends\n * every change the connection is allowed to see and the caller filters. This is\n * the only module that knows about `graphql-ws`.\n *\n * Returns the stop function, which cancels the subscription and closes the\n * socket. It is safe to call more than once.\n */\nexport function startDocumentChangesSubscription(\n options: DocumentChangesSubscriptionOptions,\n): () => void {\n const client = createClient({\n url: options.wsUrl,\n connectionParams: options.connectionParams,\n });\n\n const unsubscribe = client.subscribe<DocumentChangesSubscription>(\n {\n operationName: \"DocumentChanges\",\n query: print(DocumentChangesDocument),\n },\n {\n next: (result) => {\n const event = result.data?.documentChanges;\n if (event) {\n options.onEvent(event);\n }\n },\n error: (error) => options.onError(error),\n // The server never completes this subscription of its own accord; a\n // completion means the socket was closed, which needs no handling.\n complete: () => undefined,\n },\n );\n\n let stopped = false;\n return () => {\n if (stopped) {\n return;\n }\n stopped = true;\n unsubscribe();\n void client.dispose();\n };\n}\n\n/**\n * Derives the websocket endpoint from the GraphQL http endpoint.\n *\n * `http://host/graphql` becomes `ws://host/graphql/subscriptions`, which is\n * where the Switchboard mounts its websocket server (`packages/reactor-api`\n * `startServer`). A URL that already speaks `ws`/`wss` only gets the path.\n */\nexport function subscriptionsUrlFromGraphqlUrl(url: string): string {\n const trimmed = url.replace(/\\/+$/, \"\");\n const wsUrl = trimmed.startsWith(\"https://\")\n ? `wss://${trimmed.slice(\"https://\".length)}`\n : trimmed.startsWith(\"http://\")\n ? `ws://${trimmed.slice(\"http://\".length)}`\n : trimmed;\n return `${wsUrl}/subscriptions`;\n}\n\n/**\n * Turns a bearer token provider into `connectionParams`.\n *\n * The header key is the lowercase `authorization` the Switchboard's websocket\n * context factory reads. Without a token the payload is empty: an open\n * Switchboard serves anonymous subscribers.\n */\nexport function makeAuthConnectionParams(\n tokenProvider: BearerTokenProvider,\n): () => Promise<ConnectionParams> {\n return async (): Promise<ConnectionParams> => {\n const token = await tokenProvider();\n if (!token) {\n return {};\n }\n return { authorization: `Bearer ${token}` };\n };\n}\n","import type {\n DocumentChangeEvent,\n DocumentChangeType,\n OperationFilter,\n PagedResults,\n PagingOptions,\n PropagationMode,\n SearchFilter,\n ViewFilter,\n} from \"@powerhousedao/reactor\";\nimport type {\n ISigner,\n PHDocumentState,\n} from \"@powerhousedao/shared/document-model\";\nimport {\n normalizeDocumentModelVersion,\n toTransportAction,\n} from \"@powerhousedao/shared/document-model\";\nimport type {\n Action,\n DocumentModelModule,\n Operation,\n PHDocument,\n} from \"document-model\";\nimport { logger } from \"document-model\";\nimport type { Variables } from \"graphql-request\";\nimport { createClient } from \"../graphql/client.js\";\nimport {\n DocumentChangeType as GqlDocumentChangeType,\n PropagationMode as GqlPropagationMode,\n type OperationsFilterInput,\n type PagingInput,\n type ViewFilterInput,\n} from \"../graphql/gen/schema.js\";\nimport type { ReactorGraphQLClient } from \"../graphql/types.js\";\nimport { DOCUMENT_CHANGE_TYPE } from \"../reactor-interop.js\";\nimport { remoteOperationToLocal } from \"../remote-controller/utils.js\";\nimport type { IReactorBrowserClient } from \"../types/reactor-browser-client.js\";\nimport {\n phDocumentFromGetDocument,\n phDocumentFromMutation,\n} from \"./adapter.js\";\nimport {\n ambientRenownTokenProvider,\n makeAuthMiddleware,\n type BearerTokenProvider,\n} from \"./auth.js\";\nimport {\n MutateDocumentWithOperationsDocument,\n type MutateDocumentWithOperationsResult,\n type MutateDocumentWithOperationsVariables,\n} from \"./operations.js\";\nimport { prepareSignedActions } from \"./signing.js\";\nimport { resolveDocumentModelModule } from \"./static-package-manager.js\";\nimport {\n describeGraphQLDocument,\n SubgraphSdkRegistry,\n type GraphQLRequestOptions,\n type SubgraphSdkFactory,\n type TypedGraphQLDocument,\n} from \"./subgraph.js\";\nimport {\n makeAuthConnectionParams,\n startDocumentChangesSubscription,\n subscriptionsUrlFromGraphqlUrl,\n type DocumentChangesEventPayload,\n} from \"./subscriptions.js\";\n\nexport type GraphQLReactorClientOptions = {\n /** The Switchboard GraphQL endpoint, e.g. `http://localhost:4001/graphql`. */\n url: string;\n\n /**\n * A pre-built SDK to use instead of the transport derived from `url`.\n * Mainly a test seam.\n *\n * A client built this way carries no auth middleware: the injected SDK owns\n * its own transport, and therefore its own headers.\n */\n graphqlClient?: ReactorGraphQLClient;\n\n /**\n * Resolves the bearer token sent with every request, per request.\n *\n * Defaults to {@link ambientRenownTokenProvider}, i.e. the token of the\n * logged-in Renown user, or none when nobody is logged in.\n */\n tokenProvider?: BearerTokenProvider;\n\n /**\n * The Switchboard GraphQL subscriptions endpoint, e.g.\n * `ws://localhost:4001/graphql/subscriptions`.\n *\n * Defaults to the endpoint derived from `url` by\n * {@link subscriptionsUrlFromGraphqlUrl}.\n */\n subscriptionsUrl?: string;\n\n /**\n * Whether server-pushed changes are delivered to subscribers.\n *\n * On by default: the first `subscribe` call opens a websocket and every\n * change the Switchboard reports is emitted to matching subscribers, so\n * documents another user, tab or processor writes invalidate the cache.\n *\n * Set it to `false` where there is no websocket to talk to. The client then\n * only emits the changes it made itself.\n */\n realtime?: boolean;\n\n /**\n * The document model modules used to sign a batch of two or more actions.\n *\n * Signing action N+1 needs the state action N leaves behind, and only the\n * document's own reducer can predict it - so a batch is signable only when\n * the module matching the document's type AND its exact\n * `state.document.version` is here. One action needs no prediction and is\n * signed without any of this.\n *\n * Read once, when the client is built. Below `GraphQLReactorProvider` this\n * is its `documentModels` prop; a client constructed directly passes its own.\n */\n documentModels?: readonly DocumentModelModule<any>[];\n\n /**\n * Signs the actions this client pushes, instead of the logged-in Renown user.\n *\n * Left out - the normal case - the signer is resolved per push from\n * `window.ph.renown`, so a page signs as whoever is logged in and pushes\n * unsigned when nobody is. Set it where there is no Renown to read: tests,\n * scripts, and integration suites that must sign deterministically.\n */\n signer?: ISigner;\n};\n\n/** Paging defaults, matching the reactor's own client. */\nconst defaultPaging: PagingOptions = { cursor: \"0\", limit: 100 };\n\n/** A registered `subscribe` call. */\ntype ChangeListener = {\n search: SearchFilter;\n callback: (event: DocumentChangeEvent) => void;\n};\n\n/**\n * The marker {@link isGraphQLReactorClient} looks for.\n *\n * A page can end up with two copies of this module - an app that bundles a\n * package carrying its own copy, or a dev server that hot-replaced it - and\n * then `instanceof` compares an instance against the other copy's class object\n * and answers `false`. A branded property survives both.\n */\nconst graphQLReactorClientBrand = \"__powerhouseGraphQLReactorClient\" as const;\n\n/**\n * A light implementation of {@link IReactorBrowserClient} that talks plain\n * GraphQL to a Switchboard, with no reactor in the bundle.\n *\n * It fills the same `window.ph` slots the full in-browser reactor client fills,\n * so the reactor-browser hooks cannot tell the two apart.\n */\nexport class GraphQLReactorClient implements IReactorBrowserClient {\n /** See {@link isGraphQLReactorClient}. */\n readonly [graphQLReactorClientBrand] = true;\n\n private readonly sdk: ReactorGraphQLClient;\n private readonly subgraphs: SubgraphSdkRegistry;\n private readonly listeners: ChangeListener[] = [];\n private readonly tokenProvider: BearerTokenProvider;\n private readonly subscriptionsUrl: string | undefined;\n private readonly documentModels: readonly DocumentModelModule<any>[];\n private readonly signer: ISigner | undefined;\n private stopRealtime: (() => void) | undefined;\n private realtimeStarted = false;\n private realtimeGeneration = 0;\n private realtimeErrorLogged = false;\n\n constructor(options: GraphQLReactorClientOptions) {\n this.tokenProvider = options.tokenProvider ?? ambientRenownTokenProvider;\n // Copied, not held: the caller's array must not be able to change which\n // reducer a later batch is signed with.\n this.documentModels = [...(options.documentModels ?? [])];\n this.signer = options.signer;\n this.subscriptionsUrl =\n options.realtime === false\n ? undefined\n : (options.subscriptionsUrl ??\n subscriptionsUrlFromGraphqlUrl(options.url));\n\n // The middleware wraps the generated SDK methods AND `RunDocument`, so the\n // hand-authored mutation is authenticated by the same code path.\n const middleware = makeAuthMiddleware(this.tokenProvider);\n this.sdk = options.graphqlClient ?? createClient(options.url, middleware);\n // Subgraph transports are always derived from `url` and always carry auth,\n // including when the reactor SDK above was injected: an injected SDK is a\n // test seam that owns its own transport, not a second endpoint.\n this.subgraphs = new SubgraphSdkRegistry(options.url, middleware);\n }\n\n async get<TDocument extends PHDocument>(\n identifier: string,\n view?: ViewFilter,\n signal?: AbortSignal,\n ): Promise<TDocument> {\n const viewInput = viewFilterInputFromViewFilter(view);\n const result = await this.sdk.GetDocument(\n { identifier, view: viewInput },\n undefined,\n signal,\n );\n\n const document = result.document;\n if (!document) {\n throw new Error(`Document not found: ${identifier}`);\n }\n\n return phDocumentFromGetDocument<TDocument>(\n document.document,\n view?.branch,\n );\n }\n\n async getOperations(\n documentIdentifier: string,\n view?: ViewFilter,\n filter?: OperationFilter,\n paging?: PagingOptions,\n signal?: AbortSignal,\n ): Promise<PagedResults<Operation>> {\n const viewInput = viewFilterInputFromViewFilter(view);\n const operationsFilter: OperationsFilterInput = {\n documentId: documentIdentifier,\n branch: viewInput?.branch,\n scopes: viewInput?.scopes,\n actionTypes: filter?.actionTypes,\n timestampFrom: filter?.timestampFrom,\n timestampTo: filter?.timestampTo,\n sinceRevision: filter?.sinceRevision,\n };\n const result = await this.sdk.GetDocumentOperations(\n { filter: operationsFilter, paging: pagingInputFromPaging(paging) },\n undefined,\n signal,\n );\n\n const page = result.documentOperations;\n const nextCursor = page.hasNextPage\n ? (page.cursor ?? undefined)\n : undefined;\n const effectivePaging = paging ?? defaultPaging;\n\n return {\n results: page.items.map((item) => remoteOperationToLocal(item)),\n options: effectivePaging,\n nextCursor,\n totalCount: page.totalCount,\n next: nextCursor\n ? () =>\n this.getOperations(\n documentIdentifier,\n view,\n filter,\n { cursor: nextCursor, limit: effectivePaging.limit },\n signal,\n )\n : undefined,\n };\n }\n\n async create<TDocument extends PHDocument = PHDocument>(\n document: PHDocument,\n parentIdentifier?: string,\n signal?: AbortSignal,\n ): Promise<TDocument> {\n const result = await this.sdk.CreateDocument(\n { document, parentIdentifier },\n undefined,\n signal,\n );\n\n const created = phDocumentFromGetDocument<TDocument>(result.createDocument);\n this.emitChange({\n type: DOCUMENT_CHANGE_TYPE.Created,\n documents: [created],\n });\n return created;\n }\n\n /**\n * Pushes actions to the Switchboard and returns the updated document.\n *\n * The document is fetched first: the response is the baseline for the\n * `sinceRevision` filter that narrows the returned operations to the ones\n * this call appended, and it carries the state hash a signed action is\n * stamped with.\n *\n * The emitted `Updated` event carries the document's id, never the\n * identifier this was called with: subscribers - including `DocumentCache` -\n * work in id space.\n */\n async execute<TDocument extends PHDocument>(\n documentIdentifier: string,\n branch: string,\n actions: Action[],\n signal?: AbortSignal,\n ): Promise<TDocument> {\n const document = await this.get(documentIdentifier, { branch }, signal);\n const preparedActions = await prepareActionsForPush(\n actions,\n document,\n this.documentModels,\n this.signer,\n signal,\n );\n\n const variables: MutateDocumentWithOperationsVariables = {\n documentIdentifier,\n // Projected onto the fields the schema declares, so a stamped or signed\n // action does not carry a field the input rejects the whole request for.\n actions: preparedActions.map(toTransportAction),\n sinceRevision: sinceRevisionForActions(document, actions),\n scopes: scopesForActions(actions),\n branch,\n };\n const result =\n await this.sdk.RunDocument<MutateDocumentWithOperationsResult>({\n operationName: \"MutateDocumentWithOperations\",\n operationType: \"mutation\",\n document: MutateDocumentWithOperationsDocument,\n variables,\n signal,\n });\n\n const mutated = result.mutateDocument;\n const updated = phDocumentFromMutation<TDocument>(\n mutated,\n mutated.operations?.items ?? [],\n branch,\n );\n this.emitChange({\n type: DOCUMENT_CHANGE_TYPE.Updated,\n documents: [updated],\n });\n return updated;\n }\n\n /**\n * Deletes a document and announces it as a `Deleted` event.\n *\n * Pass a document id. The server resolves a slug just as happily, but\n * `deleteDocument` returns a boolean - there is no document left to read an\n * id off - so the identifier is announced verbatim on `context.childId`. A\n * subscriber keyed by id, `DocumentCache` included, therefore only reacts to\n * a delete by id.\n */\n async deleteDocument(\n identifier: string,\n propagate?: PropagationMode,\n signal?: AbortSignal,\n ): Promise<void> {\n await this.sdk.DeleteDocument(\n { identifier, propagate: propagationModeInput(propagate) },\n undefined,\n signal,\n );\n\n this.emitChange({\n type: DOCUMENT_CHANGE_TYPE.Deleted,\n documents: [],\n context: { childId: identifier },\n });\n }\n\n /**\n * Registers a change subscriber and returns its unsubscribe function.\n *\n * Two things produce the events delivered here. Every successful `create`,\n * `execute` and `deleteDocument` emits one, which is what makes a\n * `DocumentCache` built on this client invalidate after a dispatch. And,\n * unless realtime is switched off, the first call to this method opens a\n * websocket to the Switchboard and every change it reports - from another\n * user, another tab or a server-side processor - is emitted too. A write of\n * this client's own is therefore announced twice, once locally and once by\n * the server; the cache refetches twice, which is harmless.\n *\n * A websocket that cannot be opened or is refused is logged once and then\n * ignored: realtime is an enhancement, never a dependency. The failed socket\n * is closed, so the next subscriber to arrive tries again.\n *\n * `view` is accepted for interface compatibility and ignored: the emitted\n * documents are whatever the write returned, so there is nothing to re-scope.\n *\n * Events live in id space: `search.ids` is matched against the resolved\n * document id, never against the identifier the write was issued with. The\n * one exception is `deleteDocument`, which has no document to resolve an id\n * from - see its own note. A `DocumentCache` on this client must therefore\n * be read by id: a slug-keyed entry is never invalidated.\n */\n subscribe(\n search: SearchFilter,\n callback: (event: DocumentChangeEvent) => void,\n view?: ViewFilter,\n ): () => void {\n const listener: ChangeListener = { search, callback };\n this.listeners.push(listener);\n this.startRealtime();\n\n return () => {\n const index = this.listeners.indexOf(listener);\n if (index !== -1) {\n this.listeners.splice(index, 1);\n }\n };\n }\n\n /**\n * Closes the realtime socket, if one was opened.\n *\n * Registered subscribers are left in place: they still receive the events\n * this client produces itself.\n *\n * Disposing is NOT final - a later `subscribe` opens a new socket. React\n * remounts a tree by running an effect's cleanup and then the effect again,\n * on the same client, and `StrictMode` does exactly that on every mount; a\n * terminal flag here would leave those pages without realtime for good, with\n * nothing logged.\n */\n dispose(): void {\n this.teardownRealtime();\n }\n\n /**\n * Binds a project's generated SDK to this client's transport and auth.\n *\n * Subgraphs are served next to the reactor's own supergraph, so the endpoint\n * is derived from the client's `url` by appending the name, and the SDK is\n * handed the same auth middleware every reactor call goes through. An app\n * therefore configures one URL and one token provider, and reaches every\n * capability of its Switchboard through this one client.\n *\n * `getSdk` is the function a GraphQL code generator emits for the subgraph's\n * schema - see the README in this folder for the codegen recipe.\n *\n * Transport and typing only. Subgraph results are not cached, produce no\n * change events and never reach `useDocument`.\n */\n subgraph<TSdk>(name: string, getSdk: SubgraphSdkFactory<TSdk>): TSdk {\n return this.subgraphs.get(name, getSdk);\n }\n\n /**\n * Runs a one-off GraphQL document against the Switchboard's own endpoint,\n * through the same transport and auth as everything else.\n *\n * The escape hatch for an operation not worth generating an SDK for. Pass a\n * document a code generator typed and the result type follows; pass a plain\n * `gql` document or a string and name the result type at the call site.\n */\n async request<TResult = unknown, TVariables extends Variables = Variables>(\n document: TypedGraphQLDocument<TResult, TVariables> | string,\n variables?: TVariables,\n options?: GraphQLRequestOptions,\n ): Promise<TResult> {\n const described = describeGraphQLDocument(document);\n return this.sdk.RunDocument<TResult>({\n operationName: options?.operationName ?? described.operationName,\n operationType: options?.operationType ?? described.operationType,\n document,\n variables,\n signal: options?.signal,\n });\n }\n\n /**\n * Opens the realtime socket on the first subscriber.\n *\n * The subscription is a firehose - no `search` argument - and this client\n * applies each subscriber's own filter on the way out, exactly as it does for\n * its own emissions.\n */\n private startRealtime(): void {\n if (!this.subscriptionsUrl || this.realtimeStarted) {\n return;\n }\n\n this.realtimeStarted = true;\n const generation = this.realtimeGeneration;\n const stop = startDocumentChangesSubscription({\n wsUrl: this.subscriptionsUrl,\n connectionParams: makeAuthConnectionParams(this.tokenProvider),\n onEvent: (event) => this.emitServerEvent(event),\n onError: (error) => this.handleRealtimeFailure(generation, error),\n });\n\n if (this.realtimeGeneration !== generation) {\n // The socket failed while it was being opened, so the failure was handled\n // before this stop function existed. Close what it holds.\n stop();\n return;\n }\n this.stopRealtime = stop;\n }\n\n /**\n * Gives up on a failed socket so that a later subscriber can try again.\n *\n * `graphql-ws` retries on its own and only reports here once it has given up,\n * or once the server refused the subscription outright - which is what an\n * auth-enabled Switchboard does to an anonymous subscriber. Keeping the dead\n * stop function would make every later `subscribe` a no-op, so realtime would\n * stay off for the life of the page even after the user signs in.\n *\n * The generation stamp discards a report from a socket that has already been\n * replaced or disposed.\n */\n private handleRealtimeFailure(generation: number, error: unknown): void {\n if (generation !== this.realtimeGeneration) {\n return;\n }\n this.teardownRealtime();\n this.logRealtimeError(error);\n }\n\n /** Closes the socket and lets a later subscriber open a new one. */\n private teardownRealtime(): void {\n this.realtimeGeneration += 1;\n this.realtimeStarted = false;\n this.stopRealtime?.();\n this.stopRealtime = undefined;\n }\n\n /** Maps a server event onto the client-side event and emits it. */\n private emitServerEvent(event: DocumentChangesEventPayload): void {\n this.emitChange({\n type: documentChangeTypes[event.type],\n // The subscription carries no branch, so the documents are read as being\n // on the server's default branch - which is the only branch the\n // Switchboard pushes changes for today.\n documents: event.documents.map((document) =>\n phDocumentFromGetDocument(document),\n ),\n context: event.context\n ? {\n parentId: event.context.parentId ?? undefined,\n childId: event.context.childId ?? undefined,\n }\n : undefined,\n });\n }\n\n /**\n * Reports a broken realtime socket once per client, however many sockets it\n * goes through.\n *\n * `graphql-ws` retries on its own, and a Switchboard without a websocket\n * endpoint would otherwise fill the console for as long as the page is open.\n */\n private logRealtimeError(error: unknown): void {\n if (this.realtimeErrorLogged) {\n return;\n }\n this.realtimeErrorLogged = true;\n logger.warn(\n \"GraphQLReactorClient: realtime document changes are unavailable, falling back to local change events\",\n error,\n );\n }\n\n /**\n * Delivers an event to every matching subscriber.\n *\n * A subscriber that throws is logged and skipped so one bad listener cannot\n * stop the others from being notified.\n */\n private emitChange(event: DocumentChangeEvent): void {\n for (const listener of [...this.listeners]) {\n if (!eventMatchesSearch(event, listener.search)) {\n continue;\n }\n\n try {\n listener.callback(event);\n } catch (error) {\n logger.error(\n \"GraphQLReactorClient: a document change subscriber threw\",\n error,\n );\n }\n }\n }\n}\n\n/**\n * Whether a value is a {@link GraphQLReactorClient}, including one built by\n * another copy of this module.\n *\n * Use this rather than `instanceof`: the brand it tests for is shared by every\n * copy of the class, so a client built by a hot-replaced module or by a package\n * that bundled its own copy is still recognised.\n */\nexport function isGraphQLReactorClient(\n client: unknown,\n): client is GraphQLReactorClient {\n return (\n (client as Partial<GraphQLReactorClient> | null | undefined)?.[\n graphQLReactorClientBrand\n ] === true\n );\n}\n\n/** The schema's change types, mapped onto the reactor's. */\nconst documentChangeTypes: Record<GqlDocumentChangeType, DocumentChangeType> = {\n [GqlDocumentChangeType.Created]: DOCUMENT_CHANGE_TYPE.Created,\n [GqlDocumentChangeType.Deleted]: DOCUMENT_CHANGE_TYPE.Deleted,\n [GqlDocumentChangeType.Updated]: DOCUMENT_CHANGE_TYPE.Updated,\n [GqlDocumentChangeType.ParentAdded]: DOCUMENT_CHANGE_TYPE.ParentAdded,\n [GqlDocumentChangeType.ParentRemoved]: DOCUMENT_CHANGE_TYPE.ParentRemoved,\n [GqlDocumentChangeType.ChildAdded]: DOCUMENT_CHANGE_TYPE.ChildAdded,\n [GqlDocumentChangeType.ChildRemoved]: DOCUMENT_CHANGE_TYPE.ChildRemoved,\n};\n\n/**\n * Decides whether an event reaches a subscriber.\n *\n * Every populated field of the search filter is an AND condition, matching the\n * reactor's own subscription manager - which also treats an empty array as a\n * filter that nothing satisfies. `parentId` is a drive concept and is ignored.\n *\n * A `Deleted` event carries no documents, so it is matched on its\n * `context.childId` for identifier filters and delivered unconditionally to\n * type and slug filters: there is no document left to check them against.\n */\nfunction eventMatchesSearch(\n event: DocumentChangeEvent,\n search: SearchFilter,\n): boolean {\n const deleted = event.type === DOCUMENT_CHANGE_TYPE.Deleted;\n const { ids, slugs, type } = search;\n\n if (ids) {\n const eventIds = deleted\n ? [event.context?.childId]\n : event.documents.map((document) => document.header.id);\n if (!eventIds.some((id) => id !== undefined && ids.includes(id))) {\n return false;\n }\n }\n\n if (slugs && !deleted) {\n const eventSlugs = event.documents.map((document) => document.header.slug);\n if (!eventSlugs.some((slug) => slugs.includes(slug))) {\n return false;\n }\n }\n\n if (type && !deleted) {\n const eventTypes = event.documents.map(\n (document) => document.header.documentType,\n );\n if (!eventTypes.includes(type)) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Maps a reactor `ViewFilter` onto the GraphQL `ViewFilterInput`.\n *\n * Point-in-time reads are rejected: the Switchboard read API has no revision\n * argument, so silently returning the head state would be wrong.\n */\nexport function viewFilterInputFromViewFilter(\n view?: ViewFilter,\n): ViewFilterInput | undefined {\n if (!view) {\n return undefined;\n }\n\n if (view.revision !== undefined) {\n throw new Error(\n \"point-in-time views are not supported by GraphQLReactorClient\",\n );\n }\n\n if (view.branch === undefined && view.scopes === undefined) {\n return undefined;\n }\n\n return { branch: view.branch, scopes: view.scopes };\n}\n\nfunction pagingInputFromPaging(\n paging?: PagingOptions,\n): PagingInput | undefined {\n if (!paging) {\n return undefined;\n }\n return { cursor: paging.cursor, limit: paging.limit };\n}\n\n/**\n * The reactor and the GraphQL schema disagree on the enum: the reactor's\n * `None` is the schema's `ORPHAN`. This is the inverse of the server's\n * `toReactorPropagationMode`.\n */\nconst propagationModeInputs: Record<PropagationMode, GqlPropagationMode> = {\n cascade: GqlPropagationMode.Cascade,\n none: GqlPropagationMode.Orphan,\n};\n\nfunction propagationModeInput(\n propagate?: PropagationMode,\n): GqlPropagationMode | undefined {\n return propagate === undefined ? undefined : propagationModeInputs[propagate];\n}\n\n/**\n * Stamps and signs the actions about to be pushed.\n *\n * With no signer the actions go out exactly as given, batch or not - this\n * client does not require signatures. With one, every action is signed:\n * {@link prepareSignedActions} predicts the chain a batch will produce by\n * running the document's own reducer between signatures, which is why a batch\n * needs the module matching the document's type and exact version.\n *\n * A batch that cannot be predicted - no matching module, mixed scopes, an\n * action needing history - throws here, before the mutation. Sending it\n * unsigned instead would silently drop the signatures the caller asked for.\n */\nasync function prepareActionsForPush(\n actions: Action[],\n document: PHDocument,\n documentModels: readonly DocumentModelModule<any>[],\n explicitSigner: ISigner | undefined,\n signal?: AbortSignal,\n): Promise<Action[]> {\n const signer = explicitSigner ?? resolveAmbientSigner();\n if (!signer || actions.length === 0) {\n return actions;\n }\n\n // Only a batch needs the reducer, and it needs the EXACT one the document was\n // written with - the same rule the server applies in `SimpleJobExecutor`.\n const module =\n actions.length > 1\n ? resolveDocumentModelModule(\n documentModels,\n document.header.documentType,\n documentModelVersion(document),\n )\n : undefined;\n\n return prepareSignedActions(actions, document, signer, module, signal);\n}\n\n/**\n * The document-model version the document's actions must be reduced with.\n *\n * `state` arrives as JSON over GraphQL, so its `document` scope is only as\n * reliable as the server that sent it - one written before that scope existed\n * carries no version at all. `normalizeDocumentModelVersion` maps that, and 0,\n * to 1: the same rule `SimpleJobExecutor` applies before asking the registry\n * for a module, so client and server cannot resolve different reducers.\n */\nfunction documentModelVersion(document: PHDocument): number {\n const documentScope = document.state.document as PHDocumentState | undefined;\n return normalizeDocumentModelVersion(documentScope?.version);\n}\n\n/** Resolves the signer of the logged-in user, if there is one. */\nfunction resolveAmbientSigner(): ISigner | undefined {\n if (typeof window === \"undefined\") {\n return undefined;\n }\n const renown = window.ph?.renown;\n return renown?.user ? renown.signer : undefined;\n}\n\n/**\n * The revision the pushed operations start from: the lowest head revision\n * across the scopes the actions target.\n *\n * The baseline is only meaningful together with {@link scopesForActions}: a\n * batch that touches a scope at revision 1 and one at revision 5000 would\n * otherwise re-download the whole history of every scope of the document.\n */\nfunction sinceRevisionForActions(\n document: PHDocument,\n actions: Action[],\n): number {\n const revisions = actions.map(\n (action) => document.header.revision[action.scope] ?? 0,\n );\n return revisions.length > 0 ? Math.min(...revisions) : 0;\n}\n\n/** The distinct scopes the pushed actions target, in first-seen order. */\nfunction scopesForActions(actions: Action[]): string[] | undefined {\n if (actions.length === 0) {\n return undefined;\n }\n return [...new Set(actions.map((action) => action.scope))];\n}\n","import type {\n PHAppConfigHooks,\n PHAppConfigSetters,\n PHDocumentEditorConfigHooks,\n PHDocumentEditorConfigSetters,\n} from \"@powerhousedao/reactor-browser\";\nimport { makePHEventFunctions } from \"../make-ph-event-functions.js\";\n\nexport const isExternalControlsEnabledEventFunctions = makePHEventFunctions(\n \"isExternalControlsEnabled\",\n);\n\n/** Sets whether external controls are enabled for a given editor. */\nexport const setIsExternalControlsEnabled =\n isExternalControlsEnabledEventFunctions.setValue;\n\n/** Gets whether external controls are enabled for a given editor. */\nexport const useIsExternalControlsEnabled =\n isExternalControlsEnabledEventFunctions.useValue;\n\n/** Adds an event handler for when the external controls enabled state changes. */\nexport const addIsExternalControlsEnabledEventHandler =\n isExternalControlsEnabledEventFunctions.addEventHandler;\n\nconst isDragAndDropEnabledEventFunctions = makePHEventFunctions(\n \"isDragAndDropEnabled\",\n);\n\n/** Sets whether drag and drop is enabled for a given app. */\nexport const setIsDragAndDropEnabled =\n isDragAndDropEnabledEventFunctions.setValue;\n\n/** Gets whether drag and drop is enabled for a given app. */\nexport const useIsDragAndDropEnabled =\n isDragAndDropEnabledEventFunctions.useValue;\n\n/** Adds an event handler for when the drag and drop enabled state changes. */\nexport const addIsDragAndDropEnabledEventHandler =\n isDragAndDropEnabledEventFunctions.addEventHandler;\n\nconst allowedDocumentTypesEventFunctions = makePHEventFunctions(\n \"allowedDocumentTypes\",\n);\n\n/** Sets the allowed document types for a given app. */\nexport const setAllowedDocumentTypes =\n allowedDocumentTypesEventFunctions.setValue;\n\n/** Defines the document types a drive supports.\n *\n * Defaults to all of the document types registered in the reactor.\n */\nexport function useAllowedDocumentTypes() {\n const definedAllowedDocumentTypes =\n allowedDocumentTypesEventFunctions.useValue();\n return definedAllowedDocumentTypes;\n}\n\n/** Adds an event handler for when the allowed document types for a given app changes. */\nexport const addAllowedDocumentTypesEventHandler =\n allowedDocumentTypesEventFunctions.addEventHandler;\n\nexport const phAppConfigSetters: PHAppConfigSetters = {\n allowedDocumentTypes: setAllowedDocumentTypes,\n isDragAndDropEnabled: setIsDragAndDropEnabled,\n};\n\nexport const phDocumentEditorConfigSetters: PHDocumentEditorConfigSetters = {\n isExternalControlsEnabled: setIsExternalControlsEnabled,\n};\n\nexport const phAppConfigHooks: PHAppConfigHooks = {\n allowedDocumentTypes: useAllowedDocumentTypes,\n isDragAndDropEnabled: useIsDragAndDropEnabled,\n};\n\nexport const phDocumentEditorConfigHooks: PHDocumentEditorConfigHooks = {\n isExternalControlsEnabled: useIsExternalControlsEnabled,\n};\n","import type {\n PHAppConfigKey,\n PHDocumentEditorConfigKey,\n PHGlobalConfigHooks,\n PHGlobalConfigHooksForKey,\n PHGlobalConfigKey,\n PHGlobalConfigSetters,\n PHGlobalConfigSettersForKey,\n} from \"@powerhousedao/reactor-browser\";\nimport { makePHEventFunctions } from \"../make-ph-event-functions.js\";\nimport {\n phAppConfigHooks,\n phAppConfigSetters,\n phDocumentEditorConfigHooks,\n phDocumentEditorConfigSetters,\n} from \"./editor.js\";\n\nexport const {\n useValue: useRouterBasename,\n setValue: setRouterBasename,\n addEventHandler: addRouterBasenameEventHandler,\n} = makePHEventFunctions(\"routerBasename\");\n\nexport const {\n useValue: useVersion,\n setValue: setVersion,\n addEventHandler: addVersionEventHandler,\n} = makePHEventFunctions(\"version\");\n\nexport const {\n useValue: useRequiresHardRefresh,\n setValue: setRequiresHardRefresh,\n addEventHandler: addRequiresHardRefreshEventHandler,\n} = makePHEventFunctions(\"requiresHardRefresh\");\n\nexport const {\n useValue: useWarnOutdatedApp,\n setValue: setWarnOutdatedApp,\n addEventHandler: addWarnOutdatedAppEventHandler,\n} = makePHEventFunctions(\"warnOutdatedApp\");\n\nexport const {\n useValue: useStudioMode,\n setValue: setStudioMode,\n addEventHandler: addStudioModeEventHandler,\n} = makePHEventFunctions(\"studioMode\");\n\nexport const {\n useValue: useBasePath,\n setValue: setBasePath,\n addEventHandler: addBasePathEventHandler,\n} = makePHEventFunctions(\"basePath\");\n\nexport const {\n useValue: useVersionCheckInterval,\n setValue: setVersionCheckInterval,\n addEventHandler: addVersionCheckIntervalEventHandler,\n} = makePHEventFunctions(\"versionCheckInterval\");\n\nexport const {\n useValue: useCliVersion,\n setValue: setCliVersion,\n addEventHandler: addCliVersionEventHandler,\n} = makePHEventFunctions(\"cliVersion\");\n\nexport const {\n useValue: useFileUploadOperationsChunkSize,\n setValue: setFileUploadOperationsChunkSize,\n addEventHandler: addFileUploadOperationsChunkSizeEventHandler,\n} = makePHEventFunctions(\"fileUploadOperationsChunkSize\");\n\nexport const {\n useValue: useIsDocumentModelSelectionSettingsEnabled,\n setValue: setIsDocumentModelSelectionSettingsEnabled,\n addEventHandler: addIsDocumentModelSelectionSettingsEnabledEventHandler,\n} = makePHEventFunctions(\"isDocumentModelSelectionSettingsEnabled\");\n\nexport const {\n useValue: useGaTrackingId,\n setValue: setGaTrackingId,\n addEventHandler: addGaTrackingIdEventHandler,\n} = makePHEventFunctions(\"gaTrackingId\");\n\nexport const {\n useValue: useDefaultDrivesUrl,\n setValue: setDefaultDrivesUrl,\n addEventHandler: addDefaultDrivesUrlEventHandler,\n} = makePHEventFunctions(\"defaultDrivesUrl\");\n\nexport const {\n useValue: useDrivesPreserveStrategy,\n setValue: setDrivesPreserveStrategy,\n addEventHandler: addDrivesPreserveStrategyEventHandler,\n} = makePHEventFunctions(\"drivesPreserveStrategy\");\n\nexport const {\n useValue: useIsLocalDrivesEnabled,\n setValue: setIsLocalDrivesEnabled,\n addEventHandler: addIsLocalDrivesEnabledEventHandler,\n} = makePHEventFunctions(\"isLocalDrivesEnabled\");\n\nexport const {\n useValue: useIsAddDriveEnabled,\n setValue: setIsAddDriveEnabled,\n addEventHandler: addIsAddDriveEnabledEventHandler,\n} = makePHEventFunctions(\"isAddDriveEnabled\");\n\nexport const {\n useValue: useIsPublicDrivesEnabled,\n setValue: setIsPublicDrivesEnabled,\n addEventHandler: addIsPublicDrivesEnabledEventHandler,\n} = makePHEventFunctions(\"isPublicDrivesEnabled\");\n\nexport const {\n useValue: useIsAddPublicDrivesEnabled,\n setValue: setIsAddPublicDrivesEnabled,\n addEventHandler: addIsAddPublicDrivesEnabledEventHandler,\n} = makePHEventFunctions(\"isAddPublicDrivesEnabled\");\n\nexport const {\n useValue: useIsDeletePublicDrivesEnabled,\n setValue: setIsDeletePublicDrivesEnabled,\n addEventHandler: addIsDeletePublicDrivesEnabledEventHandler,\n} = makePHEventFunctions(\"isDeletePublicDrivesEnabled\");\n\nexport const {\n useValue: useIsCloudDrivesEnabled,\n setValue: setIsCloudDrivesEnabled,\n addEventHandler: addIsCloudDrivesEnabledEventHandler,\n} = makePHEventFunctions(\"isCloudDrivesEnabled\");\n\nexport const {\n useValue: useIsAddCloudDrivesEnabled,\n setValue: setIsAddCloudDrivesEnabled,\n addEventHandler: addIsAddCloudDrivesEnabledEventHandler,\n} = makePHEventFunctions(\"isAddCloudDrivesEnabled\");\n\nexport const {\n useValue: useIsDeleteCloudDrivesEnabled,\n setValue: setIsDeleteCloudDrivesEnabled,\n addEventHandler: addIsDeleteCloudDrivesEnabledEventHandler,\n} = makePHEventFunctions(\"isDeleteCloudDrivesEnabled\");\n\nexport const {\n useValue: useLocalDrivesEnabled,\n setValue: setLocalDrivesEnabled,\n addEventHandler: addLocalDrivesEnabledEventHandler,\n} = makePHEventFunctions(\"isLocalDrivesEnabled\");\n\nexport const {\n useValue: useIsAddLocalDrivesEnabled,\n setValue: setIsAddLocalDrivesEnabled,\n addEventHandler: addIsAddLocalDrivesEnabledEventHandler,\n} = makePHEventFunctions(\"isAddLocalDrivesEnabled\");\n\nexport const {\n useValue: useIsDeleteLocalDrivesEnabled,\n setValue: setIsDeleteLocalDrivesEnabled,\n addEventHandler: addIsDeleteLocalDrivesEnabledEventHandler,\n} = makePHEventFunctions(\"isDeleteLocalDrivesEnabled\");\n\nexport const {\n useValue: useIsEditorDebugModeEnabled,\n setValue: setIsEditorDebugModeEnabled,\n addEventHandler: addIsEditorDebugModeEnabledEventHandler,\n} = makePHEventFunctions(\"isEditorDebugModeEnabled\");\n\nexport const {\n useValue: useIsEditorReadModeEnabled,\n setValue: setIsEditorReadModeEnabled,\n addEventHandler: addIsEditorReadModeEnabledEventHandler,\n} = makePHEventFunctions(\"isEditorReadModeEnabled\");\n\nexport const {\n useValue: useIsAnalyticsDatabaseWorkerEnabled,\n setValue: setIsAnalyticsDatabaseWorkerEnabled,\n addEventHandler: addIsAnalyticsDatabaseWorkerEnabledEventHandler,\n} = makePHEventFunctions(\"isAnalyticsDatabaseWorkerEnabled\");\n\nexport const {\n useValue: useIsDiffAnalyticsEnabled,\n setValue: setIsDiffAnalyticsEnabled,\n addEventHandler: addIsDiffAnalyticsEnabledEventHandler,\n} = makePHEventFunctions(\"isDiffAnalyticsEnabled\");\n\nexport const {\n useValue: useIsDriveAnalyticsEnabled,\n setValue: setIsDriveAnalyticsEnabled,\n addEventHandler: addIsDriveAnalyticsEnabledEventHandler,\n} = makePHEventFunctions(\"isDriveAnalyticsEnabled\");\n\nexport const {\n useValue: useRenownUrl,\n setValue: setRenownUrl,\n addEventHandler: addRenownUrlEventHandler,\n} = makePHEventFunctions(\"renownUrl\");\n\nexport const {\n useValue: useRenownNetworkId,\n setValue: setRenownNetworkId,\n addEventHandler: addRenownNetworkIdEventHandler,\n} = makePHEventFunctions(\"renownNetworkId\");\n\nexport const {\n useValue: useRenownChainId,\n setValue: setRenownChainId,\n addEventHandler: addRenownChainIdEventHandler,\n} = makePHEventFunctions(\"renownChainId\");\n\nexport const {\n useValue: useSwitchboardUrl,\n setValue: setSwitchboardUrl,\n addEventHandler: addSwitchboardUrlEventHandler,\n} = makePHEventFunctions(\"switchboardUrl\");\n\nexport const {\n useValue: useRenownAdapters,\n setValue: setRenownAdapters,\n addEventHandler: addRenownAdaptersEventHandler,\n} = makePHEventFunctions(\"renownAdapters\");\n\nexport const {\n useValue: useSentryRelease,\n setValue: setSentryRelease,\n addEventHandler: addSentryReleaseEventHandler,\n} = makePHEventFunctions(\"sentryRelease\");\n\nexport const {\n useValue: useSentryDsn,\n setValue: setSentryDsn,\n addEventHandler: addSentryDsnEventHandler,\n} = makePHEventFunctions(\"sentryDsn\");\n\nexport const {\n useValue: useSentryEnv,\n setValue: setSentryEnv,\n addEventHandler: addSentryEnvEventHandler,\n} = makePHEventFunctions(\"sentryEnv\");\n\nexport const {\n useValue: useIsSentryTracingEnabled,\n setValue: setIsSentryTracingEnabled,\n addEventHandler: addIsSentryTracingEnabledEventHandler,\n} = makePHEventFunctions(\"isSentryTracingEnabled\");\n\nexport const {\n useValue: useIsExternalProcessorsEnabled,\n setValue: setIsExternalProcessorsEnabled,\n addEventHandler: addIsExternalProcessorsEnabledEventHandler,\n} = makePHEventFunctions(\"isExternalProcessorsEnabled\");\n\nexport const {\n useValue: useIsExternalPackagesEnabled,\n setValue: setIsExternalPackagesEnabled,\n addEventHandler: addIsExternalPackagesEnabledEventHandler,\n} = makePHEventFunctions(\"isExternalPackagesEnabled\");\n\nconst enabledEditorsEventFunctions = makePHEventFunctions(\"enabledEditors\");\n\n/** Sets the enabled editors for Connect. */\nexport const setEnabledEditors = enabledEditorsEventFunctions.setValue;\n\n/** Gets the enabled editors for Connect. */\nexport const useEnabledEditors = enabledEditorsEventFunctions.useValue;\n\n/** Adds an event handler for when the enabled editors for Connect changes. */\nexport const addEnabledEditorsEventHandler =\n enabledEditorsEventFunctions.addEventHandler;\n\nconst disabledEditorsEventFunctions = makePHEventFunctions(\"disabledEditors\");\n\n/** Sets the disabled editors for Connect. */\nexport const setDisabledEditors = disabledEditorsEventFunctions.setValue;\n\n/** Gets the disabled editors for Connect. */\nexport const useDisabledEditors = disabledEditorsEventFunctions.useValue;\n\n/** Adds an event handler for when the disabled editors for Connect changes. */\nexport const addDisabledEditorsEventHandler =\n disabledEditorsEventFunctions.addEventHandler;\n\nconst isRelationalProcessorsEnabled = makePHEventFunctions(\n \"isRelationalProcessorsEnabled\",\n);\n\n/** Sets the isRelationalProcessorsEnabled for Connect. */\nexport const setIsRelationalProcessorsEnabled =\n isRelationalProcessorsEnabled.setValue;\n\n/** Gets the isRelationalProcessorsEnabled for Connect. */\nexport const useIsRelationalProcessorsEnabled =\n isRelationalProcessorsEnabled.useValue;\n\n/** Adds an event handler for when the isRelationalProcessorsEnabled for Connect changes. */\nexport const addIsRelationalProcessorsEnabledEventHandler =\n isRelationalProcessorsEnabled.addEventHandler;\n\nconst isExternalRelationalProcessorsEnabled = makePHEventFunctions(\n \"isExternalRelationalProcessorsEnabled\",\n);\n\n/** Sets the isExternalRelationalProcessorsEnabled for Connect. */\nexport const setIsExternalRelationalProcessorsEnabled =\n isExternalRelationalProcessorsEnabled.setValue;\n\n/** Gets the isExternalRelationalProcessorsEnabled for Connect. */\nexport const useIsExternalRelationalProcessorsEnabled =\n isExternalRelationalProcessorsEnabled.useValue;\n\n/** Adds an event handler for when the isExternalRelationalProcessorsEnabled for Connect changes. */\nexport const addIsExternalRelationalProcessorsEnabledEventHandler =\n isExternalRelationalProcessorsEnabled.addEventHandler;\n\nconst isAnalyticsEnabledEventFunctions =\n makePHEventFunctions(\"isAnalyticsEnabled\");\n\n/** Sets the isAnalyticsEnabled for Connect. */\nexport const setIsAnalyticsEnabled = isAnalyticsEnabledEventFunctions.setValue;\n\n/** Gets the isAnalyticsEnabled for Connect. */\nexport const useIsAnalyticsEnabled = isAnalyticsEnabledEventFunctions.useValue;\n\n/** Adds an event handler for when the isAnalyticsEnabled for Connect changes. */\nexport const addIsAnalyticsEnabledEventHandler =\n isAnalyticsEnabledEventFunctions.addEventHandler;\n\nconst isAnalyticsExternalProcessorsEnabled = makePHEventFunctions(\n \"isAnalyticsExternalProcessorsEnabled\",\n);\n\n/** Sets the isAnalyticsExternalProcessorsEnabled for Connect. */\nexport const setIsAnalyticsExternalProcessorsEnabled =\n isAnalyticsExternalProcessorsEnabled.setValue;\n\n/** Gets the isAnalyticsExternalProcessorsEnabled for Connect. */\nexport const useIsAnalyticsExternalProcessorsEnabled =\n isAnalyticsExternalProcessorsEnabled.useValue;\n\n/** Adds an event handler for when the isAnalyticsExternalProcessorsEnabled for Connect changes. */\nexport const addIsAnalyticsExternalProcessorsEnabledEventHandler =\n isAnalyticsExternalProcessorsEnabled.addEventHandler;\n\nconst analyticsDatabaseNameEventFunctions = makePHEventFunctions(\n \"analyticsDatabaseName\",\n);\n\n/** Sets the analytics database name for Connect. */\nexport const setAnalyticsDatabaseName =\n analyticsDatabaseNameEventFunctions.setValue;\n\n/** Gets the analytics database name for Connect. */\nexport const useAnalyticsDatabaseName =\n analyticsDatabaseNameEventFunctions.useValue;\n\n/** Adds an event handler for when the analytics database name for Connect changes. */\nexport const addAnalyticsDatabaseNameEventHandler =\n analyticsDatabaseNameEventFunctions.addEventHandler;\n\nconst logLevelEventFunctions = makePHEventFunctions(\"logLevel\");\n\n/** Sets the log level for Connect. */\nexport const setLogLevel = logLevelEventFunctions.setValue;\n\n/** Gets the log level for Connect. */\nexport const useLogLevel = logLevelEventFunctions.useValue;\n\n/** Adds an event handler for when the log level for Connect changes. */\nexport const addLogLevelEventHandler = logLevelEventFunctions.addEventHandler;\n\nconst allowListEventFunctions = makePHEventFunctions(\"allowList\");\n\n/** Sets the allow list for Connect. */\nexport const setAllowList = allowListEventFunctions.setValue;\n\n/** Gets the allow list for Connect. */\nexport const useAllowList = allowListEventFunctions.useValue;\n\n/** Adds an event handler for when the allow list for Connect changes. */\nexport const addAllowListEventHandler = allowListEventFunctions.addEventHandler;\n\ntype NonUserConfigKey = Exclude<\n PHGlobalConfigKey,\n PHAppConfigKey | PHDocumentEditorConfigKey\n>;\ntype NonUserConfigSetters = PHGlobalConfigSettersForKey<NonUserConfigKey>;\ntype NonUserConfigHooks = PHGlobalConfigHooksForKey<NonUserConfigKey>;\n\nconst nonUserConfigSetters: NonUserConfigSetters = {\n routerBasename: setRouterBasename,\n version: setVersion,\n requiresHardRefresh: setRequiresHardRefresh,\n warnOutdatedApp: setWarnOutdatedApp,\n studioMode: setStudioMode,\n basePath: setBasePath,\n versionCheckInterval: setVersionCheckInterval,\n cliVersion: setCliVersion,\n fileUploadOperationsChunkSize: setFileUploadOperationsChunkSize,\n isDocumentModelSelectionSettingsEnabled:\n setIsDocumentModelSelectionSettingsEnabled,\n gaTrackingId: setGaTrackingId,\n defaultDrivesUrl: setDefaultDrivesUrl,\n drivesPreserveStrategy: setDrivesPreserveStrategy,\n isLocalDrivesEnabled: setIsLocalDrivesEnabled,\n isAddDriveEnabled: setIsAddDriveEnabled,\n isPublicDrivesEnabled: setIsPublicDrivesEnabled,\n isAddPublicDrivesEnabled: setIsAddPublicDrivesEnabled,\n isDeletePublicDrivesEnabled: setIsDeletePublicDrivesEnabled,\n isCloudDrivesEnabled: setIsCloudDrivesEnabled,\n isAddCloudDrivesEnabled: setIsAddCloudDrivesEnabled,\n isDeleteCloudDrivesEnabled: setIsDeleteCloudDrivesEnabled,\n isAddLocalDrivesEnabled: setIsAddLocalDrivesEnabled,\n isDeleteLocalDrivesEnabled: setIsDeleteLocalDrivesEnabled,\n isEditorDebugModeEnabled: setIsEditorDebugModeEnabled,\n isEditorReadModeEnabled: setIsEditorReadModeEnabled,\n isRelationalProcessorsEnabled: setIsRelationalProcessorsEnabled,\n isExternalRelationalProcessorsEnabled:\n setIsExternalRelationalProcessorsEnabled,\n isAnalyticsEnabled: setIsAnalyticsEnabled,\n analyticsDatabaseName: setAnalyticsDatabaseName,\n isAnalyticsExternalProcessorsEnabled: setIsAnalyticsExternalProcessorsEnabled,\n isAnalyticsDatabaseWorkerEnabled: setIsAnalyticsDatabaseWorkerEnabled,\n isDiffAnalyticsEnabled: setIsDiffAnalyticsEnabled,\n isDriveAnalyticsEnabled: setIsDriveAnalyticsEnabled,\n renownUrl: setRenownUrl,\n renownNetworkId: setRenownNetworkId,\n renownChainId: setRenownChainId,\n switchboardUrl: setSwitchboardUrl,\n renownAdapters: setRenownAdapters,\n sentryRelease: setSentryRelease,\n sentryDsn: setSentryDsn,\n sentryEnv: setSentryEnv,\n isSentryTracingEnabled: setIsSentryTracingEnabled,\n isExternalProcessorsEnabled: setIsExternalProcessorsEnabled,\n isExternalPackagesEnabled: setIsExternalPackagesEnabled,\n allowList: setAllowList,\n logLevel: setLogLevel,\n disabledEditors: setDisabledEditors,\n enabledEditors: setEnabledEditors,\n};\n\nexport const phGlobalConfigSetters: PHGlobalConfigSetters = {\n ...phAppConfigSetters,\n ...phDocumentEditorConfigSetters,\n ...nonUserConfigSetters,\n};\n\nconst nonUserConfigHooks: NonUserConfigHooks = {\n routerBasename: useRouterBasename,\n version: useVersion,\n requiresHardRefresh: useRequiresHardRefresh,\n warnOutdatedApp: useWarnOutdatedApp,\n studioMode: useStudioMode,\n basePath: useBasePath,\n versionCheckInterval: useVersionCheckInterval,\n cliVersion: useCliVersion,\n fileUploadOperationsChunkSize: useFileUploadOperationsChunkSize,\n isDocumentModelSelectionSettingsEnabled:\n useIsDocumentModelSelectionSettingsEnabled,\n gaTrackingId: useGaTrackingId,\n defaultDrivesUrl: useDefaultDrivesUrl,\n drivesPreserveStrategy: useDrivesPreserveStrategy,\n isAddDriveEnabled: useIsAddDriveEnabled,\n isPublicDrivesEnabled: useIsPublicDrivesEnabled,\n isAddPublicDrivesEnabled: useIsAddPublicDrivesEnabled,\n isDeletePublicDrivesEnabled: useIsDeletePublicDrivesEnabled,\n isCloudDrivesEnabled: useIsCloudDrivesEnabled,\n isAddCloudDrivesEnabled: useIsAddCloudDrivesEnabled,\n isDeleteCloudDrivesEnabled: useIsDeleteCloudDrivesEnabled,\n isLocalDrivesEnabled: useIsLocalDrivesEnabled,\n isAddLocalDrivesEnabled: useIsAddLocalDrivesEnabled,\n isDeleteLocalDrivesEnabled: useIsDeleteLocalDrivesEnabled,\n isEditorDebugModeEnabled: useIsEditorDebugModeEnabled,\n isEditorReadModeEnabled: useIsEditorReadModeEnabled,\n isAnalyticsDatabaseWorkerEnabled: useIsAnalyticsDatabaseWorkerEnabled,\n isDiffAnalyticsEnabled: useIsDiffAnalyticsEnabled,\n isDriveAnalyticsEnabled: useIsDriveAnalyticsEnabled,\n renownUrl: useRenownUrl,\n renownNetworkId: useRenownNetworkId,\n renownChainId: useRenownChainId,\n switchboardUrl: useSwitchboardUrl,\n renownAdapters: useRenownAdapters,\n sentryRelease: useSentryRelease,\n sentryDsn: useSentryDsn,\n sentryEnv: useSentryEnv,\n isSentryTracingEnabled: useIsSentryTracingEnabled,\n isExternalProcessorsEnabled: useIsExternalProcessorsEnabled,\n isExternalPackagesEnabled: useIsExternalPackagesEnabled,\n allowList: useAllowList,\n isAnalyticsEnabled: useIsAnalyticsEnabled,\n isAnalyticsExternalProcessorsEnabled: useIsAnalyticsExternalProcessorsEnabled,\n isRelationalProcessorsEnabled: useIsRelationalProcessorsEnabled,\n isExternalRelationalProcessorsEnabled:\n useIsExternalRelationalProcessorsEnabled,\n analyticsDatabaseName: useAnalyticsDatabaseName,\n logLevel: useLogLevel,\n disabledEditors: useDisabledEditors,\n enabledEditors: useEnabledEditors,\n};\n\nexport const phGlobalConfigHooks: PHGlobalConfigHooks = {\n ...phAppConfigHooks,\n ...phDocumentEditorConfigHooks,\n ...nonUserConfigHooks,\n};\n","import type { IAttachmentService } from \"@powerhousedao/reactor-attachments/client\";\nimport type {\n AddPHGlobalEventHandler,\n SetPHGlobalValue,\n UsePHGlobalValue,\n} from \"@powerhousedao/reactor-browser\";\nimport { makePHEventFunctions } from \"./make-ph-event-functions.js\";\n\nconst attachmentServiceEventFunctions =\n makePHEventFunctions(\"attachmentService\");\n\n/** Returns the attachment service from window.ph */\nexport const useAttachmentService: UsePHGlobalValue<IAttachmentService> =\n attachmentServiceEventFunctions.useValue;\n\n/** Sets the attachment service on window.ph */\nexport const setAttachmentService: SetPHGlobalValue<IAttachmentService> =\n attachmentServiceEventFunctions.setValue;\n\n/** Registers the attachmentService window event handler */\nexport const addAttachmentServiceEventHandler: AddPHGlobalEventHandler =\n attachmentServiceEventFunctions.addEventHandler;\n","import type {\n AddPHGlobalEventHandler,\n SetPHGlobalValue,\n UsePHGlobalValue,\n} from \"../types/global.js\";\nimport { makePHEventFunctions } from \"./make-ph-event-functions.js\";\n\nconst featuresEventFunctions = makePHEventFunctions(\"features\");\n\nexport const useFeatures: UsePHGlobalValue<Map<string, boolean>> =\n featuresEventFunctions.useValue;\n\nexport const setFeatures: SetPHGlobalValue<Map<string, boolean>> =\n featuresEventFunctions.setValue;\n\nexport const addFeaturesEventHandler: AddPHGlobalEventHandler =\n featuresEventFunctions.addEventHandler;\n","import type {\n DocumentDriveDocument,\n Node,\n} from \"@powerhousedao/shared/document-drive\";\nimport slug from \"slug\";\n\n// Returns url with base path plus provided path\nexport function resolveUrlPathname(path: string) {\n return new URL(\n path.replace(/^\\/+/, \"\"),\n window.location.origin + (window.ph?.basePath ?? \"/\"),\n ).pathname;\n}\n\n/** Returns the current path without the base path */\nexport function getPathWithoutBase(path: string) {\n const basePath = window.ph?.basePath ?? \"/\";\n return path.replace(basePath, basePath.endsWith(\"/\") ? \"/\" : \"\");\n}\n\n/** Makes a URL component for a drive. */\nexport function makeDriveUrlComponent(\n drive: DocumentDriveDocument | undefined,\n) {\n if (!drive) return \"\";\n return `/d/${slug(drive.header.slug)}`;\n}\n\n/** Makes a URL component for a node. */\nexport function makeNodeSlug(node: Node | undefined) {\n if (!node) return \"\";\n const nodeName = node.name;\n if (!nodeName) return slug(node.id);\n return slug(`${nodeName}-${node.id}`);\n}\n\n/** Extracts the node slug from a path.\n *\n * The path is expected to be in the format `/d/<drive-slug>/<node-slug>`.\n */\nexport function extractNodeSlugFromPath(path: string) {\n const currentPath = getPathWithoutBase(path);\n const match = /^\\/d\\/[^/]+\\/([^/]+)$/.exec(currentPath);\n return match?.[1];\n}\n\n/** Finds a UUID in a string, used for extracting node ids from node slugs in the URL. */\nexport function findUuid(input: string | undefined) {\n if (!input) return undefined;\n const uuidRegex =\n /\\b[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\\b/;\n const match = uuidRegex.exec(input);\n return match?.[0];\n}\n\nexport function extractNodeIdFromSlug(nodeSlug: string | undefined) {\n const nodeId = findUuid(nodeSlug);\n return nodeId;\n}\n\nexport function extractNodeIdFromPath(path: string) {\n const nodeSlug = extractNodeSlugFromPath(path);\n const nodeId = extractNodeIdFromSlug(nodeSlug);\n return nodeId;\n}\n\n/** Extracts the drive slug from a path.\n * Used for extracting drive ids from drive slugs in the URL.\n * Expects the path to be in the format `/d/<drive-slug>`.\n */\nexport function extractDriveSlugFromPath(path: string) {\n const currentPath = getPathWithoutBase(path);\n const match = /^\\/d\\/([^/]+)/.exec(currentPath);\n return match?.[1] ?? \"\";\n}\n\nexport function extractDriveIdFromSlug(driveSlug: string | undefined) {\n const driveId = findUuid(driveSlug);\n return driveId;\n}\n\nexport function extractDriveIdFromPath(path: string) {\n const driveSlug = extractDriveSlugFromPath(path);\n const driveId = extractDriveIdFromSlug(driveSlug);\n return driveId;\n}\n\n/**\n * Creates a URL string with the given pathname while preserving existing query parameters.\n */\nexport function createUrlWithPreservedParams(pathname: string): string {\n const search = window.location.search;\n return search ? `${pathname}${search}` : pathname;\n}\n","import type { DocumentDriveDocument } from \"@powerhousedao/shared/document-drive\";\nimport type { SetPHGlobalValue, UsePHGlobalValue } from \"../types/global.js\";\nimport { makePHEventFunctions } from \"./make-ph-event-functions.js\";\n\nconst drivesEventFunctions = makePHEventFunctions(\"drives\");\n\n/** Returns all of the drives in the reactor */\nexport const useDrives: UsePHGlobalValue<DocumentDriveDocument[]> =\n drivesEventFunctions.useValue;\n\n/** Sets the drives in the reactor */\nexport const setDrives: SetPHGlobalValue<DocumentDriveDocument[]> =\n drivesEventFunctions.setValue;\n\n/** Adds an event handler for the drives */\nexport const addDrivesEventHandler = drivesEventFunctions.addEventHandler;\n","import type { Node } from \"@powerhousedao/shared/document-drive\";\nimport {\n createUrlWithPreservedParams,\n extractDriveSlugFromPath,\n extractNodeIdFromSlug,\n extractNodeSlugFromPath,\n makeNodeSlug,\n resolveUrlPathname,\n} from \"../utils/url.js\";\nimport { makePHEventFunctions } from \"./make-ph-event-functions.js\";\n\nconst selectedNodeIdEventFunctions = makePHEventFunctions(\"selectedNodeId\");\nexport const useSelectedNodeId = selectedNodeIdEventFunctions.useValue;\nconst setSelectedNodeId = selectedNodeIdEventFunctions.setValue;\nexport const addSelectedNodeIdEventHandler =\n selectedNodeIdEventFunctions.addEventHandler;\n\n/** Sets the selected node (file or folder). */\nexport function setSelectedNode(nodeOrNodeSlug: Node | string | undefined) {\n const nodeSlug =\n typeof nodeOrNodeSlug === \"string\"\n ? nodeOrNodeSlug\n : makeNodeSlug(nodeOrNodeSlug);\n const nodeId = extractNodeIdFromSlug(nodeSlug);\n setSelectedNodeId(nodeId);\n const driveSlugFromPath = extractDriveSlugFromPath(window.location.pathname);\n if (!driveSlugFromPath) {\n return;\n }\n if (!nodeSlug) {\n const pathname = resolveUrlPathname(`/d/${driveSlugFromPath}`);\n if (pathname === window.location.pathname) {\n return;\n }\n window.history.pushState(null, \"\", createUrlWithPreservedParams(pathname));\n return;\n }\n const pathname = resolveUrlPathname(`/d/${driveSlugFromPath}/${nodeSlug}`);\n if (pathname === window.location.pathname) {\n return;\n }\n window.history.pushState(null, \"\", createUrlWithPreservedParams(pathname));\n}\n\nexport function addResetSelectedNodeEventHandler() {\n window.addEventListener(\"ph:selectedDriveIdUpdated\", () => {\n setSelectedNodeId(undefined);\n });\n}\n\nexport function addSetSelectedNodeOnPopStateEventHandler() {\n window.addEventListener(\"popstate\", () => {\n const pathname = window.location.pathname;\n const nodeSlug = extractNodeSlugFromPath(pathname);\n // The slug embeds the id (`<name>-<uuid>`); compare ids, not slug vs id.\n const nodeId = extractNodeIdFromSlug(nodeSlug);\n const selectedNodeId = window.ph?.selectedNodeId;\n if (nodeId !== selectedNodeId) {\n setSelectedNode(nodeSlug);\n }\n });\n}\n","import type { DocumentDispatch } from \"@powerhousedao/reactor-browser\";\nimport type {\n DocumentDriveAction,\n DocumentDriveDocument,\n} from \"@powerhousedao/shared/document-drive\";\nimport {\n createUrlWithPreservedParams,\n extractDriveIdFromPath,\n extractDriveSlugFromPath,\n extractNodeSlugFromPath,\n resolveUrlPathname,\n} from \"../utils/url.js\";\nimport { useDispatch } from \"./dispatch.js\";\nimport { useDrives } from \"./drives.js\";\nimport { makePHEventFunctions } from \"./make-ph-event-functions.js\";\nimport { setSelectedNode } from \"./set-selected-node.js\";\n\nconst selectedDriveIdEventFunctions = makePHEventFunctions(\"selectedDriveId\");\n\n/** Returns the selected drive id */\nexport const useSelectedDriveId = selectedDriveIdEventFunctions.useValue;\n\n/** Sets the selected drive id */\nexport const setSelectedDriveId = selectedDriveIdEventFunctions.setValue;\n\n/** Adds an event handler for the selected drive id */\nexport const addSelectedDriveIdEventHandler =\n selectedDriveIdEventFunctions.addEventHandler;\n\n/** Returns the selected drive */\nexport function useSelectedDrive() {\n const drive = useSelectedDriveSafe();\n if (!drive[0]) {\n throw new Error(\n \"There is no drive selected. Did you mean to call 'useSelectedDriveSafe'?\",\n );\n }\n\n return drive;\n}\n\n/** Returns the selected drive, or undefined if no drive is selected */\nexport function useSelectedDriveSafe() {\n const selectedDriveId = useSelectedDriveId();\n const drives = useDrives();\n const selectedDrive = drives?.find(\n (drive) => drive.header.id === selectedDriveId,\n );\n\n const [drive, dispatch] = useDispatch(selectedDrive);\n if (!selectedDrive) {\n return [undefined, undefined] as const;\n }\n return [drive, dispatch] as [\n DocumentDriveDocument,\n DocumentDispatch<DocumentDriveAction>,\n ];\n}\n\nexport function setSelectedDrive(\n driveOrDriveSlug: string | DocumentDriveDocument | undefined,\n) {\n const driveSlug =\n typeof driveOrDriveSlug === \"string\"\n ? driveOrDriveSlug\n : driveOrDriveSlug?.header.slug;\n\n // A full drive document is selected directly — a just-created drive\n // navigates before the collection refresh. Slugs go through the lookup.\n const drives = window.ph?.drives;\n const drive =\n typeof driveOrDriveSlug === \"object\" && driveOrDriveSlug !== null\n ? driveOrDriveSlug\n : drives?.find((d) => d.header.slug === driveSlug);\n const driveId = drive?.header.id;\n\n // A URL-pinned slug with no matching drive: the deep link may predate\n // remote drive registration, so defer instead of rewriting the URL.\n if (\n !driveId &&\n driveSlug &&\n extractDriveSlugFromPath(window.location.pathname) === driveSlug\n ) {\n // Clear the previous selection so a stale drive doesn't render against\n // the new URL; the selected node resets with it, the URL is untouched.\n if (window.ph?.selectedDriveId) {\n setSelectedDriveId(undefined);\n }\n deferDriveSelection(driveSlug);\n return;\n }\n\n // Any resolved selection supersedes a pending deferred lookup.\n cancelPendingDriveSelection();\n\n setSelectedDriveId(driveId);\n\n if (!driveId) {\n const pathname = resolveUrlPathname(\"/\");\n if (pathname === window.location.pathname) {\n return;\n }\n window.history.pushState(null, \"\", createUrlWithPreservedParams(pathname));\n return;\n }\n const pathname = resolveUrlPathname(`/d/${driveSlug}`);\n if (pathname === window.location.pathname) {\n return;\n }\n window.history.pushState(null, \"\", createUrlWithPreservedParams(pathname));\n}\n\n// Tick between unresolved-slug checks; re-armed while a sync is in flight.\nconst DEFERRED_DRIVE_TICK_MS = 2_000;\n// Hard cap so a wedged remote can't pin the deep link forever.\nconst DEFERRED_DRIVE_MAX_WAIT_MS = 15_000;\n\n// True while any sync remote has not completed its first successful pull —\n// a drive may still be on its way in, so the deferred lookup keeps waiting.\nfunction isInitialSyncInFlight(): boolean {\n const remotes =\n window.ph?.reactorClientModule?.reactorModule?.syncModule?.syncManager?.list();\n if (!remotes?.length) {\n return false;\n }\n return remotes.some((remote) => {\n try {\n const snapshot = remote.channel.getConnectionState();\n return (\n snapshot.receivingPages ||\n (!snapshot.lastSuccessUtcMs && snapshot.state !== \"error\")\n );\n } catch {\n return false;\n }\n });\n}\n\nlet pendingHandler: (() => void) | undefined;\nlet pendingTimeout: ReturnType<typeof setTimeout> | undefined;\n\nfunction cancelPendingDriveSelection() {\n if (pendingHandler) {\n window.removeEventListener(\"ph:drivesUpdated\", pendingHandler);\n pendingHandler = undefined;\n }\n if (pendingTimeout) {\n clearTimeout(pendingTimeout);\n pendingTimeout = undefined;\n }\n}\n\n// Re-runs the slug lookup on each drives update until it resolves, then\n// restores the URL-pinned node. Unresolved slugs redirect once syncs settle.\nfunction deferDriveSelection(driveSlug: string) {\n cancelPendingDriveSelection();\n\n // Capture the node pinned in the deep link before setSelectedDrive\n // rewrites the URL to /d/<driveSlug>, dropping the node segment.\n const nodeSlug = extractNodeSlugFromPath(window.location.pathname);\n const handler = () => {\n const drive = window.ph?.drives?.find((d) => d.header.slug === driveSlug);\n if (!drive) {\n return;\n }\n cancelPendingDriveSelection();\n setSelectedDrive(driveSlug);\n setSelectedNode(nodeSlug);\n };\n pendingHandler = handler;\n window.addEventListener(\"ph:drivesUpdated\", handler);\n\n const deadline = Date.now() + DEFERRED_DRIVE_MAX_WAIT_MS;\n const scheduleTick = () => {\n pendingTimeout = setTimeout(() => {\n if (Date.now() < deadline && isInitialSyncInFlight()) {\n scheduleTick();\n return;\n }\n cancelPendingDriveSelection();\n const pathname = resolveUrlPathname(\"/\");\n if (pathname === window.location.pathname) {\n return;\n }\n window.history.pushState(\n null,\n \"\",\n createUrlWithPreservedParams(pathname),\n );\n }, DEFERRED_DRIVE_TICK_MS);\n };\n scheduleTick();\n}\n\nexport function addSetSelectedDriveOnPopStateEventHandler() {\n window.addEventListener(\"popstate\", () => {\n const pathname = window.location.pathname;\n const driveId = extractDriveIdFromPath(pathname);\n const selectedDriveId = window.ph?.selectedDriveId;\n if (driveId !== selectedDriveId) {\n setSelectedDrive(driveId);\n }\n });\n}\n","import { useState } from \"react\";\nimport { funnel } from \"remeda\";\nimport { useIsDragAndDropEnabled } from \"./config/editor.js\";\n\nexport function useDropTarget() {\n const [isDropTarget, setIsDropTarget] = useState(false);\n const isDragAndDropEnabled = useIsDragAndDropEnabled();\n\n const targetSetter = funnel(() => setIsDropTarget(true), {\n triggerAt: \"start\",\n minQuietPeriodMs: 100,\n });\n\n const targetUnsetter = funnel(() => setIsDropTarget(false), {\n triggerAt: \"start\",\n minQuietPeriodMs: 100,\n });\n\n function setTarget() {\n if (!isDragAndDropEnabled) return;\n targetUnsetter.cancel();\n targetSetter.call();\n }\n\n function unsetTarget() {\n if (!isDragAndDropEnabled) return;\n targetSetter.cancel();\n targetUnsetter.call();\n }\n\n return {\n isDropTarget,\n setTarget,\n unsetTarget,\n };\n}\n","import { type DragEventHandler } from \"react\";\nimport {\n allPass,\n conditional,\n constant,\n funnel,\n isDefined,\n isNot,\n isStrictEqual,\n isString,\n isTruthy,\n once,\n} from \"remeda\";\nimport { moveNodeById } from \"../actions/document.js\";\nimport { makePHEventFunctions } from \"./make-ph-event-functions.js\";\nimport { useSelectedDriveId } from \"./selected-drive.js\";\nimport { useDropTarget } from \"./use-drop-target.js\";\nexport type DraggingNode = {\n srcId: string;\n parentId: string | null | undefined;\n};\n\nconst draggingNodeEventFunctions = makePHEventFunctions(\"draggingNode\");\nconst useDraggingNode = draggingNodeEventFunctions.useValue;\nconst setDraggingNode = draggingNodeEventFunctions.setValue;\nexport const addDraggingNodeEventHandler =\n draggingNodeEventFunctions.addEventHandler;\n\nconst draggingNodeSetter = funnel(\n (node: DraggingNode) => setDraggingNode(node),\n {\n reducer: (_, newNode: DraggingNode) => newNode,\n triggerAt: \"start\",\n minQuietPeriodMs: 100,\n },\n);\n\nconst draggingNodeUnsetter = funnel(() => setDraggingNode(undefined), {\n triggerAt: \"start\",\n minQuietPeriodMs: 100,\n});\n\nfunction setDragging(node: DraggingNode) {\n draggingNodeUnsetter.cancel();\n draggingNodeSetter.call(node);\n}\n\nfunction unsetDragging() {\n draggingNodeSetter.cancel();\n draggingNodeUnsetter.call();\n}\n\n/* Decide if a node is being dragged based on its id, parent and drive */\nconst isNodeDrag = (params: {\n srcId: string | undefined;\n driveId: string | undefined;\n parentId: string | null | undefined;\n}): params is {\n srcId: string;\n driveId: string;\n parentId: string | null | undefined;\n} =>\n conditional(\n params,\n // no drag if no src\n [({ srcId }) => isNot(isTruthy)(srcId), constant(false)],\n // no drag if no drive\n [({ driveId }) => isNot(isTruthy)(driveId), constant(false)],\n // no drag drive\n [({ driveId, srcId }) => isStrictEqual(driveId, srcId), constant(false)],\n constant(true),\n );\n\n/* Allows a node to be dragged */\nexport function useDragNode(args: {\n srcId: string | undefined;\n parentId: string | null | undefined;\n}) {\n const { srcId, parentId } = args;\n const driveId = useSelectedDriveId();\n const draggingNodeId = useDraggingNode()?.srcId;\n\n const params = {\n driveId,\n srcId,\n parentId,\n };\n const draggable = isNodeDrag(params);\n\n const isDragging = allPass({ srcId, draggingNodeId }, [\n () => draggable,\n ({ srcId }) => isString(srcId),\n ({ draggingNodeId }) => isString(draggingNodeId),\n ({ srcId, draggingNodeId }) => isStrictEqual(srcId, draggingNodeId),\n ]);\n\n const onDragStart: DragEventHandler = () => {\n if (!draggable) return;\n setDragging(params);\n };\n\n const onDragEnd: DragEventHandler = () => {\n if (!draggable) return;\n unsetDragging();\n };\n\n return {\n isDragging,\n draggable,\n onDragStart,\n onDragEnd,\n };\n}\n\n/* Decide if a node can and should be dropped on the target based on the\n * dragged node's id, the target node's id, the dragged node's current parent, \nand the drive id. */\nconst isNodeDrop = (params: {\n driveId: string | undefined;\n parentId: string | undefined | null;\n targetId: string | undefined;\n srcId: string | undefined;\n}): params is {\n driveId: string;\n srcId: string;\n parentId: string | undefined | null;\n targetId: string | undefined;\n} =>\n conditional(\n params,\n // no drop if no src\n [({ srcId }) => isNot(isTruthy)(srcId), constant(false)],\n // no drop if no drive\n [({ driveId }) => isNot(isDefined)(driveId), constant(false)],\n // no drop into self\n [({ srcId, targetId }) => isStrictEqual(srcId, targetId), constant(false)],\n // no drop into drive if already in top level of drive\n [\n ({ driveId, parentId, targetId }) =>\n isNot(isTruthy)(parentId) && isStrictEqual(targetId, driveId),\n constant(false),\n ],\n // no drop into current parent\n [\n ({ targetId, parentId }) => isStrictEqual(targetId, parentId),\n constant(false),\n ],\n constant(true),\n );\n\n/* Allows a node to be a drop target */\nexport function useDropNode(targetId: string | undefined) {\n const driveId = useSelectedDriveId();\n const { srcId, parentId } = useDraggingNode() ?? {};\n const { isDropTarget, setTarget, unsetTarget } = useDropTarget();\n\n const params = {\n driveId,\n parentId,\n targetId,\n srcId,\n };\n\n function handleNodeDrop(event: React.DragEvent<Element>, cb?: () => void) {\n if (!isNodeDrop(params)) return;\n\n event.preventDefault();\n event.stopPropagation();\n\n cb?.();\n }\n\n const onDragEnter: DragEventHandler = (event) => handleNodeDrop(event);\n\n const onDragOver: DragEventHandler = (event) =>\n handleNodeDrop(event, once(setTarget));\n\n const onDragLeave: DragEventHandler = (event) =>\n handleNodeDrop(event, once(unsetTarget));\n\n const onDrop: DragEventHandler = (event) =>\n handleNodeDrop(\n event,\n once(() => {\n unsetDragging();\n unsetTarget();\n moveNodeById(params).catch(console.error);\n }),\n );\n\n return { isDropTarget, onDragEnter, onDragOver, onDragLeave, onDrop };\n}\n","import type { ReactorGraphQLClient } from \"../graphql/types.js\";\nimport type { SetPHGlobalValue, UsePHGlobalValue } from \"../types/global.js\";\nimport { makePHEventFunctions } from \"./make-ph-event-functions.js\";\n\nconst graphQLReactorClientEventFunctions = makePHEventFunctions(\n \"reactorGraphQLClient\",\n);\n\nexport const useGraphQLReactorClient: UsePHGlobalValue<ReactorGraphQLClient> =\n graphQLReactorClientEventFunctions.useValue;\n\nexport const setGraphQLReactorClient: SetPHGlobalValue<ReactorGraphQLClient> =\n graphQLReactorClientEventFunctions.setValue;\nexport const addGraphQLReactorClientEventHandler =\n graphQLReactorClientEventFunctions.addEventHandler;\n","import { makePHEventFunctions } from \"./make-ph-event-functions.js\";\n\nconst packageDiscoveryFunctions = makePHEventFunctions(\n \"packageDiscoveryService\",\n);\n\nexport const usePackageDiscoveryService = packageDiscoveryFunctions.useValue;\nexport const setPackageDiscoveryService = packageDiscoveryFunctions.setValue;\nexport const addPackageDiscoveryServiceEventHandler =\n packageDiscoveryFunctions.addEventHandler;\n","import type { PGlite } from \"@electric-sql/pglite\";\nimport type {\n Database,\n IDocumentModelRegistry,\n ISyncManager,\n} from \"@powerhousedao/reactor\";\nimport type {\n AddPHGlobalEventHandler,\n BrowserReactorClientModule,\n IReactorBrowserClient,\n SetPHGlobalValue,\n UsePHGlobalValue,\n WorkerReactorClientModule,\n} from \"@powerhousedao/reactor-browser\";\nimport type { Kysely } from \"kysely\";\nimport { makePHEventFunctions } from \"./make-ph-event-functions.js\";\n\nconst reactorClientModuleEventFunctions = makePHEventFunctions(\n \"reactorClientModule\",\n);\nconst reactorClientEventFunctions = makePHEventFunctions(\"reactorClient\");\n\n/** Returns the reactor client module (in-process or worker-backed) */\nexport const useReactorClientModule: UsePHGlobalValue<\n BrowserReactorClientModule | WorkerReactorClientModule\n> = reactorClientModuleEventFunctions.useValue;\n\n/** Sets the reactor client module */\nexport const setReactorClientModule: SetPHGlobalValue<\n BrowserReactorClientModule | WorkerReactorClientModule\n> = reactorClientModuleEventFunctions.setValue;\n\n/** Adds an event handler for the reactor client module */\nexport const addReactorClientModuleEventHandler: AddPHGlobalEventHandler =\n reactorClientModuleEventFunctions.addEventHandler;\n\n/** Returns the reactor client */\nexport const useReactorClient: UsePHGlobalValue<IReactorBrowserClient> =\n reactorClientEventFunctions.useValue;\n\n/** Sets the reactor client */\nexport const setReactorClient: SetPHGlobalValue<IReactorBrowserClient> =\n reactorClientEventFunctions.setValue;\n\n/** Adds an event handler for the reactor client */\nexport const addReactorClientEventHandler: AddPHGlobalEventHandler =\n reactorClientEventFunctions.addEventHandler;\n\n// The following are derived from the reactor client module:\n\nexport const useSync = (): ISyncManager | undefined =>\n useReactorClientModule()?.reactorModule?.syncModule?.syncManager;\n\nexport const useSyncList = () => {\n const sync = useSync();\n return sync?.list() ?? [];\n};\n\nexport const useModelRegistry = (): IDocumentModelRegistry | undefined =>\n useReactorClientModule()?.reactorModule?.documentModelRegistry;\n\nexport const useDatabase = (): Kysely<Database> | undefined => {\n const module = useReactorClientModule();\n return module?.kind === \"browser\"\n ? module.reactorModule?.database\n : undefined;\n};\n\nexport const usePGlite = (): PGlite | undefined => {\n const module = useReactorClientModule();\n return module?.kind === \"browser\" ? module.reactorModule?.pg : undefined;\n};\n","import { makePHEventFunctions } from \"./make-ph-event-functions.js\";\n\nconst revisionHistoryEventFunctions = makePHEventFunctions(\n \"revisionHistoryVisible\",\n);\n\n/** Returns whether revision history is visible */\nexport const useRevisionHistoryVisible = revisionHistoryEventFunctions.useValue;\n\n/** Sets revision history visibility */\nexport const setRevisionHistoryVisible = revisionHistoryEventFunctions.setValue;\n\n/** Adds event handler for revision history visibility */\nexport const addRevisionHistoryVisibleEventHandler =\n revisionHistoryEventFunctions.addEventHandler;\n\n/** Shows the revision history */\nexport function showRevisionHistory() {\n setRevisionHistoryVisible(true);\n}\n\n/** Hides the revision history */\nexport function hideRevisionHistory() {\n setRevisionHistoryVisible(false);\n}\n","import type {\n FileNode,\n FolderNode,\n Node,\n} from \"@powerhousedao/shared/document-drive\";\n\n/** Sorts nodes by name. */\nexport function sortNodesByName<T extends Node>(nodes: T[]) {\n return nodes.toSorted((a, b) => a.name.localeCompare(b.name));\n}\n\n/** Returns whether a node is a file. */\nexport function isFileNodeKind(\n node: Node | null | undefined,\n): node is FileNode {\n if (!node) return false;\n return node.kind.toUpperCase() === \"FILE\";\n}\n\n/** Returns whether a node is a folder. */\nexport function isFolderNodeKind(\n node: Node | null | undefined,\n): node is FolderNode {\n if (!node) return false;\n return node.kind.toUpperCase() === \"FOLDER\";\n}\n","import type {\n FileNode,\n FolderNode,\n} from \"@powerhousedao/shared/document-drive\";\nimport type {\n DocumentModelDocument,\n PHDocument,\n} from \"@powerhousedao/shared/document-model\";\nimport { isFileNodeKind, isFolderNodeKind } from \"../utils/nodes.js\";\nimport { useDocumentsByIds } from \"./document-by-id.js\";\nimport { useSelectedDriveSafe } from \"./selected-drive.js\";\n\n/** Returns the nodes in the selected drive. */\nexport function useNodesInSelectedDrive() {\n const [selectedDrive] = useSelectedDriveSafe();\n return selectedDrive?.state.global.nodes;\n}\n\n/** Returns the file nodes in the selected drive. */\nexport function useFileNodesInSelectedDrive(): FileNode[] | undefined {\n const nodes = useNodesInSelectedDrive();\n return nodes?.filter((n) => isFileNodeKind(n));\n}\n\n/** Returns the folder nodes in the selected drive. */\nexport function useFolderNodesInSelectedDrive(): FolderNode[] | undefined {\n const nodes = useNodesInSelectedDrive();\n return nodes?.filter((n) => isFolderNodeKind(n));\n}\n\n/** Returns the documents in the selected drive. */\nexport function useDocumentsInSelectedDrive(): PHDocument[] | undefined {\n const fileNodes = useFileNodesInSelectedDrive();\n const fileNodeIds = fileNodes?.map((node) => node.id);\n return useDocumentsByIds(fileNodeIds);\n}\n\n/** Returns the document types supported by the selected drive, as defined by the document model documents present in the drive */\nexport function useDocumentTypesInSelectedDrive() {\n const documentsInSelectedDrive = useDocumentsInSelectedDrive();\n const documentModelDocumentsInSelectedDrive =\n documentsInSelectedDrive?.filter(isDocumentModelDocument);\n const documentTypesFromDocumentModelDocuments =\n documentModelDocumentsInSelectedDrive?.map((doc) => doc.state.global.id);\n return documentTypesFromDocumentModelDocuments;\n}\n\nfunction isDocumentModelDocument(\n document: PHDocument,\n): document is DocumentModelDocument {\n return document.header.documentType === \"powerhouse/document-model\";\n}\n","import type { Node } from \"@powerhousedao/shared/document-drive\";\nimport { useNodesInSelectedDrive } from \"./items-in-selected-drive.js\";\nimport { useSelectedNodeId } from \"./set-selected-node.js\";\n\nexport {\n addResetSelectedNodeEventHandler,\n addSelectedNodeIdEventHandler,\n addSetSelectedNodeOnPopStateEventHandler,\n setSelectedNode,\n} from \"./set-selected-node.js\";\n\n/** Returns the selected node. */\nexport function useSelectedNode(): Node | undefined {\n const selectedNodeId = useSelectedNodeId();\n const nodes = useNodesInSelectedDrive();\n return nodes?.find((n) => n.id === selectedNodeId);\n}\n","import { makePHEventFunctions } from \"./make-ph-event-functions.js\";\n\nconst selectedTimelineItemEventFunctions = makePHEventFunctions(\n \"selectedTimelineItem\",\n);\n\n/** Returns the selected timeline item */\nexport const useSelectedTimelineItem =\n selectedTimelineItemEventFunctions.useValue;\n\n/** Sets the selected timeline item */\nexport const setSelectedTimelineItem =\n selectedTimelineItemEventFunctions.setValue;\n\n/** Adds event handler for selected timeline item */\nexport const addSelectedTimelineItemEventHandler =\n selectedTimelineItemEventFunctions.addEventHandler;\n","import { makePHEventFunctions } from \"./make-ph-event-functions.js\";\n\nconst selectedTimelineRevisionEventFunctions = makePHEventFunctions(\n \"selectedTimelineRevision\",\n);\n\n/** Returns the selected timeline revision. */\nexport const useSelectedTimelineRevision =\n selectedTimelineRevisionEventFunctions.useValue;\n\n/** Sets the selected timeline revision. */\nexport const setSelectedTimelineRevision =\n selectedTimelineRevisionEventFunctions.setValue;\n\n/** Adds an event handler for the selected timeline revision. */\nexport const addSelectedTimelineRevisionEventHandler =\n selectedTimelineRevisionEventFunctions.addEventHandler;\n","import { makePHEventFunctions } from \"./make-ph-event-functions.js\";\n\nconst toastEventFunctions = makePHEventFunctions(\"toast\");\n\n/** Returns the toast function */\nexport const usePHToast = toastEventFunctions.useValue;\n\n/** Sets the toast function */\nexport const setPHToast = toastEventFunctions.setValue;\n\n/** Adds an event handler for the toast */\nexport const addToastEventHandler = toastEventFunctions.addEventHandler;\n","import type { DocumentModelLib } from \"document-model\";\nimport { useSyncExternalStore } from \"react\";\nimport {\n isDuplicateManifestError,\n isDuplicateModuleError,\n} from \"../reactor-interop.js\";\nimport type { IPackageManager } from \"../types/vetra.js\";\nimport { makePHEventFunctions } from \"./make-ph-event-functions.js\";\n\nconst vetraPackageManagerFunctions = makePHEventFunctions(\n \"vetraPackageManager\",\n);\n\nexport const useVetraPackageManager = vetraPackageManagerFunctions.useValue;\n\n/** Returns all of the Vetra packages loaded by the Connect instance */\nexport const useVetraPackages = () => {\n const packageManager = useVetraPackageManager();\n\n return useSyncExternalStore(\n (cb) => (packageManager ? packageManager.subscribe(cb) : () => {}),\n () => packageManager?.packages ?? [],\n );\n};\n\n/** Adds the Vetra package manager event handler */\nexport const addVetraPackageManagerEventHandler =\n vetraPackageManagerFunctions.addEventHandler;\n\n/** Sets the Vetra package manager and registers its packages */\nexport function setVetraPackageManager(packageManager: IPackageManager) {\n vetraPackageManagerFunctions.setValue(packageManager);\n updateReactorClientDocumentModels(packageManager.packages);\n updateReactorClientUpgradeManifests(packageManager.packages);\n packageManager.subscribe(({ packages }) => {\n updateReactorClientDocumentModels(packages);\n updateReactorClientUpgradeManifests(packages);\n });\n}\n\nfunction updateReactorClientDocumentModels(packages: DocumentModelLib[]) {\n const documentModelModules = packages\n .flatMap((pkg) => pkg.documentModels)\n .filter(\n (module, index, modules) =>\n // dedupe by documentType and version\n modules.findIndex(\n (m) =>\n m.documentModel.global.id === module.documentModel.global.id &&\n (m.version ?? 1) === (module.version ?? 1),\n ) === index,\n );\n\n const registry =\n window.ph?.reactorClientModule?.reactorModule?.documentModelRegistry;\n if (!registry || documentModelModules.length === 0) return;\n\n const results = registry.registerModules(...documentModelModules);\n const duplicateTypes = new Set<string>();\n for (const result of results) {\n if (result.status === \"error\") {\n if (isDuplicateModuleError(result.error)) {\n duplicateTypes.add(result.item.documentModel.global.id);\n } else {\n console.error(\n \"Failed to register document model module:\",\n result.error,\n );\n }\n }\n }\n if (duplicateTypes.size > 0) {\n // unregisterModules is type-scoped, so replace the whole version family\n // with the incoming package's modules: re-registering only the duplicated\n // items would purge any new version that registered successfully above.\n registry.unregisterModules(...duplicateTypes);\n registry.registerModules(\n ...documentModelModules.filter((module) =>\n duplicateTypes.has(module.documentModel.global.id),\n ),\n );\n }\n}\n\nfunction updateReactorClientUpgradeManifests(packages: DocumentModelLib[]) {\n const upgradeManifests = packages\n .flatMap((pkg) => pkg.upgradeManifests)\n .filter((u) => u !== undefined);\n\n const registry =\n window.ph?.reactorClientModule?.reactorModule?.documentModelRegistry;\n if (!registry || upgradeManifests.length === 0) return;\n\n const results = registry.registerUpgradeManifests(...upgradeManifests);\n const duplicates = [];\n for (const result of results) {\n if (result.status === \"error\") {\n if (isDuplicateManifestError(result.error)) {\n duplicates.push(result);\n } else {\n console.error(\"Failed to register upgrade manifest:\", result.error);\n }\n }\n }\n if (duplicates.length > 0) {\n const duplicateTypes = duplicates\n .map((r) => r.item.documentType)\n .filter((t): t is string => !!t);\n registry.unregisterUpgradeManifests(...duplicateTypes);\n registry.registerUpgradeManifests(...duplicates.map((r) => r.item));\n }\n}\n","import type { PHGlobalEventHandlerAdders } from \"../types/global.js\";\nimport {\n addAllowListEventHandler,\n addAnalyticsDatabaseNameEventHandler,\n addBasePathEventHandler,\n addCliVersionEventHandler,\n addDefaultDrivesUrlEventHandler,\n addDisabledEditorsEventHandler,\n addDrivesPreserveStrategyEventHandler,\n addEnabledEditorsEventHandler,\n addFileUploadOperationsChunkSizeEventHandler,\n addGaTrackingIdEventHandler,\n addIsAddCloudDrivesEnabledEventHandler,\n addIsAddDriveEnabledEventHandler,\n addIsAddLocalDrivesEnabledEventHandler,\n addIsAddPublicDrivesEnabledEventHandler,\n addIsAnalyticsDatabaseWorkerEnabledEventHandler,\n addIsAnalyticsEnabledEventHandler,\n addIsAnalyticsExternalProcessorsEnabledEventHandler,\n addIsCloudDrivesEnabledEventHandler,\n addIsDeleteCloudDrivesEnabledEventHandler,\n addIsDeleteLocalDrivesEnabledEventHandler,\n addIsDeletePublicDrivesEnabledEventHandler,\n addIsDiffAnalyticsEnabledEventHandler,\n addIsDocumentModelSelectionSettingsEnabledEventHandler,\n addIsDriveAnalyticsEnabledEventHandler,\n addIsEditorDebugModeEnabledEventHandler,\n addIsEditorReadModeEnabledEventHandler,\n addIsExternalPackagesEnabledEventHandler,\n addIsExternalProcessorsEnabledEventHandler,\n addIsExternalRelationalProcessorsEnabledEventHandler,\n addIsLocalDrivesEnabledEventHandler,\n addIsPublicDrivesEnabledEventHandler,\n addIsRelationalProcessorsEnabledEventHandler,\n addIsSentryTracingEnabledEventHandler,\n addLogLevelEventHandler,\n addRenownAdaptersEventHandler,\n addRenownChainIdEventHandler,\n addRenownNetworkIdEventHandler,\n addRenownUrlEventHandler,\n addRequiresHardRefreshEventHandler,\n addRouterBasenameEventHandler,\n addSentryDsnEventHandler,\n addSentryEnvEventHandler,\n addSentryReleaseEventHandler,\n addStudioModeEventHandler,\n addSwitchboardUrlEventHandler,\n addVersionCheckIntervalEventHandler,\n addVersionEventHandler,\n addWarnOutdatedAppEventHandler,\n} from \"./config/connect.js\";\nimport { addAttachmentServiceEventHandler } from \"./attachment-service.js\";\nimport { addFeaturesEventHandler } from \"./features.js\";\n\nimport { forEachObj } from \"remeda\";\nimport {\n addAllowedDocumentTypesEventHandler,\n addIsDragAndDropEnabledEventHandler,\n addIsExternalControlsEnabledEventHandler,\n} from \"./config/editor.js\";\nimport { addDocumentCacheEventHandler } from \"./document-cache.js\";\nimport { addDraggingNodeEventHandler } from \"./node-drag-and-drop.js\";\nimport { addDrivesEventHandler } from \"./drives.js\";\nimport { addGraphQLReactorClientEventHandler } from \"./graphql-reactor-client.js\";\nimport { addLoadingEventHandler } from \"./loading.js\";\nimport { addModalEventHandler } from \"./modals.js\";\nimport { addPackageDiscoveryServiceEventHandler } from \"./package-discovery.js\";\nimport {\n addReactorClientEventHandler,\n addReactorClientModuleEventHandler,\n} from \"./reactor.js\";\nimport { addRenownEventHandler } from \"./renown.js\";\nimport { addRevisionHistoryVisibleEventHandler } from \"./revision-history.js\";\nimport {\n addSelectedDriveIdEventHandler,\n addSetSelectedDriveOnPopStateEventHandler,\n} from \"./selected-drive.js\";\nimport {\n addResetSelectedNodeEventHandler,\n addSelectedNodeIdEventHandler,\n addSetSelectedNodeOnPopStateEventHandler,\n} from \"./selected-node.js\";\nimport { addSelectedTimelineItemEventHandler } from \"./selected-timeline-item.js\";\nimport { addSelectedTimelineRevisionEventHandler } from \"./timeline-revision.js\";\nimport { addToastEventHandler } from \"./toast.js\";\nimport { addVetraPackageManagerEventHandler } from \"./vetra-packages.js\";\n\nexport const commonGlobalEventHandlerFunctions = {\n loading: addLoadingEventHandler,\n drives: addDrivesEventHandler,\n selectedDriveId: () => {\n addSelectedDriveIdEventHandler();\n addSetSelectedDriveOnPopStateEventHandler();\n addResetSelectedNodeEventHandler();\n },\n selectedNodeId: () => {\n addSelectedNodeIdEventHandler();\n addSetSelectedNodeOnPopStateEventHandler();\n },\n documentCache: addDocumentCacheEventHandler,\n reactorGraphQLClient: addGraphQLReactorClientEventHandler,\n draggingNode: addDraggingNodeEventHandler,\n};\n\nconst phGlobalEventHandlerRegisterFunctions: PHGlobalEventHandlerAdders = {\n ...commonGlobalEventHandlerFunctions,\n reactorClientModule: addReactorClientModuleEventHandler,\n reactorClient: addReactorClientEventHandler,\n attachmentService: addAttachmentServiceEventHandler,\n features: addFeaturesEventHandler,\n modal: addModalEventHandler,\n renown: addRenownEventHandler,\n vetraPackageManager: addVetraPackageManagerEventHandler,\n packageDiscoveryService: addPackageDiscoveryServiceEventHandler,\n selectedTimelineRevision: addSelectedTimelineRevisionEventHandler,\n revisionHistoryVisible: addRevisionHistoryVisibleEventHandler,\n selectedTimelineItem: addSelectedTimelineItemEventHandler,\n routerBasename: addRouterBasenameEventHandler,\n version: addVersionEventHandler,\n logLevel: addLogLevelEventHandler,\n requiresHardRefresh: addRequiresHardRefreshEventHandler,\n warnOutdatedApp: addWarnOutdatedAppEventHandler,\n studioMode: addStudioModeEventHandler,\n basePath: addBasePathEventHandler,\n versionCheckInterval: addVersionCheckIntervalEventHandler,\n cliVersion: addCliVersionEventHandler,\n fileUploadOperationsChunkSize: addFileUploadOperationsChunkSizeEventHandler,\n isDocumentModelSelectionSettingsEnabled:\n addIsDocumentModelSelectionSettingsEnabledEventHandler,\n gaTrackingId: addGaTrackingIdEventHandler,\n allowList: addAllowListEventHandler,\n defaultDrivesUrl: addDefaultDrivesUrlEventHandler,\n drivesPreserveStrategy: addDrivesPreserveStrategyEventHandler,\n allowedDocumentTypes: addAllowedDocumentTypesEventHandler,\n enabledEditors: addEnabledEditorsEventHandler,\n disabledEditors: addDisabledEditorsEventHandler,\n isAddDriveEnabled: addIsAddDriveEnabledEventHandler,\n isLocalDrivesEnabled: addIsLocalDrivesEnabledEventHandler,\n isPublicDrivesEnabled: addIsPublicDrivesEnabledEventHandler,\n isAddPublicDrivesEnabled: addIsAddPublicDrivesEnabledEventHandler,\n isDeletePublicDrivesEnabled: addIsDeletePublicDrivesEnabledEventHandler,\n isCloudDrivesEnabled: addIsCloudDrivesEnabledEventHandler,\n isAddCloudDrivesEnabled: addIsAddCloudDrivesEnabledEventHandler,\n isDeleteCloudDrivesEnabled: addIsDeleteCloudDrivesEnabledEventHandler,\n isAddLocalDrivesEnabled: addIsAddLocalDrivesEnabledEventHandler,\n isDeleteLocalDrivesEnabled: addIsDeleteLocalDrivesEnabledEventHandler,\n isDragAndDropEnabled: addIsDragAndDropEnabledEventHandler,\n isExternalControlsEnabled: addIsExternalControlsEnabledEventHandler,\n isEditorDebugModeEnabled: addIsEditorDebugModeEnabledEventHandler,\n isEditorReadModeEnabled: addIsEditorReadModeEnabledEventHandler,\n isRelationalProcessorsEnabled: addIsRelationalProcessorsEnabledEventHandler,\n isExternalRelationalProcessorsEnabled:\n addIsExternalRelationalProcessorsEnabledEventHandler,\n isAnalyticsEnabled: addIsAnalyticsEnabledEventHandler,\n isAnalyticsExternalProcessorsEnabled:\n addIsAnalyticsExternalProcessorsEnabledEventHandler,\n analyticsDatabaseName: addAnalyticsDatabaseNameEventHandler,\n isAnalyticsDatabaseWorkerEnabled:\n addIsAnalyticsDatabaseWorkerEnabledEventHandler,\n isDiffAnalyticsEnabled: addIsDiffAnalyticsEnabledEventHandler,\n isDriveAnalyticsEnabled: addIsDriveAnalyticsEnabledEventHandler,\n renownUrl: addRenownUrlEventHandler,\n renownNetworkId: addRenownNetworkIdEventHandler,\n renownChainId: addRenownChainIdEventHandler,\n switchboardUrl: addSwitchboardUrlEventHandler,\n renownAdapters: addRenownAdaptersEventHandler,\n sentryRelease: addSentryReleaseEventHandler,\n sentryDsn: addSentryDsnEventHandler,\n sentryEnv: addSentryEnvEventHandler,\n isSentryTracingEnabled: addIsSentryTracingEnabledEventHandler,\n isExternalProcessorsEnabled: addIsExternalProcessorsEnabledEventHandler,\n isExternalPackagesEnabled: addIsExternalPackagesEnabledEventHandler,\n toast: addToastEventHandler,\n};\nexport function addPHEventHandlers() {\n callEventHandlerRegisterFunctions(phGlobalEventHandlerRegisterFunctions);\n}\n\nexport function callEventHandlerRegisterFunctions(\n registerFunctions: Record<string, () => void>,\n) {\n forEachObj(registerFunctions, (fn) => fn());\n}\n","\"use client\";\n\nimport type { DocumentModelModule } from \"document-model\";\nimport { type ReactNode, useEffect, useState } from \"react\";\nimport { DocumentCache } from \"../document-cache.js\";\nimport { addPHEventHandlers } from \"../hooks/add-ph-event-handlers.js\";\nimport { setAttachmentService } from \"../hooks/attachment-service.js\";\nimport { setDocumentCache } from \"../hooks/document-cache.js\";\nimport { setReactorClient, useReactorClient } from \"../hooks/reactor.js\";\nimport { setVetraPackageManager } from \"../hooks/vetra-packages.js\";\nimport type { PHGlobal } from \"../types/global.js\";\nimport {\n packageFromDocumentModels,\n StaticPackageManager,\n} from \"./static-package-manager.js\";\nimport {\n GraphQLReactorClient,\n isGraphQLReactorClient,\n type GraphQLReactorClientOptions,\n} from \"./graphql-reactor-client.js\";\n\ndeclare global {\n interface Window {\n /** Set by {@link ensurePHEventHandlers}; see its doc comment. */\n __phEventHandlersRegistered?: boolean;\n }\n}\n\n/**\n * Registers the `window.ph` event handlers once per page.\n *\n * The `set*` helpers only dispatch CustomEvents - nothing writes `window.ph`\n * until `addPHEventHandlers` has registered the listeners that do. Registration\n * is guarded by a marker on `window` rather than a module-level flag so that a\n * hot module replacement, or two copies of this module, still register once.\n */\nexport function ensurePHEventHandlers(): void {\n if (typeof window === \"undefined\" || window.__phEventHandlersRegistered) {\n return;\n }\n addPHEventHandlers();\n window.__phEventHandlersRegistered = true;\n}\n\nexport type GraphQLReactorProviderProps = {\n /** The Switchboard GraphQL endpoint, e.g. `http://localhost:4001/graphql`. */\n url: string;\n\n /**\n * Resolves the bearer token sent with every request, per request. Defaults to\n * the token of the logged-in Renown user, or none when nobody is logged in.\n */\n tokenProvider?: GraphQLReactorClientOptions[\"tokenProvider\"];\n\n /**\n * The Switchboard GraphQL subscriptions endpoint, e.g.\n * `ws://localhost:4001/graphql/subscriptions`. Defaults to the endpoint\n * derived from `url`.\n */\n subscriptionsUrl?: GraphQLReactorClientOptions[\"subscriptionsUrl\"];\n\n /**\n * Whether server-pushed changes are delivered. On by default; set it to\n * `false` where there is no websocket to talk to.\n */\n realtime?: GraphQLReactorClientOptions[\"realtime\"];\n\n /**\n * The attachment service the editors below this provider read attachments\n * through, published into the same `window.ph` slot Connect publishes it in.\n *\n * The app constructs it: attachments are a separate package, and which\n * storage an app talks to is the app's business. Leave it out and the slot\n * stays empty, exactly as it is without this provider.\n */\n attachmentService?: PHGlobal[\"attachmentService\"];\n\n /**\n * The document model modules the app works with, imported from its generated\n * package's `document-models` SUBPATH:\n *\n * ```tsx\n * import { TodoV1, TodoV2 } from \"my-models/document-models\";\n * <GraphQLReactorProvider url={url} documentModels={[TodoV1, TodoV2]}>\n * ```\n *\n * Wrapped via {@link packageFromDocumentModels} and published through a\n * {@link StaticPackageManager} into the same `window.ph.vetraPackageManager`\n * slot Connect fills, so `useDocumentModelModules` and\n * `useDocumentModelModuleById` work below this provider.\n *\n * Modules only, deliberately - not whole packages. Editors are not portable\n * outside Connect yet (they read the selected document from Connect's\n * drive/node selection) and would inflate the bundle; a light app that needs\n * an editor imports the React component directly.\n *\n * Import from the `document-models` subpath, never from the package ROOT:\n * the root entry also exports the package's `processorFactory`, and module\n * resolution happens before tree-shaking, so a root import drags processor\n * (server-side) code into the browser bundle and can break the build.\n *\n * They are also what lets the client SIGN a batch of two or more actions:\n * signing the second action needs the state the first one leaves behind, and\n * only the document's own reducer can predict it, so a batch is signable only\n * while the module matching the document's type and exact version is here.\n * Single actions are signed without any of this.\n *\n * Optional on purpose: a light app may equally ship NO modules and let the\n * Switchboard own the model entirely - both modes are supported.\n *\n * Like `url`, this is read once, when the client is built.\n */\n documentModels?: readonly DocumentModelModule<any>[];\n\n children: ReactNode;\n};\n\n/**\n * Mounts a {@link GraphQLReactorClient} into the `window.ph` slots the\n * reactor-browser hooks read, so `useDocument`, `useDispatch` and\n * `useReactorClient` work below it against a Switchboard, with no reactor in\n * the bundle.\n *\n * It fills the document slots, plus `window.ph.vetraPackageManager` when\n * `documentModels` is given (a fixed {@link StaticPackageManager}, which makes\n * the document-model hooks work). The same modules go to the client itself, so\n * a dispatch of two or more actions is signed rather than refused.\n * `window.ph.reactorClientModule` always stays empty, so full-reactor surfaces\n * (drives, jobs, editor auto-discovery) find nothing - an app below this\n * provider renders components it imports itself.\n *\n * The client is built on the client only: on the server the slots stay empty\n * and the hooks report their normal loading states. The props are read once,\n * when the client is built - changing `url` afterwards does not rebuild it.\n *\n * The effect's cleanup disposes the cache and the client's socket, and the\n * effect rebuilds both if it runs again on the same client - which is what a\n * `StrictMode` mount does.\n */\nexport function GraphQLReactorProvider({\n url,\n tokenProvider,\n subscriptionsUrl,\n realtime,\n attachmentService,\n documentModels,\n children,\n}: GraphQLReactorProviderProps) {\n const [client] = useState(() =>\n typeof window === \"undefined\"\n ? undefined\n : new GraphQLReactorClient({\n url,\n tokenProvider,\n subscriptionsUrl,\n realtime,\n documentModels,\n }),\n );\n\n useEffect(() => {\n if (!client) {\n return;\n }\n ensurePHEventHandlers();\n setReactorClient(client);\n const documentCache = new DocumentCache(client);\n setDocumentCache(documentCache);\n // Only the cache and the client's realtime socket are torn down. The window\n // slots are deliberately left populated, matching how Connect never unsets\n // them: consumers may read them while React is unmounting, and the next\n // mount overwrites them.\n return () => {\n documentCache.dispose();\n client.dispose();\n };\n }, [client]);\n\n // Published from an effect of its own so that a service the app builds\n // asynchronously still reaches the slot. Rebuilding the client and its cache\n // for it - which sharing the effect above would do - would throw away every\n // open document instead.\n useEffect(() => {\n if (!attachmentService) {\n return;\n }\n ensurePHEventHandlers();\n setAttachmentService(attachmentService);\n }, [attachmentService]);\n\n // Its own effect for the same reason as the attachment service above: the\n // modules must not rebuild the client and its cache. The slot stays\n // populated on unmount, matching the other slots. setVetraPackageManager's\n // reactor side effects no-op here - there is no reactorClientModule to\n // register modules on.\n useEffect(() => {\n if (!documentModels || documentModels.length === 0) {\n return;\n }\n ensurePHEventHandlers();\n setVetraPackageManager(\n new StaticPackageManager([packageFromDocumentModels(documentModels)]),\n );\n }, [documentModels]);\n\n return <>{children}</>;\n}\n\n/**\n * Returns the {@link GraphQLReactorClient} mounted by\n * {@link GraphQLReactorProvider}, or `undefined` when the slot holds something\n * else - the full in-browser reactor client, or nothing yet.\n *\n * `useReactorClient` is typed as the narrow `IReactorBrowserClient` subset both\n * implementations share. This is how a component reaches the light client's own\n * surface, i.e. `subgraph` and `request`.\n *\n * The narrowing is by brand, not by `instanceof`: a page can carry two copies\n * of this module - a bundled package with its own copy, or a hot-replaced one -\n * and `instanceof` would then answer `false` for a perfectly good client and\n * leave the component silently without one.\n */\nexport function useSwitchboardClient(): GraphQLReactorClient | undefined {\n const client = useReactorClient();\n return isGraphQLReactorClient(client) ? client : undefined;\n}\n","import type { DocumentModelModule } from \"document-model\";\nimport { useVetraPackages } from \"./vetra-packages.js\";\n\nexport function useDocumentModelModules(): DocumentModelModule[] | undefined {\n const vetraPackages = useVetraPackages();\n return vetraPackages\n .flatMap((pkg) => pkg.documentModels)\n .filter(\n (module, index, modules) =>\n // deduplicate by documentType and version\n modules.findIndex(\n (m) =>\n m.documentModel.global.id === module.documentModel.global.id &&\n m.version === module.version,\n ) === index,\n );\n}\n\n/**\n * Resolves a document model module by document type, mirroring the registry's\n * semantics (`IDocumentModelRegistry.getModule`): with `version` omitted the\n * LATEST version of the type wins (`version ?? 1` as each module's default),\n * with `version` given only an exact match is returned. The reactor resolves\n * modules the same way when a document is created, so metadata read through\n * this hook and the version a creation actually uses cannot disagree.\n */\nexport function useDocumentModelModuleById(\n id: string | null | undefined,\n version?: number,\n): DocumentModelModule | undefined {\n const documentModelModules = useDocumentModelModules();\n if (!id || !documentModelModules) return undefined;\n\n let latestModule: DocumentModelModule | undefined;\n let latestVersion = -1;\n for (const module of documentModelModules) {\n if (module.documentModel.global.id !== id) continue;\n const moduleVersion = module.version ?? 1;\n if (version !== undefined) {\n if (moduleVersion === version) return module;\n continue;\n }\n if (moduleVersion > latestVersion) {\n latestVersion = moduleVersion;\n latestModule = module;\n }\n }\n return latestModule;\n}\n","import type { Operation } from \"@powerhousedao/shared/document-model\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useReactorClient } from \"./reactor.js\";\n\ntype InternalState = {\n globalOperations: Operation[];\n localOperations: Operation[];\n isLoading: boolean;\n error: Error | undefined;\n};\n\n/** What `useDocumentOperations` returns; exported so consumers can name it. */\nexport type DocumentOperationsState = InternalState & {\n refetch: () => void;\n};\n\n/**\n * Hook to fetch document operations via the reactor client.\n * Operations are no longer auto-populated on documents and must be fetched explicitly.\n *\n * @param documentId - The document ID to fetch operations for\n * @returns Object containing globalOperations, localOperations, isLoading, and error\n */\nexport function useDocumentOperations(\n documentId: string | null | undefined,\n): DocumentOperationsState {\n const reactorClient = useReactorClient();\n const hasFetchedRef = useRef(false);\n const [state, setState] = useState<InternalState>(() => ({\n globalOperations: [],\n localOperations: [],\n isLoading: !!documentId,\n error: undefined,\n }));\n\n const fetchOperations = useCallback(\n async (retryCount = 0): Promise<void> => {\n const MAX_RETRIES = 5;\n const RETRY_DELAY_MS = 500;\n\n if (!documentId || !reactorClient) {\n setState({\n globalOperations: [],\n localOperations: [],\n isLoading: false,\n error: undefined,\n });\n return;\n }\n\n setState((prev) => ({ ...prev, isLoading: true, error: undefined }));\n\n let globalOps: Operation[] = [];\n let localOps: Operation[] = [];\n let fetchError: Error | undefined;\n\n try {\n const globalResult = await reactorClient.getOperations(documentId, {\n scopes: [\"global\"],\n });\n globalOps = globalResult.results;\n } catch (err) {\n fetchError = err instanceof Error ? err : new Error(String(err));\n }\n\n if (!fetchError) {\n try {\n const localResult = await reactorClient.getOperations(documentId, {\n scopes: [\"local\"],\n });\n localOps = localResult.results;\n } catch (err) {\n fetchError = err instanceof Error ? err : new Error(String(err));\n }\n }\n\n // If no operations found and we haven't exhausted retries, wait and try again\n // This handles eventual consistency where operations may not be immediately available\n if (\n !fetchError &&\n globalOps.length === 0 &&\n localOps.length === 0 &&\n retryCount < MAX_RETRIES\n ) {\n await new Promise((resolve) => setTimeout(resolve, RETRY_DELAY_MS));\n return fetchOperations(retryCount + 1);\n }\n\n setState({\n globalOperations: globalOps,\n localOperations: localOps,\n isLoading: false,\n error: fetchError,\n });\n hasFetchedRef.current = true;\n },\n [documentId, reactorClient],\n );\n\n useEffect(() => {\n if (documentId && reactorClient) {\n void fetchOperations();\n } else if (!documentId) {\n setState({\n globalOperations: [],\n localOperations: [],\n isLoading: false,\n error: undefined,\n });\n hasFetchedRef.current = false;\n }\n }, [documentId, reactorClient, fetchOperations]);\n\n // Wrap fetchOperations to hide the internal retry parameter\n const refetch = useCallback(() => {\n void fetchOperations(0);\n }, [fetchOperations]);\n\n return { ...state, refetch };\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { t as PGlite } from "./pglite-CntadC_p-BtEalg1H.js";
2
- import { c as ReactorGraphQLClient, r as GraphQLClientWindowEvents } from "./types-Bitg5Z5j.js";
2
+ import { c as ReactorGraphQLClient, r as GraphQLClientWindowEvents } from "./types-4rfAFZQd.js";
3
3
  import { r as IWorkerAdminClient, t as IInspectorProxy } from "./inspector-proxy-CaCFdEG4.js";
4
4
  import { Action, DocumentAction, DocumentModelModule, PHDocument } from "@powerhousedao/shared/document-model";
5
5
  import { DocumentDriveDocument } from "@powerhousedao/shared/document-drive";
@@ -397,4 +397,4 @@ declare global {
397
397
  } //# sourceMappingURL=global.d.ts.map
398
398
  //#endregion
399
399
  export { PHProcessorsGlobalConfig as $, FailedInstallation as A, PHAppConfigSetters as B, PHToastOptions as C, TimelineItem as D, TimelineDividerItem as E, FullPHGlobalConfig as F, PHDocumentEditorConfigSetters as G, PHDocumentEditorConfig as H, PHAnalyticsGlobalConfig as I, PHGlobalConfigHooks as J, PHDrivesGlobalConfig as K, PHAppConfig as L, IPackageDiscoveryService as M, PendingInstallation as N, DiscoveryEvent as O, PHModal as P, PHGlobalConfigSettersForKey as Q, PHAppConfigHooks as R, PHToastFn as S, TimelineBarItem as T, PHDocumentEditorConfigHooks as U, PHCommonGlobalConfig as V, PHDocumentEditorConfigKey as W, PHGlobalConfigKey as X, PHGlobalConfigHooksForKey as Y, PHGlobalConfigSetters as Z, useDropNode as _, PHGlobal as a, FulfilledPromise as at, IPackagesListener as b, PHGlobalValue as c, PromiseWithState as ct, UsePHGlobalValue as d, PHRelationalProcessorsGlobalConfig as et, WorkerReactorClientModule as f, useDragNode as g, addDraggingNodeEventHandler as h, LOADING as i, DocumentDispatch as it, FailedInstallationReason as j, DiscoveryEventListener as k, SetEvent as l, RejectedPromise as lt, DraggingNode as m, BrowserReactorClientModule as n, PHSentryGlobalConfig as nt, PHGlobalEventHandlerAdders as o, IDocumentCache as ot, WorkerReactorModule as p, PHGlobalConfig as q, BrowserReactorModule as r, IReactorBrowserClient as rt, PHGlobalKey as s, PromiseState as st, AddPHGlobalEventHandler as t, PHRenownGlobalConfig as tt, SetPHGlobalValue as u, IPackageListerUnsubscribe as v, PHToastType as w, PackageManagerInstallResult as x, IPackageManager as y, PHAppConfigKey as z };
400
- //# sourceMappingURL=global-CbyAMlZd.d.ts.map
400
+ //# sourceMappingURL=global-pg5gy2eZ.d.ts.map