@powerhousedao/reactor-browser 6.0.0-dev.226 → 6.0.0-dev.228

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.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["baseAddFolder","moveNode","baseMoveNode","copyNode","baseCopyNode","driveCollectionId","copyNode","moveNode","driveCollectionId","driveCollectionId","REACTOR_SCHEMA","#namespace","#storage","#readMap","#writeMap"],"sources":["../src/errors.ts","../src/utils/documents.ts","../src/utils/user.ts","../src/actions/document.ts","../src/actions/drive.ts","../src/constants.ts","../src/document-model.ts","../src/graphql/adapters.ts","../src/graphql/constants.ts","../src/graphql/fetchers.ts","../src/graphql/batch.ts","../src/graphql/document-fetcher.ts","../src/graphql/graphql-client-document-cache.ts","../src/graphql/mutators.ts","../src/hooks/config/editor.ts","../src/hooks/config/connect.ts","../src/hooks/features.ts","../src/hooks/drives.ts","../src/hooks/graphql-reactor-client.ts","../src/hooks/modals.ts","../src/hooks/package-discovery.ts","../src/hooks/reactor.ts","../src/hooks/revision-history.ts","../src/utils/url.ts","../src/hooks/selected-drive.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/hooks/document-model-modules.ts","../src/hooks/allowed-document-model-modules.ts","../src/hooks/selected-folder.ts","../src/hooks/child-nodes.ts","../src/hooks/config/set-config-by-key.ts","../src/hooks/config/utils.ts","../src/hooks/config/set-config-by-object.ts","../src/hooks/config/use-value-by-key.ts","../src/hooks/connection-state.ts","../src/hooks/document-of-type.ts","../src/hooks/document-operations.ts","../src/hooks/supported-document-types.ts","../src/hooks/document-types.ts","../src/hooks/drive-by-id.ts","../src/hooks/editor-modules.ts","../src/hooks/folder-by-id.ts","../src/graphql/events.ts","../src/graphql/document-cache-client-middleware.ts","../src/hooks/init-graphql-reactor-client.ts","../src/hooks/items-in-selected-folder.ts","../src/hooks/node-actions.ts","../src/hooks/node-by-id.ts","../src/hooks/node-path.ts","../src/hooks/parent-folder.ts","../src/hooks/selected-document.ts","../src/hooks/subgraph-modules.ts","../src/hooks/use-drive-system-info.ts","../src/utils/drives.ts","../src/utils/validate-document.ts","../src/utils/export-document.ts","../src/utils/get-revision-from-date.ts","../src/utils/switchboard.ts","../src/hooks/use-get-switchboard-link.ts","../src/hooks/use-on-drop-file.ts","../src/hooks/user-permissions.ts","../src/pglite/drop.ts","../src/reactor.ts","../src/registry/fetchers.ts","../src/registry/client.ts","../src/remote-controller/action-tracker.ts","../src/remote-controller/remote-client.ts","../src/remote-controller/utils.ts","../src/remote-controller/remote-controller.ts","../src/storage/base-storage.ts","../src/storage/local-storage.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","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} 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} from \"@powerhousedao/shared/document-model\";\nimport {\n baseLoadFromInput,\n baseSaveToFileHandle,\n createPresignedHeader,\n createZip,\n documentModelDocumentType,\n generateId,\n replayDocument,\n setName,\n} from \"@powerhousedao/shared/document-model\";\nimport { logger } from \"document-model\";\nimport {\n DocumentModelNotFoundError,\n UnsupportedDocumentTypeError,\n} from \"../errors.js\";\nimport { isDocumentTypeSupported } from \"../utils/documents.js\";\nimport { getUserPermissions } from \"../utils/user.js\";\nimport { queueActions, queueOperations, uploadOperations } from \"./queue.js\";\n\nconst BASE_STATE_KEYS = new Set([\"auth\"]);\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 const zip = await createZip(document);\n zip\n .generateAsync({ type: \"blob\" })\n .then((blob) => {\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 })\n .catch(logger.error);\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 const reactorClient = window.ph?.reactorClient;\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: IReactorClient,\n document: PHDocument,\n pageSize = 100,\n): Promise<DocumentOperations> {\n const scopes = Object.keys(document.state).filter(\n (k) => !BASE_STATE_KEYS.has(k),\n );\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\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\nexport async function loadFile(path: string | File) {\n const baseDocument = await baseLoadFromInput(\n path,\n (state: PHDocument) => state,\n { checkHashes: true },\n );\n\n const reactorClient = window.ph?.reactorClient;\n if (!reactorClient) {\n throw new Error(\"ReactorClient not initialized\");\n }\n const { results: documentModelModules } =\n await reactorClient.getDocumentModelModules();\n const documentModelModule = documentModelModules.find(\n (module) =>\n module.documentModel.global.id === baseDocument.header.documentType,\n );\n if (!documentModelModule) {\n throw new DocumentModelNotFoundError(baseDocument.header.documentType);\n }\n return documentModelModule.utils.loadFromInput(path);\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) {\n const { isAllowedToCreateDocuments } = getUserPermissions();\n if (!isAllowedToCreateDocuments) {\n throw new Error(\"User is not allowed to create documents\");\n }\n\n const reactorClient = window.ph?.reactorClient;\n if (!reactorClient) {\n throw new Error(\"ReactorClient not initialized\");\n }\n\n // get the module\n const documentModelModule =\n await reactorClient.getDocumentModelModule(documentType);\n\n // create - use passed document's state if available\n const newDocument = document ?? documentModelModule.utils.createDocument();\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\", e);\n throw new Error(\"There was an error adding document\");\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 (exclude document-scope ops —\n // the reactor already generated CREATE_DOCUMENT + UPGRADE_DOCUMENT above)\n await uploadOperations(\n documentId,\n filterDomainOperations(document.operations),\n queueOperations,\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 const reactor = window.ph?.reactorClient;\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 // 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 // Handle replace resolution by deleting the existing document\n if (\n duplicateCheck.isDuplicate &&\n resolveConflict === \"replace\" &&\n duplicateCheck.nodeId\n ) {\n await deleteNode(driveId, duplicateCheck.nodeId);\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 // Uploading stage (20-100%)\n await uploadOperations(\n documentId,\n filterDomainOperations(document.operations),\n queueOperations,\n {\n onProgress: (uploadProgress) => {\n if (\n uploadProgress.totalOperations &&\n uploadProgress.uploadedOperations !== undefined\n ) {\n const uploadPercent =\n uploadProgress.totalOperations > 0\n ? uploadProgress.uploadedOperations /\n uploadProgress.totalOperations\n : 0;\n const overallProgress = 20 + Math.round(uploadPercent * 80);\n onProgress?.({\n stage: \"uploading\",\n progress: overallProgress,\n totalOperations: uploadProgress.totalOperations,\n uploadedOperations: uploadProgress.uploadedOperations,\n });\n }\n },\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 const reactorClient = window.ph?.reactorClient;\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 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\nasync function _duplicateDocument(\n reactor: IReactorClient,\n document: PHDocument,\n newId = generateId(),\n) {\n const documentModule = await reactor.getDocumentModelModule(\n document.header.documentType,\n );\n\n return replayDocument(\n document.initialState,\n document.operations,\n documentModule.reducer,\n createPresignedHeader(newId, document.header.documentType),\n );\n}\n\nexport async function copyNode(\n driveId: string,\n src: Node,\n target: Node | undefined,\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 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","import { driveCollectionId } from \"@powerhousedao/reactor\";\nimport {\n driveCreateDocument,\n setAvailableOffline,\n setSharingType,\n type DocumentDriveDocument,\n type DriveInput,\n type SharingType,\n} from \"@powerhousedao/shared/document-drive\";\nimport type { PHDocument } from \"@powerhousedao/shared/document-model\";\nimport { getUserPermissions } from \"../utils/user.js\";\n\nexport async function addDrive(input: DriveInput, preferredEditor?: string) {\n const { isAllowedToCreateDocuments } = getUserPermissions();\n if (!isAllowedToCreateDocuments) {\n throw new Error(\"User is not allowed to create drives\");\n }\n\n const reactorClient = window.ph?.reactorClient;\n if (!reactorClient) {\n throw new Error(\"ReactorClient not initialized\");\n }\n\n const driveDoc = driveCreateDocument({\n global: {\n name: input.global.name || \"\",\n icon: input.global.icon ?? null,\n nodes: [],\n },\n });\n\n if (preferredEditor) {\n driveDoc.header.meta = { preferredEditor };\n }\n\n return await reactorClient.create<DocumentDriveDocument>(driveDoc);\n}\n\nexport async function addRemoteDrive(url: string, driveId?: string) {\n const reactorClient = window.ph?.reactorClient;\n if (!reactorClient) {\n throw new Error(\"ReactorClient not initialized\");\n }\n\n const sync =\n window.ph?.reactorClientModule?.reactorModule?.syncModule?.syncManager;\n if (!sync) {\n throw new Error(\"Sync not initialized\");\n }\n\n // Fetch drive info from the REST endpoint to get both id and graphqlEndpoint\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`Failed to resolve drive info from ${url}`);\n }\n const driveInfo = (await response.json()) as {\n id: string;\n graphqlEndpoint: string;\n };\n\n const resolvedDriveId = driveId ?? driveInfo.id;\n const collectionId = driveCollectionId(\"main\", resolvedDriveId);\n\n const existingRemote = sync\n .list()\n .find((remote) => remote.collectionId === collectionId);\n if (existingRemote) {\n return resolvedDriveId;\n }\n\n const remoteName = crypto.randomUUID();\n\n await sync.add(remoteName, collectionId, {\n type: \"gql\",\n parameters: {\n url: driveInfo.graphqlEndpoint,\n },\n });\n\n return resolvedDriveId;\n}\n\nexport async function deleteDrive(driveId: string) {\n const { isAllowedToCreateDocuments } = getUserPermissions();\n if (!isAllowedToCreateDocuments) {\n throw new Error(\"User is not allowed to delete drives\");\n }\n\n const reactorClient = window.ph?.reactorClient;\n if (!reactorClient) {\n throw new Error(\"ReactorClient not initialized\");\n }\n await reactorClient.deleteDocument(driveId);\n}\n\nexport async function renameDrive(\n driveId: string,\n name: string,\n): Promise<PHDocument | undefined> {\n const { isAllowedToCreateDocuments } = getUserPermissions();\n if (!isAllowedToCreateDocuments) {\n throw new Error(\"User is not allowed to rename drives\");\n }\n\n const reactorClient = window.ph?.reactorClient;\n if (!reactorClient) {\n throw new Error(\"ReactorClient not initialized\");\n }\n return await reactorClient.rename(driveId, name);\n}\n\nexport async function setDriveAvailableOffline(\n driveId: string,\n availableOffline: boolean,\n): Promise<PHDocument | undefined> {\n const { isAllowedToCreateDocuments } = getUserPermissions();\n if (!isAllowedToCreateDocuments) {\n throw new Error(\"User is not allowed to change drive availability\");\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 setAvailableOffline({ availableOffline }),\n ]);\n}\n\nexport async function setDriveSharingType(\n driveId: string,\n sharingType: SharingType,\n): Promise<PHDocument | undefined> {\n const { isAllowedToCreateDocuments } = getUserPermissions();\n if (!isAllowedToCreateDocuments) {\n throw new Error(\"User is not allowed to change drive sharing type\");\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 setSharingType({ type: sharingType }),\n ]);\n}\n","export const DEFAULT_DRIVE_EDITOR_ID = \"powerhouse/generic-drive-explorer\";\nexport const COMMON_PACKAGE_ID = \"powerhouse/common\";\n","import type {\n DocumentModelModule,\n DocumentModelPHState,\n} from \"@powerhousedao/shared/document-model\";\nimport { documentModelDocumentModelModule } from \"document-model\";\n\nexport const baseDocumentModelsMap: Record<\n string,\n DocumentModelModule<DocumentModelPHState>\n> = {\n DocumentModel:\n documentModelDocumentModelModule as DocumentModelModule<DocumentModelPHState>,\n};\n\nexport const baseDocumentModels = Object.values(baseDocumentModelsMap);\n","import type {\n DocumentOperations,\n PHBaseState,\n PHDocument,\n PHDocumentHeader,\n} from \"document-model\";\nimport { map, pipe } from \"remeda\";\nimport { z } from \"zod\";\nimport type {\n FindDocumentsQuery,\n GetDocumentWithOperationsQuery,\n} from \"./gen/schema.js\";\nimport type { TStateSchemaZodObject } from \"./types.js\";\n\ntype QueryDocumentResult = NonNullable<\n GetDocumentWithOperationsQuery[\"document\"]\n>[\"document\"];\n\ntype FindDocumentsItems = NonNullable<\n FindDocumentsQuery[\"findDocuments\"]\n>[\"items\"];\n\nexport function phDocumentFromQuery<\n TDocumentSchema extends TStateSchemaZodObject,\n>(document: QueryDocumentResult, documentSchema?: TDocumentSchema) {\n const phDocument = {\n header: phDocumentHeaderFromQuery(document),\n state: phDocumentStateFromQuery(document),\n initialState: phDocumentStateFromQuery(document),\n operations:\n phDocumentOperationsFromGetDocumentWithOperationsQuery(document),\n clipboard: [],\n };\n if (documentSchema !== undefined) documentSchema.parse(phDocument);\n return phDocument as PHDocument;\n}\n\nexport function phDocumentsFromQuery<\n TDocumentSchema extends TStateSchemaZodObject,\n>(items: FindDocumentsItems, documentSchema?: TDocumentSchema) {\n const documents = pipe(\n items,\n map((document) => phDocumentFromQuery(document, documentSchema)),\n );\n return documents;\n}\n\nfunction phDocumentHeaderFromQuery(queryDocument: QueryDocumentResult) {\n const phDocumentHeader = {\n branch: \"main\",\n id: queryDocument.id,\n name: queryDocument.name,\n documentType: queryDocument.documentType,\n createdAtUtcIso:\n queryDocument.createdAtUtcIso instanceof Date\n ? queryDocument.createdAtUtcIso.toUTCString()\n : queryDocument.createdAtUtcIso,\n lastModifiedAtUtcIso:\n queryDocument.lastModifiedAtUtcIso instanceof Date\n ? queryDocument.lastModifiedAtUtcIso.toUTCString()\n : queryDocument.lastModifiedAtUtcIso,\n slug: queryDocument.slug ?? \"\",\n };\n return phDocumentHeader as PHDocumentHeader;\n}\n\nfunction phDocumentStateFromQuery<\n TDocumentSchema extends TStateSchemaZodObject,\n>(queryDocument: QueryDocumentResult, documentSchema?: TDocumentSchema) {\n if (documentSchema !== undefined)\n return documentSchema.shape.state.parse(queryDocument.state);\n return queryDocument.state as PHBaseState;\n}\n\nfunction phDocumentOperationsFromGetDocumentWithOperationsQuery(\n queryDocument: QueryDocumentResult,\n) {\n if (\n queryDocument.operations === null ||\n queryDocument.operations === undefined\n )\n return {\n global: [],\n };\n\n const documentOperations = {\n global: [...queryDocument.operations.items],\n };\n return documentOperations as DocumentOperations;\n}\nexport function identifierFromMutateDocumentOperationVariables(\n variables: unknown,\n) {\n return z\n .object({\n documentIdentifier: z.string(),\n })\n .parse(variables).documentIdentifier;\n}\n","export const DEFAULT_DRIVE_ID = \"powerhouse\" as const;\nexport const DEFAULT_SWITCHBOARD_URL = \"http://localhost:4001/graphql\" as const;\nexport const graphqlEventsToSyncDrive = [\n \"CreateEmptyDocument\",\n \"CreateDocument\",\n \"AddChildren\",\n \"RemoveChildren\",\n \"MoveChildren\",\n \"DeleteDocument\",\n \"DeleteDocuments\",\n] as const;\n\nexport const graphqlDocumentEvents = [\n \"MutateDocument\",\n \"MutateDocumentAsync\",\n \"DeleteDocument\",\n] as const;\n\nexport const graphqlDocumentsEvents = [\"DeleteDocuments\"] as const;\n","import { map } from \"remeda\";\nimport { phDocumentFromQuery } from \"./adapters.js\";\nimport type { TStateSchemaZodObject } from \"./types.js\";\n\nexport async function reactorGraphqlFetchDocument<\n TDocumentSchema extends TStateSchemaZodObject,\n>(identifier: string, documentSchema?: TDocumentSchema) {\n const client = window.ph?.reactorGraphQLClient;\n\n if (!client) {\n throw new Error(\n \"Please call `useInitReactorGraphqlClient` to use its functions\",\n );\n }\n try {\n const result = await client.GetDocument({\n identifier,\n });\n const document = result.document?.document;\n if (!document) return undefined;\n return phDocumentFromQuery(document, documentSchema);\n } catch (error) {\n return undefined;\n }\n}\n\nexport async function reactorGraphqlBatchFetchDocuments(\n identifiers: readonly string[],\n) {\n const client = window.ph?.reactorGraphQLClient;\n\n if (!client) {\n throw new Error(\n \"Please call `useInitReactorGraphqlClient` to use its functions\",\n );\n }\n const promises = map(identifiers, (identifier) =>\n reactorGraphqlFetchDocument(identifier),\n );\n return await Promise.all(promises);\n}\n","import { funnel } from \"remeda\";\n\ntype PromiseCallbacks<Result> = Readonly<\n Parameters<ConstructorParameters<typeof Promise<Result>>[0]>\n>;\n\ntype BatchRequest<Params extends unknown[], Result> = {\n readonly params: Params;\n readonly promiseCallbacks: PromiseCallbacks<Result>;\n};\n\nexport type Batch<Params extends unknown[], Result> = {\n call: (...params: Params) => Promise<Result>;\n cancel: () => void;\n flush: () => void;\n readonly isIdle: boolean;\n};\n\n/**\n * A reference implementation for an async batching utility function built on\n * top of the `funnel` general purpose execution utility function. It will\n * accumulate all params passed to an async `call` method within the defined\n * burst duration and then use an async executor to process them in one\n * invocation. It then extracts an individual result for each call which is\n * used to resolve the original call.\n *\n * This allows synchronizing multiple async calls while keeping each call site\n * isolated from the rest (for example, as react components).\n *\n * This reference implementation can be copied into your project as-is, or you\n * can use it as the basis for a more complex implementation with additional\n * features.\n *\n * @param callback - The main function that takes a batch and returns an\n * aggregated response. The typing for the it's parameters will derive the\n * typing for the extractor and the `call` method.\n * @param extractor - A function that takes the aggregated response and extracts\n * from it the result for each individual call. The function is called with both\n * the index in the batch, and the params passed to the `call` method. This\n * allows handling APIs that return batch results as both objects and arrays.\n * @param maxBurstDurationMs - The period of time where the batcher would\n * collect params before triggering the executor. When set to 0 the batcher\n * does not incur any additional delays to the execution and would trigger at\n * the next tick, just like a regular async function would. This is also the\n * default value.\n * @returns A Funnel object with the `call` method augmented to support async\n * response.\n */\nexport function batch<Params extends unknown[], BatchResponse, Result>(\n callback: (requests: readonly Params[]) => Promise<BatchResponse>,\n extractor: (\n response: BatchResponse,\n index: number,\n ...params: Params\n ) => Result,\n maxBurstDurationMs = 0,\n): Batch<Params, Result> {\n const batchFunnel = funnel(\n (requests: readonly BatchRequest<Params, Result>[]) => {\n callback(requests.map(({ params }) => params))\n .then((response) => {\n for (const [\n index,\n {\n params,\n promiseCallbacks: [resolve, reject],\n },\n ] of requests.entries()) {\n try {\n const result = extractor(response, index, ...params);\n resolve(result);\n } catch (error) {\n reject(error);\n }\n }\n })\n .catch((error) => {\n for (const {\n promiseCallbacks: [, reject],\n } of requests) {\n reject(error);\n }\n });\n },\n {\n reducer: (\n requests: readonly BatchRequest<Params, Result>[] | undefined,\n request: BatchRequest<Params, Result>,\n ) => [...(requests ?? []), request],\n maxBurstDurationMs,\n triggerAt: \"end\",\n },\n );\n\n return {\n ...batchFunnel,\n\n call: (...params: Params) =>\n new Promise<Result>((...promiseCallbacks) => {\n batchFunnel.call({ promiseCallbacks, params });\n }),\n };\n}\n","import type { PHDocument } from \"document-model\";\nimport { filter, isTruthy, map, mapToObj, pipe, prop, unique } from \"remeda\";\nimport { type Batch, batch } from \"./batch.js\";\nimport { reactorGraphqlBatchFetchDocuments } from \"./fetchers.js\";\n\nfunction makeDocumentsById(documents: (PHDocument | undefined)[] = []) {\n return pipe(\n documents,\n filter(isTruthy),\n mapToObj((document) => [document.header.id, document]),\n );\n}\n\nexport class DocumentFetcher {\n private batchGetDocuments: Batch<[id: string], PHDocument>;\n\n constructor() {\n this.batchGetDocuments = batch(\n async (requests: readonly [id: string][]) => {\n const ids = unique(map(requests, ([id]) => id));\n const documents = await reactorGraphqlBatchFetchDocuments(ids);\n\n return makeDocumentsById(documents);\n },\n (documentsById, _, id) => {\n const document = prop(documentsById, id);\n return document;\n },\n );\n }\n\n get(id: string): Promise<PHDocument> {\n return this.batchGetDocuments.call(id);\n }\n\n getBatch(ids: string[]): Promise<PHDocument[]> {\n return Promise.all(map(ids, (id) => this.get(id)));\n }\n}\n","import type { PHDocument } from \"document-model\";\nimport { forEach } from \"remeda\";\nimport { addPromiseState, readPromiseState } from \"../document-cache.js\";\nimport type {\n FulfilledPromise,\n IDocumentCache,\n PromiseWithState,\n} from \"../types/documents.js\";\nimport { DocumentFetcher } from \"./document-fetcher.js\";\n\nexport class GraphQLClientDocumentCache implements IDocumentCache {\n private fetcher: DocumentFetcher;\n\n private documents = new Map<string, PromiseWithState<PHDocument>>();\n\n private batchPromises = new Map<\n string,\n {\n promises: readonly Promise<PHDocument>[];\n promise: PromiseWithState<PHDocument[]>;\n }\n >();\n\n private listeners = new Map<string, (() => void)[]>();\n\n constructor() {\n this.fetcher = new DocumentFetcher();\n\n window.addEventListener(\"MutateDocument\", (event) => {\n this.handleDocumentMutated(event.detail.identifier).catch(console.error);\n });\n\n window.addEventListener(\"MutateDocumentAsync\", (event) => {\n this.handleDocumentMutated(event.detail.identifier).catch(console.error);\n });\n }\n\n get(id: string, refetch?: boolean): Promise<PHDocument> {\n const current = this.documents.get(id);\n\n if (current) {\n if (current.status === \"pending\") {\n return current;\n }\n\n if (!refetch) {\n return current;\n }\n }\n\n const promise = addPromiseState(\n this.fetcher.get(id).then((document) => {\n this.invalidateBatchesContaining(id);\n return document;\n }),\n );\n\n this.documents.set(id, promise);\n\n return promise;\n }\n\n getBatch(ids: string[]): Promise<PHDocument[]> {\n const key = ids.join(\",\");\n const cached = this.batchPromises.get(key);\n\n const currentPromises = ids.map((id) => this.get(id));\n\n if (cached) {\n const samePromises = currentPromises.every(\n (promise, index) => promise === cached.promises[index],\n );\n\n if (samePromises) {\n return cached.promise;\n }\n }\n\n const states = currentPromises.map((promise) =>\n readPromiseState(promise as PromiseWithState<PHDocument>),\n );\n\n const allFulfilled = states.every((state) => state.status === \"fulfilled\");\n\n if (allFulfilled) {\n const values = states.map(\n (state) => (state as { status: \"fulfilled\"; value: PHDocument }).value,\n );\n\n const batchPromise = Promise.resolve(values) as PromiseWithState<\n PHDocument[]\n >;\n\n batchPromise.status = \"fulfilled\";\n (batchPromise as FulfilledPromise<PHDocument[]>).value = values;\n\n this.batchPromises.set(key, {\n promises: currentPromises,\n promise: batchPromise,\n });\n\n return batchPromise;\n }\n\n const batchPromise = addPromiseState(Promise.all(currentPromises));\n\n this.batchPromises.set(key, {\n promises: currentPromises,\n promise: batchPromise,\n });\n\n return batchPromise;\n }\n\n private invalidateBatchesContaining(documentId: string): void {\n for (const key of this.batchPromises.keys()) {\n if (key.split(\",\").includes(documentId)) {\n this.batchPromises.delete(key);\n }\n }\n }\n\n subscribe(id: string | string[], callback: () => void): () => void {\n const ids = Array.isArray(id) ? id : [id];\n\n for (const documentId of ids) {\n const listeners = this.listeners.get(documentId) ?? [];\n this.listeners.set(documentId, [...listeners, callback]);\n }\n\n return () => {\n for (const documentId of ids) {\n const listeners = this.listeners.get(documentId) ?? [];\n this.listeners.set(\n documentId,\n listeners.filter((listener) => listener !== callback),\n );\n }\n };\n }\n\n private notify(id: string): void {\n const listeners = this.listeners.get(id) ?? [];\n\n for (const listener of listeners) {\n listener();\n }\n }\n\n private async handleDocumentMutated(id: string) {\n this.invalidateBatchesContaining(id);\n await this.get(id);\n this.notify(id);\n }\n\n private handleDocumentDeleted(id: string) {\n this.documents.delete(id);\n this.invalidateBatchesContaining(id);\n this.notify(id);\n }\n\n private handleDocumentsDeleted(ids: string[]) {\n forEach(ids, (id) => this.handleDocumentDeleted(id));\n }\n}\n","import type { PHDocument } from \"document-model\";\nimport { DEFAULT_DRIVE_ID } from \"./constants.js\";\nimport type { Scalars } from \"./gen/schema.js\";\n\nexport async function reactorGraphqlCreateDocument<\n TDocument extends PHDocument,\n>(document: TDocument, parentIdentifier = DEFAULT_DRIVE_ID) {\n const client = window.ph?.reactorGraphQLClient;\n\n if (!client) {\n throw new Error(\n \"Please call `useInitReactorGraphqlClient` to use its functions\",\n );\n }\n\n const result = await client.CreateDocument({\n document,\n parentIdentifier,\n });\n\n return result;\n}\n\nexport async function reactorGraphqlDeleteDocument(identifier: string) {\n const client = window.ph?.reactorGraphQLClient;\n\n if (!client) {\n throw new Error(\n \"Please call `useInitReactorGraphqlClient` to use its functions\",\n );\n }\n\n const result = await client.DeleteDocument({\n identifier,\n });\n\n return result;\n}\n\nexport async function reactorGraphqlDeleteDocuments(identifiers: string[]) {\n const client = window.ph?.reactorGraphQLClient;\n\n if (!client) {\n throw new Error(\n \"Please call `useInitReactorGraphqlClient` to use its functions\",\n );\n }\n\n const result = await client.DeleteDocuments({\n identifiers,\n });\n\n return result;\n}\n\nexport async function reactorGraphqlMutateDocument(\n documentIdentifier: string,\n ...actions: ReadonlyArray<Scalars[\"JSONObject\"][\"input\"]>\n) {\n const client = window.ph?.reactorGraphQLClient;\n\n if (!client) {\n throw new Error(\n \"Please call `useInitReactorGraphqlClient` to use its functions\",\n );\n }\n\n const result = await client.MutateDocument({\n documentIdentifier,\n actions,\n });\n\n return result;\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: 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 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 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 {\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 { 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 { 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 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(documentType: string) {\n setPHModal({ type: \"createDocument\", documentType });\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","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 IReactorClient,\n ISyncManager,\n} from \"@powerhousedao/reactor\";\nimport type {\n AddPHGlobalEventHandler,\n BrowserReactorClientModule,\n SetPHGlobalValue,\n UsePHGlobalValue,\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 */\nexport const useReactorClientModule: UsePHGlobalValue<BrowserReactorClientModule> =\n reactorClientModuleEventFunctions.useValue;\n\n/** Sets the reactor client module */\nexport const setReactorClientModule: SetPHGlobalValue<BrowserReactorClientModule> =\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<IReactorClient> =\n reactorClientEventFunctions.useValue;\n\n/** Sets the reactor client */\nexport const setReactorClient: SetPHGlobalValue<IReactorClient> =\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 useReactorClientModule()?.reactorModule?.database;\n\nexport const usePGlite = (): PGlite | undefined => useReactorClientModule()?.pg;\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 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 { DocumentDispatch } from \"@powerhousedao/reactor-browser\";\nimport type {\n DocumentDriveAction,\n DocumentDriveDocument,\n} from \"@powerhousedao/shared/document-drive\";\nimport {\n createUrlWithPreservedParams,\n extractDriveIdFromPath,\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\";\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 // Find the drive by slug to get its actual ID\n const drive = window.ph?.drives?.find((d) => d.header.slug === driveSlug);\n const driveId = drive?.header.id;\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\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 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 {\n createUrlWithPreservedParams,\n extractDriveSlugFromPath,\n extractNodeIdFromSlug,\n extractNodeSlugFromPath,\n makeNodeSlug,\n resolveUrlPathname,\n} from \"../utils/url.js\";\nimport { useNodesInSelectedDrive } from \"./items-in-selected-drive.js\";\nimport { makePHEventFunctions } from \"./make-ph-event-functions.js\";\n\nconst selectedNodeIdEventFunctions = makePHEventFunctions(\"selectedNodeId\");\nconst useSelectedNodeId = selectedNodeIdEventFunctions.useValue;\nconst setSelectedNodeId = selectedNodeIdEventFunctions.setValue;\nexport const addSelectedNodeIdEventHandler =\n selectedNodeIdEventFunctions.addEventHandler;\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\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 const selectedNodeId = window.ph?.selectedNodeId;\n if (nodeSlug !== selectedNodeId) {\n setSelectedNode(nodeSlug);\n }\n });\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 {\n DuplicateManifestError,\n DuplicateModuleError,\n} from \"@powerhousedao/reactor\";\nimport type { DocumentModelLib } from \"document-model\";\nimport { useSyncExternalStore } from \"react\";\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.flatMap((pkg) => pkg.documentModels);\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 duplicates = [];\n for (const result of results) {\n if (result.status === \"error\") {\n if (DuplicateModuleError.isError(result.error)) {\n duplicates.push(result);\n } else {\n console.error(\n \"Failed to register document model module:\",\n result.error,\n );\n }\n }\n }\n if (duplicates.length > 0) {\n const duplicateTypes = duplicates.map(\n (r) => r.item.documentModel.global.id,\n );\n registry.unregisterModules(...duplicateTypes);\n registry.registerModules(...duplicates.map((r) => r.item));\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 (DuplicateManifestError.isError(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 addRenownChainIdEventHandler,\n addRenownNetworkIdEventHandler,\n addRenownUrlEventHandler,\n addRequiresHardRefreshEventHandler,\n addRouterBasenameEventHandler,\n addSentryDsnEventHandler,\n addSentryEnvEventHandler,\n addSentryReleaseEventHandler,\n addStudioModeEventHandler,\n addVersionCheckIntervalEventHandler,\n addVersionEventHandler,\n addWarnOutdatedAppEventHandler,\n} from \"./config/connect.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 { 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};\n\nconst phGlobalEventHandlerRegisterFunctions: PHGlobalEventHandlerAdders = {\n ...commonGlobalEventHandlerFunctions,\n reactorClientModule: addReactorClientModuleEventHandler,\n reactorClient: addReactorClientEventHandler,\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 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","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\nexport function useDocumentModelModuleById(\n id: string | null | undefined,\n): DocumentModelModule | undefined {\n const documentModelModules = useDocumentModelModules();\n return documentModelModules?.find(\n (module) => module.documentModel.global.id === id,\n );\n}\n","import { useAllowedDocumentTypes } from \"./config/editor.js\";\nimport { useDocumentModelModules } from \"./document-model-modules.js\";\n\nexport function useAllowedDocumentModelModules() {\n const documentModelModules = useDocumentModelModules();\n const allowedDocumentTypes = useAllowedDocumentTypes();\n if (!allowedDocumentTypes?.length) return documentModelModules;\n return documentModelModules?.filter((module) =>\n allowedDocumentTypes.includes(module.documentModel.global.id),\n );\n}\n","import type { FolderNode } from \"@powerhousedao/shared/document-drive\";\nimport { isFolderNodeKind } from \"../utils/nodes.js\";\nimport { useSelectedNode } from \"./selected-node.js\";\n\n/** Returns the selected folder. */\nexport function useSelectedFolder(): FolderNode | undefined {\n const selectedNode = useSelectedNode();\n if (isFolderNodeKind(selectedNode)) return selectedNode;\n return undefined;\n}\n","import type { Node } from \"@powerhousedao/shared/document-drive\";\nimport { sortNodesByName } from \"../utils/nodes.js\";\nimport { useNodesInSelectedDrive } from \"./items-in-selected-drive.js\";\nimport { useSelectedFolder } from \"./selected-folder.js\";\n\n/** Returns the child nodes for the selected drive or folder. */\nexport function useNodesInSelectedDriveOrFolder(): Node[] {\n const nodes = useNodesInSelectedDrive();\n const selectedFolder = useSelectedFolder();\n const selectedFolderId = selectedFolder?.id;\n if (!nodes) return [];\n if (!selectedFolderId)\n return sortNodesByName(nodes.filter((n) => !n.parentFolder));\n return sortNodesByName(\n nodes.filter((n) => n.parentFolder === selectedFolderId),\n );\n}\n","import type {\n PHAppConfig,\n PHAppConfigKey,\n PHDocumentEditorConfig,\n PHDocumentEditorConfigKey,\n PHGlobalConfig,\n PHGlobalConfigKey,\n} from \"@powerhousedao/reactor-browser\";\nimport { phGlobalConfigSetters } from \"./connect.js\";\nimport { phAppConfigSetters, phDocumentEditorConfigSetters } from \"./editor.js\";\n\nexport function setPHGlobalConfigByKey<TKey extends PHGlobalConfigKey>(\n key: TKey,\n value: PHGlobalConfig[TKey] | undefined,\n) {\n const setter = phGlobalConfigSetters[key];\n setter(value);\n}\n\nexport function setPHAppConfigByKey<TKey extends PHAppConfigKey>(\n key: TKey,\n value: PHAppConfig[TKey] | undefined,\n) {\n const setter = phAppConfigSetters[key];\n setter(value);\n}\n\nexport function setPHDocumentEditorConfigByKey<\n TKey extends PHDocumentEditorConfigKey,\n>(key: TKey, value: PHDocumentEditorConfig[TKey] | undefined) {\n const setter = phDocumentEditorConfigSetters[key];\n setter(value);\n}\n","import type {\n PHGlobalConfig,\n PHGlobalConfigKey,\n PHGlobalConfigSetters,\n} from \"@powerhousedao/reactor-browser\";\nimport { phGlobalConfigSetters } from \"./connect.js\";\n\nexport function callGlobalSetterForKey<TKey extends PHGlobalConfigKey>(\n key: TKey,\n value: PHGlobalConfig[TKey] | undefined,\n) {\n const setter = phGlobalConfigSetters[key] as PHGlobalConfigSetters[TKey];\n setter(value);\n}\n","import type {\n PHAppConfig,\n PHAppConfigKey,\n PHDocumentEditorConfig,\n PHDocumentEditorConfigKey,\n PHGlobalConfig,\n PHGlobalConfigKey,\n} from \"@powerhousedao/reactor-browser\";\nimport { useEffect, useState } from \"react\";\nimport { callGlobalSetterForKey } from \"./utils.js\";\n\nexport function setDefaultPHGlobalConfig(config: PHGlobalConfig) {\n for (const key of Object.keys(config) as PHGlobalConfigKey[]) {\n callGlobalSetterForKey(key, config[key]);\n }\n}\n\nexport function useSetDefaultPHGlobalConfig(config: PHGlobalConfig) {\n const [isInitialized, setIsInitialized] = useState(false);\n\n useEffect(() => {\n if (isInitialized) return;\n setDefaultPHGlobalConfig(config);\n setIsInitialized(true);\n }, [config, isInitialized]);\n}\n\nexport function useResetPHGlobalConfig(defaultConfigForReset: PHGlobalConfig) {\n return function reset() {\n setPHGlobalConfig(defaultConfigForReset);\n };\n}\n\nexport function setPHGlobalConfig(config: Partial<PHGlobalConfig>) {\n for (const key of Object.keys(config) as PHGlobalConfigKey[]) {\n callGlobalSetterForKey(key, config[key]);\n }\n}\n\nexport function useSetPHGlobalConfig(config: Partial<PHGlobalConfig>) {\n const [isInitialized, setIsInitialized] = useState(false);\n\n useEffect(() => {\n if (isInitialized) return;\n setPHGlobalConfig(config);\n setIsInitialized(true);\n }, [config, isInitialized]);\n}\n\n/** Sets the global drive config.\n *\n * Pass in a partial object of the global drive config to set.\n */\nexport function setPHAppConfig(config: Partial<PHAppConfig>) {\n for (const key of Object.keys(config) as PHAppConfigKey[]) {\n callGlobalSetterForKey(key, config[key]);\n }\n}\n\n/** Sets the global document config.\n *\n * Pass in a partial object of the global document config to set.\n */\nexport function setPHDocumentEditorConfig(\n config: Partial<PHDocumentEditorConfig>,\n) {\n for (const key of Object.keys(config) as PHDocumentEditorConfigKey[]) {\n callGlobalSetterForKey(key, config[key]);\n }\n}\n\n/** Wrapper hook for setting the global app config.\n *\n * Automatically sets the global app config when the component mounts.\n *\n * Pass in a partial object of the global app config to set.\n */\nexport function useSetPHAppConfig(config: Partial<PHAppConfig>) {\n const [isInitialized, setIsInitialized] = useState(false);\n\n useEffect(() => {\n if (isInitialized) return;\n setPHAppConfig(config);\n setIsInitialized(true);\n }, [config, isInitialized]);\n}\n\n/** Wrapper hook for setting the global document editor config.\n *\n * Automatically sets the global document editor config when the component mounts.\n *\n * Pass in a partial object of the global document editor config to set.\n */\nexport function useSetPHDocumentEditorConfig(\n config: Partial<PHDocumentEditorConfig>,\n) {\n const [isInitialized, setIsInitialized] = useState(false);\n\n useEffect(() => {\n if (isInitialized) return;\n setPHDocumentEditorConfig(config);\n setIsInitialized(true);\n }, [config, isInitialized]);\n}\n","import type {\n PHAppConfigKey,\n PHDocumentEditorConfigKey,\n PHGlobalConfigKey,\n} from \"@powerhousedao/reactor-browser\";\nimport { phGlobalConfigHooks } from \"./connect.js\";\nimport { phAppConfigHooks, phDocumentEditorConfigHooks } from \"./editor.js\";\n\nexport function usePHGlobalConfigByKey<TKey extends PHGlobalConfigKey>(\n key: TKey,\n) {\n const useValueHook = phGlobalConfigHooks[key];\n return useValueHook();\n}\n\n/** Gets the value of an item in the global drive config for a given key.\n *\n * Strongly typed, inferred from type definition for the key.\n */\nexport function usePHAppConfigByKey<TKey extends PHAppConfigKey>(key: TKey) {\n const useValueHook = phAppConfigHooks[key];\n return useValueHook();\n}\n\n/** Gets the value of an item in the global document config for a given key.\n *\n * Strongly typed, inferred from type definition for the key.\n */\nexport function usePHDocumentEditorConfigByKey<\n TKey extends PHDocumentEditorConfigKey,\n>(key: TKey) {\n const useValueHook = phDocumentEditorConfigHooks[key];\n return useValueHook();\n}\n","import type { ConnectionStateSnapshot } from \"@powerhousedao/reactor\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useSync } from \"./reactor.js\";\n\n/**\n * Returns a map of remote name to connection state snapshot for all remotes.\n * Re-renders when any remote's connection state changes.\n */\nexport function useConnectionStates(): ReadonlyMap<\n string,\n ConnectionStateSnapshot\n> {\n const syncManager = useSync();\n const [states, setStates] = useState<\n ReadonlyMap<string, ConnectionStateSnapshot>\n >(() => buildSnapshot(syncManager));\n const unsubscribesRef = useRef<Array<() => void>>([]);\n\n useEffect(() => {\n if (!syncManager) return;\n\n function subscribe() {\n // Clean up previous subscriptions\n for (const unsub of unsubscribesRef.current) {\n unsub();\n }\n unsubscribesRef.current = [];\n\n const remotes = syncManager!.list();\n for (const remote of remotes) {\n const unsub = remote.channel.onConnectionStateChange(() => {\n setStates(buildSnapshot(syncManager));\n });\n unsubscribesRef.current.push(unsub);\n }\n\n // Set initial state\n setStates(buildSnapshot(syncManager));\n }\n\n subscribe();\n\n // Re-subscribe periodically to pick up added/removed remotes\n const interval = setInterval(subscribe, 5000);\n\n return () => {\n clearInterval(interval);\n for (const unsub of unsubscribesRef.current) {\n unsub();\n }\n unsubscribesRef.current = [];\n };\n }, [syncManager]);\n\n return states;\n}\n\n/**\n * Returns the connection state snapshot for a specific remote by name.\n */\nexport function useConnectionState(\n remoteName: string,\n): ConnectionStateSnapshot | undefined {\n const states = useConnectionStates();\n return states.get(remoteName);\n}\n\nfunction buildSnapshot(\n syncManager: ReturnType<typeof useSync>,\n): ReadonlyMap<string, ConnectionStateSnapshot> {\n const map = new Map<string, ConnectionStateSnapshot>();\n if (!syncManager) return map;\n for (const remote of syncManager.list()) {\n map.set(remote.name, remote.channel.getConnectionState());\n }\n return map;\n}\n","import { ModuleNotFoundError } from \"@powerhousedao/reactor\";\nimport type { DocumentDispatch } from \"@powerhousedao/reactor-browser\";\nimport type { Action, PHDocument } from \"@powerhousedao/shared/document-model\";\nimport { DocumentTypeMismatchError } from \"../errors.js\";\nimport { useDocumentById } from \"./document-by-id.js\";\nimport { useDocumentModelModuleById } from \"./document-model-modules.js\";\n\n/** Returns a document of a specific type, throws an error if the found document has a different type */\nexport function useDocumentOfType<\n TDocument extends PHDocument,\n TAction extends Action,\n>(\n documentId: string | null | undefined,\n documentType: string | null | undefined,\n) {\n const [document, dispatch] = useDocumentById(documentId);\n const documentModelModule = useDocumentModelModuleById(documentType);\n\n if (!documentId || !documentType) return [];\n\n if (!document) {\n throw new Error(`Document not found: ${documentId}`);\n }\n if (!documentModelModule) {\n throw new ModuleNotFoundError(documentType);\n }\n\n if (document.header.documentType !== documentType) {\n throw new DocumentTypeMismatchError(\n documentId,\n documentType,\n document.header.documentType,\n );\n }\n\n return [document, dispatch] as [TDocument, DocumentDispatch<TAction>];\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\ntype 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","import { useDocumentModelModules } from \"./document-model-modules.js\";\n\n/** Returns the supported document types for the reactor (derived from the document model modules) */\nexport function useSupportedDocumentTypesInReactor() {\n const documentModelModules = useDocumentModelModules();\n return documentModelModules?.map((module) => module.documentModel.global.id);\n}\n","import { useAllowedDocumentTypes } from \"./config/editor.js\";\nimport { useSupportedDocumentTypesInReactor } from \"./supported-document-types.js\";\n\n/** Returns the document types a app supports.\n *\n * If present, uses the `allowedDocumentTypes` config value.\n * Otherwise, uses the supported document types from the reactor.\n */\nexport function useDocumentTypes() {\n const allowedDocumentTypes = useAllowedDocumentTypes();\n const supportedDocumentTypes = useSupportedDocumentTypesInReactor();\n return allowedDocumentTypes ?? supportedDocumentTypes;\n}\n","import type {\n DocumentDriveAction,\n DocumentDriveDocument,\n} from \"@powerhousedao/shared/document-drive\";\nimport type { DocumentDispatch } from \"../types/documents.js\";\nimport { useDispatch } from \"./dispatch.js\";\nimport { useDrives } from \"./drives.js\";\n\nexport function useDriveById(\n driveId: string | undefined | null,\n): [DocumentDriveDocument, DocumentDispatch<DocumentDriveAction>] {\n const drives = useDrives();\n const foundDrive = drives?.find((drive) => drive.header.id === driveId);\n const [drive, dispatch] = useDispatch(foundDrive);\n if (!foundDrive) {\n throw new Error(`Drive with id ${driveId} not found`);\n }\n return [drive, dispatch] as [\n DocumentDriveDocument,\n DocumentDispatch<DocumentDriveAction>,\n ];\n}\n","import type { EditorModule } from \"document-model\";\nimport { DEFAULT_DRIVE_EDITOR_ID } from \"../constants.js\";\nimport { useVetraPackages } from \"./vetra-packages.js\";\n\nexport function useEditorModules(): EditorModule[] | undefined {\n const vetraPackages = useVetraPackages();\n return vetraPackages\n .flatMap((pkg) => pkg.editors)\n .filter(\n (module) => !module.documentTypes.includes(\"powerhouse/document-drive\"),\n );\n}\n\nexport function useAppModules(): EditorModule[] | undefined {\n const vetraPackages = useVetraPackages();\n return vetraPackages\n .flatMap((pkg) => pkg.editors)\n .filter((module) =>\n module.documentTypes.includes(\"powerhouse/document-drive\"),\n );\n}\n\nexport function useFallbackEditorModule(\n documentType: string | null | undefined,\n): EditorModule | undefined {\n const editorModules = useEditorModules();\n if (!documentType) return undefined;\n if (editorModules?.length === 0) return undefined;\n\n const modulesForType = editorModules?.filter((module) =>\n module.documentTypes.includes(documentType),\n );\n return modulesForType?.[0];\n}\n\nexport function useAppModuleById(\n id: string | null | undefined,\n): EditorModule | undefined {\n const appModules = useAppModules();\n return appModules?.find((module) => module.config.id === id);\n}\n\nexport function useDefaultAppModule(): EditorModule | undefined {\n const defaultAppModule = useAppModuleById(DEFAULT_DRIVE_EDITOR_ID);\n return defaultAppModule;\n}\n\nexport function useEditorModuleById(\n id: string | null | undefined,\n): EditorModule | undefined {\n const editorModules = useEditorModules();\n return editorModules?.find((module) => module.config.id === id);\n}\n\nexport function useEditorModulesForDocumentType(\n documentType: string | null | undefined,\n) {\n const editorModules = useEditorModules();\n if (!documentType) return undefined;\n\n const modulesForType = editorModules?.filter((module) =>\n module.documentTypes.includes(documentType),\n );\n return modulesForType;\n}\n","import type { FolderNode } from \"@powerhousedao/shared/document-drive\";\nimport { useFolderNodesInSelectedDrive } from \"./items-in-selected-drive.js\";\n\nexport function useFolderById(\n id: string | null | undefined,\n): FolderNode | undefined {\n const folders = useFolderNodesInSelectedDrive();\n return folders?.find((n) => n.id === id);\n}\n","import type {\n GraphQLClientDocumentEvent,\n GraphQLClientDocumentsEvent,\n GraphQLDocumentEventOperationName,\n GraphQLDocumentEventsOperationName,\n} from \"./types.js\";\n\nexport function dispatchGraphQLClientDocumentEvent(\n operationName: GraphQLDocumentEventOperationName,\n identifier: string,\n) {\n const event: GraphQLClientDocumentEvent = new CustomEvent(operationName, {\n detail: { identifier },\n });\n window.dispatchEvent(event);\n}\n\nexport function dispatchGraphQLClientDocumentsEvent(\n operationName: GraphQLDocumentEventsOperationName,\n identifiers: string[],\n) {\n const event: GraphQLClientDocumentsEvent = new CustomEvent(operationName, {\n detail: { identifiers },\n });\n window.dispatchEvent(event);\n}\n","import { isIncludedIn, isStrictEqual } from \"remeda\";\nimport { identifierFromMutateDocumentOperationVariables } from \"./adapters.js\";\nimport { graphqlEventsToSyncDrive } from \"./constants.js\";\nimport { dispatchGraphQLClientDocumentEvent } from \"./events.js\";\nimport type { SdkFunctionWrapper } from \"./gen/schema.js\";\n\nexport const documentCacheClientMiddleware: SdkFunctionWrapper = async (\n action,\n operationName,\n operationType,\n variables: unknown,\n) => {\n console.log({ operationName, operationType, variables });\n const result = await action();\n\n if (isIncludedIn(operationName, graphqlEventsToSyncDrive)) {\n window.dispatchEvent(new CustomEvent(operationName));\n }\n\n if (isStrictEqual(operationName, \"MutateDocument\")) {\n dispatchGraphQLClientDocumentEvent(\n operationName,\n identifierFromMutateDocumentOperationVariables(variables),\n );\n }\n\n return result;\n};\n","import type { DocumentDriveDocument } from \"@powerhousedao/shared\";\nimport { DriveDocumentSchema } from \"@powerhousedao/shared/document-drive\";\nimport { useEffect, useState } from \"react\";\nimport { forEach } from \"remeda\";\nimport { phDocumentFromQuery } from \"../graphql/adapters.js\";\nimport { createClient } from \"../graphql/client.js\";\nimport {\n DEFAULT_DRIVE_ID,\n DEFAULT_SWITCHBOARD_URL,\n graphqlEventsToSyncDrive,\n} from \"../graphql/constants.js\";\nimport { documentCacheClientMiddleware } from \"../graphql/document-cache-client-middleware.js\";\nimport { GraphQLClientDocumentCache } from \"../graphql/graphql-client-document-cache.js\";\nimport {\n callEventHandlerRegisterFunctions,\n commonGlobalEventHandlerFunctions,\n} from \"./add-ph-event-handlers.js\";\nimport { setDocumentCache } from \"./document-cache.js\";\nimport { setDrives } from \"./drives.js\";\nimport { setGraphQLReactorClient } from \"./graphql-reactor-client.js\";\nimport { setSelectedDrive } from \"./selected-drive.js\";\nimport { setSelectedNode } from \"./selected-node.js\";\n\nexport function useInitReactorGraphqlClient(\n switchboardUrl = DEFAULT_SWITCHBOARD_URL,\n driveId = DEFAULT_DRIVE_ID,\n) {\n const [hasInit, setHasInit] = useState(false);\n\n useEffect(() => {\n if (hasInit) return;\n\n initGraphQLReactorClientWithDocumentCache(switchboardUrl, driveId)\n .then(() => setHasInit(true))\n .catch(console.error);\n }, [hasInit]);\n\n return hasInit;\n}\n\nasync function reactorGraphqlFetchDrive(\n identifier: string,\n): Promise<DocumentDriveDocument> {\n const client = window.ph?.reactorGraphQLClient;\n\n if (!client) {\n throw new Error(\n \"Please call `useInitReactorGraphqlClient` to use its functions\",\n );\n }\n\n const result = await client.GetDocument({ identifier });\n\n if (!result.document?.document) {\n throw new Error(\"Could not fetch drive with id: \" + identifier);\n }\n\n const drive = phDocumentFromQuery(\n result.document.document,\n DriveDocumentSchema,\n ) as DocumentDriveDocument;\n return drive;\n}\n\nasync function reactorGraphqlSyncDrive(driveId: string) {\n const client = window.ph?.reactorGraphQLClient;\n\n if (!client) {\n throw new Error(\n \"Please call `useInitReactorGraphqlClient` to use its functions\",\n );\n }\n const drive = await reactorGraphqlFetchDrive(driveId);\n setDrives([drive]);\n setSelectedDrive(drive);\n}\n\nasync function initGraphQLReactorClientWithDocumentCache(\n switchboardUrl: string,\n driveId: string,\n) {\n if (!window.ph) {\n window.ph = {};\n }\n\n callEventHandlerRegisterFunctions(commonGlobalEventHandlerFunctions);\n\n const client = createClient(switchboardUrl, documentCacheClientMiddleware);\n setGraphQLReactorClient(client);\n await reactorGraphqlSyncDrive(driveId);\n setSelectedNode(undefined);\n setDocumentCache(new GraphQLClientDocumentCache());\n\n forEach(graphqlEventsToSyncDrive, (name) => {\n window.addEventListener(name, () => {\n reactorGraphqlSyncDrive(driveId).catch(console.error);\n });\n });\n}\n","import type {\n FileNode,\n FolderNode,\n Node,\n} from \"@powerhousedao/shared/document-drive\";\nimport type { PHDocument } from \"@powerhousedao/shared/document-model\";\nimport { isFileNodeKind, isFolderNodeKind } from \"../utils/nodes.js\";\nimport {\n useDocumentsInSelectedDrive,\n useNodesInSelectedDrive,\n} from \"./items-in-selected-drive.js\";\nimport { useSelectedFolder } from \"./selected-folder.js\";\n\n/** Returns the nodes in the selected folder. */\nexport function useNodesInSelectedFolder(): Node[] | undefined {\n const selectedFolder = useSelectedFolder();\n const nodes = useNodesInSelectedDrive();\n if (!selectedFolder || !nodes) return undefined;\n\n return nodes.filter((n) => n.parentFolder === selectedFolder.id);\n}\n\n/** Returns the file nodes in the selected folder. */\nexport function useFileNodesInSelectedFolder(): FileNode[] | undefined {\n const nodes = useNodesInSelectedFolder();\n if (!nodes) return undefined;\n return nodes.filter((n) => isFileNodeKind(n));\n}\n\n/** Returns the folder nodes in the selected folder. */\nexport function useFolderNodesInSelectedFolder(): FolderNode[] | undefined {\n const nodes = useNodesInSelectedFolder();\n if (!nodes) return undefined;\n return nodes.filter((n) => isFolderNodeKind(n));\n}\n\n/** Returns the documents in the selected folder. */\nexport function useDocumentsInSelectedFolder(): PHDocument[] | undefined {\n const documents = useDocumentsInSelectedDrive();\n const fileNodes = useFileNodesInSelectedFolder();\n const fileNodeIds = fileNodes?.map((node) => node.id);\n return documents?.filter((d) => fileNodeIds?.includes(d.header.id));\n}\n","import type { Node } from \"@powerhousedao/shared/document-drive\";\nimport {\n addFile,\n addFolder,\n copyNode,\n moveNode,\n renameDriveNode,\n renameNode,\n} from \"../actions/document.js\";\nimport { useDrives } from \"./drives.js\";\nimport { useFolderById } from \"./folder-by-id.js\";\nimport { useSelectedDriveSafe } from \"./selected-drive.js\";\nimport { useSelectedFolder } from \"./selected-folder.js\";\nimport { setSelectedNode, useSelectedNode } from \"./selected-node.js\";\n\nfunction resolveNode(driveId: string, node: Node | undefined) {\n return node?.id !== driveId ? node : undefined;\n}\n\nexport function useNodeActions() {\n const [selectedDrive] = useSelectedDriveSafe();\n const selectedFolder = useSelectedFolder();\n const selectedNode = useSelectedNode();\n const selectedParentFolder = useFolderById(selectedNode?.parentFolder);\n const selectedDriveId = selectedDrive?.header.id;\n const drives = useDrives();\n\n async function onAddFile(file: File, parent: Node | undefined) {\n if (!selectedDriveId) return;\n\n const fileName = file.name.replace(/\\..+/gim, \"\");\n\n return addFile(\n file,\n selectedDriveId,\n fileName,\n resolveNode(selectedDriveId, parent)?.id,\n );\n }\n\n async function onAddFolder(name: string, parent: Node | undefined) {\n if (!selectedDriveId) return;\n\n return addFolder(\n selectedDriveId,\n name,\n resolveNode(selectedDriveId, parent)?.id,\n );\n }\n\n async function onRenameNode(\n newName: string,\n node: Node,\n ): Promise<Node | undefined> {\n if (!selectedDriveId) return;\n\n const resolvedNode = resolveNode(selectedDriveId, node);\n if (!resolvedNode) {\n console.error(`Node ${node.id} not found`);\n return;\n }\n\n return await renameNode(selectedDriveId, node.id, newName);\n }\n\n async function onCopyNode(src: Node, target: Node | undefined) {\n if (!selectedDriveId) return;\n const resolvedSrc = resolveNode(selectedDriveId, src);\n if (!resolvedSrc) {\n console.error(`Node ${src.id} not found`);\n return;\n }\n const resolvedTarget = resolveNode(selectedDriveId, target);\n\n await copyNode(selectedDriveId, resolvedSrc, resolvedTarget);\n }\n\n async function onMoveNode(src: Node, target: Node | undefined) {\n if (!selectedDriveId) return;\n\n const resolvedSrc = resolveNode(selectedDriveId, src);\n if (!resolvedSrc) {\n console.error(`Node ${src.id} not found`);\n return;\n }\n const resolvedTarget = resolveNode(selectedDriveId, target);\n\n // if node is already on target then ignore move\n if (\n (!resolvedTarget?.id && !src.parentFolder) ||\n resolvedTarget?.id === src.parentFolder\n ) {\n return;\n }\n await moveNode(selectedDriveId, resolvedSrc, resolvedTarget);\n }\n\n async function onDuplicateNode(src: Node) {\n if (!selectedDriveId) return;\n\n const resolvedSrc = resolveNode(selectedDriveId, src);\n if (!resolvedSrc) {\n console.error(`Node ${src.id} not found`);\n return;\n }\n\n const target = resolveNode(\n selectedDriveId,\n selectedFolder ?? selectedParentFolder,\n );\n await copyNode(selectedDriveId, resolvedSrc, target);\n }\n async function onAddAndSelectNewFolder(name: string) {\n if (!name) return;\n if (!selectedDriveId) return;\n\n const resolvedTarget = resolveNode(\n selectedDriveId,\n selectedFolder ?? selectedParentFolder,\n );\n if (!resolvedTarget) return;\n\n const newFolder = await onAddFolder(name, resolvedTarget);\n\n if (newFolder) {\n setSelectedNode(newFolder);\n }\n }\n\n async function onRenameDriveNodes(\n newName: string,\n nodeId: string,\n ): Promise<void> {\n if (!drives) return;\n\n // Find all drives that contain this node\n const drivesWithNode = drives.filter((drive) =>\n drive.state.global.nodes.some((n) => n.id === nodeId),\n );\n\n // Update node name in all parent drives\n await Promise.all(\n drivesWithNode.map((drive) =>\n renameDriveNode(drive.header.id, nodeId, newName),\n ),\n );\n }\n\n return {\n onAddFile,\n onAddFolder,\n onRenameNode,\n onCopyNode,\n onMoveNode,\n onDuplicateNode,\n onAddAndSelectNewFolder,\n onRenameDriveNodes,\n };\n}\n","import type { Node } from \"@powerhousedao/shared/document-drive\";\nimport { useNodesInSelectedDrive } from \"./items-in-selected-drive.js\";\n\n/** Returns a node in the selected drive by id. */\nexport function useNodeById(id: string | null | undefined): Node | undefined {\n const nodes = useNodesInSelectedDrive();\n return nodes?.find((n) => n.id === id);\n}\n","import type { Node } from \"@powerhousedao/shared/document-drive\";\nimport { useNodesInSelectedDrive } from \"./items-in-selected-drive.js\";\nimport { useSelectedNode } from \"./selected-node.js\";\n\n/** Returns the path to a node in the selected drive */\nexport function useNodePathById(id: string | null | undefined) {\n const nodes = useNodesInSelectedDrive();\n if (!nodes) return [];\n\n const path: Node[] = [];\n let current = nodes.find((n) => n.id === id);\n\n while (current) {\n path.push(current);\n if (!current.parentFolder) break;\n current = nodes.find((n) => n.id === current?.parentFolder);\n }\n\n return path.reverse();\n}\n\n/** Returns the path to the currently selected node in the selected drive. */\nexport function useSelectedNodePath() {\n const selectedNode = useSelectedNode();\n return useNodePathById(selectedNode?.id);\n}\n","import type { FolderNode } from \"@powerhousedao/shared/document-drive\";\nimport { useFolderById } from \"./folder-by-id.js\";\nimport { useNodeById } from \"./node-by-id.js\";\nimport { useSelectedNode } from \"./selected-node.js\";\n\nexport function useNodeParentFolderById(\n id: string | null | undefined,\n): FolderNode | undefined {\n const node = useNodeById(id);\n const parentFolder = useFolderById(node?.parentFolder);\n return parentFolder;\n}\n\nexport function useParentFolderForSelectedNode() {\n const node = useSelectedNode();\n return useNodeParentFolderById(node?.id);\n}\n","import type { DocumentDispatch } from \"@powerhousedao/reactor-browser\";\nimport { isFileNode } from \"@powerhousedao/shared/document-drive\";\nimport type { Action, PHDocument } from \"@powerhousedao/shared/document-model\";\nimport { NoSelectedDocumentError } from \"../errors.js\";\nimport type { DispatchFn, UseDispatchResult } from \"./dispatch.js\";\nimport { useDocumentById } from \"./document-by-id.js\";\nimport { useDocumentOfType } from \"./document-of-type.js\";\nimport { useSelectedNode } from \"./selected-node.js\";\n\n/** Returns the selected document id */\nexport function useSelectedDocumentId(): string | undefined {\n const selectedNode = useSelectedNode();\n return selectedNode && isFileNode(selectedNode) ? selectedNode.id : undefined;\n}\n\n/** Returns the selected document. */\nexport function useSelectedDocument(): readonly [\n PHDocument,\n DispatchFn<Action>,\n] {\n const selectedDocumentId = useSelectedDocumentId();\n const [document, dispatch] = useDocumentById(selectedDocumentId);\n if (!document) {\n throw new NoSelectedDocumentError();\n }\n return [document, dispatch] as const;\n}\n\n/** Returns the selected document. */\nexport function useSelectedDocumentSafe(): UseDispatchResult<\n PHDocument,\n Action\n> {\n const selectedDocumentId = useSelectedDocumentId();\n return useDocumentById(selectedDocumentId);\n}\n\n/** Returns the selected document of a specific type, throws an error if the found document has a different type */\nexport function useSelectedDocumentOfType(\n documentType: null | undefined,\n): never[];\nexport function useSelectedDocumentOfType<\n TDocument extends PHDocument,\n TAction extends Action,\n>(documentType: string): [TDocument, DocumentDispatch<TAction>];\nexport function useSelectedDocumentOfType<\n TDocument extends PHDocument,\n TAction extends Action,\n>(\n documentType: string | null | undefined,\n): never[] | [TDocument, DocumentDispatch<TAction>] {\n const documentId = useSelectedDocumentId();\n\n if (!documentType) {\n return [];\n }\n if (!documentId) {\n throw new NoSelectedDocumentError();\n }\n return useDocumentOfType<TDocument, TAction>(documentId, documentType);\n}\n","import type { SubgraphModule } from \"@powerhousedao/shared/document-model\";\nimport { useVetraPackages } from \"./vetra-packages.js\";\n\nexport function useSubgraphModules(): SubgraphModule[] | undefined {\n const vetraPackages = useVetraPackages();\n return vetraPackages.flatMap((pkg) => pkg.subgraphs || []);\n}\n","import {\n driveCollectionId,\n type GqlRequestChannel,\n} from \"@powerhousedao/reactor\";\nimport type { DocumentDriveDocument } from \"@powerhousedao/shared/document-drive\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { useSyncList } from \"./reactor.js\";\n\nexport type DriveSystemInfoState =\n | { status: \"local\" }\n | { status: \"loading\" }\n | { status: \"error\"; message: string }\n | { status: \"ready\"; version: string; gitHash: string; host: string };\n\nexport function deriveSystemUrl(channelUrl: string): string | null {\n try {\n const url = new URL(channelUrl);\n url.pathname = \"/graphql/system\";\n url.search = \"\";\n url.hash = \"\";\n return url.toString();\n } catch {\n return null;\n }\n}\n\nconst cache = new Map<string, DriveSystemInfoState>();\n\nexport function useDriveSystemInfo(\n drive: DocumentDriveDocument | undefined,\n): DriveSystemInfoState {\n const remotes = useSyncList();\n const driveId = drive?.header.id;\n\n const systemUrl = useMemo(() => {\n if (!driveId) return null;\n const remote = remotes.find(\n (r) => r.collectionId === driveCollectionId(\"main\", driveId),\n );\n const channelUrl = (remote?.channel as GqlRequestChannel | undefined)\n ?.config.url;\n if (typeof channelUrl !== \"string\") return null;\n return deriveSystemUrl(channelUrl);\n }, [remotes, driveId]);\n\n const [state, setState] = useState<DriveSystemInfoState>(() =>\n systemUrl\n ? (cache.get(systemUrl) ?? { status: \"loading\" })\n : { status: \"local\" },\n );\n\n useEffect(() => {\n if (!systemUrl) {\n setState({ status: \"local\" });\n return;\n }\n\n const cached = cache.get(systemUrl);\n if (cached && cached.status !== \"loading\") {\n setState(cached);\n return;\n }\n\n setState({ status: \"loading\" });\n cache.set(systemUrl, { status: \"loading\" });\n\n const controller = new AbortController();\n fetch(systemUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ query: \"{ system { version gitHash } }\" }),\n signal: controller.signal,\n })\n .then(async (res) => {\n const json = (await res.json()) as {\n data?: { system?: { version: string; gitHash: string } };\n errors?: Array<{ message: string }>;\n };\n if (json.errors?.length) {\n throw new Error(json.errors.map((e) => e.message).join(\"; \"));\n }\n const sys = json.data?.system;\n if (!sys) throw new Error(\"Missing system in response\");\n const next: DriveSystemInfoState = {\n status: \"ready\",\n version: sys.version,\n gitHash: sys.gitHash,\n host: new URL(systemUrl).host,\n };\n cache.set(systemUrl, next);\n setState(next);\n })\n .catch((err: unknown) => {\n if (controller.signal.aborted) return;\n const message = err instanceof Error ? err.message : String(err);\n const next: DriveSystemInfoState = { status: \"error\", message };\n cache.set(systemUrl, next);\n setState(next);\n });\n\n return () => controller.abort();\n }, [systemUrl]);\n\n return state;\n}\n","import type { IReactorClient } from \"@powerhousedao/reactor\";\nimport { SyncStatus } from \"@powerhousedao/reactor\";\nimport type {\n DocumentDriveDocument,\n SharingType,\n} from \"@powerhousedao/shared/document-drive\";\n\n// legacy sync status types\nexport type UISyncStatus =\n | \"INITIAL_SYNC\"\n | \"SUCCESS\"\n | \"CONFLICT\"\n | \"MISSING\"\n | \"ERROR\"\n | \"SYNCING\";\n\nconst syncStatusToUI: Record<SyncStatus, UISyncStatus> = {\n [SyncStatus.Synced]: \"SUCCESS\",\n [SyncStatus.Outgoing]: \"SYNCING\",\n [SyncStatus.Incoming]: \"SYNCING\",\n [SyncStatus.OutgoingAndIncoming]: \"SYNCING\",\n [SyncStatus.Error]: \"ERROR\",\n};\n\nexport async function getDrives(\n reactor: IReactorClient,\n): Promise<DocumentDriveDocument[]> {\n const results = await reactor.find({\n type: \"powerhouse/document-drive\",\n });\n return results.results as DocumentDriveDocument[];\n}\n\nexport function getSyncStatus(\n documentId: string,\n sharingType: SharingType,\n): Promise<UISyncStatus | undefined> {\n return Promise.resolve(getSyncStatusSync(documentId, sharingType));\n}\n\nexport function getSyncStatusSync(\n documentId: string,\n sharingType: SharingType,\n): UISyncStatus | undefined {\n if (sharingType === \"LOCAL\") return;\n\n const syncManager =\n window.ph?.reactorClientModule?.reactorModule?.syncModule?.syncManager;\n if (!syncManager) return;\n\n const status = syncManager.getSyncStatus(documentId);\n if (status === undefined) return;\n\n return syncStatusToUI[status];\n}\n","import type {\n DocumentModelDocument,\n PHDocument,\n ValidationError,\n} from \"@powerhousedao/shared/document-model\";\nimport {\n validateInitialState,\n validateModules,\n validateStateSchemaName,\n} from \"@powerhousedao/shared/document-model\";\n\nexport const validateDocument = (document: PHDocument) => {\n const errors: ValidationError[] = [];\n\n if (document.header.documentType !== \"powerhouse/document-model\") {\n return errors;\n }\n\n const doc = document as DocumentModelDocument;\n const specs = doc.state.global.specifications[0];\n\n // validate initial state errors\n const initialStateErrors = Object.keys(specs.state).reduce<ValidationError[]>(\n (acc, scopeKey) => {\n const scope = scopeKey as keyof typeof specs.state;\n\n return [\n ...acc,\n ...validateInitialState(\n specs.state[scope].initialValue,\n scope !== \"global\",\n ).map((err) => ({\n ...err,\n message: `${err.message}. Scope: ${scope}`,\n details: { ...err.details, scope },\n })),\n ];\n },\n [],\n );\n\n // validate schema state errors\n const schemaStateErrors = Object.keys(specs.state).reduce<ValidationError[]>(\n (acc, scopeKey) => {\n const scope = scopeKey as keyof typeof specs.state;\n const isGlobalScope = scope === \"global\";\n\n return [\n ...acc,\n ...validateStateSchemaName(\n specs.state[scope].schema,\n doc.state.global?.name || doc.header.name || \"\",\n !isGlobalScope ? scope : \"\",\n !isGlobalScope,\n ).map((err) => ({\n ...err,\n message: `${err.message}. Scope: ${scope}`,\n details: { ...err.details, scope },\n })),\n ];\n },\n [],\n );\n\n // modules validation\n const modulesErrors = validateModules(specs.modules);\n\n return [...initialStateErrors, ...schemaStateErrors, ...modulesErrors];\n};\n","import type { PHDocument } from \"@powerhousedao/shared/document-model\";\nimport { exportFile } from \"../actions/document.js\";\nimport { showPHModal } from \"../hooks/modals.js\";\nimport { validateDocument } from \"./validate-document.js\";\n\nexport const exportDocument = (document?: PHDocument) => {\n if (!document) return;\n const validationErrors = validateDocument(document);\n\n if (validationErrors.length) {\n showPHModal({\n type: \"exportDocumentWithErrors\",\n documentId: document.header.id,\n });\n } else {\n return exportFile(document);\n }\n};\n","import type { Operation } from \"@powerhousedao/shared/document-model\";\n\nexport const getRevisionFromDate = (\n startDate?: Date,\n endDate?: Date,\n operations: Operation[] = [],\n) => {\n if (!startDate || !endDate) return 0;\n\n const operation = operations.find((operation) => {\n const operationDate = new Date(operation.timestampUtcMs);\n return operationDate >= startDate && operationDate <= endDate;\n });\n\n return operation ? operation.index : 0;\n};\n","import * as lzString from \"lz-string\";\nimport { GetDocumentWithOperationsDocument } from \"../graphql/gen/schema.js\";\n\nexport async function getDriveIdBySlug(driveUrl: string, slug: string) {\n if (!driveUrl) {\n return;\n }\n\n const urlParts = driveUrl.split(\"/\");\n urlParts.pop(); // remove id\n urlParts.pop(); // remove /d\n urlParts.push(\"drives\"); // add /drives\n const drivesUrl = urlParts.join(\"/\");\n const result = await fetch(drivesUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n query: `\n query getDriveIdBySlug($slug: String!) {\n driveIdBySlug(slug: $slug)\n }\n `,\n variables: {\n slug,\n },\n }),\n });\n\n const data = (await result.json()) as {\n data: { driveIdBySlug: string };\n };\n\n return data.data.driveIdBySlug;\n}\n\nexport function getSlugFromDriveUrl(driveUrl: string) {\n const urlParts = driveUrl.split(\"/\");\n return urlParts.pop();\n}\n\nexport function getSwitchboardGatewayUrlFromDriveUrl(driveUrl: string) {\n const urlParts = driveUrl.split(\"/\");\n urlParts.pop(); // remove id\n urlParts.pop(); // remove /d\n urlParts.push(\"graphql\"); // add /graphql\n return urlParts.join(\"/\");\n}\n\nexport function getDocumentGraphqlQuery() {\n const loc = GetDocumentWithOperationsDocument.loc;\n if (!loc) {\n throw new Error(\n \"GetDocumentWithOperationsDocument is misconfigured, loc is missing.\",\n );\n }\n return loc.source.body;\n}\n\nexport function buildDocumentSubgraphQuery(\n identifier: string,\n authToken?: string,\n) {\n const query = getDocumentGraphqlQuery();\n const variables = { identifier };\n const headers = authToken\n ? {\n Authorization: `Bearer ${authToken}`,\n }\n : undefined;\n\n const payload: Record<string, string> = {\n document: query.trim(),\n variables: JSON.stringify(variables, null, 2),\n };\n if (headers) {\n payload.headers = JSON.stringify(headers);\n }\n return lzString.compressToEncodedURIComponent(JSON.stringify(payload));\n}\n\nexport function buildDocumentSubgraphUrl(\n driveUrl: string,\n identifier: string,\n authToken?: string,\n) {\n const encodedQuery = buildDocumentSubgraphQuery(identifier, authToken);\n return `${driveUrl}?explorerURLState=${encodedQuery}`;\n}\n","import {\n driveCollectionId,\n type GqlRequestChannel,\n} from \"@powerhousedao/reactor\";\nimport type { PHDocument } from \"@powerhousedao/shared/document-model\";\nimport { useMemo } from \"react\";\nimport { buildDocumentSubgraphUrl } from \"../utils/index.js\";\nimport { useRenown, useSyncList, useUser } from \"./connect.js\";\nimport { useSelectedDrive } from \"./selected-drive.js\";\n\n/**\n * Hook that returns a function to generate a document's switchboard URL.\n * Only returns a function for documents in remote drives.\n * Returns null for local drives or when the document/drive cannot be determined.\n *\n * The returned function generates a fresh bearer token and builds the switchboard URL\n * with authentication when called.\n *\n * @param document - The document to create a switchboard URL generator for\n * @returns An async function that returns the switchboard URL, or null if not applicable\n */\nexport function useGetSwitchboardLink(\n document: PHDocument | undefined,\n): (() => Promise<string>) | null {\n const [drive] = useSelectedDrive();\n const remotes = useSyncList();\n\n const isRemoteDrive = useMemo(() => {\n return remotes.some(\n (remote) =>\n remote.collectionId === driveCollectionId(\"main\", drive.header.id),\n );\n }, [remotes, drive]);\n const remoteUrl = useMemo(() => {\n try {\n const remote = remotes.find(\n (remote) =>\n remote.collectionId === driveCollectionId(\"main\", drive.header.id),\n );\n\n const channelUrl = (remote?.channel as GqlRequestChannel | undefined)\n ?.config.url;\n if (typeof channelUrl === \"string\") {\n return channelUrl;\n }\n\n return null;\n } catch (error) {\n console.error(\"Error determining remote URL:\", error);\n return null;\n }\n }, [remotes, drive]);\n const renown = useRenown();\n const user = useUser();\n\n return useMemo(() => {\n if (!isRemoteDrive || !document?.header.id || !remoteUrl) {\n return null;\n }\n\n return async () => {\n // Get bearer token if user is authenticated\n const token = user?.address\n ? await renown?.getBearerToken({\n expiresIn: 600,\n aud: remoteUrl,\n })\n : undefined;\n\n // Build and return the switchboard URL with the document subgraph query\n return buildDocumentSubgraphUrl(remoteUrl, document.header.id, token);\n };\n }, [isRemoteDrive, remoteUrl, document, user, renown]);\n}\n","import { addFileWithProgress } from \"../actions/document.js\";\nimport type {\n ConflictResolution,\n FileUploadProgressCallback,\n UseOnDropFile,\n} from \"../types/upload.js\";\nimport { useDocumentTypes } from \"./document-types.js\";\nimport { useSelectedDriveId } from \"./selected-drive.js\";\nimport { useSelectedFolder } from \"./selected-folder.js\";\n\nexport const useOnDropFile: UseOnDropFile = (\n documentTypesOverride?: string[],\n) => {\n const selectedDriveId = useSelectedDriveId();\n const selectedFolder = useSelectedFolder();\n const documentTypes = useDocumentTypes();\n\n const onDropFile = async (\n file: File,\n onProgress?: FileUploadProgressCallback,\n resolveConflict?: ConflictResolution,\n ) => {\n if (!selectedDriveId) {\n console.warn(\"No selected drive - upload skipped\");\n return;\n }\n\n const fileName = file.name.replace(/\\..+/gim, \"\");\n const targetNodeId = selectedFolder?.id;\n\n // Return the FileNode directly from addFileWithProgress\n return await addFileWithProgress(\n file,\n selectedDriveId,\n fileName,\n targetNodeId,\n onProgress,\n documentTypesOverride ?? documentTypes,\n resolveConflict,\n );\n };\n\n return onDropFile;\n};\n","import { useAllowList } from \"./connect.js\";\nimport { useUser } from \"./renown.js\";\nexport function useUserPermissions() {\n const user = useUser();\n const allowList = useAllowList();\n if (!allowList) {\n return {\n isAllowedToCreateDocuments: true,\n isAllowedToEditDocuments: true,\n };\n }\n\n return {\n isAllowedToCreateDocuments: allowList.includes(user?.address ?? \"\"),\n isAllowedToEditDocuments: allowList.includes(user?.address ?? \"\"),\n };\n}\n","import type { PGlite } from \"@electric-sql/pglite\";\nimport { REACTOR_SCHEMA } from \"@powerhousedao/reactor\";\n\nasync function dropTablesInSchema(pg: PGlite, schema: string): Promise<void> {\n await pg.exec(`\nDO $$\nDECLARE\n _schemaname text := '${schema}';\n _tablename text;\nBEGIN\n FOR _tablename IN SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname = _schemaname LOOP\n RAISE INFO 'Dropping table %.%', _schemaname, _tablename;\n EXECUTE format('DROP TABLE %I.%I CASCADE;', _schemaname, _tablename);\n END LOOP;\n IF NOT FOUND THEN\n RAISE WARNING 'Schema % does not exist', _schemaname;\n END IF;\nEND $$;\n`);\n}\n\nexport async function truncateAllTables(\n pg: PGlite,\n schema: string = REACTOR_SCHEMA,\n): Promise<void> {\n await dropTablesInSchema(pg, schema);\n}\n\nexport async function dropAllReactorStorage(pg: PGlite): Promise<void> {\n await dropTablesInSchema(pg, REACTOR_SCHEMA);\n\n // legacy\n await dropTablesInSchema(pg, \"public\");\n}\n","import type { IReactorClient } from \"@powerhousedao/reactor\";\nimport { type DocumentDriveDocument } from \"@powerhousedao/shared/document-drive\";\nimport { setDrives } from \"./hooks/drives.js\";\nimport { getDrives } from \"./utils/drives.js\";\n\nexport type ReactorDefaultDrivesConfig = {\n defaultDrivesUrl?: string[];\n};\n\nexport type RefreshReactorDataConfig = {\n debounceDelayMs?: number;\n immediateThresholdMs?: number;\n};\n\nconst DEFAULT_DEBOUNCE_DELAY_MS = 200;\nconst DEFAULT_IMMEDIATE_THRESHOLD_MS = 1000;\n\nasync function _refreshReactorData(reactor: IReactorClient) {\n const drives = await getDrives(reactor);\n\n setDrives(drives);\n}\n\nasync function _refreshReactorDataClient(reactor: IReactorClient | undefined) {\n if (!reactor) return;\n\n const result = await reactor.find({ type: \"powerhouse/document-drive\" });\n setDrives(result.results as DocumentDriveDocument[]);\n}\n\nfunction createDebouncedRefreshReactorData(\n debounceDelayMs = DEFAULT_DEBOUNCE_DELAY_MS,\n immediateThresholdMs = DEFAULT_IMMEDIATE_THRESHOLD_MS,\n) {\n let timeout: ReturnType<typeof setTimeout> | null = null;\n let lastRefreshTime = 0;\n\n return (reactor: IReactorClient, immediate = false) => {\n const now = Date.now();\n const timeSinceLastRefresh = now - lastRefreshTime;\n\n // Clear any pending timeout\n if (timeout !== null) {\n clearTimeout(timeout);\n }\n\n // If caller requests immediate execution or enough time has passed, execute immediately\n if (immediate || timeSinceLastRefresh >= immediateThresholdMs) {\n lastRefreshTime = now;\n return _refreshReactorData(reactor);\n }\n\n // Otherwise, debounce the call\n return new Promise<void>((resolve) => {\n timeout = setTimeout(() => {\n lastRefreshTime = Date.now();\n void _refreshReactorData(reactor).then(resolve);\n }, debounceDelayMs);\n });\n };\n}\n\nfunction createDebouncedRefreshReactorDataClient(\n debounceDelayMs = DEFAULT_DEBOUNCE_DELAY_MS,\n immediateThresholdMs = DEFAULT_IMMEDIATE_THRESHOLD_MS,\n) {\n let timeout: ReturnType<typeof setTimeout> | null = null;\n let lastRefreshTime = 0;\n\n return (reactor: IReactorClient | undefined, immediate = false) => {\n const now = Date.now();\n const timeSinceLastRefresh = now - lastRefreshTime;\n\n // Clear any pending timeout\n if (timeout !== null) {\n clearTimeout(timeout);\n }\n\n // If caller requests immediate execution or enough time has passed, execute immediately\n if (immediate || timeSinceLastRefresh >= immediateThresholdMs) {\n lastRefreshTime = now;\n return _refreshReactorDataClient(reactor);\n }\n\n // Otherwise, debounce the call\n return new Promise<void>((resolve) => {\n timeout = setTimeout(() => {\n lastRefreshTime = Date.now();\n void _refreshReactorDataClient(reactor).then(resolve);\n }, debounceDelayMs);\n });\n };\n}\n\nexport const refreshReactorData = createDebouncedRefreshReactorData();\nexport const refreshReactorDataClient =\n createDebouncedRefreshReactorDataClient();\n","import type { PackageInfo } from \"@powerhousedao/shared/registry\";\n\n// Strip a trailing \"/\" so we don't emit `http://host//packages` when a user\n// writes `packageRegistryUrl: \"http://host/\"`. Verdaccio's own web backend\n// 404s on the doubled slash, which cascades into an empty registry list and\n// masks the real install flow.\nfunction trimTrailingSlash(url: string): string {\n return url.endsWith(\"/\") ? url.slice(0, -1) : url;\n}\n\nexport async function getPackages(registryUrl: string) {\n const res = await fetch(`${trimTrailingSlash(registryUrl)}/packages`);\n if (!res.ok) throw new Error(`Registry error: HTTP ${res.status}`);\n const data = (await res.json()) as PackageInfo[];\n return data;\n}\n\nexport async function getPackagesByDocumentType(\n registryUrl: string,\n documentType: string,\n): Promise<string[]> {\n const encodedType = encodeURIComponent(documentType);\n const res = await fetch(\n `${trimTrailingSlash(registryUrl)}/packages/by-document-type?type=${encodedType}`,\n );\n if (!res.ok) throw new Error(`Registry error: HTTP ${res.status}`);\n return (await res.json()) as string[];\n}\n","import type { PackageInfo } from \"@powerhousedao/shared/registry\";\nimport { getPackages, getPackagesByDocumentType } from \"./fetchers.js\";\nimport type { PublishEvent } from \"./types.js\";\n\nfunction cdnUrlToApiUrl(cdnUrl: string): string {\n return cdnUrl.replace(/\\/-\\/cdn\\/?$/, \"\");\n}\nexport class RegistryClient {\n readonly apiUrl: string;\n\n constructor(cdnUrl: string) {\n this.apiUrl = cdnUrlToApiUrl(cdnUrl);\n }\n\n async getPackages(): Promise<PackageInfo[]> {\n const data = await getPackages(this.apiUrl);\n return data;\n }\n\n async getPackagesByDocumentType(documentType: string): Promise<string[]> {\n return await getPackagesByDocumentType(this.apiUrl, documentType);\n }\n\n async searchPackages(query: string): Promise<PackageInfo[]> {\n const packages = await this.getPackages();\n if (!query) return packages;\n const lowerQuery = query.toLowerCase();\n return packages.filter(\n (pkg) =>\n pkg.name.toLowerCase().includes(lowerQuery) ||\n pkg.manifest?.description?.toLowerCase().includes(lowerQuery),\n );\n }\n\n onPublish(callback: (event: PublishEvent) => void): () => void {\n const eventSource = new EventSource(`${this.apiUrl}/-/events`);\n\n eventSource.addEventListener(\"publish\", (e: MessageEvent<string>) => {\n const data = JSON.parse(e.data) as PublishEvent;\n callback(data);\n });\n\n return () => {\n eventSource.close();\n };\n }\n}\n","import type { Action } from \"@powerhousedao/shared/document-model\";\nimport type { TrackedAction } from \"./types.js\";\n\n/**\n * Tracks pending actions with their operation context (prevOpHash, prevOpIndex).\n * Actions are accumulated until flushed (on push).\n */\nexport class ActionTracker {\n private pending: TrackedAction[] = [];\n\n /** Track a new action with its operation context. */\n track(action: Action, prevOpHash: string, prevOpIndex: number): void {\n this.pending.push({ action, prevOpHash, prevOpIndex });\n }\n\n /** Flush all pending actions and return them. Clears the internal queue. */\n flush(): TrackedAction[] {\n const actions = this.pending;\n this.pending = [];\n return actions;\n }\n\n /** Number of pending actions. */\n get count(): number {\n return this.pending.length;\n }\n\n /** Prepend previously flushed actions back to the queue (for retry on failure). */\n restore(actions: TrackedAction[]): void {\n this.pending = [...actions, ...this.pending];\n }\n\n /** Clear all pending actions without returning them. */\n clear(): void {\n this.pending = [];\n }\n}\n","import type {\n GetDocumentResult,\n GetDocumentWithOperationsResult,\n GetOperationsResult,\n IRemoteClient,\n PropagationMode,\n RemoteControllerGraphQLClient,\n RemoteDocumentData,\n RemoteOperation,\n RemoteOperationResultPage,\n} from \"./types.js\";\n\n/**\n * Thin facade over the GraphQL SDK for remote document operations.\n */\nconst DEFAULT_PAGE_SIZE = 100;\n\nexport class RemoteClient implements IRemoteClient {\n private readonly pageSize: number;\n\n constructor(\n private readonly client: RemoteControllerGraphQLClient,\n pageSize?: number,\n ) {\n this.pageSize = pageSize ?? DEFAULT_PAGE_SIZE;\n }\n\n /** Fetch a document by identifier. Returns null if not found. */\n async getDocument(\n identifier: string,\n branch?: string,\n ): Promise<GetDocumentResult | null> {\n const result = await this.client.GetDocument({\n identifier,\n view: branch ? { branch } : undefined,\n });\n return result.document ?? null;\n }\n\n /**\n * Fetch a document and its operations.\n *\n * When scopes are provided and BatchGetDocumentWithOperations is available,\n * fetches the document and per-scope operations in a single HTTP request.\n * Otherwise falls back to GetDocumentWithOperations for the first page,\n * then paginates remaining operations per scope.\n */\n async getDocumentWithOperations(\n identifier: string,\n branch?: string,\n sinceRevision?: Record<string, number>,\n scopes?: string[],\n ): Promise<GetDocumentWithOperationsResult | null> {\n // Fast path: batch document + per-scope operations in one request\n if (\n this.client.BatchGetDocumentWithOperations &&\n scopes &&\n scopes.length > 0\n ) {\n return this.batchGetDocumentWithOperations(\n identifier,\n branch,\n sinceRevision,\n scopes,\n );\n }\n\n // Standard path: GetDocumentWithOperations + paginate if needed\n const result = await this.client.GetDocumentWithOperations({\n identifier,\n view: branch ? { branch } : undefined,\n operationsPaging: {\n limit: this.pageSize,\n cursor: null,\n },\n });\n\n if (!result.document) return null;\n\n const doc = result.document.document;\n const opsPage = doc.operations;\n const operationsByScope: Record<string, RemoteOperation[]> = {};\n\n if (opsPage) {\n for (const op of opsPage.items) {\n (operationsByScope[op.action.scope] ??= []).push(op);\n }\n }\n\n // Check if we have all expected operations by comparing against revisionsList\n const expectedTotal = doc.revisionsList.reduce(\n (sum, r) => sum + r.revision,\n 0,\n );\n const fetchedTotal = opsPage?.items.length ?? 0;\n\n if (fetchedTotal >= expectedTotal) {\n return {\n document: doc,\n childIds: result.document.childIds,\n operations: { operationsByScope },\n };\n }\n\n // Missing operations — fetch all per scope\n const allScopes = doc.revisionsList.map((r) => r.scope);\n const allOps = await this.getAllOperations(\n doc.id,\n branch,\n sinceRevision,\n allScopes,\n );\n\n return {\n document: doc,\n childIds: result.document.childIds,\n operations: allOps,\n };\n }\n\n /**\n * Fetch document + per-scope operations in a single HTTP request\n * via BatchGetDocumentWithOperations, then paginate any remaining pages.\n */\n private async batchGetDocumentWithOperations(\n identifier: string,\n branch: string | undefined,\n sinceRevision: Record<string, number> | undefined,\n scopes: string[],\n ): Promise<GetDocumentWithOperationsResult | null> {\n const view = branch ? { branch } : undefined;\n const filters = scopes.map((scope) => ({\n documentId: identifier,\n branch: branch ?? null,\n sinceRevision: sinceRevision?.[scope] ?? 0,\n scopes: [scope],\n }));\n const pagings = scopes.map(() => ({\n limit: this.pageSize,\n cursor: null as string | null,\n }));\n\n const result = await this.client.BatchGetDocumentWithOperations!(\n identifier,\n view,\n filters,\n pagings,\n );\n\n if (!result.document) return null;\n\n const operationsByScope: Record<string, RemoteOperation[]> = {};\n let pending: {\n scope: string;\n filter: (typeof filters)[0];\n cursor: string;\n }[] = [];\n\n for (let i = 0; i < scopes.length; i++) {\n const page = result.operations[i];\n for (const op of page.items) {\n (operationsByScope[op.action.scope] ??= []).push(op);\n }\n if (page.hasNextPage && page.cursor) {\n pending.push({\n scope: scopes[i],\n filter: filters[i],\n cursor: page.cursor,\n });\n }\n }\n\n // Continue pagination for scopes with more pages\n while (pending.length > 0) {\n const pages = await this.fetchOperationPages(\n pending.map((p) => p.filter),\n pending.map((p) => ({ limit: this.pageSize, cursor: p.cursor })),\n );\n\n const nextPending: typeof pending = [];\n for (let i = 0; i < pending.length; i++) {\n const page = pages[i];\n for (const op of page.items) {\n (operationsByScope[op.action.scope] ??= []).push(op);\n }\n if (page.hasNextPage && page.cursor) {\n nextPending.push({ ...pending[i], cursor: page.cursor });\n }\n }\n pending = nextPending;\n }\n\n return {\n document: result.document.document,\n childIds: result.document.childIds,\n operations: { operationsByScope },\n };\n }\n\n /**\n * Fetch all operations for a document, paginating through all pages.\n * Each scope is queried individually because the API only returns\n * pagination cursors for single-scope queries.\n */\n async getAllOperations(\n documentId: string,\n branch?: string,\n sinceRevision?: Record<string, number>,\n scopes?: string[],\n ): Promise<GetOperationsResult> {\n // When scopes are specified, query each scope in parallel.\n // Uses a single composed request per pagination round when available.\n if (scopes && scopes.length > 0) {\n const operationsByScope: Record<string, RemoteOperation[]> = {};\n\n // Tracks scopes still being paginated, each with its own filter and cursor\n let pending = scopes.map((scope) => ({\n scope,\n filter: {\n documentId,\n branch: branch ?? null,\n sinceRevision: sinceRevision?.[scope] ?? 0,\n scopes: [scope],\n },\n cursor: null as string | null,\n }));\n\n while (pending.length > 0) {\n const pages = await this.fetchOperationPages(\n pending.map((p) => p.filter),\n pending.map((p) => ({ limit: this.pageSize, cursor: p.cursor })),\n );\n\n const nextPending: typeof pending = [];\n\n for (let i = 0; i < pending.length; i++) {\n const page = pages[i];\n for (const op of page.items) {\n (operationsByScope[op.action.scope] ??= []).push(op);\n }\n if (page.hasNextPage && page.cursor) {\n nextPending.push({ ...pending[i], cursor: page.cursor });\n }\n }\n\n pending = nextPending;\n }\n\n return { operationsByScope };\n }\n\n // No scopes specified — single query for all scopes (no per-scope sinceRevision)\n return this.fetchOperationsForScope(documentId, branch);\n }\n\n /**\n * Fetch one page of operations per filter.\n * Uses the composed query (single HTTP request) when available,\n * otherwise falls back to parallel individual requests.\n */\n private async fetchOperationPages(\n filters: Parameters<\n RemoteControllerGraphQLClient[\"GetDocumentOperations\"]\n >[0][\"filter\"][],\n pagings: Parameters<\n RemoteControllerGraphQLClient[\"GetDocumentOperations\"]\n >[0][\"paging\"][],\n ): Promise<RemoteOperationResultPage[]> {\n if (this.client.BatchGetDocumentOperations) {\n return this.client.BatchGetDocumentOperations(filters, pagings);\n }\n\n return Promise.all(\n filters.map((filter, i) =>\n this.client\n .GetDocumentOperations({ filter, paging: pagings[i] })\n .then((r) => r.documentOperations),\n ),\n );\n }\n\n /** Fetch all pages of operations for a single scope (or all scopes if none specified). */\n private async fetchOperationsForScope(\n documentId: string,\n branch?: string,\n sinceRevision?: number,\n scope?: string,\n ): Promise<GetOperationsResult> {\n const operationsByScope: Record<string, RemoteOperation[]> = {};\n let cursor: string | null | undefined;\n let hasNextPage = true;\n\n while (hasNextPage) {\n const result = await this.client.GetDocumentOperations({\n filter: {\n documentId,\n branch: branch ?? null,\n sinceRevision: sinceRevision ?? 0,\n scopes: scope ? [scope] : null,\n },\n paging: {\n limit: this.pageSize,\n cursor: cursor ?? null,\n },\n });\n\n const page = result.documentOperations;\n\n for (const op of page.items) {\n const s = op.action.scope;\n (operationsByScope[s] ??= []).push(op);\n }\n\n hasNextPage = page.hasNextPage;\n cursor = page.cursor;\n }\n\n return { operationsByScope };\n }\n\n /** Push actions to an existing document via MutateDocument. */\n async pushActions(\n documentIdentifier: string,\n actions: ReadonlyArray<NonNullable<unknown>>,\n branch?: string,\n ): Promise<RemoteDocumentData> {\n const result = await this.client.MutateDocument({\n documentIdentifier,\n actions,\n view: branch ? { branch } : undefined,\n });\n return result.mutateDocument;\n }\n\n /** Create a new document on the remote. */\n async createDocument(\n document: NonNullable<unknown>,\n parentIdentifier?: string,\n ): Promise<RemoteDocumentData> {\n const result = await this.client.CreateDocument({\n document,\n parentIdentifier: parentIdentifier ?? null,\n });\n return result.createDocument;\n }\n\n /** Create an empty document of a given type on the remote. */\n async createEmptyDocument(\n documentType: string,\n parentIdentifier?: string,\n ): Promise<RemoteDocumentData> {\n const result = await this.client.CreateEmptyDocument({\n documentType,\n parentIdentifier: parentIdentifier ?? null,\n });\n return result.createEmptyDocument;\n }\n\n /** Delete a document on the remote. Returns true if successful. */\n async deleteDocument(\n identifier: string,\n propagate?: PropagationMode,\n ): Promise<boolean> {\n const result = await this.client.DeleteDocument({\n identifier,\n propagate,\n });\n return result.deleteDocument;\n }\n}\n","import type {\n DocumentOperations,\n Operation,\n PHBaseState,\n PHDocument,\n} 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 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 attachments: remote.action.attachments?.map((a) => ({\n data: a.data,\n mimeType: a.mimeType,\n hash: a.hash,\n extension: a.extension ?? undefined,\n fileName: a.fileName ?? undefined,\n })),\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 * Deserialize a signature string back to a 5-element tuple.\n * The server serializes tuples via `tuple.join(\", \")`.\n */\nexport function deserializeSignature(\n s: string,\n): [string, string, string, string, string] {\n const parts = s.split(\", \");\n return [\n parts[0] ?? \"\",\n parts[1] ?? \"\",\n parts[2] ?? \"\",\n parts[3] ?? \"\",\n parts[4] ?? \"\",\n ];\n}\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 Action,\n DocumentOperations,\n Operation,\n PHBaseState,\n PHDocument,\n PHDocumentHeader,\n} from \"@powerhousedao/shared/document-model\";\nimport type { PHDocumentController } from \"document-model\";\nimport { ActionTracker } from \"./action-tracker.js\";\nimport { RemoteClient } from \"./remote-client.js\";\nimport type {\n ConflictStrategy,\n DocumentChangeListener,\n IRemoteClient,\n IRemoteController,\n PropagationMode,\n PushResult,\n RemoteControllerOptions,\n RemoteDocumentChangeEvent,\n RemoteDocumentData,\n RemoteOperation,\n SyncStatus,\n TrackedAction,\n} from \"./types.js\";\nimport {\n ConflictError,\n buildPulledDocument,\n convertRemoteOperations,\n extractRevisionMap,\n hasRevisionConflict,\n screamingSnakeToCamel,\n} from \"./utils.js\";\n\n/** Extract TState from a PHDocumentController subclass. */\ntype InferState<C> = C extends PHDocumentController<infer S> ? S : never;\n\n/**\n * Extract action methods from a controller type.\n * These are the dynamically-added methods (not on the base PHDocumentController prototype).\n */\ntype ActionMethodsOf<C, TRemote> = {\n [K in Exclude<keyof C, keyof PHDocumentController<any>>]: C[K] extends (\n input: infer I,\n ) => unknown\n ? (input: I) => TRemote & ActionMethodsOf<C, TRemote>\n : C[K];\n};\n\n/** The full return type: RemoteDocumentController + action methods. */\nexport type RemoteDocumentControllerWith<C extends PHDocumentController<any>> =\n RemoteDocumentController<C> & ActionMethodsOf<C, RemoteDocumentController<C>>;\n\n/**\n * A controller that wraps a PHDocumentController with remote push/pull capabilities.\n * Composes a local controller and adds GraphQL-based sync with a reactor server.\n */\nexport class RemoteDocumentController<\n TController extends PHDocumentController<any>,\n> implements IRemoteController<InferState<TController>> {\n private inner: TController;\n private readonly remoteClient: IRemoteClient;\n private readonly tracker = new ActionTracker();\n private readonly options: RemoteControllerOptions;\n private documentId: string;\n private remoteRevision: Record<string, number> = {};\n private hasPulled = false;\n private pushScheduled = false;\n private pushQueue: Promise<void> = Promise.resolve();\n private listeners: DocumentChangeListener[] = [];\n\n private constructor(inner: TController, options: RemoteControllerOptions) {\n this.inner = inner;\n this.options = options;\n this.documentId = options.documentId ?? \"\";\n this.remoteClient = new RemoteClient(\n options.client,\n options.operationsPageSize,\n );\n\n this.setupActionInterceptors();\n }\n\n // --- State access (delegated to inner controller) ---\n\n get header(): PHDocumentHeader {\n return this.inner.header;\n }\n\n get state(): InferState<TController> {\n return this.inner.state as InferState<TController>;\n }\n\n get operations(): DocumentOperations {\n return this.inner.operations;\n }\n\n get document(): PHDocument<InferState<TController>> {\n return this.inner.document as PHDocument<InferState<TController>>;\n }\n\n get status(): SyncStatus {\n return {\n pendingActionCount: this.tracker.count,\n connected: this.documentId !== \"\",\n documentId: this.documentId,\n remoteRevision: { ...this.remoteRevision },\n };\n }\n\n /** Register a listener for document changes. Returns an unsubscribe function. */\n onChange(listener: DocumentChangeListener): () => void {\n this.listeners.push(listener);\n return () => {\n this.listeners = this.listeners.filter((l) => l !== listener);\n };\n }\n\n private notifyListeners(source: RemoteDocumentChangeEvent[\"source\"]): void {\n if (this.listeners.length === 0) return;\n const event: RemoteDocumentChangeEvent = {\n source,\n document: this.document,\n };\n for (const listener of this.listeners) {\n listener(event);\n }\n }\n\n // --- Remote operations ---\n\n /** Push all pending actions to remote, then pull latest state. */\n async push(): Promise<PushResult> {\n let tracked = this.tracker.flush();\n\n if (tracked.length === 0 && this.documentId !== \"\") {\n // Nothing to push, just pull (reuses the fetched document)\n const remoteDocument = await this.pull();\n return {\n remoteDocument,\n actionCount: 0,\n operations: [],\n };\n }\n\n try {\n await this.ensureRemoteDocument();\n\n // Conflict detection: check if remote has changed since last pull\n if (this.options.onConflict && tracked.length > 0) {\n tracked = await this.handleConflicts(tracked, this.options.onConflict);\n }\n } catch (error) {\n // Pre-push failure: restore actions so they can be retried\n this.tracker.restore(tracked);\n throw error;\n }\n\n let pushedActions: Action[] = [];\n\n try {\n if (tracked.length > 0) {\n const actions = await this.prepareActionsForPush(tracked);\n pushedActions = actions;\n\n await this.remoteClient.pushActions(\n this.documentId,\n actions,\n this.options.branch,\n );\n }\n } catch (error) {\n // Push failed: restore actions so they can be retried\n this.tracker.restore(tracked);\n throw error;\n }\n\n // Pull remote state to reconcile (remote is source of truth).\n // If this fails, actions were already pushed — do NOT restore them.\n const remoteDocument = await this.pull();\n\n return {\n remoteDocument,\n actionCount: tracked.length,\n operations: pushedActions,\n };\n }\n\n /** Delete the document on the remote. */\n async delete(propagate?: PropagationMode): Promise<boolean> {\n if (this.documentId === \"\") {\n throw new Error(\"Cannot delete: no document ID set\");\n }\n const result = await this.remoteClient.deleteDocument(\n this.documentId,\n propagate,\n );\n return result;\n }\n\n /** Pull latest state from remote, replacing local document. Returns the remote document data. */\n async pull(): Promise<RemoteDocumentData> {\n if (this.documentId === \"\") {\n throw new Error(\"Cannot pull: no document ID set\");\n }\n\n const { remoteDoc, operations } = await this.fetchDocumentAndOperations();\n\n // Get module from inner controller\n const initialDoc = this.inner.module.utils.createDocument();\n const pulledDocument = buildPulledDocument(\n remoteDoc,\n operations,\n initialDoc,\n this.options.branch ?? \"main\",\n );\n\n // Recreate inner controller with pulled document\n const ControllerClass = this.inner.constructor as new (\n doc?: PHDocument<PHBaseState>,\n ) => TController;\n this.inner = new ControllerClass(pulledDocument);\n\n // Re-setup interceptors on the new inner instance\n this.setupActionInterceptors();\n\n // Clear tracker (remote is source of truth)\n this.tracker.clear();\n\n // Update remote revision\n this.remoteRevision = extractRevisionMap(remoteDoc.revisionsList);\n\n this.notifyListeners(\"pull\");\n\n return remoteDoc;\n }\n\n // --- Static factories ---\n\n /**\n * Pull an existing document from remote and create a controller for it.\n */\n static async pull<C extends PHDocumentController<any>>(\n ControllerClass: new (doc?: PHDocument<any>) => C,\n options: RemoteControllerOptions,\n ): Promise<RemoteDocumentControllerWith<C>> {\n // Create a temporary instance to access the module\n const temp = new ControllerClass();\n const remote = new RemoteDocumentController(temp, options);\n\n if (options.documentId) {\n await remote.pull();\n }\n\n return remote as RemoteDocumentControllerWith<C>;\n }\n\n /**\n * Wrap an existing controller instance with remote capabilities.\n * Pending local actions on the inner controller are NOT tracked\n * (only new actions through the remote controller are tracked).\n */\n static from<C extends PHDocumentController<any>>(\n controller: C,\n options: RemoteControllerOptions,\n ): RemoteDocumentControllerWith<C> {\n return new RemoteDocumentController(\n controller,\n options,\n ) as RemoteDocumentControllerWith<C>;\n }\n\n // --- Private methods ---\n\n /** Create the document on the remote if it doesn't exist yet. */\n private async ensureRemoteDocument(): Promise<void> {\n if (this.documentId !== \"\") return;\n const remoteDoc = await this.remoteClient.createEmptyDocument(\n this.inner.header.documentType,\n this.options.parentIdentifier,\n );\n this.documentId = remoteDoc.id;\n }\n\n /** Set up interceptors for all action methods on the inner controller. */\n private setupActionInterceptors(): void {\n // Get the module's action keys from the inner controller\n const module = (this.inner as Record<string, unknown>)[\"module\"] as {\n actions: Record<string, unknown>;\n };\n\n for (const actionType in module.actions) {\n // Skip if it's a property on our own class\n if (actionType in RemoteDocumentController.prototype) {\n continue;\n }\n\n Object.defineProperty(this, actionType, {\n value: (input: unknown) => {\n // Snapshot operation counts per scope BEFORE applying\n const opCountsBefore: Record<string, number> = {};\n for (const scope in this.inner.operations) {\n opCountsBefore[scope] = this.inner.operations[scope].length;\n }\n\n // Apply locally via inner controller\n (\n this.inner as unknown as Record<string, (input: unknown) => unknown>\n )[actionType](input);\n\n // Find which scope got the new operation\n const newOp = this.findNewOperation(opCountsBefore);\n\n // Get prevOp in the SAME scope as the new operation\n const prevOp = newOp\n ? this.getLastOperationInScope(newOp.action.scope, newOp)\n : undefined;\n const prevOpHash = prevOp?.hash ?? \"\";\n const prevOpIndex = prevOp?.index ?? -1;\n\n if (!newOp) {\n // Action produced no operation (NOOP) — nothing to track\n return this;\n }\n\n // Track the action for push\n this.tracker.track(newOp.action, prevOpHash, prevOpIndex);\n this.notifyListeners(\"action\");\n\n if (this.options.mode === \"streaming\") {\n this.schedulePush();\n }\n\n return this;\n },\n enumerable: true,\n configurable: true,\n });\n }\n }\n\n /**\n * Find the new operation added after applying an action,\n * by comparing current operation counts against a previous snapshot.\n */\n private findNewOperation(\n opCountsBefore: Record<string, number>,\n ): Operation | undefined {\n const ops = this.inner.operations;\n for (const scope in ops) {\n const scopeOps = ops[scope];\n const prevCount = opCountsBefore[scope] ?? 0;\n if (scopeOps.length > prevCount) {\n return scopeOps[scopeOps.length - 1];\n }\n }\n return undefined;\n }\n\n /**\n * Get the last operation in a specific scope, optionally excluding\n * a given operation (e.g. the one just added).\n */\n private getLastOperationInScope(\n scope: string,\n excludeOp?: Operation,\n ): Operation | undefined {\n const scopeOps = this.inner.operations[scope];\n if (scopeOps.length === 0) return undefined;\n for (let i = scopeOps.length - 1; i >= 0; i--) {\n if (scopeOps[i] !== excludeOp) return scopeOps[i];\n }\n return undefined;\n }\n\n /**\n * Detect and handle conflicts between local pending actions and remote state.\n * Returns the (possibly rebased) tracked actions to push.\n */\n private async handleConflicts(\n localTracked: TrackedAction[],\n strategy: ConflictStrategy,\n ): Promise<TrackedAction[]> {\n // Fetch current remote document to get latest revisions\n const remoteResult = await this.remoteClient.getDocument(\n this.documentId,\n this.options.branch,\n );\n if (!remoteResult) {\n throw new Error(`Document \"${this.documentId}\" not found on remote`);\n }\n\n const currentRevision = extractRevisionMap(\n remoteResult.document.revisionsList,\n );\n\n // Only check scopes that local actions touch\n const localScopes = new Set(localTracked.map((t) => t.action.scope));\n\n if (\n !hasRevisionConflict(currentRevision, this.remoteRevision, localScopes)\n ) {\n return localTracked;\n }\n\n // Fetch new remote operations for conflicting scopes in parallel,\n // using the correct sinceRevision for each scope.\n const conflictingScopes = [...localScopes].filter(\n (scope) =>\n (currentRevision[scope] ?? 0) > (this.remoteRevision[scope] ?? 0),\n );\n const { operationsByScope } = await this.remoteClient.getAllOperations(\n this.documentId,\n this.options.branch,\n this.remoteRevision,\n conflictingScopes,\n );\n const remoteOperations: Record<string, RemoteOperation[]> = {};\n for (const [scope, ops] of Object.entries(operationsByScope)) {\n remoteOperations[scope] = ops;\n }\n\n const conflictInfo = {\n remoteOperations,\n localActions: localTracked,\n knownRevision: { ...this.remoteRevision },\n currentRevision: { ...currentRevision },\n };\n\n if (strategy === \"reject\") {\n throw new ConflictError(conflictInfo);\n }\n\n if (strategy === \"rebase\") {\n return this.pullAndReplay(localTracked.map((t) => t.action));\n }\n\n // Custom merge handler (only possibility left after narrowing)\n const mergedActions = await strategy(conflictInfo);\n return this.pullAndReplay(mergedActions);\n }\n\n /**\n * Pull latest remote state and replay actions through interceptors.\n * Returns newly tracked actions with correct prevOpHash values.\n */\n private async pullAndReplay(actions: Action[]): Promise<TrackedAction[]> {\n await this.pull();\n\n for (const action of actions) {\n // Action types are SCREAMING_SNAKE_CASE but interceptors use camelCase\n const methodName = screamingSnakeToCamel(action.type);\n const method = (\n this as unknown as Record<string, (input: unknown) => unknown>\n )[methodName];\n if (typeof method === \"function\") {\n method.call(this, action.input);\n }\n }\n\n return this.tracker.flush();\n }\n\n /** Prepare actions for push, optionally signing them. */\n private async prepareActionsForPush(\n tracked: { action: Action; prevOpHash: string; prevOpIndex: number }[],\n ) {\n const actions: Action[] = [];\n\n for (const { action, prevOpHash, prevOpIndex } of tracked) {\n let prepared: Action = {\n ...action,\n context: {\n ...action.context,\n prevOpHash,\n prevOpIndex,\n },\n };\n\n if (this.options.signer) {\n prepared = await this.signAction(prepared);\n }\n\n actions.push(prepared);\n }\n\n return actions;\n }\n\n /** Sign an action using the configured signer, preserving existing signatures. */\n private async signAction(action: Action): Promise<Action> {\n const signer = this.options.signer!;\n const signature = await signer.signAction(action);\n const existingSignatures = action.context?.signer?.signatures ?? [];\n return {\n ...action,\n context: {\n ...action.context,\n signer: {\n user: signer.user!,\n app: signer.app!,\n signatures: [...existingSignatures, signature],\n },\n },\n };\n }\n\n /**\n * Fetch document and operations from the remote.\n *\n * On the first pull, uses the combined document+operations query.\n * On subsequent pulls, fetches only new operations per scope using\n * sinceRevision, then merges with existing local operations.\n * Falls back to a full fetch if the merge produces a count mismatch.\n */\n private async fetchDocumentAndOperations(): Promise<{\n remoteDoc: RemoteDocumentData;\n operations: DocumentOperations;\n }> {\n // Incremental fetch: use sinceRevision per scope\n if (this.hasPulled) {\n return this.incrementalFetch();\n }\n\n // Initial fetch: combined document + operations query\n const result = await this.remoteClient.getDocumentWithOperations(\n this.documentId,\n this.options.branch,\n );\n\n if (!result) {\n throw new Error(`Document \"${this.documentId}\" not found on remote`);\n }\n\n this.hasPulled = true;\n return {\n remoteDoc: result.document,\n operations: convertRemoteOperations(result.operations.operationsByScope),\n };\n }\n\n /**\n * Incremental fetch: fetches the document and only new operations per scope\n * using sinceRevision in a single request when possible.\n * Falls back to a full fetch on count mismatch.\n */\n private async incrementalFetch(): Promise<{\n remoteDoc: RemoteDocumentData;\n operations: DocumentOperations;\n }> {\n const scopes = Object.keys(this.remoteRevision);\n\n const result = await this.remoteClient.getDocumentWithOperations(\n this.documentId,\n this.options.branch,\n this.remoteRevision,\n scopes.length > 0 ? scopes : undefined,\n );\n\n if (!result) {\n throw new Error(`Document \"${this.documentId}\" not found on remote`);\n }\n\n const remoteDoc = result.document;\n const expectedRevision = extractRevisionMap(remoteDoc.revisionsList);\n\n const newOps = convertRemoteOperations(result.operations.operationsByScope);\n const merged = this.mergeOperations(this.inner.operations, newOps);\n\n // Validate: merged operation counts must match remote revisions\n if (this.hasExpectedOperationCounts(merged, expectedRevision)) {\n return { remoteDoc, operations: merged };\n }\n\n // Mismatch — do a full fetch\n return this.fullFetch(remoteDoc);\n }\n\n /**\n * Full fetch fallback: fetches all operations from the beginning.\n * Used when an incremental fetch produces a count mismatch.\n */\n private async fullFetch(remoteDoc: RemoteDocumentData): Promise<{\n remoteDoc: RemoteDocumentData;\n operations: DocumentOperations;\n }> {\n const { operationsByScope } = await this.remoteClient.getAllOperations(\n this.documentId,\n this.options.branch,\n );\n\n return {\n remoteDoc,\n operations: convertRemoteOperations(operationsByScope),\n };\n }\n\n /**\n * Validate that the merged operations match the expected revision per scope.\n * Each scope's operation count should equal its revision number.\n */\n private hasExpectedOperationCounts(\n operations: DocumentOperations,\n expectedRevision: Record<string, number>,\n ): boolean {\n for (const [scope, revision] of Object.entries(expectedRevision)) {\n const opCount = scope in operations ? operations[scope].length : 0;\n if (opCount !== revision) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * Merge existing local operations with newly fetched operations.\n * Appends new operations to existing ones per scope.\n */\n private mergeOperations(\n existingOps: DocumentOperations,\n newOps: DocumentOperations,\n ): DocumentOperations {\n const merged: DocumentOperations = {};\n\n // Copy existing operations\n for (const [scope, ops] of Object.entries(existingOps)) {\n if (ops.length > 0) {\n merged[scope] = [...ops];\n }\n }\n\n // Append new operations per scope\n for (const [scope, ops] of Object.entries(newOps)) {\n if (ops.length > 0) {\n (merged[scope] ??= []).push(...ops);\n }\n }\n\n return merged;\n }\n\n /** Schedule a push via microtask (for streaming mode coalescing). */\n private schedulePush(): void {\n if (this.pushScheduled) return;\n this.pushScheduled = true;\n queueMicrotask(() => {\n this.pushScheduled = false;\n // Chain onto the push queue to prevent concurrent pushes\n this.pushQueue = this.pushQueue.then(async () => {\n try {\n await this.push();\n } catch (error: unknown) {\n // Actions remain in tracker for retry\n this.options.onPushError?.(error);\n }\n });\n });\n }\n}\n","export abstract class BaseStorage<V> implements Iterable<[string, V]> {\n abstract get(key: string): V | undefined;\n abstract set(key: string, value: V): void;\n abstract delete(key: string): boolean;\n abstract has(key: string): boolean;\n abstract clear(): void;\n abstract entries(): IterableIterator<[string, V]>;\n abstract keys(): IterableIterator<string>;\n abstract values(): IterableIterator<V>;\n\n [Symbol.iterator](): IterableIterator<[string, V]> {\n return this.entries();\n }\n\n forEach(\n callback: (value: V, key: string, storage: BaseStorage<V>) => void,\n ): void {\n for (const [key, value] of this) {\n callback(value, key, this);\n }\n }\n}\n","import { BaseStorage } from \"./base-storage.js\";\n\nexport class BrowserLocalStorage<V> extends BaseStorage<V> {\n #namespace: string;\n #storage = window.localStorage;\n constructor(namespace: string) {\n super();\n this.#namespace = namespace;\n }\n\n #readMap(): Map<string, V> {\n const raw = this.#storage.getItem(this.#namespace);\n\n if (!raw) {\n return new Map();\n }\n\n return new Map(JSON.parse(raw) as [string, V][]);\n }\n\n #writeMap(map: Map<string, V>): void {\n this.#storage.setItem(\n this.#namespace,\n JSON.stringify(Array.from(map.entries())),\n );\n }\n\n get(key: string): V | undefined {\n return this.#readMap().get(key);\n }\n\n set(key: string, value: V): void {\n const map = this.#readMap();\n map.set(key, value);\n this.#writeMap(map);\n }\n\n delete(key: string): boolean {\n const map = this.#readMap();\n const deleted = map.delete(key);\n if (deleted) {\n this.#writeMap(map);\n }\n return deleted;\n }\n\n has(key: string): boolean {\n return this.#readMap().has(key);\n }\n\n clear(): void {\n this.#storage.removeItem(this.#namespace);\n }\n\n entries(): IterableIterator<[string, V]> {\n return this.#readMap().entries();\n }\n\n keys(): IterableIterator<string> {\n return this.#readMap().keys();\n }\n\n values(): IterableIterator<V> {\n return this.#readMap().values();\n }\n\n [Symbol.iterator](): IterableIterator<[string, V]> {\n return this.#readMap().entries();\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AAAA,IAAa,+BAAb,cAAkD,MAAM;CACtD,YAAY,cAAsB;AAChC,QAAM,iBAAiB,aAAa,mBAAmB;AACvD,OAAK,OAAO;;CAGd,OAAO,QAAQ,OAAuD;AACpE,SACE,MAAM,QAAQ,MAAM,IAAI,MAAM,SAAS;;;AAW7C,IAAa,6BAAb,cAAgD,MAAM;CACpD;CACA,OAAgB;CAEhB,YAAY,cAAsB;AAChC,QAAM,kCAAkC,aAAa,YAAY;AACjE,OAAK,eAAe;;CAGtB,OAAO,QAAQ,OAAqD;AAClE,SAAO,MAAM,QAAQ,MAAM,IAAI,MAAM,SAAS;;;AAIlD,IAAa,4BAAb,cAA+C,MAAM;CACnD,YAAY,YAAoB,cAAsB,YAAoB;AACxE,QACE,YAAY,WAAW,kBAAkB,aAAa,iBAAiB,aACxE;;;AAIL,IAAa,0BAAb,cAA6C,MAAM;CACjD,cAAc;AACZ,QACE,yFACD;;;;;AC7CL,SAAgB,wBACd,cACA,oBACS;AACT,KAAI,CAAC,oBAAoB,OACvB,QAAO;AAGT,QAAO,mBAAmB,MAAM,YAAY;AAE1C,MAAI,QAAQ,SAAS,KAAK,EAAE;GAC1B,MAAM,SAAS,QAAQ,MAAM,GAAG,GAAG;AACnC,UAAO,aAAa,WAAW,SAAS,IAAI;;AAI9C,MAAI,QAAQ,SAAS,IAAI,IAAI,CAAC,QAAQ,SAAS,KAAK,EAAE;GACpD,MAAM,SAAS,QAAQ,MAAM,GAAG,GAAG;AACnC,UAAO,aAAa,WAAW,OAAO;;AAIxC,SAAO,YAAY;GACnB;;;;ACvBJ,SAAgB,qBAAqB;CACnC,MAAM,OAAO,OAAO,IAAI,QAAQ;CAChC,MAAM,YAAY,OAAO,IAAI;AAC7B,KAAI,CAAC,UACH,QAAO;EACL,4BAA4B;EAC5B,0BAA0B;EAC3B;AAEH,QAAO;EACL,4BAA4B,UAAU,SAAS,MAAM,WAAW,GAAG;EACnE,0BAA0B,UAAU,SAAS,MAAM,WAAW,GAAG;EAClE;;;;ACmCH,MAAM,kBAAkB,IAAI,IAAI,CAAC,OAAO,CAAC;AACzC,MAAM,oBAAoB,IAAI,IAAI,CAAC,QAAQ,WAAW,CAAC;AAEvD,eAAe,qBACb,UACA,SACA,cAKC;CACD,MAAM,gBAAgB,OAAO,IAAI;AACjC,KAAI,CAAC,cACH,QAAO,EAAE,aAAa,OAAO;CAI/B,IAAI;AACJ,KAAI;AACF,UAAQ,MAAM,cAAc,IAA2B,QAAQ;SACzD;AACN,SAAO,EAAE,aAAa,OAAO;;CAI/B,MAAM,WAAW,MAAM,MAAM,OAAO,MAAM,MACvC,SAAyB,KAAK,OAAO,SAAS,OAAO,GACvD;AAED,KAAI,YAAY,SAAS,kBAAkB,gBAAgB,MACzD,QAAO;EACL,aAAa;EACb,eAAe;EACf,QAAQ,SAAS;EAClB;CAIH,MAAM,oBAAoB,MAAM,MAAM,OAAO,MAAM,MAChD,SACC,WAAW,KAAK,IAChB,KAAK,SAAS,SAAS,OAAO,QAC9B,KAAK,iBAAiB,SAAS,OAAO,gBACtC,KAAK,kBAAkB,gBAAgB,MAC1C;AAED,KAAI,kBACF,QAAO;EACL,aAAa;EACb,eAAe;EACf,QAAQ,kBAAkB;EAC3B;AAGH,QAAO,EAAE,aAAa,OAAO;;AAG/B,SAAS,oBACP,UAC8B;AAG9B,SAFqB,SAAS,OAAO,cAErC;EACE,KAAK,4BACH,QAAO;EACT,KAAK,iBACH,QAAO;EACT,KAAK,6BACH,QAAO;EACT,KAAK,sBACH,QAAO;EACT,KAAK,qBACH,QAAO;EACT,KAAK,wBAAwB;GAI3B,MAAM,gBAFe,SAAS,MAC3B,QACgC;AAEnC,OAAI,kBAAkB,YAAa,QAAO;AAC1C,OAAI,kBAAkB,aAAc,QAAO;AAC3C,OAAI,kBAAkB,UAAW,QAAO;AACxC;;EAEF,QACE;;;AAIN,eAAsB,aAAa,UAAsB,UAAkB;AAEzE,EADY,MAAM,UAAU,SAAS,EAElC,cAAc,EAAE,MAAM,QAAQ,CAAC,CAC/B,MAAM,SAAS;EACd,MAAM,OAAO,OAAO,SAAS,cAAc,IAAI;AAC/C,OAAK,MAAM,UAAU;AACrB,OAAK,OAAO,IAAI,gBAAgB,KAAK;AACrC,OAAK,WAAW;AAEhB,SAAO,SAAS,KAAK,YAAY,KAAK;AACtC,OAAK,OAAO;AAEZ,SAAO,SAAS,KAAK,YAAY,KAAK;GACtC,CACD,MAAM,OAAO,MAAM;;AAGxB,eAAe,qBAAqB,UAAuC;CACzE,MAAM,eAAe,SAAS,OAAO;CAErC,IAAI;AAEJ,KAAI,iBAAiB,0BAGnB,gBAFqB,SAAS,MAC3B,QACyB;MACvB;EACL,MAAM,gBAAgB,OAAO,IAAI;AACjC,MAAI,eAAe;GACjB,MAAM,EAAE,SAAS,yBACf,MAAM,cAAc,yBAAyB;AAI/C,kBAHe,qBAAqB,MACjC,MAA2B,EAAE,cAAc,OAAO,OAAO,aAC3D,EACsB,MAAM;;;AAIjC,SAAQ,gBAAgB,IAAI,QAAQ,cAAc,GAAG;;;;;;;AAQvD,eAAsB,wBACpB,eACA,UACA,WAAW,KACkB;CAC7B,MAAM,SAAS,OAAO,KAAK,SAAS,MAAM,CAAC,QACxC,MAAM,CAAC,gBAAgB,IAAI,EAAE,CAC/B;CACD,MAAM,aAAiC,EAAE;AACzC,MAAK,MAAM,SAAS,OAClB,YAAW,SAAS,EAAE;CAGxB,IAAI,SAAS;AAEb,IAAG;EACD,MAAM,OAAO,MAAM,cAAc,cAC/B,SAAS,OAAO,IAChB,EAAE,QAAQ,EACV,KAAA,GACA;GAAE;GAAQ,OAAO;GAAU,CAC5B;AAED,OAAK,MAAM,MAAM,KAAK,SAAS;GAC7B,MAAM,QAAQ,GAAG,OAAO,SAAS;AACjC,OAAI,WAAW,OACb,YAAW,OAAO,KAAK,GAAG;;AAI9B,WAAS,KAAK,cAAc;UACrB;AAET,QAAO;;AAGT,SAAgB,oBACd,kBACa;CACb,MAAM,YAAY,iBAAiB,MAChC,OAAO,GAAG,OAAO,SAAS,mBAC5B;AACD,KAAI,CAAC,UACH,OAAM,IAAI,MACR,4DACD;CAEH,MAAM,QAAQ,UAAU,OAAO;CAI/B,MAAM,eAAe,MAAM,gBAAgB,MAAM;AACjD,KAAI,CAAC,aACH,OAAM,IAAI,MACR,uEACD;AAEH,QAAO;;AAGT,SAAgB,uBACd,YACoB;AACpB,QAAO,OAAO,YACZ,OAAO,QAAQ,WAAW,CAAC,QACxB,CAAC,WAAW,CAAC,kBAAkB,IAAI,MAAM,CAC3C,CACF;;AAGH,eAAsB,WAAW,UAAsB,eAAwB;CAC7E,MAAM,gBAAgB,OAAO,IAAI;AACjC,KAAI,CAAC,cACH,OAAM,IAAI,MAAM,gCAAgC;CAIlD,MAAM,aAAa,MAAM,wBAAwB,eAAe,SAAS;CACzE,MAAM,eAAe,oBAAoB,WAAW,eAAe,EAAE,CAAC;CACtE,MAAM,kBAAkB;EAAE,GAAG;EAAU;EAAY;EAAc;CAGjE,MAAM,YAAY,MAAM,qBAAqB,gBAAgB;CAE7D,MAAM,WAAW,iBAAiB,gBAAgB,OAAO,QAAQ;CACjE,MAAM,OAAO,YAAY,GAAG,SAAS,GAAG,UAAU,QAAQ,GAAG,SAAS;AAGtE,KAAI,CAAC,OAAO,mBACV,QAAO,MAAM,aAAa,iBAAiB,KAAK;AAElD,KAAI;EACF,MAAM,aAAa,MAAM,OAAO,mBAAmB,EACjD,eAAe,MAChB,CAAC;AAEF,QAAM,qBAAqB,iBAAiB,WAAW;AACvD,SAAO;UACA,GAAG;AAEV,MAAI,EAAE,aAAa,gBAAgB,EAAE,SAAS,cAC5C,OAAM;;;AAKZ,eAAsB,SAAS,MAAqB;CAClD,MAAM,eAAe,MAAM,kBACzB,OACC,UAAsB,OACvB,EAAE,aAAa,MAAM,CACtB;CAED,MAAM,gBAAgB,OAAO,IAAI;AACjC,KAAI,CAAC,cACH,OAAM,IAAI,MAAM,gCAAgC;CAElD,MAAM,EAAE,SAAS,yBACf,MAAM,cAAc,yBAAyB;CAC/C,MAAM,sBAAsB,qBAAqB,MAC9C,WACC,OAAO,cAAc,OAAO,OAAO,aAAa,OAAO,aAC1D;AACD,KAAI,CAAC,oBACH,OAAM,IAAI,2BAA2B,aAAa,OAAO,aAAa;AAExE,QAAO,oBAAoB,MAAM,cAAc,KAAK;;AAGtD,eAAsB,YACpB,SACA,MACA,cACA,cACA,UACA,IACA,iBACA;CACA,MAAM,EAAE,+BAA+B,oBAAoB;AAC3D,KAAI,CAAC,2BACH,OAAM,IAAI,MAAM,0CAA0C;CAG5D,MAAM,gBAAgB,OAAO,IAAI;AACjC,KAAI,CAAC,cACH,OAAM,IAAI,MAAM,gCAAgC;CAIlD,MAAM,sBACJ,MAAM,cAAc,uBAAuB,aAAa;CAG1D,MAAM,cAAc,YAAY,oBAAoB,MAAM,gBAAgB;AAC1E,aAAY,OAAO,OAAO;AAC1B,KAAI,gBACF,aAAY,OAAO,OAAO;EACxB,GAAG,YAAY,OAAO;EACtB;EACD;CAIH,IAAI;AACJ,KAAI;AACF,WAAS,MAAM,cAAc,OAAO,QAClC,SACA,aACA,aACD;UACM,GAAG;AACV,SAAO,MAAM,yBAAyB,EAAE;AACxC,QAAM,IAAI,MAAM,qCAAqC;;AAIvD,QAAO;EACL,IAAI,OAAO,OAAO;EAClB,MAAM,OAAO,OAAO;EACpB;EACA,cAAc,gBAAgB;EAC9B,MAAM;EACP;;AAGH,eAAsB,QACpB,MACA,SACA,MACA,cACA;AACA,QAAO,QACL,kBAAkB,QAAQ,UAAU,KAAK,YAAY,aAAa,GACnE;CAED,MAAM,EAAE,+BAA+B,oBAAoB;AAC3D,KAAI,CAAC,2BACH,OAAM,IAAI,MAAM,sCAAsC;CAGxD,MAAM,WAAW,MAAM,SAAS,KAAK;CAErC,IAAI,cAAc;CAElB,MAAM,gBAAgB,OAAO,IAAI;AACjC,KAAI,CAAC,cACH,OAAM,IAAI,MAAM,gCAAgC;AAGlD,KAAI;AACF,QAAM,cAAc,IAAI,SAAS,OAAO,GAAG;AAC3C,gBAAc;SACR;CAIR,MAAM,aAAa,cAAc,YAAY,GAAG,SAAS,OAAO;CAChE,MAAM,SAAS,sBACb,YACA,SAAS,OAAO,aACjB;AACD,QAAO,uBAAuB,SAAS,OAAO;AAC9C,QAAO,OAAO,SAAS,OAAO;AAC9B,QAAO,OAAO,QAAQ,SAAS,OAAO;CAGtC,MAAM,kBAAkB;EACtB,GAAG;EACH;EACA,OAAO,SAAS;EAChB,YAAY,OAAO,KAAK,SAAS,WAAW,CAAC,QAAQ,KAAK,QAAQ;AAChE,OAAI,OAAO,EAAE;AACb,UAAO;KACN,EAAE,CAAuB;EAC7B;AAED,OAAM,YACJ,SACA,QAAQ,SAAS,OAAO,MACxB,SAAS,OAAO,cAChB,cACA,iBACA,YACA,SAAS,OAAO,MAAM,gBACvB;AAID,OAAM,iBACJ,YACA,uBAAuB,SAAS,WAAW,EAC3C,gBACD;;AAGH,eAAsB,oBACpB,MACA,SACA,MACA,cACA,YACA,eACA,iBACA;AACA,QAAO,QACL,8BAA8B,QAAQ,UAAU,KAAK,YAAY,aAAa,GAC/E;CACD,MAAM,UAAU,OAAO,IAAI;AAC3B,KAAI,CAAC,QACH;CAGF,MAAM,EAAE,+BAA+B,oBAAoB;AAC3D,KAAI,CAAC,2BACH,OAAM,IAAI,MAAM,sCAAsC;AAIxD,KAAI;AACF,eAAa;GAAE,OAAO;GAAW,UAAU;GAAG,CAAC;EAC/C,IAAI;AACJ,MAAI;AACF,cAAW,MAAM,SAAS,KAAK;WACxB,WAAW;GAGlB,MAAM,mBAAmB,OAAO,IAAI;AACpC,OAAI,oBAAoB,2BAA2B,QAAQ,UAAU,EAAE;AAEhE,wBACH,kBACA,UAAU,cACV,MACA,SACA,MACA,cACA,YACA,eACA,gBACD;AACD;;AAEF,SAAM;;EAIR,MAAM,iBAAiB,MAAM,qBAC3B,UACA,SACA,aACD;AAED,MAAI,eAAe,eAAe,CAAC,iBAAiB;AAElD,gBAAa;IACX,OAAO;IACP,UAAU;IACV,eAAe,eAAe;IAC/B,CAAC;AACF;;AAIF,MACE,eAAe,eACf,oBAAoB,aACpB,eAAe,OAEf,OAAM,WAAW,SAAS,eAAe,OAAO;EAMlD,MAAM,eAAe,oBAAoB,SAAS;AAClD,MAAI,aACF,cAAa;GAAE,OAAO;GAAW,UAAU;GAAI;GAAc,CAAC;MAE9D,cAAa;GAAE,OAAO;GAAW,UAAU;GAAI,CAAC;AAGlD,MAAI,CAAC,wBAAwB,SAAS,OAAO,cAAc,cAAc,EAAE;AACzE,gBAAa;IACX,OAAO;IACP,UAAU;IACV,OAAO,iBAAiB,SAAS,OAAO,aAAa;IACtD,CAAC;AACF,SAAM,IAAI,6BAA6B,SAAS,OAAO,aAAa;;AAItE,QAAM,QAAQ,uBAAuB,SAAS,OAAO,aAAa;AAGlE,eAAa;GAAE,OAAO;GAAgB,UAAU;GAAI,CAAC;EAErD,IAAI,cAAc;AAClB,MAAI;AACF,SAAM,QAAQ,IAAI,SAAS,OAAO,GAAG;AACrC,iBAAc;UACR;EAIR,MAAM,aAAa,cAAc,YAAY,GAAG,SAAS,OAAO;EAChE,MAAM,SAAS,sBACb,YACA,SAAS,OAAO,aACjB;AACD,SAAO,uBAAuB,SAAS,OAAO;AAC9C,SAAO,OAAO,SAAS,OAAO;AAC9B,SAAO,OAAO,QAAQ,SAAS,OAAO;EAGtC,MAAM,kBAAkB;GACtB,GAAG;GACH;GACA,OAAO,SAAS;GAChB,YAAY,OAAO,KAAK,SAAS,WAAW,CAAC,QAAQ,KAAK,QAAQ;AAChE,QAAI,OAAO,EAAE;AACb,WAAO;MACN,EAAE,CAAuB;GAC7B;EAED,MAAM,WAAW,MAAM,YACrB,SACA,QAAQ,SAAS,OAAO,MACxB,SAAS,OAAO,cAChB,cACA,iBACA,YACA,SAAS,OAAO,MAAM,gBACvB;AAED,MAAI,CAAC,SACH,OAAM,IAAI,MAAM,iCAAiC;AAGnD,eAAa;GAAE,OAAO;GAAgB,UAAU;GAAI,CAAC;AAEzC,QAAM,QAAQ,IAAI,WAAW;AACzC,UAAQ,IAAI,kDAAkD;AAE9D,QAAM,iBACJ,YACA,uBAAuB,SAAS,WAAW,EAC3C,iBACA,EACE,aAAa,mBAAmB;AAC9B,OACE,eAAe,mBACf,eAAe,uBAAuB,KAAA,GACtC;IACA,MAAM,gBACJ,eAAe,kBAAkB,IAC7B,eAAe,qBACf,eAAe,kBACf;IACN,MAAM,kBAAkB,KAAK,KAAK,MAAM,gBAAgB,GAAG;AAC3D,iBAAa;KACX,OAAO;KACP,UAAU;KACV,iBAAiB,eAAe;KAChC,oBAAoB,eAAe;KACpC,CAAC;;KAGP,CACF;AAED,eAAa;GAAE,OAAO;GAAY,UAAU;GAAK;GAAU,CAAC;AAE5D,SAAO;UACA,OAAO;AAEd,MAAI,CAAC,6BAA6B,QAAQ,MAAM,EAAE;GAChD,MAAM,eACJ,iBAAiB,QAAQ,MAAM,UAAU;AAC3C,gBAAa;IACX,OAAO;IACP,UAAU;IACV,OAAO;IACR,CAAC;;AAEJ,QAAM;;;AAIV,eAAe,oBACb,kBACA,cACA,MACA,SACA,MACA,cACA,YACA,eACA,iBACe;AACf,KAAI,CAAC,iBAAkB;AACvB,KAAI;AACF,QAAM,iBAAiB,KAAK,aAAa;SACnC;AACN,eAAa;GACX,OAAO;GACP,UAAU;GACV,OAAO,iBAAiB,aAAa;GACtC,CAAC;AACF;;AAEF,OAAM,oBACJ,MACA,SACA,MACA,cACA,YACA,eACA,gBACD;;AAuCH,eAAsB,UACpB,SACA,MACA,cACA;CACA,MAAM,EAAE,+BAA+B,oBAAoB;AAC3D,KAAI,CAAC,2BACH,OAAM,IAAI,MAAM,wCAAwC;CAG1D,MAAM,gBAAgB,OAAO,IAAI;AACjC,KAAI,CAAC,cACH,OAAM,IAAI,MAAM,gCAAgC;AAIpC,OAAM,cAAc,IAA2B,QAAQ;CACrE,MAAM,WAAW,YAAY;CAa7B,MAAM,QAZe,MAAM,cAAc,QACvC,SACA,QACA,CACEA,YAAc;EACZ,IAAI;EACJ;EACA;EACD,CAAC,CACH,CACF,EAEyB,MAAM,OAAO,MAAM,MAC1C,SAAS,KAAK,OAAO,SACvB;AACD,KAAI,CAAC,QAAQ,CAAC,aAAa,KAAK,CAC9B,OAAM,IAAI,MAAM,mCAAmC;AAErD,QAAO;;AAGT,eAAsB,WAAW,SAAiB,QAAgB;CAChE,MAAM,EAAE,+BAA+B,oBAAoB;AAC3D,KAAI,CAAC,2BACH,OAAM,IAAI,MAAM,0CAA0C;CAG5D,MAAM,gBAAgB,OAAO,IAAI;AACjC,KAAI,CAAC,cACH,OAAM,IAAI,MAAM,gCAAgC;AAGlD,OAAM,cAAc,OAAO,WAAW,SAAS,OAAO;;AAGxD,eAAsB,WACpB,SACA,QACA,MAC2B;CAC3B,MAAM,EAAE,+BAA+B,oBAAoB;AAC3D,KAAI,CAAC,2BACH,OAAM,IAAI,MAAM,0CAA0C;CAG5D,MAAM,gBAAgB,OAAO,IAAI;AACjC,KAAI,CAAC,cACH,OAAM,IAAI,MAAM,gCAAgC;AAOlD,MAJyB,MAAM,cAAc,QAAQ,QAAQ,QAAQ,CACnE,QAAQ,EAAE,MAAM,CAAC,CAClB,CAAC,EAEmB,OAAO,SAAS,KACnC,OAAM,IAAI,MAAM,uCAAuC;CAUzD,MAAM,QANQ,MAAM,cAAc,QAChC,SACA,QACA,CAAC,WAAW;EAAE,IAAI;EAAQ;EAAM,CAAC,CAAC,CACnC,EAEkB,MAAM,OAAO,MAAM,MAAM,MAAM,EAAE,OAAO,OAAO;AAClE,KAAI,CAAC,KACH,OAAM,IAAI,MAAM,gDAAgD;AAElE,QAAO;;AAGT,eAAsB,gBACpB,SACA,QACA,MAC2B;CAC3B,MAAM,EAAE,+BAA+B,oBAAoB;AAC3D,KAAI,CAAC,2BACH,OAAM,IAAI,MAAM,0CAA0C;CAG5D,MAAM,gBAAgB,OAAO,IAAI;AACjC,KAAI,CAAC,cACH,OAAM,IAAI,MAAM,gCAAgC;AAOlD,MAJyB,MAAM,cAAc,QAAQ,QAAQ,QAAQ,CACnE,QAAQ,EAAE,MAAM,CAAC,CAClB,CAAC,EAEmB,OAAO,SAAS,KACnC,OAAM,IAAI,MAAM,uCAAuC;AAGzD,OAAM,cAAc,QAAQ,SAAS,QAAQ,CAC3C,WAAW;EAAE,IAAI;EAAQ;EAAM,CAAC,CACjC,CAAC;AAGF,SADc,MAAM,cAAc,IAA2B,QAAQ,EACxD,MAAM,OAAO,MAAM,MAAM,MAAY,EAAE,OAAO,OAAO;;AAGpE,eAAsBC,WACpB,SACA,KACA,QACA;CACA,MAAM,EAAE,+BAA+B,oBAAoB;AAC3D,KAAI,CAAC,2BACH,OAAM,IAAI,MAAM,wCAAwC;CAG1D,MAAM,gBAAgB,OAAO,IAAI;AACjC,KAAI,CAAC,cACH,OAAM,IAAI,MAAM,gCAAgC;AAElD,QAAO,MAAM,cAAc,QAAQ,SAAS,QAAQ,CAClDC,SAAa;EACX,WAAW,IAAI;EACf,oBAAoB,QAAQ;EAC7B,CAAC,CACH,CAAC;;AAGJ,eAAe,mBACb,SACA,UACA,QAAQ,YAAY,EACpB;CACA,MAAM,iBAAiB,MAAM,QAAQ,uBACnC,SAAS,OAAO,aACjB;AAED,QAAO,eACL,SAAS,cACT,SAAS,YACT,eAAe,SACf,sBAAsB,OAAO,SAAS,OAAO,aAAa,CAC3D;;AAGH,eAAsBC,WACpB,SACA,KACA,QACA;CACA,MAAM,UAAU,OAAO,IAAI;AAC3B,KAAI,CAAC,QACH;CAEF,MAAM,EAAE,+BAA+B,oBAAoB;AAE3D,KAAI,CAAC,2BACH,OAAM,IAAI,MAAM,wCAAwC;CAG1D,MAAM,QAAQ,MAAM,QAAQ,IAA2B,QAAQ;CAE/D,MAAM,iBAAiB,kBACrB;EACE,OAAO,IAAI;EACX,oBAAoB,QAAQ;EAC5B,YAAY,IAAI;EACjB,QACK,YAAY,EAClB,MAAM,MAAM,OAAO,MACpB;CAGD,MAAM,mCAAmB,IAAI,KAAqB;AAClD,MAAK,MAAM,iBAAiB,gBAAgB;EAC1C,MAAM,OAAO,MAAM,MAAM,OAAO,MAAM,MACnC,MAAM,EAAE,OAAO,cAAc,MAC/B;AACD,MAAI,MAAM;GACR,MAAM,eAAe,2BAA2B;IAC9C,OAAO,MAAM,MAAM,OAAO;IAC1B,SAAS,cAAc,cAAc,KAAK;IAC1C,SAAS,WAAW,KAAK,GAAG,SAAS;IACrC,oBAAoB,cAAc,sBAAsB;IACzD,CAAC;AACF,oBAAiB,IAAI,cAAc,UAAU,aAAa;;;CAI9D,MAAM,kBAAkB,eAAe,QAAQ,kBAAkB;EAC/D,MAAM,OAAO,MAAM,MAAM,OAAO,MAAM,MACnC,SAAS,KAAK,OAAO,cAAc,MACrC;AACD,SAAO,SAAS,KAAA,KAAa,WAAW,KAAK;GAC7C;AAEF,MAAK,MAAM,kBAAkB,gBAC3B,KAAI;EAGF,MAAM,qBAAqB,MAAM,mBAC/B,SAHe,MAAM,QAAQ,IAAI,eAAe,MAAM,EAKtD,eAAe,SAChB;EAGD,MAAM,eAAe,iBAAiB,IAAI,eAAe,SAAS;AAClE,MAAI,aACF,oBAAmB,OAAO,OAAO;AAGnC,QAAM,QAAQ,OAAO,QAAQ,SAAS,oBAAoB,QAAQ,GAAG;UAC9D,GAAG;AACV,SAAO,MACL,0BAA0B,eAAe,MAAM,IAAI,OAAO,EAAE,GAC7D;;AAOL,QAAO,MAAM,aAAa,OAHN,eAAe,KAAK,kBACtCC,SAAa,cAAc,CAC5B,CAC4C;;;;AC/5B/C,eAAsB,SAAS,OAAmB,iBAA0B;CAC1E,MAAM,EAAE,+BAA+B,oBAAoB;AAC3D,KAAI,CAAC,2BACH,OAAM,IAAI,MAAM,uCAAuC;CAGzD,MAAM,gBAAgB,OAAO,IAAI;AACjC,KAAI,CAAC,cACH,OAAM,IAAI,MAAM,gCAAgC;CAGlD,MAAM,WAAW,oBAAoB,EACnC,QAAQ;EACN,MAAM,MAAM,OAAO,QAAQ;EAC3B,MAAM,MAAM,OAAO,QAAQ;EAC3B,OAAO,EAAE;EACV,EACF,CAAC;AAEF,KAAI,gBACF,UAAS,OAAO,OAAO,EAAE,iBAAiB;AAG5C,QAAO,MAAM,cAAc,OAA8B,SAAS;;AAGpE,eAAsB,eAAe,KAAa,SAAkB;AAElE,KAAI,CADkB,OAAO,IAAI,cAE/B,OAAM,IAAI,MAAM,gCAAgC;CAGlD,MAAM,OACJ,OAAO,IAAI,qBAAqB,eAAe,YAAY;AAC7D,KAAI,CAAC,KACH,OAAM,IAAI,MAAM,uBAAuB;CAIzC,MAAM,WAAW,MAAM,MAAM,IAAI;AACjC,KAAI,CAAC,SAAS,GACZ,OAAM,IAAI,MAAM,qCAAqC,MAAM;CAE7D,MAAM,YAAa,MAAM,SAAS,MAAM;CAKxC,MAAM,kBAAkB,WAAW,UAAU;CAC7C,MAAM,eAAeC,oBAAkB,QAAQ,gBAAgB;AAK/D,KAHuB,KACpB,MAAM,CACN,MAAM,WAAW,OAAO,iBAAiB,aAAa,CAEvD,QAAO;CAGT,MAAM,aAAa,OAAO,YAAY;AAEtC,OAAM,KAAK,IAAI,YAAY,cAAc;EACvC,MAAM;EACN,YAAY,EACV,KAAK,UAAU,iBAChB;EACF,CAAC;AAEF,QAAO;;AAGT,eAAsB,YAAY,SAAiB;CACjD,MAAM,EAAE,+BAA+B,oBAAoB;AAC3D,KAAI,CAAC,2BACH,OAAM,IAAI,MAAM,uCAAuC;CAGzD,MAAM,gBAAgB,OAAO,IAAI;AACjC,KAAI,CAAC,cACH,OAAM,IAAI,MAAM,gCAAgC;AAElD,OAAM,cAAc,eAAe,QAAQ;;AAG7C,eAAsB,YACpB,SACA,MACiC;CACjC,MAAM,EAAE,+BAA+B,oBAAoB;AAC3D,KAAI,CAAC,2BACH,OAAM,IAAI,MAAM,uCAAuC;CAGzD,MAAM,gBAAgB,OAAO,IAAI;AACjC,KAAI,CAAC,cACH,OAAM,IAAI,MAAM,gCAAgC;AAElD,QAAO,MAAM,cAAc,OAAO,SAAS,KAAK;;AAGlD,eAAsB,yBACpB,SACA,kBACiC;CACjC,MAAM,EAAE,+BAA+B,oBAAoB;AAC3D,KAAI,CAAC,2BACH,OAAM,IAAI,MAAM,mDAAmD;CAGrE,MAAM,gBAAgB,OAAO,IAAI;AACjC,KAAI,CAAC,cACH,OAAM,IAAI,MAAM,gCAAgC;AAElD,QAAO,MAAM,cAAc,QAAQ,SAAS,QAAQ,CAClD,oBAAoB,EAAE,kBAAkB,CAAC,CAC1C,CAAC;;AAGJ,eAAsB,oBACpB,SACA,aACiC;CACjC,MAAM,EAAE,+BAA+B,oBAAoB;AAC3D,KAAI,CAAC,2BACH,OAAM,IAAI,MAAM,mDAAmD;CAGrE,MAAM,gBAAgB,OAAO,IAAI;AACjC,KAAI,CAAC,cACH,OAAM,IAAI,MAAM,gCAAgC;AAElD,QAAO,MAAM,cAAc,QAAQ,SAAS,QAAQ,CAClD,eAAe,EAAE,MAAM,aAAa,CAAC,CACtC,CAAC;;;;AChJJ,MAAa,0BAA0B;AACvC,MAAa,oBAAoB;;;ACKjC,MAAa,wBAGT,EACF,eACE,kCACH;AAED,MAAa,qBAAqB,OAAO,OAAO,sBAAsB;;;ACQtE,SAAgB,oBAEd,UAA+B,gBAAkC;CACjE,MAAM,aAAa;EACjB,QAAQ,0BAA0B,SAAS;EAC3C,OAAO,yBAAyB,SAAS;EACzC,cAAc,yBAAyB,SAAS;EAChD,YACE,uDAAuD,SAAS;EAClE,WAAW,EAAE;EACd;AACD,KAAI,mBAAmB,KAAA,EAAW,gBAAe,MAAM,WAAW;AAClE,QAAO;;AAGT,SAAgB,qBAEd,OAA2B,gBAAkC;AAK7D,QAJkB,KAChB,OACA,KAAK,aAAa,oBAAoB,UAAU,eAAe,CAAC,CACjE;;AAIH,SAAS,0BAA0B,eAAoC;AAgBrE,QAfyB;EACvB,QAAQ;EACR,IAAI,cAAc;EAClB,MAAM,cAAc;EACpB,cAAc,cAAc;EAC5B,iBACE,cAAc,2BAA2B,OACrC,cAAc,gBAAgB,aAAa,GAC3C,cAAc;EACpB,sBACE,cAAc,gCAAgC,OAC1C,cAAc,qBAAqB,aAAa,GAChD,cAAc;EACpB,MAAM,cAAc,QAAQ;EAC7B;;AAIH,SAAS,yBAEP,eAAoC,gBAAkC;AACtE,KAAI,mBAAmB,KAAA,EACrB,QAAO,eAAe,MAAM,MAAM,MAAM,cAAc,MAAM;AAC9D,QAAO,cAAc;;AAGvB,SAAS,uDACP,eACA;AACA,KACE,cAAc,eAAe,QAC7B,cAAc,eAAe,KAAA,EAE7B,QAAO,EACL,QAAQ,EAAE,EACX;AAKH,QAH2B,EACzB,QAAQ,CAAC,GAAG,cAAc,WAAW,MAAM,EAC5C;;AAGH,SAAgB,+CACd,WACA;AACA,QAAO,EACJ,OAAO,EACN,oBAAoB,EAAE,QAAQ,EAC/B,CAAC,CACD,MAAM,UAAU,CAAC;;;;ACjGtB,MAAa,mBAAmB;AAChC,MAAa,0BAA0B;AACvC,MAAa,2BAA2B;CACtC;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AAED,MAAa,wBAAwB;CACnC;CACA;CACA;CACD;AAED,MAAa,yBAAyB,CAAC,kBAAkB;;;ACdzD,eAAsB,4BAEpB,YAAoB,gBAAkC;CACtD,MAAM,SAAS,OAAO,IAAI;AAE1B,KAAI,CAAC,OACH,OAAM,IAAI,MACR,iEACD;AAEH,KAAI;EAIF,MAAM,YAHS,MAAM,OAAO,YAAY,EACtC,YACD,CAAC,EACsB,UAAU;AAClC,MAAI,CAAC,SAAU,QAAO,KAAA;AACtB,SAAO,oBAAoB,UAAU,eAAe;UAC7C,OAAO;AACd;;;AAIJ,eAAsB,kCACpB,aACA;AAGA,KAAI,CAFW,OAAO,IAAI,qBAGxB,OAAM,IAAI,MACR,iEACD;CAEH,MAAM,WAAW,IAAI,cAAc,eACjC,4BAA4B,WAAW,CACxC;AACD,QAAO,MAAM,QAAQ,IAAI,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACSpC,SAAgB,MACd,UACA,WAKA,qBAAqB,GACE;CACvB,MAAM,cAAc,QACjB,aAAsD;AACrD,WAAS,SAAS,KAAK,EAAE,aAAa,OAAO,CAAC,CAC3C,MAAM,aAAa;AAClB,QAAK,MAAM,CACT,OACA,EACE,QACA,kBAAkB,CAAC,SAAS,cAE3B,SAAS,SAAS,CACrB,KAAI;AAEF,YADe,UAAU,UAAU,OAAO,GAAG,OAAO,CACrC;YACR,OAAO;AACd,WAAO,MAAM;;IAGjB,CACD,OAAO,UAAU;AAChB,QAAK,MAAM,EACT,kBAAkB,GAAG,aAClB,SACH,QAAO,MAAM;IAEf;IAEN;EACE,UACE,UACA,YACG,CAAC,GAAI,YAAY,EAAE,EAAG,QAAQ;EACnC;EACA,WAAW;EACZ,CACF;AAED,QAAO;EACL,GAAG;EAEH,OAAO,GAAG,WACR,IAAI,SAAiB,GAAG,qBAAqB;AAC3C,eAAY,KAAK;IAAE;IAAkB;IAAQ,CAAC;IAC9C;EACL;;;;AChGH,SAAS,kBAAkB,YAAwC,EAAE,EAAE;AACrE,QAAO,KACL,WACA,OAAO,SAAS,EAChB,UAAU,aAAa,CAAC,SAAS,OAAO,IAAI,SAAS,CAAC,CACvD;;AAGH,IAAa,kBAAb,MAA6B;CAC3B;CAEA,cAAc;AACZ,OAAK,oBAAoB,MACvB,OAAO,aAAsC;AAI3C,UAAO,kBAFW,MAAM,kCADZ,OAAO,IAAI,WAAW,CAAC,QAAQ,GAAG,CAAC,CACe,CAE3B;MAEpC,eAAe,GAAG,OAAO;AAExB,UADiB,KAAK,eAAe,GAAG;IAG3C;;CAGH,IAAI,IAAiC;AACnC,SAAO,KAAK,kBAAkB,KAAK,GAAG;;CAGxC,SAAS,KAAsC;AAC7C,SAAO,QAAQ,IAAI,IAAI,MAAM,OAAO,KAAK,IAAI,GAAG,CAAC,CAAC;;;;;AC1BtD,IAAa,6BAAb,MAAkE;CAChE;CAEA,4BAAoB,IAAI,KAA2C;CAEnE,gCAAwB,IAAI,KAMzB;CAEH,4BAAoB,IAAI,KAA6B;CAErD,cAAc;AACZ,OAAK,UAAU,IAAI,iBAAiB;AAEpC,SAAO,iBAAiB,mBAAmB,UAAU;AACnD,QAAK,sBAAsB,MAAM,OAAO,WAAW,CAAC,MAAM,QAAQ,MAAM;IACxE;AAEF,SAAO,iBAAiB,wBAAwB,UAAU;AACxD,QAAK,sBAAsB,MAAM,OAAO,WAAW,CAAC,MAAM,QAAQ,MAAM;IACxE;;CAGJ,IAAI,IAAY,SAAwC;EACtD,MAAM,UAAU,KAAK,UAAU,IAAI,GAAG;AAEtC,MAAI,SAAS;AACX,OAAI,QAAQ,WAAW,UACrB,QAAO;AAGT,OAAI,CAAC,QACH,QAAO;;EAIX,MAAM,UAAU,gBACd,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,aAAa;AACtC,QAAK,4BAA4B,GAAG;AACpC,UAAO;IACP,CACH;AAED,OAAK,UAAU,IAAI,IAAI,QAAQ;AAE/B,SAAO;;CAGT,SAAS,KAAsC;EAC7C,MAAM,MAAM,IAAI,KAAK,IAAI;EACzB,MAAM,SAAS,KAAK,cAAc,IAAI,IAAI;EAE1C,MAAM,kBAAkB,IAAI,KAAK,OAAO,KAAK,IAAI,GAAG,CAAC;AAErD,MAAI;OACmB,gBAAgB,OAClC,SAAS,UAAU,YAAY,OAAO,SAAS,OACjD,CAGC,QAAO,OAAO;;EAIlB,MAAM,SAAS,gBAAgB,KAAK,YAClC,iBAAiB,QAAwC,CAC1D;AAID,MAFqB,OAAO,OAAO,UAAU,MAAM,WAAW,YAAY,EAExD;GAChB,MAAM,SAAS,OAAO,KACnB,UAAW,MAAqD,MAClE;GAED,MAAM,eAAe,QAAQ,QAAQ,OAAO;AAI5C,gBAAa,SAAS;AACrB,gBAAgD,QAAQ;AAEzD,QAAK,cAAc,IAAI,KAAK;IAC1B,UAAU;IACV,SAAS;IACV,CAAC;AAEF,UAAO;;EAGT,MAAM,eAAe,gBAAgB,QAAQ,IAAI,gBAAgB,CAAC;AAElE,OAAK,cAAc,IAAI,KAAK;GAC1B,UAAU;GACV,SAAS;GACV,CAAC;AAEF,SAAO;;CAGT,4BAAoC,YAA0B;AAC5D,OAAK,MAAM,OAAO,KAAK,cAAc,MAAM,CACzC,KAAI,IAAI,MAAM,IAAI,CAAC,SAAS,WAAW,CACrC,MAAK,cAAc,OAAO,IAAI;;CAKpC,UAAU,IAAuB,UAAkC;EACjE,MAAM,MAAM,MAAM,QAAQ,GAAG,GAAG,KAAK,CAAC,GAAG;AAEzC,OAAK,MAAM,cAAc,KAAK;GAC5B,MAAM,YAAY,KAAK,UAAU,IAAI,WAAW,IAAI,EAAE;AACtD,QAAK,UAAU,IAAI,YAAY,CAAC,GAAG,WAAW,SAAS,CAAC;;AAG1D,eAAa;AACX,QAAK,MAAM,cAAc,KAAK;IAC5B,MAAM,YAAY,KAAK,UAAU,IAAI,WAAW,IAAI,EAAE;AACtD,SAAK,UAAU,IACb,YACA,UAAU,QAAQ,aAAa,aAAa,SAAS,CACtD;;;;CAKP,OAAe,IAAkB;EAC/B,MAAM,YAAY,KAAK,UAAU,IAAI,GAAG,IAAI,EAAE;AAE9C,OAAK,MAAM,YAAY,UACrB,WAAU;;CAId,MAAc,sBAAsB,IAAY;AAC9C,OAAK,4BAA4B,GAAG;AACpC,QAAM,KAAK,IAAI,GAAG;AAClB,OAAK,OAAO,GAAG;;CAGjB,sBAA8B,IAAY;AACxC,OAAK,UAAU,OAAO,GAAG;AACzB,OAAK,4BAA4B,GAAG;AACpC,OAAK,OAAO,GAAG;;CAGjB,uBAA+B,KAAe;AAC5C,UAAQ,MAAM,OAAO,KAAK,sBAAsB,GAAG,CAAC;;;;;AC9JxD,eAAsB,6BAEpB,UAAqB,mBAAmB,kBAAkB;CAC1D,MAAM,SAAS,OAAO,IAAI;AAE1B,KAAI,CAAC,OACH,OAAM,IAAI,MACR,iEACD;AAQH,QALe,MAAM,OAAO,eAAe;EACzC;EACA;EACD,CAAC;;AAKJ,eAAsB,6BAA6B,YAAoB;CACrE,MAAM,SAAS,OAAO,IAAI;AAE1B,KAAI,CAAC,OACH,OAAM,IAAI,MACR,iEACD;AAOH,QAJe,MAAM,OAAO,eAAe,EACzC,YACD,CAAC;;AAKJ,eAAsB,8BAA8B,aAAuB;CACzE,MAAM,SAAS,OAAO,IAAI;AAE1B,KAAI,CAAC,OACH,OAAM,IAAI,MACR,iEACD;AAOH,QAJe,MAAM,OAAO,gBAAgB,EAC1C,aACD,CAAC;;AAKJ,eAAsB,6BACpB,oBACA,GAAG,SACH;CACA,MAAM,SAAS,OAAO,IAAI;AAE1B,KAAI,CAAC,OACH,OAAM,IAAI,MACR,iEACD;AAQH,QALe,MAAM,OAAO,eAAe;EACzC;EACA;EACD,CAAC;;;;AC9DJ,MAAa,0CAA0C,qBACrD,4BACD;;AAGD,MAAa,+BACX,wCAAwC;;AAG1C,MAAa,+BACX,wCAAwC;;AAG1C,MAAa,2CACX,wCAAwC;AAE1C,MAAM,qCAAqC,qBACzC,uBACD;;AAGD,MAAa,0BACX,mCAAmC;;AAGrC,MAAa,0BACX,mCAAmC;;AAGrC,MAAa,sCACX,mCAAmC;AAErC,MAAM,qCAAqC,qBACzC,uBACD;;AAGD,MAAa,0BACX,mCAAmC;;;;;AAMrC,SAAgB,0BAA0B;AAGxC,QADE,mCAAmC,UAAU;;;AAKjD,MAAa,sCACX,mCAAmC;AAErC,MAAa,qBAAyC;CACpD,sBAAsB;CACtB,sBAAsB;CACvB;AAED,MAAa,gCAA+D,EAC1E,2BAA2B,8BAC5B;AAED,MAAa,mBAAqC;CAChD,sBAAsB;CACtB,sBAAsB;CACvB;AAED,MAAa,8BAA2D,EACtE,2BAA2B,8BAC5B;;;AC7DD,MAAa,EACX,UAAU,mBACV,UAAU,mBACV,iBAAiB,kCACf,qBAAqB,iBAAiB;AAE1C,MAAa,EACX,UAAU,YACV,UAAU,YACV,iBAAiB,2BACf,qBAAqB,UAAU;AAEnC,MAAa,EACX,UAAU,wBACV,UAAU,wBACV,iBAAiB,uCACf,qBAAqB,sBAAsB;AAE/C,MAAa,EACX,UAAU,oBACV,UAAU,oBACV,iBAAiB,mCACf,qBAAqB,kBAAkB;AAE3C,MAAa,EACX,UAAU,eACV,UAAU,eACV,iBAAiB,8BACf,qBAAqB,aAAa;AAEtC,MAAa,EACX,UAAU,aACV,UAAU,aACV,iBAAiB,4BACf,qBAAqB,WAAW;AAEpC,MAAa,EACX,UAAU,yBACV,UAAU,yBACV,iBAAiB,wCACf,qBAAqB,uBAAuB;AAEhD,MAAa,EACX,UAAU,eACV,UAAU,eACV,iBAAiB,8BACf,qBAAqB,aAAa;AAEtC,MAAa,EACX,UAAU,kCACV,UAAU,kCACV,iBAAiB,iDACf,qBAAqB,gCAAgC;AAEzD,MAAa,EACX,UAAU,4CACV,UAAU,4CACV,iBAAiB,2DACf,qBAAqB,0CAA0C;AAEnE,MAAa,EACX,UAAU,iBACV,UAAU,iBACV,iBAAiB,gCACf,qBAAqB,eAAe;AAExC,MAAa,EACX,UAAU,qBACV,UAAU,qBACV,iBAAiB,oCACf,qBAAqB,mBAAmB;AAE5C,MAAa,EACX,UAAU,2BACV,UAAU,2BACV,iBAAiB,0CACf,qBAAqB,yBAAyB;AAElD,MAAa,EACX,UAAU,yBACV,UAAU,yBACV,iBAAiB,wCACf,qBAAqB,uBAAuB;AAEhD,MAAa,EACX,UAAU,sBACV,UAAU,sBACV,iBAAiB,qCACf,qBAAqB,oBAAoB;AAE7C,MAAa,EACX,UAAU,0BACV,UAAU,0BACV,iBAAiB,yCACf,qBAAqB,wBAAwB;AAEjD,MAAa,EACX,UAAU,6BACV,UAAU,6BACV,iBAAiB,4CACf,qBAAqB,2BAA2B;AAEpD,MAAa,EACX,UAAU,gCACV,UAAU,gCACV,iBAAiB,+CACf,qBAAqB,8BAA8B;AAEvD,MAAa,EACX,UAAU,yBACV,UAAU,yBACV,iBAAiB,wCACf,qBAAqB,uBAAuB;AAEhD,MAAa,EACX,UAAU,4BACV,UAAU,4BACV,iBAAiB,2CACf,qBAAqB,0BAA0B;AAEnD,MAAa,EACX,UAAU,+BACV,UAAU,+BACV,iBAAiB,8CACf,qBAAqB,6BAA6B;AAEtD,MAAa,EACX,UAAU,uBACV,UAAU,uBACV,iBAAiB,sCACf,qBAAqB,uBAAuB;AAEhD,MAAa,EACX,UAAU,4BACV,UAAU,4BACV,iBAAiB,2CACf,qBAAqB,0BAA0B;AAEnD,MAAa,EACX,UAAU,+BACV,UAAU,+BACV,iBAAiB,8CACf,qBAAqB,6BAA6B;AAEtD,MAAa,EACX,UAAU,6BACV,UAAU,6BACV,iBAAiB,4CACf,qBAAqB,2BAA2B;AAEpD,MAAa,EACX,UAAU,4BACV,UAAU,4BACV,iBAAiB,2CACf,qBAAqB,0BAA0B;AAEnD,MAAa,EACX,UAAU,qCACV,UAAU,qCACV,iBAAiB,oDACf,qBAAqB,mCAAmC;AAE5D,MAAa,EACX,UAAU,2BACV,UAAU,2BACV,iBAAiB,0CACf,qBAAqB,yBAAyB;AAElD,MAAa,EACX,UAAU,4BACV,UAAU,4BACV,iBAAiB,2CACf,qBAAqB,0BAA0B;AAEnD,MAAa,EACX,UAAU,cACV,UAAU,cACV,iBAAiB,6BACf,qBAAqB,YAAY;AAErC,MAAa,EACX,UAAU,oBACV,UAAU,oBACV,iBAAiB,mCACf,qBAAqB,kBAAkB;AAE3C,MAAa,EACX,UAAU,kBACV,UAAU,kBACV,iBAAiB,iCACf,qBAAqB,gBAAgB;AAEzC,MAAa,EACX,UAAU,kBACV,UAAU,kBACV,iBAAiB,iCACf,qBAAqB,gBAAgB;AAEzC,MAAa,EACX,UAAU,cACV,UAAU,cACV,iBAAiB,6BACf,qBAAqB,YAAY;AAErC,MAAa,EACX,UAAU,cACV,UAAU,cACV,iBAAiB,6BACf,qBAAqB,YAAY;AAErC,MAAa,EACX,UAAU,2BACV,UAAU,2BACV,iBAAiB,0CACf,qBAAqB,yBAAyB;AAElD,MAAa,EACX,UAAU,gCACV,UAAU,gCACV,iBAAiB,+CACf,qBAAqB,8BAA8B;AAEvD,MAAa,EACX,UAAU,8BACV,UAAU,8BACV,iBAAiB,6CACf,qBAAqB,4BAA4B;AAErD,MAAM,+BAA+B,qBAAqB,iBAAiB;;AAG3E,MAAa,oBAAoB,6BAA6B;;AAG9D,MAAa,oBAAoB,6BAA6B;;AAG9D,MAAa,gCACX,6BAA6B;AAE/B,MAAM,gCAAgC,qBAAqB,kBAAkB;;AAG7E,MAAa,qBAAqB,8BAA8B;;AAGhE,MAAa,qBAAqB,8BAA8B;;AAGhE,MAAa,iCACX,8BAA8B;AAEhC,MAAM,gCAAgC,qBACpC,gCACD;;AAGD,MAAa,mCACX,8BAA8B;;AAGhC,MAAa,mCACX,8BAA8B;;AAGhC,MAAa,+CACX,8BAA8B;AAEhC,MAAM,wCAAwC,qBAC5C,wCACD;;AAGD,MAAa,2CACX,sCAAsC;;AAGxC,MAAa,2CACX,sCAAsC;;AAGxC,MAAa,uDACX,sCAAsC;AAExC,MAAM,mCACJ,qBAAqB,qBAAqB;;AAG5C,MAAa,wBAAwB,iCAAiC;;AAGtE,MAAa,wBAAwB,iCAAiC;;AAGtE,MAAa,oCACX,iCAAiC;AAEnC,MAAM,uCAAuC,qBAC3C,uCACD;;AAGD,MAAa,0CACX,qCAAqC;;AAGvC,MAAa,0CACX,qCAAqC;;AAGvC,MAAa,sDACX,qCAAqC;AAEvC,MAAM,sCAAsC,qBAC1C,wBACD;;AAGD,MAAa,2BACX,oCAAoC;;AAGtC,MAAa,2BACX,oCAAoC;;AAGtC,MAAa,uCACX,oCAAoC;AAEtC,MAAM,yBAAyB,qBAAqB,WAAW;;AAG/D,MAAa,cAAc,uBAAuB;;AAGlD,MAAa,cAAc,uBAAuB;;AAGlD,MAAa,0BAA0B,uBAAuB;AAE9D,MAAM,0BAA0B,qBAAqB,YAAY;;AAGjE,MAAa,eAAe,wBAAwB;;AAGpD,MAAa,eAAe,wBAAwB;;AAGpD,MAAa,2BAA2B,wBAAwB;AAShE,MAAM,uBAA6C;CACjD,gBAAgB;CAChB,SAAS;CACT,qBAAqB;CACrB,iBAAiB;CACjB,YAAY;CACZ,UAAU;CACV,sBAAsB;CACtB,YAAY;CACZ,+BAA+B;CAC/B,yCACE;CACF,cAAc;CACd,kBAAkB;CAClB,wBAAwB;CACxB,sBAAsB;CACtB,mBAAmB;CACnB,uBAAuB;CACvB,0BAA0B;CAC1B,6BAA6B;CAC7B,sBAAsB;CACtB,yBAAyB;CACzB,4BAA4B;CAC5B,yBAAyB;CACzB,4BAA4B;CAC5B,0BAA0B;CAC1B,yBAAyB;CACzB,+BAA+B;CAC/B,uCACE;CACF,oBAAoB;CACpB,uBAAuB;CACvB,sCAAsC;CACtC,kCAAkC;CAClC,wBAAwB;CACxB,yBAAyB;CACzB,WAAW;CACX,iBAAiB;CACjB,eAAe;CACf,eAAe;CACf,WAAW;CACX,WAAW;CACX,wBAAwB;CACxB,6BAA6B;CAC7B,2BAA2B;CAC3B,WAAW;CACX,UAAU;CACV,iBAAiB;CACjB,gBAAgB;CACjB;AAED,MAAa,wBAA+C;CAC1D,GAAG;CACH,GAAG;CACH,GAAG;CACJ;AAED,MAAM,qBAAyC;CAC7C,gBAAgB;CAChB,SAAS;CACT,qBAAqB;CACrB,iBAAiB;CACjB,YAAY;CACZ,UAAU;CACV,sBAAsB;CACtB,YAAY;CACZ,+BAA+B;CAC/B,yCACE;CACF,cAAc;CACd,kBAAkB;CAClB,wBAAwB;CACxB,mBAAmB;CACnB,uBAAuB;CACvB,0BAA0B;CAC1B,6BAA6B;CAC7B,sBAAsB;CACtB,yBAAyB;CACzB,4BAA4B;CAC5B,sBAAsB;CACtB,yBAAyB;CACzB,4BAA4B;CAC5B,0BAA0B;CAC1B,yBAAyB;CACzB,kCAAkC;CAClC,wBAAwB;CACxB,yBAAyB;CACzB,WAAW;CACX,iBAAiB;CACjB,eAAe;CACf,eAAe;CACf,WAAW;CACX,WAAW;CACX,wBAAwB;CACxB,6BAA6B;CAC7B,2BAA2B;CAC3B,WAAW;CACX,oBAAoB;CACpB,sCAAsC;CACtC,+BAA+B;CAC/B,uCACE;CACF,uBAAuB;CACvB,UAAU;CACV,iBAAiB;CACjB,gBAAgB;CACjB;AAED,MAAa,sBAA2C;CACtD,GAAG;CACH,GAAG;CACH,GAAG;CACJ;;;ACheD,MAAM,yBAAyB,qBAAqB,WAAW;AAE/D,MAAa,cACX,uBAAuB;AAEzB,MAAa,cACX,uBAAuB;AAEzB,MAAa,0BACX,uBAAuB;;;ACZzB,MAAM,uBAAuB,qBAAqB,SAAS;;AAG3D,MAAa,YACX,qBAAqB;;AAGvB,MAAa,YACX,qBAAqB;;AAGvB,MAAa,wBAAwB,qBAAqB;;;ACX1D,MAAM,qCAAqC,qBACzC,uBACD;AAED,MAAa,0BACX,mCAAmC;AAErC,MAAa,0BACX,mCAAmC;AACrC,MAAa,sCACX,mCAAmC;;;ACVrC,MAAM,sBAAsB,qBAAqB,QAAQ;;AAGzD,MAAa,aAAa,oBAAoB;;AAG9C,MAAa,aAAa,oBAAoB;;AAG9C,MAAa,uBAAuB,oBAAoB;;AAGxD,SAAgB,YAAY,OAAgB;AAC1C,YAAW,MAAM;;;AAInB,SAAgB,eAAe;AAC7B,YAAW,KAAA,EAAU;;;AAIvB,SAAgB,wBAAwB,cAAsB;AAC5D,YAAW;EAAE,MAAM;EAAkB;EAAc,CAAC;;;AAItD,SAAgB,oBAAoB,UAAyB;AAE3D,YAAW;EAAE,MAAM;EAAc,IADtB,OAAO,aAAa,WAAW,WAAW,SAAS;EACzB,CAAC;;;;AC/BxC,MAAM,4BAA4B,qBAChC,0BACD;AAED,MAAa,6BAA6B,0BAA0B;AACpE,MAAa,6BAA6B,0BAA0B;AACpE,MAAa,yCACX,0BAA0B;;;ACO5B,MAAM,oCAAoC,qBACxC,sBACD;AACD,MAAM,8BAA8B,qBAAqB,gBAAgB;;AAGzE,MAAa,yBACX,kCAAkC;;AAGpC,MAAa,yBACX,kCAAkC;;AAGpC,MAAa,qCACX,kCAAkC;;AAGpC,MAAa,mBACX,4BAA4B;;AAG9B,MAAa,mBACX,4BAA4B;;AAG9B,MAAa,+BACX,4BAA4B;AAI9B,MAAa,gBACX,wBAAwB,EAAE,eAAe,YAAY;AAEvD,MAAa,oBAAoB;AAE/B,QADa,SAAS,EACT,MAAM,IAAI,EAAE;;AAG3B,MAAa,yBACX,wBAAwB,EAAE,eAAe;AAE3C,MAAa,oBACX,wBAAwB,EAAE,eAAe;AAE3C,MAAa,kBAAsC,wBAAwB,EAAE;;;AC3D7E,MAAM,gCAAgC,qBACpC,yBACD;;AAGD,MAAa,4BAA4B,8BAA8B;;AAGvE,MAAa,4BAA4B,8BAA8B;;AAGvE,MAAa,wCACX,8BAA8B;;AAGhC,SAAgB,sBAAsB;AACpC,2BAA0B,KAAK;;;AAIjC,SAAgB,sBAAsB;AACpC,2BAA0B,MAAM;;;;AChBlC,SAAgB,mBAAmB,MAAc;AAC/C,QAAO,IAAI,IACT,KAAK,QAAQ,QAAQ,GAAG,EACxB,OAAO,SAAS,UAAU,OAAO,IAAI,YAAY,KAClD,CAAC;;;AAIJ,SAAgB,mBAAmB,MAAc;CAC/C,MAAM,WAAW,OAAO,IAAI,YAAY;AACxC,QAAO,KAAK,QAAQ,UAAU,SAAS,SAAS,IAAI,GAAG,MAAM,GAAG;;;AAIlE,SAAgB,sBACd,OACA;AACA,KAAI,CAAC,MAAO,QAAO;AACnB,QAAO,MAAM,KAAK,MAAM,OAAO,KAAK;;;AAItC,SAAgB,aAAa,MAAwB;AACnD,KAAI,CAAC,KAAM,QAAO;CAClB,MAAM,WAAW,KAAK;AACtB,KAAI,CAAC,SAAU,QAAO,KAAK,KAAK,GAAG;AACnC,QAAO,KAAK,GAAG,SAAS,GAAG,KAAK,KAAK;;;;;;AAOvC,SAAgB,wBAAwB,MAAc;CACpD,MAAM,cAAc,mBAAmB,KAAK;AAE5C,QADc,wBAAwB,KAAK,YAAY,GACxC;;;AAIjB,SAAgB,SAAS,OAA2B;AAClD,KAAI,CAAC,MAAO,QAAO,KAAA;AAInB,QAFE,kFACsB,KAAK,MAAM,GACpB;;AAGjB,SAAgB,sBAAsB,UAA8B;AAElE,QADe,SAAS,SAAS;;AAInC,SAAgB,sBAAsB,MAAc;AAGlD,QADe,sBADE,wBAAwB,KAAK,CACA;;;;;;AAQhD,SAAgB,yBAAyB,MAAc;CACrD,MAAM,cAAc,mBAAmB,KAAK;AAE5C,QADc,gBAAgB,KAAK,YAAY,GAChC,MAAM;;AAGvB,SAAgB,uBAAuB,WAA+B;AAEpE,QADgB,SAAS,UAAU;;AAIrC,SAAgB,uBAAuB,MAAc;AAGnD,QADgB,uBADE,yBAAyB,KAAK,CACC;;;;;AAOnD,SAAgB,6BAA6B,UAA0B;CACrE,MAAM,SAAS,OAAO,SAAS;AAC/B,QAAO,SAAS,GAAG,WAAW,WAAW;;;;AC9E3C,MAAM,gCAAgC,qBAAqB,kBAAkB;;AAG7E,MAAa,qBAAqB,8BAA8B;;AAGhE,MAAa,qBAAqB,8BAA8B;;AAGhE,MAAa,iCACX,8BAA8B;;AAGhC,SAAgB,mBAAmB;CACjC,MAAM,QAAQ,sBAAsB;AACpC,KAAI,CAAC,MAAM,GACT,OAAM,IAAI,MACR,2EACD;AAGH,QAAO;;;AAIT,SAAgB,uBAAuB;CACrC,MAAM,kBAAkB,oBAAoB;CAE5C,MAAM,gBADS,WAAW,EACI,MAC3B,UAAU,MAAM,OAAO,OAAO,gBAChC;CAED,MAAM,CAAC,OAAO,YAAY,YAAY,cAAc;AACpD,KAAI,CAAC,cACH,QAAO,CAAC,KAAA,GAAW,KAAA,EAAU;AAE/B,QAAO,CAAC,OAAO,SAAS;;AAM1B,SAAgB,iBACd,kBACA;CACA,MAAM,YACJ,OAAO,qBAAqB,WACxB,mBACA,kBAAkB,OAAO;CAI/B,MAAM,WADQ,OAAO,IAAI,QAAQ,MAAM,MAAM,EAAE,OAAO,SAAS,UAAU,GAClD,OAAO;AAE9B,oBAAmB,QAAQ;AAE3B,KAAI,CAAC,SAAS;EACZ,MAAM,WAAW,mBAAmB,IAAI;AACxC,MAAI,aAAa,OAAO,SAAS,SAC/B;AAEF,SAAO,QAAQ,UAAU,MAAM,IAAI,6BAA6B,SAAS,CAAC;AAC1E;;CAEF,MAAM,WAAW,mBAAmB,MAAM,YAAY;AACtD,KAAI,aAAa,OAAO,SAAS,SAC/B;AAEF,QAAO,QAAQ,UAAU,MAAM,IAAI,6BAA6B,SAAS,CAAC;;AAG5E,SAAgB,4CAA4C;AAC1D,QAAO,iBAAiB,kBAAkB;EACxC,MAAM,WAAW,OAAO,SAAS;EACjC,MAAM,UAAU,uBAAuB,SAAS;AAEhD,MAAI,YADoB,OAAO,IAAI,gBAEjC,kBAAiB,QAAQ;GAE3B;;;;;ACtFJ,SAAgB,gBAAgC,OAAY;AAC1D,QAAO,MAAM,UAAU,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,KAAK,CAAC;;;AAI/D,SAAgB,eACd,MACkB;AAClB,KAAI,CAAC,KAAM,QAAO;AAClB,QAAO,KAAK,KAAK,aAAa,KAAK;;;AAIrC,SAAgB,iBACd,MACoB;AACpB,KAAI,CAAC,KAAM,QAAO;AAClB,QAAO,KAAK,KAAK,aAAa,KAAK;;;;;ACXrC,SAAgB,0BAA0B;CACxC,MAAM,CAAC,iBAAiB,sBAAsB;AAC9C,QAAO,eAAe,MAAM,OAAO;;;AAIrC,SAAgB,8BAAsD;AAEpE,QADc,yBAAyB,EACzB,QAAQ,MAAM,eAAe,EAAE,CAAC;;;AAIhD,SAAgB,gCAA0D;AAExE,QADc,yBAAyB,EACzB,QAAQ,MAAM,iBAAiB,EAAE,CAAC;;;AAIlD,SAAgB,8BAAwD;CAEtE,MAAM,cADY,6BAA6B,EAChB,KAAK,SAAS,KAAK,GAAG;AACrD,QAAO,kBAAkB,YAAY;;;AAIvC,SAAgB,kCAAkC;AAMhD,SALiC,6BAA6B,EAElC,OAAO,wBAAwB,GAElB,KAAK,QAAQ,IAAI,MAAM,OAAO,GAAG;;AAI5E,SAAS,wBACP,UACmC;AACnC,QAAO,SAAS,OAAO,iBAAiB;;;;ACtC1C,MAAM,+BAA+B,qBAAqB,iBAAiB;AAC3E,MAAM,oBAAoB,6BAA6B;AACvD,MAAM,oBAAoB,6BAA6B;AACvD,MAAa,gCACX,6BAA6B;;AAG/B,SAAgB,kBAAoC;CAClD,MAAM,iBAAiB,mBAAmB;AAE1C,QADc,yBAAyB,EACzB,MAAM,MAAM,EAAE,OAAO,eAAe;;;AAIpD,SAAgB,gBAAgB,gBAA2C;CACzE,MAAM,WACJ,OAAO,mBAAmB,WACtB,iBACA,aAAa,eAAe;AAElC,mBADe,sBAAsB,SAAS,CACrB;CACzB,MAAM,oBAAoB,yBAAyB,OAAO,SAAS,SAAS;AAC5E,KAAI,CAAC,kBACH;AAEF,KAAI,CAAC,UAAU;EACb,MAAM,WAAW,mBAAmB,MAAM,oBAAoB;AAC9D,MAAI,aAAa,OAAO,SAAS,SAC/B;AAEF,SAAO,QAAQ,UAAU,MAAM,IAAI,6BAA6B,SAAS,CAAC;AAC1E;;CAEF,MAAM,WAAW,mBAAmB,MAAM,kBAAkB,GAAG,WAAW;AAC1E,KAAI,aAAa,OAAO,SAAS,SAC/B;AAEF,QAAO,QAAQ,UAAU,MAAM,IAAI,6BAA6B,SAAS,CAAC;;AAG5E,SAAgB,mCAAmC;AACjD,QAAO,iBAAiB,mCAAmC;AACzD,oBAAkB,KAAA,EAAU;GAC5B;;AAGJ,SAAgB,2CAA2C;AACzD,QAAO,iBAAiB,kBAAkB;EACxC,MAAM,WAAW,OAAO,SAAS;EACjC,MAAM,WAAW,wBAAwB,SAAS;AAElD,MAAI,aADmB,OAAO,IAAI,eAEhC,iBAAgB,SAAS;GAE3B;;;;AChEJ,MAAM,qCAAqC,qBACzC,uBACD;;AAGD,MAAa,0BACX,mCAAmC;;AAGrC,MAAa,0BACX,mCAAmC;;AAGrC,MAAa,sCACX,mCAAmC;;;ACdrC,MAAM,yCAAyC,qBAC7C,2BACD;;AAGD,MAAa,8BACX,uCAAuC;;AAGzC,MAAa,8BACX,uCAAuC;;AAGzC,MAAa,0CACX,uCAAuC;;;ACdzC,MAAM,sBAAsB,qBAAqB,QAAQ;;AAGzD,MAAa,aAAa,oBAAoB;;AAG9C,MAAa,aAAa,oBAAoB;;AAG9C,MAAa,uBAAuB,oBAAoB;;;ACFxD,MAAM,+BAA+B,qBACnC,sBACD;AAED,MAAa,yBAAyB,6BAA6B;;AAGnE,MAAa,yBAAyB;CACpC,MAAM,iBAAiB,wBAAwB;AAE/C,QAAO,sBACJ,OAAQ,iBAAiB,eAAe,UAAU,GAAG,SAAS,UACzD,gBAAgB,YAAY,EAAE,CACrC;;;AAIH,MAAa,qCACX,6BAA6B;;AAG/B,SAAgB,uBAAuB,gBAAiC;AACtE,8BAA6B,SAAS,eAAe;AACrD,mCAAkC,eAAe,SAAS;AAC1D,qCAAoC,eAAe,SAAS;AAC5D,gBAAe,WAAW,EAAE,eAAe;AACzC,oCAAkC,SAAS;AAC3C,sCAAoC,SAAS;GAC7C;;AAGJ,SAAS,kCAAkC,UAA8B;CACvE,MAAM,uBAAuB,SAAS,SAAS,QAAQ,IAAI,eAAe;CAE1E,MAAM,WACJ,OAAO,IAAI,qBAAqB,eAAe;AACjD,KAAI,CAAC,YAAY,qBAAqB,WAAW,EAAG;CAEpD,MAAM,UAAU,SAAS,gBAAgB,GAAG,qBAAqB;CACjE,MAAM,aAAa,EAAE;AACrB,MAAK,MAAM,UAAU,QACnB,KAAI,OAAO,WAAW,QACpB,KAAI,qBAAqB,QAAQ,OAAO,MAAM,CAC5C,YAAW,KAAK,OAAO;KAEvB,SAAQ,MACN,6CACA,OAAO,MACR;AAIP,KAAI,WAAW,SAAS,GAAG;EACzB,MAAM,iBAAiB,WAAW,KAC/B,MAAM,EAAE,KAAK,cAAc,OAAO,GACpC;AACD,WAAS,kBAAkB,GAAG,eAAe;AAC7C,WAAS,gBAAgB,GAAG,WAAW,KAAK,MAAM,EAAE,KAAK,CAAC;;;AAI9D,SAAS,oCAAoC,UAA8B;CACzE,MAAM,mBAAmB,SACtB,SAAS,QAAQ,IAAI,iBAAiB,CACtC,QAAQ,MAAM,MAAM,KAAA,EAAU;CAEjC,MAAM,WACJ,OAAO,IAAI,qBAAqB,eAAe;AACjD,KAAI,CAAC,YAAY,iBAAiB,WAAW,EAAG;CAEhD,MAAM,UAAU,SAAS,yBAAyB,GAAG,iBAAiB;CACtE,MAAM,aAAa,EAAE;AACrB,MAAK,MAAM,UAAU,QACnB,KAAI,OAAO,WAAW,QACpB,KAAI,uBAAuB,QAAQ,OAAO,MAAM,CAC9C,YAAW,KAAK,OAAO;KAEvB,SAAQ,MAAM,wCAAwC,OAAO,MAAM;AAIzE,KAAI,WAAW,SAAS,GAAG;EACzB,MAAM,iBAAiB,WACpB,KAAK,MAAM,EAAE,KAAK,aAAa,CAC/B,QAAQ,MAAmB,CAAC,CAAC,EAAE;AAClC,WAAS,2BAA2B,GAAG,eAAe;AACtD,WAAS,yBAAyB,GAAG,WAAW,KAAK,MAAM,EAAE,KAAK,CAAC;;;;;ACZvE,MAAa,oCAAoC;CAC/C,SAAS;CACT,QAAQ;CACR,uBAAuB;AACrB,kCAAgC;AAChC,6CAA2C;AAC3C,oCAAkC;;CAEpC,sBAAsB;AACpB,iCAA+B;AAC/B,4CAA0C;;CAE5C,eAAe;CACf,sBAAsB;CACvB;AAED,MAAM,wCAAoE;CACxE,GAAG;CACH,qBAAqB;CACrB,eAAe;CACf,UAAU;CACV,OAAO;CACP,QAAQ;CACR,qBAAqB;CACrB,yBAAyB;CACzB,0BAA0B;CAC1B,wBAAwB;CACxB,sBAAsB;CACtB,gBAAgB;CAChB,SAAS;CACT,UAAU;CACV,qBAAqB;CACrB,iBAAiB;CACjB,YAAY;CACZ,UAAU;CACV,sBAAsB;CACtB,YAAY;CACZ,+BAA+B;CAC/B,yCACE;CACF,cAAc;CACd,WAAW;CACX,kBAAkB;CAClB,wBAAwB;CACxB,sBAAsB;CACtB,gBAAgB;CAChB,iBAAiB;CACjB,mBAAmB;CACnB,sBAAsB;CACtB,uBAAuB;CACvB,0BAA0B;CAC1B,6BAA6B;CAC7B,sBAAsB;CACtB,yBAAyB;CACzB,4BAA4B;CAC5B,yBAAyB;CACzB,4BAA4B;CAC5B,sBAAsB;CACtB,2BAA2B;CAC3B,0BAA0B;CAC1B,yBAAyB;CACzB,+BAA+B;CAC/B,uCACE;CACF,oBAAoB;CACpB,sCACE;CACF,uBAAuB;CACvB,kCACE;CACF,wBAAwB;CACxB,yBAAyB;CACzB,WAAW;CACX,iBAAiB;CACjB,eAAe;CACf,eAAe;CACf,WAAW;CACX,WAAW;CACX,wBAAwB;CACxB,6BAA6B;CAC7B,2BAA2B;CAC3B,OAAO;CACR;AACD,SAAgB,qBAAqB;AACnC,mCAAkC,sCAAsC;;AAG1E,SAAgB,kCACd,mBACA;AACA,YAAW,oBAAoB,OAAO,IAAI,CAAC;;;;AC1K7C,SAAgB,0BAA6D;AAE3E,QADsB,kBAAkB,CAErC,SAAS,QAAQ,IAAI,eAAe,CACpC,QACE,QAAQ,OAAO,YAEd,QAAQ,WACL,MACC,EAAE,cAAc,OAAO,OAAO,OAAO,cAAc,OAAO,MAC1D,EAAE,YAAY,OAAO,QACxB,KAAK,MACT;;AAGL,SAAgB,2BACd,IACiC;AAEjC,QAD6B,yBAAyB,EACzB,MAC1B,WAAW,OAAO,cAAc,OAAO,OAAO,GAChD;;;;ACrBH,SAAgB,iCAAiC;CAC/C,MAAM,uBAAuB,yBAAyB;CACtD,MAAM,uBAAuB,yBAAyB;AACtD,KAAI,CAAC,sBAAsB,OAAQ,QAAO;AAC1C,QAAO,sBAAsB,QAAQ,WACnC,qBAAqB,SAAS,OAAO,cAAc,OAAO,GAAG,CAC9D;;;;;ACJH,SAAgB,oBAA4C;CAC1D,MAAM,eAAe,iBAAiB;AACtC,KAAI,iBAAiB,aAAa,CAAE,QAAO;;;;;ACD7C,SAAgB,kCAA0C;CACxD,MAAM,QAAQ,yBAAyB;CAEvC,MAAM,mBADiB,mBAAmB,EACD;AACzC,KAAI,CAAC,MAAO,QAAO,EAAE;AACrB,KAAI,CAAC,iBACH,QAAO,gBAAgB,MAAM,QAAQ,MAAM,CAAC,EAAE,aAAa,CAAC;AAC9D,QAAO,gBACL,MAAM,QAAQ,MAAM,EAAE,iBAAiB,iBAAiB,CACzD;;;;ACJH,SAAgB,uBACd,KACA,OACA;CACA,MAAM,SAAS,sBAAsB;AACrC,QAAO,MAAM;;AAGf,SAAgB,oBACd,KACA,OACA;CACA,MAAM,SAAS,mBAAmB;AAClC,QAAO,MAAM;;AAGf,SAAgB,+BAEd,KAAW,OAAiD;CAC5D,MAAM,SAAS,8BAA8B;AAC7C,QAAO,MAAM;;;;ACxBf,SAAgB,uBACd,KACA,OACA;CACA,MAAM,SAAS,sBAAsB;AACrC,QAAO,MAAM;;;;ACDf,SAAgB,yBAAyB,QAAwB;AAC/D,MAAK,MAAM,OAAO,OAAO,KAAK,OAAO,CACnC,wBAAuB,KAAK,OAAO,KAAK;;AAI5C,SAAgB,4BAA4B,QAAwB;CAClE,MAAM,CAAC,eAAe,oBAAoB,SAAS,MAAM;AAEzD,iBAAgB;AACd,MAAI,cAAe;AACnB,2BAAyB,OAAO;AAChC,mBAAiB,KAAK;IACrB,CAAC,QAAQ,cAAc,CAAC;;AAG7B,SAAgB,uBAAuB,uBAAuC;AAC5E,QAAO,SAAS,QAAQ;AACtB,oBAAkB,sBAAsB;;;AAI5C,SAAgB,kBAAkB,QAAiC;AACjE,MAAK,MAAM,OAAO,OAAO,KAAK,OAAO,CACnC,wBAAuB,KAAK,OAAO,KAAK;;AAI5C,SAAgB,qBAAqB,QAAiC;CACpE,MAAM,CAAC,eAAe,oBAAoB,SAAS,MAAM;AAEzD,iBAAgB;AACd,MAAI,cAAe;AACnB,oBAAkB,OAAO;AACzB,mBAAiB,KAAK;IACrB,CAAC,QAAQ,cAAc,CAAC;;;;;;AAO7B,SAAgB,eAAe,QAA8B;AAC3D,MAAK,MAAM,OAAO,OAAO,KAAK,OAAO,CACnC,wBAAuB,KAAK,OAAO,KAAK;;;;;;AAQ5C,SAAgB,0BACd,QACA;AACA,MAAK,MAAM,OAAO,OAAO,KAAK,OAAO,CACnC,wBAAuB,KAAK,OAAO,KAAK;;;;;;;;AAU5C,SAAgB,kBAAkB,QAA8B;CAC9D,MAAM,CAAC,eAAe,oBAAoB,SAAS,MAAM;AAEzD,iBAAgB;AACd,MAAI,cAAe;AACnB,iBAAe,OAAO;AACtB,mBAAiB,KAAK;IACrB,CAAC,QAAQ,cAAc,CAAC;;;;;;;;AAS7B,SAAgB,6BACd,QACA;CACA,MAAM,CAAC,eAAe,oBAAoB,SAAS,MAAM;AAEzD,iBAAgB;AACd,MAAI,cAAe;AACnB,4BAA0B,OAAO;AACjC,mBAAiB,KAAK;IACrB,CAAC,QAAQ,cAAc,CAAC;;;;AC9F7B,SAAgB,uBACd,KACA;CACA,MAAM,eAAe,oBAAoB;AACzC,QAAO,cAAc;;;;;;AAOvB,SAAgB,oBAAiD,KAAW;CAC1E,MAAM,eAAe,iBAAiB;AACtC,QAAO,cAAc;;;;;;AAOvB,SAAgB,+BAEd,KAAW;CACX,MAAM,eAAe,4BAA4B;AACjD,QAAO,cAAc;;;;;;;;ACxBvB,SAAgB,sBAGd;CACA,MAAM,cAAc,SAAS;CAC7B,MAAM,CAAC,QAAQ,aAAa,eAEpB,cAAc,YAAY,CAAC;CACnC,MAAM,kBAAkB,OAA0B,EAAE,CAAC;AAErD,iBAAgB;AACd,MAAI,CAAC,YAAa;EAElB,SAAS,YAAY;AAEnB,QAAK,MAAM,SAAS,gBAAgB,QAClC,QAAO;AAET,mBAAgB,UAAU,EAAE;GAE5B,MAAM,UAAU,YAAa,MAAM;AACnC,QAAK,MAAM,UAAU,SAAS;IAC5B,MAAM,QAAQ,OAAO,QAAQ,8BAA8B;AACzD,eAAU,cAAc,YAAY,CAAC;MACrC;AACF,oBAAgB,QAAQ,KAAK,MAAM;;AAIrC,aAAU,cAAc,YAAY,CAAC;;AAGvC,aAAW;EAGX,MAAM,WAAW,YAAY,WAAW,IAAK;AAE7C,eAAa;AACX,iBAAc,SAAS;AACvB,QAAK,MAAM,SAAS,gBAAgB,QAClC,QAAO;AAET,mBAAgB,UAAU,EAAE;;IAE7B,CAAC,YAAY,CAAC;AAEjB,QAAO;;;;;AAMT,SAAgB,mBACd,YACqC;AAErC,QADe,qBAAqB,CACtB,IAAI,WAAW;;AAG/B,SAAS,cACP,aAC8C;CAC9C,MAAM,sBAAM,IAAI,KAAsC;AACtD,KAAI,CAAC,YAAa,QAAO;AACzB,MAAK,MAAM,UAAU,YAAY,MAAM,CACrC,KAAI,IAAI,OAAO,MAAM,OAAO,QAAQ,oBAAoB,CAAC;AAE3D,QAAO;;;;;ACnET,SAAgB,kBAId,YACA,cACA;CACA,MAAM,CAAC,UAAU,YAAY,gBAAgB,WAAW;CACxD,MAAM,sBAAsB,2BAA2B,aAAa;AAEpE,KAAI,CAAC,cAAc,CAAC,aAAc,QAAO,EAAE;AAE3C,KAAI,CAAC,SACH,OAAM,IAAI,MAAM,uBAAuB,aAAa;AAEtD,KAAI,CAAC,oBACH,OAAM,IAAI,oBAAoB,aAAa;AAG7C,KAAI,SAAS,OAAO,iBAAiB,aACnC,OAAM,IAAI,0BACR,YACA,cACA,SAAS,OAAO,aACjB;AAGH,QAAO,CAAC,UAAU,SAAS;;;;;;;;;;;ACb7B,SAAgB,sBACd,YACyB;CACzB,MAAM,gBAAgB,kBAAkB;CACxC,MAAM,gBAAgB,OAAO,MAAM;CACnC,MAAM,CAAC,OAAO,YAAY,gBAA+B;EACvD,kBAAkB,EAAE;EACpB,iBAAiB,EAAE;EACnB,WAAW,CAAC,CAAC;EACb,OAAO,KAAA;EACR,EAAE;CAEH,MAAM,kBAAkB,YACtB,OAAO,aAAa,MAAqB;EACvC,MAAM,cAAc;EACpB,MAAM,iBAAiB;AAEvB,MAAI,CAAC,cAAc,CAAC,eAAe;AACjC,YAAS;IACP,kBAAkB,EAAE;IACpB,iBAAiB,EAAE;IACnB,WAAW;IACX,OAAO,KAAA;IACR,CAAC;AACF;;AAGF,YAAU,UAAU;GAAE,GAAG;GAAM,WAAW;GAAM,OAAO,KAAA;GAAW,EAAE;EAEpE,IAAI,YAAyB,EAAE;EAC/B,IAAI,WAAwB,EAAE;EAC9B,IAAI;AAEJ,MAAI;AAIF,gBAHqB,MAAM,cAAc,cAAc,YAAY,EACjE,QAAQ,CAAC,SAAS,EACnB,CAAC,EACuB;WAClB,KAAK;AACZ,gBAAa,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,IAAI,CAAC;;AAGlE,MAAI,CAAC,WACH,KAAI;AAIF,eAHoB,MAAM,cAAc,cAAc,YAAY,EAChE,QAAQ,CAAC,QAAQ,EAClB,CAAC,EACqB;WAChB,KAAK;AACZ,gBAAa,eAAe,QAAQ,MAAM,IAAI,MAAM,OAAO,IAAI,CAAC;;AAMpE,MACE,CAAC,cACD,UAAU,WAAW,KACrB,SAAS,WAAW,KACpB,aAAa,aACb;AACA,SAAM,IAAI,SAAS,YAAY,WAAW,SAAS,eAAe,CAAC;AACnE,UAAO,gBAAgB,aAAa,EAAE;;AAGxC,WAAS;GACP,kBAAkB;GAClB,iBAAiB;GACjB,WAAW;GACX,OAAO;GACR,CAAC;AACF,gBAAc,UAAU;IAE1B,CAAC,YAAY,cAAc,CAC5B;AAED,iBAAgB;AACd,MAAI,cAAc,cACX,kBAAiB;WACb,CAAC,YAAY;AACtB,YAAS;IACP,kBAAkB,EAAE;IACpB,iBAAiB,EAAE;IACnB,WAAW;IACX,OAAO,KAAA;IACR,CAAC;AACF,iBAAc,UAAU;;IAEzB;EAAC;EAAY;EAAe;EAAgB,CAAC;CAGhD,MAAM,UAAU,kBAAkB;AAC3B,kBAAgB,EAAE;IACtB,CAAC,gBAAgB,CAAC;AAErB,QAAO;EAAE,GAAG;EAAO;EAAS;;;;;AClH9B,SAAgB,qCAAqC;AAEnD,QAD6B,yBAAyB,EACzB,KAAK,WAAW,OAAO,cAAc,OAAO,GAAG;;;;;;;;;ACG9E,SAAgB,mBAAmB;CACjC,MAAM,uBAAuB,yBAAyB;CACtD,MAAM,yBAAyB,oCAAoC;AACnE,QAAO,wBAAwB;;;;ACHjC,SAAgB,aACd,SACgE;CAEhE,MAAM,aADS,WAAW,EACC,MAAM,UAAU,MAAM,OAAO,OAAO,QAAQ;CACvE,MAAM,CAAC,OAAO,YAAY,YAAY,WAAW;AACjD,KAAI,CAAC,WACH,OAAM,IAAI,MAAM,iBAAiB,QAAQ,YAAY;AAEvD,QAAO,CAAC,OAAO,SAAS;;;;ACb1B,SAAgB,mBAA+C;AAE7D,QADsB,kBAAkB,CAErC,SAAS,QAAQ,IAAI,QAAQ,CAC7B,QACE,WAAW,CAAC,OAAO,cAAc,SAAS,4BAA4B,CACxE;;AAGL,SAAgB,gBAA4C;AAE1D,QADsB,kBAAkB,CAErC,SAAS,QAAQ,IAAI,QAAQ,CAC7B,QAAQ,WACP,OAAO,cAAc,SAAS,4BAA4B,CAC3D;;AAGL,SAAgB,wBACd,cAC0B;CAC1B,MAAM,gBAAgB,kBAAkB;AACxC,KAAI,CAAC,aAAc,QAAO,KAAA;AAC1B,KAAI,eAAe,WAAW,EAAG,QAAO,KAAA;AAKxC,SAHuB,eAAe,QAAQ,WAC5C,OAAO,cAAc,SAAS,aAAa,CAC5C,IACuB;;AAG1B,SAAgB,iBACd,IAC0B;AAE1B,QADmB,eAAe,EACf,MAAM,WAAW,OAAO,OAAO,OAAO,GAAG;;AAG9D,SAAgB,sBAAgD;AAE9D,QADyB,iBAAiB,wBAAwB;;AAIpE,SAAgB,oBACd,IAC0B;AAE1B,QADsB,kBAAkB,EAClB,MAAM,WAAW,OAAO,OAAO,OAAO,GAAG;;AAGjE,SAAgB,gCACd,cACA;CACA,MAAM,gBAAgB,kBAAkB;AACxC,KAAI,CAAC,aAAc,QAAO,KAAA;AAK1B,QAHuB,eAAe,QAAQ,WAC5C,OAAO,cAAc,SAAS,aAAa,CAC5C;;;;AC3DH,SAAgB,cACd,IACwB;AAExB,QADgB,+BAA+B,EAC/B,MAAM,MAAM,EAAE,OAAO,GAAG;;;;ACA1C,SAAgB,mCACd,eACA,YACA;CACA,MAAM,QAAoC,IAAI,YAAY,eAAe,EACvE,QAAQ,EAAE,YAAY,EACvB,CAAC;AACF,QAAO,cAAc,MAAM;;;;ACR7B,MAAa,gCAAoD,OAC/D,QACA,eACA,eACA,cACG;AACH,SAAQ,IAAI;EAAE;EAAe;EAAe;EAAW,CAAC;CACxD,MAAM,SAAS,MAAM,QAAQ;AAE7B,KAAI,aAAa,eAAe,yBAAyB,CACvD,QAAO,cAAc,IAAI,YAAY,cAAc,CAAC;AAGtD,KAAI,cAAc,eAAe,iBAAiB,CAChD,oCACE,eACA,+CAA+C,UAAU,CAC1D;AAGH,QAAO;;;;ACHT,SAAgB,4BACd,iBAAiB,yBACjB,UAAU,kBACV;CACA,MAAM,CAAC,SAAS,cAAc,SAAS,MAAM;AAE7C,iBAAgB;AACd,MAAI,QAAS;AAEb,4CAA0C,gBAAgB,QAAQ,CAC/D,WAAW,WAAW,KAAK,CAAC,CAC5B,MAAM,QAAQ,MAAM;IACtB,CAAC,QAAQ,CAAC;AAEb,QAAO;;AAGT,eAAe,yBACb,YACgC;CAChC,MAAM,SAAS,OAAO,IAAI;AAE1B,KAAI,CAAC,OACH,OAAM,IAAI,MACR,iEACD;CAGH,MAAM,SAAS,MAAM,OAAO,YAAY,EAAE,YAAY,CAAC;AAEvD,KAAI,CAAC,OAAO,UAAU,SACpB,OAAM,IAAI,MAAM,oCAAoC,WAAW;AAOjE,QAJc,oBACZ,OAAO,SAAS,UAChB,oBACD;;AAIH,eAAe,wBAAwB,SAAiB;AAGtD,KAAI,CAFW,OAAO,IAAI,qBAGxB,OAAM,IAAI,MACR,iEACD;CAEH,MAAM,QAAQ,MAAM,yBAAyB,QAAQ;AACrD,WAAU,CAAC,MAAM,CAAC;AAClB,kBAAiB,MAAM;;AAGzB,eAAe,0CACb,gBACA,SACA;AACA,KAAI,CAAC,OAAO,GACV,QAAO,KAAK,EAAE;AAGhB,mCAAkC,kCAAkC;AAGpE,yBADe,aAAa,gBAAgB,8BAA8B,CAC3C;AAC/B,OAAM,wBAAwB,QAAQ;AACtC,iBAAgB,KAAA,EAAU;AAC1B,kBAAiB,IAAI,4BAA4B,CAAC;AAElD,SAAQ,2BAA2B,SAAS;AAC1C,SAAO,iBAAiB,YAAY;AAClC,2BAAwB,QAAQ,CAAC,MAAM,QAAQ,MAAM;IACrD;GACF;;;;;ACnFJ,SAAgB,2BAA+C;CAC7D,MAAM,iBAAiB,mBAAmB;CAC1C,MAAM,QAAQ,yBAAyB;AACvC,KAAI,CAAC,kBAAkB,CAAC,MAAO,QAAO,KAAA;AAEtC,QAAO,MAAM,QAAQ,MAAM,EAAE,iBAAiB,eAAe,GAAG;;;AAIlE,SAAgB,+BAAuD;CACrE,MAAM,QAAQ,0BAA0B;AACxC,KAAI,CAAC,MAAO,QAAO,KAAA;AACnB,QAAO,MAAM,QAAQ,MAAM,eAAe,EAAE,CAAC;;;AAI/C,SAAgB,iCAA2D;CACzE,MAAM,QAAQ,0BAA0B;AACxC,KAAI,CAAC,MAAO,QAAO,KAAA;AACnB,QAAO,MAAM,QAAQ,MAAM,iBAAiB,EAAE,CAAC;;;AAIjD,SAAgB,+BAAyD;CACvE,MAAM,YAAY,6BAA6B;CAE/C,MAAM,cADY,8BAA8B,EACjB,KAAK,SAAS,KAAK,GAAG;AACrD,QAAO,WAAW,QAAQ,MAAM,aAAa,SAAS,EAAE,OAAO,GAAG,CAAC;;;;AC1BrE,SAAS,YAAY,SAAiB,MAAwB;AAC5D,QAAO,MAAM,OAAO,UAAU,OAAO,KAAA;;AAGvC,SAAgB,iBAAiB;CAC/B,MAAM,CAAC,iBAAiB,sBAAsB;CAC9C,MAAM,iBAAiB,mBAAmB;CAE1C,MAAM,uBAAuB,cADR,iBAAiB,EACmB,aAAa;CACtE,MAAM,kBAAkB,eAAe,OAAO;CAC9C,MAAM,SAAS,WAAW;CAE1B,eAAe,UAAU,MAAY,QAA0B;AAC7D,MAAI,CAAC,gBAAiB;AAItB,SAAO,QACL,MACA,iBAJe,KAAK,KAAK,QAAQ,WAAW,GAAG,EAM/C,YAAY,iBAAiB,OAAO,EAAE,GACvC;;CAGH,eAAe,YAAY,MAAc,QAA0B;AACjE,MAAI,CAAC,gBAAiB;AAEtB,SAAO,UACL,iBACA,MACA,YAAY,iBAAiB,OAAO,EAAE,GACvC;;CAGH,eAAe,aACb,SACA,MAC2B;AAC3B,MAAI,CAAC,gBAAiB;AAGtB,MAAI,CADiB,YAAY,iBAAiB,KAAK,EACpC;AACjB,WAAQ,MAAM,QAAQ,KAAK,GAAG,YAAY;AAC1C;;AAGF,SAAO,MAAM,WAAW,iBAAiB,KAAK,IAAI,QAAQ;;CAG5D,eAAe,WAAW,KAAW,QAA0B;AAC7D,MAAI,CAAC,gBAAiB;EACtB,MAAM,cAAc,YAAY,iBAAiB,IAAI;AACrD,MAAI,CAAC,aAAa;AAChB,WAAQ,MAAM,QAAQ,IAAI,GAAG,YAAY;AACzC;;AAIF,QAAMC,WAAS,iBAAiB,aAFT,YAAY,iBAAiB,OAAO,CAEC;;CAG9D,eAAe,WAAW,KAAW,QAA0B;AAC7D,MAAI,CAAC,gBAAiB;EAEtB,MAAM,cAAc,YAAY,iBAAiB,IAAI;AACrD,MAAI,CAAC,aAAa;AAChB,WAAQ,MAAM,QAAQ,IAAI,GAAG,YAAY;AACzC;;EAEF,MAAM,iBAAiB,YAAY,iBAAiB,OAAO;AAG3D,MACG,CAAC,gBAAgB,MAAM,CAAC,IAAI,gBAC7B,gBAAgB,OAAO,IAAI,aAE3B;AAEF,QAAMC,WAAS,iBAAiB,aAAa,eAAe;;CAG9D,eAAe,gBAAgB,KAAW;AACxC,MAAI,CAAC,gBAAiB;EAEtB,MAAM,cAAc,YAAY,iBAAiB,IAAI;AACrD,MAAI,CAAC,aAAa;AAChB,WAAQ,MAAM,QAAQ,IAAI,GAAG,YAAY;AACzC;;AAOF,QAAMD,WAAS,iBAAiB,aAJjB,YACb,iBACA,kBAAkB,qBACnB,CACmD;;CAEtD,eAAe,wBAAwB,MAAc;AACnD,MAAI,CAAC,KAAM;AACX,MAAI,CAAC,gBAAiB;EAEtB,MAAM,iBAAiB,YACrB,iBACA,kBAAkB,qBACnB;AACD,MAAI,CAAC,eAAgB;EAErB,MAAM,YAAY,MAAM,YAAY,MAAM,eAAe;AAEzD,MAAI,UACF,iBAAgB,UAAU;;CAI9B,eAAe,mBACb,SACA,QACe;AACf,MAAI,CAAC,OAAQ;EAGb,MAAM,iBAAiB,OAAO,QAAQ,UACpC,MAAM,MAAM,OAAO,MAAM,MAAM,MAAM,EAAE,OAAO,OAAO,CACtD;AAGD,QAAM,QAAQ,IACZ,eAAe,KAAK,UAClB,gBAAgB,MAAM,OAAO,IAAI,QAAQ,QAAQ,CAClD,CACF;;AAGH,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD;;;;;ACzJH,SAAgB,YAAY,IAAiD;AAE3E,QADc,yBAAyB,EACzB,MAAM,MAAM,EAAE,OAAO,GAAG;;;;;ACDxC,SAAgB,gBAAgB,IAA+B;CAC7D,MAAM,QAAQ,yBAAyB;AACvC,KAAI,CAAC,MAAO,QAAO,EAAE;CAErB,MAAM,OAAe,EAAE;CACvB,IAAI,UAAU,MAAM,MAAM,MAAM,EAAE,OAAO,GAAG;AAE5C,QAAO,SAAS;AACd,OAAK,KAAK,QAAQ;AAClB,MAAI,CAAC,QAAQ,aAAc;AAC3B,YAAU,MAAM,MAAM,MAAM,EAAE,OAAO,SAAS,aAAa;;AAG7D,QAAO,KAAK,SAAS;;;AAIvB,SAAgB,sBAAsB;AAEpC,QAAO,gBADc,iBAAiB,EACD,GAAG;;;;ACnB1C,SAAgB,wBACd,IACwB;AAGxB,QADqB,cADR,YAAY,GAAG,EACa,aAAa;;AAIxD,SAAgB,iCAAiC;AAE/C,QAAO,wBADM,iBAAiB,EACO,GAAG;;;;;ACL1C,SAAgB,wBAA4C;CAC1D,MAAM,eAAe,iBAAiB;AACtC,QAAO,gBAAgB,WAAW,aAAa,GAAG,aAAa,KAAK,KAAA;;;AAItE,SAAgB,sBAGd;CAEA,MAAM,CAAC,UAAU,YAAY,gBADF,uBAAuB,CACc;AAChE,KAAI,CAAC,SACH,OAAM,IAAI,yBAAyB;AAErC,QAAO,CAAC,UAAU,SAAS;;;AAI7B,SAAgB,0BAGd;AAEA,QAAO,gBADoB,uBAAuB,CACR;;AAW5C,SAAgB,0BAId,cACkD;CAClD,MAAM,aAAa,uBAAuB;AAE1C,KAAI,CAAC,aACH,QAAO,EAAE;AAEX,KAAI,CAAC,WACH,OAAM,IAAI,yBAAyB;AAErC,QAAO,kBAAsC,YAAY,aAAa;;;;ACxDxE,SAAgB,qBAAmD;AAEjE,QADsB,kBAAkB,CACnB,SAAS,QAAQ,IAAI,aAAa,EAAE,CAAC;;;;ACS5D,SAAgB,gBAAgB,YAAmC;AACjE,KAAI;EACF,MAAM,MAAM,IAAI,IAAI,WAAW;AAC/B,MAAI,WAAW;AACf,MAAI,SAAS;AACb,MAAI,OAAO;AACX,SAAO,IAAI,UAAU;SACf;AACN,SAAO;;;AAIX,MAAM,wBAAQ,IAAI,KAAmC;AAErD,SAAgB,mBACd,OACsB;CACtB,MAAM,UAAU,aAAa;CAC7B,MAAM,UAAU,OAAO,OAAO;CAE9B,MAAM,YAAY,cAAc;AAC9B,MAAI,CAAC,QAAS,QAAO;EAIrB,MAAM,cAHS,QAAQ,MACpB,MAAM,EAAE,iBAAiBE,oBAAkB,QAAQ,QAAQ,CAC7D,EAC2B,UACxB,OAAO;AACX,MAAI,OAAO,eAAe,SAAU,QAAO;AAC3C,SAAO,gBAAgB,WAAW;IACjC,CAAC,SAAS,QAAQ,CAAC;CAEtB,MAAM,CAAC,OAAO,YAAY,eACxB,YACK,MAAM,IAAI,UAAU,IAAI,EAAE,QAAQ,WAAW,GAC9C,EAAE,QAAQ,SAAS,CACxB;AAED,iBAAgB;AACd,MAAI,CAAC,WAAW;AACd,YAAS,EAAE,QAAQ,SAAS,CAAC;AAC7B;;EAGF,MAAM,SAAS,MAAM,IAAI,UAAU;AACnC,MAAI,UAAU,OAAO,WAAW,WAAW;AACzC,YAAS,OAAO;AAChB;;AAGF,WAAS,EAAE,QAAQ,WAAW,CAAC;AAC/B,QAAM,IAAI,WAAW,EAAE,QAAQ,WAAW,CAAC;EAE3C,MAAM,aAAa,IAAI,iBAAiB;AACxC,QAAM,WAAW;GACf,QAAQ;GACR,SAAS,EAAE,gBAAgB,oBAAoB;GAC/C,MAAM,KAAK,UAAU,EAAE,OAAO,kCAAkC,CAAC;GACjE,QAAQ,WAAW;GACpB,CAAC,CACC,KAAK,OAAO,QAAQ;GACnB,MAAM,OAAQ,MAAM,IAAI,MAAM;AAI9B,OAAI,KAAK,QAAQ,OACf,OAAM,IAAI,MAAM,KAAK,OAAO,KAAK,MAAM,EAAE,QAAQ,CAAC,KAAK,KAAK,CAAC;GAE/D,MAAM,MAAM,KAAK,MAAM;AACvB,OAAI,CAAC,IAAK,OAAM,IAAI,MAAM,6BAA6B;GACvD,MAAM,OAA6B;IACjC,QAAQ;IACR,SAAS,IAAI;IACb,SAAS,IAAI;IACb,MAAM,IAAI,IAAI,UAAU,CAAC;IAC1B;AACD,SAAM,IAAI,WAAW,KAAK;AAC1B,YAAS,KAAK;IACd,CACD,OAAO,QAAiB;AACvB,OAAI,WAAW,OAAO,QAAS;GAE/B,MAAM,OAA6B;IAAE,QAAQ;IAAS,SADtC,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;IACD;AAC/D,SAAM,IAAI,WAAW,KAAK;AAC1B,YAAS,KAAK;IACd;AAEJ,eAAa,WAAW,OAAO;IAC9B,CAAC,UAAU,CAAC;AAEf,QAAO;;;;ACvFT,MAAM,iBAAmD;EACtD,WAAW,SAAS;EACpB,WAAW,WAAW;EACtB,WAAW,WAAW;EACtB,WAAW,sBAAsB;EACjC,WAAW,QAAQ;CACrB;AAED,eAAsB,UACpB,SACkC;AAIlC,SAHgB,MAAM,QAAQ,KAAK,EACjC,MAAM,6BACP,CAAC,EACa;;AAGjB,SAAgB,cACd,YACA,aACmC;AACnC,QAAO,QAAQ,QAAQ,kBAAkB,YAAY,YAAY,CAAC;;AAGpE,SAAgB,kBACd,YACA,aAC0B;AAC1B,KAAI,gBAAgB,QAAS;CAE7B,MAAM,cACJ,OAAO,IAAI,qBAAqB,eAAe,YAAY;AAC7D,KAAI,CAAC,YAAa;CAElB,MAAM,SAAS,YAAY,cAAc,WAAW;AACpD,KAAI,WAAW,KAAA,EAAW;AAE1B,QAAO,eAAe;;;;AC1CxB,MAAa,oBAAoB,aAAyB;CACxD,MAAM,SAA4B,EAAE;AAEpC,KAAI,SAAS,OAAO,iBAAiB,4BACnC,QAAO;CAGT,MAAM,MAAM;CACZ,MAAM,QAAQ,IAAI,MAAM,OAAO,eAAe;CAG9C,MAAM,qBAAqB,OAAO,KAAK,MAAM,MAAM,CAAC,QACjD,KAAK,aAAa;EACjB,MAAM,QAAQ;AAEd,SAAO,CACL,GAAG,KACH,GAAG,qBACD,MAAM,MAAM,OAAO,cACnB,UAAU,SACX,CAAC,KAAK,SAAS;GACd,GAAG;GACH,SAAS,GAAG,IAAI,QAAQ,WAAW;GACnC,SAAS;IAAE,GAAG,IAAI;IAAS;IAAO;GACnC,EAAE,CACJ;IAEH,EAAE,CACH;CAGD,MAAM,oBAAoB,OAAO,KAAK,MAAM,MAAM,CAAC,QAChD,KAAK,aAAa;EACjB,MAAM,QAAQ;EACd,MAAM,gBAAgB,UAAU;AAEhC,SAAO,CACL,GAAG,KACH,GAAG,wBACD,MAAM,MAAM,OAAO,QACnB,IAAI,MAAM,QAAQ,QAAQ,IAAI,OAAO,QAAQ,IAC7C,CAAC,gBAAgB,QAAQ,IACzB,CAAC,cACF,CAAC,KAAK,SAAS;GACd,GAAG;GACH,SAAS,GAAG,IAAI,QAAQ,WAAW;GACnC,SAAS;IAAE,GAAG,IAAI;IAAS;IAAO;GACnC,EAAE,CACJ;IAEH,EAAE,CACH;CAGD,MAAM,gBAAgB,gBAAgB,MAAM,QAAQ;AAEpD,QAAO;EAAC,GAAG;EAAoB,GAAG;EAAmB,GAAG;EAAc;;;;AC9DxE,MAAa,kBAAkB,aAA0B;AACvD,KAAI,CAAC,SAAU;AAGf,KAFyB,iBAAiB,SAAS,CAE9B,OACnB,aAAY;EACV,MAAM;EACN,YAAY,SAAS,OAAO;EAC7B,CAAC;KAEF,QAAO,WAAW,SAAS;;;;ACb/B,MAAa,uBACX,WACA,SACA,aAA0B,EAAE,KACzB;AACH,KAAI,CAAC,aAAa,CAAC,QAAS,QAAO;CAEnC,MAAM,YAAY,WAAW,MAAM,cAAc;EAC/C,MAAM,gBAAgB,IAAI,KAAK,UAAU,eAAe;AACxD,SAAO,iBAAiB,aAAa,iBAAiB;GACtD;AAEF,QAAO,YAAY,UAAU,QAAQ;;;;ACXvC,eAAsB,iBAAiB,UAAkB,MAAc;AACrE,KAAI,CAAC,SACH;CAGF,MAAM,WAAW,SAAS,MAAM,IAAI;AACpC,UAAS,KAAK;AACd,UAAS,KAAK;AACd,UAAS,KAAK,SAAS;CACvB,MAAM,YAAY,SAAS,KAAK,IAAI;AAsBpC,SAJc,OAjBC,MAAM,MAAM,WAAW;EACpC,QAAQ;EACR,SAAS,EACP,gBAAgB,oBACjB;EACD,MAAM,KAAK,UAAU;GACnB,OAAO;;;;;GAKP,WAAW,EACT,MACD;GACF,CAAC;EACH,CAAC,EAEyB,MAAM,EAIrB,KAAK;;AAGnB,SAAgB,oBAAoB,UAAkB;AAEpD,QADiB,SAAS,MAAM,IAAI,CACpB,KAAK;;AAGvB,SAAgB,qCAAqC,UAAkB;CACrE,MAAM,WAAW,SAAS,MAAM,IAAI;AACpC,UAAS,KAAK;AACd,UAAS,KAAK;AACd,UAAS,KAAK,UAAU;AACxB,QAAO,SAAS,KAAK,IAAI;;AAG3B,SAAgB,0BAA0B;CACxC,MAAM,MAAM,kCAAkC;AAC9C,KAAI,CAAC,IACH,OAAM,IAAI,MACR,sEACD;AAEH,QAAO,IAAI,OAAO;;AAGpB,SAAgB,2BACd,YACA,WACA;CACA,MAAM,QAAQ,yBAAyB;CACvC,MAAM,YAAY,EAAE,YAAY;CAChC,MAAM,UAAU,YACZ,EACE,eAAe,UAAU,aAC1B,GACD,KAAA;CAEJ,MAAM,UAAkC;EACtC,UAAU,MAAM,MAAM;EACtB,WAAW,KAAK,UAAU,WAAW,MAAM,EAAE;EAC9C;AACD,KAAI,QACF,SAAQ,UAAU,KAAK,UAAU,QAAQ;AAE3C,QAAO,SAAS,8BAA8B,KAAK,UAAU,QAAQ,CAAC;;AAGxE,SAAgB,yBACd,UACA,YACA,WACA;AAEA,QAAO,GAAG,SAAS,oBADE,2BAA2B,YAAY,UAAU;;;;;;;;;;;;;;;AClExE,SAAgB,sBACd,UACgC;CAChC,MAAM,CAAC,SAAS,kBAAkB;CAClC,MAAM,UAAU,aAAa;CAE7B,MAAM,gBAAgB,cAAc;AAClC,SAAO,QAAQ,MACZ,WACC,OAAO,iBAAiBC,oBAAkB,QAAQ,MAAM,OAAO,GAAG,CACrE;IACA,CAAC,SAAS,MAAM,CAAC;CACpB,MAAM,YAAY,cAAc;AAC9B,MAAI;GAMF,MAAM,cALS,QAAQ,MACpB,WACC,OAAO,iBAAiBA,oBAAkB,QAAQ,MAAM,OAAO,GAAG,CACrE,EAE2B,UACxB,OAAO;AACX,OAAI,OAAO,eAAe,SACxB,QAAO;AAGT,UAAO;WACA,OAAO;AACd,WAAQ,MAAM,iCAAiC,MAAM;AACrD,UAAO;;IAER,CAAC,SAAS,MAAM,CAAC;CACpB,MAAM,SAAS,WAAW;CAC1B,MAAM,OAAO,SAAS;AAEtB,QAAO,cAAc;AACnB,MAAI,CAAC,iBAAiB,CAAC,UAAU,OAAO,MAAM,CAAC,UAC7C,QAAO;AAGT,SAAO,YAAY;GAEjB,MAAM,QAAQ,MAAM,UAChB,MAAM,QAAQ,eAAe;IAC3B,WAAW;IACX,KAAK;IACN,CAAC,GACF,KAAA;AAGJ,UAAO,yBAAyB,WAAW,SAAS,OAAO,IAAI,MAAM;;IAEtE;EAAC;EAAe;EAAW;EAAU;EAAM;EAAO,CAAC;;;;AC9DxD,MAAa,iBACX,0BACG;CACH,MAAM,kBAAkB,oBAAoB;CAC5C,MAAM,iBAAiB,mBAAmB;CAC1C,MAAM,gBAAgB,kBAAkB;CAExC,MAAM,aAAa,OACjB,MACA,YACA,oBACG;AACH,MAAI,CAAC,iBAAiB;AACpB,WAAQ,KAAK,qCAAqC;AAClD;;EAGF,MAAM,WAAW,KAAK,KAAK,QAAQ,WAAW,GAAG;EACjD,MAAM,eAAe,gBAAgB;AAGrC,SAAO,MAAM,oBACX,MACA,iBACA,UACA,cACA,YACA,yBAAyB,eACzB,gBACD;;AAGH,QAAO;;;;ACxCT,SAAgB,qBAAqB;CACnC,MAAM,OAAO,SAAS;CACtB,MAAM,YAAY,cAAc;AAChC,KAAI,CAAC,UACH,QAAO;EACL,4BAA4B;EAC5B,0BAA0B;EAC3B;AAGH,QAAO;EACL,4BAA4B,UAAU,SAAS,MAAM,WAAW,GAAG;EACnE,0BAA0B,UAAU,SAAS,MAAM,WAAW,GAAG;EAClE;;;;ACZH,eAAe,mBAAmB,IAAY,QAA+B;AAC3E,OAAM,GAAG,KAAK;;;2BAGW,OAAO;;;;;;;;;;;EAWhC;;AAGF,eAAsB,kBACpB,IACA,SAAiBC,kBACF;AACf,OAAM,mBAAmB,IAAI,OAAO;;AAGtC,eAAsB,sBAAsB,IAA2B;AACrE,OAAM,mBAAmB,IAAIA,iBAAe;AAG5C,OAAM,mBAAmB,IAAI,SAAS;;;;AClBxC,MAAM,4BAA4B;AAClC,MAAM,iCAAiC;AAEvC,eAAe,oBAAoB,SAAyB;AAG1D,WAFe,MAAM,UAAU,QAAQ,CAEtB;;AAGnB,eAAe,0BAA0B,SAAqC;AAC5E,KAAI,CAAC,QAAS;AAGd,YADe,MAAM,QAAQ,KAAK,EAAE,MAAM,6BAA6B,CAAC,EACvD,QAAmC;;AAGtD,SAAS,kCACP,kBAAkB,2BAClB,uBAAuB,gCACvB;CACA,IAAI,UAAgD;CACpD,IAAI,kBAAkB;AAEtB,SAAQ,SAAyB,YAAY,UAAU;EACrD,MAAM,MAAM,KAAK,KAAK;EACtB,MAAM,uBAAuB,MAAM;AAGnC,MAAI,YAAY,KACd,cAAa,QAAQ;AAIvB,MAAI,aAAa,wBAAwB,sBAAsB;AAC7D,qBAAkB;AAClB,UAAO,oBAAoB,QAAQ;;AAIrC,SAAO,IAAI,SAAe,YAAY;AACpC,aAAU,iBAAiB;AACzB,sBAAkB,KAAK,KAAK;AACvB,wBAAoB,QAAQ,CAAC,KAAK,QAAQ;MAC9C,gBAAgB;IACnB;;;AAIN,SAAS,wCACP,kBAAkB,2BAClB,uBAAuB,gCACvB;CACA,IAAI,UAAgD;CACpD,IAAI,kBAAkB;AAEtB,SAAQ,SAAqC,YAAY,UAAU;EACjE,MAAM,MAAM,KAAK,KAAK;EACtB,MAAM,uBAAuB,MAAM;AAGnC,MAAI,YAAY,KACd,cAAa,QAAQ;AAIvB,MAAI,aAAa,wBAAwB,sBAAsB;AAC7D,qBAAkB;AAClB,UAAO,0BAA0B,QAAQ;;AAI3C,SAAO,IAAI,SAAe,YAAY;AACpC,aAAU,iBAAiB;AACzB,sBAAkB,KAAK,KAAK;AACvB,8BAA0B,QAAQ,CAAC,KAAK,QAAQ;MACpD,gBAAgB;IACnB;;;AAIN,MAAa,qBAAqB,mCAAmC;AACrE,MAAa,2BACX,yCAAyC;;;AC1F3C,SAAS,kBAAkB,KAAqB;AAC9C,QAAO,IAAI,SAAS,IAAI,GAAG,IAAI,MAAM,GAAG,GAAG,GAAG;;AAGhD,eAAsB,YAAY,aAAqB;CACrD,MAAM,MAAM,MAAM,MAAM,GAAG,kBAAkB,YAAY,CAAC,WAAW;AACrE,KAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,wBAAwB,IAAI,SAAS;AAElE,QADc,MAAM,IAAI,MAAM;;AAIhC,eAAsB,0BACpB,aACA,cACmB;CACnB,MAAM,cAAc,mBAAmB,aAAa;CACpD,MAAM,MAAM,MAAM,MAChB,GAAG,kBAAkB,YAAY,CAAC,kCAAkC,cACrE;AACD,KAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,wBAAwB,IAAI,SAAS;AAClE,QAAQ,MAAM,IAAI,MAAM;;;;ACtB1B,SAAS,eAAe,QAAwB;AAC9C,QAAO,OAAO,QAAQ,gBAAgB,GAAG;;AAE3C,IAAa,iBAAb,MAA4B;CAC1B;CAEA,YAAY,QAAgB;AAC1B,OAAK,SAAS,eAAe,OAAO;;CAGtC,MAAM,cAAsC;AAE1C,SADa,MAAM,YAAY,KAAK,OAAO;;CAI7C,MAAM,0BAA0B,cAAyC;AACvE,SAAO,MAAM,0BAA0B,KAAK,QAAQ,aAAa;;CAGnE,MAAM,eAAe,OAAuC;EAC1D,MAAM,WAAW,MAAM,KAAK,aAAa;AACzC,MAAI,CAAC,MAAO,QAAO;EACnB,MAAM,aAAa,MAAM,aAAa;AACtC,SAAO,SAAS,QACb,QACC,IAAI,KAAK,aAAa,CAAC,SAAS,WAAW,IAC3C,IAAI,UAAU,aAAa,aAAa,CAAC,SAAS,WAAW,CAChE;;CAGH,UAAU,UAAqD;EAC7D,MAAM,cAAc,IAAI,YAAY,GAAG,KAAK,OAAO,WAAW;AAE9D,cAAY,iBAAiB,YAAY,MAA4B;AAEnE,YADa,KAAK,MAAM,EAAE,KAAK,CACjB;IACd;AAEF,eAAa;AACX,eAAY,OAAO;;;;;;;;;;ACpCzB,IAAa,gBAAb,MAA2B;CACzB,UAAmC,EAAE;;CAGrC,MAAM,QAAgB,YAAoB,aAA2B;AACnE,OAAK,QAAQ,KAAK;GAAE;GAAQ;GAAY;GAAa,CAAC;;;CAIxD,QAAyB;EACvB,MAAM,UAAU,KAAK;AACrB,OAAK,UAAU,EAAE;AACjB,SAAO;;;CAIT,IAAI,QAAgB;AAClB,SAAO,KAAK,QAAQ;;;CAItB,QAAQ,SAAgC;AACtC,OAAK,UAAU,CAAC,GAAG,SAAS,GAAG,KAAK,QAAQ;;;CAI9C,QAAc;AACZ,OAAK,UAAU,EAAE;;;;;;;;ACnBrB,MAAM,oBAAoB;AAE1B,IAAa,eAAb,MAAmD;CACjD;CAEA,YACE,QACA,UACA;AAFiB,OAAA,SAAA;AAGjB,OAAK,WAAW,YAAY;;;CAI9B,MAAM,YACJ,YACA,QACmC;AAKnC,UAJe,MAAM,KAAK,OAAO,YAAY;GAC3C;GACA,MAAM,SAAS,EAAE,QAAQ,GAAG,KAAA;GAC7B,CAAC,EACY,YAAY;;;;;;;;;;CAW5B,MAAM,0BACJ,YACA,QACA,eACA,QACiD;AAEjD,MACE,KAAK,OAAO,kCACZ,UACA,OAAO,SAAS,EAEhB,QAAO,KAAK,+BACV,YACA,QACA,eACA,OACD;EAIH,MAAM,SAAS,MAAM,KAAK,OAAO,0BAA0B;GACzD;GACA,MAAM,SAAS,EAAE,QAAQ,GAAG,KAAA;GAC5B,kBAAkB;IAChB,OAAO,KAAK;IACZ,QAAQ;IACT;GACF,CAAC;AAEF,MAAI,CAAC,OAAO,SAAU,QAAO;EAE7B,MAAM,MAAM,OAAO,SAAS;EAC5B,MAAM,UAAU,IAAI;EACpB,MAAM,oBAAuD,EAAE;AAE/D,MAAI,QACF,MAAK,MAAM,MAAM,QAAQ,MACvB,EAAC,kBAAkB,GAAG,OAAO,WAAW,EAAE,EAAE,KAAK,GAAG;EAKxD,MAAM,gBAAgB,IAAI,cAAc,QACrC,KAAK,MAAM,MAAM,EAAE,UACpB,EACD;AAGD,OAFqB,SAAS,MAAM,UAAU,MAE1B,cAClB,QAAO;GACL,UAAU;GACV,UAAU,OAAO,SAAS;GAC1B,YAAY,EAAE,mBAAmB;GAClC;EAIH,MAAM,YAAY,IAAI,cAAc,KAAK,MAAM,EAAE,MAAM;EACvD,MAAM,SAAS,MAAM,KAAK,iBACxB,IAAI,IACJ,QACA,eACA,UACD;AAED,SAAO;GACL,UAAU;GACV,UAAU,OAAO,SAAS;GAC1B,YAAY;GACb;;;;;;CAOH,MAAc,+BACZ,YACA,QACA,eACA,QACiD;EACjD,MAAM,OAAO,SAAS,EAAE,QAAQ,GAAG,KAAA;EACnC,MAAM,UAAU,OAAO,KAAK,WAAW;GACrC,YAAY;GACZ,QAAQ,UAAU;GAClB,eAAe,gBAAgB,UAAU;GACzC,QAAQ,CAAC,MAAM;GAChB,EAAE;EACH,MAAM,UAAU,OAAO,WAAW;GAChC,OAAO,KAAK;GACZ,QAAQ;GACT,EAAE;EAEH,MAAM,SAAS,MAAM,KAAK,OAAO,+BAC/B,YACA,MACA,SACA,QACD;AAED,MAAI,CAAC,OAAO,SAAU,QAAO;EAE7B,MAAM,oBAAuD,EAAE;EAC/D,IAAI,UAIE,EAAE;AAER,OAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;GACtC,MAAM,OAAO,OAAO,WAAW;AAC/B,QAAK,MAAM,MAAM,KAAK,MACpB,EAAC,kBAAkB,GAAG,OAAO,WAAW,EAAE,EAAE,KAAK,GAAG;AAEtD,OAAI,KAAK,eAAe,KAAK,OAC3B,SAAQ,KAAK;IACX,OAAO,OAAO;IACd,QAAQ,QAAQ;IAChB,QAAQ,KAAK;IACd,CAAC;;AAKN,SAAO,QAAQ,SAAS,GAAG;GACzB,MAAM,QAAQ,MAAM,KAAK,oBACvB,QAAQ,KAAK,MAAM,EAAE,OAAO,EAC5B,QAAQ,KAAK,OAAO;IAAE,OAAO,KAAK;IAAU,QAAQ,EAAE;IAAQ,EAAE,CACjE;GAED,MAAM,cAA8B,EAAE;AACtC,QAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;IACvC,MAAM,OAAO,MAAM;AACnB,SAAK,MAAM,MAAM,KAAK,MACpB,EAAC,kBAAkB,GAAG,OAAO,WAAW,EAAE,EAAE,KAAK,GAAG;AAEtD,QAAI,KAAK,eAAe,KAAK,OAC3B,aAAY,KAAK;KAAE,GAAG,QAAQ;KAAI,QAAQ,KAAK;KAAQ,CAAC;;AAG5D,aAAU;;AAGZ,SAAO;GACL,UAAU,OAAO,SAAS;GAC1B,UAAU,OAAO,SAAS;GAC1B,YAAY,EAAE,mBAAmB;GAClC;;;;;;;CAQH,MAAM,iBACJ,YACA,QACA,eACA,QAC8B;AAG9B,MAAI,UAAU,OAAO,SAAS,GAAG;GAC/B,MAAM,oBAAuD,EAAE;GAG/D,IAAI,UAAU,OAAO,KAAK,WAAW;IACnC;IACA,QAAQ;KACN;KACA,QAAQ,UAAU;KAClB,eAAe,gBAAgB,UAAU;KACzC,QAAQ,CAAC,MAAM;KAChB;IACD,QAAQ;IACT,EAAE;AAEH,UAAO,QAAQ,SAAS,GAAG;IACzB,MAAM,QAAQ,MAAM,KAAK,oBACvB,QAAQ,KAAK,MAAM,EAAE,OAAO,EAC5B,QAAQ,KAAK,OAAO;KAAE,OAAO,KAAK;KAAU,QAAQ,EAAE;KAAQ,EAAE,CACjE;IAED,MAAM,cAA8B,EAAE;AAEtC,SAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;KACvC,MAAM,OAAO,MAAM;AACnB,UAAK,MAAM,MAAM,KAAK,MACpB,EAAC,kBAAkB,GAAG,OAAO,WAAW,EAAE,EAAE,KAAK,GAAG;AAEtD,SAAI,KAAK,eAAe,KAAK,OAC3B,aAAY,KAAK;MAAE,GAAG,QAAQ;MAAI,QAAQ,KAAK;MAAQ,CAAC;;AAI5D,cAAU;;AAGZ,UAAO,EAAE,mBAAmB;;AAI9B,SAAO,KAAK,wBAAwB,YAAY,OAAO;;;;;;;CAQzD,MAAc,oBACZ,SAGA,SAGsC;AACtC,MAAI,KAAK,OAAO,2BACd,QAAO,KAAK,OAAO,2BAA2B,SAAS,QAAQ;AAGjE,SAAO,QAAQ,IACb,QAAQ,KAAK,QAAQ,MACnB,KAAK,OACF,sBAAsB;GAAE;GAAQ,QAAQ,QAAQ;GAAI,CAAC,CACrD,MAAM,MAAM,EAAE,mBAAmB,CACrC,CACF;;;CAIH,MAAc,wBACZ,YACA,QACA,eACA,OAC8B;EAC9B,MAAM,oBAAuD,EAAE;EAC/D,IAAI;EACJ,IAAI,cAAc;AAElB,SAAO,aAAa;GAclB,MAAM,QAbS,MAAM,KAAK,OAAO,sBAAsB;IACrD,QAAQ;KACN;KACA,QAAQ,UAAU;KAClB,eAAe,iBAAiB;KAChC,QAAQ,QAAQ,CAAC,MAAM,GAAG;KAC3B;IACD,QAAQ;KACN,OAAO,KAAK;KACZ,QAAQ,UAAU;KACnB;IACF,CAAC,EAEkB;AAEpB,QAAK,MAAM,MAAM,KAAK,OAAO;IAC3B,MAAM,IAAI,GAAG,OAAO;AACpB,KAAC,kBAAkB,OAAO,EAAE,EAAE,KAAK,GAAG;;AAGxC,iBAAc,KAAK;AACnB,YAAS,KAAK;;AAGhB,SAAO,EAAE,mBAAmB;;;CAI9B,MAAM,YACJ,oBACA,SACA,QAC6B;AAM7B,UALe,MAAM,KAAK,OAAO,eAAe;GAC9C;GACA;GACA,MAAM,SAAS,EAAE,QAAQ,GAAG,KAAA;GAC7B,CAAC,EACY;;;CAIhB,MAAM,eACJ,UACA,kBAC6B;AAK7B,UAJe,MAAM,KAAK,OAAO,eAAe;GAC9C;GACA,kBAAkB,oBAAoB;GACvC,CAAC,EACY;;;CAIhB,MAAM,oBACJ,cACA,kBAC6B;AAK7B,UAJe,MAAM,KAAK,OAAO,oBAAoB;GACnD;GACA,kBAAkB,oBAAoB;GACvC,CAAC,EACY;;;CAIhB,MAAM,eACJ,YACA,WACkB;AAKlB,UAJe,MAAM,KAAK,OAAO,eAAe;GAC9C;GACA;GACD,CAAC,EACY;;;;;;AClWlB,SAAgB,sBAAsB,GAAmB;AACvD,QAAO,EACJ,aAAa,CACb,QAAQ,cAAc,GAAG,MAAc,EAAE,aAAa,CAAC;;;AAI5D,IAAa,gBAAb,cAAmC,MAAM;CACvC,YAAY,UAAwC;AAClD,QAAM,2DAA2D;AADvC,OAAA,WAAA;AAE1B,OAAK,OAAO;;;;AAKhB,SAAgB,uBAAuB,QAAoC;AACzE,QAAO;EACL,IAAI,OAAO,MAAM;EACjB,OAAO,OAAO;EACd,MAAM,OAAO;EACb,gBAAgB,OAAO;EACvB,MAAM,OAAO;EACb,OAAO,OAAO,SAAS,KAAA;EACvB,QAAQ;GACN,IAAI,OAAO,OAAO;GAClB,MAAM,OAAO,OAAO;GACpB,gBAAgB,OAAO,OAAO;GAC9B,OAAO,OAAO,OAAO;GACrB,OAAO,OAAO,OAAO;GACrB,aAAa,OAAO,OAAO,aAAa,KAAK,OAAO;IAClD,MAAM,EAAE;IACR,UAAU,EAAE;IACZ,MAAM,EAAE;IACR,WAAW,EAAE,aAAa,KAAA;IAC1B,UAAU,EAAE,YAAY,KAAA;IACzB,EAAE;GACH,SAAS,OAAO,OAAO,SAAS,SAC5B,EACE,QAAQ;IACN,MAAM,OAAO,OAAO,QAAQ,OAAO,QAAQ;KACzC,SAAS;KACT,WAAW;KACX,SAAS;KACV;IACD,KAAK,OAAO,OAAO,QAAQ,OAAO,OAAO;KACvC,MAAM;KACN,KAAK;KACN;IACD,YAAY,OAAO,OAAO,QAAQ,OAAO,WAAW,KAAK,MACvD,qBAAqB,EAAE,CACxB;IACF,EACF,GACD,KAAA;GACL;EACF;;;;;;AAOH,SAAgB,qBACd,GAC0C;CAC1C,MAAM,QAAQ,EAAE,MAAM,KAAK;AAC3B,QAAO;EACL,MAAM,MAAM;EACZ,MAAM,MAAM;EACZ,MAAM,MAAM;EACZ,MAAM,MAAM;EACZ,MAAM,MAAM;EACb;;;AAIH,SAAgB,wBACd,mBACoB;CACpB,MAAM,aAAiC,EAAE;AACzC,MAAK,MAAM,CAAC,OAAO,cAAc,OAAO,QAAQ,kBAAkB,CAChE,YAAW,SAAS,UAAU,KAAK,OAAO,uBAAuB,GAAG,CAAC;AAEvE,QAAO;;;AAIT,SAAgB,oBACd,WACA,YACA,YACA,QACyB;AACzB,QAAO;EACL,QAAQ;GACN,GAAG,WAAW;GACd,IAAI,UAAU;GACd,MAAM,UAAU;GAChB,MAAM,UAAU,QAAQ;GACxB,cAAc,UAAU;GACxB,iBACE,OAAO,UAAU,oBAAoB,WACjC,UAAU,kBACV,UAAU,gBAAgB,aAAa;GAC7C,sBACE,OAAO,UAAU,yBAAyB,WACtC,UAAU,uBACV,UAAU,qBAAqB,aAAa;GAClD,UAAU,OAAO,YACf,UAAU,cAAc,KAAK,MAAM,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,CAC1D;GACD;GACD;EACD,OAAO,UAAU;EACjB,cAAc,WAAW;EACzB;EACA,WAAW,EAAE;EACd;;;AAIH,SAAgB,mBACd,eACwB;AACxB,QAAO,OAAO,YAAY,cAAc,KAAK,MAAM,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;;;;;;AAO5E,SAAgB,oBACd,iBACA,eACA,QACS;AACT,MAAK,MAAM,SAAS,iBAAiB;AACnC,MAAI,UAAU,CAAC,OAAO,IAAI,MAAM,CAAE;AAClC,OAAK,gBAAgB,UAAU,MAAM,cAAc,UAAU,GAC3D,QAAO;;AAGX,QAAO;;;;;;;;AClGT,IAAa,2BAAb,MAAa,yBAE2C;CACtD;CACA;CACA,UAA2B,IAAI,eAAe;CAC9C;CACA;CACA,iBAAiD,EAAE;CACnD,YAAoB;CACpB,gBAAwB;CACxB,YAAmC,QAAQ,SAAS;CACpD,YAA8C,EAAE;CAEhD,YAAoB,OAAoB,SAAkC;AACxE,OAAK,QAAQ;AACb,OAAK,UAAU;AACf,OAAK,aAAa,QAAQ,cAAc;AACxC,OAAK,eAAe,IAAI,aACtB,QAAQ,QACR,QAAQ,mBACT;AAED,OAAK,yBAAyB;;CAKhC,IAAI,SAA2B;AAC7B,SAAO,KAAK,MAAM;;CAGpB,IAAI,QAAiC;AACnC,SAAO,KAAK,MAAM;;CAGpB,IAAI,aAAiC;AACnC,SAAO,KAAK,MAAM;;CAGpB,IAAI,WAAgD;AAClD,SAAO,KAAK,MAAM;;CAGpB,IAAI,SAAqB;AACvB,SAAO;GACL,oBAAoB,KAAK,QAAQ;GACjC,WAAW,KAAK,eAAe;GAC/B,YAAY,KAAK;GACjB,gBAAgB,EAAE,GAAG,KAAK,gBAAgB;GAC3C;;;CAIH,SAAS,UAA8C;AACrD,OAAK,UAAU,KAAK,SAAS;AAC7B,eAAa;AACX,QAAK,YAAY,KAAK,UAAU,QAAQ,MAAM,MAAM,SAAS;;;CAIjE,gBAAwB,QAAmD;AACzE,MAAI,KAAK,UAAU,WAAW,EAAG;EACjC,MAAM,QAAmC;GACvC;GACA,UAAU,KAAK;GAChB;AACD,OAAK,MAAM,YAAY,KAAK,UAC1B,UAAS,MAAM;;;CAOnB,MAAM,OAA4B;EAChC,IAAI,UAAU,KAAK,QAAQ,OAAO;AAElC,MAAI,QAAQ,WAAW,KAAK,KAAK,eAAe,GAG9C,QAAO;GACL,gBAFqB,MAAM,KAAK,MAAM;GAGtC,aAAa;GACb,YAAY,EAAE;GACf;AAGH,MAAI;AACF,SAAM,KAAK,sBAAsB;AAGjC,OAAI,KAAK,QAAQ,cAAc,QAAQ,SAAS,EAC9C,WAAU,MAAM,KAAK,gBAAgB,SAAS,KAAK,QAAQ,WAAW;WAEjE,OAAO;AAEd,QAAK,QAAQ,QAAQ,QAAQ;AAC7B,SAAM;;EAGR,IAAI,gBAA0B,EAAE;AAEhC,MAAI;AACF,OAAI,QAAQ,SAAS,GAAG;IACtB,MAAM,UAAU,MAAM,KAAK,sBAAsB,QAAQ;AACzD,oBAAgB;AAEhB,UAAM,KAAK,aAAa,YACtB,KAAK,YACL,SACA,KAAK,QAAQ,OACd;;WAEI,OAAO;AAEd,QAAK,QAAQ,QAAQ,QAAQ;AAC7B,SAAM;;AAOR,SAAO;GACL,gBAHqB,MAAM,KAAK,MAAM;GAItC,aAAa,QAAQ;GACrB,YAAY;GACb;;;CAIH,MAAM,OAAO,WAA+C;AAC1D,MAAI,KAAK,eAAe,GACtB,OAAM,IAAI,MAAM,oCAAoC;AAMtD,SAJe,MAAM,KAAK,aAAa,eACrC,KAAK,YACL,UACD;;;CAKH,MAAM,OAAoC;AACxC,MAAI,KAAK,eAAe,GACtB,OAAM,IAAI,MAAM,kCAAkC;EAGpD,MAAM,EAAE,WAAW,eAAe,MAAM,KAAK,4BAA4B;EAIzE,MAAM,iBAAiB,oBACrB,WACA,YAHiB,KAAK,MAAM,OAAO,MAAM,gBAAgB,EAKzD,KAAK,QAAQ,UAAU,OACxB;EAGD,MAAM,kBAAkB,KAAK,MAAM;AAGnC,OAAK,QAAQ,IAAI,gBAAgB,eAAe;AAGhD,OAAK,yBAAyB;AAG9B,OAAK,QAAQ,OAAO;AAGpB,OAAK,iBAAiB,mBAAmB,UAAU,cAAc;AAEjE,OAAK,gBAAgB,OAAO;AAE5B,SAAO;;;;;CAQT,aAAa,KACX,iBACA,SAC0C;EAG1C,MAAM,SAAS,IAAI,yBADN,IAAI,iBAAiB,EACgB,QAAQ;AAE1D,MAAI,QAAQ,WACV,OAAM,OAAO,MAAM;AAGrB,SAAO;;;;;;;CAQT,OAAO,KACL,YACA,SACiC;AACjC,SAAO,IAAI,yBACT,YACA,QACD;;;CAMH,MAAc,uBAAsC;AAClD,MAAI,KAAK,eAAe,GAAI;AAK5B,OAAK,cAJa,MAAM,KAAK,aAAa,oBACxC,KAAK,MAAM,OAAO,cAClB,KAAK,QAAQ,iBACd,EAC2B;;;CAI9B,0BAAwC;EAEtC,MAAM,SAAU,KAAK,MAAkC;AAIvD,OAAK,MAAM,cAAc,OAAO,SAAS;AAEvC,OAAI,cAAc,yBAAyB,UACzC;AAGF,UAAO,eAAe,MAAM,YAAY;IACtC,QAAQ,UAAmB;KAEzB,MAAM,iBAAyC,EAAE;AACjD,UAAK,MAAM,SAAS,KAAK,MAAM,WAC7B,gBAAe,SAAS,KAAK,MAAM,WAAW,OAAO;AAKrD,UAAK,MACL,YAAY,MAAM;KAGpB,MAAM,QAAQ,KAAK,iBAAiB,eAAe;KAGnD,MAAM,SAAS,QACX,KAAK,wBAAwB,MAAM,OAAO,OAAO,MAAM,GACvD,KAAA;KACJ,MAAM,aAAa,QAAQ,QAAQ;KACnC,MAAM,cAAc,QAAQ,SAAS;AAErC,SAAI,CAAC,MAEH,QAAO;AAIT,UAAK,QAAQ,MAAM,MAAM,QAAQ,YAAY,YAAY;AACzD,UAAK,gBAAgB,SAAS;AAE9B,SAAI,KAAK,QAAQ,SAAS,YACxB,MAAK,cAAc;AAGrB,YAAO;;IAET,YAAY;IACZ,cAAc;IACf,CAAC;;;;;;;CAQN,iBACE,gBACuB;EACvB,MAAM,MAAM,KAAK,MAAM;AACvB,OAAK,MAAM,SAAS,KAAK;GACvB,MAAM,WAAW,IAAI;GACrB,MAAM,YAAY,eAAe,UAAU;AAC3C,OAAI,SAAS,SAAS,UACpB,QAAO,SAAS,SAAS,SAAS;;;;;;;CAUxC,wBACE,OACA,WACuB;EACvB,MAAM,WAAW,KAAK,MAAM,WAAW;AACvC,MAAI,SAAS,WAAW,EAAG,QAAO,KAAA;AAClC,OAAK,IAAI,IAAI,SAAS,SAAS,GAAG,KAAK,GAAG,IACxC,KAAI,SAAS,OAAO,UAAW,QAAO,SAAS;;;;;;CASnD,MAAc,gBACZ,cACA,UAC0B;EAE1B,MAAM,eAAe,MAAM,KAAK,aAAa,YAC3C,KAAK,YACL,KAAK,QAAQ,OACd;AACD,MAAI,CAAC,aACH,OAAM,IAAI,MAAM,aAAa,KAAK,WAAW,uBAAuB;EAGtE,MAAM,kBAAkB,mBACtB,aAAa,SAAS,cACvB;EAGD,MAAM,cAAc,IAAI,IAAI,aAAa,KAAK,MAAM,EAAE,OAAO,MAAM,CAAC;AAEpE,MACE,CAAC,oBAAoB,iBAAiB,KAAK,gBAAgB,YAAY,CAEvE,QAAO;EAKT,MAAM,oBAAoB,CAAC,GAAG,YAAY,CAAC,QACxC,WACE,gBAAgB,UAAU,MAAM,KAAK,eAAe,UAAU,GAClE;EACD,MAAM,EAAE,sBAAsB,MAAM,KAAK,aAAa,iBACpD,KAAK,YACL,KAAK,QAAQ,QACb,KAAK,gBACL,kBACD;EACD,MAAM,mBAAsD,EAAE;AAC9D,OAAK,MAAM,CAAC,OAAO,QAAQ,OAAO,QAAQ,kBAAkB,CAC1D,kBAAiB,SAAS;EAG5B,MAAM,eAAe;GACnB;GACA,cAAc;GACd,eAAe,EAAE,GAAG,KAAK,gBAAgB;GACzC,iBAAiB,EAAE,GAAG,iBAAiB;GACxC;AAED,MAAI,aAAa,SACf,OAAM,IAAI,cAAc,aAAa;AAGvC,MAAI,aAAa,SACf,QAAO,KAAK,cAAc,aAAa,KAAK,MAAM,EAAE,OAAO,CAAC;EAI9D,MAAM,gBAAgB,MAAM,SAAS,aAAa;AAClD,SAAO,KAAK,cAAc,cAAc;;;;;;CAO1C,MAAc,cAAc,SAA6C;AACvE,QAAM,KAAK,MAAM;AAEjB,OAAK,MAAM,UAAU,SAAS;GAE5B,MAAM,aAAa,sBAAsB,OAAO,KAAK;GACrD,MAAM,SACJ,KACA;AACF,OAAI,OAAO,WAAW,WACpB,QAAO,KAAK,MAAM,OAAO,MAAM;;AAInC,SAAO,KAAK,QAAQ,OAAO;;;CAI7B,MAAc,sBACZ,SACA;EACA,MAAM,UAAoB,EAAE;AAE5B,OAAK,MAAM,EAAE,QAAQ,YAAY,iBAAiB,SAAS;GACzD,IAAI,WAAmB;IACrB,GAAG;IACH,SAAS;KACP,GAAG,OAAO;KACV;KACA;KACD;IACF;AAED,OAAI,KAAK,QAAQ,OACf,YAAW,MAAM,KAAK,WAAW,SAAS;AAG5C,WAAQ,KAAK,SAAS;;AAGxB,SAAO;;;CAIT,MAAc,WAAW,QAAiC;EACxD,MAAM,SAAS,KAAK,QAAQ;EAC5B,MAAM,YAAY,MAAM,OAAO,WAAW,OAAO;EACjD,MAAM,qBAAqB,OAAO,SAAS,QAAQ,cAAc,EAAE;AACnE,SAAO;GACL,GAAG;GACH,SAAS;IACP,GAAG,OAAO;IACV,QAAQ;KACN,MAAM,OAAO;KACb,KAAK,OAAO;KACZ,YAAY,CAAC,GAAG,oBAAoB,UAAU;KAC/C;IACF;GACF;;;;;;;;;;CAWH,MAAc,6BAGX;AAED,MAAI,KAAK,UACP,QAAO,KAAK,kBAAkB;EAIhC,MAAM,SAAS,MAAM,KAAK,aAAa,0BACrC,KAAK,YACL,KAAK,QAAQ,OACd;AAED,MAAI,CAAC,OACH,OAAM,IAAI,MAAM,aAAa,KAAK,WAAW,uBAAuB;AAGtE,OAAK,YAAY;AACjB,SAAO;GACL,WAAW,OAAO;GAClB,YAAY,wBAAwB,OAAO,WAAW,kBAAkB;GACzE;;;;;;;CAQH,MAAc,mBAGX;EACD,MAAM,SAAS,OAAO,KAAK,KAAK,eAAe;EAE/C,MAAM,SAAS,MAAM,KAAK,aAAa,0BACrC,KAAK,YACL,KAAK,QAAQ,QACb,KAAK,gBACL,OAAO,SAAS,IAAI,SAAS,KAAA,EAC9B;AAED,MAAI,CAAC,OACH,OAAM,IAAI,MAAM,aAAa,KAAK,WAAW,uBAAuB;EAGtE,MAAM,YAAY,OAAO;EACzB,MAAM,mBAAmB,mBAAmB,UAAU,cAAc;EAEpE,MAAM,SAAS,wBAAwB,OAAO,WAAW,kBAAkB;EAC3E,MAAM,SAAS,KAAK,gBAAgB,KAAK,MAAM,YAAY,OAAO;AAGlE,MAAI,KAAK,2BAA2B,QAAQ,iBAAiB,CAC3D,QAAO;GAAE;GAAW,YAAY;GAAQ;AAI1C,SAAO,KAAK,UAAU,UAAU;;;;;;CAOlC,MAAc,UAAU,WAGrB;EACD,MAAM,EAAE,sBAAsB,MAAM,KAAK,aAAa,iBACpD,KAAK,YACL,KAAK,QAAQ,OACd;AAED,SAAO;GACL;GACA,YAAY,wBAAwB,kBAAkB;GACvD;;;;;;CAOH,2BACE,YACA,kBACS;AACT,OAAK,MAAM,CAAC,OAAO,aAAa,OAAO,QAAQ,iBAAiB,CAE9D,MADgB,SAAS,aAAa,WAAW,OAAO,SAAS,OACjD,SACd,QAAO;AAGX,SAAO;;;;;;CAOT,gBACE,aACA,QACoB;EACpB,MAAM,SAA6B,EAAE;AAGrC,OAAK,MAAM,CAAC,OAAO,QAAQ,OAAO,QAAQ,YAAY,CACpD,KAAI,IAAI,SAAS,EACf,QAAO,SAAS,CAAC,GAAG,IAAI;AAK5B,OAAK,MAAM,CAAC,OAAO,QAAQ,OAAO,QAAQ,OAAO,CAC/C,KAAI,IAAI,SAAS,EACf,EAAC,OAAO,WAAW,EAAE,EAAE,KAAK,GAAG,IAAI;AAIvC,SAAO;;;CAIT,eAA6B;AAC3B,MAAI,KAAK,cAAe;AACxB,OAAK,gBAAgB;AACrB,uBAAqB;AACnB,QAAK,gBAAgB;AAErB,QAAK,YAAY,KAAK,UAAU,KAAK,YAAY;AAC/C,QAAI;AACF,WAAM,KAAK,MAAM;aACV,OAAgB;AAEvB,UAAK,QAAQ,cAAc,MAAM;;KAEnC;IACF;;;;;AChpBN,IAAsB,cAAtB,MAAsE;CAUpE,CAAC,OAAO,YAA2C;AACjD,SAAO,KAAK,SAAS;;CAGvB,QACE,UACM;AACN,OAAK,MAAM,CAAC,KAAK,UAAU,KACzB,UAAS,OAAO,KAAK,KAAK;;;;;AChBhC,IAAa,sBAAb,cAA4C,YAAe;CACzD;CACA,WAAW,OAAO;CAClB,YAAY,WAAmB;AAC7B,SAAO;AACP,QAAA,YAAkB;;CAGpB,WAA2B;EACzB,MAAM,MAAM,MAAA,QAAc,QAAQ,MAAA,UAAgB;AAElD,MAAI,CAAC,IACH,wBAAO,IAAI,KAAK;AAGlB,SAAO,IAAI,IAAI,KAAK,MAAM,IAAI,CAAkB;;CAGlD,UAAU,KAA2B;AACnC,QAAA,QAAc,QACZ,MAAA,WACA,KAAK,UAAU,MAAM,KAAK,IAAI,SAAS,CAAC,CAAC,CAC1C;;CAGH,IAAI,KAA4B;AAC9B,SAAO,MAAA,SAAe,CAAC,IAAI,IAAI;;CAGjC,IAAI,KAAa,OAAgB;EAC/B,MAAM,MAAM,MAAA,SAAe;AAC3B,MAAI,IAAI,KAAK,MAAM;AACnB,QAAA,SAAe,IAAI;;CAGrB,OAAO,KAAsB;EAC3B,MAAM,MAAM,MAAA,SAAe;EAC3B,MAAM,UAAU,IAAI,OAAO,IAAI;AAC/B,MAAI,QACF,OAAA,SAAe,IAAI;AAErB,SAAO;;CAGT,IAAI,KAAsB;AACxB,SAAO,MAAA,SAAe,CAAC,IAAI,IAAI;;CAGjC,QAAc;AACZ,QAAA,QAAc,WAAW,MAAA,UAAgB;;CAG3C,UAAyC;AACvC,SAAO,MAAA,SAAe,CAAC,SAAS;;CAGlC,OAAiC;AAC/B,SAAO,MAAA,SAAe,CAAC,MAAM;;CAG/B,SAA8B;AAC5B,SAAO,MAAA,SAAe,CAAC,QAAQ;;CAGjC,CAAC,OAAO,YAA2C;AACjD,SAAO,MAAA,SAAe,CAAC,SAAS"}
1
+ {"version":3,"file":"index.js","names":["baseAddFolder","moveNode","baseMoveNode","copyNode","baseCopyNode","driveCollectionId","copyNode","moveNode","driveCollectionId","driveCollectionId","REACTOR_SCHEMA","#namespace","#storage","#readMap","#writeMap"],"sources":["../src/errors.ts","../src/utils/documents.ts","../src/utils/user.ts","../src/actions/document.ts","../src/actions/drive.ts","../src/constants.ts","../src/document-model.ts","../src/graphql/adapters.ts","../src/graphql/constants.ts","../src/graphql/fetchers.ts","../src/graphql/batch.ts","../src/graphql/document-fetcher.ts","../src/graphql/graphql-client-document-cache.ts","../src/graphql/mutators.ts","../src/hooks/config/editor.ts","../src/hooks/config/connect.ts","../src/hooks/features.ts","../src/hooks/drives.ts","../src/hooks/graphql-reactor-client.ts","../src/hooks/modals.ts","../src/hooks/package-discovery.ts","../src/hooks/reactor.ts","../src/hooks/revision-history.ts","../src/utils/url.ts","../src/hooks/selected-drive.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/hooks/document-model-modules.ts","../src/hooks/allowed-document-model-modules.ts","../src/hooks/selected-folder.ts","../src/hooks/child-nodes.ts","../src/hooks/config/set-config-by-key.ts","../src/hooks/config/utils.ts","../src/hooks/config/set-config-by-object.ts","../src/hooks/config/use-value-by-key.ts","../src/hooks/connection-state.ts","../src/hooks/document-of-type.ts","../src/hooks/document-operations.ts","../src/hooks/supported-document-types.ts","../src/hooks/document-types.ts","../src/hooks/drive-by-id.ts","../src/hooks/editor-modules.ts","../src/hooks/folder-by-id.ts","../src/graphql/events.ts","../src/graphql/document-cache-client-middleware.ts","../src/hooks/init-graphql-reactor-client.ts","../src/hooks/items-in-selected-folder.ts","../src/hooks/node-actions.ts","../src/hooks/node-by-id.ts","../src/hooks/node-path.ts","../src/hooks/parent-folder.ts","../src/hooks/selected-document.ts","../src/hooks/subgraph-modules.ts","../src/hooks/use-drive-system-info.ts","../src/utils/drives.ts","../src/utils/validate-document.ts","../src/utils/export-document.ts","../src/utils/get-revision-from-date.ts","../src/utils/switchboard.ts","../src/hooks/use-get-switchboard-link.ts","../src/hooks/use-on-drop-file.ts","../src/hooks/user-permissions.ts","../src/pglite/drop.ts","../src/reactor.ts","../src/registry/fetchers.ts","../src/registry/client.ts","../src/remote-controller/action-tracker.ts","../src/remote-controller/remote-client.ts","../src/remote-controller/utils.ts","../src/remote-controller/remote-controller.ts","../src/storage/base-storage.ts","../src/storage/local-storage.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","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} 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} from \"@powerhousedao/shared/document-model\";\nimport {\n baseLoadFromInput,\n baseSaveToFileHandle,\n createPresignedHeader,\n createZip,\n documentModelDocumentType,\n generateId,\n replayDocument,\n setName,\n} from \"@powerhousedao/shared/document-model\";\nimport { logger } from \"document-model\";\nimport {\n DocumentModelNotFoundError,\n UnsupportedDocumentTypeError,\n} from \"../errors.js\";\nimport { isDocumentTypeSupported } from \"../utils/documents.js\";\nimport { getUserPermissions } from \"../utils/user.js\";\nimport { queueActions, queueOperations, uploadOperations } from \"./queue.js\";\n\nconst BASE_STATE_KEYS = new Set([\"auth\"]);\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 const zip = await createZip(document);\n zip\n .generateAsync({ type: \"blob\" })\n .then((blob) => {\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 })\n .catch(logger.error);\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 const reactorClient = window.ph?.reactorClient;\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: IReactorClient,\n document: PHDocument,\n pageSize = 100,\n): Promise<DocumentOperations> {\n const scopes = Object.keys(document.state).filter(\n (k) => !BASE_STATE_KEYS.has(k),\n );\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\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\nexport async function loadFile(path: string | File) {\n const baseDocument = await baseLoadFromInput(\n path,\n (state: PHDocument) => state,\n { checkHashes: true },\n );\n\n const reactorClient = window.ph?.reactorClient;\n if (!reactorClient) {\n throw new Error(\"ReactorClient not initialized\");\n }\n const { results: documentModelModules } =\n await reactorClient.getDocumentModelModules();\n const documentModelModule = documentModelModules.find(\n (module) =>\n module.documentModel.global.id === baseDocument.header.documentType,\n );\n if (!documentModelModule) {\n throw new DocumentModelNotFoundError(baseDocument.header.documentType);\n }\n return documentModelModule.utils.loadFromInput(path);\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) {\n const { isAllowedToCreateDocuments } = getUserPermissions();\n if (!isAllowedToCreateDocuments) {\n throw new Error(\"User is not allowed to create documents\");\n }\n\n const reactorClient = window.ph?.reactorClient;\n if (!reactorClient) {\n throw new Error(\"ReactorClient not initialized\");\n }\n\n // get the module\n const documentModelModule =\n await reactorClient.getDocumentModelModule(documentType);\n\n // create - use passed document's state if available\n const newDocument = document ?? documentModelModule.utils.createDocument();\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\", e);\n throw new Error(\"There was an error adding document\");\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 (exclude document-scope ops —\n // the reactor already generated CREATE_DOCUMENT + UPGRADE_DOCUMENT above)\n await uploadOperations(\n documentId,\n filterDomainOperations(document.operations),\n queueOperations,\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 const reactor = window.ph?.reactorClient;\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 // 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 // Handle replace resolution by deleting the existing document\n if (\n duplicateCheck.isDuplicate &&\n resolveConflict === \"replace\" &&\n duplicateCheck.nodeId\n ) {\n await deleteNode(driveId, duplicateCheck.nodeId);\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 // Uploading stage (20-100%)\n await uploadOperations(\n documentId,\n filterDomainOperations(document.operations),\n queueOperations,\n {\n onProgress: (uploadProgress) => {\n if (\n uploadProgress.totalOperations &&\n uploadProgress.uploadedOperations !== undefined\n ) {\n const uploadPercent =\n uploadProgress.totalOperations > 0\n ? uploadProgress.uploadedOperations /\n uploadProgress.totalOperations\n : 0;\n const overallProgress = 20 + Math.round(uploadPercent * 80);\n onProgress?.({\n stage: \"uploading\",\n progress: overallProgress,\n totalOperations: uploadProgress.totalOperations,\n uploadedOperations: uploadProgress.uploadedOperations,\n });\n }\n },\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 const reactorClient = window.ph?.reactorClient;\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 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\nasync function _duplicateDocument(\n reactor: IReactorClient,\n document: PHDocument,\n newId = generateId(),\n) {\n const documentModule = await reactor.getDocumentModelModule(\n document.header.documentType,\n );\n\n return replayDocument(\n document.initialState,\n document.operations,\n documentModule.reducer,\n createPresignedHeader(newId, document.header.documentType),\n );\n}\n\nexport async function copyNode(\n driveId: string,\n src: Node,\n target: Node | undefined,\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 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","import { driveCollectionId, type PollBehavior } from \"@powerhousedao/reactor\";\nimport {\n driveCreateDocument,\n setAvailableOffline,\n setSharingType,\n type DocumentDriveDocument,\n type DriveInput,\n type SharingType,\n} from \"@powerhousedao/shared/document-drive\";\nimport type { PHDocument } from \"@powerhousedao/shared/document-model\";\nimport { getUserPermissions } from \"../utils/user.js\";\n\nexport type AddRemoteDriveOptions = {\n pollBehavior?: PollBehavior;\n};\n\nexport async function addDrive(input: DriveInput, preferredEditor?: string) {\n const { isAllowedToCreateDocuments } = getUserPermissions();\n if (!isAllowedToCreateDocuments) {\n throw new Error(\"User is not allowed to create drives\");\n }\n\n const reactorClient = window.ph?.reactorClient;\n if (!reactorClient) {\n throw new Error(\"ReactorClient not initialized\");\n }\n\n const driveDoc = driveCreateDocument({\n global: {\n name: input.global.name || \"\",\n icon: input.global.icon ?? null,\n nodes: [],\n },\n });\n\n if (preferredEditor) {\n driveDoc.header.meta = { preferredEditor };\n }\n\n return await reactorClient.create<DocumentDriveDocument>(driveDoc);\n}\n\nexport async function addRemoteDrive(\n url: string,\n driveId?: string,\n options?: AddRemoteDriveOptions,\n) {\n const reactorClient = window.ph?.reactorClient;\n if (!reactorClient) {\n throw new Error(\"ReactorClient not initialized\");\n }\n\n const sync =\n window.ph?.reactorClientModule?.reactorModule?.syncModule?.syncManager;\n if (!sync) {\n throw new Error(\"Sync not initialized\");\n }\n\n // Fetch drive info from the REST endpoint to get both id and graphqlEndpoint\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(`Failed to resolve drive info from ${url}`);\n }\n const driveInfo = (await response.json()) as {\n id: string;\n graphqlEndpoint: string;\n };\n\n const resolvedDriveId = driveId ?? driveInfo.id;\n const collectionId = driveCollectionId(\"main\", resolvedDriveId);\n\n const existingRemote = sync\n .list()\n .find((remote) => remote.collectionId === collectionId);\n if (existingRemote) {\n return resolvedDriveId;\n }\n\n const remoteName = crypto.randomUUID();\n\n await sync.add(\n remoteName,\n collectionId,\n {\n type: \"gql\",\n parameters: {\n url: driveInfo.graphqlEndpoint,\n },\n },\n undefined,\n options?.pollBehavior ? { pollBehavior: options.pollBehavior } : undefined,\n );\n\n return resolvedDriveId;\n}\n\nexport async function deleteDrive(driveId: string) {\n const { isAllowedToCreateDocuments } = getUserPermissions();\n if (!isAllowedToCreateDocuments) {\n throw new Error(\"User is not allowed to delete drives\");\n }\n\n const reactorClient = window.ph?.reactorClient;\n if (!reactorClient) {\n throw new Error(\"ReactorClient not initialized\");\n }\n await reactorClient.deleteDocument(driveId);\n}\n\nexport async function renameDrive(\n driveId: string,\n name: string,\n): Promise<PHDocument | undefined> {\n const { isAllowedToCreateDocuments } = getUserPermissions();\n if (!isAllowedToCreateDocuments) {\n throw new Error(\"User is not allowed to rename drives\");\n }\n\n const reactorClient = window.ph?.reactorClient;\n if (!reactorClient) {\n throw new Error(\"ReactorClient not initialized\");\n }\n return await reactorClient.rename(driveId, name);\n}\n\nexport async function setDriveAvailableOffline(\n driveId: string,\n availableOffline: boolean,\n): Promise<PHDocument | undefined> {\n const { isAllowedToCreateDocuments } = getUserPermissions();\n if (!isAllowedToCreateDocuments) {\n throw new Error(\"User is not allowed to change drive availability\");\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 setAvailableOffline({ availableOffline }),\n ]);\n}\n\nexport async function setDriveSharingType(\n driveId: string,\n sharingType: SharingType,\n): Promise<PHDocument | undefined> {\n const { isAllowedToCreateDocuments } = getUserPermissions();\n if (!isAllowedToCreateDocuments) {\n throw new Error(\"User is not allowed to change drive sharing type\");\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 setSharingType({ type: sharingType }),\n ]);\n}\n","export const DEFAULT_DRIVE_EDITOR_ID = \"powerhouse/generic-drive-explorer\";\nexport const COMMON_PACKAGE_ID = \"powerhouse/common\";\n","import type {\n DocumentModelModule,\n DocumentModelPHState,\n} from \"@powerhousedao/shared/document-model\";\nimport { documentModelDocumentModelModule } from \"document-model\";\n\nexport const baseDocumentModelsMap: Record<\n string,\n DocumentModelModule<DocumentModelPHState>\n> = {\n DocumentModel:\n documentModelDocumentModelModule as DocumentModelModule<DocumentModelPHState>,\n};\n\nexport const baseDocumentModels = Object.values(baseDocumentModelsMap);\n","import type {\n DocumentOperations,\n PHBaseState,\n PHDocument,\n PHDocumentHeader,\n} from \"document-model\";\nimport { map, pipe } from \"remeda\";\nimport { z } from \"zod\";\nimport type {\n FindDocumentsQuery,\n GetDocumentWithOperationsQuery,\n} from \"./gen/schema.js\";\nimport type { TStateSchemaZodObject } from \"./types.js\";\n\ntype QueryDocumentResult = NonNullable<\n GetDocumentWithOperationsQuery[\"document\"]\n>[\"document\"];\n\ntype FindDocumentsItems = NonNullable<\n FindDocumentsQuery[\"findDocuments\"]\n>[\"items\"];\n\nexport function phDocumentFromQuery<\n TDocumentSchema extends TStateSchemaZodObject,\n>(document: QueryDocumentResult, documentSchema?: TDocumentSchema) {\n const phDocument = {\n header: phDocumentHeaderFromQuery(document),\n state: phDocumentStateFromQuery(document),\n initialState: phDocumentStateFromQuery(document),\n operations:\n phDocumentOperationsFromGetDocumentWithOperationsQuery(document),\n clipboard: [],\n };\n if (documentSchema !== undefined) documentSchema.parse(phDocument);\n return phDocument as PHDocument;\n}\n\nexport function phDocumentsFromQuery<\n TDocumentSchema extends TStateSchemaZodObject,\n>(items: FindDocumentsItems, documentSchema?: TDocumentSchema) {\n const documents = pipe(\n items,\n map((document) => phDocumentFromQuery(document, documentSchema)),\n );\n return documents;\n}\n\nfunction phDocumentHeaderFromQuery(queryDocument: QueryDocumentResult) {\n const phDocumentHeader = {\n branch: \"main\",\n id: queryDocument.id,\n name: queryDocument.name,\n documentType: queryDocument.documentType,\n createdAtUtcIso:\n queryDocument.createdAtUtcIso instanceof Date\n ? queryDocument.createdAtUtcIso.toUTCString()\n : queryDocument.createdAtUtcIso,\n lastModifiedAtUtcIso:\n queryDocument.lastModifiedAtUtcIso instanceof Date\n ? queryDocument.lastModifiedAtUtcIso.toUTCString()\n : queryDocument.lastModifiedAtUtcIso,\n slug: queryDocument.slug ?? \"\",\n };\n return phDocumentHeader as PHDocumentHeader;\n}\n\nfunction phDocumentStateFromQuery<\n TDocumentSchema extends TStateSchemaZodObject,\n>(queryDocument: QueryDocumentResult, documentSchema?: TDocumentSchema) {\n if (documentSchema !== undefined)\n return documentSchema.shape.state.parse(queryDocument.state);\n return queryDocument.state as PHBaseState;\n}\n\nfunction phDocumentOperationsFromGetDocumentWithOperationsQuery(\n queryDocument: QueryDocumentResult,\n) {\n if (\n queryDocument.operations === null ||\n queryDocument.operations === undefined\n )\n return {\n global: [],\n };\n\n const documentOperations = {\n global: [...queryDocument.operations.items],\n };\n return documentOperations as DocumentOperations;\n}\nexport function identifierFromMutateDocumentOperationVariables(\n variables: unknown,\n) {\n return z\n .object({\n documentIdentifier: z.string(),\n })\n .parse(variables).documentIdentifier;\n}\n","export const DEFAULT_DRIVE_ID = \"powerhouse\" as const;\nexport const DEFAULT_SWITCHBOARD_URL = \"http://localhost:4001/graphql\" as const;\nexport const graphqlEventsToSyncDrive = [\n \"CreateEmptyDocument\",\n \"CreateDocument\",\n \"AddChildren\",\n \"RemoveChildren\",\n \"MoveChildren\",\n \"DeleteDocument\",\n \"DeleteDocuments\",\n] as const;\n\nexport const graphqlDocumentEvents = [\n \"MutateDocument\",\n \"MutateDocumentAsync\",\n \"DeleteDocument\",\n] as const;\n\nexport const graphqlDocumentsEvents = [\"DeleteDocuments\"] as const;\n","import { map } from \"remeda\";\nimport { phDocumentFromQuery } from \"./adapters.js\";\nimport type { TStateSchemaZodObject } from \"./types.js\";\n\nexport async function reactorGraphqlFetchDocument<\n TDocumentSchema extends TStateSchemaZodObject,\n>(identifier: string, documentSchema?: TDocumentSchema) {\n const client = window.ph?.reactorGraphQLClient;\n\n if (!client) {\n throw new Error(\n \"Please call `useInitReactorGraphqlClient` to use its functions\",\n );\n }\n try {\n const result = await client.GetDocument({\n identifier,\n });\n const document = result.document?.document;\n if (!document) return undefined;\n return phDocumentFromQuery(document, documentSchema);\n } catch (error) {\n return undefined;\n }\n}\n\nexport async function reactorGraphqlBatchFetchDocuments(\n identifiers: readonly string[],\n) {\n const client = window.ph?.reactorGraphQLClient;\n\n if (!client) {\n throw new Error(\n \"Please call `useInitReactorGraphqlClient` to use its functions\",\n );\n }\n const promises = map(identifiers, (identifier) =>\n reactorGraphqlFetchDocument(identifier),\n );\n return await Promise.all(promises);\n}\n","import { funnel } from \"remeda\";\n\ntype PromiseCallbacks<Result> = Readonly<\n Parameters<ConstructorParameters<typeof Promise<Result>>[0]>\n>;\n\ntype BatchRequest<Params extends unknown[], Result> = {\n readonly params: Params;\n readonly promiseCallbacks: PromiseCallbacks<Result>;\n};\n\nexport type Batch<Params extends unknown[], Result> = {\n call: (...params: Params) => Promise<Result>;\n cancel: () => void;\n flush: () => void;\n readonly isIdle: boolean;\n};\n\n/**\n * A reference implementation for an async batching utility function built on\n * top of the `funnel` general purpose execution utility function. It will\n * accumulate all params passed to an async `call` method within the defined\n * burst duration and then use an async executor to process them in one\n * invocation. It then extracts an individual result for each call which is\n * used to resolve the original call.\n *\n * This allows synchronizing multiple async calls while keeping each call site\n * isolated from the rest (for example, as react components).\n *\n * This reference implementation can be copied into your project as-is, or you\n * can use it as the basis for a more complex implementation with additional\n * features.\n *\n * @param callback - The main function that takes a batch and returns an\n * aggregated response. The typing for the it's parameters will derive the\n * typing for the extractor and the `call` method.\n * @param extractor - A function that takes the aggregated response and extracts\n * from it the result for each individual call. The function is called with both\n * the index in the batch, and the params passed to the `call` method. This\n * allows handling APIs that return batch results as both objects and arrays.\n * @param maxBurstDurationMs - The period of time where the batcher would\n * collect params before triggering the executor. When set to 0 the batcher\n * does not incur any additional delays to the execution and would trigger at\n * the next tick, just like a regular async function would. This is also the\n * default value.\n * @returns A Funnel object with the `call` method augmented to support async\n * response.\n */\nexport function batch<Params extends unknown[], BatchResponse, Result>(\n callback: (requests: readonly Params[]) => Promise<BatchResponse>,\n extractor: (\n response: BatchResponse,\n index: number,\n ...params: Params\n ) => Result,\n maxBurstDurationMs = 0,\n): Batch<Params, Result> {\n const batchFunnel = funnel(\n (requests: readonly BatchRequest<Params, Result>[]) => {\n callback(requests.map(({ params }) => params))\n .then((response) => {\n for (const [\n index,\n {\n params,\n promiseCallbacks: [resolve, reject],\n },\n ] of requests.entries()) {\n try {\n const result = extractor(response, index, ...params);\n resolve(result);\n } catch (error) {\n reject(error);\n }\n }\n })\n .catch((error) => {\n for (const {\n promiseCallbacks: [, reject],\n } of requests) {\n reject(error);\n }\n });\n },\n {\n reducer: (\n requests: readonly BatchRequest<Params, Result>[] | undefined,\n request: BatchRequest<Params, Result>,\n ) => [...(requests ?? []), request],\n maxBurstDurationMs,\n triggerAt: \"end\",\n },\n );\n\n return {\n ...batchFunnel,\n\n call: (...params: Params) =>\n new Promise<Result>((...promiseCallbacks) => {\n batchFunnel.call({ promiseCallbacks, params });\n }),\n };\n}\n","import type { PHDocument } from \"document-model\";\nimport { filter, isTruthy, map, mapToObj, pipe, prop, unique } from \"remeda\";\nimport { type Batch, batch } from \"./batch.js\";\nimport { reactorGraphqlBatchFetchDocuments } from \"./fetchers.js\";\n\nfunction makeDocumentsById(documents: (PHDocument | undefined)[] = []) {\n return pipe(\n documents,\n filter(isTruthy),\n mapToObj((document) => [document.header.id, document]),\n );\n}\n\nexport class DocumentFetcher {\n private batchGetDocuments: Batch<[id: string], PHDocument>;\n\n constructor() {\n this.batchGetDocuments = batch(\n async (requests: readonly [id: string][]) => {\n const ids = unique(map(requests, ([id]) => id));\n const documents = await reactorGraphqlBatchFetchDocuments(ids);\n\n return makeDocumentsById(documents);\n },\n (documentsById, _, id) => {\n const document = prop(documentsById, id);\n return document;\n },\n );\n }\n\n get(id: string): Promise<PHDocument> {\n return this.batchGetDocuments.call(id);\n }\n\n getBatch(ids: string[]): Promise<PHDocument[]> {\n return Promise.all(map(ids, (id) => this.get(id)));\n }\n}\n","import type { PHDocument } from \"document-model\";\nimport { forEach } from \"remeda\";\nimport { addPromiseState, readPromiseState } from \"../document-cache.js\";\nimport type {\n FulfilledPromise,\n IDocumentCache,\n PromiseWithState,\n} from \"../types/documents.js\";\nimport { DocumentFetcher } from \"./document-fetcher.js\";\n\nexport class GraphQLClientDocumentCache implements IDocumentCache {\n private fetcher: DocumentFetcher;\n\n private documents = new Map<string, PromiseWithState<PHDocument>>();\n\n private batchPromises = new Map<\n string,\n {\n promises: readonly Promise<PHDocument>[];\n promise: PromiseWithState<PHDocument[]>;\n }\n >();\n\n private listeners = new Map<string, (() => void)[]>();\n\n constructor() {\n this.fetcher = new DocumentFetcher();\n\n window.addEventListener(\"MutateDocument\", (event) => {\n this.handleDocumentMutated(event.detail.identifier).catch(console.error);\n });\n\n window.addEventListener(\"MutateDocumentAsync\", (event) => {\n this.handleDocumentMutated(event.detail.identifier).catch(console.error);\n });\n }\n\n get(id: string, refetch?: boolean): Promise<PHDocument> {\n const current = this.documents.get(id);\n\n if (current) {\n if (current.status === \"pending\") {\n return current;\n }\n\n if (!refetch) {\n return current;\n }\n }\n\n const promise = addPromiseState(\n this.fetcher.get(id).then((document) => {\n this.invalidateBatchesContaining(id);\n return document;\n }),\n );\n\n this.documents.set(id, promise);\n\n return promise;\n }\n\n getBatch(ids: string[]): Promise<PHDocument[]> {\n const key = ids.join(\",\");\n const cached = this.batchPromises.get(key);\n\n const currentPromises = ids.map((id) => this.get(id));\n\n if (cached) {\n const samePromises = currentPromises.every(\n (promise, index) => promise === cached.promises[index],\n );\n\n if (samePromises) {\n return cached.promise;\n }\n }\n\n const states = currentPromises.map((promise) =>\n readPromiseState(promise as PromiseWithState<PHDocument>),\n );\n\n const allFulfilled = states.every((state) => state.status === \"fulfilled\");\n\n if (allFulfilled) {\n const values = states.map(\n (state) => (state as { status: \"fulfilled\"; value: PHDocument }).value,\n );\n\n const batchPromise = Promise.resolve(values) as PromiseWithState<\n PHDocument[]\n >;\n\n batchPromise.status = \"fulfilled\";\n (batchPromise as FulfilledPromise<PHDocument[]>).value = values;\n\n this.batchPromises.set(key, {\n promises: currentPromises,\n promise: batchPromise,\n });\n\n return batchPromise;\n }\n\n const batchPromise = addPromiseState(Promise.all(currentPromises));\n\n this.batchPromises.set(key, {\n promises: currentPromises,\n promise: batchPromise,\n });\n\n return batchPromise;\n }\n\n private invalidateBatchesContaining(documentId: string): void {\n for (const key of this.batchPromises.keys()) {\n if (key.split(\",\").includes(documentId)) {\n this.batchPromises.delete(key);\n }\n }\n }\n\n subscribe(id: string | string[], callback: () => void): () => void {\n const ids = Array.isArray(id) ? id : [id];\n\n for (const documentId of ids) {\n const listeners = this.listeners.get(documentId) ?? [];\n this.listeners.set(documentId, [...listeners, callback]);\n }\n\n return () => {\n for (const documentId of ids) {\n const listeners = this.listeners.get(documentId) ?? [];\n this.listeners.set(\n documentId,\n listeners.filter((listener) => listener !== callback),\n );\n }\n };\n }\n\n private notify(id: string): void {\n const listeners = this.listeners.get(id) ?? [];\n\n for (const listener of listeners) {\n listener();\n }\n }\n\n private async handleDocumentMutated(id: string) {\n this.invalidateBatchesContaining(id);\n await this.get(id);\n this.notify(id);\n }\n\n private handleDocumentDeleted(id: string) {\n this.documents.delete(id);\n this.invalidateBatchesContaining(id);\n this.notify(id);\n }\n\n private handleDocumentsDeleted(ids: string[]) {\n forEach(ids, (id) => this.handleDocumentDeleted(id));\n }\n}\n","import type { PHDocument } from \"document-model\";\nimport { DEFAULT_DRIVE_ID } from \"./constants.js\";\nimport type { Scalars } from \"./gen/schema.js\";\n\nexport async function reactorGraphqlCreateDocument<\n TDocument extends PHDocument,\n>(document: TDocument, parentIdentifier = DEFAULT_DRIVE_ID) {\n const client = window.ph?.reactorGraphQLClient;\n\n if (!client) {\n throw new Error(\n \"Please call `useInitReactorGraphqlClient` to use its functions\",\n );\n }\n\n const result = await client.CreateDocument({\n document,\n parentIdentifier,\n });\n\n return result;\n}\n\nexport async function reactorGraphqlDeleteDocument(identifier: string) {\n const client = window.ph?.reactorGraphQLClient;\n\n if (!client) {\n throw new Error(\n \"Please call `useInitReactorGraphqlClient` to use its functions\",\n );\n }\n\n const result = await client.DeleteDocument({\n identifier,\n });\n\n return result;\n}\n\nexport async function reactorGraphqlDeleteDocuments(identifiers: string[]) {\n const client = window.ph?.reactorGraphQLClient;\n\n if (!client) {\n throw new Error(\n \"Please call `useInitReactorGraphqlClient` to use its functions\",\n );\n }\n\n const result = await client.DeleteDocuments({\n identifiers,\n });\n\n return result;\n}\n\nexport async function reactorGraphqlMutateDocument(\n documentIdentifier: string,\n ...actions: ReadonlyArray<Scalars[\"JSONObject\"][\"input\"]>\n) {\n const client = window.ph?.reactorGraphQLClient;\n\n if (!client) {\n throw new Error(\n \"Please call `useInitReactorGraphqlClient` to use its functions\",\n );\n }\n\n const result = await client.MutateDocument({\n documentIdentifier,\n actions,\n });\n\n return result;\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: 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 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 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 {\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 { 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 { 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 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(documentType: string) {\n setPHModal({ type: \"createDocument\", documentType });\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","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 IReactorClient,\n ISyncManager,\n} from \"@powerhousedao/reactor\";\nimport type {\n AddPHGlobalEventHandler,\n BrowserReactorClientModule,\n SetPHGlobalValue,\n UsePHGlobalValue,\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 */\nexport const useReactorClientModule: UsePHGlobalValue<BrowserReactorClientModule> =\n reactorClientModuleEventFunctions.useValue;\n\n/** Sets the reactor client module */\nexport const setReactorClientModule: SetPHGlobalValue<BrowserReactorClientModule> =\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<IReactorClient> =\n reactorClientEventFunctions.useValue;\n\n/** Sets the reactor client */\nexport const setReactorClient: SetPHGlobalValue<IReactorClient> =\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 useReactorClientModule()?.reactorModule?.database;\n\nexport const usePGlite = (): PGlite | undefined => useReactorClientModule()?.pg;\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 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 { DocumentDispatch } from \"@powerhousedao/reactor-browser\";\nimport type {\n DocumentDriveAction,\n DocumentDriveDocument,\n} from \"@powerhousedao/shared/document-drive\";\nimport {\n createUrlWithPreservedParams,\n extractDriveIdFromPath,\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\";\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 // Find the drive by slug to get its actual ID\n const drive = window.ph?.drives?.find((d) => d.header.slug === driveSlug);\n const driveId = drive?.header.id;\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\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 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 {\n createUrlWithPreservedParams,\n extractDriveSlugFromPath,\n extractNodeIdFromSlug,\n extractNodeSlugFromPath,\n makeNodeSlug,\n resolveUrlPathname,\n} from \"../utils/url.js\";\nimport { useNodesInSelectedDrive } from \"./items-in-selected-drive.js\";\nimport { makePHEventFunctions } from \"./make-ph-event-functions.js\";\n\nconst selectedNodeIdEventFunctions = makePHEventFunctions(\"selectedNodeId\");\nconst useSelectedNodeId = selectedNodeIdEventFunctions.useValue;\nconst setSelectedNodeId = selectedNodeIdEventFunctions.setValue;\nexport const addSelectedNodeIdEventHandler =\n selectedNodeIdEventFunctions.addEventHandler;\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\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 const selectedNodeId = window.ph?.selectedNodeId;\n if (nodeSlug !== selectedNodeId) {\n setSelectedNode(nodeSlug);\n }\n });\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 {\n DuplicateManifestError,\n DuplicateModuleError,\n} from \"@powerhousedao/reactor\";\nimport type { DocumentModelLib } from \"document-model\";\nimport { useSyncExternalStore } from \"react\";\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.flatMap((pkg) => pkg.documentModels);\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 duplicates = [];\n for (const result of results) {\n if (result.status === \"error\") {\n if (DuplicateModuleError.isError(result.error)) {\n duplicates.push(result);\n } else {\n console.error(\n \"Failed to register document model module:\",\n result.error,\n );\n }\n }\n }\n if (duplicates.length > 0) {\n const duplicateTypes = duplicates.map(\n (r) => r.item.documentModel.global.id,\n );\n registry.unregisterModules(...duplicateTypes);\n registry.registerModules(...duplicates.map((r) => r.item));\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 (DuplicateManifestError.isError(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 addRenownChainIdEventHandler,\n addRenownNetworkIdEventHandler,\n addRenownUrlEventHandler,\n addRequiresHardRefreshEventHandler,\n addRouterBasenameEventHandler,\n addSentryDsnEventHandler,\n addSentryEnvEventHandler,\n addSentryReleaseEventHandler,\n addStudioModeEventHandler,\n addVersionCheckIntervalEventHandler,\n addVersionEventHandler,\n addWarnOutdatedAppEventHandler,\n} from \"./config/connect.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 { 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};\n\nconst phGlobalEventHandlerRegisterFunctions: PHGlobalEventHandlerAdders = {\n ...commonGlobalEventHandlerFunctions,\n reactorClientModule: addReactorClientModuleEventHandler,\n reactorClient: addReactorClientEventHandler,\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 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","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\nexport function useDocumentModelModuleById(\n id: string | null | undefined,\n): DocumentModelModule | undefined {\n const documentModelModules = useDocumentModelModules();\n return documentModelModules?.find(\n (module) => module.documentModel.global.id === id,\n );\n}\n","import { useAllowedDocumentTypes } from \"./config/editor.js\";\nimport { useDocumentModelModules } from \"./document-model-modules.js\";\n\nexport function useAllowedDocumentModelModules() {\n const documentModelModules = useDocumentModelModules();\n const allowedDocumentTypes = useAllowedDocumentTypes();\n if (!allowedDocumentTypes?.length) return documentModelModules;\n return documentModelModules?.filter((module) =>\n allowedDocumentTypes.includes(module.documentModel.global.id),\n );\n}\n","import type { FolderNode } from \"@powerhousedao/shared/document-drive\";\nimport { isFolderNodeKind } from \"../utils/nodes.js\";\nimport { useSelectedNode } from \"./selected-node.js\";\n\n/** Returns the selected folder. */\nexport function useSelectedFolder(): FolderNode | undefined {\n const selectedNode = useSelectedNode();\n if (isFolderNodeKind(selectedNode)) return selectedNode;\n return undefined;\n}\n","import type { Node } from \"@powerhousedao/shared/document-drive\";\nimport { sortNodesByName } from \"../utils/nodes.js\";\nimport { useNodesInSelectedDrive } from \"./items-in-selected-drive.js\";\nimport { useSelectedFolder } from \"./selected-folder.js\";\n\n/** Returns the child nodes for the selected drive or folder. */\nexport function useNodesInSelectedDriveOrFolder(): Node[] {\n const nodes = useNodesInSelectedDrive();\n const selectedFolder = useSelectedFolder();\n const selectedFolderId = selectedFolder?.id;\n if (!nodes) return [];\n if (!selectedFolderId)\n return sortNodesByName(nodes.filter((n) => !n.parentFolder));\n return sortNodesByName(\n nodes.filter((n) => n.parentFolder === selectedFolderId),\n );\n}\n","import type {\n PHAppConfig,\n PHAppConfigKey,\n PHDocumentEditorConfig,\n PHDocumentEditorConfigKey,\n PHGlobalConfig,\n PHGlobalConfigKey,\n} from \"@powerhousedao/reactor-browser\";\nimport { phGlobalConfigSetters } from \"./connect.js\";\nimport { phAppConfigSetters, phDocumentEditorConfigSetters } from \"./editor.js\";\n\nexport function setPHGlobalConfigByKey<TKey extends PHGlobalConfigKey>(\n key: TKey,\n value: PHGlobalConfig[TKey] | undefined,\n) {\n const setter = phGlobalConfigSetters[key];\n setter(value);\n}\n\nexport function setPHAppConfigByKey<TKey extends PHAppConfigKey>(\n key: TKey,\n value: PHAppConfig[TKey] | undefined,\n) {\n const setter = phAppConfigSetters[key];\n setter(value);\n}\n\nexport function setPHDocumentEditorConfigByKey<\n TKey extends PHDocumentEditorConfigKey,\n>(key: TKey, value: PHDocumentEditorConfig[TKey] | undefined) {\n const setter = phDocumentEditorConfigSetters[key];\n setter(value);\n}\n","import type {\n PHGlobalConfig,\n PHGlobalConfigKey,\n PHGlobalConfigSetters,\n} from \"@powerhousedao/reactor-browser\";\nimport { phGlobalConfigSetters } from \"./connect.js\";\n\nexport function callGlobalSetterForKey<TKey extends PHGlobalConfigKey>(\n key: TKey,\n value: PHGlobalConfig[TKey] | undefined,\n) {\n const setter = phGlobalConfigSetters[key] as PHGlobalConfigSetters[TKey];\n setter(value);\n}\n","import type {\n PHAppConfig,\n PHAppConfigKey,\n PHDocumentEditorConfig,\n PHDocumentEditorConfigKey,\n PHGlobalConfig,\n PHGlobalConfigKey,\n} from \"@powerhousedao/reactor-browser\";\nimport { useEffect, useState } from \"react\";\nimport { callGlobalSetterForKey } from \"./utils.js\";\n\nexport function setDefaultPHGlobalConfig(config: PHGlobalConfig) {\n for (const key of Object.keys(config) as PHGlobalConfigKey[]) {\n callGlobalSetterForKey(key, config[key]);\n }\n}\n\nexport function useSetDefaultPHGlobalConfig(config: PHGlobalConfig) {\n const [isInitialized, setIsInitialized] = useState(false);\n\n useEffect(() => {\n if (isInitialized) return;\n setDefaultPHGlobalConfig(config);\n setIsInitialized(true);\n }, [config, isInitialized]);\n}\n\nexport function useResetPHGlobalConfig(defaultConfigForReset: PHGlobalConfig) {\n return function reset() {\n setPHGlobalConfig(defaultConfigForReset);\n };\n}\n\nexport function setPHGlobalConfig(config: Partial<PHGlobalConfig>) {\n for (const key of Object.keys(config) as PHGlobalConfigKey[]) {\n callGlobalSetterForKey(key, config[key]);\n }\n}\n\nexport function useSetPHGlobalConfig(config: Partial<PHGlobalConfig>) {\n const [isInitialized, setIsInitialized] = useState(false);\n\n useEffect(() => {\n if (isInitialized) return;\n setPHGlobalConfig(config);\n setIsInitialized(true);\n }, [config, isInitialized]);\n}\n\n/** Sets the global drive config.\n *\n * Pass in a partial object of the global drive config to set.\n */\nexport function setPHAppConfig(config: Partial<PHAppConfig>) {\n for (const key of Object.keys(config) as PHAppConfigKey[]) {\n callGlobalSetterForKey(key, config[key]);\n }\n}\n\n/** Sets the global document config.\n *\n * Pass in a partial object of the global document config to set.\n */\nexport function setPHDocumentEditorConfig(\n config: Partial<PHDocumentEditorConfig>,\n) {\n for (const key of Object.keys(config) as PHDocumentEditorConfigKey[]) {\n callGlobalSetterForKey(key, config[key]);\n }\n}\n\n/** Wrapper hook for setting the global app config.\n *\n * Automatically sets the global app config when the component mounts.\n *\n * Pass in a partial object of the global app config to set.\n */\nexport function useSetPHAppConfig(config: Partial<PHAppConfig>) {\n const [isInitialized, setIsInitialized] = useState(false);\n\n useEffect(() => {\n if (isInitialized) return;\n setPHAppConfig(config);\n setIsInitialized(true);\n }, [config, isInitialized]);\n}\n\n/** Wrapper hook for setting the global document editor config.\n *\n * Automatically sets the global document editor config when the component mounts.\n *\n * Pass in a partial object of the global document editor config to set.\n */\nexport function useSetPHDocumentEditorConfig(\n config: Partial<PHDocumentEditorConfig>,\n) {\n const [isInitialized, setIsInitialized] = useState(false);\n\n useEffect(() => {\n if (isInitialized) return;\n setPHDocumentEditorConfig(config);\n setIsInitialized(true);\n }, [config, isInitialized]);\n}\n","import type {\n PHAppConfigKey,\n PHDocumentEditorConfigKey,\n PHGlobalConfigKey,\n} from \"@powerhousedao/reactor-browser\";\nimport { phGlobalConfigHooks } from \"./connect.js\";\nimport { phAppConfigHooks, phDocumentEditorConfigHooks } from \"./editor.js\";\n\nexport function usePHGlobalConfigByKey<TKey extends PHGlobalConfigKey>(\n key: TKey,\n) {\n const useValueHook = phGlobalConfigHooks[key];\n return useValueHook();\n}\n\n/** Gets the value of an item in the global drive config for a given key.\n *\n * Strongly typed, inferred from type definition for the key.\n */\nexport function usePHAppConfigByKey<TKey extends PHAppConfigKey>(key: TKey) {\n const useValueHook = phAppConfigHooks[key];\n return useValueHook();\n}\n\n/** Gets the value of an item in the global document config for a given key.\n *\n * Strongly typed, inferred from type definition for the key.\n */\nexport function usePHDocumentEditorConfigByKey<\n TKey extends PHDocumentEditorConfigKey,\n>(key: TKey) {\n const useValueHook = phDocumentEditorConfigHooks[key];\n return useValueHook();\n}\n","import type { ConnectionStateSnapshot } from \"@powerhousedao/reactor\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useSync } from \"./reactor.js\";\n\n/**\n * Returns a map of remote name to connection state snapshot for all remotes.\n * Re-renders when any remote's connection state changes.\n */\nexport function useConnectionStates(): ReadonlyMap<\n string,\n ConnectionStateSnapshot\n> {\n const syncManager = useSync();\n const [states, setStates] = useState<\n ReadonlyMap<string, ConnectionStateSnapshot>\n >(() => buildSnapshot(syncManager));\n const unsubscribesRef = useRef<Array<() => void>>([]);\n\n useEffect(() => {\n if (!syncManager) return;\n\n function subscribe() {\n // Clean up previous subscriptions\n for (const unsub of unsubscribesRef.current) {\n unsub();\n }\n unsubscribesRef.current = [];\n\n const remotes = syncManager!.list();\n for (const remote of remotes) {\n const unsub = remote.channel.onConnectionStateChange(() => {\n setStates(buildSnapshot(syncManager));\n });\n unsubscribesRef.current.push(unsub);\n }\n\n // Set initial state\n setStates(buildSnapshot(syncManager));\n }\n\n subscribe();\n\n // Re-subscribe periodically to pick up added/removed remotes\n const interval = setInterval(subscribe, 5000);\n\n return () => {\n clearInterval(interval);\n for (const unsub of unsubscribesRef.current) {\n unsub();\n }\n unsubscribesRef.current = [];\n };\n }, [syncManager]);\n\n return states;\n}\n\n/**\n * Returns the connection state snapshot for a specific remote by name.\n */\nexport function useConnectionState(\n remoteName: string,\n): ConnectionStateSnapshot | undefined {\n const states = useConnectionStates();\n return states.get(remoteName);\n}\n\nfunction buildSnapshot(\n syncManager: ReturnType<typeof useSync>,\n): ReadonlyMap<string, ConnectionStateSnapshot> {\n const map = new Map<string, ConnectionStateSnapshot>();\n if (!syncManager) return map;\n for (const remote of syncManager.list()) {\n map.set(remote.name, remote.channel.getConnectionState());\n }\n return map;\n}\n","import { ModuleNotFoundError } from \"@powerhousedao/reactor\";\nimport type { DocumentDispatch } from \"@powerhousedao/reactor-browser\";\nimport type { Action, PHDocument } from \"@powerhousedao/shared/document-model\";\nimport { DocumentTypeMismatchError } from \"../errors.js\";\nimport { useDocumentById } from \"./document-by-id.js\";\nimport { useDocumentModelModuleById } from \"./document-model-modules.js\";\n\n/** Returns a document of a specific type, throws an error if the found document has a different type */\nexport function useDocumentOfType<\n TDocument extends PHDocument,\n TAction extends Action,\n>(\n documentId: string | null | undefined,\n documentType: string | null | undefined,\n) {\n const [document, dispatch] = useDocumentById(documentId);\n const documentModelModule = useDocumentModelModuleById(documentType);\n\n if (!documentId || !documentType) return [];\n\n if (!document) {\n throw new Error(`Document not found: ${documentId}`);\n }\n if (!documentModelModule) {\n throw new ModuleNotFoundError(documentType);\n }\n\n if (document.header.documentType !== documentType) {\n throw new DocumentTypeMismatchError(\n documentId,\n documentType,\n document.header.documentType,\n );\n }\n\n return [document, dispatch] as [TDocument, DocumentDispatch<TAction>];\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\ntype 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","import { useDocumentModelModules } from \"./document-model-modules.js\";\n\n/** Returns the supported document types for the reactor (derived from the document model modules) */\nexport function useSupportedDocumentTypesInReactor() {\n const documentModelModules = useDocumentModelModules();\n return documentModelModules?.map((module) => module.documentModel.global.id);\n}\n","import { useAllowedDocumentTypes } from \"./config/editor.js\";\nimport { useSupportedDocumentTypesInReactor } from \"./supported-document-types.js\";\n\n/** Returns the document types a app supports.\n *\n * If present, uses the `allowedDocumentTypes` config value.\n * Otherwise, uses the supported document types from the reactor.\n */\nexport function useDocumentTypes() {\n const allowedDocumentTypes = useAllowedDocumentTypes();\n const supportedDocumentTypes = useSupportedDocumentTypesInReactor();\n return allowedDocumentTypes ?? supportedDocumentTypes;\n}\n","import type {\n DocumentDriveAction,\n DocumentDriveDocument,\n} from \"@powerhousedao/shared/document-drive\";\nimport type { DocumentDispatch } from \"../types/documents.js\";\nimport { useDispatch } from \"./dispatch.js\";\nimport { useDrives } from \"./drives.js\";\n\nexport function useDriveById(\n driveId: string | undefined | null,\n): [DocumentDriveDocument, DocumentDispatch<DocumentDriveAction>] {\n const drives = useDrives();\n const foundDrive = drives?.find((drive) => drive.header.id === driveId);\n const [drive, dispatch] = useDispatch(foundDrive);\n if (!foundDrive) {\n throw new Error(`Drive with id ${driveId} not found`);\n }\n return [drive, dispatch] as [\n DocumentDriveDocument,\n DocumentDispatch<DocumentDriveAction>,\n ];\n}\n","import type { EditorModule } from \"document-model\";\nimport { DEFAULT_DRIVE_EDITOR_ID } from \"../constants.js\";\nimport { useVetraPackages } from \"./vetra-packages.js\";\n\nexport function useEditorModules(): EditorModule[] | undefined {\n const vetraPackages = useVetraPackages();\n return vetraPackages\n .flatMap((pkg) => pkg.editors)\n .filter(\n (module) => !module.documentTypes.includes(\"powerhouse/document-drive\"),\n );\n}\n\nexport function useAppModules(): EditorModule[] | undefined {\n const vetraPackages = useVetraPackages();\n return vetraPackages\n .flatMap((pkg) => pkg.editors)\n .filter((module) =>\n module.documentTypes.includes(\"powerhouse/document-drive\"),\n );\n}\n\nexport function useFallbackEditorModule(\n documentType: string | null | undefined,\n): EditorModule | undefined {\n const editorModules = useEditorModules();\n if (!documentType) return undefined;\n if (editorModules?.length === 0) return undefined;\n\n const modulesForType = editorModules?.filter((module) =>\n module.documentTypes.includes(documentType),\n );\n return modulesForType?.[0];\n}\n\nexport function useAppModuleById(\n id: string | null | undefined,\n): EditorModule | undefined {\n const appModules = useAppModules();\n return appModules?.find((module) => module.config.id === id);\n}\n\nexport function useDefaultAppModule(): EditorModule | undefined {\n const defaultAppModule = useAppModuleById(DEFAULT_DRIVE_EDITOR_ID);\n return defaultAppModule;\n}\n\nexport function useEditorModuleById(\n id: string | null | undefined,\n): EditorModule | undefined {\n const editorModules = useEditorModules();\n return editorModules?.find((module) => module.config.id === id);\n}\n\nexport function useEditorModulesForDocumentType(\n documentType: string | null | undefined,\n) {\n const editorModules = useEditorModules();\n if (!documentType) return undefined;\n\n const modulesForType = editorModules?.filter((module) =>\n module.documentTypes.includes(documentType),\n );\n return modulesForType;\n}\n","import type { FolderNode } from \"@powerhousedao/shared/document-drive\";\nimport { useFolderNodesInSelectedDrive } from \"./items-in-selected-drive.js\";\n\nexport function useFolderById(\n id: string | null | undefined,\n): FolderNode | undefined {\n const folders = useFolderNodesInSelectedDrive();\n return folders?.find((n) => n.id === id);\n}\n","import type {\n GraphQLClientDocumentEvent,\n GraphQLClientDocumentsEvent,\n GraphQLDocumentEventOperationName,\n GraphQLDocumentEventsOperationName,\n} from \"./types.js\";\n\nexport function dispatchGraphQLClientDocumentEvent(\n operationName: GraphQLDocumentEventOperationName,\n identifier: string,\n) {\n const event: GraphQLClientDocumentEvent = new CustomEvent(operationName, {\n detail: { identifier },\n });\n window.dispatchEvent(event);\n}\n\nexport function dispatchGraphQLClientDocumentsEvent(\n operationName: GraphQLDocumentEventsOperationName,\n identifiers: string[],\n) {\n const event: GraphQLClientDocumentsEvent = new CustomEvent(operationName, {\n detail: { identifiers },\n });\n window.dispatchEvent(event);\n}\n","import { isIncludedIn, isStrictEqual } from \"remeda\";\nimport { identifierFromMutateDocumentOperationVariables } from \"./adapters.js\";\nimport { graphqlEventsToSyncDrive } from \"./constants.js\";\nimport { dispatchGraphQLClientDocumentEvent } from \"./events.js\";\nimport type { SdkFunctionWrapper } from \"./gen/schema.js\";\n\nexport const documentCacheClientMiddleware: SdkFunctionWrapper = async (\n action,\n operationName,\n operationType,\n variables: unknown,\n) => {\n console.log({ operationName, operationType, variables });\n const result = await action();\n\n if (isIncludedIn(operationName, graphqlEventsToSyncDrive)) {\n window.dispatchEvent(new CustomEvent(operationName));\n }\n\n if (isStrictEqual(operationName, \"MutateDocument\")) {\n dispatchGraphQLClientDocumentEvent(\n operationName,\n identifierFromMutateDocumentOperationVariables(variables),\n );\n }\n\n return result;\n};\n","import type { DocumentDriveDocument } from \"@powerhousedao/shared\";\nimport { DriveDocumentSchema } from \"@powerhousedao/shared/document-drive\";\nimport { useEffect, useState } from \"react\";\nimport { forEach } from \"remeda\";\nimport { phDocumentFromQuery } from \"../graphql/adapters.js\";\nimport { createClient } from \"../graphql/client.js\";\nimport {\n DEFAULT_DRIVE_ID,\n DEFAULT_SWITCHBOARD_URL,\n graphqlEventsToSyncDrive,\n} from \"../graphql/constants.js\";\nimport { documentCacheClientMiddleware } from \"../graphql/document-cache-client-middleware.js\";\nimport { GraphQLClientDocumentCache } from \"../graphql/graphql-client-document-cache.js\";\nimport {\n callEventHandlerRegisterFunctions,\n commonGlobalEventHandlerFunctions,\n} from \"./add-ph-event-handlers.js\";\nimport { setDocumentCache } from \"./document-cache.js\";\nimport { setDrives } from \"./drives.js\";\nimport { setGraphQLReactorClient } from \"./graphql-reactor-client.js\";\nimport { setSelectedDrive } from \"./selected-drive.js\";\nimport { setSelectedNode } from \"./selected-node.js\";\n\nexport function useInitReactorGraphqlClient(\n switchboardUrl = DEFAULT_SWITCHBOARD_URL,\n driveId = DEFAULT_DRIVE_ID,\n) {\n const [hasInit, setHasInit] = useState(false);\n\n useEffect(() => {\n if (hasInit) return;\n\n initGraphQLReactorClientWithDocumentCache(switchboardUrl, driveId)\n .then(() => setHasInit(true))\n .catch(console.error);\n }, [hasInit]);\n\n return hasInit;\n}\n\nasync function reactorGraphqlFetchDrive(\n identifier: string,\n): Promise<DocumentDriveDocument> {\n const client = window.ph?.reactorGraphQLClient;\n\n if (!client) {\n throw new Error(\n \"Please call `useInitReactorGraphqlClient` to use its functions\",\n );\n }\n\n const result = await client.GetDocument({ identifier });\n\n if (!result.document?.document) {\n throw new Error(\"Could not fetch drive with id: \" + identifier);\n }\n\n const drive = phDocumentFromQuery(\n result.document.document,\n DriveDocumentSchema,\n ) as DocumentDriveDocument;\n return drive;\n}\n\nasync function reactorGraphqlSyncDrive(driveId: string) {\n const client = window.ph?.reactorGraphQLClient;\n\n if (!client) {\n throw new Error(\n \"Please call `useInitReactorGraphqlClient` to use its functions\",\n );\n }\n const drive = await reactorGraphqlFetchDrive(driveId);\n setDrives([drive]);\n setSelectedDrive(drive);\n}\n\nasync function initGraphQLReactorClientWithDocumentCache(\n switchboardUrl: string,\n driveId: string,\n) {\n if (!window.ph) {\n window.ph = {};\n }\n\n callEventHandlerRegisterFunctions(commonGlobalEventHandlerFunctions);\n\n const client = createClient(switchboardUrl, documentCacheClientMiddleware);\n setGraphQLReactorClient(client);\n await reactorGraphqlSyncDrive(driveId);\n setSelectedNode(undefined);\n setDocumentCache(new GraphQLClientDocumentCache());\n\n forEach(graphqlEventsToSyncDrive, (name) => {\n window.addEventListener(name, () => {\n reactorGraphqlSyncDrive(driveId).catch(console.error);\n });\n });\n}\n","import type {\n FileNode,\n FolderNode,\n Node,\n} from \"@powerhousedao/shared/document-drive\";\nimport type { PHDocument } from \"@powerhousedao/shared/document-model\";\nimport { isFileNodeKind, isFolderNodeKind } from \"../utils/nodes.js\";\nimport {\n useDocumentsInSelectedDrive,\n useNodesInSelectedDrive,\n} from \"./items-in-selected-drive.js\";\nimport { useSelectedFolder } from \"./selected-folder.js\";\n\n/** Returns the nodes in the selected folder. */\nexport function useNodesInSelectedFolder(): Node[] | undefined {\n const selectedFolder = useSelectedFolder();\n const nodes = useNodesInSelectedDrive();\n if (!selectedFolder || !nodes) return undefined;\n\n return nodes.filter((n) => n.parentFolder === selectedFolder.id);\n}\n\n/** Returns the file nodes in the selected folder. */\nexport function useFileNodesInSelectedFolder(): FileNode[] | undefined {\n const nodes = useNodesInSelectedFolder();\n if (!nodes) return undefined;\n return nodes.filter((n) => isFileNodeKind(n));\n}\n\n/** Returns the folder nodes in the selected folder. */\nexport function useFolderNodesInSelectedFolder(): FolderNode[] | undefined {\n const nodes = useNodesInSelectedFolder();\n if (!nodes) return undefined;\n return nodes.filter((n) => isFolderNodeKind(n));\n}\n\n/** Returns the documents in the selected folder. */\nexport function useDocumentsInSelectedFolder(): PHDocument[] | undefined {\n const documents = useDocumentsInSelectedDrive();\n const fileNodes = useFileNodesInSelectedFolder();\n const fileNodeIds = fileNodes?.map((node) => node.id);\n return documents?.filter((d) => fileNodeIds?.includes(d.header.id));\n}\n","import type { Node } from \"@powerhousedao/shared/document-drive\";\nimport {\n addFile,\n addFolder,\n copyNode,\n moveNode,\n renameDriveNode,\n renameNode,\n} from \"../actions/document.js\";\nimport { useDrives } from \"./drives.js\";\nimport { useFolderById } from \"./folder-by-id.js\";\nimport { useSelectedDriveSafe } from \"./selected-drive.js\";\nimport { useSelectedFolder } from \"./selected-folder.js\";\nimport { setSelectedNode, useSelectedNode } from \"./selected-node.js\";\n\nfunction resolveNode(driveId: string, node: Node | undefined) {\n return node?.id !== driveId ? node : undefined;\n}\n\nexport function useNodeActions() {\n const [selectedDrive] = useSelectedDriveSafe();\n const selectedFolder = useSelectedFolder();\n const selectedNode = useSelectedNode();\n const selectedParentFolder = useFolderById(selectedNode?.parentFolder);\n const selectedDriveId = selectedDrive?.header.id;\n const drives = useDrives();\n\n async function onAddFile(file: File, parent: Node | undefined) {\n if (!selectedDriveId) return;\n\n const fileName = file.name.replace(/\\..+/gim, \"\");\n\n return addFile(\n file,\n selectedDriveId,\n fileName,\n resolveNode(selectedDriveId, parent)?.id,\n );\n }\n\n async function onAddFolder(name: string, parent: Node | undefined) {\n if (!selectedDriveId) return;\n\n return addFolder(\n selectedDriveId,\n name,\n resolveNode(selectedDriveId, parent)?.id,\n );\n }\n\n async function onRenameNode(\n newName: string,\n node: Node,\n ): Promise<Node | undefined> {\n if (!selectedDriveId) return;\n\n const resolvedNode = resolveNode(selectedDriveId, node);\n if (!resolvedNode) {\n console.error(`Node ${node.id} not found`);\n return;\n }\n\n return await renameNode(selectedDriveId, node.id, newName);\n }\n\n async function onCopyNode(src: Node, target: Node | undefined) {\n if (!selectedDriveId) return;\n const resolvedSrc = resolveNode(selectedDriveId, src);\n if (!resolvedSrc) {\n console.error(`Node ${src.id} not found`);\n return;\n }\n const resolvedTarget = resolveNode(selectedDriveId, target);\n\n await copyNode(selectedDriveId, resolvedSrc, resolvedTarget);\n }\n\n async function onMoveNode(src: Node, target: Node | undefined) {\n if (!selectedDriveId) return;\n\n const resolvedSrc = resolveNode(selectedDriveId, src);\n if (!resolvedSrc) {\n console.error(`Node ${src.id} not found`);\n return;\n }\n const resolvedTarget = resolveNode(selectedDriveId, target);\n\n // if node is already on target then ignore move\n if (\n (!resolvedTarget?.id && !src.parentFolder) ||\n resolvedTarget?.id === src.parentFolder\n ) {\n return;\n }\n await moveNode(selectedDriveId, resolvedSrc, resolvedTarget);\n }\n\n async function onDuplicateNode(src: Node) {\n if (!selectedDriveId) return;\n\n const resolvedSrc = resolveNode(selectedDriveId, src);\n if (!resolvedSrc) {\n console.error(`Node ${src.id} not found`);\n return;\n }\n\n const target = resolveNode(\n selectedDriveId,\n selectedFolder ?? selectedParentFolder,\n );\n await copyNode(selectedDriveId, resolvedSrc, target);\n }\n async function onAddAndSelectNewFolder(name: string) {\n if (!name) return;\n if (!selectedDriveId) return;\n\n const resolvedTarget = resolveNode(\n selectedDriveId,\n selectedFolder ?? selectedParentFolder,\n );\n if (!resolvedTarget) return;\n\n const newFolder = await onAddFolder(name, resolvedTarget);\n\n if (newFolder) {\n setSelectedNode(newFolder);\n }\n }\n\n async function onRenameDriveNodes(\n newName: string,\n nodeId: string,\n ): Promise<void> {\n if (!drives) return;\n\n // Find all drives that contain this node\n const drivesWithNode = drives.filter((drive) =>\n drive.state.global.nodes.some((n) => n.id === nodeId),\n );\n\n // Update node name in all parent drives\n await Promise.all(\n drivesWithNode.map((drive) =>\n renameDriveNode(drive.header.id, nodeId, newName),\n ),\n );\n }\n\n return {\n onAddFile,\n onAddFolder,\n onRenameNode,\n onCopyNode,\n onMoveNode,\n onDuplicateNode,\n onAddAndSelectNewFolder,\n onRenameDriveNodes,\n };\n}\n","import type { Node } from \"@powerhousedao/shared/document-drive\";\nimport { useNodesInSelectedDrive } from \"./items-in-selected-drive.js\";\n\n/** Returns a node in the selected drive by id. */\nexport function useNodeById(id: string | null | undefined): Node | undefined {\n const nodes = useNodesInSelectedDrive();\n return nodes?.find((n) => n.id === id);\n}\n","import type { Node } from \"@powerhousedao/shared/document-drive\";\nimport { useNodesInSelectedDrive } from \"./items-in-selected-drive.js\";\nimport { useSelectedNode } from \"./selected-node.js\";\n\n/** Returns the path to a node in the selected drive */\nexport function useNodePathById(id: string | null | undefined) {\n const nodes = useNodesInSelectedDrive();\n if (!nodes) return [];\n\n const path: Node[] = [];\n let current = nodes.find((n) => n.id === id);\n\n while (current) {\n path.push(current);\n if (!current.parentFolder) break;\n current = nodes.find((n) => n.id === current?.parentFolder);\n }\n\n return path.reverse();\n}\n\n/** Returns the path to the currently selected node in the selected drive. */\nexport function useSelectedNodePath() {\n const selectedNode = useSelectedNode();\n return useNodePathById(selectedNode?.id);\n}\n","import type { FolderNode } from \"@powerhousedao/shared/document-drive\";\nimport { useFolderById } from \"./folder-by-id.js\";\nimport { useNodeById } from \"./node-by-id.js\";\nimport { useSelectedNode } from \"./selected-node.js\";\n\nexport function useNodeParentFolderById(\n id: string | null | undefined,\n): FolderNode | undefined {\n const node = useNodeById(id);\n const parentFolder = useFolderById(node?.parentFolder);\n return parentFolder;\n}\n\nexport function useParentFolderForSelectedNode() {\n const node = useSelectedNode();\n return useNodeParentFolderById(node?.id);\n}\n","import type { DocumentDispatch } from \"@powerhousedao/reactor-browser\";\nimport { isFileNode } from \"@powerhousedao/shared/document-drive\";\nimport type { Action, PHDocument } from \"@powerhousedao/shared/document-model\";\nimport { NoSelectedDocumentError } from \"../errors.js\";\nimport type { DispatchFn, UseDispatchResult } from \"./dispatch.js\";\nimport { useDocumentById } from \"./document-by-id.js\";\nimport { useDocumentOfType } from \"./document-of-type.js\";\nimport { useSelectedNode } from \"./selected-node.js\";\n\n/** Returns the selected document id */\nexport function useSelectedDocumentId(): string | undefined {\n const selectedNode = useSelectedNode();\n return selectedNode && isFileNode(selectedNode) ? selectedNode.id : undefined;\n}\n\n/** Returns the selected document. */\nexport function useSelectedDocument(): readonly [\n PHDocument,\n DispatchFn<Action>,\n] {\n const selectedDocumentId = useSelectedDocumentId();\n const [document, dispatch] = useDocumentById(selectedDocumentId);\n if (!document) {\n throw new NoSelectedDocumentError();\n }\n return [document, dispatch] as const;\n}\n\n/** Returns the selected document. */\nexport function useSelectedDocumentSafe(): UseDispatchResult<\n PHDocument,\n Action\n> {\n const selectedDocumentId = useSelectedDocumentId();\n return useDocumentById(selectedDocumentId);\n}\n\n/** Returns the selected document of a specific type, throws an error if the found document has a different type */\nexport function useSelectedDocumentOfType(\n documentType: null | undefined,\n): never[];\nexport function useSelectedDocumentOfType<\n TDocument extends PHDocument,\n TAction extends Action,\n>(documentType: string): [TDocument, DocumentDispatch<TAction>];\nexport function useSelectedDocumentOfType<\n TDocument extends PHDocument,\n TAction extends Action,\n>(\n documentType: string | null | undefined,\n): never[] | [TDocument, DocumentDispatch<TAction>] {\n const documentId = useSelectedDocumentId();\n\n if (!documentType) {\n return [];\n }\n if (!documentId) {\n throw new NoSelectedDocumentError();\n }\n return useDocumentOfType<TDocument, TAction>(documentId, documentType);\n}\n","import type { SubgraphModule } from \"@powerhousedao/shared/document-model\";\nimport { useVetraPackages } from \"./vetra-packages.js\";\n\nexport function useSubgraphModules(): SubgraphModule[] | undefined {\n const vetraPackages = useVetraPackages();\n return vetraPackages.flatMap((pkg) => pkg.subgraphs || []);\n}\n","import {\n driveCollectionId,\n type GqlRequestChannel,\n} from \"@powerhousedao/reactor\";\nimport type { DocumentDriveDocument } from \"@powerhousedao/shared/document-drive\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { useSyncList } from \"./reactor.js\";\n\nexport type DriveSystemInfoState =\n | { status: \"local\" }\n | { status: \"loading\" }\n | { status: \"error\"; message: string }\n | {\n status: \"ready\";\n version: string;\n gitHash: string;\n gitUrl: string | null;\n host: string;\n };\n\nexport function deriveSystemUrl(channelUrl: string): string | null {\n try {\n const url = new URL(channelUrl);\n url.pathname = \"/graphql/system\";\n url.search = \"\";\n url.hash = \"\";\n return url.toString();\n } catch {\n return null;\n }\n}\n\nconst cache = new Map<string, DriveSystemInfoState>();\n\nexport function useDriveSystemInfo(\n drive: DocumentDriveDocument | undefined,\n): DriveSystemInfoState {\n const remotes = useSyncList();\n const driveId = drive?.header.id;\n\n const systemUrl = useMemo(() => {\n if (!driveId) return null;\n const remote = remotes.find(\n (r) => r.collectionId === driveCollectionId(\"main\", driveId),\n );\n const channelUrl = (remote?.channel as GqlRequestChannel | undefined)\n ?.config.url;\n if (typeof channelUrl !== \"string\") return null;\n return deriveSystemUrl(channelUrl);\n }, [remotes, driveId]);\n\n const [state, setState] = useState<DriveSystemInfoState>(() =>\n systemUrl\n ? (cache.get(systemUrl) ?? { status: \"loading\" })\n : { status: \"local\" },\n );\n\n useEffect(() => {\n if (!systemUrl) {\n setState({ status: \"local\" });\n return;\n }\n\n const cached = cache.get(systemUrl);\n if (cached && cached.status !== \"loading\") {\n setState(cached);\n return;\n }\n\n setState({ status: \"loading\" });\n cache.set(systemUrl, { status: \"loading\" });\n\n const controller = new AbortController();\n fetch(systemUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n query: \"{ system { version gitHash gitUrl } }\",\n }),\n signal: controller.signal,\n })\n .then(async (res) => {\n const json = (await res.json()) as {\n data?: {\n system?: {\n version: string;\n gitHash: string;\n gitUrl: string | null;\n };\n };\n errors?: Array<{ message: string }>;\n };\n if (json.errors?.length) {\n throw new Error(json.errors.map((e) => e.message).join(\"; \"));\n }\n const sys = json.data?.system;\n if (!sys) throw new Error(\"Missing system in response\");\n const next: DriveSystemInfoState = {\n status: \"ready\",\n version: sys.version,\n gitHash: sys.gitHash,\n gitUrl: sys.gitUrl ?? null,\n host: new URL(systemUrl).host,\n };\n cache.set(systemUrl, next);\n setState(next);\n })\n .catch((err: unknown) => {\n if (controller.signal.aborted) return;\n const message = err instanceof Error ? err.message : String(err);\n const next: DriveSystemInfoState = { status: \"error\", message };\n cache.set(systemUrl, next);\n setState(next);\n });\n\n return () => controller.abort();\n }, [systemUrl]);\n\n return state;\n}\n","import type { IReactorClient } from \"@powerhousedao/reactor\";\nimport { SyncStatus } from \"@powerhousedao/reactor\";\nimport type {\n DocumentDriveDocument,\n SharingType,\n} from \"@powerhousedao/shared/document-drive\";\n\n// legacy sync status types\nexport type UISyncStatus =\n | \"INITIAL_SYNC\"\n | \"SUCCESS\"\n | \"CONFLICT\"\n | \"MISSING\"\n | \"ERROR\"\n | \"SYNCING\";\n\nconst syncStatusToUI: Record<SyncStatus, UISyncStatus> = {\n [SyncStatus.Synced]: \"SUCCESS\",\n [SyncStatus.Outgoing]: \"SYNCING\",\n [SyncStatus.Incoming]: \"SYNCING\",\n [SyncStatus.OutgoingAndIncoming]: \"SYNCING\",\n [SyncStatus.Error]: \"ERROR\",\n};\n\nexport async function getDrives(\n reactor: IReactorClient,\n): Promise<DocumentDriveDocument[]> {\n const results = await reactor.find({\n type: \"powerhouse/document-drive\",\n });\n return results.results as DocumentDriveDocument[];\n}\n\nexport function getSyncStatus(\n documentId: string,\n sharingType: SharingType,\n): Promise<UISyncStatus | undefined> {\n return Promise.resolve(getSyncStatusSync(documentId, sharingType));\n}\n\nexport function getSyncStatusSync(\n documentId: string,\n sharingType: SharingType,\n): UISyncStatus | undefined {\n if (sharingType === \"LOCAL\") return;\n\n const syncManager =\n window.ph?.reactorClientModule?.reactorModule?.syncModule?.syncManager;\n if (!syncManager) return;\n\n const status = syncManager.getSyncStatus(documentId);\n if (status === undefined) return;\n\n return syncStatusToUI[status];\n}\n","import type {\n DocumentModelDocument,\n PHDocument,\n ValidationError,\n} from \"@powerhousedao/shared/document-model\";\nimport {\n validateInitialState,\n validateModules,\n validateStateSchemaName,\n} from \"@powerhousedao/shared/document-model\";\n\nexport const validateDocument = (document: PHDocument) => {\n const errors: ValidationError[] = [];\n\n if (document.header.documentType !== \"powerhouse/document-model\") {\n return errors;\n }\n\n const doc = document as DocumentModelDocument;\n const specs = doc.state.global.specifications[0];\n\n // validate initial state errors\n const initialStateErrors = Object.keys(specs.state).reduce<ValidationError[]>(\n (acc, scopeKey) => {\n const scope = scopeKey as keyof typeof specs.state;\n\n return [\n ...acc,\n ...validateInitialState(\n specs.state[scope].initialValue,\n scope !== \"global\",\n ).map((err) => ({\n ...err,\n message: `${err.message}. Scope: ${scope}`,\n details: { ...err.details, scope },\n })),\n ];\n },\n [],\n );\n\n // validate schema state errors\n const schemaStateErrors = Object.keys(specs.state).reduce<ValidationError[]>(\n (acc, scopeKey) => {\n const scope = scopeKey as keyof typeof specs.state;\n const isGlobalScope = scope === \"global\";\n\n return [\n ...acc,\n ...validateStateSchemaName(\n specs.state[scope].schema,\n doc.state.global?.name || doc.header.name || \"\",\n !isGlobalScope ? scope : \"\",\n !isGlobalScope,\n ).map((err) => ({\n ...err,\n message: `${err.message}. Scope: ${scope}`,\n details: { ...err.details, scope },\n })),\n ];\n },\n [],\n );\n\n // modules validation\n const modulesErrors = validateModules(specs.modules);\n\n return [...initialStateErrors, ...schemaStateErrors, ...modulesErrors];\n};\n","import type { PHDocument } from \"@powerhousedao/shared/document-model\";\nimport { exportFile } from \"../actions/document.js\";\nimport { showPHModal } from \"../hooks/modals.js\";\nimport { validateDocument } from \"./validate-document.js\";\n\nexport const exportDocument = (document?: PHDocument) => {\n if (!document) return;\n const validationErrors = validateDocument(document);\n\n if (validationErrors.length) {\n showPHModal({\n type: \"exportDocumentWithErrors\",\n documentId: document.header.id,\n });\n } else {\n return exportFile(document);\n }\n};\n","import type { Operation } from \"@powerhousedao/shared/document-model\";\n\nexport const getRevisionFromDate = (\n startDate?: Date,\n endDate?: Date,\n operations: Operation[] = [],\n) => {\n if (!startDate || !endDate) return 0;\n\n const operation = operations.find((operation) => {\n const operationDate = new Date(operation.timestampUtcMs);\n return operationDate >= startDate && operationDate <= endDate;\n });\n\n return operation ? operation.index : 0;\n};\n","import * as lzString from \"lz-string\";\nimport { GetDocumentWithOperationsDocument } from \"../graphql/gen/schema.js\";\n\nexport async function getDriveIdBySlug(driveUrl: string, slug: string) {\n if (!driveUrl) {\n return;\n }\n\n const urlParts = driveUrl.split(\"/\");\n urlParts.pop(); // remove id\n urlParts.pop(); // remove /d\n urlParts.push(\"drives\"); // add /drives\n const drivesUrl = urlParts.join(\"/\");\n const result = await fetch(drivesUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n query: `\n query getDriveIdBySlug($slug: String!) {\n driveIdBySlug(slug: $slug)\n }\n `,\n variables: {\n slug,\n },\n }),\n });\n\n const data = (await result.json()) as {\n data: { driveIdBySlug: string };\n };\n\n return data.data.driveIdBySlug;\n}\n\nexport function getSlugFromDriveUrl(driveUrl: string) {\n const urlParts = driveUrl.split(\"/\");\n return urlParts.pop();\n}\n\nexport function getSwitchboardGatewayUrlFromDriveUrl(driveUrl: string) {\n const urlParts = driveUrl.split(\"/\");\n urlParts.pop(); // remove id\n urlParts.pop(); // remove /d\n urlParts.push(\"graphql\"); // add /graphql\n return urlParts.join(\"/\");\n}\n\nexport function getDocumentGraphqlQuery() {\n const loc = GetDocumentWithOperationsDocument.loc;\n if (!loc) {\n throw new Error(\n \"GetDocumentWithOperationsDocument is misconfigured, loc is missing.\",\n );\n }\n return loc.source.body;\n}\n\nexport function buildDocumentSubgraphQuery(\n identifier: string,\n authToken?: string,\n) {\n const query = getDocumentGraphqlQuery();\n const variables = { identifier };\n const headers = authToken\n ? {\n Authorization: `Bearer ${authToken}`,\n }\n : undefined;\n\n const payload: Record<string, string> = {\n document: query.trim(),\n variables: JSON.stringify(variables, null, 2),\n };\n if (headers) {\n payload.headers = JSON.stringify(headers);\n }\n return lzString.compressToEncodedURIComponent(JSON.stringify(payload));\n}\n\nexport function buildDocumentSubgraphUrl(\n driveUrl: string,\n identifier: string,\n authToken?: string,\n) {\n const encodedQuery = buildDocumentSubgraphQuery(identifier, authToken);\n return `${driveUrl}?explorerURLState=${encodedQuery}`;\n}\n","import {\n driveCollectionId,\n type GqlRequestChannel,\n} from \"@powerhousedao/reactor\";\nimport type { PHDocument } from \"@powerhousedao/shared/document-model\";\nimport { useMemo } from \"react\";\nimport { buildDocumentSubgraphUrl } from \"../utils/index.js\";\nimport { useRenown, useSyncList, useUser } from \"./connect.js\";\nimport { useSelectedDrive } from \"./selected-drive.js\";\n\n/**\n * Hook that returns a function to generate a document's switchboard URL.\n * Only returns a function for documents in remote drives.\n * Returns null for local drives or when the document/drive cannot be determined.\n *\n * The returned function generates a fresh bearer token and builds the switchboard URL\n * with authentication when called.\n *\n * @param document - The document to create a switchboard URL generator for\n * @returns An async function that returns the switchboard URL, or null if not applicable\n */\nexport function useGetSwitchboardLink(\n document: PHDocument | undefined,\n): (() => Promise<string>) | null {\n const [drive] = useSelectedDrive();\n const remotes = useSyncList();\n\n const isRemoteDrive = useMemo(() => {\n return remotes.some(\n (remote) =>\n remote.collectionId === driveCollectionId(\"main\", drive.header.id),\n );\n }, [remotes, drive]);\n const remoteUrl = useMemo(() => {\n try {\n const remote = remotes.find(\n (remote) =>\n remote.collectionId === driveCollectionId(\"main\", drive.header.id),\n );\n\n const channelUrl = (remote?.channel as GqlRequestChannel | undefined)\n ?.config.url;\n if (typeof channelUrl === \"string\") {\n return channelUrl;\n }\n\n return null;\n } catch (error) {\n console.error(\"Error determining remote URL:\", error);\n return null;\n }\n }, [remotes, drive]);\n const renown = useRenown();\n const user = useUser();\n\n return useMemo(() => {\n if (!isRemoteDrive || !document?.header.id || !remoteUrl) {\n return null;\n }\n\n return async () => {\n // Get bearer token if user is authenticated\n const token = user?.address\n ? await renown?.getBearerToken({\n expiresIn: 600,\n aud: remoteUrl,\n })\n : undefined;\n\n // Build and return the switchboard URL with the document subgraph query\n return buildDocumentSubgraphUrl(remoteUrl, document.header.id, token);\n };\n }, [isRemoteDrive, remoteUrl, document, user, renown]);\n}\n","import { addFileWithProgress } from \"../actions/document.js\";\nimport type {\n ConflictResolution,\n FileUploadProgressCallback,\n UseOnDropFile,\n} from \"../types/upload.js\";\nimport { useDocumentTypes } from \"./document-types.js\";\nimport { useSelectedDriveId } from \"./selected-drive.js\";\nimport { useSelectedFolder } from \"./selected-folder.js\";\n\nexport const useOnDropFile: UseOnDropFile = (\n documentTypesOverride?: string[],\n) => {\n const selectedDriveId = useSelectedDriveId();\n const selectedFolder = useSelectedFolder();\n const documentTypes = useDocumentTypes();\n\n const onDropFile = async (\n file: File,\n onProgress?: FileUploadProgressCallback,\n resolveConflict?: ConflictResolution,\n ) => {\n if (!selectedDriveId) {\n console.warn(\"No selected drive - upload skipped\");\n return;\n }\n\n const fileName = file.name.replace(/\\..+/gim, \"\");\n const targetNodeId = selectedFolder?.id;\n\n // Return the FileNode directly from addFileWithProgress\n return await addFileWithProgress(\n file,\n selectedDriveId,\n fileName,\n targetNodeId,\n onProgress,\n documentTypesOverride ?? documentTypes,\n resolveConflict,\n );\n };\n\n return onDropFile;\n};\n","import { useAllowList } from \"./connect.js\";\nimport { useUser } from \"./renown.js\";\nexport function useUserPermissions() {\n const user = useUser();\n const allowList = useAllowList();\n if (!allowList) {\n return {\n isAllowedToCreateDocuments: true,\n isAllowedToEditDocuments: true,\n };\n }\n\n return {\n isAllowedToCreateDocuments: allowList.includes(user?.address ?? \"\"),\n isAllowedToEditDocuments: allowList.includes(user?.address ?? \"\"),\n };\n}\n","import type { PGlite } from \"@electric-sql/pglite\";\nimport { REACTOR_SCHEMA } from \"@powerhousedao/reactor\";\n\nasync function dropTablesInSchema(pg: PGlite, schema: string): Promise<void> {\n await pg.exec(`\nDO $$\nDECLARE\n _schemaname text := '${schema}';\n _tablename text;\nBEGIN\n FOR _tablename IN SELECT tablename FROM pg_catalog.pg_tables WHERE schemaname = _schemaname LOOP\n RAISE INFO 'Dropping table %.%', _schemaname, _tablename;\n EXECUTE format('DROP TABLE %I.%I CASCADE;', _schemaname, _tablename);\n END LOOP;\n IF NOT FOUND THEN\n RAISE WARNING 'Schema % does not exist', _schemaname;\n END IF;\nEND $$;\n`);\n}\n\nexport async function truncateAllTables(\n pg: PGlite,\n schema: string = REACTOR_SCHEMA,\n): Promise<void> {\n await dropTablesInSchema(pg, schema);\n}\n\nexport async function dropAllReactorStorage(pg: PGlite): Promise<void> {\n await dropTablesInSchema(pg, REACTOR_SCHEMA);\n\n // legacy\n await dropTablesInSchema(pg, \"public\");\n}\n","import type { IReactorClient } from \"@powerhousedao/reactor\";\nimport { type DocumentDriveDocument } from \"@powerhousedao/shared/document-drive\";\nimport { setDrives } from \"./hooks/drives.js\";\nimport { getDrives } from \"./utils/drives.js\";\n\nexport type ReactorDefaultDrivesConfig = {\n defaultDrivesUrl?: string[];\n};\n\nexport type RefreshReactorDataConfig = {\n debounceDelayMs?: number;\n immediateThresholdMs?: number;\n};\n\nconst DEFAULT_DEBOUNCE_DELAY_MS = 200;\nconst DEFAULT_IMMEDIATE_THRESHOLD_MS = 1000;\n\nasync function _refreshReactorData(reactor: IReactorClient) {\n const drives = await getDrives(reactor);\n\n setDrives(drives);\n}\n\nasync function _refreshReactorDataClient(reactor: IReactorClient | undefined) {\n if (!reactor) return;\n\n const result = await reactor.find({ type: \"powerhouse/document-drive\" });\n setDrives(result.results as DocumentDriveDocument[]);\n}\n\nfunction createDebouncedRefreshReactorData(\n debounceDelayMs = DEFAULT_DEBOUNCE_DELAY_MS,\n immediateThresholdMs = DEFAULT_IMMEDIATE_THRESHOLD_MS,\n) {\n let timeout: ReturnType<typeof setTimeout> | null = null;\n let lastRefreshTime = 0;\n\n return (reactor: IReactorClient, immediate = false) => {\n const now = Date.now();\n const timeSinceLastRefresh = now - lastRefreshTime;\n\n // Clear any pending timeout\n if (timeout !== null) {\n clearTimeout(timeout);\n }\n\n // If caller requests immediate execution or enough time has passed, execute immediately\n if (immediate || timeSinceLastRefresh >= immediateThresholdMs) {\n lastRefreshTime = now;\n return _refreshReactorData(reactor);\n }\n\n // Otherwise, debounce the call\n return new Promise<void>((resolve) => {\n timeout = setTimeout(() => {\n lastRefreshTime = Date.now();\n void _refreshReactorData(reactor).then(resolve);\n }, debounceDelayMs);\n });\n };\n}\n\nfunction createDebouncedRefreshReactorDataClient(\n debounceDelayMs = DEFAULT_DEBOUNCE_DELAY_MS,\n immediateThresholdMs = DEFAULT_IMMEDIATE_THRESHOLD_MS,\n) {\n let timeout: ReturnType<typeof setTimeout> | null = null;\n let lastRefreshTime = 0;\n\n return (reactor: IReactorClient | undefined, immediate = false) => {\n const now = Date.now();\n const timeSinceLastRefresh = now - lastRefreshTime;\n\n // Clear any pending timeout\n if (timeout !== null) {\n clearTimeout(timeout);\n }\n\n // If caller requests immediate execution or enough time has passed, execute immediately\n if (immediate || timeSinceLastRefresh >= immediateThresholdMs) {\n lastRefreshTime = now;\n return _refreshReactorDataClient(reactor);\n }\n\n // Otherwise, debounce the call\n return new Promise<void>((resolve) => {\n timeout = setTimeout(() => {\n lastRefreshTime = Date.now();\n void _refreshReactorDataClient(reactor).then(resolve);\n }, debounceDelayMs);\n });\n };\n}\n\nexport const refreshReactorData = createDebouncedRefreshReactorData();\nexport const refreshReactorDataClient =\n createDebouncedRefreshReactorDataClient();\n","import type { PackageInfo } from \"@powerhousedao/shared/registry\";\n\n// Strip a trailing \"/\" so we don't emit `http://host//packages` when a user\n// writes `packageRegistryUrl: \"http://host/\"`. Verdaccio's own web backend\n// 404s on the doubled slash, which cascades into an empty registry list and\n// masks the real install flow.\nfunction trimTrailingSlash(url: string): string {\n return url.endsWith(\"/\") ? url.slice(0, -1) : url;\n}\n\nexport async function getPackages(registryUrl: string) {\n const res = await fetch(`${trimTrailingSlash(registryUrl)}/packages`);\n if (!res.ok) throw new Error(`Registry error: HTTP ${res.status}`);\n const data = (await res.json()) as PackageInfo[];\n return data;\n}\n\nexport async function getPackagesByDocumentType(\n registryUrl: string,\n documentType: string,\n): Promise<string[]> {\n const encodedType = encodeURIComponent(documentType);\n const res = await fetch(\n `${trimTrailingSlash(registryUrl)}/packages/by-document-type?type=${encodedType}`,\n );\n if (!res.ok) throw new Error(`Registry error: HTTP ${res.status}`);\n return (await res.json()) as string[];\n}\n","import type { PackageInfo } from \"@powerhousedao/shared/registry\";\nimport { getPackages, getPackagesByDocumentType } from \"./fetchers.js\";\nimport type { PublishEvent } from \"./types.js\";\n\nfunction cdnUrlToApiUrl(cdnUrl: string): string {\n return cdnUrl.replace(/\\/-\\/cdn\\/?$/, \"\");\n}\nexport class RegistryClient {\n readonly apiUrl: string;\n\n constructor(cdnUrl: string) {\n this.apiUrl = cdnUrlToApiUrl(cdnUrl);\n }\n\n async getPackages(): Promise<PackageInfo[]> {\n const data = await getPackages(this.apiUrl);\n return data;\n }\n\n async getPackagesByDocumentType(documentType: string): Promise<string[]> {\n return await getPackagesByDocumentType(this.apiUrl, documentType);\n }\n\n async searchPackages(query: string): Promise<PackageInfo[]> {\n const packages = await this.getPackages();\n if (!query) return packages;\n const lowerQuery = query.toLowerCase();\n return packages.filter(\n (pkg) =>\n pkg.name.toLowerCase().includes(lowerQuery) ||\n pkg.manifest?.description?.toLowerCase().includes(lowerQuery),\n );\n }\n\n onPublish(callback: (event: PublishEvent) => void): () => void {\n const eventSource = new EventSource(`${this.apiUrl}/-/events`);\n\n eventSource.addEventListener(\"publish\", (e: MessageEvent<string>) => {\n const data = JSON.parse(e.data) as PublishEvent;\n callback(data);\n });\n\n return () => {\n eventSource.close();\n };\n }\n}\n","import type { Action } from \"@powerhousedao/shared/document-model\";\nimport type { TrackedAction } from \"./types.js\";\n\n/**\n * Tracks pending actions with their operation context (prevOpHash, prevOpIndex).\n * Actions are accumulated until flushed (on push).\n */\nexport class ActionTracker {\n private pending: TrackedAction[] = [];\n\n /** Track a new action with its operation context. */\n track(action: Action, prevOpHash: string, prevOpIndex: number): void {\n this.pending.push({ action, prevOpHash, prevOpIndex });\n }\n\n /** Flush all pending actions and return them. Clears the internal queue. */\n flush(): TrackedAction[] {\n const actions = this.pending;\n this.pending = [];\n return actions;\n }\n\n /** Number of pending actions. */\n get count(): number {\n return this.pending.length;\n }\n\n /** Prepend previously flushed actions back to the queue (for retry on failure). */\n restore(actions: TrackedAction[]): void {\n this.pending = [...actions, ...this.pending];\n }\n\n /** Clear all pending actions without returning them. */\n clear(): void {\n this.pending = [];\n }\n}\n","import type {\n GetDocumentResult,\n GetDocumentWithOperationsResult,\n GetOperationsResult,\n IRemoteClient,\n PropagationMode,\n RemoteControllerGraphQLClient,\n RemoteDocumentData,\n RemoteOperation,\n RemoteOperationResultPage,\n} from \"./types.js\";\n\n/**\n * Thin facade over the GraphQL SDK for remote document operations.\n */\nconst DEFAULT_PAGE_SIZE = 100;\n\nexport class RemoteClient implements IRemoteClient {\n private readonly pageSize: number;\n\n constructor(\n private readonly client: RemoteControllerGraphQLClient,\n pageSize?: number,\n ) {\n this.pageSize = pageSize ?? DEFAULT_PAGE_SIZE;\n }\n\n /** Fetch a document by identifier. Returns null if not found. */\n async getDocument(\n identifier: string,\n branch?: string,\n ): Promise<GetDocumentResult | null> {\n const result = await this.client.GetDocument({\n identifier,\n view: branch ? { branch } : undefined,\n });\n return result.document ?? null;\n }\n\n /**\n * Fetch a document and its operations.\n *\n * When scopes are provided and BatchGetDocumentWithOperations is available,\n * fetches the document and per-scope operations in a single HTTP request.\n * Otherwise falls back to GetDocumentWithOperations for the first page,\n * then paginates remaining operations per scope.\n */\n async getDocumentWithOperations(\n identifier: string,\n branch?: string,\n sinceRevision?: Record<string, number>,\n scopes?: string[],\n ): Promise<GetDocumentWithOperationsResult | null> {\n // Fast path: batch document + per-scope operations in one request\n if (\n this.client.BatchGetDocumentWithOperations &&\n scopes &&\n scopes.length > 0\n ) {\n return this.batchGetDocumentWithOperations(\n identifier,\n branch,\n sinceRevision,\n scopes,\n );\n }\n\n // Standard path: GetDocumentWithOperations + paginate if needed\n const result = await this.client.GetDocumentWithOperations({\n identifier,\n view: branch ? { branch } : undefined,\n operationsPaging: {\n limit: this.pageSize,\n cursor: null,\n },\n });\n\n if (!result.document) return null;\n\n const doc = result.document.document;\n const opsPage = doc.operations;\n const operationsByScope: Record<string, RemoteOperation[]> = {};\n\n if (opsPage) {\n for (const op of opsPage.items) {\n (operationsByScope[op.action.scope] ??= []).push(op);\n }\n }\n\n // Check if we have all expected operations by comparing against revisionsList\n const expectedTotal = doc.revisionsList.reduce(\n (sum, r) => sum + r.revision,\n 0,\n );\n const fetchedTotal = opsPage?.items.length ?? 0;\n\n if (fetchedTotal >= expectedTotal) {\n return {\n document: doc,\n childIds: result.document.childIds,\n operations: { operationsByScope },\n };\n }\n\n // Missing operations — fetch all per scope\n const allScopes = doc.revisionsList.map((r) => r.scope);\n const allOps = await this.getAllOperations(\n doc.id,\n branch,\n sinceRevision,\n allScopes,\n );\n\n return {\n document: doc,\n childIds: result.document.childIds,\n operations: allOps,\n };\n }\n\n /**\n * Fetch document + per-scope operations in a single HTTP request\n * via BatchGetDocumentWithOperations, then paginate any remaining pages.\n */\n private async batchGetDocumentWithOperations(\n identifier: string,\n branch: string | undefined,\n sinceRevision: Record<string, number> | undefined,\n scopes: string[],\n ): Promise<GetDocumentWithOperationsResult | null> {\n const view = branch ? { branch } : undefined;\n const filters = scopes.map((scope) => ({\n documentId: identifier,\n branch: branch ?? null,\n sinceRevision: sinceRevision?.[scope] ?? 0,\n scopes: [scope],\n }));\n const pagings = scopes.map(() => ({\n limit: this.pageSize,\n cursor: null as string | null,\n }));\n\n const result = await this.client.BatchGetDocumentWithOperations!(\n identifier,\n view,\n filters,\n pagings,\n );\n\n if (!result.document) return null;\n\n const operationsByScope: Record<string, RemoteOperation[]> = {};\n let pending: {\n scope: string;\n filter: (typeof filters)[0];\n cursor: string;\n }[] = [];\n\n for (let i = 0; i < scopes.length; i++) {\n const page = result.operations[i];\n for (const op of page.items) {\n (operationsByScope[op.action.scope] ??= []).push(op);\n }\n if (page.hasNextPage && page.cursor) {\n pending.push({\n scope: scopes[i],\n filter: filters[i],\n cursor: page.cursor,\n });\n }\n }\n\n // Continue pagination for scopes with more pages\n while (pending.length > 0) {\n const pages = await this.fetchOperationPages(\n pending.map((p) => p.filter),\n pending.map((p) => ({ limit: this.pageSize, cursor: p.cursor })),\n );\n\n const nextPending: typeof pending = [];\n for (let i = 0; i < pending.length; i++) {\n const page = pages[i];\n for (const op of page.items) {\n (operationsByScope[op.action.scope] ??= []).push(op);\n }\n if (page.hasNextPage && page.cursor) {\n nextPending.push({ ...pending[i], cursor: page.cursor });\n }\n }\n pending = nextPending;\n }\n\n return {\n document: result.document.document,\n childIds: result.document.childIds,\n operations: { operationsByScope },\n };\n }\n\n /**\n * Fetch all operations for a document, paginating through all pages.\n * Each scope is queried individually because the API only returns\n * pagination cursors for single-scope queries.\n */\n async getAllOperations(\n documentId: string,\n branch?: string,\n sinceRevision?: Record<string, number>,\n scopes?: string[],\n ): Promise<GetOperationsResult> {\n // When scopes are specified, query each scope in parallel.\n // Uses a single composed request per pagination round when available.\n if (scopes && scopes.length > 0) {\n const operationsByScope: Record<string, RemoteOperation[]> = {};\n\n // Tracks scopes still being paginated, each with its own filter and cursor\n let pending = scopes.map((scope) => ({\n scope,\n filter: {\n documentId,\n branch: branch ?? null,\n sinceRevision: sinceRevision?.[scope] ?? 0,\n scopes: [scope],\n },\n cursor: null as string | null,\n }));\n\n while (pending.length > 0) {\n const pages = await this.fetchOperationPages(\n pending.map((p) => p.filter),\n pending.map((p) => ({ limit: this.pageSize, cursor: p.cursor })),\n );\n\n const nextPending: typeof pending = [];\n\n for (let i = 0; i < pending.length; i++) {\n const page = pages[i];\n for (const op of page.items) {\n (operationsByScope[op.action.scope] ??= []).push(op);\n }\n if (page.hasNextPage && page.cursor) {\n nextPending.push({ ...pending[i], cursor: page.cursor });\n }\n }\n\n pending = nextPending;\n }\n\n return { operationsByScope };\n }\n\n // No scopes specified — single query for all scopes (no per-scope sinceRevision)\n return this.fetchOperationsForScope(documentId, branch);\n }\n\n /**\n * Fetch one page of operations per filter.\n * Uses the composed query (single HTTP request) when available,\n * otherwise falls back to parallel individual requests.\n */\n private async fetchOperationPages(\n filters: Parameters<\n RemoteControllerGraphQLClient[\"GetDocumentOperations\"]\n >[0][\"filter\"][],\n pagings: Parameters<\n RemoteControllerGraphQLClient[\"GetDocumentOperations\"]\n >[0][\"paging\"][],\n ): Promise<RemoteOperationResultPage[]> {\n if (this.client.BatchGetDocumentOperations) {\n return this.client.BatchGetDocumentOperations(filters, pagings);\n }\n\n return Promise.all(\n filters.map((filter, i) =>\n this.client\n .GetDocumentOperations({ filter, paging: pagings[i] })\n .then((r) => r.documentOperations),\n ),\n );\n }\n\n /** Fetch all pages of operations for a single scope (or all scopes if none specified). */\n private async fetchOperationsForScope(\n documentId: string,\n branch?: string,\n sinceRevision?: number,\n scope?: string,\n ): Promise<GetOperationsResult> {\n const operationsByScope: Record<string, RemoteOperation[]> = {};\n let cursor: string | null | undefined;\n let hasNextPage = true;\n\n while (hasNextPage) {\n const result = await this.client.GetDocumentOperations({\n filter: {\n documentId,\n branch: branch ?? null,\n sinceRevision: sinceRevision ?? 0,\n scopes: scope ? [scope] : null,\n },\n paging: {\n limit: this.pageSize,\n cursor: cursor ?? null,\n },\n });\n\n const page = result.documentOperations;\n\n for (const op of page.items) {\n const s = op.action.scope;\n (operationsByScope[s] ??= []).push(op);\n }\n\n hasNextPage = page.hasNextPage;\n cursor = page.cursor;\n }\n\n return { operationsByScope };\n }\n\n /** Push actions to an existing document via MutateDocument. */\n async pushActions(\n documentIdentifier: string,\n actions: ReadonlyArray<NonNullable<unknown>>,\n branch?: string,\n ): Promise<RemoteDocumentData> {\n const result = await this.client.MutateDocument({\n documentIdentifier,\n actions,\n view: branch ? { branch } : undefined,\n });\n return result.mutateDocument;\n }\n\n /** Create a new document on the remote. */\n async createDocument(\n document: NonNullable<unknown>,\n parentIdentifier?: string,\n ): Promise<RemoteDocumentData> {\n const result = await this.client.CreateDocument({\n document,\n parentIdentifier: parentIdentifier ?? null,\n });\n return result.createDocument;\n }\n\n /** Create an empty document of a given type on the remote. */\n async createEmptyDocument(\n documentType: string,\n parentIdentifier?: string,\n ): Promise<RemoteDocumentData> {\n const result = await this.client.CreateEmptyDocument({\n documentType,\n parentIdentifier: parentIdentifier ?? null,\n });\n return result.createEmptyDocument;\n }\n\n /** Delete a document on the remote. Returns true if successful. */\n async deleteDocument(\n identifier: string,\n propagate?: PropagationMode,\n ): Promise<boolean> {\n const result = await this.client.DeleteDocument({\n identifier,\n propagate,\n });\n return result.deleteDocument;\n }\n}\n","import type {\n DocumentOperations,\n Operation,\n PHBaseState,\n PHDocument,\n} 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 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 attachments: remote.action.attachments?.map((a) => ({\n data: a.data,\n mimeType: a.mimeType,\n hash: a.hash,\n extension: a.extension ?? undefined,\n fileName: a.fileName ?? undefined,\n })),\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 * Deserialize a signature string back to a 5-element tuple.\n * The server serializes tuples via `tuple.join(\", \")`.\n */\nexport function deserializeSignature(\n s: string,\n): [string, string, string, string, string] {\n const parts = s.split(\", \");\n return [\n parts[0] ?? \"\",\n parts[1] ?? \"\",\n parts[2] ?? \"\",\n parts[3] ?? \"\",\n parts[4] ?? \"\",\n ];\n}\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 Action,\n DocumentOperations,\n Operation,\n PHBaseState,\n PHDocument,\n PHDocumentHeader,\n} from \"@powerhousedao/shared/document-model\";\nimport type { PHDocumentController } from \"document-model\";\nimport { ActionTracker } from \"./action-tracker.js\";\nimport { RemoteClient } from \"./remote-client.js\";\nimport type {\n ConflictStrategy,\n DocumentChangeListener,\n IRemoteClient,\n IRemoteController,\n PropagationMode,\n PushResult,\n RemoteControllerOptions,\n RemoteDocumentChangeEvent,\n RemoteDocumentData,\n RemoteOperation,\n SyncStatus,\n TrackedAction,\n} from \"./types.js\";\nimport {\n ConflictError,\n buildPulledDocument,\n convertRemoteOperations,\n extractRevisionMap,\n hasRevisionConflict,\n screamingSnakeToCamel,\n} from \"./utils.js\";\n\n/** Extract TState from a PHDocumentController subclass. */\ntype InferState<C> = C extends PHDocumentController<infer S> ? S : never;\n\n/**\n * Extract action methods from a controller type.\n * These are the dynamically-added methods (not on the base PHDocumentController prototype).\n */\ntype ActionMethodsOf<C, TRemote> = {\n [K in Exclude<keyof C, keyof PHDocumentController<any>>]: C[K] extends (\n input: infer I,\n ) => unknown\n ? (input: I) => TRemote & ActionMethodsOf<C, TRemote>\n : C[K];\n};\n\n/** The full return type: RemoteDocumentController + action methods. */\nexport type RemoteDocumentControllerWith<C extends PHDocumentController<any>> =\n RemoteDocumentController<C> & ActionMethodsOf<C, RemoteDocumentController<C>>;\n\n/**\n * A controller that wraps a PHDocumentController with remote push/pull capabilities.\n * Composes a local controller and adds GraphQL-based sync with a reactor server.\n */\nexport class RemoteDocumentController<\n TController extends PHDocumentController<any>,\n> implements IRemoteController<InferState<TController>> {\n private inner: TController;\n private readonly remoteClient: IRemoteClient;\n private readonly tracker = new ActionTracker();\n private readonly options: RemoteControllerOptions;\n private documentId: string;\n private remoteRevision: Record<string, number> = {};\n private hasPulled = false;\n private pushScheduled = false;\n private pushQueue: Promise<void> = Promise.resolve();\n private listeners: DocumentChangeListener[] = [];\n\n private constructor(inner: TController, options: RemoteControllerOptions) {\n this.inner = inner;\n this.options = options;\n this.documentId = options.documentId ?? \"\";\n this.remoteClient = new RemoteClient(\n options.client,\n options.operationsPageSize,\n );\n\n this.setupActionInterceptors();\n }\n\n // --- State access (delegated to inner controller) ---\n\n get header(): PHDocumentHeader {\n return this.inner.header;\n }\n\n get state(): InferState<TController> {\n return this.inner.state as InferState<TController>;\n }\n\n get operations(): DocumentOperations {\n return this.inner.operations;\n }\n\n get document(): PHDocument<InferState<TController>> {\n return this.inner.document as PHDocument<InferState<TController>>;\n }\n\n get status(): SyncStatus {\n return {\n pendingActionCount: this.tracker.count,\n connected: this.documentId !== \"\",\n documentId: this.documentId,\n remoteRevision: { ...this.remoteRevision },\n };\n }\n\n /** Register a listener for document changes. Returns an unsubscribe function. */\n onChange(listener: DocumentChangeListener): () => void {\n this.listeners.push(listener);\n return () => {\n this.listeners = this.listeners.filter((l) => l !== listener);\n };\n }\n\n private notifyListeners(source: RemoteDocumentChangeEvent[\"source\"]): void {\n if (this.listeners.length === 0) return;\n const event: RemoteDocumentChangeEvent = {\n source,\n document: this.document,\n };\n for (const listener of this.listeners) {\n listener(event);\n }\n }\n\n // --- Remote operations ---\n\n /** Push all pending actions to remote, then pull latest state. */\n async push(): Promise<PushResult> {\n let tracked = this.tracker.flush();\n\n if (tracked.length === 0 && this.documentId !== \"\") {\n // Nothing to push, just pull (reuses the fetched document)\n const remoteDocument = await this.pull();\n return {\n remoteDocument,\n actionCount: 0,\n operations: [],\n };\n }\n\n try {\n await this.ensureRemoteDocument();\n\n // Conflict detection: check if remote has changed since last pull\n if (this.options.onConflict && tracked.length > 0) {\n tracked = await this.handleConflicts(tracked, this.options.onConflict);\n }\n } catch (error) {\n // Pre-push failure: restore actions so they can be retried\n this.tracker.restore(tracked);\n throw error;\n }\n\n let pushedActions: Action[] = [];\n\n try {\n if (tracked.length > 0) {\n const actions = await this.prepareActionsForPush(tracked);\n pushedActions = actions;\n\n await this.remoteClient.pushActions(\n this.documentId,\n actions,\n this.options.branch,\n );\n }\n } catch (error) {\n // Push failed: restore actions so they can be retried\n this.tracker.restore(tracked);\n throw error;\n }\n\n // Pull remote state to reconcile (remote is source of truth).\n // If this fails, actions were already pushed — do NOT restore them.\n const remoteDocument = await this.pull();\n\n return {\n remoteDocument,\n actionCount: tracked.length,\n operations: pushedActions,\n };\n }\n\n /** Delete the document on the remote. */\n async delete(propagate?: PropagationMode): Promise<boolean> {\n if (this.documentId === \"\") {\n throw new Error(\"Cannot delete: no document ID set\");\n }\n const result = await this.remoteClient.deleteDocument(\n this.documentId,\n propagate,\n );\n return result;\n }\n\n /** Pull latest state from remote, replacing local document. Returns the remote document data. */\n async pull(): Promise<RemoteDocumentData> {\n if (this.documentId === \"\") {\n throw new Error(\"Cannot pull: no document ID set\");\n }\n\n const { remoteDoc, operations } = await this.fetchDocumentAndOperations();\n\n // Get module from inner controller\n const initialDoc = this.inner.module.utils.createDocument();\n const pulledDocument = buildPulledDocument(\n remoteDoc,\n operations,\n initialDoc,\n this.options.branch ?? \"main\",\n );\n\n // Recreate inner controller with pulled document\n const ControllerClass = this.inner.constructor as new (\n doc?: PHDocument<PHBaseState>,\n ) => TController;\n this.inner = new ControllerClass(pulledDocument);\n\n // Re-setup interceptors on the new inner instance\n this.setupActionInterceptors();\n\n // Clear tracker (remote is source of truth)\n this.tracker.clear();\n\n // Update remote revision\n this.remoteRevision = extractRevisionMap(remoteDoc.revisionsList);\n\n this.notifyListeners(\"pull\");\n\n return remoteDoc;\n }\n\n // --- Static factories ---\n\n /**\n * Pull an existing document from remote and create a controller for it.\n */\n static async pull<C extends PHDocumentController<any>>(\n ControllerClass: new (doc?: PHDocument<any>) => C,\n options: RemoteControllerOptions,\n ): Promise<RemoteDocumentControllerWith<C>> {\n // Create a temporary instance to access the module\n const temp = new ControllerClass();\n const remote = new RemoteDocumentController(temp, options);\n\n if (options.documentId) {\n await remote.pull();\n }\n\n return remote as RemoteDocumentControllerWith<C>;\n }\n\n /**\n * Wrap an existing controller instance with remote capabilities.\n * Pending local actions on the inner controller are NOT tracked\n * (only new actions through the remote controller are tracked).\n */\n static from<C extends PHDocumentController<any>>(\n controller: C,\n options: RemoteControllerOptions,\n ): RemoteDocumentControllerWith<C> {\n return new RemoteDocumentController(\n controller,\n options,\n ) as RemoteDocumentControllerWith<C>;\n }\n\n // --- Private methods ---\n\n /** Create the document on the remote if it doesn't exist yet. */\n private async ensureRemoteDocument(): Promise<void> {\n if (this.documentId !== \"\") return;\n const remoteDoc = await this.remoteClient.createEmptyDocument(\n this.inner.header.documentType,\n this.options.parentIdentifier,\n );\n this.documentId = remoteDoc.id;\n }\n\n /** Set up interceptors for all action methods on the inner controller. */\n private setupActionInterceptors(): void {\n // Get the module's action keys from the inner controller\n const module = (this.inner as Record<string, unknown>)[\"module\"] as {\n actions: Record<string, unknown>;\n };\n\n for (const actionType in module.actions) {\n // Skip if it's a property on our own class\n if (actionType in RemoteDocumentController.prototype) {\n continue;\n }\n\n Object.defineProperty(this, actionType, {\n value: (input: unknown) => {\n // Snapshot operation counts per scope BEFORE applying\n const opCountsBefore: Record<string, number> = {};\n for (const scope in this.inner.operations) {\n opCountsBefore[scope] = this.inner.operations[scope].length;\n }\n\n // Apply locally via inner controller\n (\n this.inner as unknown as Record<string, (input: unknown) => unknown>\n )[actionType](input);\n\n // Find which scope got the new operation\n const newOp = this.findNewOperation(opCountsBefore);\n\n // Get prevOp in the SAME scope as the new operation\n const prevOp = newOp\n ? this.getLastOperationInScope(newOp.action.scope, newOp)\n : undefined;\n const prevOpHash = prevOp?.hash ?? \"\";\n const prevOpIndex = prevOp?.index ?? -1;\n\n if (!newOp) {\n // Action produced no operation (NOOP) — nothing to track\n return this;\n }\n\n // Track the action for push\n this.tracker.track(newOp.action, prevOpHash, prevOpIndex);\n this.notifyListeners(\"action\");\n\n if (this.options.mode === \"streaming\") {\n this.schedulePush();\n }\n\n return this;\n },\n enumerable: true,\n configurable: true,\n });\n }\n }\n\n /**\n * Find the new operation added after applying an action,\n * by comparing current operation counts against a previous snapshot.\n */\n private findNewOperation(\n opCountsBefore: Record<string, number>,\n ): Operation | undefined {\n const ops = this.inner.operations;\n for (const scope in ops) {\n const scopeOps = ops[scope];\n const prevCount = opCountsBefore[scope] ?? 0;\n if (scopeOps.length > prevCount) {\n return scopeOps[scopeOps.length - 1];\n }\n }\n return undefined;\n }\n\n /**\n * Get the last operation in a specific scope, optionally excluding\n * a given operation (e.g. the one just added).\n */\n private getLastOperationInScope(\n scope: string,\n excludeOp?: Operation,\n ): Operation | undefined {\n const scopeOps = this.inner.operations[scope];\n if (scopeOps.length === 0) return undefined;\n for (let i = scopeOps.length - 1; i >= 0; i--) {\n if (scopeOps[i] !== excludeOp) return scopeOps[i];\n }\n return undefined;\n }\n\n /**\n * Detect and handle conflicts between local pending actions and remote state.\n * Returns the (possibly rebased) tracked actions to push.\n */\n private async handleConflicts(\n localTracked: TrackedAction[],\n strategy: ConflictStrategy,\n ): Promise<TrackedAction[]> {\n // Fetch current remote document to get latest revisions\n const remoteResult = await this.remoteClient.getDocument(\n this.documentId,\n this.options.branch,\n );\n if (!remoteResult) {\n throw new Error(`Document \"${this.documentId}\" not found on remote`);\n }\n\n const currentRevision = extractRevisionMap(\n remoteResult.document.revisionsList,\n );\n\n // Only check scopes that local actions touch\n const localScopes = new Set(localTracked.map((t) => t.action.scope));\n\n if (\n !hasRevisionConflict(currentRevision, this.remoteRevision, localScopes)\n ) {\n return localTracked;\n }\n\n // Fetch new remote operations for conflicting scopes in parallel,\n // using the correct sinceRevision for each scope.\n const conflictingScopes = [...localScopes].filter(\n (scope) =>\n (currentRevision[scope] ?? 0) > (this.remoteRevision[scope] ?? 0),\n );\n const { operationsByScope } = await this.remoteClient.getAllOperations(\n this.documentId,\n this.options.branch,\n this.remoteRevision,\n conflictingScopes,\n );\n const remoteOperations: Record<string, RemoteOperation[]> = {};\n for (const [scope, ops] of Object.entries(operationsByScope)) {\n remoteOperations[scope] = ops;\n }\n\n const conflictInfo = {\n remoteOperations,\n localActions: localTracked,\n knownRevision: { ...this.remoteRevision },\n currentRevision: { ...currentRevision },\n };\n\n if (strategy === \"reject\") {\n throw new ConflictError(conflictInfo);\n }\n\n if (strategy === \"rebase\") {\n return this.pullAndReplay(localTracked.map((t) => t.action));\n }\n\n // Custom merge handler (only possibility left after narrowing)\n const mergedActions = await strategy(conflictInfo);\n return this.pullAndReplay(mergedActions);\n }\n\n /**\n * Pull latest remote state and replay actions through interceptors.\n * Returns newly tracked actions with correct prevOpHash values.\n */\n private async pullAndReplay(actions: Action[]): Promise<TrackedAction[]> {\n await this.pull();\n\n for (const action of actions) {\n // Action types are SCREAMING_SNAKE_CASE but interceptors use camelCase\n const methodName = screamingSnakeToCamel(action.type);\n const method = (\n this as unknown as Record<string, (input: unknown) => unknown>\n )[methodName];\n if (typeof method === \"function\") {\n method.call(this, action.input);\n }\n }\n\n return this.tracker.flush();\n }\n\n /** Prepare actions for push, optionally signing them. */\n private async prepareActionsForPush(\n tracked: { action: Action; prevOpHash: string; prevOpIndex: number }[],\n ) {\n const actions: Action[] = [];\n\n for (const { action, prevOpHash, prevOpIndex } of tracked) {\n let prepared: Action = {\n ...action,\n context: {\n ...action.context,\n prevOpHash,\n prevOpIndex,\n },\n };\n\n if (this.options.signer) {\n prepared = await this.signAction(prepared);\n }\n\n actions.push(prepared);\n }\n\n return actions;\n }\n\n /** Sign an action using the configured signer, preserving existing signatures. */\n private async signAction(action: Action): Promise<Action> {\n const signer = this.options.signer!;\n const signature = await signer.signAction(action);\n const existingSignatures = action.context?.signer?.signatures ?? [];\n return {\n ...action,\n context: {\n ...action.context,\n signer: {\n user: signer.user!,\n app: signer.app!,\n signatures: [...existingSignatures, signature],\n },\n },\n };\n }\n\n /**\n * Fetch document and operations from the remote.\n *\n * On the first pull, uses the combined document+operations query.\n * On subsequent pulls, fetches only new operations per scope using\n * sinceRevision, then merges with existing local operations.\n * Falls back to a full fetch if the merge produces a count mismatch.\n */\n private async fetchDocumentAndOperations(): Promise<{\n remoteDoc: RemoteDocumentData;\n operations: DocumentOperations;\n }> {\n // Incremental fetch: use sinceRevision per scope\n if (this.hasPulled) {\n return this.incrementalFetch();\n }\n\n // Initial fetch: combined document + operations query\n const result = await this.remoteClient.getDocumentWithOperations(\n this.documentId,\n this.options.branch,\n );\n\n if (!result) {\n throw new Error(`Document \"${this.documentId}\" not found on remote`);\n }\n\n this.hasPulled = true;\n return {\n remoteDoc: result.document,\n operations: convertRemoteOperations(result.operations.operationsByScope),\n };\n }\n\n /**\n * Incremental fetch: fetches the document and only new operations per scope\n * using sinceRevision in a single request when possible.\n * Falls back to a full fetch on count mismatch.\n */\n private async incrementalFetch(): Promise<{\n remoteDoc: RemoteDocumentData;\n operations: DocumentOperations;\n }> {\n const scopes = Object.keys(this.remoteRevision);\n\n const result = await this.remoteClient.getDocumentWithOperations(\n this.documentId,\n this.options.branch,\n this.remoteRevision,\n scopes.length > 0 ? scopes : undefined,\n );\n\n if (!result) {\n throw new Error(`Document \"${this.documentId}\" not found on remote`);\n }\n\n const remoteDoc = result.document;\n const expectedRevision = extractRevisionMap(remoteDoc.revisionsList);\n\n const newOps = convertRemoteOperations(result.operations.operationsByScope);\n const merged = this.mergeOperations(this.inner.operations, newOps);\n\n // Validate: merged operation counts must match remote revisions\n if (this.hasExpectedOperationCounts(merged, expectedRevision)) {\n return { remoteDoc, operations: merged };\n }\n\n // Mismatch — do a full fetch\n return this.fullFetch(remoteDoc);\n }\n\n /**\n * Full fetch fallback: fetches all operations from the beginning.\n * Used when an incremental fetch produces a count mismatch.\n */\n private async fullFetch(remoteDoc: RemoteDocumentData): Promise<{\n remoteDoc: RemoteDocumentData;\n operations: DocumentOperations;\n }> {\n const { operationsByScope } = await this.remoteClient.getAllOperations(\n this.documentId,\n this.options.branch,\n );\n\n return {\n remoteDoc,\n operations: convertRemoteOperations(operationsByScope),\n };\n }\n\n /**\n * Validate that the merged operations match the expected revision per scope.\n * Each scope's operation count should equal its revision number.\n */\n private hasExpectedOperationCounts(\n operations: DocumentOperations,\n expectedRevision: Record<string, number>,\n ): boolean {\n for (const [scope, revision] of Object.entries(expectedRevision)) {\n const opCount = scope in operations ? operations[scope].length : 0;\n if (opCount !== revision) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * Merge existing local operations with newly fetched operations.\n * Appends new operations to existing ones per scope.\n */\n private mergeOperations(\n existingOps: DocumentOperations,\n newOps: DocumentOperations,\n ): DocumentOperations {\n const merged: DocumentOperations = {};\n\n // Copy existing operations\n for (const [scope, ops] of Object.entries(existingOps)) {\n if (ops.length > 0) {\n merged[scope] = [...ops];\n }\n }\n\n // Append new operations per scope\n for (const [scope, ops] of Object.entries(newOps)) {\n if (ops.length > 0) {\n (merged[scope] ??= []).push(...ops);\n }\n }\n\n return merged;\n }\n\n /** Schedule a push via microtask (for streaming mode coalescing). */\n private schedulePush(): void {\n if (this.pushScheduled) return;\n this.pushScheduled = true;\n queueMicrotask(() => {\n this.pushScheduled = false;\n // Chain onto the push queue to prevent concurrent pushes\n this.pushQueue = this.pushQueue.then(async () => {\n try {\n await this.push();\n } catch (error: unknown) {\n // Actions remain in tracker for retry\n this.options.onPushError?.(error);\n }\n });\n });\n }\n}\n","export abstract class BaseStorage<V> implements Iterable<[string, V]> {\n abstract get(key: string): V | undefined;\n abstract set(key: string, value: V): void;\n abstract delete(key: string): boolean;\n abstract has(key: string): boolean;\n abstract clear(): void;\n abstract entries(): IterableIterator<[string, V]>;\n abstract keys(): IterableIterator<string>;\n abstract values(): IterableIterator<V>;\n\n [Symbol.iterator](): IterableIterator<[string, V]> {\n return this.entries();\n }\n\n forEach(\n callback: (value: V, key: string, storage: BaseStorage<V>) => void,\n ): void {\n for (const [key, value] of this) {\n callback(value, key, this);\n }\n }\n}\n","import { BaseStorage } from \"./base-storage.js\";\n\nexport class BrowserLocalStorage<V> extends BaseStorage<V> {\n #namespace: string;\n #storage = window.localStorage;\n constructor(namespace: string) {\n super();\n this.#namespace = namespace;\n }\n\n #readMap(): Map<string, V> {\n const raw = this.#storage.getItem(this.#namespace);\n\n if (!raw) {\n return new Map();\n }\n\n return new Map(JSON.parse(raw) as [string, V][]);\n }\n\n #writeMap(map: Map<string, V>): void {\n this.#storage.setItem(\n this.#namespace,\n JSON.stringify(Array.from(map.entries())),\n );\n }\n\n get(key: string): V | undefined {\n return this.#readMap().get(key);\n }\n\n set(key: string, value: V): void {\n const map = this.#readMap();\n map.set(key, value);\n this.#writeMap(map);\n }\n\n delete(key: string): boolean {\n const map = this.#readMap();\n const deleted = map.delete(key);\n if (deleted) {\n this.#writeMap(map);\n }\n return deleted;\n }\n\n has(key: string): boolean {\n return this.#readMap().has(key);\n }\n\n clear(): void {\n this.#storage.removeItem(this.#namespace);\n }\n\n entries(): IterableIterator<[string, V]> {\n return this.#readMap().entries();\n }\n\n keys(): IterableIterator<string> {\n return this.#readMap().keys();\n }\n\n values(): IterableIterator<V> {\n return this.#readMap().values();\n }\n\n [Symbol.iterator](): IterableIterator<[string, V]> {\n return this.#readMap().entries();\n }\n}\n"],"mappings":"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"}