@arbidocs/react 0.5.106 → 0.5.107
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/README.md +9 -1
- package/dist/artifacts/index.cjs +13 -13
- package/dist/artifacts/index.js +3 -3
- package/dist/calls/livekit/index.cjs +48 -48
- package/dist/calls/livekit/index.js +3 -3
- package/dist/{chunk-XOS7ISIR.cjs → chunk-5HDKL6XB.cjs} +57 -57
- package/dist/chunk-5HDKL6XB.cjs.map +1 -0
- package/dist/{chunk-M74JCOXW.js → chunk-6H3O63TQ.js} +7 -4
- package/dist/chunk-6H3O63TQ.js.map +1 -0
- package/dist/{chunk-Q2GNEVG2.cjs → chunk-7LIMHY56.cjs} +7 -4
- package/dist/chunk-7LIMHY56.cjs.map +1 -0
- package/dist/{chunk-ZGGDH54R.js → chunk-CPQ3CU4B.js} +3 -3
- package/dist/{chunk-ZGGDH54R.js.map → chunk-CPQ3CU4B.js.map} +1 -1
- package/dist/{chunk-VAO76OJO.js → chunk-DQALOQPI.js} +4 -4
- package/dist/chunk-DQALOQPI.js.map +1 -0
- package/dist/{chunk-7NKF3VUN.js → chunk-FZJMA32S.js} +4 -4
- package/dist/{chunk-7NKF3VUN.js.map → chunk-FZJMA32S.js.map} +1 -1
- package/dist/{chunk-AXKIOI2U.js → chunk-H5M7FXLB.js} +4 -4
- package/dist/chunk-H5M7FXLB.js.map +1 -0
- package/dist/{chunk-K7UUWND5.cjs → chunk-HD5H2PPP.cjs} +66 -66
- package/dist/chunk-HD5H2PPP.cjs.map +1 -0
- package/dist/{chunk-FQVNZCTD.cjs → chunk-LBAG7KL7.cjs} +3 -3
- package/dist/{chunk-FQVNZCTD.cjs.map → chunk-LBAG7KL7.cjs.map} +1 -1
- package/dist/{chunk-DPR7LVZO.js → chunk-NNAJLY6B.js} +3 -3
- package/dist/{chunk-DPR7LVZO.js.map → chunk-NNAJLY6B.js.map} +1 -1
- package/dist/{chunk-OSFKAJT2.js → chunk-OYPKKHXY.js} +3 -3
- package/dist/{chunk-OSFKAJT2.js.map → chunk-OYPKKHXY.js.map} +1 -1
- package/dist/{chunk-MAUZSNQY.js → chunk-P6WLV5UY.js} +3 -3
- package/dist/{chunk-MAUZSNQY.js.map → chunk-P6WLV5UY.js.map} +1 -1
- package/dist/{chunk-2YRQJ3DR.cjs → chunk-QF2BW6HZ.cjs} +38 -38
- package/dist/{chunk-2YRQJ3DR.cjs.map → chunk-QF2BW6HZ.cjs.map} +1 -1
- package/dist/{chunk-IXE7HCCA.cjs → chunk-RVUGSM65.cjs} +44 -44
- package/dist/{chunk-IXE7HCCA.cjs.map → chunk-RVUGSM65.cjs.map} +1 -1
- package/dist/{chunk-YUESCKE2.cjs → chunk-W2FATOTX.cjs} +4 -4
- package/dist/{chunk-YUESCKE2.cjs.map → chunk-W2FATOTX.cjs.map} +1 -1
- package/dist/{chunk-C72FSQUE.cjs → chunk-Z3W4XFWB.cjs} +3 -3
- package/dist/{chunk-C72FSQUE.cjs.map → chunk-Z3W4XFWB.cjs.map} +1 -1
- package/dist/document-tools/core.cjs +99 -99
- package/dist/document-tools/core.d.cts +2 -2
- package/dist/document-tools/core.d.ts +2 -2
- package/dist/document-tools/core.js +4 -4
- package/dist/document-tools/index.cjs +101 -101
- package/dist/document-tools/index.d.cts +1 -1
- package/dist/document-tools/index.d.ts +1 -1
- package/dist/document-tools/index.js +5 -5
- package/dist/index.cjs +1951 -1599
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +180 -4
- package/dist/index.d.ts +180 -4
- package/dist/index.js +363 -24
- package/dist/index.js.map +1 -1
- package/dist/{query-keys.d-Bpb7R_lB.d.cts → query-keys.d-ChgpJLPF.d.cts} +5 -2
- package/dist/{query-keys.d-Bpb7R_lB.d.ts → query-keys.d-ChgpJLPF.d.ts} +5 -2
- package/dist/shell/index.cjs +37 -37
- package/dist/shell/index.js +2 -2
- package/dist/ui/index.cjs +154 -154
- package/dist/ui/index.js +2 -2
- package/package.json +3 -3
- package/dist/chunk-AXKIOI2U.js.map +0 -1
- package/dist/chunk-K7UUWND5.cjs.map +0 -1
- package/dist/chunk-M74JCOXW.js.map +0 -1
- package/dist/chunk-Q2GNEVG2.cjs.map +0 -1
- package/dist/chunk-VAO76OJO.js.map +0 -1
- package/dist/chunk-XOS7ISIR.cjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/documents/documents-cache.ts","../src/entity-extraction.ts","../src/queued-writes.ts","../src/tags.ts","../src/documents/documents-loader.ts","../src/documents/processing-order.ts","../src/websocket/store.ts","../src/documents/documents-data.ts"],"names":["update","useCallback","tagOps","controller","create","openWorkspaceId","useQueryClient","useQuery"],"mappings":"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","file":"chunk-MAUZSNQY.js","sourcesContent":["/**\n * The workspace documents list in the query cache: one entry per workspace\n * (`arbiQueryKeys.documents(workspaceId)`), read once (progressively, see `documents-loader.ts`)\n * and then kept current in place. Every write goes through {@link patchDocuments}, which also\n * tells row listeners (a grid that applies row transactions instead of re-diffing the whole list)\n * exactly which rows were added, changed or removed.\n *\n * A single document's own entry (`arbiQueryKeys.document(id)`, read by a viewer) is patched next to\n * the list by {@link setCachedDocument}, so a viewer never blanks while a write settles.\n */\n\nimport type { QueryClient } from '@tanstack/react-query'\nimport type { components } from '@arbidocs/client'\nimport { arbiQueryKeys } from '../hooks'\n\n/** A document as the server lists it. */\nexport type WorkspaceDocument = components['schemas']['DocResponse']\n\n/** The rows one write added, changed and removed (removed: by id). */\nexport interface DocumentRowChange {\n workspaceId: string\n add: WorkspaceDocument[]\n update: WorkspaceDocument[]\n remove: string[]\n}\n\ntype RowListener = (change: DocumentRowChange) => void\n\nconst rowListeners = new Set<RowListener>()\n\n/**\n * Follow the row-level changes of every write to a workspace documents list (a grid applying them\n * as transactions). Returns the unsubscribe.\n */\nexport function subscribeDocumentRows(listener: RowListener): () => void {\n rowListeners.add(listener)\n return () => {\n rowListeners.delete(listener)\n }\n}\n\n/** The cached documents of a workspace (`undefined` before its list has been read). */\nexport function getCachedDocuments(\n qc: QueryClient,\n workspaceId: string | null | undefined\n): WorkspaceDocument[] | undefined {\n if (!workspaceId) return undefined\n return qc.getQueryData<WorkspaceDocument[]>(arbiQueryKeys.documents(workspaceId))\n}\n\n/** Every cached workspace documents list, with its workspace. */\nfunction cachedLists(qc: QueryClient): Array<[string, WorkspaceDocument[]]> {\n return qc\n .getQueriesData<WorkspaceDocument[]>({ queryKey: arbiQueryKeys.allDocuments() })\n .flatMap(([key, data]) =>\n typeof key[2] === 'string' && Array.isArray(data) ? [[key[2], data]] : []\n )\n}\n\n/** Diff two versions of a list by id. */\nfunction diffRows(\n workspaceId: string,\n before: WorkspaceDocument[],\n after: WorkspaceDocument[]\n): DocumentRowChange {\n const beforeById = new Map(before.map((doc) => [doc.external_id, doc]))\n const add: WorkspaceDocument[] = []\n const update: WorkspaceDocument[] = []\n const seen = new Set<string>()\n for (const doc of after) {\n seen.add(doc.external_id)\n const previous = beforeById.get(doc.external_id)\n if (!previous) add.push(doc)\n else if (previous !== doc) update.push(doc)\n }\n const remove = [...beforeById.keys()].filter((id) => !seen.has(id))\n return { workspaceId, add, update, remove }\n}\n\n/**\n * Apply `reducer` to a workspace's documents list, or (no `workspaceId`) to every cached one: the\n * one place a list is written after it was read. Returning the same array is a no-op. Row\n * listeners get the diff; a document that moved to a new version makes the open version lists\n * re-read. A workspace whose list has not been read is left alone (its first read brings it).\n */\nexport function patchDocuments(\n qc: QueryClient,\n reducer: (documents: WorkspaceDocument[]) => WorkspaceDocument[],\n workspaceId?: string | null\n): void {\n const lists: Array<[string, WorkspaceDocument[]]> = workspaceId\n ? (() => {\n const current = getCachedDocuments(qc, workspaceId)\n return current ? [[workspaceId, current] as [string, WorkspaceDocument[]]] : []\n })()\n : cachedLists(qc)\n for (const [id, before] of lists) {\n const after = reducer(before)\n if (after === before) continue\n qc.setQueryData(arbiQueryKeys.documents(id), after)\n const change = diffRows(id, before, after)\n const beforeById = new Map(before.map((doc) => [doc.external_id, doc]))\n if (\n change.update.some(\n (doc) => doc.current_version !== beforeById.get(doc.external_id)?.current_version\n )\n )\n void qc.invalidateQueries({ queryKey: arbiQueryKeys.allDocumentVersions() })\n if (change.add.length || change.update.length || change.remove.length)\n for (const listener of rowListeners) listener(change)\n }\n}\n\n/** Put `doc` in its list in place, or at the end when the list does not hold it yet. */\nexport function upsertDocuments(\n qc: QueryClient,\n documents: WorkspaceDocument[],\n workspaceId?: string | null\n): void {\n if (!documents.length) return\n const byId = new Map(documents.map((doc) => [doc.external_id, doc]))\n const byWorkspace = new Map<string, WorkspaceDocument[]>()\n for (const doc of documents) {\n const ws = workspaceId ?? doc.workspace_ext_id\n byWorkspace.set(ws, [...(byWorkspace.get(ws) ?? []), doc])\n }\n for (const [ws, incoming] of byWorkspace) {\n patchDocuments(\n qc,\n (old) => {\n const known = new Set(old.map((doc) => doc.external_id))\n return [\n ...old.map((doc) => byId.get(doc.external_id) ?? doc),\n ...incoming.filter((doc) => !known.has(doc.external_id)),\n ]\n },\n ws\n )\n }\n}\n\n/** Write a document's own entry (what `useDocument` reads), keeping a viewer current. */\nexport function setCachedDocument(qc: QueryClient, doc: WorkspaceDocument): void {\n qc.setQueryData(arbiQueryKeys.document(doc.external_id), doc)\n}\n\n/** Apply `reducer` to a document's own entry, when one is cached. */\nexport function patchCachedDocument(\n qc: QueryClient,\n docId: string,\n reducer: (doc: WorkspaceDocument) => WorkspaceDocument\n): void {\n const current = qc.getQueryData<WorkspaceDocument | null>(arbiQueryKeys.document(docId))\n if (current) qc.setQueryData(arbiQueryKeys.document(docId), reducer(current))\n}\n\n/** A deleted tag leaves every cached document that carried it: the lists' rows and their entries. */\nexport function dropTagFromCachedDocuments(qc: QueryClient, tagId: string): void {\n const strip = (doc: WorkspaceDocument): WorkspaceDocument => {\n const doctags = doc.doctags?.filter((dt) => dt.tag_ext_id !== tagId)\n return doctags && doctags.length !== doc.doctags?.length ? { ...doc, doctags } : doc\n }\n const carriers: string[] = []\n patchDocuments(qc, (docs) => {\n const next = docs.map(strip)\n next.forEach((doc, i) => doc !== docs[i] && carriers.push(doc.external_id))\n return carriers.length ? next : docs\n })\n for (const id of carriers) patchCachedDocument(qc, id, strip)\n}\n\n/** Forget everything cached about deleted documents, so nothing re-reads them into a 404. */\nexport function forgetDocuments(qc: QueryClient, docIds: string[]): void {\n for (const id of docIds) {\n qc.removeQueries({ queryKey: arbiQueryKeys.document(id) })\n qc.removeQueries({ queryKey: arbiQueryKeys.documentVersions(id) })\n qc.removeQueries({ queryKey: arbiQueryKeys.parsedDocument(id) })\n }\n}\n","/**\n * The documents whose people and organisations are being found (`useExtractEntities`), from the\n * request until the live connection says the batch is done (`batch_complete`, `entity_extract`):\n * the package's WebSocket (`ArbiWebSocketProvider`) ends it, and a host on its own connection calls\n * `finishEntityExtraction` from its handler.\n */\n\nimport { create } from 'zustand'\n\nconst useEntityExtractionStore = create<{ docIds: readonly string[] }>(() => ({ docIds: [] }))\n\nfunction update(docIds: readonly string[], running: boolean): void {\n if (!docIds.length) return\n useEntityExtractionStore.setState((state) => {\n const ids = new Set(state.docIds)\n docIds.forEach((id) => (running ? ids.add(id) : ids.delete(id)))\n return { docIds: [...ids] }\n })\n}\n\n/** The documents an extraction was started on are running. */\nexport function startEntityExtraction(docIds: readonly string[]): void {\n update(docIds, true)\n}\n\n/** The extraction of these documents is done. */\nexport function finishEntityExtraction(docIds: readonly string[]): void {\n update(docIds, false)\n}\n\n/** The documents being extracted now. */\nexport function useEntityExtractionDocIds(): readonly string[] {\n return useEntityExtractionStore((state) => state.docIds)\n}\n","/**\n * The workspace of a write that may be queued (offline, then replayed on reconnect or after a\n * reload). The workspace is captured when the write is made and kept with it, and the write is\n * sent in that workspace: it is opened for this session first (its key deposited, without\n * switching to it), and the request names it or acts on resources the server keys by their own\n * workspace. So a replay never lands in whatever workspace happens to be open by then.\n *\n * When the workspace cannot be opened (signed out, access removed), nothing is sent: the write\n * fails with `ArbiWorkspaceUnavailableError`, is retried a few times (a reload replays before the\n * sign-in has finished), and then stays in the pending changes as not sent, with its local edit\n * kept, rather than going anywhere else.\n */\n\nimport { useCallback, useRef } from 'react'\nimport { isAbortError, type ArbiClient } from '@arbidocs/client'\nimport { ArbiWorkspaceUnavailableError } from '@arbidocs/sdk/browser'\n\n/** A queued write's own workspace (`wrk-…`), captured when it was made. */\nexport interface QueuedWriteWorkspace {\n /** The workspace the write belongs to. Filled in when it is made; absent on older queued writes. */\n workspaceId?: string\n}\n\n/** What a write that could not be sent in its workspace says. */\nexport const QUEUED_WRITE_BLOCKED_MESSAGE =\n \"This change belongs to a workspace that can't be opened right now, so it was not sent. It is kept here until it can be.\"\n\n/** Opens a workspace for this server session without switching to it (nothing for the current one). */\nexport type WorkspacePrimer = (workspaceId: string) => Promise<void> | void\n\n/** {@link WorkspacePrimer} on a bare client (a replay after a reload): its key, via `/prime-key`. */\nexport function primeOnClient(client: ArbiClient): WorkspacePrimer {\n return (workspaceId) =>\n workspaceId === client.session.getState().selectedWorkspaceId\n ? undefined\n : client.workspaceKeys.prime(workspaceId)\n}\n\n/** {@link WorkspacePrimer} on an `Arbi` (`workspaces.open`, which never switches). */\nexport function primeOnArbi(arbi: {\n hasWorkspace: boolean\n getWorkspaceId(): string\n workspaces: { open(workspaceId: string): Promise<void> }\n}): WorkspacePrimer {\n return (workspaceId) =>\n arbi.hasWorkspace && workspaceId === arbi.getWorkspaceId()\n ? undefined\n : arbi.workspaces.open(workspaceId)\n}\n\n/**\n * Run `write` in `workspaceId`: that workspace is opened for this server session first (`prime`).\n * When it can't be, nothing is sent. No workspace (a write queued before workspaces were\n * recorded): as before.\n */\nexport async function inWorkspace<T>(\n prime: WorkspacePrimer,\n workspaceId: string | null | undefined,\n write: () => Promise<T>\n): Promise<T> {\n if (workspaceId) {\n try {\n await prime(workspaceId)\n } catch (error) {\n if (isAbortError(error)) throw error\n throw new ArbiWorkspaceUnavailableError(workspaceId, error, QUEUED_WRITE_BLOCKED_MESSAGE)\n }\n }\n return write()\n}\n\n/** Whether a write failed only because its workspace could not be opened (nothing was sent). */\nexport function isWorkspaceUnavailable(error: unknown): boolean {\n return error instanceof ArbiWorkspaceUnavailableError\n}\n\n/** How many times a write whose workspace cannot be opened is tried again, and how long apart. */\nexport const QUEUED_WRITE_RETRY = {\n retry: (failureCount: number, error: unknown) =>\n isWorkspaceUnavailable(error) && failureCount < 8,\n retryDelay: (attempt: number) => Math.min(1000 * 2 ** attempt, 30_000),\n} as const\n\n/** Whether a queued write is held back because its workspace cannot be opened. */\nexport function isBlockedOnWorkspace(mutation: {\n state: { error?: unknown; failureReason?: unknown }\n}): boolean {\n return isWorkspaceUnavailable(mutation.state.error ?? mutation.state.failureReason)\n}\n\n/**\n * Fill in the workspace of each write a mutation makes, when its caller gave none: `mutate` and\n * `mutateAsync` pass `capture(variables)` on. Read when the write is made, so a write queued\n * offline keeps the workspace it was made in. The wrapped functions are as stable as the mutation's.\n */\nexport function useCapturingWorkspace<\n V,\n T extends { mutate: (variables: V, ...rest: never[]) => unknown; mutateAsync: unknown },\n>(mutation: T, capture: (variables: V) => V): T {\n const captureRef = useRef(capture)\n captureRef.current = capture\n const { mutate: rawMutate, mutateAsync: rawMutateAsync } = mutation\n const mutate = useCallback(\n (variables: V, ...rest: never[]) =>\n (rawMutate as (v: V, ...r: never[]) => unknown)(captureRef.current(variables), ...rest),\n [rawMutate]\n ) as T['mutate']\n const mutateAsync = useCallback(\n (variables: V, ...rest: never[]) =>\n (rawMutateAsync as (v: V, ...r: never[]) => Promise<unknown>)(\n captureRef.current(variables),\n ...rest\n ),\n [rawMutateAsync]\n ) as T['mutateAsync']\n return { ...mutation, mutate, mutateAsync }\n}\n","/**\n * Tags: the open workspace's tag list (`useTags()`), the writes (create, update, delete, values,\n * entity extraction), and tag kinds — a kind's fields in the workspace are the columns of a table\n * of its tags (`useTagKindSchema('issue')`), whose rows are the tag list filtered by kind with\n * links (`useTags(workspaceId, { kind, include })`).\n *\n * Everything is cached under the workspace's tags (`arbiQueryKeys.tags`). The whole list is kept\n * current in place: every write here patches it ({@link patchWorkspaceTags}, which a host also\n * uses for its own writes that move a tag's counts, e.g. applying it to documents) and refreshes\n * the filtered lists (the tables). Anything that invalidates the workspace's tags (a document batch\n * finishing, {@link useInvalidateTagData} after a doctag or fact change) refreshes them all.\n *\n * Creating a tag can be queued while offline and replayed after a reload: see `offline.ts`.\n *\n * Requires an `ArbiHost` (with an `arbi`) and a React Query client above it.\n */\n\nimport { useCallback } from 'react'\nimport { useMutation, useQuery, useQueryClient, type QueryClient } from '@tanstack/react-query'\nimport type { ArbiClient } from '@arbidocs/client'\nimport {\n tags as tagOps,\n type TagChange,\n type TagFieldDefinition,\n type TagKind,\n type TagKindSchema,\n type TagResponse,\n} from '@arbidocs/sdk/browser'\nimport { useArbi } from './useArbi'\nimport { dropTagFromCachedDocuments } from './documents/documents-cache'\nimport { startEntityExtraction } from './entity-extraction'\nimport { arbiMutationKeys, arbiQueryKeys } from './hooks'\nimport {\n QUEUED_WRITE_RETRY,\n inWorkspace,\n primeOnArbi,\n primeOnClient,\n useCapturingWorkspace,\n} from './queued-writes'\n\n/** The workspace open on `arbi`, or `null` (`getWorkspaceId()` throws when none is open). */\n/** The workspace whose cached tag list holds `tagId`, if any. */\nfunction workspaceOfTag(qc: QueryClient, tagId: string): string | null {\n for (const [key, tags] of qc.getQueriesData<TagResponse[]>({\n queryKey: arbiQueryKeys.allTags(),\n })) {\n if (Array.isArray(tags) && tags.some((t) => t.external_id === tagId))\n return (key[2] as string | undefined) ?? null\n }\n return null\n}\n\nfunction openWorkspaceId(arbi: ReturnType<typeof useArbi>): string | null {\n return arbi.hasWorkspace ? arbi.getWorkspaceId() : null\n}\n\n/**\n * Apply `reducer` to a workspace's cached tag list (nothing cached: nothing to do). The list is\n * read once, then kept current by these patches; a host's own write that changes a tag (applying\n * it to documents moves its `doctag_count`) patches it here too.\n */\nexport function patchWorkspaceTags(\n qc: QueryClient,\n workspaceId: string,\n reducer: (tags: TagResponse[]) => TagResponse[]\n): void {\n const key = arbiQueryKeys.tags(workspaceId)\n const current = qc.getQueryData<TagResponse[]>(key)\n if (!current) return\n const next = reducer(current)\n if (next !== current) qc.setQueryData(key, next)\n}\n\n/** Refetch a workspace's tables of tags (its filtered lists), not the whole list. */\nexport function invalidateTagTables(qc: QueryClient, workspaceId: string): Promise<void> {\n return qc.invalidateQueries({ queryKey: arbiQueryKeys.tagLists(workspaceId) })\n}\n\n/** Refresh what a tag, doctag or fact change affects: the workspace's tags, tables and facts. */\nexport function invalidateTagData(qc: QueryClient, workspaceId: string): Promise<unknown> {\n return Promise.all([\n qc.invalidateQueries({ queryKey: arbiQueryKeys.tags(workspaceId) }),\n qc.invalidateQueries({ queryKey: arbiQueryKeys.facts(workspaceId) }),\n ])\n}\n\n/** {@link invalidateTagData} for the open workspace: call it after a doctag or fact write. */\nexport function useInvalidateTagData(): () => Promise<unknown> {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useCallback(() => {\n const workspaceId = openWorkspaceId(arbi)\n return workspaceId ? invalidateTagData(qc, workspaceId) : Promise.resolve()\n }, [arbi, qc])\n}\n\n/**\n * What a new tag is: its name, and optionally kind, format, parent, values, sharing, and the workspace it goes in\n * (absent: the open one).\n */\nexport type CreateTagInput = Parameters<typeof tagOps.createTag>[1]\n\n/** A created tag joins its workspace's list; the tables re-read. */\nfunction settleCreatedTag(qc: QueryClient, created: TagResponse): Promise<void> {\n const workspaceId = created.workspace_ext_id\n patchWorkspaceTags(qc, workspaceId, (old) =>\n old.some((t) => t.external_id === created.external_id) ? old : [...old, created]\n )\n return invalidateTagTables(qc, workspaceId)\n}\n\n/** A changed tag replaces its entry in the list; the tables re-read. */\nfunction settleChangedTag(qc: QueryClient, tag: TagResponse): Promise<void> {\n const workspaceId = tag.workspace_ext_id\n patchWorkspaceTags(qc, workspaceId, (old) =>\n old.map((t) => (t.external_id === tag.external_id ? { ...t, ...tag } : t))\n )\n return invalidateTagTables(qc, workspaceId)\n}\n\n/**\n * The tag writes a host may queue while offline and replay after a reload (`offline.ts`): each\n * key's request on a bare client, and what its success does to the cache.\n */\nexport const replayableTagMutations = [\n {\n mutationKey: arbiMutationKeys.createTag(),\n // In the workspace it was made in (named on the request), opened for this session first.\n run: (client: ArbiClient, input: CreateTagInput) =>\n inWorkspace(primeOnClient(client), input.workspaceId, () => tagOps.createTag(client, input)),\n settle: (qc: QueryClient, created: TagResponse) => settleCreatedTag(qc, created),\n },\n] as const\n\n/**\n * Create a tag in the open workspace, or `workspaceId` (`{ name, kind: 'issue' }`, `{ name, parentId }`, …): it is\n * added to the tag list and the tables re-read. Resolves with the new tag. Offline it is held and\n * sent on reconnect (a host that registers `registerArbiMutationDefaults` keeps it across reloads).\n */\nexport function useCreateTag() {\n const arbi = useArbi()\n const qc = useQueryClient()\n // The workspace is captured when the tag is made, so a create queued offline keeps it.\n const capture = (input: CreateTagInput): CreateTagInput =>\n input.workspaceId || !arbi.hasWorkspace\n ? input\n : { ...input, workspaceId: arbi.getWorkspaceId() }\n return useCapturingWorkspace(\n useMutation({\n mutationKey: arbiMutationKeys.createTag(),\n mutationFn: (input: CreateTagInput): Promise<TagResponse> =>\n inWorkspace(primeOnArbi(arbi), input.workspaceId, () => arbi.tags.create(input)),\n onSuccess: (created) => settleCreatedTag(qc, created),\n ...QUEUED_WRITE_RETRY,\n }),\n capture\n )\n}\n\n/**\n * Whether a tag of this name (any case) is being created right now: a second create of the same\n * name (a double Enter) is skipped instead of making a duplicate.\n */\nexport function useIsCreatingTag(): (name: string) => boolean {\n const qc = useQueryClient()\n return useCallback(\n (name: string) => {\n const wanted = name.trim().toLowerCase()\n return (\n qc.getMutationCache().findAll({\n mutationKey: arbiMutationKeys.createTag(),\n predicate: (m) =>\n m.state.status === 'pending' &&\n (m.state.variables as CreateTagInput | undefined)?.name.trim().toLowerCase() === wanted,\n }).length > 0\n )\n },\n [qc]\n )\n}\n\n/** Change a tag (name, format, instruction, parent, sharing, values): patched in the list. */\nexport function useUpdateTag() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationKey: arbiMutationKeys.updateTag(),\n mutationFn: ({ tagId, change }: { tagId: string; change: TagChange }): Promise<TagResponse> =>\n arbi.tags.update(tagId, change),\n onSuccess: (tag) => settleChangedTag(qc, tag),\n })\n}\n\n/** Merge-patch a tag's values for its kind's fields (`null` clears one); its tables refresh. */\nexport function useSetTagValues() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationKey: arbiMutationKeys.updateTag(),\n mutationFn: ({\n tagId,\n values,\n }: {\n tagId: string\n values: Record<string, unknown>\n }): Promise<TagResponse> => arbi.tags.setValues(tagId, values),\n onSuccess: (tag) => settleChangedTag(qc, tag),\n })\n}\n\n/**\n * Delete a tag: it leaves the list (its sub-tags move to the top level on the server, so the list\n * re-reads them), and the tables and facts re-read. A host that shows the tag on its own items\n * (documents' tags) follows `arbiMutationKeys.deleteTag()` to drop it there.\n */\nexport function useDeleteTag() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationKey: arbiMutationKeys.deleteTag(),\n mutationFn: (tagId: string) => arbi.tags.delete(tagId),\n // The tag's own workspace (the cached list holding it), else the one open when it is sent: a\n // switch while the delete runs must not patch the next workspace's list.\n onMutate: (tagId) => ({ workspaceId: workspaceOfTag(qc, tagId) ?? openWorkspaceId(arbi) }),\n onSuccess: (_data, tagId, context) => {\n // Its pills come off the documents grid in place (and off any open document).\n dropTagFromCachedDocuments(qc, tagId)\n const workspaceId = context?.workspaceId\n if (!workspaceId) return\n patchWorkspaceTags(qc, workspaceId, (old) =>\n old\n .filter((t) => t.external_id !== tagId)\n .map((t) => (t.parent_ext_id === tagId ? { ...t, parent_ext_id: null } : t))\n )\n return Promise.all([\n invalidateTagTables(qc, workspaceId),\n qc.invalidateQueries({ queryKey: arbiQueryKeys.facts(workspaceId) }),\n ])\n },\n })\n}\n\n/**\n * Find the people and organisations documents name and link each to its entity tag. Accepted at\n * once with the documents' ids, which show as running (`useEntityExtractionDocIds`) until a\n * `batch_complete` (`entity_extract`) WebSocket message says they are done.\n */\nexport function useExtractEntities() {\n const arbi = useArbi()\n return useMutation({\n mutationKey: arbiMutationKeys.extractEntities(),\n mutationFn: (docIds: string[]) => arbi.tags.extractEntities(docIds),\n onSuccess: (data) => startEntityExtraction(data.doc_ext_ids),\n })\n}\n\n/**\n * A kind's fields in the open workspace (`'issue'`: its issue fields): the columns of a table of\n * that kind's tags. The built-in ones (`is_default`) until the workspace sets its own.\n */\nexport function useTagKindSchema(\n kind: TagKind | null | undefined,\n options?: { enabled?: boolean }\n) {\n const arbi = useArbi()\n const workspaceId = openWorkspaceId(arbi) ?? ''\n return useQuery({\n queryKey: arbiQueryKeys.tagKind(workspaceId, kind ?? ''),\n queryFn: (): Promise<TagKindSchema> =>\n arbi.readInWorkspace(workspaceId, () => arbi.tagKinds.get(kind as TagKind)),\n enabled: (options?.enabled ?? true) && !!kind && !!workspaceId,\n })\n}\n\n/**\n * Set a kind's fields in full (a field with its `id` keeps its values; one without is new; one\n * left out is removed). The kind's schema and the workspace's tags refresh.\n */\nexport function useUpdateTagKindSchema() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationKey: arbiMutationKeys.updateTagKindSchema(),\n mutationFn: ({\n kind,\n fields,\n }: {\n kind: TagKind\n fields: TagFieldDefinition[]\n }): Promise<TagKindSchema> => arbi.tagKinds.update(kind, fields),\n // The workspace open when it is sent (the server writes the open workspace's schema until\n // the request can name it): a switch meanwhile must not rewrite the next workspace's columns.\n onMutate: () => ({ workspaceId: openWorkspaceId(arbi) }),\n onSuccess: (schema, _input, context) => {\n const workspaceId = context?.workspaceId\n if (!workspaceId) return\n qc.setQueryData(arbiQueryKeys.tagKind(workspaceId, schema.kind), schema)\n return invalidateTagData(qc, workspaceId)\n },\n })\n}\n","/**\n * Reading a workspace's documents progressively: the first page is the query's result, so the\n * list shows within a few hundred milliseconds even for 100k documents, and the remaining pages\n * are appended to the same cache entry in the background as they arrive. One background read per\n * workspace; opening another workspace stops the previous one. Whether a background read is\n * running is observable ({@link useDocumentsLoading}), for a \"still loading\" indicator.\n */\n\nimport { useSyncExternalStore } from 'react'\nimport type { QueryClient } from '@tanstack/react-query'\nimport type { Arbi } from '@arbidocs/sdk/browser'\nimport { patchDocuments, type WorkspaceDocument } from './documents-cache'\n\n/** First page: small, so rows are on screen in a few hundred ms even in a large workspace. */\nexport const DOCUMENTS_FIRST_PAGE_SIZE = 500\n\n/** Later pages: larger, fewer round trips (the server caps a page at 10 000). */\nexport const DOCUMENTS_PAGE_SIZE = 2000\n\n/**\n * The time to the first page, as a `performance` measure of this name (a host reporting\n * performance can observe it).\n */\nexport const DOCUMENTS_FIRST_PAGE_MEASURE = 'arbi:document-list:page1'\nconst FIRST_PAGE_MEASURE = DOCUMENTS_FIRST_PAGE_MEASURE\nconst FIRST_PAGE_START = 'arbi:document-list:start'\n\nfunction mark(name: string): void {\n try {\n performance.mark(name)\n } catch {\n // No performance timeline here (an old runtime, a test): nothing to record.\n }\n}\n\nfunction measure(name: string, start: string): void {\n try {\n performance.measure(name, start)\n } catch {\n // The start mark is missing: nothing to record.\n }\n}\n\nconst backgroundReads = new Map<string, AbortController>()\nconst loadingListeners = new Set<() => void>()\n\nfunction emitLoading(): void {\n for (const listener of loadingListeners) listener()\n}\n\nfunction subscribeLoading(listener: () => void): () => void {\n loadingListeners.add(listener)\n return () => {\n loadingListeners.delete(listener)\n }\n}\n\n/** Whether a workspace's remaining document pages are being read in the background. */\nexport function isDocumentsLoading(): boolean {\n return backgroundReads.size > 0\n}\n\n/** True while the remaining pages of a documents list are still arriving. */\nexport function useDocumentsLoading(): boolean {\n return useSyncExternalStore(subscribeLoading, isDocumentsLoading, () => false)\n}\n\n/** Stop a workspace's background read (closing the workspace). */\nexport function stopDocumentsLoading(workspaceId: string): void {\n const controller = backgroundReads.get(workspaceId)\n if (!controller) return\n controller.abort()\n backgroundReads.delete(workspaceId)\n emitLoading()\n}\n\n/**\n * Read a workspace's documents: resolves with the first page and appends the rest to\n * `arbiQueryKeys.documents(workspaceId)` in the background. The query function of `useDocuments`.\n */\nexport async function loadDocuments(\n qc: QueryClient,\n arbi: Arbi,\n workspaceId: string,\n signal?: AbortSignal\n): Promise<WorkspaceDocument[]> {\n let stopped = false\n for (const [id, controller] of backgroundReads) {\n if (id === workspaceId) continue\n controller.abort()\n backgroundReads.delete(id)\n stopped = true\n }\n if (stopped) emitLoading()\n\n const controller = new AbortController()\n signal?.addEventListener('abort', () => controller.abort(), { once: true })\n // Named, not the session's open workspace: the pages are this workspace's whatever the server\n // session is in, so a list read across a workspace switch can never be another's.\n const pages = arbi.documents.listPaginated({\n workspaceId,\n pageSize: DOCUMENTS_PAGE_SIZE,\n firstPageSize: DOCUMENTS_FIRST_PAGE_SIZE,\n signal: controller.signal,\n })\n mark(FIRST_PAGE_START)\n const first = await pages.next()\n const firstPage = first.done ? [] : first.value\n measure(FIRST_PAGE_MEASURE, FIRST_PAGE_START)\n if (first.done || firstPage.length < DOCUMENTS_FIRST_PAGE_SIZE) return firstPage\n if (backgroundReads.has(workspaceId)) {\n controller.abort()\n return firstPage\n }\n\n backgroundReads.set(workspaceId, controller)\n emitLoading()\n void appendRemainingPages(qc, workspaceId, pages, controller.signal).finally(() => {\n if (backgroundReads.get(workspaceId) !== controller) return\n backgroundReads.delete(workspaceId)\n emitLoading()\n })\n return firstPage\n}\n\nasync function appendRemainingPages(\n qc: QueryClient,\n workspaceId: string,\n pages: AsyncGenerator<WorkspaceDocument[]>,\n signal: AbortSignal\n): Promise<void> {\n // Let the query store the first page before the second is appended to it.\n await Promise.resolve()\n try {\n for await (const page of pages) {\n if (signal.aborted) return\n // A write may already have added some of these (an upload finishing meanwhile).\n patchDocuments(\n qc,\n (old) => {\n const known = new Set(old.map((doc) => doc.external_id))\n const fresh = page.filter((doc) => !known.has(doc.external_id))\n return fresh.length ? [...old, ...fresh] : old\n },\n workspaceId\n )\n }\n } catch (error) {\n if (!signal.aborted) console.error(`Reading the documents of ${workspaceId} failed:`, error)\n }\n}\n\n/** Test-only: stop every background read. @internal */\nexport function resetDocumentsLoadingForTests(): void {\n for (const controller of backgroundReads.values()) controller.abort()\n backgroundReads.clear()\n emitLoading()\n}\n","/**\n * Which is newer: a document's live processing status or its row as last read?\n *\n * Every `task_update` carries `seq`, taken by the server from one sequence for all documents and\n * all of its instances, so a higher seq is a later event however the events arrive. A document row\n * carries `status_seq`: the seq of the last time its processing ended (a finished status written or\n * broadcast). The two compare:\n * - an event at or below the seq of the one already held is stale (overtaken), and is dropped;\n * - a row whose `status_seq` is above the live status's seq finished after it: the live status is\n * over (its final event was lost), and the row wins;\n * - a live status above the row's `status_seq` is newer than the row: the document is being\n * processed again (AI fields being filled) although the row still says it finished.\n *\n * Without the seqs (an optimistic \"queued\" set here, a server before them) the older rule stands:\n * a live in-flight status wins, then a finished row, then whatever was heard live.\n */\n\n/** Statuses after which a document's processing is over (`low-content`: indexed, little text). */\nexport const FINISHED_DOCUMENT_STATUSES: ReadonlySet<string> = new Set([\n 'completed',\n 'low-content',\n 'failed',\n 'skipped',\n 'empty',\n])\n\n/** A live processing status and its order (`task_update.seq`). */\nexport interface SequencedTask {\n status: string\n seq?: number | null\n}\n\n/** A document row's status and the order of its last finished status (`status_seq`). */\nexport interface SequencedRow {\n status?: string | null\n status_seq?: number | null\n}\n\n/** Statuses of a document still being processed. */\nexport const IN_FLIGHT_DOCUMENT_STATUSES: ReadonlySet<string> = new Set([\n 'uploading',\n 'queued',\n 'parsing',\n 'encrypting',\n 'indexing',\n 'analysing',\n])\n\nfunction ordered(value: number | null | undefined): value is number {\n return typeof value === 'number'\n}\n\n/** Whether `next` is older than (or the same event as) the live status already held. */\nexport function isStaleTaskUpdate(held: SequencedTask | undefined, next: SequencedTask): boolean {\n return !!held && ordered(held.seq) && ordered(next.seq) && next.seq <= held.seq\n}\n\n/**\n * Whether the row is newer than the live status: `true` / `false` when both are ordered, `undefined`\n * when they cannot be compared.\n */\nexport function isRowNewer(row: SequencedRow, task: SequencedTask): boolean | undefined {\n if (!ordered(row.status_seq) || !ordered(task.seq)) return undefined\n return row.status_seq > task.seq\n}\n\n/** The status a document shows now: its row's, or the live one when that is newer. */\nexport function resolveDocumentStatus(row: SequencedRow, task: SequencedTask | undefined): string {\n const rowStatus = (row.status ?? '').toLowerCase()\n const live = task?.status\n if (!task || !live) return rowStatus\n const rowNewer = isRowNewer(row, task)\n if (rowNewer !== undefined) return rowNewer ? rowStatus || live : live\n if (IN_FLIGHT_DOCUMENT_STATUSES.has(live)) return live\n if (FINISHED_DOCUMENT_STATUSES.has(rowStatus)) return rowStatus\n return live\n}\n\n/**\n * The live statuses a read of `rows` ends: each in-flight one whose row has since finished. Ordered,\n * the row must be newer (so a reprocess the row predates keeps its progress); unordered, a finished\n * row is enough (the older rule). Returns each such task with the row's status and order. Cheap when\n * nothing is in flight (it runs on every read of a list).\n */\nexport function settledByRows<T extends SequencedTask & { doc_ext_id: string }>(\n tasks: Readonly<Record<string, T>>,\n rows: ReadonlyArray<SequencedRow & { external_id: string }>\n): T[] {\n const inFlight = new Map<string, T>()\n for (const task of Object.values(tasks))\n if (IN_FLIGHT_DOCUMENT_STATUSES.has(task.status)) inFlight.set(task.doc_ext_id, task)\n if (!inFlight.size) return []\n const settled: T[] = []\n for (const row of rows) {\n const task = inFlight.get(row.external_id)\n if (!task) continue\n const rowStatus = (row.status ?? '').toLowerCase()\n if (!FINISHED_DOCUMENT_STATUSES.has(rowStatus) || isRowNewer(row, task) === false) continue\n settled.push({ ...task, status: rowStatus, seq: row.status_seq ?? task.seq })\n }\n return settled\n}\n","/**\n * Canonical WebSocket state, shared across apps.\n *\n * One store for every site's live connection: its status, people's presence and each document's\n * live processing. `ArbiWebSocketProvider` feeds it; components read it with the selector hooks in\n * `./hooks` and the documents hooks (`useProcessingTasks`, `useWorkspaceProcessing`).\n */\n\nimport { create } from 'zustand'\nimport type { WsTaskUpdateMessage, WsPresenceUpdateMessage } from '@arbidocs/client'\nimport {\n FINISHED_DOCUMENT_STATUSES,\n isStaleTaskUpdate,\n settledByRows,\n type SequencedRow,\n} from '../documents/processing-order'\n\n/** `error`: the host's socket failed. */\nexport type ArbiWsStatus = 'disconnected' | 'connecting' | 'connected' | 'reconnecting' | 'error'\n\n/**\n * A document's live processing: its last `task_update` (or a status set here, such as \"queued\"\n * while a write sends it back into processing), with when it was first seen (`startTime`) and\n * when it finished (`endTime`), both on this device's clock.\n */\nexport type LiveTask = Omit<WsTaskUpdateMessage, 'type' | 'seq'> & {\n type?: 'task_update'\n seq?: number | null\n startTime?: number\n endTime?: number\n}\n\n/** How long a document's tasks stay dismissed (late updates of a deleted upload are dropped). */\nexport const DISMISSED_TASK_TTL_MS = 10 * 60 * 1000\n\nexport interface ArbiWsState {\n /** Live connection status of the shared socket. */\n status: ArbiWsStatus\n /** Latest processing status per document id (the `task_update` stream). */\n tasks: Record<string, LiveTask>\n /** Documents whose processing rows were dismissed (deleted, cleared), with when. */\n dismissed: Record<string, number>\n /** The most recent `task_update` — a convenient single-value change trigger. */\n lastTaskUpdate: WsTaskUpdateMessage | null\n /** Online status keyed by user id (the `presence_update` stream). */\n presence: Record<string, string>\n /**\n * The server closed this socket for a newer session of the same user (another device, close\n * code 1008). The socket stays closed: reconnecting would only be evicted again.\n */\n evicted: boolean\n setStatus: (status: ArbiWsStatus) => void\n setEvicted: (evicted: boolean) => void\n /**\n * Take a `task_update`, unless it is older than the one held for its document (`seq`) or the\n * document was dismissed a moment ago. Resolves whether it was taken.\n */\n applyTaskUpdate: (msg: WsTaskUpdateMessage) => boolean\n /** Set a document's live processing directly (an optimistic status, or an undo). */\n putTask: (task: LiveTask) => void\n /** Drop a document's processing row, and ignore its late updates for a while. */\n clearTask: (docId: string) => void\n /** Drop every finished processing row (the in-flight ones stay). */\n clearFinishedTasks: () => void\n /** End the in-flight statuses that documents read since say finished after them. */\n settleTasks: (rows: ReadonlyArray<SequencedRow & { external_id: string }>) => void\n applyPresence: (msg: WsPresenceUpdateMessage) => void\n reset: () => void\n}\n\nconst finished = (status: string) => FINISHED_DOCUMENT_STATUSES.has(status)\n\nexport const useArbiWsStore = create<ArbiWsState>((set, get) => ({\n status: 'disconnected',\n tasks: {},\n dismissed: {},\n lastTaskUpdate: null,\n presence: {},\n evicted: false,\n setStatus: (status) => set({ status }),\n setEvicted: (evicted) => set({ evicted }),\n applyTaskUpdate: (msg) => {\n const { tasks, dismissed } = get()\n const dismissedAt = dismissed[msg.doc_ext_id]\n if (dismissedAt !== undefined && Date.now() - dismissedAt < DISMISSED_TASK_TTL_MS) return false\n const held = tasks[msg.doc_ext_id]\n if (isStaleTaskUpdate(held, msg)) return false\n const now = Date.now()\n const task: LiveTask = {\n ...msg,\n startTime: held?.startTime ?? now,\n endTime: finished(msg.status) ? (held?.endTime ?? now) : undefined,\n }\n set({ tasks: { ...tasks, [msg.doc_ext_id]: task }, lastTaskUpdate: msg })\n return true\n },\n putTask: (task) => set((s) => ({ tasks: { ...s.tasks, [task.doc_ext_id]: task } })),\n clearTask: (docId) =>\n set((s) => {\n const tasks = { ...s.tasks }\n delete tasks[docId]\n return { tasks, dismissed: { ...s.dismissed, [docId]: Date.now() } }\n }),\n clearFinishedTasks: () =>\n set((s) => ({\n tasks: Object.fromEntries(Object.entries(s.tasks).filter(([, t]) => !finished(t.status))),\n })),\n settleTasks: (rows) =>\n set((s) => {\n const settled = settledByRows(s.tasks, rows)\n if (!settled.length) return s\n const tasks = { ...s.tasks }\n const now = Date.now()\n for (const task of settled)\n tasks[task.doc_ext_id] = { ...(task as LiveTask), endTime: task.endTime ?? now }\n return { tasks }\n }),\n applyPresence: (msg) => set((s) => ({ presence: { ...s.presence, [msg.user_id]: msg.status } })),\n reset: () =>\n set({ status: 'disconnected', tasks: {}, dismissed: {}, lastTaskUpdate: null, presence: {} }),\n}))\n","/**\n * Reading documents: a workspace's list (`useDocuments`, progressive, read once and then patched in\n * place), one document (`useDocument`, for a viewer), a set of documents by id, near-duplicate pairs\n * (`useSimilarDocuments`), and {@link refreshDocuments}, which re-reads just the documents an event\n * named and patches them into every cache that shows them.\n */\n\nimport { useCallback } from 'react'\nimport { useQuery, useQueryClient, type QueryClient } from '@tanstack/react-query'\nimport type { Arbi } from '@arbidocs/sdk/browser'\nimport { useArbi } from '../useArbi'\nimport { arbiQueryKeys } from '../hooks'\nimport { invalidateTagTables, patchWorkspaceTags } from '../tags'\nimport {\n getCachedDocuments,\n setCachedDocument,\n upsertDocuments,\n type WorkspaceDocument,\n} from './documents-cache'\nimport { loadDocuments } from './documents-loader'\nimport { FINISHED_DOCUMENT_STATUSES, isRowNewer } from './processing-order'\nimport { useArbiWsStore } from '../websocket/store'\n\nexport { FINISHED_DOCUMENT_STATUSES }\n\n/** The workspace open on `arbi`, or `null`. */\nfunction openWorkspaceId(arbi: Arbi): string | null {\n return arbi.hasWorkspace ? arbi.getWorkspaceId() : null\n}\n\n/**\n * A workspace's documents (default: the open one). Read progressively: the first page is the\n * result, the remaining pages arrive in the background (`useDocumentsLoading`). After that the list\n * is never re-read on its own (mounting, focus, reconnecting): writes, processing events and\n * {@link refreshDocuments} patch it in place, as re-reading 100k documents is slow and tells\n * nothing new. Invalidating it re-reads it.\n */\nexport function useDocuments(workspaceId?: string | null, options?: { enabled?: boolean }) {\n const arbi = useArbi()\n const qc = useQueryClient()\n const workspace = workspaceId ?? openWorkspaceId(arbi) ?? ''\n return useQuery({\n queryKey: arbiQueryKeys.documents(workspace),\n queryFn: ({ signal }) => {\n if (openWorkspaceId(arbi) !== workspace)\n return Promise.reject(new Error('The selected workspace changed.'))\n return loadDocuments(qc, arbi, workspace, signal)\n },\n enabled: (options?.enabled ?? true) && !!workspace && arbi.hasWorkspace,\n staleTime: Infinity,\n refetchOnMount: false,\n refetchOnReconnect: false,\n refetchOnWindowFocus: false,\n })\n}\n\n/** How often a document still being processed is re-read (`useDocument`'s `pollWhileProcessing`). */\nexport const DOCUMENT_STATUS_POLL_MS = 4000\n\n/** Re-read a document while it is processing (a viewer waiting for its pages). */\nfunction processingInterval(doc: WorkspaceDocument | null | undefined): number | false {\n return doc?.status && !FINISHED_DOCUMENT_STATUSES.has(doc.status)\n ? DOCUMENT_STATUS_POLL_MS\n : false\n}\n\n/**\n * One document (`null`: not found or not visible). `pollWhileProcessing` re-reads it every few\n * seconds until its processing is over. Writes here keep it current.\n */\nexport function useDocument(\n docId: string | null | undefined,\n options?: { enabled?: boolean; pollWhileProcessing?: boolean }\n) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.document(docId ?? ''),\n queryFn: async (): Promise<WorkspaceDocument | null> =>\n (await arbi.documents.get([docId as string]))[0] ?? null,\n enabled: (options?.enabled ?? true) && !!docId && arbi.isLoggedIn,\n refetchInterval: options?.pollWhileProcessing\n ? (query) => processingInterval(query.state.data)\n : false,\n })\n}\n\n/**\n * The similarity at or above which two documents count as near duplicates (the Related column).\n * The server keeps every pair above 0.75 but returns only those at or above what is asked.\n */\nexport const SIMILARITY_THRESHOLD = 0.98\n\n/** Near-duplicate document pairs in the open workspace, at or above {@link SIMILARITY_THRESHOLD}. */\nexport function useSimilarDocuments(options?: { enabled?: boolean }) {\n const arbi = useArbi()\n const workspace = openWorkspaceId(arbi) ?? ''\n return useQuery({\n queryKey: arbiQueryKeys.similarDocuments(workspace, SIMILARITY_THRESHOLD),\n queryFn: () =>\n arbi.readInWorkspace(workspace, () =>\n arbi.documents.similar({ threshold: SIMILARITY_THRESHOLD })\n ),\n enabled: (options?.enabled ?? true) && !!workspace,\n })\n}\n\n// Each re-read gets a number; only the latest one issued for a document may write it. Events can\n// return out of order, and an older read must not undo tags a newer one applied.\nlet readSeq = 0\nconst latestReadByDoc = new Map<string, number>()\n\n/**\n * Re-read `docIds` and patch them into the caches that show them: their workspace's list (added\n * when new), their own entries, and the tag list's document counts (tags the server applied, e.g.\n * AI fields). For events that name documents (a batch finished, a version saved, an upload): the\n * list is never re-read for them. A failed read leaves the caches as they were.\n */\nexport async function refreshDocuments(\n qc: QueryClient,\n arbi: Arbi,\n docIds: string[]\n): Promise<WorkspaceDocument[]> {\n if (!docIds.length) return []\n const seq = ++readSeq\n for (const id of docIds) latestReadByDoc.set(id, seq)\n try {\n const read = await arbi.documents.get(docIds)\n const fresh = read\n .filter((doc) => latestReadByDoc.get(doc.external_id) === seq)\n .map((doc) => {\n // A finished status heard live wins over a read that predates it (the row may not be\n // committed yet), never over a row that finished after it.\n const live = useArbiWsStore.getState().tasks[doc.external_id]\n return live &&\n FINISHED_DOCUMENT_STATUSES.has(live.status) &&\n doc.status !== live.status &&\n isRowNewer(doc, live) !== true\n ? { ...doc, status: live.status }\n : doc\n })\n if (!fresh.length) return []\n reconcileTagCounts(qc, fresh)\n upsertDocuments(qc, fresh)\n for (const doc of fresh) setCachedDocument(qc, doc)\n return fresh\n } catch (error) {\n // Leave the caches as they were: re-reading the whole list would shrink it to its first page.\n console.error('Re-reading documents failed; the cached ones are kept:', error)\n return []\n } finally {\n for (const id of docIds) if (latestReadByDoc.get(id) === seq) latestReadByDoc.delete(id)\n }\n}\n\n/** `refreshDocuments` on this host's cache and `Arbi`, for a component or a hook. */\nexport function useRefreshDocuments(): (docIds: string[]) => Promise<WorkspaceDocument[]> {\n const qc = useQueryClient()\n const arbi = useArbi()\n return useCallback((docIds: string[]) => refreshDocuments(qc, arbi, docIds), [qc, arbi])\n}\n\n/** Move each tag's document count by the tags the re-read documents gained or lost. */\nfunction reconcileTagCounts(qc: QueryClient, fresh: WorkspaceDocument[]): void {\n const byWorkspace = new Map<string, Map<string, number>>()\n for (const doc of fresh) {\n const cached = getCachedDocuments(qc, doc.workspace_ext_id)?.find(\n (d) => d.external_id === doc.external_id\n )\n const before = new Set((cached?.doctags ?? []).map((dt) => dt.tag_ext_id))\n const after = new Set((doc.doctags ?? []).map((dt) => dt.tag_ext_id))\n const delta = byWorkspace.get(doc.workspace_ext_id) ?? new Map<string, number>()\n for (const id of after) if (!before.has(id)) delta.set(id, (delta.get(id) ?? 0) + 1)\n for (const id of before) if (!after.has(id)) delta.set(id, (delta.get(id) ?? 0) - 1)\n byWorkspace.set(doc.workspace_ext_id, delta)\n }\n for (const [workspaceId, delta] of byWorkspace) adjustTagCounts(qc, workspaceId, delta)\n}\n\n/** Add `delta` (tag id → change) to the tags' document counts; the tag tables re-read. */\nexport function adjustTagCounts(\n qc: QueryClient,\n workspaceId: string,\n delta: Map<string, number>\n): void {\n if (![...delta.values()].some(Boolean)) return\n patchWorkspaceTags(qc, workspaceId, (tags) =>\n tags.map((tag) => {\n const change = delta.get(tag.external_id)\n return change ? { ...tag, doctag_count: Math.max(0, tag.doctag_count + change) } : tag\n })\n )\n void invalidateTagTables(qc, workspaceId)\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/documents/documents-cache.ts","../src/entity-extraction.ts","../src/queued-writes.ts","../src/tags.ts","../src/documents/documents-loader.ts","../src/documents/processing-order.ts","../src/websocket/store.ts","../src/documents/documents-data.ts"],"names":["update","useCallback","tagOps","controller","create","openWorkspaceId","useQueryClient","useQuery"],"mappings":";;;;;;;;AA4BA,IAAM,YAAA,uBAAmB,GAAA,EAAiB;AAMnC,SAAS,sBAAsB,QAAA,EAAmC;AACvE,EAAA,YAAA,CAAa,IAAI,QAAQ,CAAA;AACzB,EAAA,OAAO,MAAM;AACX,IAAA,YAAA,CAAa,OAAO,QAAQ,CAAA;AAAA,EAC9B,CAAA;AACF;AAGO,SAAS,kBAAA,CACd,IACA,WAAA,EACiC;AACjC,EAAA,IAAI,CAAC,aAAa,OAAO,MAAA;AACzB,EAAA,OAAO,EAAA,CAAG,YAAA,CAAkC,aAAA,CAAc,SAAA,CAAU,WAAW,CAAC,CAAA;AAClF;AAGA,SAAS,YAAY,EAAA,EAAuD;AAC1E,EAAA,OAAO,EAAA,CACJ,eAAoC,EAAE,QAAA,EAAU,cAAc,YAAA,EAAa,EAAG,CAAA,CAC9E,OAAA;AAAA,IAAQ,CAAC,CAAC,GAAA,EAAK,IAAI,MAClB,OAAO,GAAA,CAAI,CAAC,CAAA,KAAM,QAAA,IAAY,KAAA,CAAM,QAAQ,IAAI,CAAA,GAAI,CAAC,CAAC,GAAA,CAAI,CAAC,CAAA,EAAG,IAAI,CAAC,CAAA,GAAI;AAAC,GAC1E;AACJ;AAGA,SAAS,QAAA,CACP,WAAA,EACA,MAAA,EACA,KAAA,EACmB;AACnB,EAAA,MAAM,UAAA,GAAa,IAAI,GAAA,CAAI,MAAA,CAAO,GAAA,CAAI,CAAC,GAAA,KAAQ,CAAC,GAAA,CAAI,WAAA,EAAa,GAAG,CAAC,CAAC,CAAA;AACtE,EAAA,MAAM,MAA2B,EAAC;AAClC,EAAA,MAAMA,UAA8B,EAAC;AACrC,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAC7B,EAAA,KAAA,MAAW,OAAO,KAAA,EAAO;AACvB,IAAA,IAAA,CAAK,GAAA,CAAI,IAAI,WAAW,CAAA;AACxB,IAAA,MAAM,QAAA,GAAW,UAAA,CAAW,GAAA,CAAI,GAAA,CAAI,WAAW,CAAA;AAC/C,IAAA,IAAI,CAAC,QAAA,EAAU,GAAA,CAAI,IAAA,CAAK,GAAG,CAAA;AAAA,SAAA,IAClB,QAAA,KAAa,GAAA,EAAKA,OAAAA,CAAO,KAAK,GAAG,CAAA;AAAA,EAC5C;AACA,EAAA,MAAM,MAAA,GAAS,CAAC,GAAG,UAAA,CAAW,MAAM,CAAA,CAAE,MAAA,CAAO,CAAC,EAAA,KAAO,CAAC,IAAA,CAAK,GAAA,CAAI,EAAE,CAAC,CAAA;AAClE,EAAA,OAAO,EAAE,WAAA,EAAa,GAAA,EAAK,MAAA,EAAAA,SAAQ,MAAA,EAAO;AAC5C;AAQO,SAAS,cAAA,CACd,EAAA,EACA,OAAA,EACA,WAAA,EACM;AACN,EAAA,MAAM,KAAA,GAA8C,eAC/C,MAAM;AACL,IAAA,MAAM,OAAA,GAAU,kBAAA,CAAmB,EAAA,EAAI,WAAW,CAAA;AAClD,IAAA,OAAO,UAAU,CAAC,CAAC,aAAa,OAAO,CAAkC,IAAI,EAAC;AAAA,EAChF,CAAA,GAAG,GACH,WAAA,CAAY,EAAE,CAAA;AAClB,EAAA,KAAA,MAAW,CAAC,EAAA,EAAI,MAAM,CAAA,IAAK,KAAA,EAAO;AAChC,IAAA,MAAM,KAAA,GAAQ,QAAQ,MAAM,CAAA;AAC5B,IAAA,IAAI,UAAU,MAAA,EAAQ;AACtB,IAAA,EAAA,CAAG,YAAA,CAAa,aAAA,CAAc,SAAA,CAAU,EAAE,GAAG,KAAK,CAAA;AAClD,IAAA,MAAM,MAAA,GAAS,QAAA,CAAS,EAAA,EAAI,MAAA,EAAQ,KAAK,CAAA;AACzC,IAAA,MAAM,UAAA,GAAa,IAAI,GAAA,CAAI,MAAA,CAAO,GAAA,CAAI,CAAC,GAAA,KAAQ,CAAC,GAAA,CAAI,WAAA,EAAa,GAAG,CAAC,CAAC,CAAA;AACtE,IAAA,IACE,OAAO,MAAA,CAAO,IAAA;AAAA,MACZ,CAAC,QAAQ,GAAA,CAAI,eAAA,KAAoB,WAAW,GAAA,CAAI,GAAA,CAAI,WAAW,CAAA,EAAG;AAAA,KACpE;AAEA,MAAA,KAAK,GAAG,iBAAA,CAAkB,EAAE,UAAU,aAAA,CAAc,mBAAA,IAAuB,CAAA;AAC7E,IAAA,IAAI,OAAO,GAAA,CAAI,MAAA,IAAU,OAAO,MAAA,CAAO,MAAA,IAAU,OAAO,MAAA,CAAO,MAAA;AAC7D,MAAA,KAAA,MAAW,QAAA,IAAY,YAAA,EAAc,QAAA,CAAS,MAAM,CAAA;AAAA,EACxD;AACF;AAGO,SAAS,eAAA,CACd,EAAA,EACA,SAAA,EACA,WAAA,EACM;AACN,EAAA,IAAI,CAAC,UAAU,MAAA,EAAQ;AACvB,EAAA,MAAM,IAAA,GAAO,IAAI,GAAA,CAAI,SAAA,CAAU,GAAA,CAAI,CAAC,GAAA,KAAQ,CAAC,GAAA,CAAI,WAAA,EAAa,GAAG,CAAC,CAAC,CAAA;AACnE,EAAA,MAAM,WAAA,uBAAkB,GAAA,EAAiC;AACzD,EAAA,KAAA,MAAW,OAAO,SAAA,EAAW;AAC3B,IAAA,MAAM,EAAA,GAAK,eAAe,GAAA,CAAI,gBAAA;AAC9B,IAAA,WAAA,CAAY,GAAA,CAAI,EAAA,EAAI,CAAC,GAAI,WAAA,CAAY,GAAA,CAAI,EAAE,CAAA,IAAK,EAAC,EAAI,GAAG,CAAC,CAAA;AAAA,EAC3D;AACA,EAAA,KAAA,MAAW,CAAC,EAAA,EAAI,QAAQ,CAAA,IAAK,WAAA,EAAa;AACxC,IAAA,cAAA;AAAA,MACE,EAAA;AAAA,MACA,CAAC,GAAA,KAAQ;AACP,QAAA,MAAM,KAAA,GAAQ,IAAI,GAAA,CAAI,GAAA,CAAI,IAAI,CAAC,GAAA,KAAQ,GAAA,CAAI,WAAW,CAAC,CAAA;AACvD,QAAA,OAAO;AAAA,UACL,GAAG,GAAA,CAAI,GAAA,CAAI,CAAC,GAAA,KAAQ,KAAK,GAAA,CAAI,GAAA,CAAI,WAAW,CAAA,IAAK,GAAG,CAAA;AAAA,UACpD,GAAG,QAAA,CAAS,MAAA,CAAO,CAAC,GAAA,KAAQ,CAAC,KAAA,CAAM,GAAA,CAAI,GAAA,CAAI,WAAW,CAAC;AAAA,SACzD;AAAA,MACF,CAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF;AACF;AAGO,SAAS,iBAAA,CAAkB,IAAiB,GAAA,EAA8B;AAC/E,EAAA,EAAA,CAAG,aAAa,aAAA,CAAc,QAAA,CAAS,GAAA,CAAI,WAAW,GAAG,GAAG,CAAA;AAC9D;AAGO,SAAS,mBAAA,CACd,EAAA,EACA,KAAA,EACA,OAAA,EACM;AACN,EAAA,MAAM,UAAU,EAAA,CAAG,YAAA,CAAuC,aAAA,CAAc,QAAA,CAAS,KAAK,CAAC,CAAA;AACvF,EAAA,IAAI,OAAA,KAAY,YAAA,CAAa,aAAA,CAAc,SAAS,KAAK,CAAA,EAAG,OAAA,CAAQ,OAAO,CAAC,CAAA;AAC9E;AAGO,SAAS,0BAAA,CAA2B,IAAiB,KAAA,EAAqB;AAC/E,EAAA,MAAM,KAAA,GAAQ,CAAC,GAAA,KAA8C;AAC3D,IAAA,MAAM,OAAA,GAAU,IAAI,OAAA,EAAS,MAAA,CAAO,CAAC,EAAA,KAAO,EAAA,CAAG,eAAe,KAAK,CAAA;AACnE,IAAA,OAAO,OAAA,IAAW,OAAA,CAAQ,MAAA,KAAW,GAAA,CAAI,OAAA,EAAS,SAAS,EAAE,GAAG,GAAA,EAAK,OAAA,EAAQ,GAAI,GAAA;AAAA,EACnF,CAAA;AACA,EAAA,MAAM,WAAqB,EAAC;AAC5B,EAAA,cAAA,CAAe,EAAA,EAAI,CAAC,IAAA,KAAS;AAC3B,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,KAAK,CAAA;AAC3B,IAAA,IAAA,CAAK,OAAA,CAAQ,CAAC,GAAA,EAAK,CAAA,KAAM,GAAA,KAAQ,IAAA,CAAK,CAAC,CAAA,IAAK,QAAA,CAAS,IAAA,CAAK,GAAA,CAAI,WAAW,CAAC,CAAA;AAC1E,IAAA,OAAO,QAAA,CAAS,SAAS,IAAA,GAAO,IAAA;AAAA,EAClC,CAAC,CAAA;AACD,EAAA,KAAA,MAAW,EAAA,IAAM,QAAA,EAAU,mBAAA,CAAoB,EAAA,EAAI,IAAI,KAAK,CAAA;AAC9D;AAGO,SAAS,eAAA,CAAgB,IAAiB,MAAA,EAAwB;AACvE,EAAA,KAAA,MAAW,MAAM,MAAA,EAAQ;AACvB,IAAA,EAAA,CAAG,cAAc,EAAE,QAAA,EAAU,cAAc,QAAA,CAAS,EAAE,GAAG,CAAA;AACzD,IAAA,EAAA,CAAG,cAAc,EAAE,QAAA,EAAU,cAAc,gBAAA,CAAiB,EAAE,GAAG,CAAA;AACjE,IAAA,EAAA,CAAG,cAAc,EAAE,QAAA,EAAU,cAAc,cAAA,CAAe,EAAE,GAAG,CAAA;AAAA,EACjE;AACF;ACzKA,IAAM,2BAA2B,MAAA,CAAsC,OAAO,EAAE,MAAA,EAAQ,IAAG,CAAE,CAAA;AAE7F,SAAS,MAAA,CAAO,QAA2B,OAAA,EAAwB;AACjE,EAAA,IAAI,CAAC,OAAO,MAAA,EAAQ;AACpB,EAAA,wBAAA,CAAyB,QAAA,CAAS,CAAC,KAAA,KAAU;AAC3C,IAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,KAAA,CAAM,MAAM,CAAA;AAChC,IAAA,MAAA,CAAO,OAAA,CAAQ,CAAC,EAAA,KAAQ,OAAA,GAAU,GAAA,CAAI,GAAA,CAAI,EAAE,CAAA,GAAI,GAAA,CAAI,MAAA,CAAO,EAAE,CAAE,CAAA;AAC/D,IAAA,OAAO,EAAE,MAAA,EAAQ,CAAC,GAAG,GAAG,CAAA,EAAE;AAAA,EAC5B,CAAC,CAAA;AACH;AAGO,SAAS,sBAAsB,MAAA,EAAiC;AACrE,EAAA,MAAA,CAAO,QAAQ,IAAI,CAAA;AACrB;AAGO,SAAS,uBAAuB,MAAA,EAAiC;AACtE,EAAA,MAAA,CAAO,QAAQ,KAAK,CAAA;AACtB;AAGO,SAAS,yBAAA,GAA+C;AAC7D,EAAA,OAAO,wBAAA,CAAyB,CAAC,KAAA,KAAU,KAAA,CAAM,MAAM,CAAA;AACzD;ACTO,IAAM,4BAAA,GACX;AAMK,SAAS,cAAc,MAAA,EAAqC;AACjE,EAAA,OAAO,CAAC,WAAA,KACN,WAAA,KAAgB,MAAA,CAAO,OAAA,CAAQ,QAAA,EAAS,CAAE,mBAAA,GACtC,MAAA,GACA,MAAA,CAAO,aAAA,CAAc,KAAA,CAAM,WAAW,CAAA;AAC9C;AAGO,SAAS,YAAY,IAAA,EAIR;AAClB,EAAA,OAAO,CAAC,WAAA,KACN,IAAA,CAAK,YAAA,IAAgB,WAAA,KAAgB,IAAA,CAAK,cAAA,EAAe,GACrD,MAAA,GACA,IAAA,CAAK,UAAA,CAAW,IAAA,CAAK,WAAW,CAAA;AACxC;AAOA,eAAsB,WAAA,CACpB,KAAA,EACA,WAAA,EACA,KAAA,EACY;AACZ,EAAA,IAAI,WAAA,EAAa;AACf,IAAA,IAAI;AACF,MAAA,MAAM,MAAM,WAAW,CAAA;AAAA,IACzB,SAAS,KAAA,EAAO;AACd,MAAA,IAAI,YAAA,CAAa,KAAK,CAAA,EAAG,MAAM,KAAA;AAC/B,MAAA,MAAM,IAAI,6BAAA,CAA8B,WAAA,EAAa,KAAA,EAAO,4BAA4B,CAAA;AAAA,IAC1F;AAAA,EACF;AACA,EAAA,OAAO,KAAA,EAAM;AACf;AAGO,SAAS,uBAAuB,KAAA,EAAyB;AAC9D,EAAA,OAAO,KAAA,YAAiB,6BAAA;AAC1B;AAGO,IAAM,kBAAA,GAAqB;AAAA,EAChC,OAAO,CAAC,YAAA,EAAsB,UAC5B,sBAAA,CAAuB,KAAK,KAAK,YAAA,GAAe,CAAA;AAAA,EAClD,UAAA,EAAY,CAAC,OAAA,KAAoB,IAAA,CAAK,IAAI,GAAA,GAAO,CAAA,IAAK,SAAS,GAAM;AACvE;AAGO,SAAS,qBAAqB,QAAA,EAEzB;AACV,EAAA,OAAO,uBAAuB,QAAA,CAAS,KAAA,CAAM,KAAA,IAAS,QAAA,CAAS,MAAM,aAAa,CAAA;AACpF;AAOO,SAAS,qBAAA,CAGd,UAAa,OAAA,EAAiC;AAC9C,EAAA,MAAM,UAAA,GAAa,OAAO,OAAO,CAAA;AACjC,EAAA,UAAA,CAAW,OAAA,GAAU,OAAA;AACrB,EAAA,MAAM,EAAE,MAAA,EAAQ,SAAA,EAAW,WAAA,EAAa,gBAAe,GAAI,QAAA;AAC3D,EAAA,MAAM,MAAA,GAAS,WAAA;AAAA,IACb,CAAC,cAAiB,IAAA,KACf,SAAA,CAA+C,WAAW,OAAA,CAAQ,SAAS,CAAA,EAAG,GAAG,IAAI,CAAA;AAAA,IACxF,CAAC,SAAS;AAAA,GACZ;AACA,EAAA,MAAM,WAAA,GAAc,WAAA;AAAA,IAClB,CAAC,cAAiB,IAAA,KACf,cAAA;AAAA,MACC,UAAA,CAAW,QAAQ,SAAS,CAAA;AAAA,MAC5B,GAAG;AAAA,KACL;AAAA,IACF,CAAC,cAAc;AAAA,GACjB;AACA,EAAA,OAAO,EAAE,GAAG,QAAA,EAAU,MAAA,EAAQ,WAAA,EAAY;AAC5C;;;AC1EA,SAAS,cAAA,CAAe,IAAiB,KAAA,EAA8B;AACrE,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,IAAI,CAAA,IAAK,GAAG,cAAA,CAA8B;AAAA,IACzD,QAAA,EAAU,cAAc,OAAA;AAAQ,GACjC,CAAA,EAAG;AACF,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,IAAK,IAAA,CAAK,KAAK,CAAC,CAAA,KAAM,CAAA,CAAE,WAAA,KAAgB,KAAK,CAAA;AACjE,MAAA,OAAQ,GAAA,CAAI,CAAC,CAAA,IAA4B,IAAA;AAAA,EAC7C;AACA,EAAA,OAAO,IAAA;AACT;AAEA,SAAS,gBAAgB,IAAA,EAAiD;AACxE,EAAA,OAAO,IAAA,CAAK,YAAA,GAAe,IAAA,CAAK,cAAA,EAAe,GAAI,IAAA;AACrD;AAOO,SAAS,kBAAA,CACd,EAAA,EACA,WAAA,EACA,OAAA,EACM;AACN,EAAA,MAAM,GAAA,GAAM,aAAA,CAAc,IAAA,CAAK,WAAW,CAAA;AAC1C,EAAA,MAAM,OAAA,GAAU,EAAA,CAAG,YAAA,CAA4B,GAAG,CAAA;AAClD,EAAA,IAAI,CAAC,OAAA,EAAS;AACd,EAAA,MAAM,IAAA,GAAO,QAAQ,OAAO,CAAA;AAC5B,EAAA,IAAI,IAAA,KAAS,OAAA,EAAS,EAAA,CAAG,YAAA,CAAa,KAAK,IAAI,CAAA;AACjD;AAGO,SAAS,mBAAA,CAAoB,IAAiB,WAAA,EAAoC;AACvF,EAAA,OAAO,EAAA,CAAG,kBAAkB,EAAE,QAAA,EAAU,cAAc,QAAA,CAAS,WAAW,GAAG,CAAA;AAC/E;AAGO,SAAS,iBAAA,CAAkB,IAAiB,WAAA,EAAuC;AACxF,EAAA,OAAO,QAAQ,GAAA,CAAI;AAAA,IACjB,EAAA,CAAG,kBAAkB,EAAE,QAAA,EAAU,cAAc,IAAA,CAAK,WAAW,GAAG,CAAA;AAAA,IAClE,EAAA,CAAG,kBAAkB,EAAE,QAAA,EAAU,cAAc,KAAA,CAAM,WAAW,GAAG;AAAA,GACpE,CAAA;AACH;AAGO,SAAS,oBAAA,GAA+C;AAC7D,EAAA,MAAM,OAAO,OAAA,EAAQ;AACrB,EAAA,MAAM,KAAK,cAAA,EAAe;AAC1B,EAAA,OAAOC,YAAY,MAAM;AACvB,IAAA,MAAM,WAAA,GAAc,gBAAgB,IAAI,CAAA;AACxC,IAAA,OAAO,cAAc,iBAAA,CAAkB,EAAA,EAAI,WAAW,CAAA,GAAI,QAAQ,OAAA,EAAQ;AAAA,EAC5E,CAAA,EAAG,CAAC,IAAA,EAAM,EAAE,CAAC,CAAA;AACf;AASA,SAAS,gBAAA,CAAiB,IAAiB,OAAA,EAAqC;AAC9E,EAAA,MAAM,cAAc,OAAA,CAAQ,gBAAA;AAC5B,EAAA,kBAAA;AAAA,IAAmB,EAAA;AAAA,IAAI,WAAA;AAAA,IAAa,CAAC,GAAA,KACnC,GAAA,CAAI,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,WAAA,KAAgB,OAAA,CAAQ,WAAW,CAAA,GAAI,GAAA,GAAM,CAAC,GAAG,KAAK,OAAO;AAAA,GACjF;AACA,EAAA,OAAO,mBAAA,CAAoB,IAAI,WAAW,CAAA;AAC5C;AAGA,SAAS,gBAAA,CAAiB,IAAiB,GAAA,EAAiC;AAC1E,EAAA,MAAM,cAAc,GAAA,CAAI,gBAAA;AACxB,EAAA,kBAAA;AAAA,IAAmB,EAAA;AAAA,IAAI,WAAA;AAAA,IAAa,CAAC,GAAA,KACnC,GAAA,CAAI,GAAA,CAAI,CAAC,MAAO,CAAA,CAAE,WAAA,KAAgB,GAAA,CAAI,WAAA,GAAc,EAAE,GAAG,CAAA,EAAG,GAAG,GAAA,KAAQ,CAAE;AAAA,GAC3E;AACA,EAAA,OAAO,mBAAA,CAAoB,IAAI,WAAW,CAAA;AAC5C;AAMO,IAAM,sBAAA,GAAyB;AAAA,EACpC;AAAA,IACE,WAAA,EAAa,iBAAiB,SAAA,EAAU;AAAA;AAAA,IAExC,GAAA,EAAK,CAAC,MAAA,EAAoB,KAAA,KACxB,YAAY,aAAA,CAAc,MAAM,CAAA,EAAG,KAAA,CAAM,aAAa,MAAMC,IAAA,CAAO,SAAA,CAAU,MAAA,EAAQ,KAAK,CAAC,CAAA;AAAA,IAC7F,QAAQ,CAAC,EAAA,EAAiB,OAAA,KAAyB,gBAAA,CAAiB,IAAI,OAAO;AAAA;AAEnF;AAOO,SAAS,YAAA,GAAe;AAC7B,EAAA,MAAM,OAAO,OAAA,EAAQ;AACrB,EAAA,MAAM,KAAK,cAAA,EAAe;AAE1B,EAAA,MAAM,OAAA,GAAU,CAAC,KAAA,KACf,KAAA,CAAM,eAAe,CAAC,IAAA,CAAK,YAAA,GACvB,KAAA,GACA,EAAE,GAAG,KAAA,EAAO,WAAA,EAAa,IAAA,CAAK,gBAAe,EAAE;AACrD,EAAA,OAAO,qBAAA;AAAA,IACL,WAAA,CAAY;AAAA,MACV,WAAA,EAAa,iBAAiB,SAAA,EAAU;AAAA,MACxC,UAAA,EAAY,CAAC,KAAA,KACX,WAAA,CAAY,YAAY,IAAI,CAAA,EAAG,KAAA,CAAM,WAAA,EAAa,MAAM,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,KAAK,CAAC,CAAA;AAAA,MACjF,SAAA,EAAW,CAAC,OAAA,KAAY,gBAAA,CAAiB,IAAI,OAAO,CAAA;AAAA,MACpD,GAAG;AAAA,KACJ,CAAA;AAAA,IACD;AAAA,GACF;AACF;AAMO,SAAS,gBAAA,GAA8C;AAC5D,EAAA,MAAM,KAAK,cAAA,EAAe;AAC1B,EAAA,OAAOD,WAAAA;AAAA,IACL,CAAC,IAAA,KAAiB;AAChB,MAAA,MAAM,MAAA,GAAS,IAAA,CAAK,IAAA,EAAK,CAAE,WAAA,EAAY;AACvC,MAAA,OACE,EAAA,CAAG,gBAAA,EAAiB,CAAE,OAAA,CAAQ;AAAA,QAC5B,WAAA,EAAa,iBAAiB,SAAA,EAAU;AAAA,QACxC,SAAA,EAAW,CAAC,CAAA,KACV,CAAA,CAAE,MAAM,MAAA,KAAW,SAAA,IAClB,CAAA,CAAE,KAAA,CAAM,SAAA,EAA0C,IAAA,CAAK,IAAA,EAAK,CAAE,aAAY,KAAM;AAAA,OACpF,EAAE,MAAA,GAAS,CAAA;AAAA,IAEhB,CAAA;AAAA,IACA,CAAC,EAAE;AAAA,GACL;AACF;AAGO,SAAS,YAAA,GAAe;AAC7B,EAAA,MAAM,OAAO,OAAA,EAAQ;AACrB,EAAA,MAAM,KAAK,cAAA,EAAe;AAC1B,EAAA,OAAO,WAAA,CAAY;AAAA,IACjB,WAAA,EAAa,iBAAiB,SAAA,EAAU;AAAA,IACxC,UAAA,EAAY,CAAC,EAAE,KAAA,EAAO,MAAA,OACpB,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,KAAA,EAAO,MAAM,CAAA;AAAA,IAChC,SAAA,EAAW,CAAC,GAAA,KAAQ,gBAAA,CAAiB,IAAI,GAAG;AAAA,GAC7C,CAAA;AACH;AAGO,SAAS,eAAA,GAAkB;AAChC,EAAA,MAAM,OAAO,OAAA,EAAQ;AACrB,EAAA,MAAM,KAAK,cAAA,EAAe;AAC1B,EAAA,OAAO,WAAA,CAAY;AAAA,IACjB,WAAA,EAAa,iBAAiB,SAAA,EAAU;AAAA,IACxC,YAAY,CAAC;AAAA,MACX,KAAA;AAAA,MACA;AAAA,KACF,KAG4B,IAAA,CAAK,IAAA,CAAK,SAAA,CAAU,OAAO,MAAM,CAAA;AAAA,IAC7D,SAAA,EAAW,CAAC,GAAA,KAAQ,gBAAA,CAAiB,IAAI,GAAG;AAAA,GAC7C,CAAA;AACH;AAOO,SAAS,YAAA,GAAe;AAC7B,EAAA,MAAM,OAAO,OAAA,EAAQ;AACrB,EAAA,MAAM,KAAK,cAAA,EAAe;AAC1B,EAAA,OAAO,WAAA,CAAY;AAAA,IACjB,WAAA,EAAa,iBAAiB,SAAA,EAAU;AAAA,IACxC,YAAY,CAAC,KAAA,KAAkB,IAAA,CAAK,IAAA,CAAK,OAAO,KAAK,CAAA;AAAA;AAAA;AAAA,IAGrD,QAAA,EAAU,CAAC,KAAA,MAAW,EAAE,WAAA,EAAa,cAAA,CAAe,EAAA,EAAI,KAAK,CAAA,IAAK,eAAA,CAAgB,IAAI,CAAA,EAAE,CAAA;AAAA,IACxF,SAAA,EAAW,CAAC,KAAA,EAAO,KAAA,EAAO,OAAA,KAAY;AAEpC,MAAA,0BAAA,CAA2B,IAAI,KAAK,CAAA;AACpC,MAAA,MAAM,cAAc,OAAA,EAAS,WAAA;AAC7B,MAAA,IAAI,CAAC,WAAA,EAAa;AAClB,MAAA,kBAAA;AAAA,QAAmB,EAAA;AAAA,QAAI,WAAA;AAAA,QAAa,CAAC,QACnC,GAAA,CACG,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,WAAA,KAAgB,KAAK,CAAA,CACrC,GAAA,CAAI,CAAC,CAAA,KAAO,CAAA,CAAE,kBAAkB,KAAA,GAAQ,EAAE,GAAG,CAAA,EAAG,aAAA,EAAe,IAAA,EAAK,GAAI,CAAE;AAAA,OAC/E;AACA,MAAA,OAAO,QAAQ,GAAA,CAAI;AAAA,QACjB,mBAAA,CAAoB,IAAI,WAAW,CAAA;AAAA,QACnC,EAAA,CAAG,kBAAkB,EAAE,QAAA,EAAU,cAAc,KAAA,CAAM,WAAW,GAAG;AAAA,OACpE,CAAA;AAAA,IACH;AAAA,GACD,CAAA;AACH;AAOO,SAAS,kBAAA,GAAqB;AACnC,EAAA,MAAM,OAAO,OAAA,EAAQ;AACrB,EAAA,OAAO,WAAA,CAAY;AAAA,IACjB,WAAA,EAAa,iBAAiB,eAAA,EAAgB;AAAA,IAC9C,YAAY,CAAC,MAAA,KAAqB,IAAA,CAAK,IAAA,CAAK,gBAAgB,MAAM,CAAA;AAAA,IAClE,SAAA,EAAW,CAAC,IAAA,KAAS,qBAAA,CAAsB,KAAK,WAAW;AAAA,GAC5D,CAAA;AACH;AAMO,SAAS,gBAAA,CACd,MACA,OAAA,EACA;AACA,EAAA,MAAM,OAAO,OAAA,EAAQ;AACrB,EAAA,MAAM,WAAA,GAAc,eAAA,CAAgB,IAAI,CAAA,IAAK,EAAA;AAC7C,EAAA,OAAO,QAAA,CAAS;AAAA,IACd,QAAA,EAAU,aAAA,CAAc,OAAA,CAAQ,WAAA,EAAa,QAAQ,EAAE,CAAA;AAAA,IACvD,OAAA,EAAS,MACP,IAAA,CAAK,eAAA,CAAgB,WAAA,EAAa,MAAM,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,IAAe,CAAC,CAAA;AAAA,IAC5E,OAAA,EAAA,CAAU,SAAS,OAAA,IAAW,IAAA,KAAS,CAAC,CAAC,IAAA,IAAQ,CAAC,CAAC;AAAA,GACpD,CAAA;AACH;AAMO,SAAS,sBAAA,GAAyB;AACvC,EAAA,MAAM,OAAO,OAAA,EAAQ;AACrB,EAAA,MAAM,KAAK,cAAA,EAAe;AAC1B,EAAA,OAAO,WAAA,CAAY;AAAA,IACjB,WAAA,EAAa,iBAAiB,mBAAA,EAAoB;AAAA,IAClD,YAAY,CAAC;AAAA,MACX,IAAA;AAAA,MACA;AAAA,KACF,KAG8B,IAAA,CAAK,QAAA,CAAS,MAAA,CAAO,MAAM,MAAM,CAAA;AAAA;AAAA;AAAA,IAG/D,UAAU,OAAO,EAAE,WAAA,EAAa,eAAA,CAAgB,IAAI,CAAA,EAAE,CAAA;AAAA,IACtD,SAAA,EAAW,CAAC,MAAA,EAAQ,MAAA,EAAQ,OAAA,KAAY;AACtC,MAAA,MAAM,cAAc,OAAA,EAAS,WAAA;AAC7B,MAAA,IAAI,CAAC,WAAA,EAAa;AAClB,MAAA,EAAA,CAAG,aAAa,aAAA,CAAc,OAAA,CAAQ,aAAa,MAAA,CAAO,IAAI,GAAG,MAAM,CAAA;AACvE,MAAA,OAAO,iBAAA,CAAkB,IAAI,WAAW,CAAA;AAAA,IAC1C;AAAA,GACD,CAAA;AACH;AC9RO,IAAM,yBAAA,GAA4B;AAGlC,IAAM,mBAAA,GAAsB;AAM5B,IAAM,4BAAA,GAA+B;AAC5C,IAAM,kBAAA,GAAqB,4BAAA;AAC3B,IAAM,gBAAA,GAAmB,0BAAA;AAEzB,SAAS,KAAK,IAAA,EAAoB;AAChC,EAAA,IAAI;AACF,IAAA,WAAA,CAAY,KAAK,IAAI,CAAA;AAAA,EACvB,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;AAEA,SAAS,OAAA,CAAQ,MAAc,KAAA,EAAqB;AAClD,EAAA,IAAI;AACF,IAAA,WAAA,CAAY,OAAA,CAAQ,MAAM,KAAK,CAAA;AAAA,EACjC,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;AAEA,IAAM,eAAA,uBAAsB,GAAA,EAA6B;AACzD,IAAM,gBAAA,uBAAuB,GAAA,EAAgB;AAE7C,SAAS,WAAA,GAAoB;AAC3B,EAAA,KAAA,MAAW,QAAA,IAAY,kBAAkB,QAAA,EAAS;AACpD;AAEA,SAAS,iBAAiB,QAAA,EAAkC;AAC1D,EAAA,gBAAA,CAAiB,IAAI,QAAQ,CAAA;AAC7B,EAAA,OAAO,MAAM;AACX,IAAA,gBAAA,CAAiB,OAAO,QAAQ,CAAA;AAAA,EAClC,CAAA;AACF;AAGO,SAAS,kBAAA,GAA8B;AAC5C,EAAA,OAAO,gBAAgB,IAAA,GAAO,CAAA;AAChC;AAGO,SAAS,mBAAA,GAA+B;AAC7C,EAAA,OAAO,oBAAA,CAAqB,gBAAA,EAAkB,kBAAA,EAAoB,MAAM,KAAK,CAAA;AAC/E;AAGO,SAAS,qBAAqB,WAAA,EAA2B;AAC9D,EAAA,MAAM,UAAA,GAAa,eAAA,CAAgB,GAAA,CAAI,WAAW,CAAA;AAClD,EAAA,IAAI,CAAC,UAAA,EAAY;AACjB,EAAA,UAAA,CAAW,KAAA,EAAM;AACjB,EAAA,eAAA,CAAgB,OAAO,WAAW,CAAA;AAClC,EAAA,WAAA,EAAY;AACd;AAMA,eAAsB,aAAA,CACpB,EAAA,EACA,IAAA,EACA,WAAA,EACA,MAAA,EAC8B;AAC9B,EAAA,IAAI,OAAA,GAAU,KAAA;AACd,EAAA,KAAA,MAAW,CAAC,EAAA,EAAIE,WAAU,CAAA,IAAK,eAAA,EAAiB;AAC9C,IAAA,IAAI,OAAO,WAAA,EAAa;AACxB,IAAAA,YAAW,KAAA,EAAM;AACjB,IAAA,eAAA,CAAgB,OAAO,EAAE,CAAA;AACzB,IAAA,OAAA,GAAU,IAAA;AAAA,EACZ;AACA,EAAA,IAAI,SAAS,WAAA,EAAY;AAEzB,EAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,EAAA,MAAA,EAAQ,gBAAA,CAAiB,SAAS,MAAM,UAAA,CAAW,OAAM,EAAG,EAAE,IAAA,EAAM,IAAA,EAAM,CAAA;AAG1E,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,SAAA,CAAU,aAAA,CAAc;AAAA,IACzC,WAAA;AAAA,IACA,QAAA,EAAU,mBAAA;AAAA,IACV,aAAA,EAAe,yBAAA;AAAA,IACf,QAAQ,UAAA,CAAW;AAAA,GACpB,CAAA;AACD,EAAA,IAAA,CAAK,gBAAgB,CAAA;AACrB,EAAA,MAAM,KAAA,GAAQ,MAAM,KAAA,CAAM,IAAA,EAAK;AAC/B,EAAA,MAAM,SAAA,GAAY,KAAA,CAAM,IAAA,GAAO,KAAK,KAAA,CAAM,KAAA;AAC1C,EAAA,OAAA,CAAQ,oBAAoB,gBAAgB,CAAA;AAC5C,EAAA,IAAI,KAAA,CAAM,IAAA,IAAQ,SAAA,CAAU,MAAA,GAAS,2BAA2B,OAAO,SAAA;AACvE,EAAA,IAAI,eAAA,CAAgB,GAAA,CAAI,WAAW,CAAA,EAAG;AACpC,IAAA,UAAA,CAAW,KAAA,EAAM;AACjB,IAAA,OAAO,SAAA;AAAA,EACT;AAEA,EAAA,eAAA,CAAgB,GAAA,CAAI,aAAa,UAAU,CAAA;AAC3C,EAAA,WAAA,EAAY;AACZ,EAAA,KAAK,oBAAA,CAAqB,IAAI,WAAA,EAAa,KAAA,EAAO,WAAW,MAAM,CAAA,CAAE,QAAQ,MAAM;AACjF,IAAA,IAAI,eAAA,CAAgB,GAAA,CAAI,WAAW,CAAA,KAAM,UAAA,EAAY;AACrD,IAAA,eAAA,CAAgB,OAAO,WAAW,CAAA;AAClC,IAAA,WAAA,EAAY;AAAA,EACd,CAAC,CAAA;AACD,EAAA,OAAO,SAAA;AACT;AAEA,eAAe,oBAAA,CACb,EAAA,EACA,WAAA,EACA,KAAA,EACA,MAAA,EACe;AAEf,EAAA,MAAM,QAAQ,OAAA,EAAQ;AACtB,EAAA,IAAI;AACF,IAAA,WAAA,MAAiB,QAAQ,KAAA,EAAO;AAC9B,MAAA,IAAI,OAAO,OAAA,EAAS;AAEpB,MAAA,cAAA;AAAA,QACE,EAAA;AAAA,QACA,CAAC,GAAA,KAAQ;AACP,UAAA,MAAM,KAAA,GAAQ,IAAI,GAAA,CAAI,GAAA,CAAI,IAAI,CAAC,GAAA,KAAQ,GAAA,CAAI,WAAW,CAAC,CAAA;AACvD,UAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,MAAA,CAAO,CAAC,GAAA,KAAQ,CAAC,KAAA,CAAM,GAAA,CAAI,GAAA,CAAI,WAAW,CAAC,CAAA;AAC9D,UAAA,OAAO,MAAM,MAAA,GAAS,CAAC,GAAG,GAAA,EAAK,GAAG,KAAK,CAAA,GAAI,GAAA;AAAA,QAC7C,CAAA;AAAA,QACA;AAAA,OACF;AAAA,IACF;AAAA,EACF,SAAS,KAAA,EAAO;AACd,IAAA,IAAI,CAAC,OAAO,OAAA,EAAS,OAAA,CAAQ,MAAM,CAAA,yBAAA,EAA4B,WAAW,YAAY,KAAK,CAAA;AAAA,EAC7F;AACF;;;ACpIO,IAAM,0BAAA,uBAAsD,GAAA,CAAI;AAAA,EACrE,WAAA;AAAA,EACA,aAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA;AACF,CAAC;AAeM,IAAM,2BAAA,uBAAuD,GAAA,CAAI;AAAA,EACtE,WAAA;AAAA,EACA,QAAA;AAAA,EACA,SAAA;AAAA,EACA,YAAA;AAAA,EACA,UAAA;AAAA,EACA;AACF,CAAC;AAED,SAAS,QAAQ,KAAA,EAAmD;AAClE,EAAA,OAAO,OAAO,KAAA,KAAU,QAAA;AAC1B;AAGO,SAAS,iBAAA,CAAkB,MAAiC,IAAA,EAA8B;AAC/F,EAAA,OAAO,CAAC,CAAC,IAAA,IAAQ,OAAA,CAAQ,IAAA,CAAK,GAAG,CAAA,IAAK,OAAA,CAAQ,IAAA,CAAK,GAAG,CAAA,IAAK,IAAA,CAAK,OAAO,IAAA,CAAK,GAAA;AAC9E;AAMO,SAAS,UAAA,CAAW,KAAmB,IAAA,EAA0C;AACtF,EAAA,IAAI,CAAC,OAAA,CAAQ,GAAA,CAAI,UAAU,CAAA,IAAK,CAAC,OAAA,CAAQ,IAAA,CAAK,GAAG,CAAA,EAAG,OAAO,MAAA;AAC3D,EAAA,OAAO,GAAA,CAAI,aAAa,IAAA,CAAK,GAAA;AAC/B;AAGO,SAAS,qBAAA,CAAsB,KAAmB,IAAA,EAAyC;AAChG,EAAA,MAAM,SAAA,GAAA,CAAa,GAAA,CAAI,MAAA,IAAU,EAAA,EAAI,WAAA,EAAY;AACjD,EAAA,MAAM,OAAO,IAAA,EAAM,MAAA;AACnB,EAAA,IAAI,CAAC,IAAA,IAAQ,CAAC,IAAA,EAAM,OAAO,SAAA;AAC3B,EAAA,MAAM,QAAA,GAAW,UAAA,CAAW,GAAA,EAAK,IAAI,CAAA;AACrC,EAAA,IAAI,QAAA,KAAa,MAAA,EAAW,OAAO,QAAA,GAAW,aAAa,IAAA,GAAO,IAAA;AAClE,EAAA,IAAI,2BAAA,CAA4B,GAAA,CAAI,IAAI,CAAA,EAAG,OAAO,IAAA;AAClD,EAAA,IAAI,0BAAA,CAA2B,GAAA,CAAI,SAAS,CAAA,EAAG,OAAO,SAAA;AACtD,EAAA,OAAO,IAAA;AACT;AAQO,SAAS,aAAA,CACd,OACA,IAAA,EACK;AACL,EAAA,MAAM,QAAA,uBAAe,GAAA,EAAe;AACpC,EAAA,KAAA,MAAW,IAAA,IAAQ,MAAA,CAAO,MAAA,CAAO,KAAK,CAAA;AACpC,IAAA,IAAI,2BAAA,CAA4B,IAAI,IAAA,CAAK,MAAM,GAAG,QAAA,CAAS,GAAA,CAAI,IAAA,CAAK,UAAA,EAAY,IAAI,CAAA;AACtF,EAAA,IAAI,CAAC,QAAA,CAAS,IAAA,EAAM,OAAO,EAAC;AAC5B,EAAA,MAAM,UAAe,EAAC;AACtB,EAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,IAAA,MAAM,IAAA,GAAO,QAAA,CAAS,GAAA,CAAI,GAAA,CAAI,WAAW,CAAA;AACzC,IAAA,IAAI,CAAC,IAAA,EAAM;AACX,IAAA,MAAM,SAAA,GAAA,CAAa,GAAA,CAAI,MAAA,IAAU,EAAA,EAAI,WAAA,EAAY;AACjD,IAAA,IAAI,CAAC,2BAA2B,GAAA,CAAI,SAAS,KAAK,UAAA,CAAW,GAAA,EAAK,IAAI,CAAA,KAAM,KAAA,EAAO;AACnF,IAAA,OAAA,CAAQ,IAAA,CAAK,EAAE,GAAG,IAAA,EAAM,MAAA,EAAQ,SAAA,EAAW,GAAA,EAAK,GAAA,CAAI,UAAA,IAAc,IAAA,CAAK,GAAA,EAAK,CAAA;AAAA,EAC9E;AACA,EAAA,OAAO,OAAA;AACT;ACpEO,IAAM,qBAAA,GAAwB,KAAK,EAAA,GAAK;AAqC/C,IAAM,QAAA,GAAW,CAAC,MAAA,KAAmB,0BAAA,CAA2B,IAAI,MAAM,CAAA;AAEnE,IAAM,cAAA,GAAiBC,MAAAA,CAAoB,CAAC,GAAA,EAAK,GAAA,MAAS;AAAA,EAC/D,MAAA,EAAQ,cAAA;AAAA,EACR,OAAO,EAAC;AAAA,EACR,WAAW,EAAC;AAAA,EACZ,cAAA,EAAgB,IAAA;AAAA,EAChB,UAAU,EAAC;AAAA,EACX,OAAA,EAAS,KAAA;AAAA,EACT,WAAW,CAAC,MAAA,KAAW,GAAA,CAAI,EAAE,QAAQ,CAAA;AAAA,EACrC,YAAY,CAAC,OAAA,KAAY,GAAA,CAAI,EAAE,SAAS,CAAA;AAAA,EACxC,eAAA,EAAiB,CAAC,GAAA,KAAQ;AACxB,IAAA,MAAM,EAAE,KAAA,EAAO,SAAA,EAAU,GAAI,GAAA,EAAI;AACjC,IAAA,MAAM,WAAA,GAAc,SAAA,CAAU,GAAA,CAAI,UAAU,CAAA;AAC5C,IAAA,IAAI,gBAAgB,MAAA,IAAa,IAAA,CAAK,KAAI,GAAI,WAAA,GAAc,uBAAuB,OAAO,KAAA;AAC1F,IAAA,MAAM,IAAA,GAAO,KAAA,CAAM,GAAA,CAAI,UAAU,CAAA;AACjC,IAAA,IAAI,iBAAA,CAAkB,IAAA,EAAM,GAAG,CAAA,EAAG,OAAO,KAAA;AACzC,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,IAAA,MAAM,IAAA,GAAiB;AAAA,MACrB,GAAG,GAAA;AAAA,MACH,SAAA,EAAW,MAAM,SAAA,IAAa,GAAA;AAAA,MAC9B,SAAS,QAAA,CAAS,GAAA,CAAI,MAAM,CAAA,GAAK,IAAA,EAAM,WAAW,GAAA,GAAO;AAAA,KAC3D;AACA,IAAA,GAAA,CAAI,EAAE,KAAA,EAAO,EAAE,GAAG,KAAA,EAAO,CAAC,GAAA,CAAI,UAAU,GAAG,IAAA,EAAK,EAAG,cAAA,EAAgB,KAAK,CAAA;AACxE,IAAA,OAAO,IAAA;AAAA,EACT,CAAA;AAAA,EACA,SAAS,CAAC,IAAA,KAAS,IAAI,CAAC,CAAA,MAAO,EAAE,KAAA,EAAO,EAAE,GAAG,CAAA,CAAE,OAAO,CAAC,IAAA,CAAK,UAAU,GAAG,IAAA,IAAO,CAAE,CAAA;AAAA,EAClF,SAAA,EAAW,CAAC,KAAA,KACV,GAAA,CAAI,CAAC,CAAA,KAAM;AACT,IAAA,MAAM,KAAA,GAAQ,EAAE,GAAG,CAAA,CAAE,KAAA,EAAM;AAC3B,IAAA,OAAO,MAAM,KAAK,CAAA;AAClB,IAAA,OAAO,EAAE,KAAA,EAAO,SAAA,EAAW,EAAE,GAAG,CAAA,CAAE,SAAA,EAAW,CAAC,KAAK,GAAG,IAAA,CAAK,GAAA,IAAM,EAAE;AAAA,EACrE,CAAC,CAAA;AAAA,EACH,kBAAA,EAAoB,MAClB,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,IACV,OAAO,MAAA,CAAO,WAAA,CAAY,OAAO,OAAA,CAAQ,CAAA,CAAE,KAAK,CAAA,CAAE,MAAA,CAAO,CAAC,GAAG,CAAC,CAAA,KAAM,CAAC,SAAS,CAAA,CAAE,MAAM,CAAC,CAAC;AAAA,GAC1F,CAAE,CAAA;AAAA,EACJ,WAAA,EAAa,CAAC,IAAA,KACZ,GAAA,CAAI,CAAC,CAAA,KAAM;AACT,IAAA,MAAM,OAAA,GAAU,aAAA,CAAc,CAAA,CAAE,KAAA,EAAO,IAAI,CAAA;AAC3C,IAAA,IAAI,CAAC,OAAA,CAAQ,MAAA,EAAQ,OAAO,CAAA;AAC5B,IAAA,MAAM,KAAA,GAAQ,EAAE,GAAG,CAAA,CAAE,KAAA,EAAM;AAC3B,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AACrB,IAAA,KAAA,MAAW,IAAA,IAAQ,OAAA;AACjB,MAAA,KAAA,CAAM,IAAA,CAAK,UAAU,CAAA,GAAI,EAAE,GAAI,IAAA,EAAmB,OAAA,EAAS,IAAA,CAAK,OAAA,IAAW,GAAA,EAAI;AACjF,IAAA,OAAO,EAAE,KAAA,EAAM;AAAA,EACjB,CAAC,CAAA;AAAA,EACH,eAAe,CAAC,GAAA,KAAQ,IAAI,CAAC,CAAA,MAAO,EAAE,QAAA,EAAU,EAAE,GAAG,CAAA,CAAE,QAAA,EAAU,CAAC,GAAA,CAAI,OAAO,GAAG,GAAA,CAAI,MAAA,IAAS,CAAE,CAAA;AAAA,EAC/F,OAAO,MACL,GAAA,CAAI,EAAE,MAAA,EAAQ,gBAAgB,KAAA,EAAO,EAAC,EAAG,SAAA,EAAW,EAAC,EAAG,cAAA,EAAgB,MAAM,QAAA,EAAU,IAAI;AAChG,CAAA,CAAE;AC9FF,SAASC,iBAAgB,IAAA,EAA2B;AAClD,EAAA,OAAO,IAAA,CAAK,YAAA,GAAe,IAAA,CAAK,cAAA,EAAe,GAAI,IAAA;AACrD;AASO,SAAS,YAAA,CAAa,aAA6B,OAAA,EAAiC;AACzF,EAAA,MAAM,OAAO,OAAA,EAAQ;AACrB,EAAA,MAAM,KAAKC,cAAAA,EAAe;AAC1B,EAAA,MAAM,SAAA,GAAY,WAAA,IAAeD,gBAAAA,CAAgB,IAAI,CAAA,IAAK,EAAA;AAC1D,EAAA,OAAOE,QAAAA,CAAS;AAAA,IACd,QAAA,EAAU,aAAA,CAAc,SAAA,CAAU,SAAS,CAAA;AAAA,IAC3C,OAAA,EAAS,CAAC,EAAE,MAAA,EAAO,KAAM;AACvB,MAAA,IAAIF,gBAAAA,CAAgB,IAAI,CAAA,KAAM,SAAA;AAC5B,QAAA,OAAO,OAAA,CAAQ,MAAA,CAAO,IAAI,KAAA,CAAM,iCAAiC,CAAC,CAAA;AACpE,MAAA,OAAO,aAAA,CAAc,EAAA,EAAI,IAAA,EAAM,SAAA,EAAW,MAAM,CAAA;AAAA,IAClD,CAAA;AAAA,IACA,UAAU,OAAA,EAAS,OAAA,IAAW,SAAS,CAAC,CAAC,aAAa,IAAA,CAAK,YAAA;AAAA,IAC3D,SAAA,EAAW,QAAA;AAAA,IACX,cAAA,EAAgB,KAAA;AAAA,IAChB,kBAAA,EAAoB,KAAA;AAAA,IACpB,oBAAA,EAAsB;AAAA,GACvB,CAAA;AACH;AAGO,IAAM,uBAAA,GAA0B,GAAA;AAGvC,SAAS,mBAAmB,GAAA,EAA2D;AACrF,EAAA,OAAO,GAAA,EAAK,UAAU,CAAC,0BAAA,CAA2B,IAAI,GAAA,CAAI,MAAM,IAC5D,uBAAA,GACA,KAAA;AACN;AAMO,SAAS,WAAA,CACd,OACA,OAAA,EACA;AACA,EAAA,MAAM,OAAO,OAAA,EAAQ;AACrB,EAAA,OAAOE,QAAAA,CAAS;AAAA,IACd,QAAA,EAAU,aAAA,CAAc,QAAA,CAAS,KAAA,IAAS,EAAE,CAAA;AAAA,IAC5C,OAAA,EAAS,YAAA,CACN,MAAM,IAAA,CAAK,SAAA,CAAU,GAAA,CAAI,CAAC,KAAe,CAAC,CAAA,EAAG,CAAC,CAAA,IAAK,IAAA;AAAA,IACtD,UAAU,OAAA,EAAS,OAAA,IAAW,SAAS,CAAC,CAAC,SAAS,IAAA,CAAK,UAAA;AAAA,IACvD,eAAA,EAAiB,SAAS,mBAAA,GACtB,CAAC,UAAU,kBAAA,CAAmB,KAAA,CAAM,KAAA,CAAM,IAAI,CAAA,GAC9C;AAAA,GACL,CAAA;AACH;AAMO,IAAM,oBAAA,GAAuB;AAG7B,SAAS,oBAAoB,OAAA,EAAiC;AACnE,EAAA,MAAM,OAAO,OAAA,EAAQ;AACrB,EAAA,MAAM,SAAA,GAAYF,gBAAAA,CAAgB,IAAI,CAAA,IAAK,EAAA;AAC3C,EAAA,OAAOE,QAAAA,CAAS;AAAA,IACd,QAAA,EAAU,aAAA,CAAc,gBAAA,CAAiB,SAAA,EAAW,oBAAoB,CAAA;AAAA,IACxE,OAAA,EAAS,MACP,IAAA,CAAK,eAAA;AAAA,MAAgB,SAAA;AAAA,MAAW,MAC9B,IAAA,CAAK,SAAA,CAAU,QAAQ,EAAE,SAAA,EAAW,sBAAsB;AAAA,KAC5D;AAAA,IACF,OAAA,EAAA,CAAU,OAAA,EAAS,OAAA,IAAW,IAAA,KAAS,CAAC,CAAC;AAAA,GAC1C,CAAA;AACH;AAIA,IAAI,OAAA,GAAU,CAAA;AACd,IAAM,eAAA,uBAAsB,GAAA,EAAoB;AAQhD,eAAsB,gBAAA,CACpB,EAAA,EACA,IAAA,EACA,MAAA,EAC8B;AAC9B,EAAA,IAAI,CAAC,MAAA,CAAO,MAAA,EAAQ,OAAO,EAAC;AAC5B,EAAA,MAAM,MAAM,EAAE,OAAA;AACd,EAAA,KAAA,MAAW,EAAA,IAAM,MAAA,EAAQ,eAAA,CAAgB,GAAA,CAAI,IAAI,GAAG,CAAA;AACpD,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,SAAA,CAAU,IAAI,MAAM,CAAA;AAC5C,IAAA,MAAM,KAAA,GAAQ,IAAA,CACX,MAAA,CAAO,CAAC,QAAQ,eAAA,CAAgB,GAAA,CAAI,GAAA,CAAI,WAAW,CAAA,KAAM,GAAG,CAAA,CAC5D,GAAA,CAAI,CAAC,GAAA,KAAQ;AAGZ,MAAA,MAAM,OAAO,cAAA,CAAe,QAAA,EAAS,CAAE,KAAA,CAAM,IAAI,WAAW,CAAA;AAC5D,MAAA,OAAO,IAAA,IACL,2BAA2B,GAAA,CAAI,IAAA,CAAK,MAAM,CAAA,IAC1C,GAAA,CAAI,WAAW,IAAA,CAAK,MAAA,IACpB,WAAW,GAAA,EAAK,IAAI,MAAM,IAAA,GACxB,EAAE,GAAG,GAAA,EAAK,MAAA,EAAQ,IAAA,CAAK,MAAA,EAAO,GAC9B,GAAA;AAAA,IACN,CAAC,CAAA;AACH,IAAA,IAAI,CAAC,KAAA,CAAM,MAAA,EAAQ,OAAO,EAAC;AAC3B,IAAA,kBAAA,CAAmB,IAAI,KAAK,CAAA;AAC5B,IAAA,eAAA,CAAgB,IAAI,KAAK,CAAA;AACzB,IAAA,KAAA,MAAW,GAAA,IAAO,KAAA,EAAO,iBAAA,CAAkB,EAAA,EAAI,GAAG,CAAA;AAClD,IAAA,OAAO,KAAA;AAAA,EACT,SAAS,KAAA,EAAO;AAEd,IAAA,OAAA,CAAQ,KAAA,CAAM,0DAA0D,KAAK,CAAA;AAC7E,IAAA,OAAO,EAAC;AAAA,EACV,CAAA,SAAE;AACA,IAAA,KAAA,MAAW,EAAA,IAAM,MAAA,EAAQ,IAAI,eAAA,CAAgB,GAAA,CAAI,EAAE,CAAA,KAAM,GAAA,EAAK,eAAA,CAAgB,MAAA,CAAO,EAAE,CAAA;AAAA,EACzF;AACF;AAGO,SAAS,mBAAA,GAA0E;AACxF,EAAA,MAAM,KAAKD,cAAAA,EAAe;AAC1B,EAAA,MAAM,OAAO,OAAA,EAAQ;AACrB,EAAA,OAAOL,WAAAA,CAAY,CAAC,MAAA,KAAqB,gBAAA,CAAiB,EAAA,EAAI,IAAA,EAAM,MAAM,CAAA,EAAG,CAAC,EAAA,EAAI,IAAI,CAAC,CAAA;AACzF;AAGA,SAAS,kBAAA,CAAmB,IAAiB,KAAA,EAAkC;AAC7E,EAAA,MAAM,WAAA,uBAAkB,GAAA,EAAiC;AACzD,EAAA,KAAA,MAAW,OAAO,KAAA,EAAO;AACvB,IAAA,MAAM,MAAA,GAAS,kBAAA,CAAmB,EAAA,EAAI,GAAA,CAAI,gBAAgB,CAAA,EAAG,IAAA;AAAA,MAC3D,CAAC,CAAA,KAAM,CAAA,CAAE,WAAA,KAAgB,GAAA,CAAI;AAAA,KAC/B;AACA,IAAA,MAAM,MAAA,GAAS,IAAI,GAAA,CAAA,CAAK,MAAA,EAAQ,OAAA,IAAW,EAAC,EAAG,GAAA,CAAI,CAAC,EAAA,KAAO,EAAA,CAAG,UAAU,CAAC,CAAA;AACzE,IAAA,MAAM,KAAA,GAAQ,IAAI,GAAA,CAAA,CAAK,GAAA,CAAI,OAAA,IAAW,EAAC,EAAG,GAAA,CAAI,CAAC,EAAA,KAAO,EAAA,CAAG,UAAU,CAAC,CAAA;AACpE,IAAA,MAAM,QAAQ,WAAA,CAAY,GAAA,CAAI,IAAI,gBAAgB,CAAA,wBAAS,GAAA,EAAoB;AAC/E,IAAA,KAAA,MAAW,MAAM,KAAA,EAAO,IAAI,CAAC,MAAA,CAAO,IAAI,EAAE,CAAA,EAAG,KAAA,CAAM,GAAA,CAAI,KAAK,KAAA,CAAM,GAAA,CAAI,EAAE,CAAA,IAAK,KAAK,CAAC,CAAA;AACnF,IAAA,KAAA,MAAW,MAAM,MAAA,EAAQ,IAAI,CAAC,KAAA,CAAM,IAAI,EAAE,CAAA,EAAG,KAAA,CAAM,GAAA,CAAI,KAAK,KAAA,CAAM,GAAA,CAAI,EAAE,CAAA,IAAK,KAAK,CAAC,CAAA;AACnF,IAAA,WAAA,CAAY,GAAA,CAAI,GAAA,CAAI,gBAAA,EAAkB,KAAK,CAAA;AAAA,EAC7C;AACA,EAAA,KAAA,MAAW,CAAC,aAAa,KAAK,CAAA,IAAK,aAAa,eAAA,CAAgB,EAAA,EAAI,aAAa,KAAK,CAAA;AACxF;AAGO,SAAS,eAAA,CACd,EAAA,EACA,WAAA,EACA,KAAA,EACM;AACN,EAAA,IAAI,CAAC,CAAC,GAAG,KAAA,CAAM,QAAQ,CAAA,CAAE,IAAA,CAAK,OAAO,CAAA,EAAG;AACxC,EAAA,kBAAA;AAAA,IAAmB,EAAA;AAAA,IAAI,WAAA;AAAA,IAAa,CAAC,IAAA,KACnC,IAAA,CAAK,GAAA,CAAI,CAAC,GAAA,KAAQ;AAChB,MAAA,MAAM,MAAA,GAAS,KAAA,CAAM,GAAA,CAAI,GAAA,CAAI,WAAW,CAAA;AACxC,MAAA,OAAO,MAAA,GAAS,EAAE,GAAG,GAAA,EAAK,YAAA,EAAc,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,GAAA,CAAI,YAAA,GAAe,MAAM,CAAA,EAAE,GAAI,GAAA;AAAA,IACrF,CAAC;AAAA,GACH;AACA,EAAA,KAAK,mBAAA,CAAoB,IAAI,WAAW,CAAA;AAC1C","file":"chunk-P6WLV5UY.js","sourcesContent":["/**\n * The workspace documents list in the query cache: one entry per workspace\n * (`arbiQueryKeys.documents(workspaceId)`), read once (progressively, see `documents-loader.ts`)\n * and then kept current in place. Every write goes through {@link patchDocuments}, which also\n * tells row listeners (a grid that applies row transactions instead of re-diffing the whole list)\n * exactly which rows were added, changed or removed.\n *\n * A single document's own entry (`arbiQueryKeys.document(id)`, read by a viewer) is patched next to\n * the list by {@link setCachedDocument}, so a viewer never blanks while a write settles.\n */\n\nimport type { QueryClient } from '@tanstack/react-query'\nimport type { components } from '@arbidocs/client'\nimport { arbiQueryKeys } from '../hooks'\n\n/** A document as the server lists it. */\nexport type WorkspaceDocument = components['schemas']['DocResponse']\n\n/** The rows one write added, changed and removed (removed: by id). */\nexport interface DocumentRowChange {\n workspaceId: string\n add: WorkspaceDocument[]\n update: WorkspaceDocument[]\n remove: string[]\n}\n\ntype RowListener = (change: DocumentRowChange) => void\n\nconst rowListeners = new Set<RowListener>()\n\n/**\n * Follow the row-level changes of every write to a workspace documents list (a grid applying them\n * as transactions). Returns the unsubscribe.\n */\nexport function subscribeDocumentRows(listener: RowListener): () => void {\n rowListeners.add(listener)\n return () => {\n rowListeners.delete(listener)\n }\n}\n\n/** The cached documents of a workspace (`undefined` before its list has been read). */\nexport function getCachedDocuments(\n qc: QueryClient,\n workspaceId: string | null | undefined\n): WorkspaceDocument[] | undefined {\n if (!workspaceId) return undefined\n return qc.getQueryData<WorkspaceDocument[]>(arbiQueryKeys.documents(workspaceId))\n}\n\n/** Every cached workspace documents list, with its workspace. */\nfunction cachedLists(qc: QueryClient): Array<[string, WorkspaceDocument[]]> {\n return qc\n .getQueriesData<WorkspaceDocument[]>({ queryKey: arbiQueryKeys.allDocuments() })\n .flatMap(([key, data]) =>\n typeof key[2] === 'string' && Array.isArray(data) ? [[key[2], data]] : []\n )\n}\n\n/** Diff two versions of a list by id. */\nfunction diffRows(\n workspaceId: string,\n before: WorkspaceDocument[],\n after: WorkspaceDocument[]\n): DocumentRowChange {\n const beforeById = new Map(before.map((doc) => [doc.external_id, doc]))\n const add: WorkspaceDocument[] = []\n const update: WorkspaceDocument[] = []\n const seen = new Set<string>()\n for (const doc of after) {\n seen.add(doc.external_id)\n const previous = beforeById.get(doc.external_id)\n if (!previous) add.push(doc)\n else if (previous !== doc) update.push(doc)\n }\n const remove = [...beforeById.keys()].filter((id) => !seen.has(id))\n return { workspaceId, add, update, remove }\n}\n\n/**\n * Apply `reducer` to a workspace's documents list, or (no `workspaceId`) to every cached one: the\n * one place a list is written after it was read. Returning the same array is a no-op. Row\n * listeners get the diff; a document that moved to a new version makes the open version lists\n * re-read. A workspace whose list has not been read is left alone (its first read brings it).\n */\nexport function patchDocuments(\n qc: QueryClient,\n reducer: (documents: WorkspaceDocument[]) => WorkspaceDocument[],\n workspaceId?: string | null\n): void {\n const lists: Array<[string, WorkspaceDocument[]]> = workspaceId\n ? (() => {\n const current = getCachedDocuments(qc, workspaceId)\n return current ? [[workspaceId, current] as [string, WorkspaceDocument[]]] : []\n })()\n : cachedLists(qc)\n for (const [id, before] of lists) {\n const after = reducer(before)\n if (after === before) continue\n qc.setQueryData(arbiQueryKeys.documents(id), after)\n const change = diffRows(id, before, after)\n const beforeById = new Map(before.map((doc) => [doc.external_id, doc]))\n if (\n change.update.some(\n (doc) => doc.current_version !== beforeById.get(doc.external_id)?.current_version\n )\n )\n void qc.invalidateQueries({ queryKey: arbiQueryKeys.allDocumentVersions() })\n if (change.add.length || change.update.length || change.remove.length)\n for (const listener of rowListeners) listener(change)\n }\n}\n\n/** Put `doc` in its list in place, or at the end when the list does not hold it yet. */\nexport function upsertDocuments(\n qc: QueryClient,\n documents: WorkspaceDocument[],\n workspaceId?: string | null\n): void {\n if (!documents.length) return\n const byId = new Map(documents.map((doc) => [doc.external_id, doc]))\n const byWorkspace = new Map<string, WorkspaceDocument[]>()\n for (const doc of documents) {\n const ws = workspaceId ?? doc.workspace_ext_id\n byWorkspace.set(ws, [...(byWorkspace.get(ws) ?? []), doc])\n }\n for (const [ws, incoming] of byWorkspace) {\n patchDocuments(\n qc,\n (old) => {\n const known = new Set(old.map((doc) => doc.external_id))\n return [\n ...old.map((doc) => byId.get(doc.external_id) ?? doc),\n ...incoming.filter((doc) => !known.has(doc.external_id)),\n ]\n },\n ws\n )\n }\n}\n\n/** Write a document's own entry (what `useDocument` reads), keeping a viewer current. */\nexport function setCachedDocument(qc: QueryClient, doc: WorkspaceDocument): void {\n qc.setQueryData(arbiQueryKeys.document(doc.external_id), doc)\n}\n\n/** Apply `reducer` to a document's own entry, when one is cached. */\nexport function patchCachedDocument(\n qc: QueryClient,\n docId: string,\n reducer: (doc: WorkspaceDocument) => WorkspaceDocument\n): void {\n const current = qc.getQueryData<WorkspaceDocument | null>(arbiQueryKeys.document(docId))\n if (current) qc.setQueryData(arbiQueryKeys.document(docId), reducer(current))\n}\n\n/** A deleted tag leaves every cached document that carried it: the lists' rows and their entries. */\nexport function dropTagFromCachedDocuments(qc: QueryClient, tagId: string): void {\n const strip = (doc: WorkspaceDocument): WorkspaceDocument => {\n const doctags = doc.doctags?.filter((dt) => dt.tag_ext_id !== tagId)\n return doctags && doctags.length !== doc.doctags?.length ? { ...doc, doctags } : doc\n }\n const carriers: string[] = []\n patchDocuments(qc, (docs) => {\n const next = docs.map(strip)\n next.forEach((doc, i) => doc !== docs[i] && carriers.push(doc.external_id))\n return carriers.length ? next : docs\n })\n for (const id of carriers) patchCachedDocument(qc, id, strip)\n}\n\n/** Forget everything cached about deleted documents, so nothing re-reads them into a 404. */\nexport function forgetDocuments(qc: QueryClient, docIds: string[]): void {\n for (const id of docIds) {\n qc.removeQueries({ queryKey: arbiQueryKeys.document(id) })\n qc.removeQueries({ queryKey: arbiQueryKeys.documentVersions(id) })\n qc.removeQueries({ queryKey: arbiQueryKeys.parsedDocument(id) })\n }\n}\n","/**\n * The documents whose people and organisations are being found (`useExtractEntities`), from the\n * request until the live connection says the batch is done (`batch_complete`, `entity_extract`):\n * the package's WebSocket (`ArbiWebSocketProvider`) ends it, and a host on its own connection calls\n * `finishEntityExtraction` from its handler.\n */\n\nimport { create } from 'zustand'\n\nconst useEntityExtractionStore = create<{ docIds: readonly string[] }>(() => ({ docIds: [] }))\n\nfunction update(docIds: readonly string[], running: boolean): void {\n if (!docIds.length) return\n useEntityExtractionStore.setState((state) => {\n const ids = new Set(state.docIds)\n docIds.forEach((id) => (running ? ids.add(id) : ids.delete(id)))\n return { docIds: [...ids] }\n })\n}\n\n/** The documents an extraction was started on are running. */\nexport function startEntityExtraction(docIds: readonly string[]): void {\n update(docIds, true)\n}\n\n/** The extraction of these documents is done. */\nexport function finishEntityExtraction(docIds: readonly string[]): void {\n update(docIds, false)\n}\n\n/** The documents being extracted now. */\nexport function useEntityExtractionDocIds(): readonly string[] {\n return useEntityExtractionStore((state) => state.docIds)\n}\n","/**\n * The workspace of a write that may be queued (offline, then replayed on reconnect or after a\n * reload). The workspace is captured when the write is made and kept with it, and the write is\n * sent in that workspace: it is opened for this session first (its key deposited, without\n * switching to it), and the request names it or acts on resources the server keys by their own\n * workspace. So a replay never lands in whatever workspace happens to be open by then.\n *\n * When the workspace cannot be opened (signed out, access removed), nothing is sent: the write\n * fails with `ArbiWorkspaceUnavailableError`, is retried a few times (a reload replays before the\n * sign-in has finished), and then stays in the pending changes as not sent, with its local edit\n * kept, rather than going anywhere else.\n */\n\nimport { useCallback, useRef } from 'react'\nimport { isAbortError, type ArbiClient } from '@arbidocs/client'\nimport { ArbiWorkspaceUnavailableError } from '@arbidocs/sdk/browser'\n\n/** A queued write's own workspace (`wrk-…`), captured when it was made. */\nexport interface QueuedWriteWorkspace {\n /** The workspace the write belongs to. Filled in when it is made; absent on older queued writes. */\n workspaceId?: string\n}\n\n/** What a write that could not be sent in its workspace says. */\nexport const QUEUED_WRITE_BLOCKED_MESSAGE =\n \"This change belongs to a workspace that can't be opened right now, so it was not sent. It is kept here until it can be.\"\n\n/** Opens a workspace for this server session without switching to it (nothing for the current one). */\nexport type WorkspacePrimer = (workspaceId: string) => Promise<void> | void\n\n/** {@link WorkspacePrimer} on a bare client (a replay after a reload): its key, via `/prime-key`. */\nexport function primeOnClient(client: ArbiClient): WorkspacePrimer {\n return (workspaceId) =>\n workspaceId === client.session.getState().selectedWorkspaceId\n ? undefined\n : client.workspaceKeys.prime(workspaceId)\n}\n\n/** {@link WorkspacePrimer} on an `Arbi` (`workspaces.open`, which never switches). */\nexport function primeOnArbi(arbi: {\n hasWorkspace: boolean\n getWorkspaceId(): string\n workspaces: { open(workspaceId: string): Promise<void> }\n}): WorkspacePrimer {\n return (workspaceId) =>\n arbi.hasWorkspace && workspaceId === arbi.getWorkspaceId()\n ? undefined\n : arbi.workspaces.open(workspaceId)\n}\n\n/**\n * Run `write` in `workspaceId`: that workspace is opened for this server session first (`prime`).\n * When it can't be, nothing is sent. No workspace (a write queued before workspaces were\n * recorded): as before.\n */\nexport async function inWorkspace<T>(\n prime: WorkspacePrimer,\n workspaceId: string | null | undefined,\n write: () => Promise<T>\n): Promise<T> {\n if (workspaceId) {\n try {\n await prime(workspaceId)\n } catch (error) {\n if (isAbortError(error)) throw error\n throw new ArbiWorkspaceUnavailableError(workspaceId, error, QUEUED_WRITE_BLOCKED_MESSAGE)\n }\n }\n return write()\n}\n\n/** Whether a write failed only because its workspace could not be opened (nothing was sent). */\nexport function isWorkspaceUnavailable(error: unknown): boolean {\n return error instanceof ArbiWorkspaceUnavailableError\n}\n\n/** How many times a write whose workspace cannot be opened is tried again, and how long apart. */\nexport const QUEUED_WRITE_RETRY = {\n retry: (failureCount: number, error: unknown) =>\n isWorkspaceUnavailable(error) && failureCount < 8,\n retryDelay: (attempt: number) => Math.min(1000 * 2 ** attempt, 30_000),\n} as const\n\n/** Whether a queued write is held back because its workspace cannot be opened. */\nexport function isBlockedOnWorkspace(mutation: {\n state: { error?: unknown; failureReason?: unknown }\n}): boolean {\n return isWorkspaceUnavailable(mutation.state.error ?? mutation.state.failureReason)\n}\n\n/**\n * Fill in the workspace of each write a mutation makes, when its caller gave none: `mutate` and\n * `mutateAsync` pass `capture(variables)` on. Read when the write is made, so a write queued\n * offline keeps the workspace it was made in. The wrapped functions are as stable as the mutation's.\n */\nexport function useCapturingWorkspace<\n V,\n T extends { mutate: (variables: V, ...rest: never[]) => unknown; mutateAsync: unknown },\n>(mutation: T, capture: (variables: V) => V): T {\n const captureRef = useRef(capture)\n captureRef.current = capture\n const { mutate: rawMutate, mutateAsync: rawMutateAsync } = mutation\n const mutate = useCallback(\n (variables: V, ...rest: never[]) =>\n (rawMutate as (v: V, ...r: never[]) => unknown)(captureRef.current(variables), ...rest),\n [rawMutate]\n ) as T['mutate']\n const mutateAsync = useCallback(\n (variables: V, ...rest: never[]) =>\n (rawMutateAsync as (v: V, ...r: never[]) => Promise<unknown>)(\n captureRef.current(variables),\n ...rest\n ),\n [rawMutateAsync]\n ) as T['mutateAsync']\n return { ...mutation, mutate, mutateAsync }\n}\n","/**\n * Tags: the open workspace's tag list (`useTags()`), the writes (create, update, delete, values,\n * entity extraction), and tag kinds — a kind's fields in the workspace are the columns of a table\n * of its tags (`useTagKindSchema('issue')`), whose rows are the tag list filtered by kind with\n * links (`useTags(workspaceId, { kind, include })`).\n *\n * Everything is cached under the workspace's tags (`arbiQueryKeys.tags`). The whole list is kept\n * current in place: every write here patches it ({@link patchWorkspaceTags}, which a host also\n * uses for its own writes that move a tag's counts, e.g. applying it to documents) and refreshes\n * the filtered lists (the tables). Anything that invalidates the workspace's tags (a document batch\n * finishing, {@link useInvalidateTagData} after a doctag or fact change) refreshes them all.\n *\n * Creating a tag can be queued while offline and replayed after a reload: see `offline.ts`.\n *\n * Requires an `ArbiHost` (with an `arbi`) and a React Query client above it.\n */\n\nimport { useCallback } from 'react'\nimport { useMutation, useQuery, useQueryClient, type QueryClient } from '@tanstack/react-query'\nimport type { ArbiClient } from '@arbidocs/client'\nimport {\n tags as tagOps,\n type TagChange,\n type TagFieldDefinition,\n type TagKind,\n type TagKindSchema,\n type TagResponse,\n} from '@arbidocs/sdk/browser'\nimport { useArbi } from './useArbi'\nimport { dropTagFromCachedDocuments } from './documents/documents-cache'\nimport { startEntityExtraction } from './entity-extraction'\nimport { arbiMutationKeys, arbiQueryKeys } from './hooks'\nimport {\n QUEUED_WRITE_RETRY,\n inWorkspace,\n primeOnArbi,\n primeOnClient,\n useCapturingWorkspace,\n} from './queued-writes'\n\n/** The workspace open on `arbi`, or `null` (`getWorkspaceId()` throws when none is open). */\n/** The workspace whose cached tag list holds `tagId`, if any. */\nfunction workspaceOfTag(qc: QueryClient, tagId: string): string | null {\n for (const [key, tags] of qc.getQueriesData<TagResponse[]>({\n queryKey: arbiQueryKeys.allTags(),\n })) {\n if (Array.isArray(tags) && tags.some((t) => t.external_id === tagId))\n return (key[2] as string | undefined) ?? null\n }\n return null\n}\n\nfunction openWorkspaceId(arbi: ReturnType<typeof useArbi>): string | null {\n return arbi.hasWorkspace ? arbi.getWorkspaceId() : null\n}\n\n/**\n * Apply `reducer` to a workspace's cached tag list (nothing cached: nothing to do). The list is\n * read once, then kept current by these patches; a host's own write that changes a tag (applying\n * it to documents moves its `doctag_count`) patches it here too.\n */\nexport function patchWorkspaceTags(\n qc: QueryClient,\n workspaceId: string,\n reducer: (tags: TagResponse[]) => TagResponse[]\n): void {\n const key = arbiQueryKeys.tags(workspaceId)\n const current = qc.getQueryData<TagResponse[]>(key)\n if (!current) return\n const next = reducer(current)\n if (next !== current) qc.setQueryData(key, next)\n}\n\n/** Refetch a workspace's tables of tags (its filtered lists), not the whole list. */\nexport function invalidateTagTables(qc: QueryClient, workspaceId: string): Promise<void> {\n return qc.invalidateQueries({ queryKey: arbiQueryKeys.tagLists(workspaceId) })\n}\n\n/** Refresh what a tag, doctag or fact change affects: the workspace's tags, tables and facts. */\nexport function invalidateTagData(qc: QueryClient, workspaceId: string): Promise<unknown> {\n return Promise.all([\n qc.invalidateQueries({ queryKey: arbiQueryKeys.tags(workspaceId) }),\n qc.invalidateQueries({ queryKey: arbiQueryKeys.facts(workspaceId) }),\n ])\n}\n\n/** {@link invalidateTagData} for the open workspace: call it after a doctag or fact write. */\nexport function useInvalidateTagData(): () => Promise<unknown> {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useCallback(() => {\n const workspaceId = openWorkspaceId(arbi)\n return workspaceId ? invalidateTagData(qc, workspaceId) : Promise.resolve()\n }, [arbi, qc])\n}\n\n/**\n * What a new tag is: its name, and optionally kind, format, parent, values, sharing, and the workspace it goes in\n * (absent: the open one).\n */\nexport type CreateTagInput = Parameters<typeof tagOps.createTag>[1]\n\n/** A created tag joins its workspace's list; the tables re-read. */\nfunction settleCreatedTag(qc: QueryClient, created: TagResponse): Promise<void> {\n const workspaceId = created.workspace_ext_id\n patchWorkspaceTags(qc, workspaceId, (old) =>\n old.some((t) => t.external_id === created.external_id) ? old : [...old, created]\n )\n return invalidateTagTables(qc, workspaceId)\n}\n\n/** A changed tag replaces its entry in the list; the tables re-read. */\nfunction settleChangedTag(qc: QueryClient, tag: TagResponse): Promise<void> {\n const workspaceId = tag.workspace_ext_id\n patchWorkspaceTags(qc, workspaceId, (old) =>\n old.map((t) => (t.external_id === tag.external_id ? { ...t, ...tag } : t))\n )\n return invalidateTagTables(qc, workspaceId)\n}\n\n/**\n * The tag writes a host may queue while offline and replay after a reload (`offline.ts`): each\n * key's request on a bare client, and what its success does to the cache.\n */\nexport const replayableTagMutations = [\n {\n mutationKey: arbiMutationKeys.createTag(),\n // In the workspace it was made in (named on the request), opened for this session first.\n run: (client: ArbiClient, input: CreateTagInput) =>\n inWorkspace(primeOnClient(client), input.workspaceId, () => tagOps.createTag(client, input)),\n settle: (qc: QueryClient, created: TagResponse) => settleCreatedTag(qc, created),\n },\n] as const\n\n/**\n * Create a tag in the open workspace, or `workspaceId` (`{ name, kind: 'issue' }`, `{ name, parentId }`, …): it is\n * added to the tag list and the tables re-read. Resolves with the new tag. Offline it is held and\n * sent on reconnect (a host that registers `registerArbiMutationDefaults` keeps it across reloads).\n */\nexport function useCreateTag() {\n const arbi = useArbi()\n const qc = useQueryClient()\n // The workspace is captured when the tag is made, so a create queued offline keeps it.\n const capture = (input: CreateTagInput): CreateTagInput =>\n input.workspaceId || !arbi.hasWorkspace\n ? input\n : { ...input, workspaceId: arbi.getWorkspaceId() }\n return useCapturingWorkspace(\n useMutation({\n mutationKey: arbiMutationKeys.createTag(),\n mutationFn: (input: CreateTagInput): Promise<TagResponse> =>\n inWorkspace(primeOnArbi(arbi), input.workspaceId, () => arbi.tags.create(input)),\n onSuccess: (created) => settleCreatedTag(qc, created),\n ...QUEUED_WRITE_RETRY,\n }),\n capture\n )\n}\n\n/**\n * Whether a tag of this name (any case) is being created right now: a second create of the same\n * name (a double Enter) is skipped instead of making a duplicate.\n */\nexport function useIsCreatingTag(): (name: string) => boolean {\n const qc = useQueryClient()\n return useCallback(\n (name: string) => {\n const wanted = name.trim().toLowerCase()\n return (\n qc.getMutationCache().findAll({\n mutationKey: arbiMutationKeys.createTag(),\n predicate: (m) =>\n m.state.status === 'pending' &&\n (m.state.variables as CreateTagInput | undefined)?.name.trim().toLowerCase() === wanted,\n }).length > 0\n )\n },\n [qc]\n )\n}\n\n/** Change a tag (name, format, instruction, parent, sharing, values): patched in the list. */\nexport function useUpdateTag() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationKey: arbiMutationKeys.updateTag(),\n mutationFn: ({ tagId, change }: { tagId: string; change: TagChange }): Promise<TagResponse> =>\n arbi.tags.update(tagId, change),\n onSuccess: (tag) => settleChangedTag(qc, tag),\n })\n}\n\n/** Merge-patch a tag's values for its kind's fields (`null` clears one); its tables refresh. */\nexport function useSetTagValues() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationKey: arbiMutationKeys.updateTag(),\n mutationFn: ({\n tagId,\n values,\n }: {\n tagId: string\n values: Record<string, unknown>\n }): Promise<TagResponse> => arbi.tags.setValues(tagId, values),\n onSuccess: (tag) => settleChangedTag(qc, tag),\n })\n}\n\n/**\n * Delete a tag: it leaves the list (its sub-tags move to the top level on the server, so the list\n * re-reads them), and the tables and facts re-read. A host that shows the tag on its own items\n * (documents' tags) follows `arbiMutationKeys.deleteTag()` to drop it there.\n */\nexport function useDeleteTag() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationKey: arbiMutationKeys.deleteTag(),\n mutationFn: (tagId: string) => arbi.tags.delete(tagId),\n // The tag's own workspace (the cached list holding it), else the one open when it is sent: a\n // switch while the delete runs must not patch the next workspace's list.\n onMutate: (tagId) => ({ workspaceId: workspaceOfTag(qc, tagId) ?? openWorkspaceId(arbi) }),\n onSuccess: (_data, tagId, context) => {\n // Its pills come off the documents grid in place (and off any open document).\n dropTagFromCachedDocuments(qc, tagId)\n const workspaceId = context?.workspaceId\n if (!workspaceId) return\n patchWorkspaceTags(qc, workspaceId, (old) =>\n old\n .filter((t) => t.external_id !== tagId)\n .map((t) => (t.parent_ext_id === tagId ? { ...t, parent_ext_id: null } : t))\n )\n return Promise.all([\n invalidateTagTables(qc, workspaceId),\n qc.invalidateQueries({ queryKey: arbiQueryKeys.facts(workspaceId) }),\n ])\n },\n })\n}\n\n/**\n * Find the people and organisations documents name and link each to its entity tag. Accepted at\n * once with the documents' ids, which show as running (`useEntityExtractionDocIds`) until a\n * `batch_complete` (`entity_extract`) WebSocket message says they are done.\n */\nexport function useExtractEntities() {\n const arbi = useArbi()\n return useMutation({\n mutationKey: arbiMutationKeys.extractEntities(),\n mutationFn: (docIds: string[]) => arbi.tags.extractEntities(docIds),\n onSuccess: (data) => startEntityExtraction(data.doc_ext_ids),\n })\n}\n\n/**\n * A kind's fields in the open workspace (`'issue'`: its issue fields): the columns of a table of\n * that kind's tags. The built-in ones (`is_default`) until the workspace sets its own.\n */\nexport function useTagKindSchema(\n kind: TagKind | null | undefined,\n options?: { enabled?: boolean }\n) {\n const arbi = useArbi()\n const workspaceId = openWorkspaceId(arbi) ?? ''\n return useQuery({\n queryKey: arbiQueryKeys.tagKind(workspaceId, kind ?? ''),\n queryFn: (): Promise<TagKindSchema> =>\n arbi.readInWorkspace(workspaceId, () => arbi.tagKinds.get(kind as TagKind)),\n enabled: (options?.enabled ?? true) && !!kind && !!workspaceId,\n })\n}\n\n/**\n * Set a kind's fields in full (a field with its `id` keeps its values; one without is new; one\n * left out is removed). The kind's schema and the workspace's tags refresh.\n */\nexport function useUpdateTagKindSchema() {\n const arbi = useArbi()\n const qc = useQueryClient()\n return useMutation({\n mutationKey: arbiMutationKeys.updateTagKindSchema(),\n mutationFn: ({\n kind,\n fields,\n }: {\n kind: TagKind\n fields: TagFieldDefinition[]\n }): Promise<TagKindSchema> => arbi.tagKinds.update(kind, fields),\n // The workspace open when it is sent (the server writes the open workspace's schema until\n // the request can name it): a switch meanwhile must not rewrite the next workspace's columns.\n onMutate: () => ({ workspaceId: openWorkspaceId(arbi) }),\n onSuccess: (schema, _input, context) => {\n const workspaceId = context?.workspaceId\n if (!workspaceId) return\n qc.setQueryData(arbiQueryKeys.tagKind(workspaceId, schema.kind), schema)\n return invalidateTagData(qc, workspaceId)\n },\n })\n}\n","/**\n * Reading a workspace's documents progressively: the first page is the query's result, so the\n * list shows within a few hundred milliseconds even for 100k documents, and the remaining pages\n * are appended to the same cache entry in the background as they arrive. One background read per\n * workspace; opening another workspace stops the previous one. Whether a background read is\n * running is observable ({@link useDocumentsLoading}), for a \"still loading\" indicator.\n */\n\nimport { useSyncExternalStore } from 'react'\nimport type { QueryClient } from '@tanstack/react-query'\nimport type { Arbi } from '@arbidocs/sdk/browser'\nimport { patchDocuments, type WorkspaceDocument } from './documents-cache'\n\n/** First page: small, so rows are on screen in a few hundred ms even in a large workspace. */\nexport const DOCUMENTS_FIRST_PAGE_SIZE = 500\n\n/** Later pages: larger, fewer round trips (the server caps a page at 10 000). */\nexport const DOCUMENTS_PAGE_SIZE = 2000\n\n/**\n * The time to the first page, as a `performance` measure of this name (a host reporting\n * performance can observe it).\n */\nexport const DOCUMENTS_FIRST_PAGE_MEASURE = 'arbi:document-list:page1'\nconst FIRST_PAGE_MEASURE = DOCUMENTS_FIRST_PAGE_MEASURE\nconst FIRST_PAGE_START = 'arbi:document-list:start'\n\nfunction mark(name: string): void {\n try {\n performance.mark(name)\n } catch {\n // No performance timeline here (an old runtime, a test): nothing to record.\n }\n}\n\nfunction measure(name: string, start: string): void {\n try {\n performance.measure(name, start)\n } catch {\n // The start mark is missing: nothing to record.\n }\n}\n\nconst backgroundReads = new Map<string, AbortController>()\nconst loadingListeners = new Set<() => void>()\n\nfunction emitLoading(): void {\n for (const listener of loadingListeners) listener()\n}\n\nfunction subscribeLoading(listener: () => void): () => void {\n loadingListeners.add(listener)\n return () => {\n loadingListeners.delete(listener)\n }\n}\n\n/** Whether a workspace's remaining document pages are being read in the background. */\nexport function isDocumentsLoading(): boolean {\n return backgroundReads.size > 0\n}\n\n/** True while the remaining pages of a documents list are still arriving. */\nexport function useDocumentsLoading(): boolean {\n return useSyncExternalStore(subscribeLoading, isDocumentsLoading, () => false)\n}\n\n/** Stop a workspace's background read (closing the workspace). */\nexport function stopDocumentsLoading(workspaceId: string): void {\n const controller = backgroundReads.get(workspaceId)\n if (!controller) return\n controller.abort()\n backgroundReads.delete(workspaceId)\n emitLoading()\n}\n\n/**\n * Read a workspace's documents: resolves with the first page and appends the rest to\n * `arbiQueryKeys.documents(workspaceId)` in the background. The query function of `useDocuments`.\n */\nexport async function loadDocuments(\n qc: QueryClient,\n arbi: Arbi,\n workspaceId: string,\n signal?: AbortSignal\n): Promise<WorkspaceDocument[]> {\n let stopped = false\n for (const [id, controller] of backgroundReads) {\n if (id === workspaceId) continue\n controller.abort()\n backgroundReads.delete(id)\n stopped = true\n }\n if (stopped) emitLoading()\n\n const controller = new AbortController()\n signal?.addEventListener('abort', () => controller.abort(), { once: true })\n // Named, not the session's open workspace: the pages are this workspace's whatever the server\n // session is in, so a list read across a workspace switch can never be another's.\n const pages = arbi.documents.listPaginated({\n workspaceId,\n pageSize: DOCUMENTS_PAGE_SIZE,\n firstPageSize: DOCUMENTS_FIRST_PAGE_SIZE,\n signal: controller.signal,\n })\n mark(FIRST_PAGE_START)\n const first = await pages.next()\n const firstPage = first.done ? [] : first.value\n measure(FIRST_PAGE_MEASURE, FIRST_PAGE_START)\n if (first.done || firstPage.length < DOCUMENTS_FIRST_PAGE_SIZE) return firstPage\n if (backgroundReads.has(workspaceId)) {\n controller.abort()\n return firstPage\n }\n\n backgroundReads.set(workspaceId, controller)\n emitLoading()\n void appendRemainingPages(qc, workspaceId, pages, controller.signal).finally(() => {\n if (backgroundReads.get(workspaceId) !== controller) return\n backgroundReads.delete(workspaceId)\n emitLoading()\n })\n return firstPage\n}\n\nasync function appendRemainingPages(\n qc: QueryClient,\n workspaceId: string,\n pages: AsyncGenerator<WorkspaceDocument[]>,\n signal: AbortSignal\n): Promise<void> {\n // Let the query store the first page before the second is appended to it.\n await Promise.resolve()\n try {\n for await (const page of pages) {\n if (signal.aborted) return\n // A write may already have added some of these (an upload finishing meanwhile).\n patchDocuments(\n qc,\n (old) => {\n const known = new Set(old.map((doc) => doc.external_id))\n const fresh = page.filter((doc) => !known.has(doc.external_id))\n return fresh.length ? [...old, ...fresh] : old\n },\n workspaceId\n )\n }\n } catch (error) {\n if (!signal.aborted) console.error(`Reading the documents of ${workspaceId} failed:`, error)\n }\n}\n\n/** Test-only: stop every background read. @internal */\nexport function resetDocumentsLoadingForTests(): void {\n for (const controller of backgroundReads.values()) controller.abort()\n backgroundReads.clear()\n emitLoading()\n}\n","/**\n * Which is newer: a document's live processing status or its row as last read?\n *\n * Every `task_update` carries `seq`, taken by the server from one sequence for all documents and\n * all of its instances, so a higher seq is a later event however the events arrive. A document row\n * carries `status_seq`: the seq of the last time its processing ended (a finished status written or\n * broadcast). The two compare:\n * - an event at or below the seq of the one already held is stale (overtaken), and is dropped;\n * - a row whose `status_seq` is above the live status's seq finished after it: the live status is\n * over (its final event was lost), and the row wins;\n * - a live status above the row's `status_seq` is newer than the row: the document is being\n * processed again (AI fields being filled) although the row still says it finished.\n *\n * Without the seqs (an optimistic \"queued\" set here, a server before them) the older rule stands:\n * a live in-flight status wins, then a finished row, then whatever was heard live.\n */\n\n/** Statuses after which a document's processing is over (`low-content`: indexed, little text). */\nexport const FINISHED_DOCUMENT_STATUSES: ReadonlySet<string> = new Set([\n 'completed',\n 'low-content',\n 'failed',\n 'skipped',\n 'empty',\n])\n\n/** A live processing status and its order (`task_update.seq`). */\nexport interface SequencedTask {\n status: string\n seq?: number | null\n}\n\n/** A document row's status and the order of its last finished status (`status_seq`). */\nexport interface SequencedRow {\n status?: string | null\n status_seq?: number | null\n}\n\n/** Statuses of a document still being processed. */\nexport const IN_FLIGHT_DOCUMENT_STATUSES: ReadonlySet<string> = new Set([\n 'uploading',\n 'queued',\n 'parsing',\n 'encrypting',\n 'indexing',\n 'analysing',\n])\n\nfunction ordered(value: number | null | undefined): value is number {\n return typeof value === 'number'\n}\n\n/** Whether `next` is older than (or the same event as) the live status already held. */\nexport function isStaleTaskUpdate(held: SequencedTask | undefined, next: SequencedTask): boolean {\n return !!held && ordered(held.seq) && ordered(next.seq) && next.seq <= held.seq\n}\n\n/**\n * Whether the row is newer than the live status: `true` / `false` when both are ordered, `undefined`\n * when they cannot be compared.\n */\nexport function isRowNewer(row: SequencedRow, task: SequencedTask): boolean | undefined {\n if (!ordered(row.status_seq) || !ordered(task.seq)) return undefined\n return row.status_seq > task.seq\n}\n\n/** The status a document shows now: its row's, or the live one when that is newer. */\nexport function resolveDocumentStatus(row: SequencedRow, task: SequencedTask | undefined): string {\n const rowStatus = (row.status ?? '').toLowerCase()\n const live = task?.status\n if (!task || !live) return rowStatus\n const rowNewer = isRowNewer(row, task)\n if (rowNewer !== undefined) return rowNewer ? rowStatus || live : live\n if (IN_FLIGHT_DOCUMENT_STATUSES.has(live)) return live\n if (FINISHED_DOCUMENT_STATUSES.has(rowStatus)) return rowStatus\n return live\n}\n\n/**\n * The live statuses a read of `rows` ends: each in-flight one whose row has since finished. Ordered,\n * the row must be newer (so a reprocess the row predates keeps its progress); unordered, a finished\n * row is enough (the older rule). Returns each such task with the row's status and order. Cheap when\n * nothing is in flight (it runs on every read of a list).\n */\nexport function settledByRows<T extends SequencedTask & { doc_ext_id: string }>(\n tasks: Readonly<Record<string, T>>,\n rows: ReadonlyArray<SequencedRow & { external_id: string }>\n): T[] {\n const inFlight = new Map<string, T>()\n for (const task of Object.values(tasks))\n if (IN_FLIGHT_DOCUMENT_STATUSES.has(task.status)) inFlight.set(task.doc_ext_id, task)\n if (!inFlight.size) return []\n const settled: T[] = []\n for (const row of rows) {\n const task = inFlight.get(row.external_id)\n if (!task) continue\n const rowStatus = (row.status ?? '').toLowerCase()\n if (!FINISHED_DOCUMENT_STATUSES.has(rowStatus) || isRowNewer(row, task) === false) continue\n settled.push({ ...task, status: rowStatus, seq: row.status_seq ?? task.seq })\n }\n return settled\n}\n","/**\n * Canonical WebSocket state, shared across apps.\n *\n * One store for every site's live connection: its status, people's presence and each document's\n * live processing. `ArbiWebSocketProvider` feeds it; components read it with the selector hooks in\n * `./hooks` and the documents hooks (`useProcessingTasks`, `useWorkspaceProcessing`).\n */\n\nimport { create } from 'zustand'\nimport type { WsTaskUpdateMessage, WsPresenceUpdateMessage } from '@arbidocs/client'\nimport {\n FINISHED_DOCUMENT_STATUSES,\n isStaleTaskUpdate,\n settledByRows,\n type SequencedRow,\n} from '../documents/processing-order'\n\n/** `error`: the host's socket failed. */\nexport type ArbiWsStatus = 'disconnected' | 'connecting' | 'connected' | 'reconnecting' | 'error'\n\n/**\n * A document's live processing: its last `task_update` (or a status set here, such as \"queued\"\n * while a write sends it back into processing), with when it was first seen (`startTime`) and\n * when it finished (`endTime`), both on this device's clock.\n */\nexport type LiveTask = Omit<WsTaskUpdateMessage, 'type' | 'seq'> & {\n type?: 'task_update'\n seq?: number | null\n startTime?: number\n endTime?: number\n}\n\n/** How long a document's tasks stay dismissed (late updates of a deleted upload are dropped). */\nexport const DISMISSED_TASK_TTL_MS = 10 * 60 * 1000\n\nexport interface ArbiWsState {\n /** Live connection status of the shared socket. */\n status: ArbiWsStatus\n /** Latest processing status per document id (the `task_update` stream). */\n tasks: Record<string, LiveTask>\n /** Documents whose processing rows were dismissed (deleted, cleared), with when. */\n dismissed: Record<string, number>\n /** The most recent `task_update` — a convenient single-value change trigger. */\n lastTaskUpdate: WsTaskUpdateMessage | null\n /** Online status keyed by user id (the `presence_update` stream). */\n presence: Record<string, string>\n /**\n * The server closed this socket for a newer session of the same user (another device, close\n * code 1008). The socket stays closed: reconnecting would only be evicted again.\n */\n evicted: boolean\n setStatus: (status: ArbiWsStatus) => void\n setEvicted: (evicted: boolean) => void\n /**\n * Take a `task_update`, unless it is older than the one held for its document (`seq`) or the\n * document was dismissed a moment ago. Resolves whether it was taken.\n */\n applyTaskUpdate: (msg: WsTaskUpdateMessage) => boolean\n /** Set a document's live processing directly (an optimistic status, or an undo). */\n putTask: (task: LiveTask) => void\n /** Drop a document's processing row, and ignore its late updates for a while. */\n clearTask: (docId: string) => void\n /** Drop every finished processing row (the in-flight ones stay). */\n clearFinishedTasks: () => void\n /** End the in-flight statuses that documents read since say finished after them. */\n settleTasks: (rows: ReadonlyArray<SequencedRow & { external_id: string }>) => void\n applyPresence: (msg: WsPresenceUpdateMessage) => void\n reset: () => void\n}\n\nconst finished = (status: string) => FINISHED_DOCUMENT_STATUSES.has(status)\n\nexport const useArbiWsStore = create<ArbiWsState>((set, get) => ({\n status: 'disconnected',\n tasks: {},\n dismissed: {},\n lastTaskUpdate: null,\n presence: {},\n evicted: false,\n setStatus: (status) => set({ status }),\n setEvicted: (evicted) => set({ evicted }),\n applyTaskUpdate: (msg) => {\n const { tasks, dismissed } = get()\n const dismissedAt = dismissed[msg.doc_ext_id]\n if (dismissedAt !== undefined && Date.now() - dismissedAt < DISMISSED_TASK_TTL_MS) return false\n const held = tasks[msg.doc_ext_id]\n if (isStaleTaskUpdate(held, msg)) return false\n const now = Date.now()\n const task: LiveTask = {\n ...msg,\n startTime: held?.startTime ?? now,\n endTime: finished(msg.status) ? (held?.endTime ?? now) : undefined,\n }\n set({ tasks: { ...tasks, [msg.doc_ext_id]: task }, lastTaskUpdate: msg })\n return true\n },\n putTask: (task) => set((s) => ({ tasks: { ...s.tasks, [task.doc_ext_id]: task } })),\n clearTask: (docId) =>\n set((s) => {\n const tasks = { ...s.tasks }\n delete tasks[docId]\n return { tasks, dismissed: { ...s.dismissed, [docId]: Date.now() } }\n }),\n clearFinishedTasks: () =>\n set((s) => ({\n tasks: Object.fromEntries(Object.entries(s.tasks).filter(([, t]) => !finished(t.status))),\n })),\n settleTasks: (rows) =>\n set((s) => {\n const settled = settledByRows(s.tasks, rows)\n if (!settled.length) return s\n const tasks = { ...s.tasks }\n const now = Date.now()\n for (const task of settled)\n tasks[task.doc_ext_id] = { ...(task as LiveTask), endTime: task.endTime ?? now }\n return { tasks }\n }),\n applyPresence: (msg) => set((s) => ({ presence: { ...s.presence, [msg.user_id]: msg.status } })),\n reset: () =>\n set({ status: 'disconnected', tasks: {}, dismissed: {}, lastTaskUpdate: null, presence: {} }),\n}))\n","/**\n * Reading documents: a workspace's list (`useDocuments`, progressive, read once and then patched in\n * place), one document (`useDocument`, for a viewer), a set of documents by id, near-duplicate pairs\n * (`useSimilarDocuments`), and {@link refreshDocuments}, which re-reads just the documents an event\n * named and patches them into every cache that shows them.\n */\n\nimport { useCallback } from 'react'\nimport { useQuery, useQueryClient, type QueryClient } from '@tanstack/react-query'\nimport type { Arbi } from '@arbidocs/sdk/browser'\nimport { useArbi } from '../useArbi'\nimport { arbiQueryKeys } from '../hooks'\nimport { invalidateTagTables, patchWorkspaceTags } from '../tags'\nimport {\n getCachedDocuments,\n setCachedDocument,\n upsertDocuments,\n type WorkspaceDocument,\n} from './documents-cache'\nimport { loadDocuments } from './documents-loader'\nimport { FINISHED_DOCUMENT_STATUSES, isRowNewer } from './processing-order'\nimport { useArbiWsStore } from '../websocket/store'\n\nexport { FINISHED_DOCUMENT_STATUSES }\n\n/** The workspace open on `arbi`, or `null`. */\nfunction openWorkspaceId(arbi: Arbi): string | null {\n return arbi.hasWorkspace ? arbi.getWorkspaceId() : null\n}\n\n/**\n * A workspace's documents (default: the open one). Read progressively: the first page is the\n * result, the remaining pages arrive in the background (`useDocumentsLoading`). After that the list\n * is never re-read on its own (mounting, focus, reconnecting): writes, processing events and\n * {@link refreshDocuments} patch it in place, as re-reading 100k documents is slow and tells\n * nothing new. Invalidating it re-reads it.\n */\nexport function useDocuments(workspaceId?: string | null, options?: { enabled?: boolean }) {\n const arbi = useArbi()\n const qc = useQueryClient()\n const workspace = workspaceId ?? openWorkspaceId(arbi) ?? ''\n return useQuery({\n queryKey: arbiQueryKeys.documents(workspace),\n queryFn: ({ signal }) => {\n if (openWorkspaceId(arbi) !== workspace)\n return Promise.reject(new Error('The selected workspace changed.'))\n return loadDocuments(qc, arbi, workspace, signal)\n },\n enabled: (options?.enabled ?? true) && !!workspace && arbi.hasWorkspace,\n staleTime: Infinity,\n refetchOnMount: false,\n refetchOnReconnect: false,\n refetchOnWindowFocus: false,\n })\n}\n\n/** How often a document still being processed is re-read (`useDocument`'s `pollWhileProcessing`). */\nexport const DOCUMENT_STATUS_POLL_MS = 4000\n\n/** Re-read a document while it is processing (a viewer waiting for its pages). */\nfunction processingInterval(doc: WorkspaceDocument | null | undefined): number | false {\n return doc?.status && !FINISHED_DOCUMENT_STATUSES.has(doc.status)\n ? DOCUMENT_STATUS_POLL_MS\n : false\n}\n\n/**\n * One document (`null`: not found or not visible). `pollWhileProcessing` re-reads it every few\n * seconds until its processing is over. Writes here keep it current.\n */\nexport function useDocument(\n docId: string | null | undefined,\n options?: { enabled?: boolean; pollWhileProcessing?: boolean }\n) {\n const arbi = useArbi()\n return useQuery({\n queryKey: arbiQueryKeys.document(docId ?? ''),\n queryFn: async (): Promise<WorkspaceDocument | null> =>\n (await arbi.documents.get([docId as string]))[0] ?? null,\n enabled: (options?.enabled ?? true) && !!docId && arbi.isLoggedIn,\n refetchInterval: options?.pollWhileProcessing\n ? (query) => processingInterval(query.state.data)\n : false,\n })\n}\n\n/**\n * The similarity at or above which two documents count as near duplicates (the Related column).\n * The server keeps every pair above 0.75 but returns only those at or above what is asked.\n */\nexport const SIMILARITY_THRESHOLD = 0.98\n\n/** Near-duplicate document pairs in the open workspace, at or above {@link SIMILARITY_THRESHOLD}. */\nexport function useSimilarDocuments(options?: { enabled?: boolean }) {\n const arbi = useArbi()\n const workspace = openWorkspaceId(arbi) ?? ''\n return useQuery({\n queryKey: arbiQueryKeys.similarDocuments(workspace, SIMILARITY_THRESHOLD),\n queryFn: () =>\n arbi.readInWorkspace(workspace, () =>\n arbi.documents.similar({ threshold: SIMILARITY_THRESHOLD })\n ),\n enabled: (options?.enabled ?? true) && !!workspace,\n })\n}\n\n// Each re-read gets a number; only the latest one issued for a document may write it. Events can\n// return out of order, and an older read must not undo tags a newer one applied.\nlet readSeq = 0\nconst latestReadByDoc = new Map<string, number>()\n\n/**\n * Re-read `docIds` and patch them into the caches that show them: their workspace's list (added\n * when new), their own entries, and the tag list's document counts (tags the server applied, e.g.\n * AI fields). For events that name documents (a batch finished, a version saved, an upload): the\n * list is never re-read for them. A failed read leaves the caches as they were.\n */\nexport async function refreshDocuments(\n qc: QueryClient,\n arbi: Arbi,\n docIds: string[]\n): Promise<WorkspaceDocument[]> {\n if (!docIds.length) return []\n const seq = ++readSeq\n for (const id of docIds) latestReadByDoc.set(id, seq)\n try {\n const read = await arbi.documents.get(docIds)\n const fresh = read\n .filter((doc) => latestReadByDoc.get(doc.external_id) === seq)\n .map((doc) => {\n // A finished status heard live wins over a read that predates it (the row may not be\n // committed yet), never over a row that finished after it.\n const live = useArbiWsStore.getState().tasks[doc.external_id]\n return live &&\n FINISHED_DOCUMENT_STATUSES.has(live.status) &&\n doc.status !== live.status &&\n isRowNewer(doc, live) !== true\n ? { ...doc, status: live.status }\n : doc\n })\n if (!fresh.length) return []\n reconcileTagCounts(qc, fresh)\n upsertDocuments(qc, fresh)\n for (const doc of fresh) setCachedDocument(qc, doc)\n return fresh\n } catch (error) {\n // Leave the caches as they were: re-reading the whole list would shrink it to its first page.\n console.error('Re-reading documents failed; the cached ones are kept:', error)\n return []\n } finally {\n for (const id of docIds) if (latestReadByDoc.get(id) === seq) latestReadByDoc.delete(id)\n }\n}\n\n/** `refreshDocuments` on this host's cache and `Arbi`, for a component or a hook. */\nexport function useRefreshDocuments(): (docIds: string[]) => Promise<WorkspaceDocument[]> {\n const qc = useQueryClient()\n const arbi = useArbi()\n return useCallback((docIds: string[]) => refreshDocuments(qc, arbi, docIds), [qc, arbi])\n}\n\n/** Move each tag's document count by the tags the re-read documents gained or lost. */\nfunction reconcileTagCounts(qc: QueryClient, fresh: WorkspaceDocument[]): void {\n const byWorkspace = new Map<string, Map<string, number>>()\n for (const doc of fresh) {\n const cached = getCachedDocuments(qc, doc.workspace_ext_id)?.find(\n (d) => d.external_id === doc.external_id\n )\n const before = new Set((cached?.doctags ?? []).map((dt) => dt.tag_ext_id))\n const after = new Set((doc.doctags ?? []).map((dt) => dt.tag_ext_id))\n const delta = byWorkspace.get(doc.workspace_ext_id) ?? new Map<string, number>()\n for (const id of after) if (!before.has(id)) delta.set(id, (delta.get(id) ?? 0) + 1)\n for (const id of before) if (!after.has(id)) delta.set(id, (delta.get(id) ?? 0) - 1)\n byWorkspace.set(doc.workspace_ext_id, delta)\n }\n for (const [workspaceId, delta] of byWorkspace) adjustTagCounts(qc, workspaceId, delta)\n}\n\n/** Add `delta` (tag id → change) to the tags' document counts; the tag tables re-read. */\nexport function adjustTagCounts(\n qc: QueryClient,\n workspaceId: string,\n delta: Map<string, number>\n): void {\n if (![...delta.values()].some(Boolean)) return\n patchWorkspaceTags(qc, workspaceId, (tags) =>\n tags.map((tag) => {\n const change = delta.get(tag.external_id)\n return change ? { ...tag, doctag_count: Math.max(0, tag.doctag_count + change) } : tag\n })\n )\n void invalidateTagTables(qc, workspaceId)\n}\n"]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var chunkQ2GNEVG2_cjs = require('./chunk-Q2GNEVG2.cjs');
|
|
3
|
+
var chunkW2FATOTX_cjs = require('./chunk-W2FATOTX.cjs');
|
|
5
4
|
var chunkSUZORMAB_cjs = require('./chunk-SUZORMAB.cjs');
|
|
6
5
|
var chunk2IJP73ZG_cjs = require('./chunk-2IJP73ZG.cjs');
|
|
6
|
+
var chunk7LIMHY56_cjs = require('./chunk-7LIMHY56.cjs');
|
|
7
7
|
var chunkNDIKMOBJ_cjs = require('./chunk-NDIKMOBJ.cjs');
|
|
8
8
|
var react = require('react');
|
|
9
9
|
var reactQuery = require('@tanstack/react-query');
|
|
@@ -210,7 +210,7 @@ function versionsWithMarkup(versions) {
|
|
|
210
210
|
}
|
|
211
211
|
var SIGNED_UNCHANGED = "The signed PDF is unchanged: the comments are kept beside it as markup.";
|
|
212
212
|
function useDocumentMarkup(documentData, snapshotVersion, currentSigned = false) {
|
|
213
|
-
const { client, notify, saveFile, onDocumentsChanged } =
|
|
213
|
+
const { client, notify, saveFile, onDocumentsChanged } = chunkW2FATOTX_cjs.useDocumentTools();
|
|
214
214
|
const documentId = documentData?.external_id;
|
|
215
215
|
const currentVersion = documentData?.current_version ?? 1;
|
|
216
216
|
const shownVersion = snapshotVersion ?? currentVersion;
|
|
@@ -241,11 +241,11 @@ function useDocumentMarkup(documentData, snapshotVersion, currentSigned = false)
|
|
|
241
241
|
const downloadMarkup = react.useCallback(async () => {
|
|
242
242
|
if (!documentId) return;
|
|
243
243
|
if (currentSigned) {
|
|
244
|
-
notify(
|
|
244
|
+
notify(chunkW2FATOTX_cjs.SIGNED_LOCKED_REASON, "info");
|
|
245
245
|
return;
|
|
246
246
|
}
|
|
247
247
|
try {
|
|
248
|
-
const { blob, fileName } = await
|
|
248
|
+
const { blob, fileName } = await chunkW2FATOTX_cjs.fetchMarkupPdf(
|
|
249
249
|
client,
|
|
250
250
|
documentId,
|
|
251
251
|
snapshotVersion ? snapshotVersion : void 0
|
|
@@ -383,17 +383,17 @@ function useIsOnline() {
|
|
|
383
383
|
);
|
|
384
384
|
}
|
|
385
385
|
function useDocumentBytes(documentRef, options) {
|
|
386
|
-
const { client } =
|
|
386
|
+
const { client } = chunkW2FATOTX_cjs.useDocumentTools();
|
|
387
387
|
const { version, kind, enabled = true, fallback } = options;
|
|
388
388
|
return reactQuery.useQuery({
|
|
389
|
-
queryKey:
|
|
389
|
+
queryKey: chunk7LIMHY56_cjs.documentBytesKey(documentRef, version ?? null, kind),
|
|
390
390
|
queryFn: async ({ signal }) => {
|
|
391
391
|
if (fallback && typeof navigator !== "undefined" && navigator.onLine === false) {
|
|
392
392
|
const offline = await fallback();
|
|
393
393
|
if (offline) return offline;
|
|
394
394
|
}
|
|
395
395
|
try {
|
|
396
|
-
return await (kind === "original" ?
|
|
396
|
+
return await (kind === "original" ? chunkW2FATOTX_cjs.fetchDocumentFile : chunkW2FATOTX_cjs.fetchDocumentPdf)(
|
|
397
397
|
client,
|
|
398
398
|
documentRef,
|
|
399
399
|
{ signal }
|
|
@@ -438,10 +438,10 @@ async function fetchDocumentSignatures(client, documentRef) {
|
|
|
438
438
|
return data;
|
|
439
439
|
}
|
|
440
440
|
function useDocumentSignatures(documentId, enabled = true) {
|
|
441
|
-
const { client } =
|
|
441
|
+
const { client } = chunkW2FATOTX_cjs.useDocumentTools();
|
|
442
442
|
const { docId, version } = chunkNDIKMOBJ_cjs.parseVersionRef(documentId);
|
|
443
443
|
return reactQuery.useQuery({
|
|
444
|
-
queryKey:
|
|
444
|
+
queryKey: chunk7LIMHY56_cjs.arbiQueryKeys.documentSignatures(docId ?? "", version),
|
|
445
445
|
queryFn: () => fetchDocumentSignatures(client, documentId),
|
|
446
446
|
enabled: enabled && !!docId,
|
|
447
447
|
staleTime: 6e4
|
|
@@ -506,7 +506,7 @@ async function signDocument(client$1, deploymentDomain, {
|
|
|
506
506
|
return signed.data;
|
|
507
507
|
}
|
|
508
508
|
function useSignDocument() {
|
|
509
|
-
const env =
|
|
509
|
+
const env = chunkW2FATOTX_cjs.useDocumentTools();
|
|
510
510
|
const queryClient = reactQuery.useQueryClient();
|
|
511
511
|
return reactQuery.useMutation({
|
|
512
512
|
mutationFn: (vars) => {
|
|
@@ -515,7 +515,7 @@ function useSignDocument() {
|
|
|
515
515
|
},
|
|
516
516
|
onSuccess: async (result) => {
|
|
517
517
|
await env.onDocumentsChanged?.([result.doc_ext_id], "signed");
|
|
518
|
-
await queryClient.invalidateQueries({ queryKey:
|
|
518
|
+
await queryClient.invalidateQueries({ queryKey: chunk7LIMHY56_cjs.arbiQueryKeys.documentSignatures() });
|
|
519
519
|
}
|
|
520
520
|
});
|
|
521
521
|
}
|
|
@@ -552,9 +552,9 @@ async function fetchSignatureVerification(client, reference) {
|
|
|
552
552
|
return data;
|
|
553
553
|
}
|
|
554
554
|
function useSignatureVerification(reference) {
|
|
555
|
-
const { client } =
|
|
555
|
+
const { client } = chunkW2FATOTX_cjs.useDocumentTools();
|
|
556
556
|
return reactQuery.useQuery({
|
|
557
|
-
queryKey:
|
|
557
|
+
queryKey: chunk7LIMHY56_cjs.arbiQueryKeys.signatureVerification(reference ?? ""),
|
|
558
558
|
queryFn: () => fetchSignatureVerification(client, reference),
|
|
559
559
|
enabled: !!reference,
|
|
560
560
|
retry: false
|
|
@@ -567,7 +567,7 @@ async function matchSignedCopy(file, verification) {
|
|
|
567
567
|
return signature ? { kind: "earlier", signature } : { kind: "none" };
|
|
568
568
|
}
|
|
569
569
|
function useOpenWorkspaceRead() {
|
|
570
|
-
const arbi =
|
|
570
|
+
const arbi = chunk7LIMHY56_cjs.useArbiHost().arbi;
|
|
571
571
|
const workspaceId = arbi?.hasWorkspace ? arbi.getWorkspaceId() : void 0;
|
|
572
572
|
const read = (run) => arbi && workspaceId ? arbi.readInWorkspace(workspaceId, run) : run();
|
|
573
573
|
return { workspaceId, read };
|
|
@@ -661,9 +661,9 @@ async function fetchDocumentSignatureRequests(client, documentId) {
|
|
|
661
661
|
return data;
|
|
662
662
|
}
|
|
663
663
|
function useDocumentSignatureRequests(documentId, enabled = true) {
|
|
664
|
-
const { client } =
|
|
664
|
+
const { client } = chunkW2FATOTX_cjs.useDocumentTools();
|
|
665
665
|
return reactQuery.useQuery({
|
|
666
|
-
queryKey:
|
|
666
|
+
queryKey: chunk7LIMHY56_cjs.arbiQueryKeys.signatureRequestsForDocument(documentId ?? ""),
|
|
667
667
|
queryFn: () => fetchDocumentSignatureRequests(client, documentId),
|
|
668
668
|
enabled: enabled && !!documentId,
|
|
669
669
|
staleTime: 15e3
|
|
@@ -706,10 +706,10 @@ async function saveSignatureRequest(client, { documentId, version, fields, messa
|
|
|
706
706
|
}
|
|
707
707
|
function useInvalidateRequests() {
|
|
708
708
|
const queryClient = reactQuery.useQueryClient();
|
|
709
|
-
return () => queryClient.invalidateQueries({ queryKey:
|
|
709
|
+
return () => queryClient.invalidateQueries({ queryKey: chunk7LIMHY56_cjs.arbiQueryKeys.signatureRequests() });
|
|
710
710
|
}
|
|
711
711
|
function useSaveSignatureRequest() {
|
|
712
|
-
const { client } =
|
|
712
|
+
const { client } = chunkW2FATOTX_cjs.useDocumentTools();
|
|
713
713
|
const invalidate = useInvalidateRequests();
|
|
714
714
|
return reactQuery.useMutation({
|
|
715
715
|
mutationFn: (vars) => saveSignatureRequest(client, vars),
|
|
@@ -717,7 +717,7 @@ function useSaveSignatureRequest() {
|
|
|
717
717
|
});
|
|
718
718
|
}
|
|
719
719
|
function useVoidSignatureRequest() {
|
|
720
|
-
const { client } =
|
|
720
|
+
const { client } = chunkW2FATOTX_cjs.useDocumentTools();
|
|
721
721
|
const invalidate = useInvalidateRequests();
|
|
722
722
|
return reactQuery.useMutation({
|
|
723
723
|
mutationFn: async (requestId) => {
|
|
@@ -731,7 +731,7 @@ function useVoidSignatureRequest() {
|
|
|
731
731
|
});
|
|
732
732
|
}
|
|
733
733
|
function useDeclineSignatureRequest() {
|
|
734
|
-
const { client } =
|
|
734
|
+
const { client } = chunkW2FATOTX_cjs.useDocumentTools();
|
|
735
735
|
const invalidate = useInvalidateRequests();
|
|
736
736
|
return reactQuery.useMutation({
|
|
737
737
|
mutationFn: async ({ requestId, reason }) => {
|
|
@@ -771,7 +771,7 @@ async function signSignatureRequest(client$1, deploymentDomain, { request, pdfBl
|
|
|
771
771
|
return signed.data;
|
|
772
772
|
}
|
|
773
773
|
function useSignSignatureRequest() {
|
|
774
|
-
const env =
|
|
774
|
+
const env = chunkW2FATOTX_cjs.useDocumentTools();
|
|
775
775
|
const invalidate = useInvalidateRequests();
|
|
776
776
|
const queryClient = reactQuery.useQueryClient();
|
|
777
777
|
return reactQuery.useMutation({
|
|
@@ -783,16 +783,16 @@ function useSignSignatureRequest() {
|
|
|
783
783
|
await invalidate();
|
|
784
784
|
if (result.completed && result.request.doc_ext_id) {
|
|
785
785
|
await env.onDocumentsChanged?.([result.request.doc_ext_id], "signed");
|
|
786
|
-
await queryClient.invalidateQueries({ queryKey:
|
|
786
|
+
await queryClient.invalidateQueries({ queryKey: chunk7LIMHY56_cjs.arbiQueryKeys.documentSignatures() });
|
|
787
787
|
}
|
|
788
788
|
}
|
|
789
789
|
});
|
|
790
790
|
}
|
|
791
791
|
function useSignerCandidates(enabled = true) {
|
|
792
|
-
const { client, user } =
|
|
792
|
+
const { client, user } = chunkW2FATOTX_cjs.useDocumentTools();
|
|
793
793
|
const { workspaceId, read } = useOpenWorkspaceRead();
|
|
794
794
|
return reactQuery.useQuery({
|
|
795
|
-
queryKey:
|
|
795
|
+
queryKey: chunk7LIMHY56_cjs.arbiQueryKeys.signatureCandidates(workspaceId ?? ""),
|
|
796
796
|
queryFn: async () => {
|
|
797
797
|
const { data, error } = await read(() => client.GET("/v1/workspace/users"));
|
|
798
798
|
if (!data) throw new Error(detail(error, "The workspace members could not be read"));
|
|
@@ -830,14 +830,14 @@ async function inviteSigners(client, documentId, emails) {
|
|
|
830
830
|
}
|
|
831
831
|
}
|
|
832
832
|
function useInviteSigners() {
|
|
833
|
-
const { client } =
|
|
833
|
+
const { client } = chunkW2FATOTX_cjs.useDocumentTools();
|
|
834
834
|
const invalidate = useInvalidateRequests();
|
|
835
835
|
const queryClient = reactQuery.useQueryClient();
|
|
836
836
|
return reactQuery.useMutation({
|
|
837
837
|
mutationFn: ({ documentId, emails }) => inviteSigners(client, documentId, emails),
|
|
838
838
|
onSuccess: async () => {
|
|
839
839
|
await invalidate();
|
|
840
|
-
await queryClient.invalidateQueries({ queryKey:
|
|
840
|
+
await queryClient.invalidateQueries({ queryKey: chunk7LIMHY56_cjs.arbiQueryKeys.signatureCandidates() });
|
|
841
841
|
}
|
|
842
842
|
});
|
|
843
843
|
}
|
|
@@ -874,9 +874,9 @@ async function deleteSavedSignature(client) {
|
|
|
874
874
|
if (!response.ok) throw new Error(detail2(error, "Your saved signature could not be deleted"));
|
|
875
875
|
}
|
|
876
876
|
function useSavedSignature(enabled = true) {
|
|
877
|
-
const { client } =
|
|
877
|
+
const { client } = chunkW2FATOTX_cjs.useDocumentTools();
|
|
878
878
|
return reactQuery.useQuery({
|
|
879
|
-
queryKey:
|
|
879
|
+
queryKey: chunk7LIMHY56_cjs.arbiQueryKeys.savedSignature(),
|
|
880
880
|
queryFn: () => fetchSavedSignature(client),
|
|
881
881
|
enabled,
|
|
882
882
|
staleTime: 6e4,
|
|
@@ -884,19 +884,19 @@ function useSavedSignature(enabled = true) {
|
|
|
884
884
|
});
|
|
885
885
|
}
|
|
886
886
|
function useStoreSavedSignature() {
|
|
887
|
-
const { client } =
|
|
887
|
+
const { client } = chunkW2FATOTX_cjs.useDocumentTools();
|
|
888
888
|
const queryClient = reactQuery.useQueryClient();
|
|
889
889
|
return reactQuery.useMutation({
|
|
890
890
|
mutationFn: (signature) => storeSavedSignature(client, signature),
|
|
891
|
-
onSuccess: (_, signature) => queryClient.setQueryData(
|
|
891
|
+
onSuccess: (_, signature) => queryClient.setQueryData(chunk7LIMHY56_cjs.arbiQueryKeys.savedSignature(), signature)
|
|
892
892
|
});
|
|
893
893
|
}
|
|
894
894
|
function useDeleteSavedSignature() {
|
|
895
|
-
const { client } =
|
|
895
|
+
const { client } = chunkW2FATOTX_cjs.useDocumentTools();
|
|
896
896
|
const queryClient = reactQuery.useQueryClient();
|
|
897
897
|
return reactQuery.useMutation({
|
|
898
898
|
mutationFn: () => deleteSavedSignature(client),
|
|
899
|
-
onSuccess: () => queryClient.setQueryData(
|
|
899
|
+
onSuccess: () => queryClient.setQueryData(chunk7LIMHY56_cjs.arbiQueryKeys.savedSignature(), null)
|
|
900
900
|
});
|
|
901
901
|
}
|
|
902
902
|
function pngBytes(base64) {
|
|
@@ -984,14 +984,14 @@ async function signFileShare(client$1, domain, vars) {
|
|
|
984
984
|
}
|
|
985
985
|
function useFileShare(client, shareId, signing) {
|
|
986
986
|
return reactQuery.useQuery({
|
|
987
|
-
queryKey:
|
|
987
|
+
queryKey: chunk7LIMHY56_cjs.arbiQueryKeys.fileShare(shareId),
|
|
988
988
|
queryFn: () => getFileShare(client, shareId),
|
|
989
989
|
refetchInterval: signing ? false : 5e3
|
|
990
990
|
});
|
|
991
991
|
}
|
|
992
992
|
function useFileSharePdf(client, shareId, share) {
|
|
993
993
|
return reactQuery.useQuery({
|
|
994
|
-
queryKey:
|
|
994
|
+
queryKey: chunk7LIMHY56_cjs.arbiQueryKeys.fileSharePdf(shareId, share?.status),
|
|
995
995
|
queryFn: () => fileShareBytes(client, shareId, share?.status === "completed" ? "signed" : "view"),
|
|
996
996
|
enabled: !!share?.can_preview,
|
|
997
997
|
staleTime: Infinity
|
|
@@ -999,7 +999,7 @@ function useFileSharePdf(client, shareId, share) {
|
|
|
999
999
|
}
|
|
1000
1000
|
function useFileShares(client) {
|
|
1001
1001
|
return reactQuery.useQuery({
|
|
1002
|
-
queryKey:
|
|
1002
|
+
queryKey: chunk7LIMHY56_cjs.arbiQueryKeys.fileShares(),
|
|
1003
1003
|
queryFn: async () => {
|
|
1004
1004
|
const result = await client.GET("/v1/file-shares");
|
|
1005
1005
|
if (!result.data) throw new Error("Could not load shared files");
|
|
@@ -1085,5 +1085,5 @@ exports.useSignerCandidates = useSignerCandidates;
|
|
|
1085
1085
|
exports.useStoreSavedSignature = useStoreSavedSignature;
|
|
1086
1086
|
exports.useVoidSignatureRequest = useVoidSignatureRequest;
|
|
1087
1087
|
exports.versionsWithMarkup = versionsWithMarkup;
|
|
1088
|
-
//# sourceMappingURL=chunk-
|
|
1089
|
-
//# sourceMappingURL=chunk-
|
|
1088
|
+
//# sourceMappingURL=chunk-QF2BW6HZ.cjs.map
|
|
1089
|
+
//# sourceMappingURL=chunk-QF2BW6HZ.cjs.map
|