@tearleads/client-sdk 0.1.75 → 0.1.77
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/data/containers/shared/mutationAcknowledgement.d.ts +38 -0
- package/data/{containers → persistence/container-contents}/containerBinding.js +1 -1
- package/data/persistence/container-contents/containerContentsPersistence.js +2 -2
- package/data/persistence/container-contents/containerContentsPersistence.js.map +1 -1
- package/data/persistence/container-contents/containerContentsPersistenceTypes.d.ts +2 -2
- package/data/persistence/container-contents/containerContentsPersistenceTypes.js.map +1 -1
- package/data/persistence/container-contents/containerDeletionPersistence.js +2 -2
- package/data/persistence/container-contents/containerDeletionPersistence.js.map +1 -1
- package/data/persistence/container-contents/containerHydrationPersistence.js +2 -2
- package/data/persistence/container-contents/containerHydrationPersistence.js.map +1 -1
- package/data/persistence/container-contents/containerMetadataMutationPersistence.js +2 -2
- package/data/persistence/container-contents/containerMetadataMutationPersistence.js.map +1 -1
- package/data/persistence/container-contents/containerMetadataRows.js +1 -1
- package/data/persistence/container-contents/containerMetadataRows.js.map +1 -1
- package/data/persistence/container-contents/containerRebindPersistence.js.map +1 -1
- package/data/persistence/container-contents/containerReconcilePersistence.js +2 -2
- package/data/persistence/container-contents/containerReconcilePersistence.js.map +1 -1
- package/data/persistence/container-contents/containerStructuralRepair.js +1 -1
- package/data/persistence/container-contents/containerStructuralRepair.js.map +1 -1
- package/data/persistence/container-contents/dormantMetadataSweep.js +1 -1
- package/data/persistence/container-contents/dormantMetadataSweep.js.map +1 -1
- package/data/persistence/documents/internal/containerDocumentTombstoneHolds.js +1 -1
- package/data/persistence/documents/internal/containerDocumentTombstoneHolds.js.map +1 -1
- package/data/persistence/documents/internal/containerDocumentTombstones.js +1 -1
- package/data/persistence/documents/internal/containerDocumentTombstones.js.map +1 -1
- package/data/persistence/documents/internal/discoveredDocumentPlacement.js +1 -1
- package/data/persistence/documents/internal/discoveredDocumentPlacement.js.map +1 -1
- package/data/principals/currentPolicyReferenceResolver.d.ts +3 -0
- package/index.d.ts +2 -2
- package/index.js +2 -2
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/stores/container-contents/systemContainers/systemContainerIcon.js +1 -1
- package/stores/container-contents/systemContainers/systemContainerIcon.js.map +1 -1
- package/workflows/container-contents/container-state/create/createChild.js +1 -1
- package/workflows/container-contents/container-state/create/createChild.js.map +1 -1
- package/workflows/container-contents/container-state/purge/purgeTree.js +1 -1
- package/workflows/container-contents/container-state/purge/purgeTree.js.map +1 -1
- package/workflows/container-contents/container-state/remote.js +1 -1
- package/workflows/container-contents/container-state/remote.js.map +1 -1
- package/workflows/container-contents/container-state/share/groupGrantVerification.js +1 -1
- package/workflows/container-contents/container-state/share/groupGrantVerification.js.map +1 -1
- package/workflows/container-contents/container-state/share/groupShareEpoch.js +1 -1
- package/workflows/container-contents/container-state/share/groupShareEpoch.js.map +1 -1
- package/workflows/container-contents/container-state/types.js.map +1 -1
- package/workflows/container-contents/containerPersistence.d.ts +3 -3
- package/workflows/container-contents/containerPersistence.js +1 -1
- package/workflows/container-contents/containerPersistence.js.map +1 -1
- package/workflows/container-contents/documentLinks/documentLinkIntent.js +1 -1
- package/workflows/container-contents/documentLinks/documentLinkIntent.js.map +1 -1
- package/workflows/container-contents/documentLinks/index.js +1 -1
- package/workflows/container-contents/documentLinks/index.js.map +1 -1
- package/workflows/container-contents/documentMove/documentMoveIntent.js +1 -1
- package/workflows/container-contents/documentMove/documentMoveIntent.js.map +1 -1
- package/workflows/container-contents/documentMove/documentMoveIntentSettlement.js +2 -2
- package/workflows/container-contents/documentMove/documentMoveIntentSettlement.js.map +1 -1
- package/workflows/container-contents/documentQueries/documentSubtreeQueries.js +1 -1
- package/workflows/container-contents/documentQueries/documentSubtreeQueries.js.map +1 -1
- package/workflows/container-contents/documentQueries/index.js +3 -3
- package/workflows/container-contents/documentQueries/index.js.map +1 -1
- package/workflows/container-contents/documentQueries/pendingDownloads.js +1 -1
- package/workflows/container-contents/documentQueries/pendingDownloads.js.map +1 -1
- package/workflows/container-contents/index.d.ts +1 -1
- package/workflows/container-contents/index.js +1 -1
- package/workflows/container-contents/index.js.map +1 -1
- package/workflows/container-contents/info/blobInfo.js +1 -1
- package/workflows/container-contents/info/blobInfo.js.map +1 -1
- package/workflows/container-contents/info/containerInfo.js +2 -2
- package/workflows/container-contents/info/containerInfo.js.map +1 -1
- package/{data/containers → workflows/container-contents/metadata}/containerMetadataDocument.d.ts +1 -1
- package/{data/containers → workflows/container-contents/metadata}/containerMetadataDocument.js +2 -2
- package/workflows/container-contents/metadata/containerMetadataDocument.js.map +1 -0
- package/workflows/container-contents/metadata/metadataMutationPreparation.js +1 -1
- package/workflows/container-contents/metadata/metadataMutationPreparation.js.map +1 -1
- package/workflows/container-contents/metadata/metadataPersistence.js +1 -1
- package/workflows/container-contents/metadata/metadataPersistence.js.map +1 -1
- package/workflows/container-contents/metadata/metadataRecord.js.map +1 -1
- package/workflows/container-contents/metadata/metadataStateIsolation.js +1 -1
- package/workflows/container-contents/metadata/metadataStateIsolation.js.map +1 -1
- package/workflows/container-contents/metadata/metadataSyncSettlement.js +1 -1
- package/workflows/container-contents/metadata/metadataSyncSettlement.js.map +1 -1
- package/workflows/container-contents/metadata/metadataTypes.d.ts +2 -2
- package/workflows/container-contents/metadata/metadataTypes.js.map +1 -1
- package/workflows/container-contents/recovery/folderRecovery.js +1 -1
- package/workflows/container-contents/recovery/folderRecovery.js.map +1 -1
- package/workflows/container-contents/remoteHydration/destination/replacementBinding.js +1 -1
- package/workflows/container-contents/remoteHydration/destination/replacementBinding.js.map +1 -1
- package/workflows/container-contents/remoteHydration/destination/verifiedDestination.js +1 -1
- package/workflows/container-contents/remoteHydration/destination/verifiedDestination.js.map +1 -1
- package/workflows/container-contents/remoteHydration/heldContainerRebind.js +1 -1
- package/workflows/container-contents/remoteHydration/heldContainerRebind.js.map +1 -1
- package/workflows/container-contents/remoteHydration/reattachMetadata.js +1 -1
- package/workflows/container-contents/remoteHydration/reattachMetadata.js.map +1 -1
- package/workflows/container-contents/remoteHydration/remoteContainers/insertRemoteContainer.js +2 -2
- package/workflows/container-contents/remoteHydration/remoteContainers/insertRemoteContainer.js.map +1 -1
- package/workflows/container-contents/remoteHydration/remoteContainers/remoteContainerState.js +1 -1
- package/workflows/container-contents/remoteHydration/remoteContainers/remoteContainerState.js.map +1 -1
- package/workflows/container-contents/remoteHydration/types.d.ts +1 -1
- package/workflows/container-contents/remoteHydration/types.js.map +1 -1
- package/workflows/container-contents/storedContainerState.js +1 -1
- package/workflows/container-contents/storedContainerState.js.map +1 -1
- package/workflows/containers/child/mutationSubmit.d.ts +76 -0
- package/workflows/containers/child/rekey/carriedDescendantRekeys.d.ts +70 -0
- package/workflows/containers/child/share/index.d.ts +1 -38
- package/workflows/containers/child/share/index.js +1 -205
- package/workflows/containers/child/share/index.js.map +1 -1
- package/workflows/containers/child/share/shareAncestorRepair.d.ts +37 -0
- package/workflows/containers/child/share/shareProjection.d.ts +7 -0
- package/workflows/containers/index.d.ts +3 -2
- package/workflows/containers/index.js +4 -2
- package/workflows/containers/index.js.map +1 -1
- package/workflows/organizations/currentOrganizationAuthority.d.ts +21 -0
- package/workflows/organizations/groupMetadata/groupMetadataAccess.js +1 -1
- package/workflows/organizations/groupMetadata/groupMetadataAccess.js.map +1 -1
- package/workflows/organizations/groupMetadata/groupMetadataRuntime.d.ts +30 -0
- package/workflows/{containers/child/share → organizations/groupShare}/currentShareGrantMutation.js +6 -6
- package/workflows/organizations/groupShare/currentShareGrantMutation.js.map +1 -0
- package/workflows/organizations/groupShare/currentSharePrincipalPolicy.d.ts +30 -0
- package/workflows/{containers/child/share → organizations/groupShare}/currentSharePrincipalPolicy.js +10 -10
- package/workflows/organizations/groupShare/currentSharePrincipalPolicy.js.map +1 -0
- package/workflows/organizations/groupShare/index.d.ts +4 -0
- package/workflows/organizations/groupShare/index.js +7 -0
- package/workflows/organizations/groupShare/index.js.map +1 -0
- package/workflows/organizations/groupShare/runtimeCurrentGroupShare.d.ts +4 -0
- package/workflows/{containers/child/share → organizations/groupShare}/runtimeCurrentGroupShare.js +6 -8
- package/workflows/organizations/groupShare/runtimeCurrentGroupShare.js.map +1 -0
- package/workflows/{containers/child/share → organizations/groupShare}/sharePrincipalPolicy.d.ts +9 -9
- package/workflows/{containers/child/share → organizations/groupShare}/sharePrincipalPolicy.js +13 -13
- package/workflows/organizations/groupShare/sharePrincipalPolicy.js.map +1 -0
- package/workflows/organizations/groupShare/shareWithGroup.d.ts +44 -0
- package/workflows/organizations/groupShare/shareWithGroup.js +210 -0
- package/workflows/organizations/groupShare/shareWithGroup.js.map +1 -0
- package/workflows/organizations/index.d.ts +1 -0
- package/workflows/organizations/index.js +1 -0
- package/workflows/organizations/index.js.map +1 -1
- package/workflows/organizations/principalMutations/currentPrincipalMutationLease.d.ts +16 -0
- package/workflows/organizations/readModel/localReadModelDetails.js +1 -1
- package/workflows/organizations/readModel/localReadModelDetails.js.map +1 -1
- package/workflows/principals/runtimePolicyRecovery.d.ts +42 -0
- package/workflows/registration/bootstrapRootContainer.js +1 -1
- package/workflows/registration/bootstrapRootContainer.js.map +1 -1
- package/workflows/registration/provisioningBootstrapBuilders.js +1 -1
- package/workflows/registration/provisioningBootstrapBuilders.js.map +1 -1
- package/workflows/registration/rootMetadataBootstrap.js +1 -1
- package/workflows/registration/rootMetadataBootstrap.js.map +1 -1
- package/workflows/sync/remoteReset.js +1 -1
- package/workflows/sync/remoteReset.js.map +1 -1
- package/data/containers/containerMetadataDocument.js.map +0 -1
- package/workflows/containers/child/share/currentShareGrantMutation.js.map +0 -1
- package/workflows/containers/child/share/currentSharePrincipalPolicy.js.map +0 -1
- package/workflows/containers/child/share/runtimeCurrentGroupShare.js.map +0 -1
- package/workflows/containers/child/share/sharePrincipalPolicy.js.map +0 -1
- /package/data/{containers → persistence/container-contents}/containerBinding.d.ts +0 -0
- /package/data/{containers → persistence/container-contents}/containerBinding.js.map +0 -0
- /package/data/persistence/{containers → container-contents}/containerPersistence.d.ts +0 -0
- /package/data/persistence/{containers → container-contents}/containerPersistence.js +0 -0
- /package/data/persistence/{containers → container-contents}/containerPersistence.js.map +0 -0
- /package/data/persistence/{containers → container-contents}/containerSyncWatermarkPersistence.d.ts +0 -0
- /package/data/persistence/{containers → container-contents}/containerSyncWatermarkPersistence.js +0 -0
- /package/data/persistence/{containers → container-contents}/containerSyncWatermarkPersistence.js.map +0 -0
- /package/data/persistence/{containers → container-contents}/documentContainerProjectionPersistence.js +0 -0
- /package/data/persistence/{containers → container-contents}/documentContainerProjectionPersistence.js.map +0 -0
- /package/data/persistence/{containers → container-contents}/documentPlacement.js +0 -0
- /package/data/persistence/{containers → container-contents}/documentPlacement.js.map +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"groupShareEpoch.js","sourceRoot":"","sources":["groupShareEpoch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oCAAoC,EAAE,MAAM,qEAAqE,CAAC;AAC3H,OAAO,EAAE,wCAAwC,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"groupShareEpoch.js","sourceRoot":"","sources":["groupShareEpoch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oCAAoC,EAAE,MAAM,qEAAqE,CAAC;AAC3H,OAAO,EAAE,wCAAwC,EAAE,MAAM,mCAAmC,CAAC;AAG7F,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAAC,KAQjD;IACC,IAAI,KAAK,CAAC,YAAY,EAAE,EAAE,KAAK,KAAK;QAAE,OAAO,IAAI,CAAC;IAClD,MAAM,WAAW,GAAG,wCAAwC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC5E,IAAI,CAAC,WAAW;QACd,MAAM,IAAI,oCAAoC,CAC5C,+CAA+C,CAChD,CAAC;IACJ,OAAO,WAAW,CAChB;QACE,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;QAC1C,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,cAAc,EAAE,KAAK,CAAC,cAAc;QACpC,YAAY,EAAE,KAAK,CAAC,YAAY,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;KACjD,EACD,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CACtC,CAAC;AACJ,CAAC","sourcesContent":["import { ProjectionDependencyUnavailableError } from \"../../../../data/keyingProjectionVerification/dependencyUnavailable\";\nimport { createRuntimeCurrentSharePrincipalPolicy } from \"../../../organizations/groupShare\";\nimport type { ContainerWorkflowRuntime } from \"../types\";\n\nexport async function resolveCurrentGroupKeyEpoch(input: {\n // Bound here, in the one verified load a duplicate share performs, so a\n // duplicate never reports success for a group the user did not choose.\n expectedGroupName?: string | undefined;\n groupId: string;\n organizationId: string;\n runtime: ContainerWorkflowRuntime;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<number | null> {\n if (input.stillCurrent?.() === false) return null;\n const readCurrent = createRuntimeCurrentSharePrincipalPolicy(input.runtime);\n if (!readCurrent)\n throw new ProjectionDependencyUnavailableError(\n \"Group sharing requires private paged recovery\",\n );\n return readCurrent(\n {\n expectedGroupName: input.expectedGroupName,\n groupId: input.groupId,\n organizationId: input.organizationId,\n stillCurrent: input.stillCurrent ?? (() => true),\n },\n async ({ policy }) => policy.keyEpoch,\n );\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"","sourcesContent":["import type { ContainerSystemSlot } from \"@tearleads/validators/containerSystemSlot\";\nimport type {\n ContainerDeleteResponse,\n ContainerWriterProjectionResponse,\n ReferencedPrincipalStateResponse,\n} from \"@tearleads/validators/response\";\nimport type {
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"","sourcesContent":["import type { ContainerSystemSlot } from \"@tearleads/validators/containerSystemSlot\";\nimport type {\n ContainerDeleteResponse,\n ContainerWriterProjectionResponse,\n ReferencedPrincipalStateResponse,\n} from \"@tearleads/validators/response\";\nimport type { ProjectionUserKeyResolver } from \"../../../data/keyingProjectionVerification\";\nimport type { DocumentRecord } from \"../../../data/sqlite/documentPersistence\";\nimport type {\n createRemoteContainer,\n moveRemoteContainer,\n shareRemoteContainer,\n} from \"../../containers\";\nimport type { createRemoteDocument } from \"../../documents\";\nimport type { shareRemoteContainerWithGroup } from \"../../organizations/groupShare\";\nimport type { CurrentPrincipalPolicyReader } from \"../../principals/currentPrincipalPolicyReader\";\nimport type { PrincipalPolicyHistoryReader } from \"../../principals/principalPolicyHistoryReader\";\nimport type {\n ContainerContentsPersistence,\n ContainerCreateIntentRecord,\n ContainerMoveIntentRecord,\n} from \"../containerPersistence\";\nimport type { createInitializedContainerMetadataDocument } from \"../metadata/containerMetadataDocument\";\nimport type {\n ContainerState,\n RemoteContainer as HydratedRemoteContainer,\n RemoteContainerHydrationHost,\n} from \"../remoteHydration\";\nimport type { ContainerContentsWorkflowRuntime } from \"../runtime\";\n\nexport type ContainerWorkflowApi = Parameters<\n typeof createRemoteContainer\n>[0][\"apiClient\"] &\n Parameters<typeof shareRemoteContainer>[0][\"apiClient\"] &\n Parameters<typeof shareRemoteContainerWithGroup>[0][\"apiClient\"] &\n Parameters<typeof moveRemoteContainer>[0][\"apiClient\"] &\n Parameters<typeof createRemoteDocument>[0][\"apiClient\"] &\n Partial<PrincipalPolicyHistoryReader> &\n CurrentPrincipalPolicyReader & {\n deleteContainerResult(\n containerId: string,\n options?: {\n expectedPaymentRequiredOrganizationId?: string;\n reportErrors?: boolean;\n requiredAncestorId?: string | undefined;\n },\n ): Promise<\n | { data: ContainerDeleteResponse; ok: true }\n | {\n ok: false;\n report: () => void;\n status: number | null;\n }\n >;\n primeContainerWriterProjection(\n containerId: string,\n projection: ContainerWriterProjectionResponse,\n ): void;\n };\n\nexport interface ContainerWorkflowRuntime\n extends Pick<\n ContainerContentsWorkflowRuntime,\n | \"auth\"\n | \"crypto\"\n | \"infra\"\n | \"resolveTrustedUserIdentity\"\n | \"state\"\n | \"util\"\n > {\n readonly apiClient: ContainerWorkflowApi;\n}\n\nexport interface CreatedRemoteContainerState {\n accessManifestHash: string;\n /**\n * The metadata seed the create committed, settled by the caller instead of\n * a first metadata sync. Absent when the create carried no seed or fell back\n * to a plain create.\n */\n metadataSeed?:\n | { readonly commitLsn: string | null; readonly updateId: string }\n | undefined;\n /** The slot this client signed into the create; never the server's echo. */\n systemSlot: ContainerSystemSlot | null;\n containerId: string;\n createdAt: string;\n metadataDocumentId: string;\n organizationId: string;\n /** A created container is a child; the acknowledgement echoed this parent. */\n parentId: string;\n persistedMetadataState: Pick<\n DocumentRecord,\n | \"documentId\"\n | \"contentKeyBundle\"\n | \"documentKekTargets\"\n | \"documentManifestBundle\"\n >;\n updatedAt: string;\n}\n\nexport interface SharedRemoteContainerState {\n accessEpoch: number;\n accessManifestHash: string;\n createdAt: string;\n metadataDocumentId: string;\n referencedPrincipalHeads: ReferencedPrincipalStateResponse[];\n updatedAt: string;\n writerProjection: ContainerWriterProjectionResponse | null;\n}\n\nexport interface SharedContainerState {\n container: ContainerState[\"container\"];\n record: ContainerState[\"record\"];\n}\n\nexport type SharedContainerStateResult =\n | { status: \"missing\" }\n | { status: \"confirmed\" }\n | (SharedContainerState & {\n status: \"identity-superseded\" | \"persisted\";\n });\n\nexport type RemoteContainer = HydratedRemoteContainer;\n\nexport type ContainerMetadataDocumentState = Awaited<\n ReturnType<typeof createInitializedContainerMetadataDocument>\n>[\"doc\"];\n\nexport interface CreatedChildContainerState {\n containerState: ContainerState;\n initialUpdate: Uint8Array;\n shouldRequestSync: boolean;\n}\n\nexport interface ContainerIntentSyncState {\n containersById: ReadonlyMap<string, ContainerState>;\n /**\n * Metadata update ids this device sent, so their own update echoes are\n * classified as self-authored (shared with the metadata sync).\n */\n locallyAcceptedMetadataUpdateIds?: Set<string> | undefined;\n /** Metadata document ids of folder creates in flight (shared with hints). */\n plannedMetadataDocumentIds?: Set<string> | undefined;\n persistence: ContainerContentsPersistence;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n runtime: ContainerWorkflowRuntime;\n /**\n * Verifies that a listed container is this device's pending create before it\n * is adopted and returns where it sits; `assertContainerCreateAdoptable`\n * unless a test replaces it.\n */\n verifyCreateAdoption?: (input: {\n readonly containerId: string;\n readonly expectedOrganizationId: string;\n }) => Promise<AdoptedContainerPlacement>;\n}\n\n/** Where a verified listed create committed, and where its container is now. */\nexport interface AdoptedContainerPlacement {\n /** The parent its signed epoch-1 `container.create` named. */\n readonly createdParentId: string;\n /** The verified head's parent; another writer may have moved it since. */\n readonly currentParentId: string;\n}\n\nexport type ContainerCreateIntentSyncState = ContainerIntentSyncState;\n\nexport type ContainerCreateIntentSyncHost = Pick<\n RemoteContainerHydrationHost,\n \"persistContainerState\"\n>;\n\nexport interface ContainerCreateIntentSyncInput {\n host: ContainerCreateIntentSyncHost;\n /** A parent whose own create has not settled takes no child create. */\n isCreatePending: (containerId: string) => boolean;\n isCurrent: () => boolean;\n isRemoteSyncBlocked: (organizationId: string) => boolean;\n intent: ContainerCreateIntentRecord;\n requestRemoteReconciliation: (parentContainerId: string | null) => void;\n state: ContainerCreateIntentSyncState;\n}\n\nexport type ContainerMoveIntentSyncState = ContainerIntentSyncState;\n\nexport type ContainerMoveIntentSyncHost = Pick<\n RemoteContainerHydrationHost,\n \"persistContainerState\" | \"updateSnapshot\"\n>;\n\n/** Later passes for moves the server accepted but no pass settled. */\nexport interface AcceptedMoveRetry {\n /** The server holds the move: schedule a replay to settle it. */\n arm: (intentId: string) => void;\n /** A replay failed; continue an accepted move's retries, if it has some. */\n resume: (intentId: string) => void;\n}\n\nexport interface ContainerMoveIntentSyncInput {\n host: ContainerMoveIntentSyncHost;\n isCurrent: () => boolean;\n /** A folder whose create has not settled takes no structural writes. */\n isCreatePending: (containerId: string) => boolean;\n isRemoteSyncBlocked: (organizationId: string) => boolean;\n intent: ContainerMoveIntentRecord;\n requestRemoteReconciliation: (parentContainerId: string | null) => void;\n acceptedMoveRetry: AcceptedMoveRetry;\n state: ContainerMoveIntentSyncState;\n}\n"]}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { SyncWatermark } from "../../internal/validators/response/index.js";
|
|
2
2
|
import type { ContainerContentsPersistence } from "../../data/persistence/container-contents/containerContentsPersistence.js";
|
|
3
|
-
import { type ContainerSyncLaneCheckRecord, type ContainerSyncWatermarkLane } from "../../data/persistence/
|
|
3
|
+
import { type ContainerSyncLaneCheckRecord, type ContainerSyncWatermarkLane } from "../../data/persistence/container-contents/containerSyncWatermarkPersistence.js";
|
|
4
4
|
import type { ExecSql } from "../../data/sqlite/sqlSchema.js";
|
|
5
5
|
export type { ContainerContentsPersistence, ContainerCreateIntentRecord, ContainerHydrationTombstone, ContainerMetadataRecord, ContainerMetadataRecord as ContainerDocumentRecord, ContainerMoveIntentRecord, LocalRootDescendantReparentInput, StoredContainerState, } from "../../data/persistence/container-contents/containerContentsPersistence.js";
|
|
6
6
|
export { sqlContainerContentsPersistence as defaultContainerContentsPersistence } from "../../data/persistence/container-contents/containerContentsPersistence.js";
|
|
7
|
-
export type { ContainerRecord } from "../../data/persistence/
|
|
8
|
-
export type { ContainerSyncWatermarkLane } from "../../data/persistence/
|
|
7
|
+
export type { ContainerRecord } from "../../data/persistence/container-contents/containerPersistence.js";
|
|
8
|
+
export type { ContainerSyncWatermarkLane } from "../../data/persistence/container-contents/containerSyncWatermarkPersistence.js";
|
|
9
9
|
export declare function enqueuePendingContainerUpdate(execSql: ExecSql, persistence: ContainerContentsPersistence, params: {
|
|
10
10
|
containerId: string;
|
|
11
11
|
sourceVersionVector?: string | null | undefined;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createPendingUpdateFields } from "../../data/documents/documentSync.js";
|
|
2
|
-
import { containerContentsSyncLane, containerParentSyncLane, sqlContainerSyncWatermarkPersistence, } from "../../data/persistence/
|
|
2
|
+
import { containerContentsSyncLane, containerParentSyncLane, sqlContainerSyncWatermarkPersistence, } from "../../data/persistence/container-contents/containerSyncWatermarkPersistence.js";
|
|
3
3
|
export { sqlContainerContentsPersistence as defaultContainerContentsPersistence } from "../../data/persistence/container-contents/containerContentsPersistence.js";
|
|
4
4
|
export async function enqueuePendingContainerUpdate(execSql, persistence, params) {
|
|
5
5
|
const pendingUpdateFields = createPendingUpdateFields(params.update, params.sourceVersionVector);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"containerPersistence.js","sourceRoot":"","sources":["containerPersistence.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC;AAE9E,OAAO,EAGL,yBAAyB,EACzB,uBAAuB,EACvB,oCAAoC,GACrC,MAAM,
|
|
1
|
+
{"version":3,"file":"containerPersistence.js","sourceRoot":"","sources":["containerPersistence.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC;AAE9E,OAAO,EAGL,yBAAyB,EACzB,uBAAuB,EACvB,oCAAoC,GACrC,MAAM,6EAA6E,CAAC;AAarF,OAAO,EAAE,+BAA+B,IAAI,mCAAmC,EAAE,MAAM,wEAAwE,CAAC;AAIhK,MAAM,CAAC,KAAK,UAAU,6BAA6B,CACjD,OAAgB,EAChB,WAAyC,EACzC,MAIC;IAED,MAAM,mBAAmB,GAAG,yBAAyB,CACnD,MAAM,CAAC,MAAM,EACb,MAAM,CAAC,mBAAmB,CAC3B,CAAC;IACF,IAAI,CAAC,mBAAmB,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,WAAW,CAAC,oBAAoB,CAAC,OAAO,EAAE;QAC/C,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,GAAG,mBAAmB;KACvB,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,6BAA6B,CAC3C,QAAuB;IAEvB,OAAO,uBAAuB,CAAC,QAAQ,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,+BAA+B,CAC7C,WAAmB;IAEnB,OAAO,yBAAyB,CAAC,WAAW,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,OAAgB,EAChB,QAAoC;IAEpC,OAAO,oCAAoC,CAAC,aAAa,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;AAC/E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,OAAgB,EAChB,QAAoC,EACpC,SAAwB;IAExB,MAAM,oCAAoC,CAAC,aAAa,CACtD,OAAO,EACP,QAAQ,EACR,SAAS,CACV,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iCAAiC,CACrD,OAAgB,EAChB,SAAoD;IAEpD,OAAO,oCAAoC,CAAC,gBAAgB,CAC1D,OAAO,EACP,SAAS,CACV,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAChD,OAAgB,EAChB,QAAoC;IAEpC,MAAM,oCAAoC,CAAC,WAAW,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;AAC5E,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,qCAAqC,CACzD,OAAgB,EAChB,QAAoC,EACpC,KAGC,EACD,YAA0C;IAE1C,OAAO,oCAAoC,CAAC,eAAe,CACzD,OAAO,EACP,QAAQ,EACR,KAAK,EACL,EAAE,YAAY,EAAE,CACjB,CAAC;AACJ,CAAC","sourcesContent":["import type { SyncWatermark } from \"@tearleads/validators/response\";\nimport { createPendingUpdateFields } from \"../../data/documents/documentSync\";\nimport type { ContainerContentsPersistence } from \"../../data/persistence/container-contents/containerContentsPersistence\";\nimport {\n type ContainerSyncLaneCheckRecord,\n type ContainerSyncWatermarkLane,\n containerContentsSyncLane,\n containerParentSyncLane,\n sqlContainerSyncWatermarkPersistence,\n} from \"../../data/persistence/container-contents/containerSyncWatermarkPersistence\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\n\nexport type {\n ContainerContentsPersistence,\n ContainerCreateIntentRecord,\n ContainerHydrationTombstone,\n ContainerMetadataRecord,\n ContainerMetadataRecord as ContainerDocumentRecord,\n ContainerMoveIntentRecord,\n LocalRootDescendantReparentInput,\n StoredContainerState,\n} from \"../../data/persistence/container-contents/containerContentsPersistence\";\nexport { sqlContainerContentsPersistence as defaultContainerContentsPersistence } from \"../../data/persistence/container-contents/containerContentsPersistence\";\nexport type { ContainerRecord } from \"../../data/persistence/container-contents/containerPersistence\";\nexport type { ContainerSyncWatermarkLane } from \"../../data/persistence/container-contents/containerSyncWatermarkPersistence\";\n\nexport async function enqueuePendingContainerUpdate(\n execSql: ExecSql,\n persistence: ContainerContentsPersistence,\n params: {\n containerId: string;\n sourceVersionVector?: string | null | undefined;\n update: Uint8Array;\n },\n): Promise<string | null> {\n const pendingUpdateFields = createPendingUpdateFields(\n params.update,\n params.sourceVersionVector,\n );\n if (!pendingUpdateFields) {\n return null;\n }\n\n return persistence.enqueuePendingUpdate(execSql, {\n containerId: params.containerId,\n ...pendingUpdateFields,\n });\n}\n\nexport function createContainerParentSyncLane(\n parentId: string | null,\n): ContainerSyncWatermarkLane {\n return containerParentSyncLane(parentId);\n}\n\nexport function createContainerContentsSyncLane(\n containerId: string,\n): ContainerSyncWatermarkLane {\n return containerContentsSyncLane(containerId);\n}\n\nexport async function loadContainerSyncWatermark(\n execSql: ExecSql,\n syncLane: ContainerSyncWatermarkLane,\n): Promise<SyncWatermark | null> {\n return sqlContainerSyncWatermarkPersistence.loadWatermark(execSql, syncLane);\n}\n\nexport async function saveContainerSyncWatermark(\n execSql: ExecSql,\n syncLane: ContainerSyncWatermarkLane,\n watermark: SyncWatermark,\n): Promise<void> {\n await sqlContainerSyncWatermarkPersistence.saveWatermark(\n execSql,\n syncLane,\n watermark,\n );\n}\n\nexport async function loadContainerSyncLaneCheckRecords(\n execSql: ExecSql,\n syncLanes: ReadonlyArray<ContainerSyncWatermarkLane>,\n): Promise<Array<ContainerSyncLaneCheckRecord | null>> {\n return sqlContainerSyncWatermarkPersistence.loadCheckRecords(\n execSql,\n syncLanes,\n );\n}\n\nexport async function markContainerSyncLaneChecked(\n execSql: ExecSql,\n syncLane: ContainerSyncWatermarkLane,\n): Promise<void> {\n await sqlContainerSyncWatermarkPersistence.markChecked(execSql, syncLane);\n}\n\n/**\n * Records one lane fetch in a single guarded upsert: the cursor when the page\n * carried one and the freshness marker when the lane is fully drained.\n */\nexport async function recordContainerSyncLaneFetchIfCurrent(\n execSql: ExecSql,\n syncLane: ContainerSyncWatermarkLane,\n fetch: {\n readonly checked: boolean;\n readonly watermark: SyncWatermark | null;\n },\n stillCurrent?: (() => boolean) | undefined,\n): Promise<boolean> {\n return sqlContainerSyncWatermarkPersistence.recordLaneFetch(\n execSql,\n syncLane,\n fetch,\n { stillCurrent },\n );\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { uniqueSortedStrings } from "../../../data/documents/shared/readers.js";
|
|
2
|
+
import { sqlDocumentContainerProjectionPersistence as links } from "../../../data/persistence/container-contents/documentContainerProjectionPersistence.js";
|
|
2
3
|
import { sqlDocumentMoveIntentPersistence } from "../../../data/persistence/container-contents/documentMoveIntentPersistence.js";
|
|
3
|
-
import { sqlDocumentContainerProjectionPersistence as links } from "../../../data/persistence/containers/documentContainerProjectionPersistence.js";
|
|
4
4
|
import { defaultDocumentsPersistence } from "../../documents/index.js";
|
|
5
5
|
import { relinkContainerDocumentLocally } from "./documentLocalRelink.js";
|
|
6
6
|
export async function addDocumentLinkLocally(input) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"documentLinkIntent.js","sourceRoot":"","sources":["documentLinkIntent.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,wCAAwC,CAAC;AAC7E,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"documentLinkIntent.js","sourceRoot":"","sources":["documentLinkIntent.ts"],"names":[],"mappings":"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","sourcesContent":["import type { DocumentSummary } from \"../../../data/documents/documentSummary\";\nimport { uniqueSortedStrings } from \"../../../data/documents/shared/readers\";\nimport { sqlDocumentContainerProjectionPersistence as links } from \"../../../data/persistence/container-contents/documentContainerProjectionPersistence\";\nimport { sqlDocumentMoveIntentPersistence } from \"../../../data/persistence/container-contents/documentMoveIntentPersistence\";\nimport { defaultDocumentsPersistence } from \"../../documents\";\nimport type {\n DocumentStructuralMutationHost,\n DocumentStructuralMutationLocalStore,\n DocumentStructuralMutationRuntime,\n SetLinkedContainerIdsForDocument,\n} from \"../documentQueries/documentStructureTypes\";\nimport { relinkContainerDocumentLocally } from \"./documentLocalRelink\";\n\nexport async function addDocumentLinkLocally<TRuntime>(input: {\n currentDocumentStore: DocumentStructuralMutationLocalStore<TRuntime>;\n host: DocumentStructuralMutationHost<TRuntime>;\n note: DocumentSummary & { documentId: string; containerId: string };\n runtime: DocumentStructuralMutationRuntime;\n scheduleSync?: (() => void) | undefined;\n setLinkedContainerIdsForDocument: SetLinkedContainerIdsForDocument;\n targetContainerId: string;\n}): Promise<DocumentSummary | null> {\n const { note, runtime, targetContainerId } = input;\n const persisted = await defaultDocumentsPersistence.loadDocument(\n runtime.infra.execSql,\n note.id,\n );\n if (!persisted) return null;\n const intentId = crypto.randomUUID();\n let linkedContainerIds: readonly string[] = [];\n const linkedNote = await relinkContainerDocumentLocally({\n ...input,\n accessEpoch: persisted.accessEpoch,\n requestSync: false,\n targetContainerId: note.containerId,\n commitSideEffect: async (execSql) => {\n const currentLinks = await links.listLinkedContainerIds(\n execSql,\n note.documentId,\n );\n linkedContainerIds = uniqueSortedStrings([\n ...currentLinks,\n note.containerId,\n targetContainerId,\n ]);\n await sqlDocumentMoveIntentPersistence.enqueueLinkIntent(execSql, {\n id: intentId,\n documentId: note.documentId,\n localId: note.id,\n sourceContainerId: note.containerId,\n targetContainerId,\n });\n await links.replaceDocumentLinks(\n execSql,\n note.documentId,\n linkedContainerIds,\n { moveIntentId: intentId },\n );\n },\n });\n if (!linkedNote) return null;\n input.setLinkedContainerIdsForDocument(note.documentId, linkedContainerIds);\n input.scheduleSync?.();\n runtime.util.log(\n `Container contents: queued note ${note.id} link to ${targetContainerId}`,\n );\n return linkedNote;\n}\n\nexport async function removeDocumentLinkLocally<TRuntime>(\n input: Omit<\n Parameters<typeof addDocumentLinkLocally<TRuntime>>[0],\n \"targetContainerId\"\n > & { removedContainerId: string },\n): Promise<DocumentSummary | null> {\n const { note, runtime, removedContainerId } = input;\n const execSql = runtime.infra.execSql;\n const persisted = await defaultDocumentsPersistence.loadDocument(\n execSql,\n note.id,\n );\n if (!persisted) return null;\n const currentLinks = await links.listLinkedContainerIds(\n execSql,\n note.documentId,\n );\n const remaining = currentLinks.filter((id) => id !== removedContainerId);\n const nextContainerId = remaining.includes(note.containerId)\n ? note.containerId\n : remaining[0];\n if (!nextContainerId || !currentLinks.includes(removedContainerId))\n return null;\n const intentId = crypto.randomUUID();\n let linkedContainerIds: readonly string[] = [];\n const unlinkedNote = await relinkContainerDocumentLocally({\n ...input,\n accessEpoch: persisted.accessEpoch,\n requestSync: false,\n targetContainerId: nextContainerId,\n commitSideEffect: async (transactionExecSql) => {\n linkedContainerIds = (\n await links.listLinkedContainerIds(transactionExecSql, note.documentId)\n ).filter((id) => id !== removedContainerId);\n if (!linkedContainerIds.includes(nextContainerId))\n throw new Error(\"Document placement changed before unlink\");\n await sqlDocumentMoveIntentPersistence.enqueueUnlinkIntent(\n transactionExecSql,\n {\n id: intentId,\n documentId: note.documentId,\n localId: note.id,\n removedContainerId,\n targetContainerId: nextContainerId,\n },\n );\n await links.replaceDocumentLinks(\n transactionExecSql,\n note.documentId,\n linkedContainerIds,\n { moveIntentId: intentId },\n );\n },\n });\n if (!unlinkedNote) return null;\n input.setLinkedContainerIdsForDocument(note.documentId, linkedContainerIds);\n input.scheduleSync?.();\n return unlinkedNote;\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { assertDocumentWriterProjectionConsistent, readLinkedContainerIdsFromDocumentManifest, } from "../../../data/documents/shared/projection/index.js";
|
|
2
2
|
import { persistedDocumentCreateStateFromWriterProjection } from "../../../data/documents/shared/responses.js";
|
|
3
3
|
import { reportAndRethrowKeyingVerificationError } from "../../../data/keyingProjectionVerification/error.js";
|
|
4
|
-
import { sqlDocumentContainerProjectionPersistence } from "../../../data/persistence/
|
|
4
|
+
import { sqlDocumentContainerProjectionPersistence } from "../../../data/persistence/container-contents/documentContainerProjectionPersistence.js";
|
|
5
5
|
import { errorMessage } from "../../../data/shared/errorMessage.js";
|
|
6
6
|
import { isDatabaseUnavailableError } from "../../../data/sync/databaseUnavailable.js";
|
|
7
7
|
import { relinkRemoteDocument, resolveDocumentCreateAuthor, } from "../../documents/index.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { VerifiedDocumentLinkSetManifest } from \"@tearleads/crypto\";\nimport type { DocumentWriterProjectionResponse } from \"@tearleads/validators/response\";\nimport {\n assertDocumentWriterProjectionConsistent,\n readLinkedContainerIdsFromDocumentManifest,\n} from \"../../../data/documents/shared/projection\";\nimport { persistedDocumentCreateStateFromWriterProjection } from \"../../../data/documents/shared/responses\";\nimport type { ProjectionUserKeyResolver } from \"../../../data/keyingProjectionVerification\";\nimport { reportAndRethrowKeyingVerificationError } from \"../../../data/keyingProjectionVerification/error\";\nimport { sqlDocumentContainerProjectionPersistence } from \"../../../data/persistence/containers/documentContainerProjectionPersistence\";\nimport { errorMessage } from \"../../../data/shared/errorMessage\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport { isDatabaseUnavailableError } from \"../../../data/sync/databaseUnavailable\";\nimport {\n type DocumentLinkSetFailureHandler,\n type RelinkRemoteDocumentResult,\n relinkRemoteDocument,\n resolveDocumentCreateAuthor,\n} from \"../../documents\";\nimport type { SubtreePurgeRoot } from \"../../documents/purge/subtreePurgeScope\";\nimport { createRuntimePrincipalPolicyWarmer } from \"../../principals/runtimePolicyWarmer\";\nimport { resolveContainerDocumentMoveUnlinkIds } from \"../documentMove/documentMoveUnlinkIds\";\nimport type { ContainerContentsWorkflowRuntime } from \"../runtime\";\n\ntype ContainerDocumentLinkApi = Parameters<\n typeof relinkRemoteDocument\n>[0][\"apiClient\"];\ntype ContainerDocumentLinkOperation = Parameters<\n typeof relinkRemoteDocument\n>[0][\"operation\"];\ntype RemoteDocumentPersistedState =\n RelinkRemoteDocumentResult[\"persistedState\"];\n\n// A cold-cache denial must keep its HTTP status: collapsing a 403 to null\n// would leave an access-denied move routinely retriable instead of parking\n// it for the access-restored signal (row 7).\nasync function fetchMoveWriterProjection(input: {\n documentId: string;\n onFailure?: DocumentLinkSetFailureHandler | undefined;\n runtime: ContainerDocumentLinkRuntime;\n}): Promise<Awaited<\n ReturnType<ContainerDocumentLinkApi[\"getDocumentWriterProjection\"]>\n> | null> {\n const { apiClient } = input.runtime;\n const result = await apiClient.getDocumentWriterProjectionResult(\n input.documentId,\n { reportErrors: false },\n );\n if (result.ok) {\n return result.data;\n }\n result.report();\n input.onFailure?.({ message: result.message, status: result.status });\n return null;\n}\n\ninterface ContainerDocumentLinkRuntime\n extends Pick<\n ContainerContentsWorkflowRuntime,\n | \"auth\"\n | \"crypto\"\n | \"infra\"\n | \"resolveTrustedUserIdentity\"\n | \"state\"\n | \"util\"\n > {\n apiClient: ContainerDocumentLinkApi &\n Pick<\n ContainerContentsWorkflowRuntime[\"apiClient\"],\n \"getPrincipalPolicyPages\" | \"getProjectionPolicyHistoryPages\"\n >;\n}\n\ntype MoveRemoteContainerDocumentStatus = \"complete\" | \"partial\";\n\ninterface MoveRemoteContainerDocumentResult {\n accessEpoch: number | null;\n accessStateHash: string | null;\n linkedContainerIds: readonly string[];\n nextContainerId: string;\n remoteState: RemoteDocumentPersistedState | null;\n status: MoveRemoteContainerDocumentStatus;\n}\n\nexport type { RemoteDocumentPersistedState };\n\nexport async function initializeDocumentLinksSchema(\n execSql: ExecSql,\n): Promise<void> {\n await sqlDocumentContainerProjectionPersistence.ensureSchema(execSql);\n}\n\nexport async function listDocumentLinkedContainerIds(\n execSql: ExecSql,\n documentId: string,\n): Promise<ReadonlyArray<string>> {\n return sqlDocumentContainerProjectionPersistence.listLinkedContainerIds(\n execSql,\n documentId,\n );\n}\n\nexport async function replaceDocumentLinks(\n execSql: ExecSql,\n documentId: string,\n containerIds: ReadonlyArray<string>,\n): Promise<void> {\n await sqlDocumentContainerProjectionPersistence.replaceDocumentLinks(\n execSql,\n documentId,\n containerIds,\n );\n}\n\nfunction resolveActiveDocumentContainerId(\n linkedContainerIds: ReadonlyArray<string>,\n preferredContainerId: string,\n): string | null {\n if (linkedContainerIds.includes(preferredContainerId)) {\n return preferredContainerId;\n }\n\n return linkedContainerIds[0] ?? null;\n}\n\nfunction containerDocumentMoveResult(input: {\n document: RelinkRemoteDocumentResult;\n nextContainerId: string;\n status: MoveRemoteContainerDocumentStatus;\n}): MoveRemoteContainerDocumentResult {\n return {\n accessEpoch: input.document.plan.state.epoch,\n accessStateHash: input.document.response.accessManifest.manifestHash,\n linkedContainerIds: input.document.linkedContainerIds,\n nextContainerId: input.nextContainerId,\n remoteState: input.document.persistedState,\n status: input.status,\n };\n}\n\nasync function containerDocumentAlreadyMovedResult(input: {\n writerProjection: DocumentWriterProjectionResponse;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n runtime: ContainerDocumentLinkRuntime;\n isCurrent?: (() => boolean) | undefined;\n linkedContainerIds: readonly string[];\n nextContainerId: string;\n status: MoveRemoteContainerDocumentStatus;\n}): Promise<MoveRemoteContainerDocumentResult> {\n const verified: { head?: VerifiedDocumentLinkSetManifest | undefined } = {};\n await assertDocumentWriterProjectionConsistent(input.writerProjection, {\n execSql: input.runtime.infra.execSql,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n stillCurrent: input.isCurrent,\n warmReferencedPrincipalPolicies: createRuntimePrincipalPolicyWarmer(\n input.runtime,\n ),\n onVerifiedAuthorization: (authorization) => {\n verified.head = authorization.documentManifestByHash.get(\n input.writerProjection.documentManifest.manifestHash,\n );\n },\n });\n if (!verified.head)\n throw new Error(\"Move replay lacks a verified document head\");\n return {\n accessEpoch: verified.head.state.epoch,\n accessStateHash: verified.head.manifestHash,\n linkedContainerIds: input.linkedContainerIds,\n nextContainerId: input.nextContainerId,\n remoteState: persistedDocumentCreateStateFromWriterProjection(\n input.writerProjection,\n ),\n status: input.status,\n };\n}\n\n/**\n * Hand a link/unlink/move/purge failure to host diagnostics as a real `Error`.\n * The caller's string-only log line stays the fallback for a host without\n * `logError`, so this never logs a second copy of the same failure.\n */\nfunction reportDocumentLinkMutationFailure(\n util: ContainerDocumentLinkRuntime[\"util\"],\n error: unknown,\n): void {\n // `ApiClient` returns `RequestFailure` objects instead of throwing, so\n // offline and 403/404/409 already left through the `!result` branch: a status\n // filter here would be dead code. Only a database lost mid-flight stays quiet.\n if (!util.logError || isDatabaseUnavailableError(error)) return;\n try {\n // A host logger that throws or rejects must not replace the null result or\n // skip the failure handler below.\n void Promise.resolve(\n util.logError(\"Container contents: document link mutation failed\", error),\n ).catch(() => undefined);\n } catch {\n // Hosts may throw synchronously or return a rejected promise.\n }\n}\n\nexport async function relinkRemoteContainerDocument(input: {\n beforeSubmit?: (() => Promise<boolean>) | undefined;\n documentId: string;\n expectedSubtreeRoot?: SubtreePurgeRoot | undefined;\n isCurrent?: (() => boolean) | undefined;\n noteId: string;\n onFailure?: DocumentLinkSetFailureHandler | undefined;\n operation: ContainerDocumentLinkOperation;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n rotationSnapshot?: Uint8Array | undefined;\n runtime: ContainerDocumentLinkRuntime;\n targetContainerId: string;\n}): Promise<RelinkRemoteDocumentResult | null> {\n const {\n documentId,\n noteId,\n operation,\n resolveProjectionUserKey,\n runtime,\n targetContainerId,\n } = input;\n const author = resolveDocumentCreateAuthor(runtime);\n const targetSecretKey = runtime.crypto.encapsulationKeyPair?.secretKey;\n const execSql = runtime.infra.execSql;\n if (input.isCurrent?.() === false) return null;\n if (!author || !targetSecretKey) {\n runtime.util.log(\n \"Container contents: document mutation skipped because the local key context is unavailable\",\n );\n input.onFailure?.({\n message: \"the local key context is unavailable\",\n status: null,\n });\n return null;\n }\n\n try {\n const result = await relinkRemoteDocument({\n beforeSubmit: input.beforeSubmit,\n apiClient: runtime.apiClient,\n author,\n documentId,\n expectedSubtreeRoot: input.expectedSubtreeRoot,\n execSql,\n onFailure: input.onFailure,\n operation,\n resolveProjectionUserKey,\n rotationSnapshot: input.rotationSnapshot,\n stillCurrent: input.isCurrent,\n targetContainerId,\n targetSecretKey,\n warmReferencedPrincipalPolicies:\n createRuntimePrincipalPolicyWarmer(runtime),\n });\n if (!result) {\n runtime.util.log(\n `Container contents: failed to ${operation} note ${noteId} ${operation === \"link\" ? \"to\" : \"from\"} container ${targetContainerId}`,\n );\n return null;\n }\n if (input.isCurrent?.() === false) return null;\n\n await sqlDocumentContainerProjectionPersistence.replaceDocumentLinks(\n execSql,\n documentId,\n result.linkedContainerIds,\n { stillCurrent: input.isCurrent },\n );\n\n return result;\n } catch (error) {\n await reportAndRethrowKeyingVerificationError(\n error,\n runtime.util.reportSecurityIncident,\n {\n objectId: documentId,\n objectKind: \"document\",\n operation: `document.${operation}`,\n },\n );\n const message = errorMessage(error);\n runtime.util.log(\n `Container contents: failed to ${operation} note ${noteId} ${operation === \"link\" ? \"to\" : \"from\"} container ${targetContainerId}: ${message}`,\n );\n // After the keying rethrow above, so a verification failure keeps its\n // security incident instead of being reported twice, and before the failure\n // handler, so a throwing caller callback cannot swallow the report.\n reportDocumentLinkMutationFailure(runtime.util, error);\n input.onFailure?.({ message, status: null });\n return null;\n }\n}\n\nasync function linkRemoteContainerDocument(input: {\n documentId: string;\n isCurrent?: (() => boolean) | undefined;\n noteId: string;\n onFailure?: DocumentLinkSetFailureHandler | undefined;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n runtime: ContainerDocumentLinkRuntime;\n targetContainerId: string;\n}): Promise<RelinkRemoteDocumentResult | null> {\n return relinkRemoteContainerDocument({\n ...input,\n operation: \"link\",\n });\n}\n\nexport async function unlinkRemoteContainerDocument(input: {\n beforeSubmit?: (() => Promise<boolean>) | undefined;\n documentId: string;\n expectedSubtreeRoot?: SubtreePurgeRoot | undefined;\n isCurrent?: (() => boolean) | undefined;\n noteId: string;\n onFailure?: DocumentLinkSetFailureHandler | undefined;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n rotationSnapshot: Uint8Array;\n runtime: ContainerDocumentLinkRuntime;\n targetContainerId: string;\n}): Promise<RelinkRemoteDocumentResult | null> {\n return relinkRemoteContainerDocument({\n ...input,\n operation: \"unlink\",\n });\n}\n\nexport async function moveRemoteContainerDocument(input: {\n linkOnly?: boolean | undefined;\n additionalLinkContainerIds?: readonly string[] | undefined;\n removedLinkContainerIds?: readonly string[] | undefined;\n currentContainerId: string;\n documentId: string;\n isCurrent?: (() => boolean) | undefined;\n noteId: string;\n onFailure?: DocumentLinkSetFailureHandler | undefined;\n replaceLinkedContainers?: boolean | undefined;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n rotationSnapshot: Uint8Array;\n runtime: ContainerDocumentLinkRuntime;\n targetContainerId: string;\n}): Promise<MoveRemoteContainerDocumentResult | null> {\n const {\n documentId,\n noteId,\n resolveProjectionUserKey,\n runtime,\n targetContainerId,\n } = input;\n if (input.isCurrent?.() === false) return null;\n const writerProjection = await fetchMoveWriterProjection({\n documentId,\n onFailure: input.onFailure,\n runtime,\n });\n if (!writerProjection || input.isCurrent?.() === false) {\n return null;\n }\n if (writerProjection.documentId !== documentId)\n throw new Error(\"Move replay document id mismatch\");\n const initialLinkedContainerIds =\n readLinkedContainerIdsFromDocumentManifest(writerProjection);\n\n let latestLinkedContainerIds: readonly string[] = initialLinkedContainerIds;\n let latestDocument: RelinkRemoteDocumentResult | null = null;\n for (const linkTarget of new Set([\n ...(input.linkOnly ? [] : [targetContainerId]),\n ...(input.additionalLinkContainerIds ?? []),\n ])) {\n if (latestLinkedContainerIds.includes(linkTarget)) continue;\n const linkedDocument = await linkRemoteContainerDocument({\n documentId,\n isCurrent: input.isCurrent,\n noteId,\n onFailure: input.onFailure,\n resolveProjectionUserKey,\n runtime,\n targetContainerId: linkTarget,\n });\n if (!linkedDocument || input.isCurrent?.() === false) {\n return null;\n }\n\n latestDocument = linkedDocument;\n latestLinkedContainerIds = linkedDocument.linkedContainerIds;\n }\n\n const unlinkContainerIds = resolveContainerDocumentMoveUnlinkIds({\n ...input,\n linkedContainerIds: latestLinkedContainerIds,\n });\n\n const unlinked = await unlinkMovedDocumentSources({\n ...input,\n latestDocument,\n latestLinkedContainerIds,\n unlinkContainerIds,\n });\n if (!unlinked) return null;\n latestDocument = unlinked.latestDocument;\n latestLinkedContainerIds = unlinked.latestLinkedContainerIds;\n\n const nextContainerId = resolveActiveDocumentContainerId(\n latestLinkedContainerIds,\n targetContainerId,\n );\n if (!nextContainerId) {\n return null;\n }\n\n const status =\n unlinked.failedUnlinkContainerIds.length > 0 ? \"partial\" : \"complete\";\n return latestDocument\n ? containerDocumentMoveResult({\n document: latestDocument,\n nextContainerId,\n status,\n })\n : containerDocumentAlreadyMovedResult({\n writerProjection,\n resolveProjectionUserKey,\n runtime,\n isCurrent: input.isCurrent,\n linkedContainerIds: latestLinkedContainerIds,\n nextContainerId,\n status,\n });\n}\n\n// The unlink half of a move: every source is attempted even when an earlier\n// one fails, so one dead source cannot strand the others; a failed unlink\n// leaves the move \"partial\" for the queue to retry.\nasync function unlinkMovedDocumentSources(input: {\n documentId: string;\n isCurrent?: (() => boolean) | undefined;\n latestDocument: RelinkRemoteDocumentResult | null;\n latestLinkedContainerIds: readonly string[];\n noteId: string;\n onFailure?: DocumentLinkSetFailureHandler | undefined;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n rotationSnapshot: Uint8Array;\n runtime: ContainerDocumentLinkRuntime;\n targetContainerId: string;\n unlinkContainerIds: readonly string[];\n}): Promise<{\n failedUnlinkContainerIds: readonly string[];\n latestDocument: RelinkRemoteDocumentResult | null;\n latestLinkedContainerIds: readonly string[];\n} | null> {\n const { noteId, runtime, targetContainerId } = input;\n let { latestDocument, latestLinkedContainerIds } = input;\n const failedUnlinkContainerIds: string[] = [];\n for (const unlinkContainerId of input.unlinkContainerIds) {\n if (input.isCurrent?.() === false) return null;\n const unlinkedDocument = await unlinkRemoteContainerDocument({\n documentId: input.documentId,\n isCurrent: input.isCurrent,\n noteId,\n onFailure: input.onFailure,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n rotationSnapshot: input.rotationSnapshot,\n runtime,\n targetContainerId: unlinkContainerId,\n });\n if (input.isCurrent?.() === false) return null;\n if (!unlinkedDocument) {\n failedUnlinkContainerIds.push(unlinkContainerId);\n runtime.util.log(\n `Container contents: note ${noteId} was linked to ${targetContainerId} but failed to unlink from ${unlinkContainerId}`,\n );\n continue;\n }\n\n latestDocument = unlinkedDocument;\n latestLinkedContainerIds = unlinkedDocument.linkedContainerIds;\n }\n return { failedUnlinkContainerIds, latestDocument, latestLinkedContainerIds };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { VerifiedDocumentLinkSetManifest } from \"@tearleads/crypto\";\nimport type { DocumentWriterProjectionResponse } from \"@tearleads/validators/response\";\nimport {\n assertDocumentWriterProjectionConsistent,\n readLinkedContainerIdsFromDocumentManifest,\n} from \"../../../data/documents/shared/projection\";\nimport { persistedDocumentCreateStateFromWriterProjection } from \"../../../data/documents/shared/responses\";\nimport type { ProjectionUserKeyResolver } from \"../../../data/keyingProjectionVerification\";\nimport { reportAndRethrowKeyingVerificationError } from \"../../../data/keyingProjectionVerification/error\";\nimport { sqlDocumentContainerProjectionPersistence } from \"../../../data/persistence/container-contents/documentContainerProjectionPersistence\";\nimport { errorMessage } from \"../../../data/shared/errorMessage\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport { isDatabaseUnavailableError } from \"../../../data/sync/databaseUnavailable\";\nimport {\n type DocumentLinkSetFailureHandler,\n type RelinkRemoteDocumentResult,\n relinkRemoteDocument,\n resolveDocumentCreateAuthor,\n} from \"../../documents\";\nimport type { SubtreePurgeRoot } from \"../../documents/purge/subtreePurgeScope\";\nimport { createRuntimePrincipalPolicyWarmer } from \"../../principals/runtimePolicyWarmer\";\nimport { resolveContainerDocumentMoveUnlinkIds } from \"../documentMove/documentMoveUnlinkIds\";\nimport type { ContainerContentsWorkflowRuntime } from \"../runtime\";\n\ntype ContainerDocumentLinkApi = Parameters<\n typeof relinkRemoteDocument\n>[0][\"apiClient\"];\ntype ContainerDocumentLinkOperation = Parameters<\n typeof relinkRemoteDocument\n>[0][\"operation\"];\ntype RemoteDocumentPersistedState =\n RelinkRemoteDocumentResult[\"persistedState\"];\n\n// A cold-cache denial must keep its HTTP status: collapsing a 403 to null\n// would leave an access-denied move routinely retriable instead of parking\n// it for the access-restored signal (row 7).\nasync function fetchMoveWriterProjection(input: {\n documentId: string;\n onFailure?: DocumentLinkSetFailureHandler | undefined;\n runtime: ContainerDocumentLinkRuntime;\n}): Promise<Awaited<\n ReturnType<ContainerDocumentLinkApi[\"getDocumentWriterProjection\"]>\n> | null> {\n const { apiClient } = input.runtime;\n const result = await apiClient.getDocumentWriterProjectionResult(\n input.documentId,\n { reportErrors: false },\n );\n if (result.ok) {\n return result.data;\n }\n result.report();\n input.onFailure?.({ message: result.message, status: result.status });\n return null;\n}\n\ninterface ContainerDocumentLinkRuntime\n extends Pick<\n ContainerContentsWorkflowRuntime,\n | \"auth\"\n | \"crypto\"\n | \"infra\"\n | \"resolveTrustedUserIdentity\"\n | \"state\"\n | \"util\"\n > {\n apiClient: ContainerDocumentLinkApi &\n Pick<\n ContainerContentsWorkflowRuntime[\"apiClient\"],\n \"getPrincipalPolicyPages\" | \"getProjectionPolicyHistoryPages\"\n >;\n}\n\ntype MoveRemoteContainerDocumentStatus = \"complete\" | \"partial\";\n\ninterface MoveRemoteContainerDocumentResult {\n accessEpoch: number | null;\n accessStateHash: string | null;\n linkedContainerIds: readonly string[];\n nextContainerId: string;\n remoteState: RemoteDocumentPersistedState | null;\n status: MoveRemoteContainerDocumentStatus;\n}\n\nexport type { RemoteDocumentPersistedState };\n\nexport async function initializeDocumentLinksSchema(\n execSql: ExecSql,\n): Promise<void> {\n await sqlDocumentContainerProjectionPersistence.ensureSchema(execSql);\n}\n\nexport async function listDocumentLinkedContainerIds(\n execSql: ExecSql,\n documentId: string,\n): Promise<ReadonlyArray<string>> {\n return sqlDocumentContainerProjectionPersistence.listLinkedContainerIds(\n execSql,\n documentId,\n );\n}\n\nexport async function replaceDocumentLinks(\n execSql: ExecSql,\n documentId: string,\n containerIds: ReadonlyArray<string>,\n): Promise<void> {\n await sqlDocumentContainerProjectionPersistence.replaceDocumentLinks(\n execSql,\n documentId,\n containerIds,\n );\n}\n\nfunction resolveActiveDocumentContainerId(\n linkedContainerIds: ReadonlyArray<string>,\n preferredContainerId: string,\n): string | null {\n if (linkedContainerIds.includes(preferredContainerId)) {\n return preferredContainerId;\n }\n\n return linkedContainerIds[0] ?? null;\n}\n\nfunction containerDocumentMoveResult(input: {\n document: RelinkRemoteDocumentResult;\n nextContainerId: string;\n status: MoveRemoteContainerDocumentStatus;\n}): MoveRemoteContainerDocumentResult {\n return {\n accessEpoch: input.document.plan.state.epoch,\n accessStateHash: input.document.response.accessManifest.manifestHash,\n linkedContainerIds: input.document.linkedContainerIds,\n nextContainerId: input.nextContainerId,\n remoteState: input.document.persistedState,\n status: input.status,\n };\n}\n\nasync function containerDocumentAlreadyMovedResult(input: {\n writerProjection: DocumentWriterProjectionResponse;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n runtime: ContainerDocumentLinkRuntime;\n isCurrent?: (() => boolean) | undefined;\n linkedContainerIds: readonly string[];\n nextContainerId: string;\n status: MoveRemoteContainerDocumentStatus;\n}): Promise<MoveRemoteContainerDocumentResult> {\n const verified: { head?: VerifiedDocumentLinkSetManifest | undefined } = {};\n await assertDocumentWriterProjectionConsistent(input.writerProjection, {\n execSql: input.runtime.infra.execSql,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n stillCurrent: input.isCurrent,\n warmReferencedPrincipalPolicies: createRuntimePrincipalPolicyWarmer(\n input.runtime,\n ),\n onVerifiedAuthorization: (authorization) => {\n verified.head = authorization.documentManifestByHash.get(\n input.writerProjection.documentManifest.manifestHash,\n );\n },\n });\n if (!verified.head)\n throw new Error(\"Move replay lacks a verified document head\");\n return {\n accessEpoch: verified.head.state.epoch,\n accessStateHash: verified.head.manifestHash,\n linkedContainerIds: input.linkedContainerIds,\n nextContainerId: input.nextContainerId,\n remoteState: persistedDocumentCreateStateFromWriterProjection(\n input.writerProjection,\n ),\n status: input.status,\n };\n}\n\n/**\n * Hand a link/unlink/move/purge failure to host diagnostics as a real `Error`.\n * The caller's string-only log line stays the fallback for a host without\n * `logError`, so this never logs a second copy of the same failure.\n */\nfunction reportDocumentLinkMutationFailure(\n util: ContainerDocumentLinkRuntime[\"util\"],\n error: unknown,\n): void {\n // `ApiClient` returns `RequestFailure` objects instead of throwing, so\n // offline and 403/404/409 already left through the `!result` branch: a status\n // filter here would be dead code. Only a database lost mid-flight stays quiet.\n if (!util.logError || isDatabaseUnavailableError(error)) return;\n try {\n // A host logger that throws or rejects must not replace the null result or\n // skip the failure handler below.\n void Promise.resolve(\n util.logError(\"Container contents: document link mutation failed\", error),\n ).catch(() => undefined);\n } catch {\n // Hosts may throw synchronously or return a rejected promise.\n }\n}\n\nexport async function relinkRemoteContainerDocument(input: {\n beforeSubmit?: (() => Promise<boolean>) | undefined;\n documentId: string;\n expectedSubtreeRoot?: SubtreePurgeRoot | undefined;\n isCurrent?: (() => boolean) | undefined;\n noteId: string;\n onFailure?: DocumentLinkSetFailureHandler | undefined;\n operation: ContainerDocumentLinkOperation;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n rotationSnapshot?: Uint8Array | undefined;\n runtime: ContainerDocumentLinkRuntime;\n targetContainerId: string;\n}): Promise<RelinkRemoteDocumentResult | null> {\n const {\n documentId,\n noteId,\n operation,\n resolveProjectionUserKey,\n runtime,\n targetContainerId,\n } = input;\n const author = resolveDocumentCreateAuthor(runtime);\n const targetSecretKey = runtime.crypto.encapsulationKeyPair?.secretKey;\n const execSql = runtime.infra.execSql;\n if (input.isCurrent?.() === false) return null;\n if (!author || !targetSecretKey) {\n runtime.util.log(\n \"Container contents: document mutation skipped because the local key context is unavailable\",\n );\n input.onFailure?.({\n message: \"the local key context is unavailable\",\n status: null,\n });\n return null;\n }\n\n try {\n const result = await relinkRemoteDocument({\n beforeSubmit: input.beforeSubmit,\n apiClient: runtime.apiClient,\n author,\n documentId,\n expectedSubtreeRoot: input.expectedSubtreeRoot,\n execSql,\n onFailure: input.onFailure,\n operation,\n resolveProjectionUserKey,\n rotationSnapshot: input.rotationSnapshot,\n stillCurrent: input.isCurrent,\n targetContainerId,\n targetSecretKey,\n warmReferencedPrincipalPolicies:\n createRuntimePrincipalPolicyWarmer(runtime),\n });\n if (!result) {\n runtime.util.log(\n `Container contents: failed to ${operation} note ${noteId} ${operation === \"link\" ? \"to\" : \"from\"} container ${targetContainerId}`,\n );\n return null;\n }\n if (input.isCurrent?.() === false) return null;\n\n await sqlDocumentContainerProjectionPersistence.replaceDocumentLinks(\n execSql,\n documentId,\n result.linkedContainerIds,\n { stillCurrent: input.isCurrent },\n );\n\n return result;\n } catch (error) {\n await reportAndRethrowKeyingVerificationError(\n error,\n runtime.util.reportSecurityIncident,\n {\n objectId: documentId,\n objectKind: \"document\",\n operation: `document.${operation}`,\n },\n );\n const message = errorMessage(error);\n runtime.util.log(\n `Container contents: failed to ${operation} note ${noteId} ${operation === \"link\" ? \"to\" : \"from\"} container ${targetContainerId}: ${message}`,\n );\n // After the keying rethrow above, so a verification failure keeps its\n // security incident instead of being reported twice, and before the failure\n // handler, so a throwing caller callback cannot swallow the report.\n reportDocumentLinkMutationFailure(runtime.util, error);\n input.onFailure?.({ message, status: null });\n return null;\n }\n}\n\nasync function linkRemoteContainerDocument(input: {\n documentId: string;\n isCurrent?: (() => boolean) | undefined;\n noteId: string;\n onFailure?: DocumentLinkSetFailureHandler | undefined;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n runtime: ContainerDocumentLinkRuntime;\n targetContainerId: string;\n}): Promise<RelinkRemoteDocumentResult | null> {\n return relinkRemoteContainerDocument({\n ...input,\n operation: \"link\",\n });\n}\n\nexport async function unlinkRemoteContainerDocument(input: {\n beforeSubmit?: (() => Promise<boolean>) | undefined;\n documentId: string;\n expectedSubtreeRoot?: SubtreePurgeRoot | undefined;\n isCurrent?: (() => boolean) | undefined;\n noteId: string;\n onFailure?: DocumentLinkSetFailureHandler | undefined;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n rotationSnapshot: Uint8Array;\n runtime: ContainerDocumentLinkRuntime;\n targetContainerId: string;\n}): Promise<RelinkRemoteDocumentResult | null> {\n return relinkRemoteContainerDocument({\n ...input,\n operation: \"unlink\",\n });\n}\n\nexport async function moveRemoteContainerDocument(input: {\n linkOnly?: boolean | undefined;\n additionalLinkContainerIds?: readonly string[] | undefined;\n removedLinkContainerIds?: readonly string[] | undefined;\n currentContainerId: string;\n documentId: string;\n isCurrent?: (() => boolean) | undefined;\n noteId: string;\n onFailure?: DocumentLinkSetFailureHandler | undefined;\n replaceLinkedContainers?: boolean | undefined;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n rotationSnapshot: Uint8Array;\n runtime: ContainerDocumentLinkRuntime;\n targetContainerId: string;\n}): Promise<MoveRemoteContainerDocumentResult | null> {\n const {\n documentId,\n noteId,\n resolveProjectionUserKey,\n runtime,\n targetContainerId,\n } = input;\n if (input.isCurrent?.() === false) return null;\n const writerProjection = await fetchMoveWriterProjection({\n documentId,\n onFailure: input.onFailure,\n runtime,\n });\n if (!writerProjection || input.isCurrent?.() === false) {\n return null;\n }\n if (writerProjection.documentId !== documentId)\n throw new Error(\"Move replay document id mismatch\");\n const initialLinkedContainerIds =\n readLinkedContainerIdsFromDocumentManifest(writerProjection);\n\n let latestLinkedContainerIds: readonly string[] = initialLinkedContainerIds;\n let latestDocument: RelinkRemoteDocumentResult | null = null;\n for (const linkTarget of new Set([\n ...(input.linkOnly ? [] : [targetContainerId]),\n ...(input.additionalLinkContainerIds ?? []),\n ])) {\n if (latestLinkedContainerIds.includes(linkTarget)) continue;\n const linkedDocument = await linkRemoteContainerDocument({\n documentId,\n isCurrent: input.isCurrent,\n noteId,\n onFailure: input.onFailure,\n resolveProjectionUserKey,\n runtime,\n targetContainerId: linkTarget,\n });\n if (!linkedDocument || input.isCurrent?.() === false) {\n return null;\n }\n\n latestDocument = linkedDocument;\n latestLinkedContainerIds = linkedDocument.linkedContainerIds;\n }\n\n const unlinkContainerIds = resolveContainerDocumentMoveUnlinkIds({\n ...input,\n linkedContainerIds: latestLinkedContainerIds,\n });\n\n const unlinked = await unlinkMovedDocumentSources({\n ...input,\n latestDocument,\n latestLinkedContainerIds,\n unlinkContainerIds,\n });\n if (!unlinked) return null;\n latestDocument = unlinked.latestDocument;\n latestLinkedContainerIds = unlinked.latestLinkedContainerIds;\n\n const nextContainerId = resolveActiveDocumentContainerId(\n latestLinkedContainerIds,\n targetContainerId,\n );\n if (!nextContainerId) {\n return null;\n }\n\n const status =\n unlinked.failedUnlinkContainerIds.length > 0 ? \"partial\" : \"complete\";\n return latestDocument\n ? containerDocumentMoveResult({\n document: latestDocument,\n nextContainerId,\n status,\n })\n : containerDocumentAlreadyMovedResult({\n writerProjection,\n resolveProjectionUserKey,\n runtime,\n isCurrent: input.isCurrent,\n linkedContainerIds: latestLinkedContainerIds,\n nextContainerId,\n status,\n });\n}\n\n// The unlink half of a move: every source is attempted even when an earlier\n// one fails, so one dead source cannot strand the others; a failed unlink\n// leaves the move \"partial\" for the queue to retry.\nasync function unlinkMovedDocumentSources(input: {\n documentId: string;\n isCurrent?: (() => boolean) | undefined;\n latestDocument: RelinkRemoteDocumentResult | null;\n latestLinkedContainerIds: readonly string[];\n noteId: string;\n onFailure?: DocumentLinkSetFailureHandler | undefined;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n rotationSnapshot: Uint8Array;\n runtime: ContainerDocumentLinkRuntime;\n targetContainerId: string;\n unlinkContainerIds: readonly string[];\n}): Promise<{\n failedUnlinkContainerIds: readonly string[];\n latestDocument: RelinkRemoteDocumentResult | null;\n latestLinkedContainerIds: readonly string[];\n} | null> {\n const { noteId, runtime, targetContainerId } = input;\n let { latestDocument, latestLinkedContainerIds } = input;\n const failedUnlinkContainerIds: string[] = [];\n for (const unlinkContainerId of input.unlinkContainerIds) {\n if (input.isCurrent?.() === false) return null;\n const unlinkedDocument = await unlinkRemoteContainerDocument({\n documentId: input.documentId,\n isCurrent: input.isCurrent,\n noteId,\n onFailure: input.onFailure,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n rotationSnapshot: input.rotationSnapshot,\n runtime,\n targetContainerId: unlinkContainerId,\n });\n if (input.isCurrent?.() === false) return null;\n if (!unlinkedDocument) {\n failedUnlinkContainerIds.push(unlinkContainerId);\n runtime.util.log(\n `Container contents: note ${noteId} was linked to ${targetContainerId} but failed to unlink from ${unlinkContainerId}`,\n );\n continue;\n }\n\n latestDocument = unlinkedDocument;\n latestLinkedContainerIds = unlinkedDocument.linkedContainerIds;\n }\n return { failedUnlinkContainerIds, latestDocument, latestLinkedContainerIds };\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DEFAULT_DOCUMENT_ACCESS_EPOCH } from "../../../data/documents/documentConstants.js";
|
|
2
2
|
import { uniqueSortedStrings } from "../../../data/documents/shared/readers.js";
|
|
3
|
+
import { sqlDocumentContainerProjectionPersistence } from "../../../data/persistence/container-contents/documentContainerProjectionPersistence.js";
|
|
3
4
|
import { sqlDocumentMoveIntentPersistence } from "../../../data/persistence/container-contents/documentMoveIntentPersistence.js";
|
|
4
|
-
import { sqlDocumentContainerProjectionPersistence } from "../../../data/persistence/containers/documentContainerProjectionPersistence.js";
|
|
5
5
|
import { defaultDocumentsPersistence } from "../../documents/index.js";
|
|
6
6
|
import { listDocumentLinkedContainerIds } from "../documentLinks/index.js";
|
|
7
7
|
import { relinkContainerDocumentLocally } from "../documentLinks/documentLocalRelink.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"documentMoveIntent.js","sourceRoot":"","sources":["documentMoveIntent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,6BAA6B,EAAE,MAAM,2CAA2C,CAAC;AAE1F,OAAO,EAAE,mBAAmB,EAAE,MAAM,wCAAwC,CAAC;AAC7E,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"documentMoveIntent.js","sourceRoot":"","sources":["documentMoveIntent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,6BAA6B,EAAE,MAAM,2CAA2C,CAAC;AAE1F,OAAO,EAAE,mBAAmB,EAAE,MAAM,wCAAwC,CAAC;AAC7E,OAAO,EAAE,yCAAyC,EAAE,MAAM,qFAAqF,CAAC;AAChJ,OAAO,EAAE,gCAAgC,EAAE,MAAM,4EAA4E,CAAC;AAC9H,OAAO,EAAE,2BAA2B,EAAE,MAAM,iBAAiB,CAAC;AAC9D,OAAO,EAAE,8BAA8B,EAAE,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAE,8BAA8B,EAAE,MAAM,sCAAsC,CAAC;AAQtF,KAAK,UAAU,kCAAkC,CAAC,KAMjD;IACC,IAAI,KAAK,CAAC,uBAAuB,EAAE,CAAC;QAClC,OAAO,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACnC,CAAC;IAED,MAAM,yBAAyB,GAAG,MAAM,8BAA8B,CACpE,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,EAC3B,KAAK,CAAC,UAAU,CACjB,CAAC;IACF,MAAM,kBAAkB,GACtB,yBAAyB,CAAC,MAAM,GAAG,CAAC;QAClC,CAAC,CAAC,yBAAyB;QAC3B,CAAC,CAAC,KAAK,CAAC,kBAAkB;YACxB,CAAC,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC;YAC5B,CAAC,CAAC,EAAE,CAAC;IAEX,OAAO,mBAAmB,CAAC;QACzB,GAAG,kBAAkB,CAAC,MAAM,CAC1B,CAAC,WAAW,EAAE,EAAE,CAAC,WAAW,KAAK,KAAK,CAAC,kBAAkB,CAC1D;QACD,KAAK,CAAC,iBAAiB;KACxB,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,2BAA2B,CAAC,KAG1C;IACC,MAAM,gBAAgB,GAAG,MAAM,2BAA2B,CAAC,YAAY,CACrE,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,EAC3B,KAAK,CAAC,OAAO,CACd,CAAC;IACF,4EAA4E;IAC5E,yEAAyE;IACzE,sDAAsD;IACtD,OAAO,gBAAgB,EAAE,WAAW,IAAI,6BAA6B,CAAC;AACxE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,6BAA6B,CAAW,MAU7D;IACC,MAAM,EACJ,oBAAoB,EACpB,UAAU,EACV,IAAI,EACJ,IAAI,EACJ,uBAAuB,EACvB,OAAO,EACP,YAAY,EACZ,gCAAgC,EAChC,iBAAiB,GAClB,GAAG,MAAM,CAAC;IACX,MAAM,kBAAkB,GAAG,MAAM,kCAAkC,CAAC;QAClE,kBAAkB,EAAE,IAAI,CAAC,WAAW;QACpC,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,uBAAuB;QACvB,OAAO;QACP,iBAAiB;KAClB,CAAC,CAAC;IAEH,wEAAwE;IACxE,8EAA8E;IAC9E,6EAA6E;IAC7E,4EAA4E;IAC5E,mBAAmB;IACnB,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;IAErC,MAAM,SAAS,GAAG,MAAM,8BAA8B,CAAC;QACrD,WAAW,EAAE,MAAM,2BAA2B,CAAC;YAC7C,OAAO,EAAE,IAAI,CAAC,EAAE;YAChB,OAAO;SACR,CAAC;QACF,oBAAoB;QACpB,IAAI;QACJ,IAAI;QACJ,gBAAgB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;YAClC,MAAM,gCAAgC,CAAC,iBAAiB,CAAC,OAAO,EAAE;gBAChE,EAAE,EAAE,QAAQ;gBACZ,UAAU,EAAE,IAAI,CAAC,UAAU;gBAC3B,OAAO,EAAE,IAAI,CAAC,EAAE;gBAChB,uBAAuB;gBACvB,iBAAiB,EAAE,IAAI,CAAC,WAAW;gBACnC,iBAAiB;aAClB,CAAC,CAAC;YACH,MAAM,yCAAyC,CAAC,oBAAoB,CAClE,OAAO,EACP,IAAI,CAAC,UAAU,EACf,kBAAkB,EAClB,EAAE,YAAY,EAAE,QAAQ,EAAE,CAC3B,CAAC;QACJ,CAAC;QACD,WAAW,EAAE,KAAK;QAClB,OAAO;QACP,iBAAiB;KAClB,CAAC,CAAC;IACH,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAC7C,CAAC;IAED,gCAAgC,CAAC,IAAI,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;IACtE,UAAU,CAAC,iBAAiB,CAAC,CAAC;IAC9B,YAAY,EAAE,EAAE,CAAC;IACjB,OAAO,CAAC,IAAI,CAAC,GAAG,CACd,mCAAmC,SAAS,CAAC,EAAE,YAAY,iBAAiB,EAAE,CAC/E,CAAC;IACF,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;AACjD,CAAC","sourcesContent":["import { DEFAULT_DOCUMENT_ACCESS_EPOCH } from \"../../../data/documents/documentConstants\";\nimport type { DocumentSummary } from \"../../../data/documents/documentSummary\";\nimport { uniqueSortedStrings } from \"../../../data/documents/shared/readers\";\nimport { sqlDocumentContainerProjectionPersistence } from \"../../../data/persistence/container-contents/documentContainerProjectionPersistence\";\nimport { sqlDocumentMoveIntentPersistence } from \"../../../data/persistence/container-contents/documentMoveIntentPersistence\";\nimport { defaultDocumentsPersistence } from \"../../documents\";\nimport { listDocumentLinkedContainerIds } from \"../documentLinks\";\nimport { relinkContainerDocumentLocally } from \"../documentLinks/documentLocalRelink\";\nimport type {\n DocumentStructuralMutationHost,\n DocumentStructuralMutationLocalStore,\n DocumentStructuralMutationRuntime,\n SetLinkedContainerIdsForDocument,\n} from \"../documentQueries/documentStructureTypes\";\n\nasync function resolveOptimisticDocumentMoveLinks(input: {\n currentContainerId: string | null;\n documentId: string;\n replaceLinkedContainers?: boolean | undefined;\n runtime: DocumentStructuralMutationRuntime;\n targetContainerId: string;\n}): Promise<string[]> {\n if (input.replaceLinkedContainers) {\n return [input.targetContainerId];\n }\n\n const currentLinkedContainerIds = await listDocumentLinkedContainerIds(\n input.runtime.infra.execSql,\n input.documentId,\n );\n const linkedContainerIds =\n currentLinkedContainerIds.length > 0\n ? currentLinkedContainerIds\n : input.currentContainerId\n ? [input.currentContainerId]\n : [];\n\n return uniqueSortedStrings([\n ...linkedContainerIds.filter(\n (containerId) => containerId !== input.currentContainerId,\n ),\n input.targetContainerId,\n ]);\n}\n\nasync function resolveLocalMoveAccessEpoch(input: {\n localId: string;\n runtime: DocumentStructuralMutationRuntime;\n}): Promise<number> {\n const existingDocument = await defaultDocumentsPersistence.loadDocument(\n input.runtime.infra.execSql,\n input.localId,\n );\n // The local relink must keep the document's current key epoch. Falling back\n // is only for partially seeded local state; downgrading synced documents\n // would make offline edits use stale access material.\n return existingDocument?.accessEpoch ?? DEFAULT_DOCUMENT_ACCESS_EPOCH;\n}\n\nexport async function moveRemoteDocumentLinkLocally<TRuntime>(params: {\n currentDocumentStore: DocumentStructuralMutationLocalStore<TRuntime>;\n expandNode: (nodeId: string) => void;\n host: DocumentStructuralMutationHost<TRuntime>;\n note: DocumentSummary & { documentId: string };\n replaceLinkedContainers?: boolean | undefined;\n runtime: DocumentStructuralMutationRuntime;\n scheduleSync?: (() => void) | undefined;\n setLinkedContainerIdsForDocument: SetLinkedContainerIdsForDocument;\n targetContainerId: string;\n}): Promise<{ linksChanged: boolean; note: DocumentSummary | null }> {\n const {\n currentDocumentStore,\n expandNode,\n host,\n note,\n replaceLinkedContainers,\n runtime,\n scheduleSync,\n setLinkedContainerIdsForDocument,\n targetContainerId,\n } = params;\n const linkedContainerIds = await resolveOptimisticDocumentMoveLinks({\n currentContainerId: note.containerId,\n documentId: note.documentId,\n replaceLinkedContainers,\n runtime,\n targetContainerId,\n });\n\n // Apply the user's chosen placement locally now, then replay the signed\n // link-set mutation from this durable intent when auth/network/key context is\n // back. This mirrors container move intents: UI state should not wait on the\n // server, but the remote contract still converges through the normal writer\n // projection path.\n const intentId = crypto.randomUUID();\n\n const movedNote = await relinkContainerDocumentLocally({\n accessEpoch: await resolveLocalMoveAccessEpoch({\n localId: note.id,\n runtime,\n }),\n currentDocumentStore,\n host,\n note,\n commitSideEffect: async (execSql) => {\n await sqlDocumentMoveIntentPersistence.enqueueMoveIntent(execSql, {\n id: intentId,\n documentId: note.documentId,\n localId: note.id,\n replaceLinkedContainers,\n sourceContainerId: note.containerId,\n targetContainerId,\n });\n await sqlDocumentContainerProjectionPersistence.replaceDocumentLinks(\n execSql,\n note.documentId,\n linkedContainerIds,\n { moveIntentId: intentId },\n );\n },\n requestSync: false,\n runtime,\n targetContainerId,\n });\n if (!movedNote) {\n return { linksChanged: false, note: null };\n }\n\n setLinkedContainerIdsForDocument(note.documentId, linkedContainerIds);\n expandNode(targetContainerId);\n scheduleSync?.();\n runtime.util.log(\n `Container contents: queued note ${movedNote.id} move to ${targetContainerId}`,\n );\n return { linksChanged: true, note: movedNote };\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { sqlDocumentContainerProjectionPersistence } from "../../../data/persistence/container-contents/documentContainerProjectionPersistence.js";
|
|
1
2
|
import { sqlDocumentMoveIntentPersistence, } from "../../../data/persistence/container-contents/documentMoveIntentPersistence.js";
|
|
2
|
-
import {
|
|
3
|
-
import { loadDocumentMovePlacement } from "../../../data/persistence/containers/documentPlacement.js";
|
|
3
|
+
import { loadDocumentMovePlacement } from "../../../data/persistence/container-contents/documentPlacement.js";
|
|
4
4
|
import { getClientSQLitePersistenceRuntime } from "../../../data/sqlite/sqlitePersistenceRuntime.js";
|
|
5
5
|
export async function settleDocumentMoveIntent(input) {
|
|
6
6
|
if (!input.isCurrent()) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"documentMoveIntentSettlement.js","sourceRoot":"","sources":["documentMoveIntentSettlement.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"documentMoveIntentSettlement.js","sourceRoot":"","sources":["documentMoveIntentSettlement.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yCAAyC,EAAE,MAAM,qFAAqF,CAAC;AAChJ,OAAO,EAEL,gCAAgC,GACjC,MAAM,4EAA4E,CAAC;AACpF,OAAO,EAAE,yBAAyB,EAAE,MAAM,gEAAgE,CAAC;AAC3G,OAAO,EAAE,iCAAiC,EAAE,MAAM,+CAA+C,CAAC;AAGlG,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAAC,KAM9C;IACC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAC;IAC9E,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAClB,MAAM,MAAM,GAAG,MAAM,yBAAyB,CAC5C,iCAAiC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,EACnD,KAAK,CAAC,MAAM,CAAC,UAAU,CACxB,CAAC;QACF,IAAI,MAAM,EAAE,EAAE,KAAK,KAAK,CAAC,MAAM,CAAC,EAAE;YAChC,MAAM,IAAI,KAAK,CACb,6DAA6D,CAC9D,CAAC;QACJ,OAAO;IACT,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,gCAAgC,CAAC,oBAAoB,CACzE,KAAK,CAAC,OAAO,EACb;QACE,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,UAAU;QACnC,gBAAgB,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE;QACjC,iBAAiB,EAAE,KAAK,CAAC,MAAM,CAAC,SAAS;KAC1C,CACF,CAAC;IACF,IAAI,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CACb,6DAA6D,CAC9D,CAAC;IACJ,CAAC;IACD,MAAM,yCAAyC,CAAC,oBAAoB,CAClE,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,MAAM,CAAC,UAAU,EACvB,KAAK,CAAC,kBAAkB,CACzB,CAAC;AACJ,CAAC","sourcesContent":["import { sqlDocumentContainerProjectionPersistence } from \"../../../data/persistence/container-contents/documentContainerProjectionPersistence\";\nimport {\n type DocumentMoveIntentRecord,\n sqlDocumentMoveIntentPersistence,\n} from \"../../../data/persistence/container-contents/documentMoveIntentPersistence\";\nimport { loadDocumentMovePlacement } from \"../../../data/persistence/container-contents/documentPlacement\";\nimport { getClientSQLitePersistenceRuntime } from \"../../../data/sqlite/sqlitePersistenceRuntime\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\n\nexport async function settleDocumentMoveIntent(input: {\n execSql: ExecSql;\n intent: DocumentMoveIntentRecord;\n isCurrent: () => boolean;\n linkedContainerIds: readonly string[];\n partial: boolean;\n}): Promise<void> {\n if (!input.isCurrent()) {\n throw new Error(\"Document move generation changed before local settlement\");\n }\n if (input.partial) {\n const intent = await loadDocumentMovePlacement(\n getClientSQLitePersistenceRuntime(input.execSql).db,\n input.intent.documentId,\n );\n if (intent?.id !== input.intent.id)\n throw new Error(\n \"Document move intent was superseded before local settlement\",\n );\n return;\n }\n const settled = await sqlDocumentMoveIntentPersistence.markMoveIntentSynced(\n input.execSql,\n {\n documentId: input.intent.documentId,\n expectedIntentId: input.intent.id,\n expectedUpdatedAt: input.intent.updatedAt,\n },\n );\n if (!settled || !input.isCurrent()) {\n throw new Error(\n \"Document move intent was superseded before local settlement\",\n );\n }\n await sqlDocumentContainerProjectionPersistence.replaceDocumentLinks(\n input.execSql,\n input.intent.documentId,\n input.linkedContainerIds,\n );\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { sqlDocumentContainerProjectionPersistence } from "../../../data/persistence/
|
|
1
|
+
import { sqlDocumentContainerProjectionPersistence } from "../../../data/persistence/container-contents/documentContainerProjectionPersistence.js";
|
|
2
2
|
import { containerDocumentPlacementKey, listContainerDocumentTombstoneHoldsForDocuments, } from "../../../data/persistence/documents/containerDocumentTombstoneHoldsPersistence.js";
|
|
3
3
|
import { sqlDocumentsPersistence } from "../../../data/persistence/documents/documentsPersistence.js";
|
|
4
4
|
import { compareContainerContentsDocumentSummaries } from "./rows.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"documentSubtreeQueries.js","sourceRoot":"","sources":["documentSubtreeQueries.ts"],"names":[],"mappings":"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","sourcesContent":["import type { DocumentSummary } from \"../../../data/documents/documentSummary\";\nimport { sqlDocumentContainerProjectionPersistence } from \"../../../data/persistence/containers/documentContainerProjectionPersistence\";\nimport {\n containerDocumentPlacementKey,\n listContainerDocumentTombstoneHoldsForDocuments,\n} from \"../../../data/persistence/documents/containerDocumentTombstoneHoldsPersistence\";\nimport { sqlDocumentsPersistence } from \"../../../data/persistence/documents/documentsPersistence\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport { compareContainerContentsDocumentSummaries } from \"./rows\";\nimport { listContainerContentsSqlIdBatches } from \"./sql\";\nimport type {\n ContainerContentsContainerSubtreeState,\n ContainerContentsDocumentRuntimeTarget,\n ContainerContentsSharedDocumentSummaries,\n ContainerDocumentQueriesRuntime,\n} from \"./types\";\n\nfunction addContainerContentsDocumentSummaries(\n documentSummariesById: Map<string, DocumentSummary>,\n documentSummaries: ReadonlyArray<DocumentSummary>,\n): void {\n for (const documentSummary of documentSummaries) {\n documentSummariesById.set(documentSummary.id, documentSummary);\n }\n}\n\nasync function listContainerContentsDocumentIdsByContainerIds(\n execSql: ExecSql,\n containerIds: ReadonlyArray<string>,\n): Promise<string[]> {\n const documentIds = new Set<string>();\n\n for (const containerIdBatch of listContainerContentsSqlIdBatches(\n containerIds,\n )) {\n const batchDocumentIds =\n await sqlDocumentContainerProjectionPersistence.listDocumentIdsByContainerIds(\n execSql,\n containerIdBatch,\n );\n for (const documentId of batchDocumentIds) {\n documentIds.add(documentId);\n }\n }\n\n return Array.from(documentIds).sort();\n}\n\nasync function listContainerContentsDocumentSummariesByContainerIdsOrDocumentIds(\n execSql: ExecSql,\n input: {\n containerIds: ReadonlyArray<string>;\n documentIds: ReadonlyArray<string>;\n sortDocumentSummaries: boolean;\n },\n): Promise<DocumentSummary[]> {\n const documentSummariesById = new Map<string, DocumentSummary>();\n\n for (const containerIdBatch of listContainerContentsSqlIdBatches(\n input.containerIds,\n )) {\n addContainerContentsDocumentSummaries(\n documentSummariesById,\n await sqlDocumentsPersistence.listDocumentsByContainerIdsOrDocumentIds(\n execSql,\n {\n containerIds: containerIdBatch,\n documentIds: [],\n },\n ),\n );\n }\n\n for (const documentIdBatch of listContainerContentsSqlIdBatches(\n input.documentIds,\n )) {\n addContainerContentsDocumentSummaries(\n documentSummariesById,\n await sqlDocumentsPersistence.listDocumentsByContainerIdsOrDocumentIds(\n execSql,\n {\n containerIds: [],\n documentIds: documentIdBatch,\n },\n ),\n );\n }\n\n const documentSummaries = Array.from(documentSummariesById.values());\n return input.sortDocumentSummaries\n ? documentSummaries.sort(compareContainerContentsDocumentSummaries)\n : documentSummaries;\n}\n\nfunction heldPlacementKey(\n documentId: string | null,\n containerId: string,\n): string {\n return containerDocumentPlacementKey({\n containerId,\n documentId: documentId ?? \"\",\n });\n}\n\nfunction withoutHeldPlacements(\n linkedContainerIdsByDocumentId: ReadonlyMap<string, ReadonlyArray<string>>,\n holds: ReadonlyArray<{ containerId: string; documentId: string }>,\n): {\n held: ReadonlySet<string>;\n links: ReadonlyMap<string, ReadonlyArray<string>>;\n} {\n const held = new Set(\n holds.map((hold) => heldPlacementKey(hold.documentId, hold.containerId)),\n );\n if (held.size === 0) {\n return { held, links: linkedContainerIdsByDocumentId };\n }\n return {\n held,\n links: new Map(\n Array.from(linkedContainerIdsByDocumentId, ([documentId, ids]) => [\n documentId,\n ids.filter((id) => !held.has(heldPlacementKey(documentId, id))),\n ]),\n ),\n };\n}\n\n/**\n * Shared batched read pipeline for a flat set of container ids: linked\n * document ids → document summaries → linked container ids per document.\n * Sorting is optional so device-first projection reads can skip it.\n */\nexport async function listContainerContentsDocumentsForContainers(\n execSql: ExecSql,\n containerIds: ReadonlyArray<string>,\n options: { sortDocumentSummaries: boolean },\n): Promise<ContainerContentsSharedDocumentSummaries> {\n await sqlDocumentsPersistence.ensureSchema(execSql);\n const linkedDocumentIds =\n await listContainerContentsDocumentIdsByContainerIds(execSql, containerIds);\n const documentSummaries =\n await listContainerContentsDocumentSummariesByContainerIdsOrDocumentIds(\n execSql,\n {\n containerIds,\n documentIds: linkedDocumentIds,\n sortDocumentSummaries: options.sortDocumentSummaries,\n },\n );\n const documentIds = Array.from(\n new Set(\n documentSummaries.flatMap((documentSummary) =>\n documentSummary.documentId ? [documentSummary.documentId] : [],\n ),\n ),\n );\n const linkedContainerIdsByDocumentId = withoutHeldPlacements(\n await sqlDocumentContainerProjectionPersistence.listLinkedContainerIdsByDocumentIds(\n execSql,\n documentIds,\n ),\n await listContainerDocumentTombstoneHoldsForDocuments(execSql, documentIds),\n );\n\n // An earlier link-id read can race a move. Recheck membership against the\n // summaries and final link read so a fresh trash summary cannot ride stale\n // root ids into the root view. Notification fences reject older summaries.\n // A held placement (a listing tombstone awaiting signed evidence) is not a\n // membership here either, matching the container item and sidebar views.\n const requestedIds = new Set(containerIds);\n return {\n documentSummaries: documentSummaries.filter(\n (summary) =>\n (summary.containerId !== null &&\n requestedIds.has(summary.containerId) &&\n !linkedContainerIdsByDocumentId.held.has(\n heldPlacementKey(summary.documentId, summary.containerId),\n )) ||\n (summary.documentId !== null &&\n linkedContainerIdsByDocumentId.links\n .get(summary.documentId)\n ?.some((id) => requestedIds.has(id))),\n ),\n linkedContainerIdsByDocumentId: linkedContainerIdsByDocumentId.links,\n };\n}\n\nfunction listContainerContentsContainerSubtreeIds(\n containersById: ReadonlyMap<string, ContainerContentsContainerSubtreeState>,\n rootContainerId: string,\n): string[] {\n const childrenByParentId = new Map<string, string[]>();\n for (const containerState of containersById.values()) {\n const parentId = containerState.container.parentId;\n if (parentId === null) {\n continue;\n }\n\n const children = childrenByParentId.get(parentId);\n if (children) {\n children.push(containerState.container.id);\n } else {\n childrenByParentId.set(parentId, [containerState.container.id]);\n }\n }\n\n const subtreeIds: string[] = [];\n const stack = [rootContainerId];\n const visited = new Set<string>();\n while (stack.length > 0) {\n const containerId = stack.pop();\n if (containerId === undefined || visited.has(containerId)) {\n continue;\n }\n visited.add(containerId);\n\n if (containersById.has(containerId)) {\n subtreeIds.push(containerId);\n }\n\n const children = childrenByParentId.get(containerId);\n if (children) {\n stack.push(...children);\n }\n }\n\n return subtreeIds;\n}\n\nfunction resolveContainerContentsDocumentRuntimeContainerId(params: {\n documentSummary: Pick<DocumentSummary, \"containerId\" | \"documentId\">;\n linkedContainerIdsByDocumentId: ReadonlyMap<string, ReadonlyArray<string>>;\n sharedContainerIds: ReadonlySet<string>;\n}): string | null {\n const {\n documentSummary,\n linkedContainerIdsByDocumentId,\n sharedContainerIds,\n } = params;\n if (\n documentSummary.containerId &&\n sharedContainerIds.has(documentSummary.containerId)\n ) {\n return documentSummary.containerId;\n }\n\n if (!documentSummary.documentId) {\n return null;\n }\n\n return (\n linkedContainerIdsByDocumentId\n .get(documentSummary.documentId)\n ?.find((containerId) => sharedContainerIds.has(containerId)) ?? null\n );\n}\n\nasync function listDocumentRuntimeTargetsForContainerSubtree(input: {\n containersById: ReadonlyMap<string, ContainerContentsContainerSubtreeState>;\n execSql: ExecSql;\n rootContainerId: string;\n}): Promise<ContainerContentsDocumentRuntimeTarget[]> {\n const { containersById, execSql, rootContainerId } = input;\n const sharedContainerIds = new Set(\n listContainerContentsContainerSubtreeIds(containersById, rootContainerId),\n );\n if (sharedContainerIds.size === 0) {\n return [];\n }\n\n const { documentSummaries, linkedContainerIdsByDocumentId } =\n await listContainerContentsDocumentsForContainers(\n execSql,\n Array.from(sharedContainerIds),\n { sortDocumentSummaries: true },\n );\n\n return documentSummaries.flatMap((documentSummary) => {\n const runtimeContainerId =\n resolveContainerContentsDocumentRuntimeContainerId({\n documentSummary,\n linkedContainerIdsByDocumentId,\n sharedContainerIds,\n });\n if (!runtimeContainerId) {\n return [];\n }\n\n return [\n {\n documentId: documentSummary.documentId,\n localId: documentSummary.id,\n runtimeContainerId,\n },\n ];\n });\n}\n\nexport function listDocumentRuntimeTargetsForContainerSubtreeFromRuntime({\n runtime,\n ...input\n}: Omit<\n Parameters<typeof listDocumentRuntimeTargetsForContainerSubtree>[0],\n \"execSql\"\n> & {\n runtime: ContainerDocumentQueriesRuntime;\n}): ReturnType<typeof listDocumentRuntimeTargetsForContainerSubtree> {\n return listDocumentRuntimeTargetsForContainerSubtree({\n ...input,\n execSql: runtime.infra.execSql,\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"documentSubtreeQueries.js","sourceRoot":"","sources":["documentSubtreeQueries.ts"],"names":[],"mappings":"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","sourcesContent":["import type { DocumentSummary } from \"../../../data/documents/documentSummary\";\nimport { sqlDocumentContainerProjectionPersistence } from \"../../../data/persistence/container-contents/documentContainerProjectionPersistence\";\nimport {\n containerDocumentPlacementKey,\n listContainerDocumentTombstoneHoldsForDocuments,\n} from \"../../../data/persistence/documents/containerDocumentTombstoneHoldsPersistence\";\nimport { sqlDocumentsPersistence } from \"../../../data/persistence/documents/documentsPersistence\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport { compareContainerContentsDocumentSummaries } from \"./rows\";\nimport { listContainerContentsSqlIdBatches } from \"./sql\";\nimport type {\n ContainerContentsContainerSubtreeState,\n ContainerContentsDocumentRuntimeTarget,\n ContainerContentsSharedDocumentSummaries,\n ContainerDocumentQueriesRuntime,\n} from \"./types\";\n\nfunction addContainerContentsDocumentSummaries(\n documentSummariesById: Map<string, DocumentSummary>,\n documentSummaries: ReadonlyArray<DocumentSummary>,\n): void {\n for (const documentSummary of documentSummaries) {\n documentSummariesById.set(documentSummary.id, documentSummary);\n }\n}\n\nasync function listContainerContentsDocumentIdsByContainerIds(\n execSql: ExecSql,\n containerIds: ReadonlyArray<string>,\n): Promise<string[]> {\n const documentIds = new Set<string>();\n\n for (const containerIdBatch of listContainerContentsSqlIdBatches(\n containerIds,\n )) {\n const batchDocumentIds =\n await sqlDocumentContainerProjectionPersistence.listDocumentIdsByContainerIds(\n execSql,\n containerIdBatch,\n );\n for (const documentId of batchDocumentIds) {\n documentIds.add(documentId);\n }\n }\n\n return Array.from(documentIds).sort();\n}\n\nasync function listContainerContentsDocumentSummariesByContainerIdsOrDocumentIds(\n execSql: ExecSql,\n input: {\n containerIds: ReadonlyArray<string>;\n documentIds: ReadonlyArray<string>;\n sortDocumentSummaries: boolean;\n },\n): Promise<DocumentSummary[]> {\n const documentSummariesById = new Map<string, DocumentSummary>();\n\n for (const containerIdBatch of listContainerContentsSqlIdBatches(\n input.containerIds,\n )) {\n addContainerContentsDocumentSummaries(\n documentSummariesById,\n await sqlDocumentsPersistence.listDocumentsByContainerIdsOrDocumentIds(\n execSql,\n {\n containerIds: containerIdBatch,\n documentIds: [],\n },\n ),\n );\n }\n\n for (const documentIdBatch of listContainerContentsSqlIdBatches(\n input.documentIds,\n )) {\n addContainerContentsDocumentSummaries(\n documentSummariesById,\n await sqlDocumentsPersistence.listDocumentsByContainerIdsOrDocumentIds(\n execSql,\n {\n containerIds: [],\n documentIds: documentIdBatch,\n },\n ),\n );\n }\n\n const documentSummaries = Array.from(documentSummariesById.values());\n return input.sortDocumentSummaries\n ? documentSummaries.sort(compareContainerContentsDocumentSummaries)\n : documentSummaries;\n}\n\nfunction heldPlacementKey(\n documentId: string | null,\n containerId: string,\n): string {\n return containerDocumentPlacementKey({\n containerId,\n documentId: documentId ?? \"\",\n });\n}\n\nfunction withoutHeldPlacements(\n linkedContainerIdsByDocumentId: ReadonlyMap<string, ReadonlyArray<string>>,\n holds: ReadonlyArray<{ containerId: string; documentId: string }>,\n): {\n held: ReadonlySet<string>;\n links: ReadonlyMap<string, ReadonlyArray<string>>;\n} {\n const held = new Set(\n holds.map((hold) => heldPlacementKey(hold.documentId, hold.containerId)),\n );\n if (held.size === 0) {\n return { held, links: linkedContainerIdsByDocumentId };\n }\n return {\n held,\n links: new Map(\n Array.from(linkedContainerIdsByDocumentId, ([documentId, ids]) => [\n documentId,\n ids.filter((id) => !held.has(heldPlacementKey(documentId, id))),\n ]),\n ),\n };\n}\n\n/**\n * Shared batched read pipeline for a flat set of container ids: linked\n * document ids → document summaries → linked container ids per document.\n * Sorting is optional so device-first projection reads can skip it.\n */\nexport async function listContainerContentsDocumentsForContainers(\n execSql: ExecSql,\n containerIds: ReadonlyArray<string>,\n options: { sortDocumentSummaries: boolean },\n): Promise<ContainerContentsSharedDocumentSummaries> {\n await sqlDocumentsPersistence.ensureSchema(execSql);\n const linkedDocumentIds =\n await listContainerContentsDocumentIdsByContainerIds(execSql, containerIds);\n const documentSummaries =\n await listContainerContentsDocumentSummariesByContainerIdsOrDocumentIds(\n execSql,\n {\n containerIds,\n documentIds: linkedDocumentIds,\n sortDocumentSummaries: options.sortDocumentSummaries,\n },\n );\n const documentIds = Array.from(\n new Set(\n documentSummaries.flatMap((documentSummary) =>\n documentSummary.documentId ? [documentSummary.documentId] : [],\n ),\n ),\n );\n const linkedContainerIdsByDocumentId = withoutHeldPlacements(\n await sqlDocumentContainerProjectionPersistence.listLinkedContainerIdsByDocumentIds(\n execSql,\n documentIds,\n ),\n await listContainerDocumentTombstoneHoldsForDocuments(execSql, documentIds),\n );\n\n // An earlier link-id read can race a move. Recheck membership against the\n // summaries and final link read so a fresh trash summary cannot ride stale\n // root ids into the root view. Notification fences reject older summaries.\n // A held placement (a listing tombstone awaiting signed evidence) is not a\n // membership here either, matching the container item and sidebar views.\n const requestedIds = new Set(containerIds);\n return {\n documentSummaries: documentSummaries.filter(\n (summary) =>\n (summary.containerId !== null &&\n requestedIds.has(summary.containerId) &&\n !linkedContainerIdsByDocumentId.held.has(\n heldPlacementKey(summary.documentId, summary.containerId),\n )) ||\n (summary.documentId !== null &&\n linkedContainerIdsByDocumentId.links\n .get(summary.documentId)\n ?.some((id) => requestedIds.has(id))),\n ),\n linkedContainerIdsByDocumentId: linkedContainerIdsByDocumentId.links,\n };\n}\n\nfunction listContainerContentsContainerSubtreeIds(\n containersById: ReadonlyMap<string, ContainerContentsContainerSubtreeState>,\n rootContainerId: string,\n): string[] {\n const childrenByParentId = new Map<string, string[]>();\n for (const containerState of containersById.values()) {\n const parentId = containerState.container.parentId;\n if (parentId === null) {\n continue;\n }\n\n const children = childrenByParentId.get(parentId);\n if (children) {\n children.push(containerState.container.id);\n } else {\n childrenByParentId.set(parentId, [containerState.container.id]);\n }\n }\n\n const subtreeIds: string[] = [];\n const stack = [rootContainerId];\n const visited = new Set<string>();\n while (stack.length > 0) {\n const containerId = stack.pop();\n if (containerId === undefined || visited.has(containerId)) {\n continue;\n }\n visited.add(containerId);\n\n if (containersById.has(containerId)) {\n subtreeIds.push(containerId);\n }\n\n const children = childrenByParentId.get(containerId);\n if (children) {\n stack.push(...children);\n }\n }\n\n return subtreeIds;\n}\n\nfunction resolveContainerContentsDocumentRuntimeContainerId(params: {\n documentSummary: Pick<DocumentSummary, \"containerId\" | \"documentId\">;\n linkedContainerIdsByDocumentId: ReadonlyMap<string, ReadonlyArray<string>>;\n sharedContainerIds: ReadonlySet<string>;\n}): string | null {\n const {\n documentSummary,\n linkedContainerIdsByDocumentId,\n sharedContainerIds,\n } = params;\n if (\n documentSummary.containerId &&\n sharedContainerIds.has(documentSummary.containerId)\n ) {\n return documentSummary.containerId;\n }\n\n if (!documentSummary.documentId) {\n return null;\n }\n\n return (\n linkedContainerIdsByDocumentId\n .get(documentSummary.documentId)\n ?.find((containerId) => sharedContainerIds.has(containerId)) ?? null\n );\n}\n\nasync function listDocumentRuntimeTargetsForContainerSubtree(input: {\n containersById: ReadonlyMap<string, ContainerContentsContainerSubtreeState>;\n execSql: ExecSql;\n rootContainerId: string;\n}): Promise<ContainerContentsDocumentRuntimeTarget[]> {\n const { containersById, execSql, rootContainerId } = input;\n const sharedContainerIds = new Set(\n listContainerContentsContainerSubtreeIds(containersById, rootContainerId),\n );\n if (sharedContainerIds.size === 0) {\n return [];\n }\n\n const { documentSummaries, linkedContainerIdsByDocumentId } =\n await listContainerContentsDocumentsForContainers(\n execSql,\n Array.from(sharedContainerIds),\n { sortDocumentSummaries: true },\n );\n\n return documentSummaries.flatMap((documentSummary) => {\n const runtimeContainerId =\n resolveContainerContentsDocumentRuntimeContainerId({\n documentSummary,\n linkedContainerIdsByDocumentId,\n sharedContainerIds,\n });\n if (!runtimeContainerId) {\n return [];\n }\n\n return [\n {\n documentId: documentSummary.documentId,\n localId: documentSummary.id,\n runtimeContainerId,\n },\n ];\n });\n}\n\nexport function listDocumentRuntimeTargetsForContainerSubtreeFromRuntime({\n runtime,\n ...input\n}: Omit<\n Parameters<typeof listDocumentRuntimeTargetsForContainerSubtree>[0],\n \"execSql\"\n> & {\n runtime: ContainerDocumentQueriesRuntime;\n}): ReturnType<typeof listDocumentRuntimeTargetsForContainerSubtree> {\n return listDocumentRuntimeTargetsForContainerSubtree({\n ...input,\n execSql: runtime.infra.execSql,\n });\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { ensureContainerTables } from "../../../data/persistence/container-contents/containerPersistence.js";
|
|
1
2
|
import { hasRetainedContainerMetadata, listRecoveryFolderMoveIds, } from "../../../data/persistence/container-contents/containerRecoveryPersistence.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { sqlDocumentContainerProjectionPersistence } from "../../../data/persistence/containers/documentContainerProjectionPersistence.js";
|
|
3
|
+
import { containerContentsSyncLane, sqlContainerSyncWatermarkPersistence, } from "../../../data/persistence/container-contents/containerSyncWatermarkPersistence.js";
|
|
4
|
+
import { sqlDocumentContainerProjectionPersistence } from "../../../data/persistence/container-contents/documentContainerProjectionPersistence.js";
|
|
5
5
|
import { applyContainerDocumentTombstones as applyPersistedContainerDocumentTombstones, sqlDocumentsPersistence, upsertDiscoveredDocuments, } from "../../../data/persistence/documents/documentsPersistence.js";
|
|
6
6
|
import { localIntentTables } from "../../../data/sqlite/schema/index.js";
|
|
7
7
|
import { ensureSqlTables } from "../../../data/sqlite/sqlSchema.js";
|