@tearleads/client-sdk 0.1.71 → 0.1.73

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/client/containerContents/index.js +8 -2
  2. package/client/containerContents/index.js.map +1 -1
  3. package/client/containerContents/types.d.ts +4 -1
  4. package/client/containerContents/types.js.map +1 -1
  5. package/client/documents/index.d.ts +4 -1
  6. package/client/documents/index.js +6 -2
  7. package/client/documents/index.js.map +1 -1
  8. package/data/shared/userTiming.js +42 -0
  9. package/data/shared/userTiming.js.map +1 -0
  10. package/data/sqlite/sqlExec.js +27 -3
  11. package/data/sqlite/sqlExec.js.map +1 -1
  12. package/data/sync/coordinatorLaneRun.js +29 -6
  13. package/data/sync/coordinatorLaneRun.js.map +1 -1
  14. package/data/sync/coordinatorState.d.ts +3 -1
  15. package/data/sync/coordinatorState.js +1 -0
  16. package/data/sync/coordinatorState.js.map +1 -1
  17. package/data/sync/syncTelemetry.d.ts +15 -0
  18. package/data/sync/syncTelemetry.js +10 -0
  19. package/data/sync/syncTelemetry.js.map +1 -1
  20. package/data/sync/uploadLane.js +20 -3
  21. package/data/sync/uploadLane.js.map +1 -1
  22. package/package.json +1 -1
  23. package/stores/documents/documentStore/index.js +5 -1
  24. package/stores/documents/documentStore/index.js.map +1 -1
  25. package/stores/documents/documentStore/initialization/index.js +4 -1
  26. package/stores/documents/documentStore/initialization/index.js.map +1 -1
  27. package/stores/documents/documentStore/initialization/initialContent.js +44 -0
  28. package/stores/documents/documentStore/initialization/initialContent.js.map +1 -0
  29. package/stores/documents/documentStore/{rows.js → rows/index.js} +12 -21
  30. package/stores/documents/documentStore/rows/index.js.map +1 -0
  31. package/stores/documents/documentStore/rows/rowAttribution.js +11 -0
  32. package/stores/documents/documentStore/rows/rowAttribution.js.map +1 -0
  33. package/stores/documents/documentStore/snapshotEquality.js +29 -0
  34. package/stores/documents/documentStore/snapshotEquality.js.map +1 -0
  35. package/stores/documents/documentStore/state.js +1 -28
  36. package/stores/documents/documentStore/state.js.map +1 -1
  37. package/stores/documents/types.d.ts +8 -0
  38. package/stores/documents/types.js.map +1 -1
  39. package/stores/documents/documentStore/rows.js.map +0 -1
@@ -46,6 +46,13 @@ function moveDocumentLinkNote(input) {
46
46
  }
47
47
  return input.note;
48
48
  }
49
+ function openContainerDocument(runtime, documentRuntime, input) {
50
+ return openDocumentStore(runtime.state.domainScope, input.localId, documentRuntime(input.containerId), input.documentId ?? null, input.initialText, input.initialDocumentKind, {
51
+ deferInitialUpdate: input.deferInitialUpdate,
52
+ initialRows: input.initialRows,
53
+ initialStructuredFields: input.initialStructuredFields,
54
+ });
55
+ }
49
56
  function readyExecSql(runtime) {
50
57
  return runtime.infra.dbStatus === "ready" ? runtime.infra.execSql : null;
51
58
  }
@@ -91,11 +98,10 @@ class ContainerContentsService {
91
98
  const runtime = this.workflowRuntime();
92
99
  const resolveProjectionUserKey = createContainerContentsDocumentProjectionUserKeyResolver(runtime);
93
100
  const documentRuntime = (containerId) => createContainerContentsDocumentsRuntime(runtime, containerId);
94
- const openContainerDocument = (input) => openDocumentStore(runtime.state.domainScope, input.localId, documentRuntime(input.containerId), input.documentId ?? null, input.initialText, input.initialDocumentKind, { deferInitialUpdate: input.deferInitialUpdate });
95
101
  const documentLinks = {
96
102
  ...runtime,
97
103
  documentRuntime,
98
- openDocument: openContainerDocument,
104
+ openDocument: (input) => openContainerDocument(runtime, documentRuntime, input),
99
105
  setActiveDocumentContainer: (input) => activateDocumentLink({
100
106
  host: createDocumentLinkHost(documentLinks, input.mergeDocumentSummary),
101
107
  note: input.note,
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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","sourcesContent":["import { DEFAULT_DOCUMENT_KIND } from \"../../data/documents/documentConstants\";\nimport type { DocumentSummary } from \"../../data/documents/documentSummary\";\nimport { inheritPrincipalHistoryProtection } from \"../../data/principals/principalHistoryRuntime\";\nimport {\n type ContainerContentsStore,\n type ContainerContentsStoreOptions,\n getOrCreateContainerContentsStore,\n} from \"../../stores/container-contents\";\nimport { openDocumentStore } from \"../../stores/documents\";\nimport { relinkDocumentStoreWithCommitSideEffect } from \"../../stores/documents/documentStore/internalRelink\";\nimport {\n type DocumentAttributionRangesInput,\n type DocumentAttributionRangesPage,\n loadDocumentAttributionRanges,\n} from \"../../workflows/container-contents/attribution/documentAttributionRanges\";\nimport {\n type ContainerDocumentQueries,\n createContainerDocumentQueriesFromRuntime,\n} from \"../../workflows/container-contents/documentQueries\";\nimport {\n activateDocumentLink,\n addDocumentLink,\n canMutateDocumentLink,\n canMutateLocalDocumentLink,\n type DocumentStructuralMutationHost,\n moveDocumentLink,\n removeDocumentLink,\n} from \"../../workflows/container-contents/documentQueries/documentStructure\";\nimport {\n type BlobInfoInput,\n type BlobInfoList,\n listBlobInfo,\n} from \"../../workflows/container-contents/info/blobInfo\";\nimport {\n type ContainerInfo,\n loadContainerInfo,\n} from \"../../workflows/container-contents/info/containerInfo\";\nimport {\n type DocumentInfo,\n loadDocumentInfo,\n} from \"../../workflows/container-contents/info/documentInfo\";\nimport { createContainerContentsDocumentProjectionUserKeyResolver } from \"../../workflows/container-contents/projectionKeys\";\nimport {\n type ContainerContentsStoreWorkflowRuntime,\n createContainerContentsDocumentsRuntime,\n createContainerContentsStoreWorkflowRuntime,\n} from \"../../workflows/container-contents/runtime\";\nimport { createContainerDocumentObjectSyncState } from \"../../workflows/container-contents/syncState\";\nimport {\n purgeLocalContainerDocument,\n purgeRemoteContainerDocument,\n} from \"../../workflows/container-contents/tombstones/documentPurge\";\nimport type { DocumentsWorkflowRuntime } from \"../../workflows/documents\";\nimport {\n createOrganizationReadModelCoordinator,\n type OrganizationReadModelCoordinator,\n} from \"../organizations/organizationReadModels\";\nimport type {\n InternalRuntime,\n InternalWorkflowRuntimeInput,\n} from \"../runtime/workflowRuntime\";\nimport { discoverContainerDocumentsForRuntime } from \"./documentDiscovery\";\nimport type {\n ContainerContents,\n ContainerDocumentLinks,\n ContainerInfoInput,\n DocumentInfoInput,\n MergeDocumentSummary,\n MoveDocumentToContainerInput,\n OpenContainerDocumentInput,\n} from \"./types\";\n\nexport type {\n ContainerContentsContextValue,\n ContainerContentsStore,\n ContainerContentsStoreOptions,\n ContainerNode,\n} from \"../../stores/container-contents\";\nexport type {\n DocumentAttributionRangesInput,\n DocumentAttributionRangesPage,\n} from \"../../workflows/container-contents/attribution/documentAttributionRanges\";\nexport type {\n ContainerDocumentQueries,\n ContainerDocumentSidebarRow,\n ContainerItemRow,\n ContainerItemSort,\n ContainerItemSortDirection,\n ContainerItemSortKey,\n} from \"../../workflows/container-contents/documentQueries\";\nexport type { SetLinkedContainerIdsForDocument } from \"../../workflows/container-contents/documentQueries/documentStructure\";\nexport type {\n BlobInfo,\n BlobInfoAttachmentKind,\n BlobInfoDocumentReference,\n BlobInfoInput,\n BlobInfoList,\n BlobInfoSort,\n BlobInfoSortDirection,\n BlobInfoSortKey,\n} from \"../../workflows/container-contents/info/blobInfo\";\nexport type {\n ContainerInfo,\n ContainerShareAccessLevel,\n} from \"../../workflows/container-contents/info/containerInfo\";\nexport type { DocumentInfo } from \"../../workflows/container-contents/info/documentInfo\";\nexport type {\n PendingWriteQueueItem,\n PendingWriteQueueItemStatus,\n PendingWriteQueueObjectKind,\n PendingWriteQueueOperation,\n PendingWriteQueueOperationKind,\n PendingWriteQueueOperationStatus,\n} from \"../../workflows/container-contents/pendingWrites\";\nexport type {\n ContainerDocumentObjectSyncState,\n ContainerDocumentObjectSyncStatus,\n} from \"../../workflows/container-contents/syncState\";\nexport type {\n ContainerContents,\n ContainerDocumentLinkInput,\n ContainerDocumentLinks,\n ContainerInfoInput,\n DocumentInfoInput,\n LinkDocumentToContainerInput,\n MergeDocumentSummary,\n MoveDocumentToContainerInput,\n OpenContainerDocumentInput,\n PurgeDocumentInput,\n PurgeDocumentResult,\n SetActiveDocumentContainerInput,\n UnlinkDocumentFromContainerInput,\n} from \"./types\";\n\nexport { createContainerDocumentObjectSyncState };\n\nexport function createContainerContents(\n runtime: InternalRuntime,\n): ContainerContents {\n return new ContainerContentsService(runtime);\n}\n\nfunction createDocumentLinkHost(\n runtime: ContainerDocumentLinks,\n mergeDocumentSummary: MergeDocumentSummary,\n): DocumentStructuralMutationHost<DocumentsWorkflowRuntime> {\n return {\n documentWorkflowRuntime: runtime.documentRuntime,\n mergeDocumentSummary,\n openDocumentStore: (input) => {\n const store = runtime.openDocument({\n containerId: input.containerId,\n documentId: input.documentId,\n localId: input.localId,\n });\n return {\n ...store,\n relink: ({ commitSideEffect, ...relinkInput }) =>\n commitSideEffect\n ? relinkDocumentStoreWithCommitSideEffect(\n store,\n relinkInput,\n commitSideEffect,\n )\n : store.relink(relinkInput),\n };\n },\n };\n}\n\nfunction moveDocumentLinkNote(\n input: Pick<MoveDocumentToContainerInput, \"note\" | \"sourceContainerId\">,\n): DocumentSummary {\n if (\n input.note.documentId &&\n input.sourceContainerId &&\n input.sourceContainerId !== input.note.containerId\n ) {\n return { ...input.note, containerId: input.sourceContainerId };\n }\n\n return input.note;\n}\n\ninterface ContainerInfoOrganizationScope {\n readonly domainScope: InternalWorkflowRuntimeInput[\"state\"][\"domainScope\"];\n readonly organizationId: string;\n readonly userId: string;\n}\n\nfunction readyExecSql(\n runtime: InternalWorkflowRuntimeInput,\n): InternalWorkflowRuntimeInput[\"infra\"][\"execSql\"] | null {\n return runtime.infra.dbStatus === \"ready\" ? runtime.infra.execSql : null;\n}\n\nfunction isActiveContainerInfoOrganizationScope(\n runtime: InternalWorkflowRuntimeInput,\n scope: ContainerInfoOrganizationScope,\n): boolean {\n return (\n runtime.auth.isAuthenticated &&\n runtime.auth.organizationId === scope.organizationId &&\n runtime.auth.userId === scope.userId &&\n runtime.state.domainScope === scope.domainScope\n );\n}\n\nfunction purgeDocumentFromLinks(input: {\n readonly document: Parameters<ContainerDocumentLinks[\"purgeDocument\"]>[0];\n readonly resolveProjectionUserKey: ContainerDocumentLinks[\"resolveProjectionUserKey\"];\n readonly runtime: ContainerDocumentLinks;\n}) {\n const { note } = input.document;\n if (!note.documentId) {\n return purgeLocalContainerDocument({\n noteId: note.id,\n runtime: input.runtime,\n });\n }\n return purgeRemoteContainerDocument({\n documentId: note.documentId,\n documentKind: note.documentKind ?? DEFAULT_DOCUMENT_KIND,\n noteId: note.id,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n runtime: input.runtime,\n });\n}\n\nclass ContainerContentsService implements ContainerContents {\n private readonly organizationReadModels: OrganizationReadModelCoordinator;\n\n constructor(private readonly runtimeService: InternalRuntime) {\n this.organizationReadModels =\n createOrganizationReadModelCoordinator(runtimeService);\n }\n\n openTree(\n options?: ContainerContentsStoreOptions | undefined,\n ): ContainerContentsStore {\n const runtime = this.workflowRuntime();\n const store = getOrCreateContainerContentsStore(\n runtime.state.domainScope,\n runtime,\n options,\n );\n return store;\n }\n\n documentQueries(): ContainerDocumentQueries {\n return createContainerDocumentQueriesFromRuntime(this.workflowRuntime());\n }\n\n documentLinks(): ContainerDocumentLinks {\n const runtime = this.workflowRuntime();\n const resolveProjectionUserKey =\n createContainerContentsDocumentProjectionUserKeyResolver(runtime);\n const documentRuntime = (containerId: string | null) =>\n createContainerContentsDocumentsRuntime(runtime, containerId);\n const openContainerDocument = (input: OpenContainerDocumentInput) =>\n openDocumentStore(\n runtime.state.domainScope,\n input.localId,\n documentRuntime(input.containerId),\n input.documentId ?? null,\n input.initialText,\n input.initialDocumentKind,\n { deferInitialUpdate: input.deferInitialUpdate },\n );\n const documentLinks: ContainerDocumentLinks = {\n ...runtime,\n documentRuntime,\n openDocument: openContainerDocument,\n setActiveDocumentContainer: (input) =>\n activateDocumentLink({\n host: createDocumentLinkHost(\n documentLinks,\n input.mergeDocumentSummary,\n ),\n note: input.note,\n runtime: documentLinks,\n targetContainerId: input.targetContainerId,\n }),\n canMutateDocumentLinks: canMutateDocumentLink(runtime),\n canMutateUnsyncedDocumentLinks: canMutateLocalDocumentLink(runtime),\n linkDocumentToContainer: (input) =>\n addDocumentLink({\n host: createDocumentLinkHost(\n documentLinks,\n input.mergeDocumentSummary,\n ),\n note: input.note,\n runtime: documentLinks,\n scheduleSync: () => this.openTree().requestSync(),\n setLinkedContainerIdsForDocument:\n input.setLinkedContainerIdsForDocument,\n targetContainerId: input.targetContainerId,\n }),\n moveDocumentToContainer: (input) =>\n moveDocumentLink({\n expandNode: input.expandNode,\n host: createDocumentLinkHost(\n documentLinks,\n input.mergeDocumentSummary,\n ),\n note: moveDocumentLinkNote(input),\n replaceLinkedContainers: input.replaceLinkedContainers,\n runtime: documentLinks,\n scheduleSync: () => this.openTree().requestSync(),\n setLinkedContainerIdsForDocument:\n input.setLinkedContainerIdsForDocument,\n targetContainerId: input.targetContainerId,\n }),\n purgeDocument: (document) =>\n purgeDocumentFromLinks({\n document,\n resolveProjectionUserKey,\n runtime: documentLinks,\n }),\n resolveProjectionUserKey,\n unlinkDocumentFromContainer: (input) =>\n removeDocumentLink({\n host: createDocumentLinkHost(\n documentLinks,\n input.mergeDocumentSummary,\n ),\n note: input.note,\n removedContainerId: input.removedContainerId,\n runtime: documentLinks,\n scheduleSync: () => this.openTree().requestSync(),\n setLinkedContainerIdsForDocument:\n input.setLinkedContainerIdsForDocument,\n }),\n };\n\n return inheritPrincipalHistoryProtection(runtime, documentLinks);\n }\n\n discoverContainerDocuments(\n containerId: string,\n ): Promise<ReadonlyArray<DocumentSummary> | null> {\n return discoverContainerDocumentsForRuntime({\n containerId,\n runtimeService: this.runtimeService,\n });\n }\n\n pullDocumentContent(input: {\n containerId: string;\n localId: string;\n documentId?: string | null | undefined;\n }): void {\n const runtime = this.workflowRuntime();\n const store = openDocumentStore(\n runtime.state.domainScope,\n input.localId,\n createContainerContentsDocumentsRuntime(runtime, input.containerId),\n input.documentId ?? null,\n );\n store.requestRemoteSync();\n }\n\n loadContainerInfo(input: ContainerInfoInput): Promise<ContainerInfo> {\n const runtime = this.runtimeService.workflowInput();\n const organizationScope =\n runtime.auth.isAuthenticated &&\n runtime.auth.organizationId &&\n runtime.auth.userId\n ? {\n domainScope: runtime.state.domainScope,\n organizationId: runtime.auth.organizationId,\n userId: runtime.auth.userId,\n }\n : null;\n const cachedContainerProjection =\n input.remoteInfoMode === \"always\"\n ? null\n : this.openTree().getCachedContainerWriterProjection(input.containerId);\n return loadContainerInfo({\n ...input,\n apiClient: runtime.apiClient,\n containerProjection: cachedContainerProjection,\n execSql: readyExecSql(runtime),\n loadOrganizationGroups: async () => {\n if (\n !organizationScope ||\n !isActiveContainerInfoOrganizationScope(\n this.runtimeService.workflowInput(),\n organizationScope,\n )\n ) {\n return [];\n }\n // Organization groups are disposable presentation data. Container\n // writer projections remain the authority for grants and access.\n const projection = await this.organizationReadModels.loadLocal(\n organizationScope.organizationId,\n );\n return isActiveContainerInfoOrganizationScope(\n this.runtimeService.workflowInput(),\n organizationScope,\n )\n ? (projection?.groups ?? [])\n : [];\n },\n parentId: input.parentId ?? null,\n });\n }\n\n loadDocumentInfo(input: DocumentInfoInput): Promise<DocumentInfo> {\n const runtime = this.runtimeService.workflowInput();\n return loadDocumentInfo({\n ...input,\n apiClient: runtime.apiClient,\n execSql: readyExecSql(runtime),\n reportSecurityIncident: runtime.util.reportSecurityIncident,\n });\n }\n\n loadDocumentEditAttribution(\n documentId: string,\n ): ReturnType<ContainerContents[\"loadDocumentEditAttribution\"]> {\n return this.runtimeService\n .workflowInput()\n .apiClient.getDocumentEditAttribution(documentId);\n }\n\n loadDocumentAttributionRanges(\n input: DocumentAttributionRangesInput,\n ): Promise<DocumentAttributionRangesPage> {\n return loadDocumentAttributionRanges({\n apiClient: this.runtimeService.workflowInput().apiClient,\n query: input,\n });\n }\n\n listBlobInfo(input: BlobInfoInput = {}): Promise<BlobInfoList> {\n const runtime = this.runtimeService.workflowInput();\n return listBlobInfo({\n ...input,\n execSql: readyExecSql(runtime),\n });\n }\n\n workflowRuntime(): ContainerContentsStoreWorkflowRuntime {\n return createContainerContentsStoreWorkflowRuntime(\n this.runtimeService.workflowInput(),\n this.runtimeService.adoptRootContainer,\n );\n }\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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","sourcesContent":["import { DEFAULT_DOCUMENT_KIND } from \"../../data/documents/documentConstants\";\nimport type { DocumentSummary } from \"../../data/documents/documentSummary\";\nimport { inheritPrincipalHistoryProtection } from \"../../data/principals/principalHistoryRuntime\";\nimport {\n type ContainerContentsStore,\n type ContainerContentsStoreOptions,\n getOrCreateContainerContentsStore,\n} from \"../../stores/container-contents\";\nimport { openDocumentStore } from \"../../stores/documents\";\nimport { relinkDocumentStoreWithCommitSideEffect } from \"../../stores/documents/documentStore/internalRelink\";\nimport {\n type DocumentAttributionRangesInput,\n type DocumentAttributionRangesPage,\n loadDocumentAttributionRanges,\n} from \"../../workflows/container-contents/attribution/documentAttributionRanges\";\nimport {\n type ContainerDocumentQueries,\n createContainerDocumentQueriesFromRuntime,\n} from \"../../workflows/container-contents/documentQueries\";\nimport {\n activateDocumentLink,\n addDocumentLink,\n canMutateDocumentLink,\n canMutateLocalDocumentLink,\n type DocumentStructuralMutationHost,\n moveDocumentLink,\n removeDocumentLink,\n} from \"../../workflows/container-contents/documentQueries/documentStructure\";\nimport {\n type BlobInfoInput,\n type BlobInfoList,\n listBlobInfo,\n} from \"../../workflows/container-contents/info/blobInfo\";\nimport {\n type ContainerInfo,\n loadContainerInfo,\n} from \"../../workflows/container-contents/info/containerInfo\";\nimport {\n type DocumentInfo,\n loadDocumentInfo,\n} from \"../../workflows/container-contents/info/documentInfo\";\nimport { createContainerContentsDocumentProjectionUserKeyResolver } from \"../../workflows/container-contents/projectionKeys\";\nimport {\n type ContainerContentsStoreWorkflowRuntime,\n createContainerContentsDocumentsRuntime,\n createContainerContentsStoreWorkflowRuntime,\n} from \"../../workflows/container-contents/runtime\";\nimport { createContainerDocumentObjectSyncState } from \"../../workflows/container-contents/syncState\";\nimport {\n purgeLocalContainerDocument,\n purgeRemoteContainerDocument,\n} from \"../../workflows/container-contents/tombstones/documentPurge\";\nimport type { DocumentsWorkflowRuntime } from \"../../workflows/documents\";\nimport {\n createOrganizationReadModelCoordinator,\n type OrganizationReadModelCoordinator,\n} from \"../organizations/organizationReadModels\";\nimport type {\n InternalRuntime,\n InternalWorkflowRuntimeInput,\n} from \"../runtime/workflowRuntime\";\nimport { discoverContainerDocumentsForRuntime } from \"./documentDiscovery\";\nimport type {\n ContainerContents,\n ContainerDocumentLinks,\n ContainerInfoInput,\n DocumentInfoInput,\n MergeDocumentSummary,\n MoveDocumentToContainerInput,\n OpenContainerDocumentInput,\n} from \"./types\";\n\nexport type {\n ContainerContentsContextValue,\n ContainerContentsStore,\n ContainerContentsStoreOptions,\n ContainerNode,\n} from \"../../stores/container-contents\";\nexport type {\n DocumentAttributionRangesInput,\n DocumentAttributionRangesPage,\n} from \"../../workflows/container-contents/attribution/documentAttributionRanges\";\nexport type {\n ContainerDocumentQueries,\n ContainerDocumentSidebarRow,\n ContainerItemRow,\n ContainerItemSort,\n ContainerItemSortDirection,\n ContainerItemSortKey,\n} from \"../../workflows/container-contents/documentQueries\";\nexport type { SetLinkedContainerIdsForDocument } from \"../../workflows/container-contents/documentQueries/documentStructure\";\nexport type {\n BlobInfo,\n BlobInfoAttachmentKind,\n BlobInfoDocumentReference,\n BlobInfoInput,\n BlobInfoList,\n BlobInfoSort,\n BlobInfoSortDirection,\n BlobInfoSortKey,\n} from \"../../workflows/container-contents/info/blobInfo\";\nexport type {\n ContainerInfo,\n ContainerShareAccessLevel,\n} from \"../../workflows/container-contents/info/containerInfo\";\nexport type { DocumentInfo } from \"../../workflows/container-contents/info/documentInfo\";\nexport type {\n PendingWriteQueueItem,\n PendingWriteQueueItemStatus,\n PendingWriteQueueObjectKind,\n PendingWriteQueueOperation,\n PendingWriteQueueOperationKind,\n PendingWriteQueueOperationStatus,\n} from \"../../workflows/container-contents/pendingWrites\";\nexport type {\n ContainerDocumentObjectSyncState,\n ContainerDocumentObjectSyncStatus,\n} from \"../../workflows/container-contents/syncState\";\nexport type {\n ContainerContents,\n ContainerDocumentLinkInput,\n ContainerDocumentLinks,\n ContainerInfoInput,\n DocumentInfoInput,\n LinkDocumentToContainerInput,\n MergeDocumentSummary,\n MoveDocumentToContainerInput,\n OpenContainerDocumentInput,\n PurgeDocumentInput,\n PurgeDocumentResult,\n SetActiveDocumentContainerInput,\n UnlinkDocumentFromContainerInput,\n} from \"./types\";\n\nexport { createContainerDocumentObjectSyncState };\n\nexport function createContainerContents(\n runtime: InternalRuntime,\n): ContainerContents {\n return new ContainerContentsService(runtime);\n}\n\nfunction createDocumentLinkHost(\n runtime: ContainerDocumentLinks,\n mergeDocumentSummary: MergeDocumentSummary,\n): DocumentStructuralMutationHost<DocumentsWorkflowRuntime> {\n return {\n documentWorkflowRuntime: runtime.documentRuntime,\n mergeDocumentSummary,\n openDocumentStore: (input) => {\n const store = runtime.openDocument({\n containerId: input.containerId,\n documentId: input.documentId,\n localId: input.localId,\n });\n return {\n ...store,\n relink: ({ commitSideEffect, ...relinkInput }) =>\n commitSideEffect\n ? relinkDocumentStoreWithCommitSideEffect(\n store,\n relinkInput,\n commitSideEffect,\n )\n : store.relink(relinkInput),\n };\n },\n };\n}\n\nfunction moveDocumentLinkNote(\n input: Pick<MoveDocumentToContainerInput, \"note\" | \"sourceContainerId\">,\n): DocumentSummary {\n if (\n input.note.documentId &&\n input.sourceContainerId &&\n input.sourceContainerId !== input.note.containerId\n ) {\n return { ...input.note, containerId: input.sourceContainerId };\n }\n\n return input.note;\n}\n\ninterface ContainerInfoOrganizationScope {\n readonly domainScope: InternalWorkflowRuntimeInput[\"state\"][\"domainScope\"];\n readonly organizationId: string;\n readonly userId: string;\n}\n\nfunction openContainerDocument(\n runtime: ContainerContentsStoreWorkflowRuntime,\n documentRuntime: (containerId: string | null) => DocumentsWorkflowRuntime,\n input: OpenContainerDocumentInput,\n) {\n return openDocumentStore(\n runtime.state.domainScope,\n input.localId,\n documentRuntime(input.containerId),\n input.documentId ?? null,\n input.initialText,\n input.initialDocumentKind,\n {\n deferInitialUpdate: input.deferInitialUpdate,\n initialRows: input.initialRows,\n initialStructuredFields: input.initialStructuredFields,\n },\n );\n}\n\nfunction readyExecSql(\n runtime: InternalWorkflowRuntimeInput,\n): InternalWorkflowRuntimeInput[\"infra\"][\"execSql\"] | null {\n return runtime.infra.dbStatus === \"ready\" ? runtime.infra.execSql : null;\n}\n\nfunction isActiveContainerInfoOrganizationScope(\n runtime: InternalWorkflowRuntimeInput,\n scope: ContainerInfoOrganizationScope,\n): boolean {\n return (\n runtime.auth.isAuthenticated &&\n runtime.auth.organizationId === scope.organizationId &&\n runtime.auth.userId === scope.userId &&\n runtime.state.domainScope === scope.domainScope\n );\n}\n\nfunction purgeDocumentFromLinks(input: {\n readonly document: Parameters<ContainerDocumentLinks[\"purgeDocument\"]>[0];\n readonly resolveProjectionUserKey: ContainerDocumentLinks[\"resolveProjectionUserKey\"];\n readonly runtime: ContainerDocumentLinks;\n}) {\n const { note } = input.document;\n if (!note.documentId) {\n return purgeLocalContainerDocument({\n noteId: note.id,\n runtime: input.runtime,\n });\n }\n return purgeRemoteContainerDocument({\n documentId: note.documentId,\n documentKind: note.documentKind ?? DEFAULT_DOCUMENT_KIND,\n noteId: note.id,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n runtime: input.runtime,\n });\n}\n\nclass ContainerContentsService implements ContainerContents {\n private readonly organizationReadModels: OrganizationReadModelCoordinator;\n\n constructor(private readonly runtimeService: InternalRuntime) {\n this.organizationReadModels =\n createOrganizationReadModelCoordinator(runtimeService);\n }\n\n openTree(\n options?: ContainerContentsStoreOptions | undefined,\n ): ContainerContentsStore {\n const runtime = this.workflowRuntime();\n const store = getOrCreateContainerContentsStore(\n runtime.state.domainScope,\n runtime,\n options,\n );\n return store;\n }\n\n documentQueries(): ContainerDocumentQueries {\n return createContainerDocumentQueriesFromRuntime(this.workflowRuntime());\n }\n\n documentLinks(): ContainerDocumentLinks {\n const runtime = this.workflowRuntime();\n const resolveProjectionUserKey =\n createContainerContentsDocumentProjectionUserKeyResolver(runtime);\n const documentRuntime = (containerId: string | null) =>\n createContainerContentsDocumentsRuntime(runtime, containerId);\n const documentLinks: ContainerDocumentLinks = {\n ...runtime,\n documentRuntime,\n openDocument: (input) =>\n openContainerDocument(runtime, documentRuntime, input),\n setActiveDocumentContainer: (input) =>\n activateDocumentLink({\n host: createDocumentLinkHost(\n documentLinks,\n input.mergeDocumentSummary,\n ),\n note: input.note,\n runtime: documentLinks,\n targetContainerId: input.targetContainerId,\n }),\n canMutateDocumentLinks: canMutateDocumentLink(runtime),\n canMutateUnsyncedDocumentLinks: canMutateLocalDocumentLink(runtime),\n linkDocumentToContainer: (input) =>\n addDocumentLink({\n host: createDocumentLinkHost(\n documentLinks,\n input.mergeDocumentSummary,\n ),\n note: input.note,\n runtime: documentLinks,\n scheduleSync: () => this.openTree().requestSync(),\n setLinkedContainerIdsForDocument:\n input.setLinkedContainerIdsForDocument,\n targetContainerId: input.targetContainerId,\n }),\n moveDocumentToContainer: (input) =>\n moveDocumentLink({\n expandNode: input.expandNode,\n host: createDocumentLinkHost(\n documentLinks,\n input.mergeDocumentSummary,\n ),\n note: moveDocumentLinkNote(input),\n replaceLinkedContainers: input.replaceLinkedContainers,\n runtime: documentLinks,\n scheduleSync: () => this.openTree().requestSync(),\n setLinkedContainerIdsForDocument:\n input.setLinkedContainerIdsForDocument,\n targetContainerId: input.targetContainerId,\n }),\n purgeDocument: (document) =>\n purgeDocumentFromLinks({\n document,\n resolveProjectionUserKey,\n runtime: documentLinks,\n }),\n resolveProjectionUserKey,\n unlinkDocumentFromContainer: (input) =>\n removeDocumentLink({\n host: createDocumentLinkHost(\n documentLinks,\n input.mergeDocumentSummary,\n ),\n note: input.note,\n removedContainerId: input.removedContainerId,\n runtime: documentLinks,\n scheduleSync: () => this.openTree().requestSync(),\n setLinkedContainerIdsForDocument:\n input.setLinkedContainerIdsForDocument,\n }),\n };\n\n return inheritPrincipalHistoryProtection(runtime, documentLinks);\n }\n\n discoverContainerDocuments(\n containerId: string,\n ): Promise<ReadonlyArray<DocumentSummary> | null> {\n return discoverContainerDocumentsForRuntime({\n containerId,\n runtimeService: this.runtimeService,\n });\n }\n\n pullDocumentContent(input: {\n containerId: string;\n localId: string;\n documentId?: string | null | undefined;\n }): void {\n const runtime = this.workflowRuntime();\n const store = openDocumentStore(\n runtime.state.domainScope,\n input.localId,\n createContainerContentsDocumentsRuntime(runtime, input.containerId),\n input.documentId ?? null,\n );\n store.requestRemoteSync();\n }\n\n loadContainerInfo(input: ContainerInfoInput): Promise<ContainerInfo> {\n const runtime = this.runtimeService.workflowInput();\n const organizationScope =\n runtime.auth.isAuthenticated &&\n runtime.auth.organizationId &&\n runtime.auth.userId\n ? {\n domainScope: runtime.state.domainScope,\n organizationId: runtime.auth.organizationId,\n userId: runtime.auth.userId,\n }\n : null;\n const cachedContainerProjection =\n input.remoteInfoMode === \"always\"\n ? null\n : this.openTree().getCachedContainerWriterProjection(input.containerId);\n return loadContainerInfo({\n ...input,\n apiClient: runtime.apiClient,\n containerProjection: cachedContainerProjection,\n execSql: readyExecSql(runtime),\n loadOrganizationGroups: async () => {\n if (\n !organizationScope ||\n !isActiveContainerInfoOrganizationScope(\n this.runtimeService.workflowInput(),\n organizationScope,\n )\n ) {\n return [];\n }\n // Organization groups are disposable presentation data. Container\n // writer projections remain the authority for grants and access.\n const projection = await this.organizationReadModels.loadLocal(\n organizationScope.organizationId,\n );\n return isActiveContainerInfoOrganizationScope(\n this.runtimeService.workflowInput(),\n organizationScope,\n )\n ? (projection?.groups ?? [])\n : [];\n },\n parentId: input.parentId ?? null,\n });\n }\n\n loadDocumentInfo(input: DocumentInfoInput): Promise<DocumentInfo> {\n const runtime = this.runtimeService.workflowInput();\n return loadDocumentInfo({\n ...input,\n apiClient: runtime.apiClient,\n execSql: readyExecSql(runtime),\n reportSecurityIncident: runtime.util.reportSecurityIncident,\n });\n }\n\n loadDocumentEditAttribution(\n documentId: string,\n ): ReturnType<ContainerContents[\"loadDocumentEditAttribution\"]> {\n return this.runtimeService\n .workflowInput()\n .apiClient.getDocumentEditAttribution(documentId);\n }\n\n loadDocumentAttributionRanges(\n input: DocumentAttributionRangesInput,\n ): Promise<DocumentAttributionRangesPage> {\n return loadDocumentAttributionRanges({\n apiClient: this.runtimeService.workflowInput().apiClient,\n query: input,\n });\n }\n\n listBlobInfo(input: BlobInfoInput = {}): Promise<BlobInfoList> {\n const runtime = this.runtimeService.workflowInput();\n return listBlobInfo({\n ...input,\n execSql: readyExecSql(runtime),\n });\n }\n\n workflowRuntime(): ContainerContentsStoreWorkflowRuntime {\n return createContainerContentsStoreWorkflowRuntime(\n this.runtimeService.workflowInput(),\n this.runtimeService.adoptRootContainer,\n );\n }\n}\n"]}
@@ -2,7 +2,7 @@ import type { DocumentEditAttributionResponse } from "../../internal/validators/
2
2
  import type { StoredDocumentKind } from "../../data/documents/documentKinds.js";
3
3
  import type { DocumentSummary } from "../../data/documents/documentSummary.js";
4
4
  import type { ContainerContentsStore, ContainerContentsStoreOptions, ContainerContentsStoreRuntime } from "../../stores/container-contents/index.js";
5
- import type { DocumentStore } from "../../stores/documents/index.js";
5
+ import type { DocumentStore, DocumentStoreOpenOptions } from "../../stores/documents/index.js";
6
6
  import type { DocumentAttributionRangesInput, DocumentAttributionRangesPage } from "../../workflows/container-contents/attribution/documentAttributionRanges.js";
7
7
  import type { ContainerDocumentQueries } from "../../workflows/container-contents/documentQueries/index.js";
8
8
  import type { SetLinkedContainerIdsForDocument } from "../../workflows/container-contents/documentQueries/documentStructure.js";
@@ -55,6 +55,9 @@ export interface OpenContainerDocumentInput {
55
55
  readonly deferInitialUpdate?: boolean | undefined;
56
56
  readonly documentId?: string | null | undefined;
57
57
  readonly initialDocumentKind?: StoredDocumentKind | undefined;
58
+ /** Birth content of a created record; see `DocumentStoreOpenOptions`. */
59
+ readonly initialRows?: DocumentStoreOpenOptions["initialRows"];
60
+ readonly initialStructuredFields?: DocumentStoreOpenOptions["initialStructuredFields"];
58
61
  readonly initialText?: string | undefined;
59
62
  readonly localId: string;
60
63
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"","sourcesContent":["import type { DocumentEditAttributionResponse } from \"@tearleads/validators/response\";\nimport type { StoredDocumentKind } from \"../../data/documents/documentKinds\";\nimport type { DocumentSummary } from \"../../data/documents/documentSummary\";\nimport type {\n ContainerContentsStore,\n ContainerContentsStoreOptions,\n ContainerContentsStoreRuntime,\n} from \"../../stores/container-contents\";\nimport type { DocumentStore } from \"../../stores/documents\";\nimport type {\n DocumentAttributionRangesInput,\n DocumentAttributionRangesPage,\n} from \"../../workflows/container-contents/attribution/documentAttributionRanges\";\nimport type { ContainerDocumentQueries } from \"../../workflows/container-contents/documentQueries\";\nimport type { SetLinkedContainerIdsForDocument } from \"../../workflows/container-contents/documentQueries/documentStructure\";\nimport type {\n BlobInfoInput,\n BlobInfoList,\n} from \"../../workflows/container-contents/info/blobInfo\";\nimport type {\n ContainerInfo,\n ContainerInfoRemoteMode,\n} from \"../../workflows/container-contents/info/containerInfo\";\nimport type {\n DocumentInfo,\n DocumentInfoRemoteMode,\n} from \"../../workflows/container-contents/info/documentInfo\";\nimport type { ContainerContentsProjectionUserKeyResolver } from \"../../workflows/container-contents/projectionKeys\";\nimport type { ContainerContentsWorkflowRuntime } from \"../../workflows/container-contents/runtime\";\nimport type { DocumentsWorkflowRuntime } from \"../../workflows/documents\";\n\n/**\n * Selects the container to inspect.\n *\n * Container info combines local SQLite timestamps with optional remote writer\n * projection details. Remote details include direct and inherited grants,\n * organization groups, security-path metadata, and sync watermarks for the\n * parent, child-container, and document lanes.\n *\n * Fields:\n * - `containerId`: Container id to inspect.\n * - `parentId`: Known parent id used when the container has not been synced\n * locally yet. Synced local state wins when available.\n * - `remoteInfoMode`: Controls whether remote projection details are fetched.\n */\nexport interface ContainerInfoInput {\n containerId: string;\n parentId?: string | null | undefined;\n remoteInfoMode?: ContainerInfoRemoteMode | undefined;\n}\n\n/**\n * Selects the document to inspect.\n *\n * Document info combines local document state, local and pending attachment\n * rows, and optional remote writer projection details.\n *\n * Fields:\n * - `attributionRequestKey`: Optional freshness generation used to coalesce\n * duplicate attribution reads without joining requests across invalidation.\n * - `localId`: Local document id stored in the client database.\n * - `remoteInfoMode`: Controls whether remote projection details are fetched.\n */\nexport interface DocumentInfoInput {\n attributionRequestKey?: string | undefined;\n localId: string;\n remoteInfoMode?: DocumentInfoRemoteMode | undefined;\n}\n\nexport type MergeDocumentSummary = (nextDocument: DocumentSummary) => void;\n\nexport interface OpenContainerDocumentInput {\n readonly containerId: string | null;\n /** A file attach follows creation and carries the birth; see the store. */\n readonly deferInitialUpdate?: boolean | undefined;\n readonly documentId?: string | null | undefined;\n readonly initialDocumentKind?: StoredDocumentKind | undefined;\n readonly initialText?: string | undefined;\n readonly localId: string;\n}\n\nexport interface ContainerDocumentLinkInput {\n readonly mergeDocumentSummary: MergeDocumentSummary;\n readonly note: DocumentSummary;\n}\n\nexport interface MoveDocumentToContainerInput\n extends ContainerDocumentLinkInput {\n readonly expandNode: (nodeId: string) => void;\n readonly replaceLinkedContainers?: boolean | undefined;\n readonly setLinkedContainerIdsForDocument: SetLinkedContainerIdsForDocument;\n readonly sourceContainerId?: string | null | undefined;\n readonly targetContainerId: string;\n}\n\nexport interface LinkDocumentToContainerInput\n extends ContainerDocumentLinkInput {\n readonly setLinkedContainerIdsForDocument: SetLinkedContainerIdsForDocument;\n readonly targetContainerId: string;\n}\n\nexport interface UnlinkDocumentFromContainerInput\n extends ContainerDocumentLinkInput {\n readonly removedContainerId: string;\n readonly setLinkedContainerIdsForDocument: SetLinkedContainerIdsForDocument;\n}\n\nexport interface SetActiveDocumentContainerInput\n extends ContainerDocumentLinkInput {\n readonly targetContainerId: string;\n}\n\nexport interface PurgeDocumentInput {\n /** The current local summary of the document to destroy. */\n readonly note: DocumentSummary;\n}\n\nexport interface PurgeDocumentResult {\n readonly documentId: string;\n readonly purgedAt: string;\n readonly reclaimedBlobStorageKeys: ReadonlyArray<string>;\n}\n\nexport interface ContainerDocumentLinks\n extends ContainerContentsWorkflowRuntime {\n documentRuntime(containerId: string | null): DocumentsWorkflowRuntime;\n openDocument(input: OpenContainerDocumentInput): DocumentStore;\n setActiveDocumentContainer(\n input: SetActiveDocumentContainerInput,\n ): Promise<DocumentSummary | null>;\n readonly canMutateDocumentLinks: boolean;\n readonly canMutateUnsyncedDocumentLinks: boolean;\n linkDocumentToContainer(\n input: LinkDocumentToContainerInput,\n ): Promise<DocumentSummary | null>;\n moveDocumentToContainer(\n input: MoveDocumentToContainerInput,\n ): Promise<{ linksChanged: boolean; note: DocumentSummary | null }>;\n /**\n * Permanently destroy a local-only document, or submit and verify a signed\n * terminal purge for a remote document. Remote purge requires exactly one\n * remaining container link and returns null on refusal or verification\n * failure.\n */\n purgeDocument(input: PurgeDocumentInput): Promise<PurgeDocumentResult | null>;\n readonly resolveProjectionUserKey: ContainerContentsProjectionUserKeyResolver;\n unlinkDocumentFromContainer(\n input: UnlinkDocumentFromContainerInput,\n ): Promise<DocumentSummary | null>;\n}\n\n/**\n * High-level container-content service for tree state, document lists, document\n * links, discovery, and diagnostics.\n *\n * The facade owns the normal SDK protocol: it supplies the API client,\n * referenced-principal policy cache, local document query helpers, link\n * projection, tombstone handling, and sync watermarks. Consumers that need a\n * custom persistence protocol can call the lower-level workflows directly from\n * `@tearleads/client-sdk`.\n */\nexport interface ContainerContents {\n /**\n * Open the container tree state store for the current SDK runtime.\n *\n * The store is cached per domain scope and created from the current runtime\n * snapshot. Long-lived hosts should call `updateRuntime` after runtime\n * changes, such as from a React effect.\n */\n openTree(\n options?: ContainerContentsStoreOptions | undefined,\n ): ContainerContentsStore;\n\n /**\n * Create local document query helpers for container contents.\n *\n * The facade is bound to the current SDK runtime snapshot, including the\n * active SQLite executor. Recreate it when the SDK runtime version changes.\n */\n documentQueries(): ContainerDocumentQueries;\n\n /**\n * Create the default document-link workflow helper.\n *\n * The returned object includes the current container-contents runtime,\n * the document projection-key resolver, mutation readiness, document store\n * priming, and container document-link mutations. Product stores can pass\n * this bundle around without rebuilding SDK runtime plumbing themselves.\n */\n documentLinks(): ContainerDocumentLinks;\n\n /**\n * Discover remote documents linked to one container.\n *\n * The method pages the remote container-document lane, writes discovered\n * document summaries into local SQLite, replaces the local link projection for\n * each discovered document, applies applicable tombstones, caches referenced\n * principal policies needed by newly visible documents, and advances the\n * container-document watermark after the local apply completes.\n *\n * One call verifies a bounded batch. Pending evidence is durable; a later\n * explicit call or background reconciliation resumes it.\n *\n * Returns the summaries touched by the apply, or `null` when the database or\n * listing is unavailable, a trust reset cancels the pass, or all evidence is\n * pending. Pending evidence may advance the watermark after durable staging.\n *\n * Parameters:\n * - `containerId`: Remote container id whose document lane should be listed.\n */\n discoverContainerDocuments(\n containerId: string,\n ): Promise<ReadonlyArray<DocumentSummary> | null>;\n\n /**\n * Sync the content of a single document that no mini-app has opened.\n *\n * Discovery only records a document's metadata + an empty content shell, and a\n * document's locally authored content is only pushed once its store syncs; both\n * normally happen lazily when a mini-app opens the document. Some documents are\n * never opened yet still need to sync — notably the organization profile\n * document, which lives in an org's Members-granted metadata container and\n * holds the org display name. This opens a transient document store (registered\n * under the container's keys, so it can decrypt) and schedules a remote sync\n * pass. The pass both pushes the store's pending updates and merges + persists\n * any remote body, so the same call lets an owning device publish its profile\n * content and a member device pull it. `documentId` may be omitted; the store\n * then resolves it from the persisted record (the owning device keys the\n * document under a local alias, not its server id).\n */\n pullDocumentContent(input: {\n containerId: string;\n localId: string;\n documentId?: string | null | undefined;\n }): void;\n\n /**\n * Load diagnostic information for one local document.\n *\n * Local details are available when SQLite is ready. Remote details are loaded\n * from the document writer projection according to `remoteInfoMode`; the\n * default is `\"if-synced\"`.\n */\n loadDocumentInfo(input: DocumentInfoInput): Promise<DocumentInfo>;\n\n /**\n * Fetch a synced document's compact edit-attribution segments (peer -> writer\n * intervals) on their own, without the writer-projection/attachment work\n * `loadDocumentInfo` also does. Resolves to `null` on any request failure.\n * Callers must ignore the segments when `truncated` is set — a truncated\n * interval list can drop a peer's segments and mis-resolve it.\n */\n loadDocumentEditAttribution(\n documentId: string,\n ): Promise<DocumentEditAttributionResponse | null>;\n\n /** Load one revision-bound page of detailed per-upload edit attribution. */\n loadDocumentAttributionRanges(\n input: DocumentAttributionRangesInput,\n ): Promise<DocumentAttributionRangesPage>;\n\n /**\n * List local blob projections and pending attachment bytes grouped by blob.\n *\n * This is a reverse lookup query: callers can search by server blob id,\n * local storage key, document id/title, attachment slot, or MIME metadata and\n * then traverse matching blobs back to their owning local documents.\n */\n listBlobInfo(input?: BlobInfoInput | undefined): Promise<BlobInfoList>;\n\n /**\n * Load diagnostic information for one container.\n *\n * Local details include synced timestamps. Remote details are loaded from the\n * container writer projection according to `remoteInfoMode`; the default is\n * `\"always\"`. Pass `parentId` when inspecting a container before its local row\n * has been synced.\n */\n loadContainerInfo(input: ContainerInfoInput): Promise<ContainerInfo>;\n\n /**\n * Create a workflow runtime for advanced container-content workflows.\n *\n * Prefer the high-level methods on this service for the default SDK protocol.\n * Use this when constructing lower-level stores or custom workflows that need\n * access to the current runtime snapshot.\n */\n workflowRuntime(): ContainerContentsStoreRuntime;\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"","sourcesContent":["import type { DocumentEditAttributionResponse } from \"@tearleads/validators/response\";\nimport type { StoredDocumentKind } from \"../../data/documents/documentKinds\";\nimport type { DocumentSummary } from \"../../data/documents/documentSummary\";\nimport type {\n ContainerContentsStore,\n ContainerContentsStoreOptions,\n ContainerContentsStoreRuntime,\n} from \"../../stores/container-contents\";\nimport type {\n DocumentStore,\n DocumentStoreOpenOptions,\n} from \"../../stores/documents\";\nimport type {\n DocumentAttributionRangesInput,\n DocumentAttributionRangesPage,\n} from \"../../workflows/container-contents/attribution/documentAttributionRanges\";\nimport type { ContainerDocumentQueries } from \"../../workflows/container-contents/documentQueries\";\nimport type { SetLinkedContainerIdsForDocument } from \"../../workflows/container-contents/documentQueries/documentStructure\";\nimport type {\n BlobInfoInput,\n BlobInfoList,\n} from \"../../workflows/container-contents/info/blobInfo\";\nimport type {\n ContainerInfo,\n ContainerInfoRemoteMode,\n} from \"../../workflows/container-contents/info/containerInfo\";\nimport type {\n DocumentInfo,\n DocumentInfoRemoteMode,\n} from \"../../workflows/container-contents/info/documentInfo\";\nimport type { ContainerContentsProjectionUserKeyResolver } from \"../../workflows/container-contents/projectionKeys\";\nimport type { ContainerContentsWorkflowRuntime } from \"../../workflows/container-contents/runtime\";\nimport type { DocumentsWorkflowRuntime } from \"../../workflows/documents\";\n\n/**\n * Selects the container to inspect.\n *\n * Container info combines local SQLite timestamps with optional remote writer\n * projection details. Remote details include direct and inherited grants,\n * organization groups, security-path metadata, and sync watermarks for the\n * parent, child-container, and document lanes.\n *\n * Fields:\n * - `containerId`: Container id to inspect.\n * - `parentId`: Known parent id used when the container has not been synced\n * locally yet. Synced local state wins when available.\n * - `remoteInfoMode`: Controls whether remote projection details are fetched.\n */\nexport interface ContainerInfoInput {\n containerId: string;\n parentId?: string | null | undefined;\n remoteInfoMode?: ContainerInfoRemoteMode | undefined;\n}\n\n/**\n * Selects the document to inspect.\n *\n * Document info combines local document state, local and pending attachment\n * rows, and optional remote writer projection details.\n *\n * Fields:\n * - `attributionRequestKey`: Optional freshness generation used to coalesce\n * duplicate attribution reads without joining requests across invalidation.\n * - `localId`: Local document id stored in the client database.\n * - `remoteInfoMode`: Controls whether remote projection details are fetched.\n */\nexport interface DocumentInfoInput {\n attributionRequestKey?: string | undefined;\n localId: string;\n remoteInfoMode?: DocumentInfoRemoteMode | undefined;\n}\n\nexport type MergeDocumentSummary = (nextDocument: DocumentSummary) => void;\n\nexport interface OpenContainerDocumentInput {\n readonly containerId: string | null;\n /** A file attach follows creation and carries the birth; see the store. */\n readonly deferInitialUpdate?: boolean | undefined;\n readonly documentId?: string | null | undefined;\n readonly initialDocumentKind?: StoredDocumentKind | undefined;\n /** Birth content of a created record; see `DocumentStoreOpenOptions`. */\n readonly initialRows?: DocumentStoreOpenOptions[\"initialRows\"];\n readonly initialStructuredFields?: DocumentStoreOpenOptions[\"initialStructuredFields\"];\n readonly initialText?: string | undefined;\n readonly localId: string;\n}\n\nexport interface ContainerDocumentLinkInput {\n readonly mergeDocumentSummary: MergeDocumentSummary;\n readonly note: DocumentSummary;\n}\n\nexport interface MoveDocumentToContainerInput\n extends ContainerDocumentLinkInput {\n readonly expandNode: (nodeId: string) => void;\n readonly replaceLinkedContainers?: boolean | undefined;\n readonly setLinkedContainerIdsForDocument: SetLinkedContainerIdsForDocument;\n readonly sourceContainerId?: string | null | undefined;\n readonly targetContainerId: string;\n}\n\nexport interface LinkDocumentToContainerInput\n extends ContainerDocumentLinkInput {\n readonly setLinkedContainerIdsForDocument: SetLinkedContainerIdsForDocument;\n readonly targetContainerId: string;\n}\n\nexport interface UnlinkDocumentFromContainerInput\n extends ContainerDocumentLinkInput {\n readonly removedContainerId: string;\n readonly setLinkedContainerIdsForDocument: SetLinkedContainerIdsForDocument;\n}\n\nexport interface SetActiveDocumentContainerInput\n extends ContainerDocumentLinkInput {\n readonly targetContainerId: string;\n}\n\nexport interface PurgeDocumentInput {\n /** The current local summary of the document to destroy. */\n readonly note: DocumentSummary;\n}\n\nexport interface PurgeDocumentResult {\n readonly documentId: string;\n readonly purgedAt: string;\n readonly reclaimedBlobStorageKeys: ReadonlyArray<string>;\n}\n\nexport interface ContainerDocumentLinks\n extends ContainerContentsWorkflowRuntime {\n documentRuntime(containerId: string | null): DocumentsWorkflowRuntime;\n openDocument(input: OpenContainerDocumentInput): DocumentStore;\n setActiveDocumentContainer(\n input: SetActiveDocumentContainerInput,\n ): Promise<DocumentSummary | null>;\n readonly canMutateDocumentLinks: boolean;\n readonly canMutateUnsyncedDocumentLinks: boolean;\n linkDocumentToContainer(\n input: LinkDocumentToContainerInput,\n ): Promise<DocumentSummary | null>;\n moveDocumentToContainer(\n input: MoveDocumentToContainerInput,\n ): Promise<{ linksChanged: boolean; note: DocumentSummary | null }>;\n /**\n * Permanently destroy a local-only document, or submit and verify a signed\n * terminal purge for a remote document. Remote purge requires exactly one\n * remaining container link and returns null on refusal or verification\n * failure.\n */\n purgeDocument(input: PurgeDocumentInput): Promise<PurgeDocumentResult | null>;\n readonly resolveProjectionUserKey: ContainerContentsProjectionUserKeyResolver;\n unlinkDocumentFromContainer(\n input: UnlinkDocumentFromContainerInput,\n ): Promise<DocumentSummary | null>;\n}\n\n/**\n * High-level container-content service for tree state, document lists, document\n * links, discovery, and diagnostics.\n *\n * The facade owns the normal SDK protocol: it supplies the API client,\n * referenced-principal policy cache, local document query helpers, link\n * projection, tombstone handling, and sync watermarks. Consumers that need a\n * custom persistence protocol can call the lower-level workflows directly from\n * `@tearleads/client-sdk`.\n */\nexport interface ContainerContents {\n /**\n * Open the container tree state store for the current SDK runtime.\n *\n * The store is cached per domain scope and created from the current runtime\n * snapshot. Long-lived hosts should call `updateRuntime` after runtime\n * changes, such as from a React effect.\n */\n openTree(\n options?: ContainerContentsStoreOptions | undefined,\n ): ContainerContentsStore;\n\n /**\n * Create local document query helpers for container contents.\n *\n * The facade is bound to the current SDK runtime snapshot, including the\n * active SQLite executor. Recreate it when the SDK runtime version changes.\n */\n documentQueries(): ContainerDocumentQueries;\n\n /**\n * Create the default document-link workflow helper.\n *\n * The returned object includes the current container-contents runtime,\n * the document projection-key resolver, mutation readiness, document store\n * priming, and container document-link mutations. Product stores can pass\n * this bundle around without rebuilding SDK runtime plumbing themselves.\n */\n documentLinks(): ContainerDocumentLinks;\n\n /**\n * Discover remote documents linked to one container.\n *\n * The method pages the remote container-document lane, writes discovered\n * document summaries into local SQLite, replaces the local link projection for\n * each discovered document, applies applicable tombstones, caches referenced\n * principal policies needed by newly visible documents, and advances the\n * container-document watermark after the local apply completes.\n *\n * One call verifies a bounded batch. Pending evidence is durable; a later\n * explicit call or background reconciliation resumes it.\n *\n * Returns the summaries touched by the apply, or `null` when the database or\n * listing is unavailable, a trust reset cancels the pass, or all evidence is\n * pending. Pending evidence may advance the watermark after durable staging.\n *\n * Parameters:\n * - `containerId`: Remote container id whose document lane should be listed.\n */\n discoverContainerDocuments(\n containerId: string,\n ): Promise<ReadonlyArray<DocumentSummary> | null>;\n\n /**\n * Sync the content of a single document that no mini-app has opened.\n *\n * Discovery only records a document's metadata + an empty content shell, and a\n * document's locally authored content is only pushed once its store syncs; both\n * normally happen lazily when a mini-app opens the document. Some documents are\n * never opened yet still need to sync — notably the organization profile\n * document, which lives in an org's Members-granted metadata container and\n * holds the org display name. This opens a transient document store (registered\n * under the container's keys, so it can decrypt) and schedules a remote sync\n * pass. The pass both pushes the store's pending updates and merges + persists\n * any remote body, so the same call lets an owning device publish its profile\n * content and a member device pull it. `documentId` may be omitted; the store\n * then resolves it from the persisted record (the owning device keys the\n * document under a local alias, not its server id).\n */\n pullDocumentContent(input: {\n containerId: string;\n localId: string;\n documentId?: string | null | undefined;\n }): void;\n\n /**\n * Load diagnostic information for one local document.\n *\n * Local details are available when SQLite is ready. Remote details are loaded\n * from the document writer projection according to `remoteInfoMode`; the\n * default is `\"if-synced\"`.\n */\n loadDocumentInfo(input: DocumentInfoInput): Promise<DocumentInfo>;\n\n /**\n * Fetch a synced document's compact edit-attribution segments (peer -> writer\n * intervals) on their own, without the writer-projection/attachment work\n * `loadDocumentInfo` also does. Resolves to `null` on any request failure.\n * Callers must ignore the segments when `truncated` is set — a truncated\n * interval list can drop a peer's segments and mis-resolve it.\n */\n loadDocumentEditAttribution(\n documentId: string,\n ): Promise<DocumentEditAttributionResponse | null>;\n\n /** Load one revision-bound page of detailed per-upload edit attribution. */\n loadDocumentAttributionRanges(\n input: DocumentAttributionRangesInput,\n ): Promise<DocumentAttributionRangesPage>;\n\n /**\n * List local blob projections and pending attachment bytes grouped by blob.\n *\n * This is a reverse lookup query: callers can search by server blob id,\n * local storage key, document id/title, attachment slot, or MIME metadata and\n * then traverse matching blobs back to their owning local documents.\n */\n listBlobInfo(input?: BlobInfoInput | undefined): Promise<BlobInfoList>;\n\n /**\n * Load diagnostic information for one container.\n *\n * Local details include synced timestamps. Remote details are loaded from the\n * container writer projection according to `remoteInfoMode`; the default is\n * `\"always\"`. Pass `parentId` when inspecting a container before its local row\n * has been synced.\n */\n loadContainerInfo(input: ContainerInfoInput): Promise<ContainerInfo>;\n\n /**\n * Create a workflow runtime for advanced container-content workflows.\n *\n * Prefer the high-level methods on this service for the default SDK protocol.\n * Use this when constructing lower-level stores or custom workflows that need\n * access to the current runtime snapshot.\n */\n workflowRuntime(): ContainerContentsStoreRuntime;\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import type { StoredDocumentKind } from "../../data/documents/documentKinds.js";
2
2
  import type { DocumentSummaryList, DocumentSummarySort, DocumentSummarySortDirection, DocumentSummarySortKey, ListDocumentSummariesInput } from "../../data/persistence/documents/types.js";
3
- import { DEFAULT_DOCUMENT_ID as DEFAULT_LOCAL_DOCUMENT_ID, type DocumentStore, type DocumentsRuntime, type PersistedDocumentListener } from "../../stores/documents/index.js";
3
+ import { DEFAULT_DOCUMENT_ID as DEFAULT_LOCAL_DOCUMENT_ID, type DocumentStore, type DocumentStoreOpenOptions, type DocumentsRuntime, type PersistedDocumentListener } from "../../stores/documents/index.js";
4
4
  import type { InternalRuntime } from "../runtime/workflowRuntime.js";
5
5
  export type { DocumentAttachmentStatus, DocumentAttachmentUpload, DocumentContextValue, DocumentStore, DocumentsRuntime, PersistedDocumentListener, } from "../../stores/documents/index.js";
6
6
  export type DocumentSortDirection = DocumentSummarySortDirection;
@@ -14,6 +14,9 @@ export interface OpenDocumentInput {
14
14
  readonly containerId?: string | null | undefined;
15
15
  readonly documentId?: string | null | undefined;
16
16
  readonly initialDocumentKind?: StoredDocumentKind | undefined;
17
+ /** Birth content of a created record; see `DocumentStoreOpenOptions`. */
18
+ readonly initialRows?: DocumentStoreOpenOptions["initialRows"];
19
+ readonly initialStructuredFields?: DocumentStoreOpenOptions["initialStructuredFields"];
17
20
  readonly initialText?: string | undefined;
18
21
  readonly localId?: string | undefined;
19
22
  }
@@ -50,9 +50,13 @@ class DocumentsService {
50
50
  return createDocumentsWorkflowRuntime(input);
51
51
  }
52
52
  open(input = {}, options = {}) {
53
- const { containerId, documentId = null, initialDocumentKind = DEFAULT_DOCUMENT_KIND, initialText = "", localId = DEFAULT_LOCAL_DOCUMENT_ID, } = input;
53
+ const { containerId, documentId = null, initialDocumentKind = DEFAULT_DOCUMENT_KIND, initialRows, initialStructuredFields, initialText = "", localId = DEFAULT_LOCAL_DOCUMENT_ID, } = input;
54
54
  const runtime = options.workflowRuntime ?? this.workflowRuntime(containerId);
55
- return openDocumentStore(runtime.state.domainScope, localId, runtime, documentId, initialText, initialDocumentKind, { remoteSyncMode: options.remoteSyncMode });
55
+ return openDocumentStore(runtime.state.domainScope, localId, runtime, documentId, initialText, initialDocumentKind, {
56
+ initialRows,
57
+ initialStructuredFields,
58
+ remoteSyncMode: options.remoteSyncMode,
59
+ });
56
60
  }
57
61
  subscribe(listener, options = {}) {
58
62
  return subscribeToPersistedDocuments(this.dependencies.runtime.workflowInput(options.containerId).state
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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","sourcesContent":["import { DEFAULT_DOCUMENT_KIND } from \"../../data/documents/documentConstants\";\nimport type { StoredDocumentKind } from \"../../data/documents/documentKinds\";\nimport type {\n DocumentSummaryList,\n DocumentSummarySort,\n DocumentSummarySortDirection,\n DocumentSummarySortKey,\n ListDocumentSummariesInput,\n} from \"../../data/persistence/documents/types\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport {\n DEFAULT_DOCUMENT_ID as DEFAULT_LOCAL_DOCUMENT_ID,\n type DocumentStore,\n type DocumentsRuntime,\n openDocumentStore,\n type PersistedDocumentListener,\n subscribeToPersistedDocuments,\n} from \"../../stores/documents\";\nimport { emitPersistedDocumentDeletion } from \"../../stores/documents/registry\";\nimport {\n createDocumentsWorkflowRuntime,\n defaultDocumentsPersistence,\n deletePersistedDocument,\n reclaimDocumentOrphanBlobs,\n} from \"../../workflows/documents\";\nimport type { InternalRuntime } from \"../runtime/workflowRuntime\";\n\nexport type {\n DocumentAttachmentStatus,\n DocumentAttachmentUpload,\n DocumentContextValue,\n DocumentStore,\n DocumentsRuntime,\n PersistedDocumentListener,\n} from \"../../stores/documents\";\n\nexport type DocumentSortDirection = DocumentSummarySortDirection;\nexport type DocumentSortKey = DocumentSummarySortKey;\n\nexport type DocumentSort = DocumentSummarySort;\n\nexport interface ListDocumentsInput extends ListDocumentSummariesInput {}\n\nexport type DocumentList = DocumentSummaryList;\n\nexport { DEFAULT_LOCAL_DOCUMENT_ID as DEFAULT_DOCUMENT_ID };\n\nexport interface OpenDocumentInput {\n readonly containerId?: string | null | undefined;\n readonly documentId?: string | null | undefined;\n readonly initialDocumentKind?: StoredDocumentKind | undefined;\n readonly initialText?: string | undefined;\n readonly localId?: string | undefined;\n}\n\nexport interface OpenDocumentOptions {\n readonly remoteSyncMode?: \"on-demand\" | \"startup\" | undefined;\n readonly workflowRuntime?: DocumentsRuntime | undefined;\n}\n\nexport interface DocumentSubscriptionOptions {\n readonly containerId?: string | null | undefined;\n}\n\nexport interface Documents {\n delete(localId: string): Promise<boolean>;\n findLocalIdByDocumentId(documentId: string): Promise<string | null>;\n list(input?: ListDocumentsInput | undefined): Promise<DocumentList | null>;\n open(\n input?: OpenDocumentInput | undefined,\n options?: OpenDocumentOptions | undefined,\n ): DocumentStore;\n subscribe(\n listener: PersistedDocumentListener,\n options?: DocumentSubscriptionOptions | undefined,\n ): () => void;\n workflowRuntime(containerId?: string | null | undefined): DocumentsRuntime;\n}\n\ninterface DocumentsDependencies {\n getDefaultContainerId: () => string | null;\n runtime: InternalRuntime;\n}\n\nexport function createDocuments(\n dependencies: DocumentsDependencies,\n): Documents {\n return new DocumentsService(dependencies);\n}\n\nclass DocumentsService implements Documents {\n private readonly schemaEnsuresByExecSql = new WeakMap<\n ExecSql,\n Promise<void>\n >();\n\n constructor(private readonly dependencies: DocumentsDependencies) {}\n\n async delete(localId: string): Promise<boolean> {\n const runtime = this.workflowRuntime();\n if (runtime.infra.dbStatus !== \"ready\") {\n return false;\n }\n\n const deleted = await deletePersistedDocument({\n documentProjectors: runtime.infra.documentProjectors,\n execSql: runtime.infra.execSql,\n localId,\n persistence: defaultDocumentsPersistence,\n });\n if (!deleted) return false;\n void reclaimDocumentOrphanBlobs(runtime);\n emitPersistedDocumentDeletion(runtime.state.domainScope, localId);\n return true;\n }\n\n async findLocalIdByDocumentId(documentId: string): Promise<string | null> {\n const runtime = this.dependencies.runtime.workflowInput();\n if (runtime.infra.dbStatus !== \"ready\") {\n return null;\n }\n\n await this.ensureSchema(runtime.infra.execSql);\n return defaultDocumentsPersistence.findLocalIdByDocumentId(\n runtime.infra.execSql,\n documentId,\n );\n }\n\n async list(input: ListDocumentsInput = {}): Promise<DocumentList | null> {\n const runtime = this.dependencies.runtime.workflowInput();\n if (runtime.infra.dbStatus !== \"ready\") {\n return null;\n }\n\n await this.ensureSchema(runtime.infra.execSql);\n return defaultDocumentsPersistence.listDocumentSummaries(\n runtime.infra.execSql,\n input,\n );\n }\n\n workflowRuntime(\n containerId = this.dependencies.getDefaultContainerId(),\n ): DocumentsRuntime {\n const input = this.dependencies.runtime.workflowInput(containerId);\n return createDocumentsWorkflowRuntime(input);\n }\n\n open(\n input: OpenDocumentInput = {},\n options: OpenDocumentOptions = {},\n ): DocumentStore {\n const {\n containerId,\n documentId = null,\n initialDocumentKind = DEFAULT_DOCUMENT_KIND,\n initialText = \"\",\n localId = DEFAULT_LOCAL_DOCUMENT_ID,\n } = input;\n const runtime =\n options.workflowRuntime ?? this.workflowRuntime(containerId);\n return openDocumentStore(\n runtime.state.domainScope,\n localId,\n runtime,\n documentId,\n initialText,\n initialDocumentKind,\n { remoteSyncMode: options.remoteSyncMode },\n );\n }\n\n subscribe(\n listener: PersistedDocumentListener,\n options: DocumentSubscriptionOptions = {},\n ): () => void {\n return subscribeToPersistedDocuments(\n this.dependencies.runtime.workflowInput(options.containerId).state\n .domainScope,\n listener,\n );\n }\n\n private ensureSchema(execSql: ExecSql): Promise<void> {\n const existing = this.schemaEnsuresByExecSql.get(execSql);\n if (existing) {\n return existing;\n }\n\n const ensure = defaultDocumentsPersistence\n .ensureSchema(execSql)\n .catch((error: unknown) => {\n this.schemaEnsuresByExecSql.delete(execSql);\n throw error;\n });\n this.schemaEnsuresByExecSql.set(execSql, ensure);\n return ensure;\n }\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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","sourcesContent":["import { DEFAULT_DOCUMENT_KIND } from \"../../data/documents/documentConstants\";\nimport type { StoredDocumentKind } from \"../../data/documents/documentKinds\";\nimport type {\n DocumentSummaryList,\n DocumentSummarySort,\n DocumentSummarySortDirection,\n DocumentSummarySortKey,\n ListDocumentSummariesInput,\n} from \"../../data/persistence/documents/types\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport {\n DEFAULT_DOCUMENT_ID as DEFAULT_LOCAL_DOCUMENT_ID,\n type DocumentStore,\n type DocumentStoreOpenOptions,\n type DocumentsRuntime,\n openDocumentStore,\n type PersistedDocumentListener,\n subscribeToPersistedDocuments,\n} from \"../../stores/documents\";\nimport { emitPersistedDocumentDeletion } from \"../../stores/documents/registry\";\nimport {\n createDocumentsWorkflowRuntime,\n defaultDocumentsPersistence,\n deletePersistedDocument,\n reclaimDocumentOrphanBlobs,\n} from \"../../workflows/documents\";\nimport type { InternalRuntime } from \"../runtime/workflowRuntime\";\n\nexport type {\n DocumentAttachmentStatus,\n DocumentAttachmentUpload,\n DocumentContextValue,\n DocumentStore,\n DocumentsRuntime,\n PersistedDocumentListener,\n} from \"../../stores/documents\";\n\nexport type DocumentSortDirection = DocumentSummarySortDirection;\nexport type DocumentSortKey = DocumentSummarySortKey;\n\nexport type DocumentSort = DocumentSummarySort;\n\nexport interface ListDocumentsInput extends ListDocumentSummariesInput {}\n\nexport type DocumentList = DocumentSummaryList;\n\nexport { DEFAULT_LOCAL_DOCUMENT_ID as DEFAULT_DOCUMENT_ID };\n\nexport interface OpenDocumentInput {\n readonly containerId?: string | null | undefined;\n readonly documentId?: string | null | undefined;\n readonly initialDocumentKind?: StoredDocumentKind | undefined;\n /** Birth content of a created record; see `DocumentStoreOpenOptions`. */\n readonly initialRows?: DocumentStoreOpenOptions[\"initialRows\"];\n readonly initialStructuredFields?: DocumentStoreOpenOptions[\"initialStructuredFields\"];\n readonly initialText?: string | undefined;\n readonly localId?: string | undefined;\n}\n\nexport interface OpenDocumentOptions {\n readonly remoteSyncMode?: \"on-demand\" | \"startup\" | undefined;\n readonly workflowRuntime?: DocumentsRuntime | undefined;\n}\n\nexport interface DocumentSubscriptionOptions {\n readonly containerId?: string | null | undefined;\n}\n\nexport interface Documents {\n delete(localId: string): Promise<boolean>;\n findLocalIdByDocumentId(documentId: string): Promise<string | null>;\n list(input?: ListDocumentsInput | undefined): Promise<DocumentList | null>;\n open(\n input?: OpenDocumentInput | undefined,\n options?: OpenDocumentOptions | undefined,\n ): DocumentStore;\n subscribe(\n listener: PersistedDocumentListener,\n options?: DocumentSubscriptionOptions | undefined,\n ): () => void;\n workflowRuntime(containerId?: string | null | undefined): DocumentsRuntime;\n}\n\ninterface DocumentsDependencies {\n getDefaultContainerId: () => string | null;\n runtime: InternalRuntime;\n}\n\nexport function createDocuments(\n dependencies: DocumentsDependencies,\n): Documents {\n return new DocumentsService(dependencies);\n}\n\nclass DocumentsService implements Documents {\n private readonly schemaEnsuresByExecSql = new WeakMap<\n ExecSql,\n Promise<void>\n >();\n\n constructor(private readonly dependencies: DocumentsDependencies) {}\n\n async delete(localId: string): Promise<boolean> {\n const runtime = this.workflowRuntime();\n if (runtime.infra.dbStatus !== \"ready\") {\n return false;\n }\n\n const deleted = await deletePersistedDocument({\n documentProjectors: runtime.infra.documentProjectors,\n execSql: runtime.infra.execSql,\n localId,\n persistence: defaultDocumentsPersistence,\n });\n if (!deleted) return false;\n void reclaimDocumentOrphanBlobs(runtime);\n emitPersistedDocumentDeletion(runtime.state.domainScope, localId);\n return true;\n }\n\n async findLocalIdByDocumentId(documentId: string): Promise<string | null> {\n const runtime = this.dependencies.runtime.workflowInput();\n if (runtime.infra.dbStatus !== \"ready\") {\n return null;\n }\n\n await this.ensureSchema(runtime.infra.execSql);\n return defaultDocumentsPersistence.findLocalIdByDocumentId(\n runtime.infra.execSql,\n documentId,\n );\n }\n\n async list(input: ListDocumentsInput = {}): Promise<DocumentList | null> {\n const runtime = this.dependencies.runtime.workflowInput();\n if (runtime.infra.dbStatus !== \"ready\") {\n return null;\n }\n\n await this.ensureSchema(runtime.infra.execSql);\n return defaultDocumentsPersistence.listDocumentSummaries(\n runtime.infra.execSql,\n input,\n );\n }\n\n workflowRuntime(\n containerId = this.dependencies.getDefaultContainerId(),\n ): DocumentsRuntime {\n const input = this.dependencies.runtime.workflowInput(containerId);\n return createDocumentsWorkflowRuntime(input);\n }\n\n open(\n input: OpenDocumentInput = {},\n options: OpenDocumentOptions = {},\n ): DocumentStore {\n const {\n containerId,\n documentId = null,\n initialDocumentKind = DEFAULT_DOCUMENT_KIND,\n initialRows,\n initialStructuredFields,\n initialText = \"\",\n localId = DEFAULT_LOCAL_DOCUMENT_ID,\n } = input;\n const runtime =\n options.workflowRuntime ?? this.workflowRuntime(containerId);\n return openDocumentStore(\n runtime.state.domainScope,\n localId,\n runtime,\n documentId,\n initialText,\n initialDocumentKind,\n {\n initialRows,\n initialStructuredFields,\n remoteSyncMode: options.remoteSyncMode,\n },\n );\n }\n\n subscribe(\n listener: PersistedDocumentListener,\n options: DocumentSubscriptionOptions = {},\n ): () => void {\n return subscribeToPersistedDocuments(\n this.dependencies.runtime.workflowInput(options.containerId).state\n .domainScope,\n listener,\n );\n }\n\n private ensureSchema(execSql: ExecSql): Promise<void> {\n const existing = this.schemaEnsuresByExecSql.get(execSql);\n if (existing) {\n return existing;\n }\n\n const ensure = defaultDocumentsPersistence\n .ensureSchema(execSql)\n .catch((error: unknown) => {\n this.schemaEnsuresByExecSql.delete(execSql);\n throw error;\n });\n this.schemaEnsuresByExecSql.set(execSql, ensure);\n return ensure;\n }\n}\n"]}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * On-device timing marks for the DevTools Performance panel. Nothing here
3
+ * leaves the device: entries reach only a locally recorded trace.
4
+ */
5
+ const USER_TIMING_TRACK_GROUP = "Tearleads";
6
+ /** Monotonic milliseconds on the same clock as recorded entries. */
7
+ export function readUserTimingClock() {
8
+ return typeof globalThis.performance?.now === "function"
9
+ ? globalThis.performance.now()
10
+ : Date.now();
11
+ }
12
+ /**
13
+ * Records one measure for a running trace, then clears it from the timeline
14
+ * buffer at once: DevTools captures the measure when it is created, while an
15
+ * uncleared buffer would grow for the whole session.
16
+ */
17
+ export function recordUserTimingEntry(entry) {
18
+ try {
19
+ const performance = globalThis.performance;
20
+ if (typeof performance?.measure !== "function") {
21
+ return;
22
+ }
23
+ performance.measure(entry.name, {
24
+ detail: {
25
+ devtools: {
26
+ color: entry.failed ? "error" : "primary",
27
+ dataType: "track-entry",
28
+ properties: entry.properties ?? [],
29
+ track: entry.track,
30
+ trackGroup: USER_TIMING_TRACK_GROUP,
31
+ },
32
+ },
33
+ end: entry.endMs,
34
+ start: entry.startMs,
35
+ });
36
+ performance.clearMeasures(entry.name);
37
+ }
38
+ catch {
39
+ // Diagnostics must never change a sync or SQL outcome.
40
+ }
41
+ }
42
+ //# sourceMappingURL=userTiming.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"userTiming.js","sourceRoot":"","sources":["userTiming.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAYH,MAAM,uBAAuB,GAAG,WAAW,CAAC;AAE5C,oEAAoE;AACpE,MAAM,UAAU,mBAAmB;IACjC,OAAO,OAAO,UAAU,CAAC,WAAW,EAAE,GAAG,KAAK,UAAU;QACtD,CAAC,CAAC,UAAU,CAAC,WAAW,CAAC,GAAG,EAAE;QAC9B,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;AACjB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAsB;IAC1D,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,UAAU,CAAC,WAAW,CAAC;QAC3C,IAAI,OAAO,WAAW,EAAE,OAAO,KAAK,UAAU,EAAE,CAAC;YAC/C,OAAO;QACT,CAAC;QACD,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE;YAC9B,MAAM,EAAE;gBACN,QAAQ,EAAE;oBACR,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;oBACzC,QAAQ,EAAE,aAAa;oBACvB,UAAU,EAAE,KAAK,CAAC,UAAU,IAAI,EAAE;oBAClC,KAAK,EAAE,KAAK,CAAC,KAAK;oBAClB,UAAU,EAAE,uBAAuB;iBACpC;aACF;YACD,GAAG,EAAE,KAAK,CAAC,KAAK;YAChB,KAAK,EAAE,KAAK,CAAC,OAAO;SACrB,CAAC,CAAC;QACH,WAAW,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,uDAAuD;IACzD,CAAC;AACH,CAAC","sourcesContent":["/**\n * On-device timing marks for the DevTools Performance panel. Nothing here\n * leaves the device: entries reach only a locally recorded trace.\n */\n\nexport interface UserTimingEntry {\n readonly name: string;\n /** The DevTools track the entry is drawn on, under the Tearleads group. */\n readonly track: string;\n readonly startMs: number;\n readonly endMs: number;\n readonly failed?: boolean | undefined;\n readonly properties?: ReadonlyArray<readonly [string, string]> | undefined;\n}\n\nconst USER_TIMING_TRACK_GROUP = \"Tearleads\";\n\n/** Monotonic milliseconds on the same clock as recorded entries. */\nexport function readUserTimingClock(): number {\n return typeof globalThis.performance?.now === \"function\"\n ? globalThis.performance.now()\n : Date.now();\n}\n\n/**\n * Records one measure for a running trace, then clears it from the timeline\n * buffer at once: DevTools captures the measure when it is created, while an\n * uncleared buffer would grow for the whole session.\n */\nexport function recordUserTimingEntry(entry: UserTimingEntry): void {\n try {\n const performance = globalThis.performance;\n if (typeof performance?.measure !== \"function\") {\n return;\n }\n performance.measure(entry.name, {\n detail: {\n devtools: {\n color: entry.failed ? \"error\" : \"primary\",\n dataType: \"track-entry\",\n properties: entry.properties ?? [],\n track: entry.track,\n trackGroup: USER_TIMING_TRACK_GROUP,\n },\n },\n end: entry.endMs,\n start: entry.startMs,\n });\n performance.clearMeasures(entry.name);\n } catch {\n // Diagnostics must never change a sync or SQL outcome.\n }\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import { readUserTimingClock, recordUserTimingEntry, } from "../shared/userTiming.js";
1
2
  export const unavailableExecSql = async () => {
2
3
  throw new Error("Database client is unavailable.");
3
4
  };
@@ -92,27 +93,50 @@ function createSerializedSqlExec(execSql) {
92
93
  // Nested callers must keep passing the provided locked executor. Re-entering
93
94
  // with the original canonical executor will wait on the current mutation and
94
95
  // deadlock.
96
+ // Each outermost mutation is drawn on DevTools tracks: time spent queued
97
+ // behind another mutation, then time holding the lock.
95
98
  export async function runSerializedSqlMutation(execSql, operation) {
96
99
  if (isSerializedSqlExec(execSql)) {
97
100
  return operation(execSql);
98
101
  }
99
- const previous = sqlMutationQueue.get(execSql) ?? Promise.resolve();
102
+ const queuedAtMs = readUserTimingClock();
103
+ const previous = sqlMutationQueue.get(execSql);
100
104
  let releaseCurrent = () => { };
101
105
  const current = new Promise((resolve) => {
102
106
  releaseCurrent = resolve;
103
107
  });
104
- const waitForPrevious = previous.catch(() => undefined);
108
+ const waitForPrevious = (previous ?? Promise.resolve()).catch(() => undefined);
105
109
  const queuedCurrent = waitForPrevious.then(() => current);
106
110
  sqlMutationQueue.set(execSql, queuedCurrent);
107
111
  await waitForPrevious;
112
+ const acquiredAtMs = readUserTimingClock();
113
+ if (previous) {
114
+ recordUserTimingEntry({
115
+ endMs: acquiredAtMs,
116
+ name: "SQLite mutation wait",
117
+ startMs: queuedAtMs,
118
+ track: "SQLite mutation queue",
119
+ });
120
+ }
121
+ let failed = true;
108
122
  try {
109
- return await operation(createSerializedSqlExec(execSql));
123
+ const result = await operation(createSerializedSqlExec(execSql));
124
+ failed = false;
125
+ return result;
110
126
  }
111
127
  finally {
128
+ const releasedAtMs = readUserTimingClock();
112
129
  releaseCurrent();
113
130
  if (sqlMutationQueue.get(execSql) === queuedCurrent) {
114
131
  sqlMutationQueue.delete(execSql);
115
132
  }
133
+ recordUserTimingEntry({
134
+ endMs: releasedAtMs,
135
+ failed,
136
+ name: "SQLite mutation",
137
+ startMs: acquiredAtMs,
138
+ track: "SQLite mutations",
139
+ });
116
140
  }
117
141
  }
118
142
  //# sourceMappingURL=sqlExec.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sqlExec.js","sourceRoot":"","sources":["sqlExec.ts"],"names":[],"mappings":"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","sourcesContent":["export type SqlRowValue = string | number | null;\nexport type SqlRow = Record<string, SqlRowValue>;\nexport type SqlArrayRow = SqlRowValue[];\nexport type SqlBind = Record<string, SqlRowValue> | ReadonlyArray<SqlRowValue>;\nexport type SqlRowMode = \"object\" | \"array\";\n\nexport interface ExecSql {\n (\n sql: string,\n bind?: SqlBind,\n options?: { rowMode?: \"object\" },\n ): Promise<SqlRow[]>;\n (\n sql: string,\n bind: SqlBind | undefined,\n options: { rowMode: \"array\" },\n ): Promise<SqlArrayRow[]>;\n (\n sql: string,\n bind?: SqlBind,\n options?: { rowMode?: SqlRowMode },\n ): Promise<Array<SqlRow | SqlArrayRow>>;\n}\n\nexport interface ExecSqlClientLike {\n exec(options: {\n sql: string;\n bind?: SqlBind;\n rowMode?: SqlRowMode;\n }): Promise<{ rows: Array<SqlRow | SqlArrayRow> }>;\n}\n\nexport const unavailableExecSql: ExecSql = async () => {\n throw new Error(\"Database client is unavailable.\");\n};\n\n// Tracks the active serialized mutation chain for each canonical SQL executor\n// so callers sharing one connection cannot interleave transactional statements.\nconst sqlMutationQueue = new WeakMap<ExecSql, Promise<void>>();\n\n// Marks executors that already run inside the shared mutation lock so nested\n// callers can reuse the current lock instead of queueing a second time.\nconst serializedSqlExecs = new WeakSet<ExecSql>();\n\n// Reuses one ExecSql adapter per client so all wrappers around the same\n// connection share the same serialized mutation queue.\nconst clientExecSqls = new WeakMap<ExecSqlClientLike, ExecSql>();\n\n// Maps each locked executor back to the canonical executor whose lock it runs\n// under, so per-connection caches key on one stable identity no matter which\n// wrapper a caller holds.\nconst serializedSqlExecCanonicals = new WeakMap<ExecSql, ExecSql>();\n\nexport function resolveCanonicalExecSql(execSql: ExecSql): ExecSql {\n return serializedSqlExecCanonicals.get(execSql) ?? execSql;\n}\n\n// Completed once-per-connection keys (schema ensures).\n// Only COMPLETED runs are recorded — never in-flight promises — so two lock\n// contexts racing the same key both run the (idempotent) work instead of one\n// awaiting a promise that can only settle after the lock the other context is\n// already holding.\nconst completedConnectionOnceKeys = new WeakMap<ExecSql, Set<string>>();\n\nexport function hasCompletedConnectionOnce(\n execSql: ExecSql,\n key: string,\n): boolean {\n return (\n completedConnectionOnceKeys\n .get(resolveCanonicalExecSql(execSql))\n ?.has(key) ?? false\n );\n}\n\nexport function markCompletedConnectionOnce(\n execSql: ExecSql,\n key: string,\n): void {\n const canonical = resolveCanonicalExecSql(execSql);\n const keys = completedConnectionOnceKeys.get(canonical) ?? new Set<string>();\n keys.add(key);\n completedConnectionOnceKeys.set(canonical, keys);\n}\n\n// Callers must not invoke this inside an explicit SQL transaction that can\n// roll back: completion is recorded as soon as `run` resolves, so a later\n// ROLLBACK would leave the memo asserting schema that no longer exists.\nexport async function runOncePerConnection(\n execSql: ExecSql,\n key: string,\n run: () => Promise<void>,\n): Promise<void> {\n if (hasCompletedConnectionOnce(execSql, key)) {\n return;\n }\n await run();\n markCompletedConnectionOnce(execSql, key);\n}\n\n/**\n * Forget every completed once-per-connection key for this connection. Required\n * after an operation that rebuilds the schema out from under the runtime (the\n * local backup restore drops and recreates all user tables) so the next query\n * re-runs its schema ensures.\n */\nexport function resetConnectionSchemaMemo(execSql: ExecSql): void {\n completedConnectionOnceKeys.delete(resolveCanonicalExecSql(execSql));\n}\n\nfunction defineExecSql(\n run: (\n sql: string,\n bind?: SqlBind,\n options?: { rowMode?: SqlRowMode },\n ) => Promise<Array<SqlRow | SqlArrayRow>>,\n): ExecSql {\n function execSql(\n sql: string,\n bind?: SqlBind,\n options?: { rowMode?: \"object\" },\n ): Promise<SqlRow[]>;\n function execSql(\n sql: string,\n bind: SqlBind | undefined,\n options: { rowMode: \"array\" },\n ): Promise<SqlArrayRow[]>;\n function execSql(\n sql: string,\n bind?: SqlBind,\n options?: { rowMode?: SqlRowMode },\n ): Promise<Array<SqlRow | SqlArrayRow>>;\n async function execSql(\n sql: string,\n bind?: SqlBind,\n options?: { rowMode?: SqlRowMode },\n ): Promise<Array<SqlRow | SqlArrayRow>> {\n return run(sql, bind, options);\n }\n\n return execSql;\n}\n\nexport function createExecSql(client: ExecSqlClientLike): ExecSql {\n const existingExecSql = clientExecSqls.get(client);\n if (existingExecSql) {\n return existingExecSql;\n }\n\n const execSql = defineExecSql(async (sql, bind, options) => {\n const result = await client.exec({\n sql,\n ...(bind !== undefined ? { bind } : {}),\n ...(options?.rowMode ? { rowMode: options.rowMode } : {}),\n });\n return result.rows;\n });\n\n clientExecSqls.set(client, execSql);\n return execSql;\n}\n\nfunction isSerializedSqlExec(execSql: ExecSql): boolean {\n return serializedSqlExecs.has(execSql);\n}\n\nfunction createSerializedSqlExec(execSql: ExecSql): ExecSql {\n if (isSerializedSqlExec(execSql)) {\n return execSql;\n }\n\n const serializedExecSql = defineExecSql(execSql);\n serializedSqlExecs.add(serializedExecSql);\n serializedSqlExecCanonicals.set(\n serializedExecSql,\n resolveCanonicalExecSql(execSql),\n );\n return serializedExecSql;\n}\n\n// SQLite transactions are scoped to the shared connection, so we must hold a\n// connection-level lock across multi-statement mutations to prevent interleaving.\n// Nested callers must keep passing the provided locked executor. Re-entering\n// with the original canonical executor will wait on the current mutation and\n// deadlock.\nexport async function runSerializedSqlMutation<T>(\n execSql: ExecSql,\n operation: (execSql: ExecSql) => Promise<T> | T,\n): Promise<T> {\n if (isSerializedSqlExec(execSql)) {\n return operation(execSql);\n }\n\n const previous = sqlMutationQueue.get(execSql) ?? Promise.resolve();\n let releaseCurrent = () => {};\n const current = new Promise<void>((resolve) => {\n releaseCurrent = resolve;\n });\n const waitForPrevious = previous.catch(() => undefined);\n const queuedCurrent = waitForPrevious.then(() => current);\n\n sqlMutationQueue.set(execSql, queuedCurrent);\n await waitForPrevious;\n\n try {\n return await operation(createSerializedSqlExec(execSql));\n } finally {\n releaseCurrent();\n if (sqlMutationQueue.get(execSql) === queuedCurrent) {\n sqlMutationQueue.delete(execSql);\n }\n }\n}\n"]}
1
+ {"version":3,"file":"sqlExec.js","sourceRoot":"","sources":["sqlExec.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n readUserTimingClock,\n recordUserTimingEntry,\n} from \"../shared/userTiming\";\n\nexport type SqlRowValue = string | number | null;\nexport type SqlRow = Record<string, SqlRowValue>;\nexport type SqlArrayRow = SqlRowValue[];\nexport type SqlBind = Record<string, SqlRowValue> | ReadonlyArray<SqlRowValue>;\nexport type SqlRowMode = \"object\" | \"array\";\n\nexport interface ExecSql {\n (\n sql: string,\n bind?: SqlBind,\n options?: { rowMode?: \"object\" },\n ): Promise<SqlRow[]>;\n (\n sql: string,\n bind: SqlBind | undefined,\n options: { rowMode: \"array\" },\n ): Promise<SqlArrayRow[]>;\n (\n sql: string,\n bind?: SqlBind,\n options?: { rowMode?: SqlRowMode },\n ): Promise<Array<SqlRow | SqlArrayRow>>;\n}\n\nexport interface ExecSqlClientLike {\n exec(options: {\n sql: string;\n bind?: SqlBind;\n rowMode?: SqlRowMode;\n }): Promise<{ rows: Array<SqlRow | SqlArrayRow> }>;\n}\n\nexport const unavailableExecSql: ExecSql = async () => {\n throw new Error(\"Database client is unavailable.\");\n};\n\n// Tracks the active serialized mutation chain for each canonical SQL executor\n// so callers sharing one connection cannot interleave transactional statements.\nconst sqlMutationQueue = new WeakMap<ExecSql, Promise<void>>();\n\n// Marks executors that already run inside the shared mutation lock so nested\n// callers can reuse the current lock instead of queueing a second time.\nconst serializedSqlExecs = new WeakSet<ExecSql>();\n\n// Reuses one ExecSql adapter per client so all wrappers around the same\n// connection share the same serialized mutation queue.\nconst clientExecSqls = new WeakMap<ExecSqlClientLike, ExecSql>();\n\n// Maps each locked executor back to the canonical executor whose lock it runs\n// under, so per-connection caches key on one stable identity no matter which\n// wrapper a caller holds.\nconst serializedSqlExecCanonicals = new WeakMap<ExecSql, ExecSql>();\n\nexport function resolveCanonicalExecSql(execSql: ExecSql): ExecSql {\n return serializedSqlExecCanonicals.get(execSql) ?? execSql;\n}\n\n// Completed once-per-connection keys (schema ensures).\n// Only COMPLETED runs are recorded — never in-flight promises — so two lock\n// contexts racing the same key both run the (idempotent) work instead of one\n// awaiting a promise that can only settle after the lock the other context is\n// already holding.\nconst completedConnectionOnceKeys = new WeakMap<ExecSql, Set<string>>();\n\nexport function hasCompletedConnectionOnce(\n execSql: ExecSql,\n key: string,\n): boolean {\n return (\n completedConnectionOnceKeys\n .get(resolveCanonicalExecSql(execSql))\n ?.has(key) ?? false\n );\n}\n\nexport function markCompletedConnectionOnce(\n execSql: ExecSql,\n key: string,\n): void {\n const canonical = resolveCanonicalExecSql(execSql);\n const keys = completedConnectionOnceKeys.get(canonical) ?? new Set<string>();\n keys.add(key);\n completedConnectionOnceKeys.set(canonical, keys);\n}\n\n// Callers must not invoke this inside an explicit SQL transaction that can\n// roll back: completion is recorded as soon as `run` resolves, so a later\n// ROLLBACK would leave the memo asserting schema that no longer exists.\nexport async function runOncePerConnection(\n execSql: ExecSql,\n key: string,\n run: () => Promise<void>,\n): Promise<void> {\n if (hasCompletedConnectionOnce(execSql, key)) {\n return;\n }\n await run();\n markCompletedConnectionOnce(execSql, key);\n}\n\n/**\n * Forget every completed once-per-connection key for this connection. Required\n * after an operation that rebuilds the schema out from under the runtime (the\n * local backup restore drops and recreates all user tables) so the next query\n * re-runs its schema ensures.\n */\nexport function resetConnectionSchemaMemo(execSql: ExecSql): void {\n completedConnectionOnceKeys.delete(resolveCanonicalExecSql(execSql));\n}\n\nfunction defineExecSql(\n run: (\n sql: string,\n bind?: SqlBind,\n options?: { rowMode?: SqlRowMode },\n ) => Promise<Array<SqlRow | SqlArrayRow>>,\n): ExecSql {\n function execSql(\n sql: string,\n bind?: SqlBind,\n options?: { rowMode?: \"object\" },\n ): Promise<SqlRow[]>;\n function execSql(\n sql: string,\n bind: SqlBind | undefined,\n options: { rowMode: \"array\" },\n ): Promise<SqlArrayRow[]>;\n function execSql(\n sql: string,\n bind?: SqlBind,\n options?: { rowMode?: SqlRowMode },\n ): Promise<Array<SqlRow | SqlArrayRow>>;\n async function execSql(\n sql: string,\n bind?: SqlBind,\n options?: { rowMode?: SqlRowMode },\n ): Promise<Array<SqlRow | SqlArrayRow>> {\n return run(sql, bind, options);\n }\n\n return execSql;\n}\n\nexport function createExecSql(client: ExecSqlClientLike): ExecSql {\n const existingExecSql = clientExecSqls.get(client);\n if (existingExecSql) {\n return existingExecSql;\n }\n\n const execSql = defineExecSql(async (sql, bind, options) => {\n const result = await client.exec({\n sql,\n ...(bind !== undefined ? { bind } : {}),\n ...(options?.rowMode ? { rowMode: options.rowMode } : {}),\n });\n return result.rows;\n });\n\n clientExecSqls.set(client, execSql);\n return execSql;\n}\n\nfunction isSerializedSqlExec(execSql: ExecSql): boolean {\n return serializedSqlExecs.has(execSql);\n}\n\nfunction createSerializedSqlExec(execSql: ExecSql): ExecSql {\n if (isSerializedSqlExec(execSql)) {\n return execSql;\n }\n\n const serializedExecSql = defineExecSql(execSql);\n serializedSqlExecs.add(serializedExecSql);\n serializedSqlExecCanonicals.set(\n serializedExecSql,\n resolveCanonicalExecSql(execSql),\n );\n return serializedExecSql;\n}\n\n// SQLite transactions are scoped to the shared connection, so we must hold a\n// connection-level lock across multi-statement mutations to prevent interleaving.\n// Nested callers must keep passing the provided locked executor. Re-entering\n// with the original canonical executor will wait on the current mutation and\n// deadlock.\n// Each outermost mutation is drawn on DevTools tracks: time spent queued\n// behind another mutation, then time holding the lock.\nexport async function runSerializedSqlMutation<T>(\n execSql: ExecSql,\n operation: (execSql: ExecSql) => Promise<T> | T,\n): Promise<T> {\n if (isSerializedSqlExec(execSql)) {\n return operation(execSql);\n }\n\n const queuedAtMs = readUserTimingClock();\n const previous = sqlMutationQueue.get(execSql);\n let releaseCurrent = () => {};\n const current = new Promise<void>((resolve) => {\n releaseCurrent = resolve;\n });\n const waitForPrevious = (previous ?? Promise.resolve()).catch(\n () => undefined,\n );\n const queuedCurrent = waitForPrevious.then(() => current);\n\n sqlMutationQueue.set(execSql, queuedCurrent);\n await waitForPrevious;\n const acquiredAtMs = readUserTimingClock();\n if (previous) {\n recordUserTimingEntry({\n endMs: acquiredAtMs,\n name: \"SQLite mutation wait\",\n startMs: queuedAtMs,\n track: \"SQLite mutation queue\",\n });\n }\n\n let failed = true;\n try {\n const result = await operation(createSerializedSqlExec(execSql));\n failed = false;\n return result;\n } finally {\n const releasedAtMs = readUserTimingClock();\n releaseCurrent();\n if (sqlMutationQueue.get(execSql) === queuedCurrent) {\n sqlMutationQueue.delete(execSql);\n }\n recordUserTimingEntry({\n endMs: releasedAtMs,\n failed,\n name: \"SQLite mutation\",\n startMs: acquiredAtMs,\n track: \"SQLite mutations\",\n });\n }\n}\n"]}
@@ -1,5 +1,6 @@
1
+ import { readUserTimingClock, recordUserTimingEntry, } from "../shared/userTiming.js";
1
2
  import { describeSyncLaneError, publishSyncCoordinatorSnapshot, } from "./coordinatorState.js";
2
- import { createSyncTimestamp } from "./syncTelemetry.js";
3
+ import { addSyncLaneRunDuration, createSyncTimestamp } from "./syncTelemetry.js";
3
4
  const SYNC_LANE_WATCHDOG_MS = 120_000;
4
5
  const FAILED_LANE_REARM_BACKOFF_MS = 1000;
5
6
  // Keyed on the registered config so a discarded lane is collectable.
@@ -72,13 +73,33 @@ function recordSyncLaneRunResult(lane, runResult) {
72
73
  lane.lastError = null;
73
74
  }
74
75
  }
76
+ // Times a settled run and draws it on the DevTools "Sync lanes" track. A
77
+ // watchdog verdict is not a settlement and records nothing: the abandoned run
78
+ // is timed when its late result arrives.
79
+ function recordSyncLaneRunTiming(lane, startedAtMs, runResult, abandoned) {
80
+ const endedAtMs = readUserTimingClock();
81
+ lane.runDurations = addSyncLaneRunDuration(lane.runDurations, endedAtMs - startedAtMs);
82
+ recordUserTimingEntry({
83
+ endMs: endedAtMs,
84
+ failed: runResult.status === "failed",
85
+ name: `Sync lane: ${lane.config.label ?? lane.key}`,
86
+ properties: [
87
+ ["phase", lane.config.phase ?? "document"],
88
+ ["outcome", runResult.status],
89
+ ["watchdog", abandoned ? "abandoned" : "within limit"],
90
+ ],
91
+ startMs: startedAtMs,
92
+ track: "Sync lanes",
93
+ });
94
+ }
75
95
  // Replace the watchdog failure with the late result, then release queued work.
76
- function settleAbandonedSyncLaneRun(coordinatorState, lane, runToken, runResult, wake) {
77
- if (lane.activeRunToken !== runToken) {
96
+ function settleAbandonedSyncLaneRun(coordinatorState, lane, run, runResult, wake) {
97
+ if (lane.activeRunToken !== run.token) {
78
98
  return;
79
99
  }
80
100
  lane.activeRunToken = null;
81
101
  lane.runAbandoned = false;
102
+ recordSyncLaneRunTiming(lane, run.startedAtMs, runResult, true);
82
103
  recordSyncLaneRunResult(lane, runResult);
83
104
  publishSyncCoordinatorSnapshot(coordinatorState);
84
105
  if (!coordinatorState.disposed && lane.requested) {
@@ -97,6 +118,7 @@ function startSyncLaneRun(coordinatorState, lane) {
97
118
  const runToken = {};
98
119
  lane.activeRunToken = runToken;
99
120
  publishSyncCoordinatorSnapshot(coordinatorState);
121
+ const startedAtMs = readUserTimingClock();
100
122
  // Keep follow-up requests even on failure to preserve phase ordering; see
101
123
  // docs/client-sync-ordering.md.
102
124
  // The fallback also catches errors thrown by the lane's error handlers.
@@ -104,10 +126,10 @@ function startSyncLaneRun(coordinatorState, lane) {
104
126
  reportUnexpectedSyncLaneError(lane, error);
105
127
  return { status: "failed", error };
106
128
  });
107
- return { runToken, runResultPromise };
129
+ return { runToken, runResultPromise, startedAtMs };
108
130
  }
109
131
  export async function runCoordinatorLane(coordinatorState, lane, wake) {
110
- const { runToken, runResultPromise } = startSyncLaneRun(coordinatorState, lane);
132
+ const { runToken, runResultPromise, startedAtMs } = startSyncLaneRun(coordinatorState, lane);
111
133
  // Clamp overrides to at least 1ms so every run has a chance to complete.
112
134
  const watchdogMs = Math.max(1, lane.config.watchdogMs ?? SYNC_LANE_WATCHDOG_MS);
113
135
  let watchdogTimer = null;
@@ -128,6 +150,7 @@ export async function runCoordinatorLane(coordinatorState, lane, wake) {
128
150
  if (raceOutcome.kind === "settled") {
129
151
  lane.activeRunToken = null;
130
152
  runResult = raceOutcome.result;
153
+ recordSyncLaneRunTiming(lane, startedAtMs, runResult, false);
131
154
  }
132
155
  else {
133
156
  lane.runAbandoned = true;
@@ -135,7 +158,7 @@ export async function runCoordinatorLane(coordinatorState, lane, wake) {
135
158
  status: "failed",
136
159
  error: new Error(`Sync lane watchdog: run exceeded ${watchdogMs}ms; continuing with other lanes`),
137
160
  };
138
- void runResultPromise.then((result) => settleAbandonedSyncLaneRun(coordinatorState, lane, runToken, result, wake));
161
+ void runResultPromise.then((result) => settleAbandonedSyncLaneRun(coordinatorState, lane, { startedAtMs, token: runToken }, result, wake));
139
162
  }
140
163
  recordSyncLaneRunResult(lane, runResult);
141
164
  publishSyncCoordinatorSnapshot(coordinatorState);