@tearleads/client-sdk 0.1.60 → 0.1.62
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/Tearleads.d.ts +8 -48
- package/Tearleads.js +18 -25
- package/Tearleads.js.map +1 -1
- package/TearleadsOptions.d.ts +49 -0
- package/TearleadsOptions.js +2 -0
- package/TearleadsOptions.js.map +1 -0
- package/client/containerContents/documentDiscovery.js +5 -5
- package/client/containerContents/documentDiscovery.js.map +1 -1
- package/client/containerContents/index.d.ts +7 -7
- package/client/containerContents/index.js +7 -7
- package/client/containerContents/index.js.map +1 -1
- package/client/containerContents/types.d.ts +6 -6
- package/client/containerContents/types.js.map +1 -1
- package/client/deviceFirst/index.js +2 -2
- package/client/deviceFirst/index.js.map +1 -1
- package/client/root/index.d.ts +1 -1
- package/client/root/index.js.map +1 -1
- package/client/runtime/workflowRuntime.d.ts +1 -1
- package/client/runtime/workflowRuntime.js.map +1 -1
- package/index.d.ts +2 -1
- package/index.js +1 -1
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/stores/container-contents/containerStatePersistence.js +1 -1
- package/stores/container-contents/documentRecovery.js +2 -2
- package/stores/container-contents/documentRecovery.js.map +1 -1
- package/stores/container-contents/documentWork.js.map +1 -1
- package/stores/container-contents/localRefresh.js +2 -2
- package/stores/container-contents/localRefresh.js.map +1 -1
- package/stores/container-contents/operations.js +2 -2
- package/stores/container-contents/operations.js.map +1 -1
- package/stores/container-contents/remoteContainerIngestion.js +1 -1
- package/stores/container-contents/remoteEventSync.js +1 -1
- package/stores/container-contents/remoteHydrationRequest.js +1 -1
- package/stores/container-contents/setContainerIconOperation.js +2 -2
- package/stores/container-contents/setContainerIconOperation.js.map +1 -1
- package/stores/container-contents/shareOperations.js +1 -1
- package/stores/container-contents/startupHydration.js +1 -1
- package/stores/container-contents/syncAgent.d.ts +2 -2
- package/stores/container-contents/syncAgentTypes.d.ts +1 -1
- package/stores/container-contents/syncLaneIteration.js +2 -2
- package/stores/container-contents/syncLaneIteration.js.map +1 -1
- package/stores/container-contents/systemContainerIcon.js +1 -1
- package/stores/container-contents/systemContainerIcon.js.map +1 -1
- package/workflows/container-contents/{documentAttributionRanges.d.ts → attribution/documentAttributionRanges.d.ts} +1 -1
- package/workflows/container-contents/{documentCharacterBlame.js → attribution/documentCharacterBlame.js} +3 -3
- package/workflows/container-contents/attribution/documentCharacterBlame.js.map +1 -0
- package/workflows/container-contents/{documentFieldBlame.js → attribution/documentFieldBlame.js} +4 -4
- package/workflows/container-contents/attribution/documentFieldBlame.js.map +1 -0
- package/workflows/container-contents/container-state/createIntentSync.js +1 -1
- package/workflows/container-contents/container-state/createIntentSync.js.map +1 -1
- package/workflows/container-contents/container-state/moveIntentSync.js +1 -1
- package/workflows/container-contents/container-state/moveIntentSync.js.map +1 -1
- package/workflows/container-contents/container-state/purgeTree.js +2 -2
- package/workflows/container-contents/container-state/purgeTree.js.map +1 -1
- package/workflows/container-contents/container-state/sharePersistence.js +2 -2
- package/workflows/container-contents/container-state/sharePersistence.js.map +1 -1
- package/workflows/container-contents/{containerDocumentListing.js → documentDiscovery/containerDocumentListing.js} +1 -1
- package/workflows/container-contents/{documentDiscoveryApply.js → documentDiscovery/documentDiscoveryApply.js} +3 -3
- package/workflows/container-contents/documentDiscovery/documentDiscoveryApply.js.map +1 -0
- package/workflows/container-contents/{documentDiscoveryCandidates.js.map → documentDiscovery/documentDiscoveryCandidates.js.map} +1 -1
- package/workflows/container-contents/{documentDiscoveryEvidence.js → documentDiscovery/documentDiscoveryEvidence.js} +1 -1
- package/workflows/container-contents/documentDiscovery/documentDiscoveryEvidence.js.map +1 -0
- package/workflows/container-contents/{documentDiscoveryInputs.js → documentDiscovery/documentDiscoveryInputs.js} +2 -2
- package/workflows/container-contents/documentDiscovery/documentDiscoveryInputs.js.map +1 -0
- package/workflows/container-contents/documentDiscovery/documentDiscoveryLanes.js.map +1 -0
- package/workflows/container-contents/{documentDiscoveryTypes.d.ts → documentDiscovery/documentDiscoveryTypes.d.ts} +4 -4
- package/workflows/container-contents/documentDiscovery/documentDiscoveryTypes.js.map +1 -0
- package/workflows/container-contents/{documentDiscovery.d.ts → documentDiscovery/index.d.ts} +1 -1
- package/workflows/container-contents/{documentDiscovery.js → documentDiscovery/index.js} +5 -5
- package/workflows/container-contents/documentDiscovery/index.js.map +1 -0
- package/workflows/container-contents/{availableDocumentLinkIntent.js → documentLinks/availableDocumentLinkIntent.js} +1 -1
- package/workflows/container-contents/documentLinks/availableDocumentLinkIntent.js.map +1 -0
- package/workflows/container-contents/{deferredDocumentLinks.js → documentLinks/deferredDocumentLinks.js} +1 -1
- package/workflows/container-contents/documentLinks/deferredDocumentLinks.js.map +1 -0
- package/workflows/container-contents/{documentLinkIntent.js → documentLinks/documentLinkIntent.js} +4 -4
- package/workflows/container-contents/documentLinks/documentLinkIntent.js.map +1 -0
- package/workflows/container-contents/documentLinks/documentLocalRelink.js.map +1 -0
- package/workflows/container-contents/{documentLinks.d.ts → documentLinks/index.d.ts} +5 -5
- package/workflows/container-contents/{documentLinks.js → documentLinks/index.js} +10 -10
- package/workflows/container-contents/documentLinks/index.js.map +1 -0
- package/workflows/container-contents/documentMove/documentMoveDeniedReplay.js.map +1 -0
- package/workflows/container-contents/{documentMoveFailure.js → documentMove/documentMoveFailure.js} +1 -1
- package/workflows/container-contents/documentMove/documentMoveFailure.js.map +1 -0
- package/workflows/container-contents/{documentMoveIntent.js → documentMove/documentMoveIntent.js} +7 -7
- package/workflows/container-contents/documentMove/documentMoveIntent.js.map +1 -0
- package/workflows/container-contents/{documentMoveIntentErrors.js → documentMove/documentMoveIntentErrors.js} +1 -1
- package/workflows/container-contents/documentMove/documentMoveIntentErrors.js.map +1 -0
- package/workflows/container-contents/{documentMoveIntentSettlement.js → documentMove/documentMoveIntentSettlement.js} +4 -4
- package/workflows/container-contents/documentMove/documentMoveIntentSettlement.js.map +1 -0
- package/workflows/container-contents/{documentMoveIntentSync.js → documentMove/documentMoveIntentSync.js} +7 -7
- package/workflows/container-contents/documentMove/documentMoveIntentSync.js.map +1 -0
- package/workflows/container-contents/{documentMoveVanishedRefresh.js → documentMove/documentMoveVanishedRefresh.js} +3 -3
- package/workflows/container-contents/documentMove/documentMoveVanishedRefresh.js.map +1 -0
- package/workflows/container-contents/{documentHydrationProbe.js → documentPriming/documentHydrationProbe.js} +4 -4
- package/workflows/container-contents/documentPriming/documentHydrationProbe.js.map +1 -0
- package/workflows/container-contents/documentPriming/documentRuntimeTargetSync.js.map +1 -0
- package/workflows/container-contents/{documentPriming.js → documentPriming/index.js} +5 -5
- package/workflows/container-contents/documentPriming/index.js.map +1 -0
- package/workflows/container-contents/{documentStructure.d.ts → documentQueries/documentStructure.d.ts} +1 -1
- package/workflows/container-contents/{documentStructure.js → documentQueries/documentStructure.js} +4 -4
- package/workflows/container-contents/documentQueries/documentStructure.js.map +1 -0
- package/workflows/container-contents/{documentStructureTypes.d.ts → documentQueries/documentStructureTypes.d.ts} +4 -4
- package/workflows/container-contents/documentQueries/documentStructureTypes.js.map +1 -0
- package/workflows/container-contents/{documentSubtreeQueries.js → documentQueries/documentSubtreeQueries.js} +5 -5
- package/workflows/container-contents/documentQueries/documentSubtreeQueries.js.map +1 -0
- package/workflows/container-contents/{documentQueries.d.ts → documentQueries/index.d.ts} +8 -8
- package/workflows/container-contents/{documentQueries.js → documentQueries/index.js} +13 -13
- package/workflows/container-contents/documentQueries/index.js.map +1 -0
- package/workflows/container-contents/{orphanedDocumentSql.js → documentQueries/orphanedDocumentSql.js} +1 -1
- package/workflows/container-contents/documentQueries/orphanedDocumentSql.js.map +1 -0
- package/workflows/container-contents/{pendingDownloads.d.ts → documentQueries/pendingDownloads.d.ts} +1 -1
- package/workflows/container-contents/{pendingDownloads.js → documentQueries/pendingDownloads.js} +3 -3
- package/workflows/container-contents/documentQueries/pendingDownloads.js.map +1 -0
- package/workflows/container-contents/documentQueries/sql.js +1 -1
- package/workflows/container-contents/documentQueries/sql.js.map +1 -1
- package/workflows/container-contents/index.d.ts +13 -13
- package/workflows/container-contents/index.js +11 -11
- package/workflows/container-contents/index.js.map +1 -1
- package/workflows/container-contents/{blobInfo.d.ts → info/blobInfo.d.ts} +1 -1
- package/workflows/container-contents/{blobInfo.js → info/blobInfo.js} +4 -4
- package/workflows/container-contents/info/blobInfo.js.map +1 -0
- package/workflows/container-contents/{blobInfoTypes.d.ts → info/blobInfoTypes.d.ts} +1 -1
- package/workflows/container-contents/info/blobInfoTypes.js.map +1 -0
- package/workflows/container-contents/{containerInfo.d.ts → info/containerInfo.d.ts} +4 -4
- package/workflows/container-contents/{containerInfo.js → info/containerInfo.js} +5 -5
- package/workflows/container-contents/info/containerInfo.js.map +1 -0
- package/workflows/container-contents/{documentInfo.d.ts → info/documentInfo.d.ts} +3 -3
- package/workflows/container-contents/{documentInfo.js → info/documentInfo.js} +11 -11
- package/workflows/container-contents/info/documentInfo.js.map +1 -0
- package/workflows/container-contents/{documentInfoTypes.d.ts → info/documentInfoTypes.d.ts} +3 -3
- package/workflows/container-contents/info/documentInfoTypes.js.map +1 -0
- package/workflows/container-contents/{metadata.d.ts → metadata/index.d.ts} +2 -2
- package/workflows/container-contents/{metadata.js → metadata/index.js} +5 -5
- package/workflows/container-contents/metadata/index.js.map +1 -0
- package/workflows/container-contents/{metadataEvents.d.ts → metadata/metadataEvents.d.ts} +1 -1
- package/workflows/container-contents/{metadataEvents.js → metadata/metadataEvents.js} +1 -1
- package/workflows/container-contents/metadata/metadataEvents.js.map +1 -0
- package/workflows/container-contents/{metadataIncomingUpdateIsolation.js → metadata/metadataIncomingUpdateIsolation.js} +5 -5
- package/workflows/container-contents/metadata/metadataIncomingUpdateIsolation.js.map +1 -0
- package/workflows/container-contents/{metadataMutationPreparation.d.ts → metadata/metadataMutationPreparation.d.ts} +7 -7
- package/workflows/container-contents/{metadataMutationPreparation.js → metadata/metadataMutationPreparation.js} +5 -5
- package/workflows/container-contents/metadata/metadataMutationPreparation.js.map +1 -0
- package/workflows/container-contents/{metadataPersistence.d.ts → metadata/metadataPersistence.d.ts} +2 -2
- package/workflows/container-contents/{metadataPersistence.js → metadata/metadataPersistence.js} +4 -4
- package/workflows/container-contents/metadata/metadataPersistence.js.map +1 -0
- package/workflows/container-contents/{metadataPullContinuationInvalidation.js → metadata/metadataPullContinuationInvalidation.js} +4 -4
- package/workflows/container-contents/metadata/metadataPullContinuationInvalidation.js.map +1 -0
- package/workflows/container-contents/{metadataReadState.d.ts → metadata/metadataReadState.d.ts} +1 -1
- package/workflows/container-contents/metadata/metadataReadState.js.map +1 -0
- package/workflows/container-contents/{metadataRecord.js → metadata/metadataRecord.js} +2 -2
- package/workflows/container-contents/metadata/metadataRecord.js.map +1 -0
- package/workflows/container-contents/{metadataRemoteSync.d.ts → metadata/metadataRemoteSync.d.ts} +5 -5
- package/workflows/container-contents/{metadataRemoteSync.js → metadata/metadataRemoteSync.js} +3 -3
- package/workflows/container-contents/metadata/metadataRemoteSync.js.map +1 -0
- package/workflows/container-contents/{metadataStateInstallation.d.ts → metadata/metadataStateInstallation.d.ts} +1 -1
- package/workflows/container-contents/metadata/metadataStateInstallation.js.map +1 -0
- package/workflows/container-contents/{metadataStateIsolation.js → metadata/metadataStateIsolation.js} +3 -3
- package/workflows/container-contents/metadata/metadataStateIsolation.js.map +1 -0
- package/workflows/container-contents/{metadataSyncErrors.js → metadata/metadataSyncErrors.js} +3 -3
- package/workflows/container-contents/metadata/metadataSyncErrors.js.map +1 -0
- package/workflows/container-contents/{metadataSyncSettlement.d.ts → metadata/metadataSyncSettlement.d.ts} +2 -2
- package/workflows/container-contents/{metadataSyncSettlement.js → metadata/metadataSyncSettlement.js} +3 -3
- package/workflows/container-contents/metadata/metadataSyncSettlement.js.map +1 -0
- package/workflows/container-contents/{metadataTypes.d.ts → metadata/metadataTypes.d.ts} +5 -5
- package/workflows/container-contents/metadata/metadataTypes.js.map +1 -0
- package/workflows/container-contents/pendingWrites/aggregation.js.map +1 -1
- package/workflows/container-contents/pendingWrites/deferredTails.js.map +1 -1
- package/workflows/container-contents/{pendingWrites.d.ts → pendingWrites/index.d.ts} +1 -1
- package/workflows/container-contents/{pendingWrites.js → pendingWrites/index.js} +12 -12
- package/workflows/container-contents/pendingWrites/index.js.map +1 -0
- package/workflows/container-contents/projectionGeneration.js.map +1 -1
- package/workflows/container-contents/projectionKeys.d.ts +1 -1
- package/workflows/container-contents/projectionKeys.js.map +1 -1
- package/workflows/container-contents/projectionView.js +1 -1
- package/workflows/container-contents/projectionView.js.map +1 -1
- package/workflows/container-contents/{folderRecovery.d.ts → recovery/folderRecovery.d.ts} +1 -1
- package/workflows/container-contents/{folderRecovery.js → recovery/folderRecovery.js} +4 -4
- package/workflows/container-contents/recovery/folderRecovery.js.map +1 -0
- package/workflows/container-contents/{staleRootRecovery.js → recovery/staleRootRecovery.js} +1 -1
- package/workflows/container-contents/recovery/staleRootRecovery.js.map +1 -0
- package/workflows/container-contents/remoteHydration/completeHydration.js +1 -1
- package/workflows/container-contents/remoteHydration/completeHydration.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.d.ts → remoteHydration/index.d.ts} +2 -2
- package/workflows/container-contents/{remoteHydration.js → remoteHydration/index.js} +6 -6
- package/workflows/container-contents/remoteHydration/index.js.map +1 -0
- package/workflows/container-contents/{remoteContainerPageHydration.js → remoteHydration/remoteContainerPageHydration.js} +8 -8
- package/workflows/container-contents/remoteHydration/remoteContainerPageHydration.js.map +1 -0
- package/workflows/container-contents/{remoteContainerState.js → remoteHydration/remoteContainerState.js} +11 -11
- package/workflows/container-contents/remoteHydration/remoteContainerState.js.map +1 -0
- package/workflows/container-contents/remoteHydration/types.d.ts +1 -1
- package/workflows/container-contents/runtime.d.ts +1 -1
- package/workflows/container-contents/runtime.js.map +1 -1
- package/workflows/container-contents/{documentPurge.d.ts → tombstones/documentPurge.d.ts} +6 -6
- package/workflows/container-contents/{documentPurge.js → tombstones/documentPurge.js} +6 -6
- package/workflows/container-contents/tombstones/documentPurge.js.map +1 -0
- package/workflows/container-contents/{documentTombstoneEvidence.js → tombstones/documentTombstoneEvidence.js} +9 -9
- package/workflows/container-contents/tombstones/documentTombstoneEvidence.js.map +1 -0
- package/workflows/container-contents/{documentTombstoneGate.js → tombstones/documentTombstoneGate.js} +1 -1
- package/workflows/container-contents/tombstones/documentTombstoneGate.js.map +1 -0
- package/workflows/documents/projectionKeys.d.ts +1 -1
- package/workflows/documents/projectionKeys.js.map +1 -1
- package/workflows/documents/reportDocumentSyncQuarantine.js.map +1 -1
- package/workflows/documents/runtime.d.ts +1 -1
- package/workflows/documents/runtime.js.map +1 -1
- package/workflows/{runtimeInput.d.ts → shared/runtimeInput.d.ts} +6 -6
- package/workflows/shared/runtimeInput.js.map +1 -0
- package/workflows/container-contents/availableDocumentLinkIntent.js.map +0 -1
- package/workflows/container-contents/blobInfo.js.map +0 -1
- package/workflows/container-contents/blobInfoTypes.js.map +0 -1
- package/workflows/container-contents/containerInfo.js.map +0 -1
- package/workflows/container-contents/deferredDocumentLinks.js.map +0 -1
- package/workflows/container-contents/documentCharacterBlame.js.map +0 -1
- package/workflows/container-contents/documentDiscovery.js.map +0 -1
- package/workflows/container-contents/documentDiscoveryApply.js.map +0 -1
- package/workflows/container-contents/documentDiscoveryEvidence.js.map +0 -1
- package/workflows/container-contents/documentDiscoveryInputs.js.map +0 -1
- package/workflows/container-contents/documentDiscoveryLanes.js.map +0 -1
- package/workflows/container-contents/documentDiscoveryTypes.js.map +0 -1
- package/workflows/container-contents/documentFieldBlame.js.map +0 -1
- package/workflows/container-contents/documentHydrationProbe.js.map +0 -1
- package/workflows/container-contents/documentInfo.js.map +0 -1
- package/workflows/container-contents/documentInfoTypes.js.map +0 -1
- package/workflows/container-contents/documentLinkIntent.js.map +0 -1
- package/workflows/container-contents/documentLinks.js.map +0 -1
- package/workflows/container-contents/documentLocalRelink.js.map +0 -1
- package/workflows/container-contents/documentMoveDeniedReplay.js.map +0 -1
- package/workflows/container-contents/documentMoveFailure.js.map +0 -1
- package/workflows/container-contents/documentMoveIntent.js.map +0 -1
- package/workflows/container-contents/documentMoveIntentErrors.js.map +0 -1
- package/workflows/container-contents/documentMoveIntentSettlement.js.map +0 -1
- package/workflows/container-contents/documentMoveIntentSync.js.map +0 -1
- package/workflows/container-contents/documentMoveVanishedRefresh.js.map +0 -1
- package/workflows/container-contents/documentPriming.js.map +0 -1
- package/workflows/container-contents/documentPurge.js.map +0 -1
- package/workflows/container-contents/documentQueries.js.map +0 -1
- package/workflows/container-contents/documentRuntimeTargetSync.js.map +0 -1
- package/workflows/container-contents/documentStructure.js.map +0 -1
- package/workflows/container-contents/documentStructureTypes.js.map +0 -1
- package/workflows/container-contents/documentSubtreeQueries.js.map +0 -1
- package/workflows/container-contents/documentTombstoneEvidence.js.map +0 -1
- package/workflows/container-contents/documentTombstoneGate.js.map +0 -1
- package/workflows/container-contents/folderRecovery.js.map +0 -1
- package/workflows/container-contents/metadata.js.map +0 -1
- package/workflows/container-contents/metadataEvents.js.map +0 -1
- package/workflows/container-contents/metadataIncomingUpdateIsolation.js.map +0 -1
- package/workflows/container-contents/metadataMutationPreparation.js.map +0 -1
- package/workflows/container-contents/metadataPersistence.js.map +0 -1
- package/workflows/container-contents/metadataPullContinuationInvalidation.js.map +0 -1
- package/workflows/container-contents/metadataReadState.js.map +0 -1
- package/workflows/container-contents/metadataRecord.js.map +0 -1
- package/workflows/container-contents/metadataRemoteSync.js.map +0 -1
- package/workflows/container-contents/metadataStateInstallation.js.map +0 -1
- package/workflows/container-contents/metadataStateIsolation.js.map +0 -1
- package/workflows/container-contents/metadataSyncErrors.js.map +0 -1
- package/workflows/container-contents/metadataSyncSettlement.js.map +0 -1
- package/workflows/container-contents/metadataTypes.js.map +0 -1
- package/workflows/container-contents/orphanedDocumentSql.js.map +0 -1
- package/workflows/container-contents/pendingDownloads.js.map +0 -1
- package/workflows/container-contents/pendingWrites.js.map +0 -1
- package/workflows/container-contents/remoteContainerPageHydration.js.map +0 -1
- package/workflows/container-contents/remoteContainerState.js.map +0 -1
- package/workflows/container-contents/remoteHydration.js.map +0 -1
- package/workflows/container-contents/staleRootRecovery.js.map +0 -1
- package/workflows/runtimeInput.js.map +0 -1
- /package/workflows/container-contents/{documentAttributionRanges.js → attribution/documentAttributionRanges.js} +0 -0
- /package/workflows/container-contents/{documentAttributionRanges.js.map → attribution/documentAttributionRanges.js.map} +0 -0
- /package/workflows/container-contents/{containerDocumentListing.js.map → documentDiscovery/containerDocumentListing.js.map} +0 -0
- /package/workflows/container-contents/{documentDiscoveryCandidates.js → documentDiscovery/documentDiscoveryCandidates.js} +0 -0
- /package/workflows/container-contents/{documentDiscoveryLanes.js → documentDiscovery/documentDiscoveryLanes.js} +0 -0
- /package/workflows/container-contents/{documentDiscoveryTypes.js → documentDiscovery/documentDiscoveryTypes.js} +0 -0
- /package/workflows/container-contents/{documentHeadScope.js → documentDiscovery/documentHeadScope.js} +0 -0
- /package/workflows/container-contents/{documentHeadScope.js.map → documentDiscovery/documentHeadScope.js.map} +0 -0
- /package/workflows/container-contents/{documentLocalRelink.js → documentLinks/documentLocalRelink.js} +0 -0
- /package/workflows/container-contents/{documentMoveDeniedReplay.js → documentMove/documentMoveDeniedReplay.js} +0 -0
- /package/workflows/container-contents/{documentMoveUnlinkIds.js → documentMove/documentMoveUnlinkIds.js} +0 -0
- /package/workflows/container-contents/{documentMoveUnlinkIds.js.map → documentMove/documentMoveUnlinkIds.js.map} +0 -0
- /package/workflows/container-contents/{documentRuntimeTargetSync.js → documentPriming/documentRuntimeTargetSync.js} +0 -0
- /package/workflows/container-contents/{documentStructureTypes.js → documentQueries/documentStructureTypes.js} +0 -0
- /package/workflows/container-contents/{blobInfoRows.js → info/blobInfoRows.js} +0 -0
- /package/workflows/container-contents/{blobInfoRows.js.map → info/blobInfoRows.js.map} +0 -0
- /package/workflows/container-contents/{blobInfoTypes.js → info/blobInfoTypes.js} +0 -0
- /package/workflows/container-contents/{documentInfoTypes.js → info/documentInfoTypes.js} +0 -0
- /package/workflows/container-contents/{metadataReadState.js → metadata/metadataReadState.js} +0 -0
- /package/workflows/container-contents/{metadataStateInstallation.js → metadata/metadataStateInstallation.js} +0 -0
- /package/workflows/container-contents/{metadataSyncFollowup.js → metadata/metadataSyncFollowup.js} +0 -0
- /package/workflows/container-contents/{metadataSyncFollowup.js.map → metadata/metadataSyncFollowup.js.map} +0 -0
- /package/workflows/container-contents/{metadataSyncRegistrations.d.ts → metadata/metadataSyncRegistrations.d.ts} +0 -0
- /package/workflows/container-contents/{metadataSyncRegistrations.js → metadata/metadataSyncRegistrations.js} +0 -0
- /package/workflows/container-contents/{metadataSyncRegistrations.js.map → metadata/metadataSyncRegistrations.js.map} +0 -0
- /package/workflows/container-contents/{metadataTypes.js → metadata/metadataTypes.js} +0 -0
- /package/workflows/container-contents/{pendingWritesTypes.d.ts → pendingWrites/pendingWritesTypes.d.ts} +0 -0
- /package/workflows/container-contents/{pendingWritesTypes.js → pendingWrites/pendingWritesTypes.js} +0 -0
- /package/workflows/container-contents/{pendingWritesTypes.js.map → pendingWrites/pendingWritesTypes.js.map} +0 -0
- /package/workflows/container-contents/{remoteHydrationLog.js → remoteHydration/remoteHydrationLog.js} +0 -0
- /package/workflows/container-contents/{remoteHydrationLog.js.map → remoteHydration/remoteHydrationLog.js.map} +0 -0
- /package/workflows/{runtimeInput.js → shared/runtimeInput.js} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { ContainerContentsPersistence } from "
|
|
2
|
-
import type { ExecSql } from "
|
|
3
|
-
import type { ContainerDocumentRecord as DocumentRecord } from "
|
|
1
|
+
import type { ContainerContentsPersistence } from "../../../data/persistence/container-contents/containerContentsPersistence.js";
|
|
2
|
+
import type { ExecSql } from "../../../data/sqlite/sqlSchema.js";
|
|
3
|
+
import type { ContainerDocumentRecord as DocumentRecord } from "../containerPersistence.js";
|
|
4
4
|
import { type ExpectedContainerMetadataSyncState } from "./metadataSyncSettlement.js";
|
|
5
5
|
import type { ContainerMetadataPatch, ContainerMetadataState } from "./metadataTypes.js";
|
|
6
6
|
export interface PersistContainerMetadataStateInput {
|
|
@@ -19,7 +19,7 @@ export interface PersistContainerMetadataStateInput {
|
|
|
19
19
|
saveOptions?: Parameters<ContainerContentsPersistence["saveContainer"]>[3] | undefined;
|
|
20
20
|
stillCurrent?: (() => boolean) | undefined;
|
|
21
21
|
}
|
|
22
|
-
export declare function currentMetadataPullContinuation(metadataState: ContainerMetadataState): import("
|
|
22
|
+
export declare function currentMetadataPullContinuation(metadataState: ContainerMetadataState): import("../../documents/index.js").DocumentSyncPullContinuation | null;
|
|
23
23
|
export declare function resolveMetadataSecurityContext(metadataState: ContainerMetadataState, patch: Partial<ContainerMetadataPatch>): {
|
|
24
24
|
accessEpoch: number;
|
|
25
25
|
changed: boolean;
|
|
@@ -31,7 +31,7 @@ export declare function loadAuthoritativeContainerMetadataState(input: {
|
|
|
31
31
|
execSql: ExecSql;
|
|
32
32
|
persistence: ContainerContentsPersistence;
|
|
33
33
|
}): Promise<{
|
|
34
|
-
container: import("
|
|
34
|
+
container: import("../containerPersistence.js").ContainerRecord;
|
|
35
35
|
record: DocumentRecord;
|
|
36
36
|
} | null>;
|
|
37
37
|
export declare function prepareContainerMetadataMutation(input: PersistContainerMetadataStateInput, execSql: ExecSql, patch: Partial<ContainerMetadataPatch>): Promise<{
|
|
@@ -46,7 +46,7 @@ export declare function prepareContainerMetadataMutation(input: PersistContainer
|
|
|
46
46
|
securityContext?: never;
|
|
47
47
|
} | {
|
|
48
48
|
authoritativeState: {
|
|
49
|
-
container: import("
|
|
49
|
+
container: import("../containerPersistence.js").ContainerRecord;
|
|
50
50
|
record: DocumentRecord;
|
|
51
51
|
};
|
|
52
52
|
pullContinuationSuperseded: boolean;
|
|
@@ -59,7 +59,7 @@ export declare function prepareContainerMetadataMutation(input: PersistContainer
|
|
|
59
59
|
securityContext?: never;
|
|
60
60
|
} | {
|
|
61
61
|
durableRecord: DocumentRecord;
|
|
62
|
-
mutationContainer: import("
|
|
62
|
+
mutationContainer: import("../containerPersistence.js").ContainerRecord;
|
|
63
63
|
mutationMetadataState: ContainerMetadataState;
|
|
64
64
|
mutationPatch: Partial<ContainerMetadataPatch>;
|
|
65
65
|
pendingLocalUpdate: Uint8Array<ArrayBufferLike> | undefined;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { base64ToBytes } from "
|
|
2
|
-
import { encodeVersionVector, exportUpdatesSince, importUpdates, } from "
|
|
3
|
-
import { getDefaultContainerName, readContainerMetadataValue, writeContainerMetadataValue, } from "
|
|
4
|
-
import { documentSyncPullContinuationsEqual } from "
|
|
5
|
-
import { canWriteEffectiveAccessLevel } from "
|
|
1
|
+
import { base64ToBytes } from "../../../internal/encoding/index.js";
|
|
2
|
+
import { encodeVersionVector, exportUpdatesSince, importUpdates, } from "../../../internal/loro/index.js";
|
|
3
|
+
import { getDefaultContainerName, readContainerMetadataValue, writeContainerMetadataValue, } from "../../../data/containers/containerMetadataDocument.js";
|
|
4
|
+
import { documentSyncPullContinuationsEqual } from "../../../data/documents/shared/syncPagination.js";
|
|
5
|
+
import { canWriteEffectiveAccessLevel } from "../../../data/keying/accessLevel.js";
|
|
6
6
|
import { metadataSyncSecurityContextMatches, replaceSupersededMetadataIdentity, sameNullableMetadataValue, } from "./metadataSyncSettlement.js";
|
|
7
7
|
export function currentMetadataPullContinuation(metadataState) {
|
|
8
8
|
return Object.hasOwn(metadataState, "pullContinuation")
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadataMutationPreparation.js","sourceRoot":"","sources":["metadataMutationPreparation.ts"],"names":[],"mappings":"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","sourcesContent":["import { base64ToBytes } from \"@tearleads/encoding\";\nimport {\n encodeVersionVector,\n exportUpdatesSince,\n importUpdates,\n} from \"@tearleads/loro\";\nimport {\n getDefaultContainerName,\n readContainerMetadataValue,\n writeContainerMetadataValue,\n} from \"../../../data/containers/containerMetadataDocument\";\nimport { documentSyncPullContinuationsEqual } from \"../../../data/documents/shared/syncPagination\";\nimport { canWriteEffectiveAccessLevel } from \"../../../data/keying/accessLevel\";\nimport type { ContainerContentsPersistence } from \"../../../data/persistence/container-contents/containerContentsPersistence\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport type { ContainerDocumentRecord as DocumentRecord } from \"../containerPersistence\";\nimport {\n type ExpectedContainerMetadataSyncState,\n metadataSyncSecurityContextMatches,\n replaceSupersededMetadataIdentity,\n sameNullableMetadataValue,\n} from \"./metadataSyncSettlement\";\nimport type {\n ContainerMetadataPatch,\n ContainerMetadataState,\n} from \"./metadataTypes\";\n\nexport interface PersistContainerMetadataStateInput {\n acceptedPendingUpdateIds?: readonly string[] | undefined;\n clearSyncFailure?: boolean | undefined;\n execSql: ExecSql;\n expectedSyncState?: ExpectedContainerMetadataSyncState | undefined;\n localMetadataPatch?:\n | Partial<Pick<ContainerMetadataPatch, \"icon\" | \"name\">>\n | undefined;\n localUpdate?: Uint8Array | undefined;\n metadataState: ContainerMetadataState;\n createIntentSettlement?: Parameters<\n ContainerContentsPersistence[\"commitMetadataMutation\"]\n >[1][\"createIntentSettlement\"];\n moveIntentSettlement?: Parameters<\n ContainerContentsPersistence[\"commitMetadataMutation\"]\n >[1][\"moveIntentSettlement\"];\n patch?: Partial<ContainerMetadataPatch> | undefined;\n persistence: ContainerContentsPersistence;\n preserveDurableStructureWhenPending?: boolean | undefined;\n saveOptions?:\n | Parameters<ContainerContentsPersistence[\"saveContainer\"]>[3]\n | undefined;\n stillCurrent?: (() => boolean) | undefined;\n}\n\nexport function currentMetadataPullContinuation(\n metadataState: ContainerMetadataState,\n) {\n return Object.hasOwn(metadataState, \"pullContinuation\")\n ? (metadataState.pullContinuation ?? null)\n : (metadataState.record.pullContinuation ?? null);\n}\n\nexport function resolveMetadataSecurityContext(\n metadataState: ContainerMetadataState,\n patch: Partial<ContainerMetadataPatch>,\n) {\n const currentDocumentId = metadataState.record.documentId ?? null;\n const documentId =\n patch.documentId !== undefined ? patch.documentId : currentDocumentId;\n const accessEpoch = patch.accessEpoch ?? metadataState.record.accessEpoch;\n const documentIdChanged = documentId !== currentDocumentId;\n\n return {\n accessEpoch,\n changed:\n documentIdChanged || accessEpoch !== metadataState.record.accessEpoch,\n documentId,\n documentIdChanged,\n };\n}\n\nfunction mergeDurableMetadataCheckpoint(input: {\n durableRecord: DocumentRecord | null;\n metadataState: ContainerMetadataState;\n securityContext: ReturnType<typeof resolveMetadataSecurityContext>;\n}): void {\n const { durableRecord, metadataState, securityContext } = input;\n if (\n !durableRecord?.metadataUpdates ||\n durableRecord.documentId !== metadataState.record.documentId ||\n durableRecord.documentId !== securityContext.documentId ||\n durableRecord.accessEpoch !== metadataState.record.accessEpoch ||\n durableRecord.accessEpoch !== securityContext.accessEpoch\n ) {\n return;\n }\n\n importUpdates(metadataState.doc, [\n base64ToBytes(durableRecord.metadataUpdates),\n ]);\n}\n\nexport async function loadAuthoritativeContainerMetadataState(input: {\n containerId: string;\n execSql: ExecSql;\n persistence: ContainerContentsPersistence;\n}) {\n const stored = await input.persistence.loadContainerMetadataState(\n input.execSql,\n input.containerId,\n );\n return stored?.record\n ? { container: stored.container, record: stored.record }\n : null;\n}\n\nfunction localMetadataWriteAccessWasRevoked(input: {\n authoritativeState: NonNullable<\n Awaited<ReturnType<typeof loadAuthoritativeContainerMetadataState>>\n >;\n mutationInput: PersistContainerMetadataStateInput;\n}): boolean {\n return (\n input.mutationInput.expectedSyncState === undefined &&\n input.mutationInput.localUpdate !== undefined &&\n canWriteEffectiveAccessLevel(\n input.mutationInput.metadataState.container.effectiveAccessLevel,\n ) &&\n !canWriteEffectiveAccessLevel(\n input.authoritativeState.container.effectiveAccessLevel,\n )\n );\n}\n\nasync function prepareRebasedLocalMetadataMutation(input: {\n authoritativeState: NonNullable<\n Awaited<ReturnType<typeof loadAuthoritativeContainerMetadataState>>\n >;\n metadataState: ContainerMetadataState;\n localMetadataPatch:\n | Partial<Pick<ContainerMetadataPatch, \"icon\" | \"name\">>\n | undefined;\n patch: Partial<ContainerMetadataPatch>;\n}) {\n const { authoritativeState, metadataState, patch } = input;\n const replacementVersion = encodeVersionVector(metadataState.doc);\n const replacementMetadata = readContainerMetadataValue(\n metadataState.doc,\n getDefaultContainerName(authoritativeState.container.parentId),\n );\n writeContainerMetadataValue(metadataState.doc, {\n ...replacementMetadata,\n ...input.localMetadataPatch,\n });\n const rebasedMetadataState = {\n ...metadataState,\n container: authoritativeState.container,\n pullContinuation: authoritativeState.record.pullContinuation ?? null,\n record: authoritativeState.record,\n };\n return {\n durableRecord: authoritativeState.record,\n mutationContainer: authoritativeState.container,\n mutationMetadataState: rebasedMetadataState,\n mutationPatch: patch,\n pendingLocalUpdate: exportUpdatesSince(\n metadataState.doc,\n replacementVersion,\n ),\n pullContinuationSuperseded: false,\n securityContext: resolveMetadataSecurityContext(\n rebasedMetadataState,\n patch,\n ),\n securityContextMatches: true,\n };\n}\n\nfunction resolveMetadataSettlementMatch(\n expectedSyncState: ExpectedContainerMetadataSyncState | undefined,\n durableRecord: DocumentRecord | null,\n) {\n if (!expectedSyncState) {\n return {\n contentStateSuperseded: false,\n pullContinuationSuperseded: false,\n securityContextMatches: true,\n };\n }\n const securityContextMatches = metadataSyncSecurityContextMatches(\n durableRecord,\n expectedSyncState.record,\n );\n const progressStateMatches =\n securityContextMatches &&\n sameNullableMetadataValue(\n durableRecord?.lastCommitLsn,\n expectedSyncState.record.lastCommitLsn,\n ) &&\n Boolean(durableRecord?.pullContinuationRecoveryRequired) ===\n Boolean(expectedSyncState.record.pullContinuationRecoveryRequired) &&\n documentSyncPullContinuationsEqual(\n durableRecord?.pullContinuation,\n expectedSyncState.pullContinuation,\n );\n const contentStateMatches =\n progressStateMatches &&\n sameNullableMetadataValue(\n durableRecord?.metadataUpdates,\n expectedSyncState.record.metadataUpdates,\n ) &&\n sameNullableMetadataValue(\n durableRecord?.snapshotEndVersion,\n expectedSyncState.record.snapshotEndVersion,\n );\n return {\n contentStateSuperseded: progressStateMatches && !contentStateMatches,\n pullContinuationSuperseded: !progressStateMatches,\n securityContextMatches,\n };\n}\n\nexport async function prepareContainerMetadataMutation(\n input: PersistContainerMetadataStateInput,\n execSql: ExecSql,\n patch: Partial<ContainerMetadataPatch>,\n) {\n const { metadataState, persistence } = input;\n const authoritativeState = await loadAuthoritativeContainerMetadataState({\n containerId: metadataState.container.id,\n execSql,\n persistence,\n });\n if (!authoritativeState) {\n return {\n authoritativeState: null,\n pullContinuationSuperseded: true,\n securityContextMatches: false,\n };\n }\n if (\n localMetadataWriteAccessWasRevoked({\n authoritativeState,\n mutationInput: input,\n })\n ) {\n await replaceSupersededMetadataIdentity({\n durableRecord: authoritativeState.record,\n metadataState,\n });\n return {\n authoritativeState,\n pullContinuationSuperseded: true,\n securityContextMatches: false,\n };\n }\n const durableRecord = authoritativeState.record;\n const mutationMetadataState = durableRecord\n ? {\n ...metadataState,\n pullContinuation: durableRecord.pullContinuation ?? null,\n record: durableRecord,\n }\n : metadataState;\n const capturedSecurityContextMatches =\n durableRecord !== null &&\n metadataSyncSecurityContextMatches(durableRecord, metadataState.record);\n const {\n contentStateSuperseded,\n pullContinuationSuperseded,\n securityContextMatches,\n } = resolveMetadataSettlementMatch(input.expectedSyncState, durableRecord);\n\n if (\n input.expectedSyncState === undefined &&\n !capturedSecurityContextMatches\n ) {\n await replaceSupersededMetadataIdentity({\n durableRecord: authoritativeState.record,\n metadataState,\n });\n if (input.localUpdate === undefined) {\n return {\n authoritativeState,\n pullContinuationSuperseded: true,\n securityContextMatches: false,\n };\n }\n return prepareRebasedLocalMetadataMutation({\n authoritativeState,\n localMetadataPatch: input.localMetadataPatch,\n metadataState,\n patch,\n });\n }\n const mutationPatch = pullContinuationSuperseded ? {} : patch;\n const securityContext = resolveMetadataSecurityContext(\n mutationMetadataState,\n mutationPatch,\n );\n if (\n securityContextMatches &&\n (input.expectedSyncState === undefined || contentStateSuperseded)\n ) {\n mergeDurableMetadataCheckpoint({\n durableRecord,\n metadataState,\n securityContext,\n });\n }\n return {\n durableRecord,\n mutationContainer: authoritativeState.container,\n mutationMetadataState,\n mutationPatch,\n pendingLocalUpdate: input.localUpdate,\n pullContinuationSuperseded,\n securityContext,\n securityContextMatches,\n };\n}\n"]}
|
package/workflows/container-contents/{metadataPersistence.d.ts → metadata/metadataPersistence.d.ts}
RENAMED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { ContainerContentsPersistence } from "
|
|
1
|
+
import type { ContainerContentsPersistence } from "../../../data/persistence/container-contents/containerContentsPersistence.js";
|
|
2
|
+
import type { ContainerContentsWorkflowSqlRuntime } from "../runtime.js";
|
|
2
3
|
import { currentMetadataPullContinuation, type PersistContainerMetadataStateInput } from "./metadataMutationPreparation.js";
|
|
3
4
|
import { type ExpectedContainerMetadataSyncState } from "./metadataSyncSettlement.js";
|
|
4
5
|
import type { ContainerMetadataState, PersistedContainerMetadataState } from "./metadataTypes.js";
|
|
5
|
-
import type { ContainerContentsWorkflowSqlRuntime } from "./runtime.js";
|
|
6
6
|
type ContainerMetadataPersistenceRuntime = ContainerContentsWorkflowSqlRuntime;
|
|
7
7
|
export { hasCurrentContainerMetadataReadState } from "./metadataReadState.js";
|
|
8
8
|
export { installContainerMetadataRecord } from "./metadataStateInstallation.js";
|
package/workflows/container-contents/{metadataPersistence.js → metadata/metadataPersistence.js}
RENAMED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { encodeVersionVector, exportUpdatesSince } from "
|
|
2
|
-
import { getDefaultContainerName, readContainerMetadataValue, writeContainerMetadataValue, } from "
|
|
3
|
-
import { createPendingUpdateFields } from "
|
|
4
|
-
import { runSerializedSqlMutation, } from "
|
|
1
|
+
import { encodeVersionVector, exportUpdatesSince } from "../../../internal/loro/index.js";
|
|
2
|
+
import { getDefaultContainerName, readContainerMetadataValue, writeContainerMetadataValue, } from "../../../data/containers/containerMetadataDocument.js";
|
|
3
|
+
import { createPendingUpdateFields } from "../../../data/documents/documentSync.js";
|
|
4
|
+
import { runSerializedSqlMutation, } from "../../../data/sqlite/sqlSchema.js";
|
|
5
5
|
import { currentMetadataPullContinuation, loadAuthoritativeContainerMetadataState, prepareContainerMetadataMutation, } from "./metadataMutationPreparation.js";
|
|
6
6
|
import { buildContainerMetadataRecord, resolveContainerSystemSlot, resolveMetadataDocumentId, } from "./metadataRecord.js";
|
|
7
7
|
import { installContainerMetadataRecord } from "./metadataStateInstallation.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadataPersistence.js","sourceRoot":"","sources":["metadataPersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import { encodeVersionVector, exportUpdatesSince } from \"@tearleads/loro\";\nimport {\n getDefaultContainerName,\n readContainerMetadataValue,\n writeContainerMetadataValue,\n} from \"../../../data/containers/containerMetadataDocument\";\nimport { createPendingUpdateFields } from \"../../../data/documents/documentSync\";\nimport type { ContainerContentsPersistence } from \"../../../data/persistence/container-contents/containerContentsPersistence\";\nimport type { ContainerRecord } from \"../../../data/persistence/containers/containerPersistence\";\nimport {\n type ExecSql,\n runSerializedSqlMutation,\n} from \"../../../data/sqlite/sqlSchema\";\nimport type { ContainerDocumentRecord as DocumentRecord } from \"../containerPersistence\";\nimport type { ContainerContentsWorkflowSqlRuntime } from \"../runtime\";\nimport {\n currentMetadataPullContinuation,\n loadAuthoritativeContainerMetadataState,\n type PersistContainerMetadataStateInput,\n prepareContainerMetadataMutation,\n} from \"./metadataMutationPreparation\";\nimport {\n buildContainerMetadataRecord,\n resolveContainerSystemSlot,\n resolveMetadataDocumentId,\n} from \"./metadataRecord\";\nimport { installContainerMetadataRecord } from \"./metadataStateInstallation\";\nimport {\n type ExpectedContainerMetadataSyncState,\n metadataSyncSecurityContextMatches,\n replaceSupersededMetadataIdentity,\n} from \"./metadataSyncSettlement\";\nimport type {\n ContainerMetadataPatch,\n ContainerMetadataState,\n PersistedContainerMetadataState,\n} from \"./metadataTypes\";\n\ntype ContainerMetadataPersistenceRuntime = ContainerContentsWorkflowSqlRuntime;\nconst MAX_METADATA_MUTATION_COMMIT_ATTEMPTS = 8;\ntype SaveContainerOptions = Parameters<\n ContainerContentsPersistence[\"saveContainer\"]\n>[3];\n\nexport { hasCurrentContainerMetadataReadState } from \"./metadataReadState\";\nexport { installContainerMetadataRecord } from \"./metadataStateInstallation\";\nexport { currentMetadataPullContinuation };\n\nfunction invalidateMetadataWriterProjection(\n metadataState: ContainerMetadataState,\n securityContextChanged: boolean,\n): void {\n if (securityContextChanged) {\n metadataState.metadataWriterProjection = null;\n }\n}\ntype PreparedContainerMetadataMutation = Awaited<\n ReturnType<typeof prepareContainerMetadataMutation>\n>;\ntype ApplicableContainerMetadataMutation = Exclude<\n PreparedContainerMetadataMutation,\n { authoritativeState: unknown }\n>;\nasync function settleSupersededMetadataMutation(input: {\n acceptedPendingUpdateIds?: readonly string[] | undefined;\n execSql: ExecSql;\n expectedRecord?: DocumentRecord | undefined;\n metadataState: ContainerMetadataState;\n persistence: ContainerContentsPersistence;\n prepared: PreparedContainerMetadataMutation;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<PersistedContainerMetadataState | null> {\n const { metadataState, persistence, prepared } = input;\n const settledState = input.expectedRecord\n ? await persistence.settleAcceptedMetadataPendingUpdates(input.execSql, {\n containerId: metadataState.container.id,\n expectedRecord: input.expectedRecord,\n pendingUpdateIds: input.acceptedPendingUpdateIds ?? [],\n stillCurrent: input.stillCurrent,\n })\n : undefined;\n if (\"authoritativeState\" in prepared) {\n const authoritativeState = settledState ?? prepared.authoritativeState;\n if (!authoritativeState?.record) return null;\n metadataState.container = authoritativeState.container;\n installContainerMetadataRecord(metadataState, authoritativeState.record);\n return {\n container: authoritativeState.container,\n pullContinuationSuperseded: true,\n record: authoritativeState.record,\n syncIdentitySuperseded: true,\n };\n }\n const authoritativeState =\n settledState ??\n (await loadAuthoritativeContainerMetadataState({\n containerId: metadataState.container.id,\n execSql: input.execSql,\n persistence,\n }));\n if (!authoritativeState?.record) return null;\n // The rejected response may already have mutated the live Loro document.\n // Rebuild from the authoritative durable snapshot instead of merging into\n // that losing document, which would retain non-overlapping rejected fields.\n await replaceSupersededMetadataIdentity({\n durableRecord: authoritativeState.record,\n metadataState,\n });\n metadataState.container = authoritativeState.container;\n installContainerMetadataRecord(metadataState, authoritativeState.record);\n return {\n container: authoritativeState.container,\n pullContinuationSuperseded: true,\n record: authoritativeState.record,\n ...(!prepared.securityContextMatches\n ? { syncIdentitySuperseded: true as const }\n : {}),\n };\n}\nasync function persistPreparedMetadataMutation(input: {\n clearSyncFailure?: boolean | undefined;\n createIntentSettlement?: Parameters<\n ContainerContentsPersistence[\"commitMetadataMutation\"]\n >[1][\"createIntentSettlement\"];\n execSql: ExecSql;\n metadataState: ContainerMetadataState;\n moveIntentSettlement?: Parameters<\n ContainerContentsPersistence[\"commitMetadataMutation\"]\n >[1][\"moveIntentSettlement\"];\n persistence: ContainerContentsPersistence;\n prepared: ApplicableContainerMetadataMutation;\n acceptedPendingUpdateIds?: readonly string[] | undefined;\n preserveDurableStructureWhenPending?: boolean | undefined;\n saveOptions?: SaveContainerOptions;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<\n | PersistedContainerMetadataState\n | {\n conflict: true;\n currentState: Awaited<\n ReturnType<ContainerContentsPersistence[\"loadContainerMetadataState\"]>\n >;\n staleServerState?: true;\n }\n> {\n const { metadataState, persistence, prepared } = input;\n const metadata = readContainerMetadataValue(\n metadataState.doc,\n getDefaultContainerName(prepared.mutationContainer.parentId),\n );\n const nextContainer: ContainerRecord = {\n ...prepared.mutationContainer,\n ...(prepared.mutationPatch.effectiveAccessLevel !== undefined\n ? {\n effectiveAccessLevel: prepared.mutationPatch.effectiveAccessLevel,\n }\n : {}),\n organizationId:\n prepared.mutationPatch.organizationId ??\n prepared.mutationContainer.organizationId,\n parentId:\n prepared.mutationPatch.parentId ?? prepared.mutationContainer.parentId,\n metadataDocumentId: resolveMetadataDocumentId(\n prepared.mutationPatch,\n prepared.mutationContainer,\n ),\n systemSlot: resolveContainerSystemSlot(\n prepared.mutationPatch,\n prepared.mutationContainer,\n ),\n name: prepared.mutationPatch.name ?? metadata.name,\n icon:\n prepared.mutationPatch.icon !== undefined\n ? prepared.mutationPatch.icon\n : metadata.icon,\n };\n const nextRecord = buildContainerMetadataRecord({\n metadataState: prepared.mutationMetadataState,\n patch: prepared.mutationPatch,\n securityContext: prepared.securityContext,\n });\n const pendingUpdate = prepared.pendingLocalUpdate\n ? (createPendingUpdateFields(prepared.pendingLocalUpdate) ?? undefined)\n : undefined;\n const committed = await persistence.commitMetadataMutation(input.execSql, {\n acceptedPendingUpdateIds: input.acceptedPendingUpdateIds ?? [],\n clearSyncFailure: input.clearSyncFailure,\n container: nextContainer,\n createIntentSettlement: input.createIntentSettlement,\n expectedContainer: prepared.mutationContainer,\n expectedRecord: prepared.durableRecord,\n moveIntentSettlement: input.moveIntentSettlement,\n pendingUpdate,\n preserveDurableStructureWhenPending:\n input.preserveDurableStructureWhenPending,\n record: nextRecord,\n saveOptions: input.saveOptions,\n settleAcceptedPendingOnConflict:\n input.acceptedPendingUpdateIds !== undefined,\n stillCurrent: input.stillCurrent,\n });\n if (!committed.committed) {\n return {\n conflict: true,\n currentState: committed.currentState,\n ...(committed.staleServerState\n ? { staleServerState: true as const }\n : {}),\n };\n }\n invalidateMetadataWriterProjection(\n metadataState,\n prepared.securityContext.changed,\n );\n return {\n container: committed.container,\n record: nextRecord,\n ...(committed.createIntentSettled\n ? { createIntentSettled: true as const }\n : {}),\n ...(committed.moveIntentSettled\n ? { moveIntentSettled: true as const }\n : {}),\n };\n}\nasync function adoptMetadataCommitConflict(input: {\n currentState: Awaited<\n ReturnType<ContainerContentsPersistence[\"loadContainerMetadataState\"]>\n >;\n expectedRecord: DocumentRecord;\n expectedSyncState?: ExpectedContainerMetadataSyncState | undefined;\n metadataState: ContainerMetadataState;\n staleServerState?: true | undefined;\n}): Promise<PersistedContainerMetadataState | null | \"retry\"> {\n if (!input.staleServerState && input.expectedSyncState === undefined) {\n return \"retry\";\n }\n if (!input.currentState?.record) return null;\n await replaceSupersededMetadataIdentity({\n durableRecord: input.currentState.record,\n metadataState: input.metadataState,\n });\n input.metadataState.container = input.currentState.container;\n installContainerMetadataRecord(\n input.metadataState,\n input.currentState.record,\n );\n return {\n container: input.currentState.container,\n pullContinuationSuperseded: true,\n record: input.currentState.record,\n ...(input.staleServerState ? { mutationSuperseded: true as const } : {}),\n ...(!metadataSyncSecurityContextMatches(\n input.currentState.record,\n input.expectedSyncState?.record ?? input.expectedRecord,\n )\n ? { syncIdentitySuperseded: true as const }\n : {}),\n };\n}\nasync function persistContainerMetadataState(\n input: PersistContainerMetadataStateInput,\n): Promise<PersistedContainerMetadataState | null> {\n const patch = input.patch ?? {};\n const prepareMutation = prepareContainerMetadataMutation;\n return runSerializedSqlMutation(input.execSql, async (lockedExecSql) => {\n for (\n let attempt = 0;\n attempt < MAX_METADATA_MUTATION_COMMIT_ATTEMPTS;\n attempt += 1\n ) {\n const prepared = await prepareMutation(input, lockedExecSql, patch);\n if (input.stillCurrent?.() === false) return null;\n if (\n \"authoritativeState\" in prepared ||\n prepared.pullContinuationSuperseded\n ) {\n return settleSupersededMetadataMutation({\n acceptedPendingUpdateIds: input.acceptedPendingUpdateIds,\n execSql: lockedExecSql,\n expectedRecord: input.expectedSyncState?.record,\n metadataState: input.metadataState,\n persistence: input.persistence,\n prepared,\n stillCurrent: input.stillCurrent,\n });\n }\n const persisted = await persistPreparedMetadataMutation({\n acceptedPendingUpdateIds: input.acceptedPendingUpdateIds,\n clearSyncFailure: input.clearSyncFailure,\n createIntentSettlement: input.createIntentSettlement,\n execSql: lockedExecSql,\n metadataState: input.metadataState,\n moveIntentSettlement: input.moveIntentSettlement,\n persistence: input.persistence,\n prepared,\n preserveDurableStructureWhenPending:\n input.preserveDurableStructureWhenPending,\n saveOptions: input.saveOptions,\n stillCurrent: input.stillCurrent,\n });\n if (input.stillCurrent?.() === false) return null;\n if (!(\"conflict\" in persisted)) return persisted;\n const conflict = await adoptMetadataCommitConflict({\n currentState: persisted.currentState,\n expectedRecord: prepared.durableRecord,\n expectedSyncState: input.expectedSyncState,\n metadataState: input.metadataState,\n staleServerState: persisted.staleServerState,\n });\n if (conflict !== \"retry\") return conflict;\n }\n throw new Error(\n `Container metadata mutation commit gave up after ${MAX_METADATA_MUTATION_COMMIT_ATTEMPTS} concurrent conflicts`,\n );\n });\n}\ntype PersistContainerMetadataStateRuntimeInput = Omit<\n PersistContainerMetadataStateInput,\n \"execSql\"\n> & {\n onDurableStateNeedsReload?: (() => void) | undefined;\n persistence: ContainerContentsPersistence;\n runtime: ContainerMetadataPersistenceRuntime;\n};\n\nexport function persistContainerMetadataStateFromRuntime(\n input: PersistContainerMetadataStateRuntimeInput & {\n expectedSyncState: ExpectedContainerMetadataSyncState;\n },\n): Promise<PersistedContainerMetadataState | null>;\nexport function persistContainerMetadataStateFromRuntime(\n input: PersistContainerMetadataStateRuntimeInput & {\n expectedSyncState?: undefined;\n },\n): Promise<PersistedContainerMetadataState | null>;\nexport async function persistContainerMetadataStateFromRuntime(\n input: PersistContainerMetadataStateRuntimeInput,\n): Promise<PersistedContainerMetadataState | null> {\n const { onDurableStateNeedsReload, runtime, ...persistenceInput } = input;\n const execSql = runtime.infra.execSql;\n const persisted = await persistContainerMetadataState({\n ...persistenceInput,\n execSql,\n });\n if (input.stillCurrent?.() === false) {\n onDurableStateNeedsReload?.();\n return null;\n }\n return persisted;\n}\n\nasync function writeContainerMetadataPatch(input: {\n execSql: ExecSql;\n metadataState: ContainerMetadataState;\n patch: Partial<Pick<ContainerMetadataPatch, \"icon\" | \"name\">>;\n persistence: ContainerContentsPersistence;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<PersistedContainerMetadataState | null> {\n const { execSql, metadataState, patch, persistence } = input;\n const metadata = readContainerMetadataValue(\n metadataState.doc,\n getDefaultContainerName(metadataState.container.parentId),\n );\n const previousVersion = encodeVersionVector(metadataState.doc);\n writeContainerMetadataValue(metadataState.doc, { ...metadata, ...patch });\n const update = exportUpdatesSince(metadataState.doc, previousVersion);\n\n return persistContainerMetadataState({\n execSql,\n localMetadataPatch: patch,\n localUpdate: update,\n metadataState,\n patch,\n persistence,\n stillCurrent: input.stillCurrent,\n });\n}\n\nexport async function renameContainerMetadataStateFromRuntime(input: {\n metadataState: ContainerMetadataState;\n name: string;\n persistence: ContainerContentsPersistence;\n runtime: ContainerMetadataPersistenceRuntime;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<PersistedContainerMetadataState | null> {\n const trimmedName = input.name.trim();\n if (!trimmedName) {\n return null;\n }\n\n return writeContainerMetadataPatch({\n execSql: input.runtime.infra.execSql,\n metadataState: input.metadataState,\n patch: { name: trimmedName },\n persistence: input.persistence,\n stillCurrent: input.stillCurrent,\n });\n}\n\nexport async function setContainerIconMetadataStateFromRuntime(input: {\n icon: string | null;\n metadataState: ContainerMetadataState;\n persistence: ContainerContentsPersistence;\n runtime: ContainerMetadataPersistenceRuntime;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<PersistedContainerMetadataState | null> {\n return writeContainerMetadataPatch({\n execSql: input.runtime.infra.execSql,\n metadataState: input.metadataState,\n patch: { icon: input.icon?.trim() || null },\n persistence: input.persistence,\n stillCurrent: input.stillCurrent,\n });\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { base64ToBytes } from "
|
|
2
|
-
import { importUpdates } from "
|
|
3
|
-
import { documentSyncPullContinuationsEqual, } from "
|
|
4
|
-
import { runSerializedSqlMutation } from "
|
|
1
|
+
import { base64ToBytes } from "../../../internal/encoding/index.js";
|
|
2
|
+
import { importUpdates } from "../../../internal/loro/index.js";
|
|
3
|
+
import { documentSyncPullContinuationsEqual, } from "../../../data/documents/shared/syncPagination.js";
|
|
4
|
+
import { runSerializedSqlMutation } from "../../../data/sqlite/sqlSchema.js";
|
|
5
5
|
import { currentMetadataPullContinuation } from "./metadataPersistence.js";
|
|
6
6
|
function metadataInvalidationStateMatches(input) {
|
|
7
7
|
const { accessEpoch, continuation, documentId, durableRecord, metadataState, } = input;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadataPullContinuationInvalidation.js","sourceRoot":"","sources":["metadataPullContinuationInvalidation.ts"],"names":[],"mappings":"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","sourcesContent":["import { base64ToBytes } from \"@tearleads/encoding\";\nimport { importUpdates } from \"@tearleads/loro\";\nimport {\n type DocumentSyncPullContinuation,\n documentSyncPullContinuationsEqual,\n} from \"../../../data/documents/shared/syncPagination\";\nimport type { ContainerContentsPersistence } from \"../../../data/persistence/container-contents/containerContentsPersistence\";\nimport { runSerializedSqlMutation } from \"../../../data/sqlite/sqlSchema\";\nimport type { ContainerContentsWorkflowSqlRuntime } from \"../runtime\";\nimport { currentMetadataPullContinuation } from \"./metadataPersistence\";\nimport type { ContainerMetadataState } from \"./metadataTypes\";\n\nfunction metadataInvalidationStateMatches(input: {\n accessEpoch: number;\n continuation: DocumentSyncPullContinuation;\n documentId: string;\n durableRecord: NonNullable<\n Awaited<\n ReturnType<ContainerContentsPersistence[\"loadContainerMetadataRecord\"]>\n >\n >;\n metadataState: ContainerMetadataState;\n}): boolean {\n const {\n accessEpoch,\n continuation,\n documentId,\n durableRecord,\n metadataState,\n } = input;\n return (\n metadataState.record.documentId === documentId &&\n metadataState.record.accessEpoch === accessEpoch &&\n durableRecord.documentId === documentId &&\n durableRecord.accessEpoch === accessEpoch &&\n (durableRecord.accessStateHash ?? null) ===\n (metadataState.record.accessStateHash ?? null) &&\n (durableRecord.contentKeyBundle ?? null) ===\n (metadataState.record.contentKeyBundle ?? null) &&\n (durableRecord.documentKekTargets ?? null) ===\n (metadataState.record.documentKekTargets ?? null) &&\n (durableRecord.documentManifestBundle ?? null) ===\n (metadataState.record.documentManifestBundle ?? null) &&\n documentSyncPullContinuationsEqual(\n currentMetadataPullContinuation(metadataState),\n continuation,\n )\n );\n}\n\nexport async function invalidateContainerMetadataPullContinuation(input: {\n continuation: DocumentSyncPullContinuation;\n isCurrent?: (() => boolean) | undefined;\n metadataState: ContainerMetadataState;\n persistence: ContainerContentsPersistence;\n runtime: ContainerContentsWorkflowSqlRuntime;\n}): Promise<void> {\n const { continuation, metadataState, runtime } = input;\n if (input.isCurrent?.() === false) return;\n const { accessEpoch, documentId } = metadataState.record;\n if (!documentId) return;\n\n await runSerializedSqlMutation(\n runtime.infra.execSql,\n async (lockedExecSql) => {\n if (input.isCurrent?.() === false) return;\n const durableRecord =\n await input.persistence.invalidateMetadataPullContinuation(\n lockedExecSql,\n {\n accessEpoch,\n accessStateHash: metadataState.record.accessStateHash ?? null,\n continuation,\n containerId: metadataState.container.id,\n contentKeyBundle: metadataState.record.contentKeyBundle ?? null,\n documentId,\n documentKekTargets: metadataState.record.documentKekTargets ?? null,\n documentManifestBundle:\n metadataState.record.documentManifestBundle ?? null,\n lastCommitLsn: metadataState.record.lastCommitLsn ?? null,\n stillCurrent: input.isCurrent,\n },\n );\n if (\n input.isCurrent?.() === false ||\n !durableRecord ||\n !metadataInvalidationStateMatches({\n accessEpoch,\n continuation,\n documentId,\n durableRecord,\n metadataState,\n })\n ) {\n return;\n }\n if (durableRecord.metadataUpdates) {\n importUpdates(metadataState.doc, [\n base64ToBytes(durableRecord.metadataUpdates),\n ]);\n }\n const {\n pullContinuation: _stalePullContinuation,\n pullContinuationRecoveryRequired: _staleRecoveryMarker,\n ...liveRecord\n } = metadataState.record;\n metadataState.record = { ...liveRecord, ...durableRecord };\n metadataState.pullContinuation = durableRecord.pullContinuation ?? null;\n },\n );\n}\n"]}
|
package/workflows/container-contents/{metadataReadState.d.ts → metadata/metadataReadState.d.ts}
RENAMED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { ContainerDocumentRecord as DocumentRecord } from "
|
|
1
|
+
import type { ContainerDocumentRecord as DocumentRecord } from "../containerPersistence.js";
|
|
2
2
|
export declare function hasCurrentContainerMetadataReadState(record: Pick<DocumentRecord, "contentKeyBundle" | "documentKekTargets" | "documentManifestBundle" | "lastCommitLsn">): boolean;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadataReadState.js","sourceRoot":"","sources":["metadataReadState.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,oCAAoC,CAClD,MAMC;IAED,OAAO,CACL,OAAO,MAAM,CAAC,aAAa,KAAK,QAAQ;QACxC,MAAM,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC;QAC/B,OAAO,MAAM,CAAC,gBAAgB,KAAK,QAAQ;QAC3C,MAAM,CAAC,gBAAgB,CAAC,MAAM,GAAG,CAAC;QAClC,OAAO,MAAM,CAAC,kBAAkB,KAAK,QAAQ;QAC7C,MAAM,CAAC,kBAAkB,CAAC,MAAM,GAAG,CAAC;QACpC,OAAO,MAAM,CAAC,sBAAsB,KAAK,QAAQ;QACjD,MAAM,CAAC,sBAAsB,CAAC,MAAM,GAAG,CAAC,CACzC,CAAC;AACJ,CAAC","sourcesContent":["import type { ContainerDocumentRecord as DocumentRecord } from \"../containerPersistence\";\n\nexport function hasCurrentContainerMetadataReadState(\n record: Pick<\n DocumentRecord,\n | \"contentKeyBundle\"\n | \"documentKekTargets\"\n | \"documentManifestBundle\"\n | \"lastCommitLsn\"\n >,\n): boolean {\n return (\n typeof record.lastCommitLsn === \"string\" &&\n record.lastCommitLsn.length > 0 &&\n typeof record.contentKeyBundle === \"string\" &&\n record.contentKeyBundle.length > 0 &&\n typeof record.documentKekTargets === \"string\" &&\n record.documentKekTargets.length > 0 &&\n typeof record.documentManifestBundle === \"string\" &&\n record.documentManifestBundle.length > 0\n );\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { bytesToBase64 } from "
|
|
2
|
-
import { exportAllUpdates } from "
|
|
1
|
+
import { bytesToBase64 } from "../../../internal/encoding/index.js";
|
|
2
|
+
import { exportAllUpdates } from "../../../internal/loro/index.js";
|
|
3
3
|
import { currentMetadataPullContinuation, } from "./metadataMutationPreparation.js";
|
|
4
4
|
export function resolveContainerSystemSlot(patch, container) {
|
|
5
5
|
return patch.systemSlot ?? container.systemSlot ?? null;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadataRecord.js","sourceRoot":"","sources":["metadataRecord.ts"],"names":[],"mappings":"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","sourcesContent":["import { bytesToBase64 } from \"@tearleads/encoding\";\nimport { exportAllUpdates } from \"@tearleads/loro\";\nimport type { ContainerRecord } from \"../../../data/persistence/containers/containerPersistence\";\nimport type { ContainerDocumentRecord as DocumentRecord } from \"../containerPersistence\";\nimport {\n currentMetadataPullContinuation,\n type resolveMetadataSecurityContext,\n} from \"./metadataMutationPreparation\";\nimport type {\n ContainerMetadataPatch,\n ContainerMetadataState,\n} from \"./metadataTypes\";\n\ntype NullableContainerMetadataDocumentField =\n | \"accessStateHash\"\n | \"lastCommitLsn\"\n | \"contentKeyBundle\"\n | \"documentKekTargets\"\n | \"documentManifestBundle\";\n\nexport function resolveContainerSystemSlot(\n patch: Partial<ContainerMetadataPatch>,\n container: ContainerRecord,\n): NonNullable<ContainerRecord[\"systemSlot\"]> | null {\n return patch.systemSlot ?? container.systemSlot ?? null;\n}\n\nexport function resolveMetadataDocumentId(\n patch: Partial<ContainerMetadataPatch>,\n container: ContainerRecord,\n): ContainerRecord[\"metadataDocumentId\"] {\n return (\n patch.metadataDocumentId ?? patch.documentId ?? container.metadataDocumentId\n );\n}\n\nfunction resolveNullableContainerMetadataDocumentField(\n patch: Partial<ContainerMetadataPatch>,\n key: NullableContainerMetadataDocumentField,\n currentValue: string | null | undefined,\n resetWhenUnpatched = false,\n): string | null {\n if (Object.hasOwn(patch, key)) return patch[key] ?? null;\n return resetWhenUnpatched ? null : (currentValue ?? null);\n}\n\nfunction resolveMetadataPullState(\n metadataState: ContainerMetadataState,\n patch: Partial<ContainerMetadataPatch>,\n securityContextChanged: boolean,\n): Pick<\n DocumentRecord,\n \"pullContinuation\" | \"pullContinuationRecoveryRequired\"\n> {\n if (Object.hasOwn(patch, \"pullContinuation\")) {\n return { pullContinuation: patch.pullContinuation ?? null };\n }\n if (securityContextChanged) return { pullContinuation: null };\n if (metadataState.record.pullContinuationRecoveryRequired) {\n return { pullContinuationRecoveryRequired: true };\n }\n return { pullContinuation: currentMetadataPullContinuation(metadataState) };\n}\n\nexport function buildContainerMetadataRecord(input: {\n metadataState: ContainerMetadataState;\n patch: Partial<ContainerMetadataPatch>;\n securityContext: ReturnType<typeof resolveMetadataSecurityContext>;\n}): DocumentRecord {\n const { metadataState, patch, securityContext } = input;\n return {\n id: metadataState.container.id,\n documentId: securityContext.documentId,\n metadataUpdates:\n patch.metadataUpdates ??\n bytesToBase64(exportAllUpdates(metadataState.doc)),\n snapshotEndVersion: \"\",\n accessEpoch: securityContext.accessEpoch,\n accessStateHash: resolveNullableContainerMetadataDocumentField(\n patch,\n \"accessStateHash\",\n metadataState.record.accessStateHash,\n securityContext.changed,\n ),\n lastCommitLsn: resolveNullableContainerMetadataDocumentField(\n patch,\n \"lastCommitLsn\",\n metadataState.record.lastCommitLsn,\n securityContext.documentIdChanged,\n ),\n contentKeyBundle: resolveNullableContainerMetadataDocumentField(\n patch,\n \"contentKeyBundle\",\n metadataState.record.contentKeyBundle,\n securityContext.changed,\n ),\n documentKekTargets: resolveNullableContainerMetadataDocumentField(\n patch,\n \"documentKekTargets\",\n metadataState.record.documentKekTargets,\n securityContext.changed,\n ),\n documentManifestBundle: resolveNullableContainerMetadataDocumentField(\n patch,\n \"documentManifestBundle\",\n metadataState.record.documentManifestBundle,\n securityContext.changed,\n ),\n ...resolveMetadataPullState(metadataState, patch, securityContext.changed),\n };\n}\n"]}
|
package/workflows/container-contents/{metadataRemoteSync.d.ts → metadata/metadataRemoteSync.d.ts}
RENAMED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { DocumentWriterProjectionResponse } from "
|
|
2
|
-
import type { ProjectionUserKeyResolver } from "
|
|
3
|
-
import type { PendingUpdateRecord } from "
|
|
4
|
-
import { type RekeyPendingUpdate, syncRemoteDocument } from "
|
|
1
|
+
import type { DocumentWriterProjectionResponse } from "../../../internal/validators/response/index.js";
|
|
2
|
+
import type { ProjectionUserKeyResolver } from "../../../data/keyingProjectionVerification/index.js";
|
|
3
|
+
import type { PendingUpdateRecord } from "../../../data/sqlite/documentPersistence.js";
|
|
4
|
+
import { type RekeyPendingUpdate, syncRemoteDocument } from "../../documents/index.js";
|
|
5
|
+
import type { ContainerContentsWorkflowRuntime } from "../runtime.js";
|
|
5
6
|
import type { ContainerMetadataState } from "./metadataTypes.js";
|
|
6
|
-
import type { ContainerContentsWorkflowRuntime } from "./runtime.js";
|
|
7
7
|
type ContainerMetadataSyncApi = Parameters<typeof syncRemoteDocument>[0]["apiClient"] & Pick<ContainerContentsWorkflowRuntime["apiClient"], "getPrincipalPolicyPages" | "getProjectionPolicyHistoryPages">;
|
|
8
8
|
export interface ContainerMetadataSyncRuntime extends Pick<ContainerContentsWorkflowRuntime, "auth" | "crypto" | "infra" | "resolveTrustedUserIdentity" | "state" | "util"> {
|
|
9
9
|
apiClient: ContainerMetadataSyncApi;
|
package/workflows/container-contents/{metadataRemoteSync.js → metadata/metadataRemoteSync.js}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { CONTAINER_METADATA_APP_KIND } from "
|
|
2
|
-
import { createDocumentWriterPublicKeyResolver, describeDocumentSyncSubmitFailure, resolveDocumentCreateAuthor, syncRemoteDocument, } from "
|
|
3
|
-
import { createRuntimePrincipalPolicyWarmer } from "
|
|
1
|
+
import { CONTAINER_METADATA_APP_KIND } from "../../../data/persistence/container-contents/containerContentsPersistence.js";
|
|
2
|
+
import { createDocumentWriterPublicKeyResolver, describeDocumentSyncSubmitFailure, resolveDocumentCreateAuthor, syncRemoteDocument, } from "../../documents/index.js";
|
|
3
|
+
import { createRuntimePrincipalPolicyWarmer } from "../../principals/runtimePolicyWarmer.js";
|
|
4
4
|
import { metadataIncomingUpdateIsolation, recordCurrentMetadataSyncFailure, } from "./metadataIncomingUpdateIsolation.js";
|
|
5
5
|
import { deferRecoverableMetadataSyncError } from "./metadataSyncErrors.js";
|
|
6
6
|
function createContainerMetadataSyncAttempt(input) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadataRemoteSync.js","sourceRoot":"","sources":["metadataRemoteSync.ts"],"names":[],"mappings":"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","sourcesContent":["import type { DocumentWriterProjectionResponse } from \"@tearleads/validators/response\";\nimport type { ProjectionUserKeyResolver } from \"../../../data/keyingProjectionVerification\";\nimport { CONTAINER_METADATA_APP_KIND } from \"../../../data/persistence/container-contents/containerContentsPersistence\";\nimport type { PendingUpdateRecord } from \"../../../data/sqlite/documentPersistence\";\nimport {\n createDocumentWriterPublicKeyResolver,\n describeDocumentSyncSubmitFailure,\n type RekeyPendingUpdate,\n resolveDocumentCreateAuthor,\n syncRemoteDocument,\n} from \"../../documents\";\nimport { createRuntimePrincipalPolicyWarmer } from \"../../principals/runtimePolicyWarmer\";\nimport type { ContainerContentsWorkflowRuntime } from \"../runtime\";\nimport {\n metadataIncomingUpdateIsolation,\n recordCurrentMetadataSyncFailure,\n} from \"./metadataIncomingUpdateIsolation\";\nimport { deferRecoverableMetadataSyncError } from \"./metadataSyncErrors\";\nimport type { ContainerMetadataState } from \"./metadataTypes\";\n\ntype ContainerMetadataSyncApi = Parameters<\n typeof syncRemoteDocument\n>[0][\"apiClient\"] &\n Pick<\n ContainerContentsWorkflowRuntime[\"apiClient\"],\n \"getPrincipalPolicyPages\" | \"getProjectionPolicyHistoryPages\"\n >;\n\nexport interface ContainerMetadataSyncRuntime\n extends Pick<\n ContainerContentsWorkflowRuntime,\n | \"auth\"\n | \"crypto\"\n | \"infra\"\n | \"resolveTrustedUserIdentity\"\n | \"state\"\n | \"util\"\n > {\n apiClient: ContainerMetadataSyncApi;\n}\n\ntype ContainerMetadataSyncResult = NonNullable<\n Awaited<ReturnType<typeof syncRemoteDocument>>\n>;\n\nexport interface ContainerMetadataSyncAttempt {\n consumedPullContinuation: ContainerMetadataState[\"pullContinuation\"];\n outgoingUpdateCount: number;\n requestRecord: ContainerMetadataState[\"record\"];\n synced: ContainerMetadataSyncResult;\n}\n\ninterface SyncRemoteContainerMetadataInput {\n buildRotationSnapshot?: (() => Promise<Uint8Array | null>) | undefined;\n containerId: string;\n currentDocument: ContainerMetadataState[\"doc\"];\n documentId: string | null;\n isCurrent: () => boolean;\n lastCommitLsn?: string | null | undefined;\n localVersionVector: string | null;\n onOutgoingUpdatesMaterialized?:\n | ((updateIds: readonly string[]) => void)\n | undefined;\n onPullContinuationInvalidated?: Parameters<\n typeof syncRemoteDocument\n >[0][\"onPullContinuationInvalidated\"];\n pendingUpdates: readonly PendingUpdateRecord[];\n persistedState: ContainerMetadataState[\"record\"];\n pullContinuation?: ContainerMetadataState[\"pullContinuation\"];\n rekeyPendingUpdate: RekeyPendingUpdate;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n runtime: ContainerMetadataSyncRuntime;\n targetSecretKey: Uint8Array;\n writerProjection?: DocumentWriterProjectionResponse | undefined;\n}\n\nfunction createContainerMetadataSyncAttempt(input: {\n outgoingUpdateCount: number;\n requestedPullContinuation: ContainerMetadataState[\"pullContinuation\"];\n requestRecord: ContainerMetadataState[\"record\"];\n synced: ContainerMetadataSyncResult;\n}): ContainerMetadataSyncAttempt {\n return {\n consumedPullContinuation:\n input.synced.plan.request.pullCursor === undefined\n ? null\n : (input.requestedPullContinuation ?? null),\n outgoingUpdateCount: input.outgoingUpdateCount,\n requestRecord: input.requestRecord,\n synced: input.synced,\n };\n}\n\nexport async function syncRemoteContainerMetadata(\n input: SyncRemoteContainerMetadataInput,\n): Promise<ContainerMetadataSyncAttempt | null> {\n const { documentId, isCurrent, runtime } = input;\n if (!documentId) return null;\n const author = resolveDocumentCreateAuthor(runtime);\n if (!author) {\n runtime.util.log(\n \"Container contents: skipped metadata sync because the writer context is unavailable.\",\n );\n return null;\n }\n const execSql = runtime.infra.execSql;\n const metadataScope = {\n appKind: CONTAINER_METADATA_APP_KIND,\n localId: input.containerId,\n };\n const synced = await syncRemoteDocument({\n apiClient: runtime.apiClient,\n author,\n buildRotationSnapshot: input.buildRotationSnapshot,\n documentId,\n execSql,\n isRemoteSyncBlocked: runtime.util.isRemoteSyncBlocked,\n localVersionVector: input.localVersionVector,\n minLsn: input.lastCommitLsn ?? undefined,\n ...metadataIncomingUpdateIsolation({\n currentDocument: input.currentDocument,\n execSql,\n isCurrent,\n logError: runtime.util.logError,\n metadataScope,\n }),\n onOutgoingUpdatesMaterialized: input.onOutgoingUpdatesMaterialized,\n onPullContinuationInvalidated: input.onPullContinuationInvalidated,\n onSyncTrace: (line) => runtime.util.log(`Container contents: ${line}`),\n onTerminalSubmitFailure: async (failure) => {\n await recordCurrentMetadataSyncFailure({\n execSql,\n failure: {\n attemptedAt: new Date().toISOString(),\n message: describeDocumentSyncSubmitFailure(failure),\n status: failure.status,\n },\n isCurrent,\n metadataScope,\n });\n },\n pendingUpdates: input.pendingUpdates,\n persistedState: input.persistedState,\n pullContinuation: input.pullContinuation ?? undefined,\n rekeyPendingUpdate: (rekeyExecSql, updateId) =>\n isCurrent()\n ? input.rekeyPendingUpdate(rekeyExecSql, updateId)\n : Promise.resolve(null),\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n resolveWriterPublicKey: createDocumentWriterPublicKeyResolver({\n logPrefix: \"Container contents\",\n runtime,\n writerKeyLabel: \"metadata writer key\",\n }),\n stillCurrent: isCurrent,\n targetSecretKey: input.targetSecretKey,\n warmReferencedPrincipalPolicies:\n createRuntimePrincipalPolicyWarmer(runtime),\n writerProjection: input.writerProjection,\n }).catch((error: unknown) =>\n deferRecoverableMetadataSyncError({\n containerId: input.containerId,\n error,\n runtime,\n }),\n );\n if (!synced) return null;\n return createContainerMetadataSyncAttempt({\n outgoingUpdateCount: input.pendingUpdates.length,\n requestedPullContinuation: input.pullContinuation,\n requestRecord: input.persistedState,\n synced,\n });\n}\n"]}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type { ContainerDocumentRecord } from "
|
|
1
|
+
import type { ContainerDocumentRecord } from "../containerPersistence.js";
|
|
2
2
|
import type { ContainerMetadataState } from "./metadataTypes.js";
|
|
3
3
|
export declare function installContainerMetadataRecord(metadataState: ContainerMetadataState, record: ContainerDocumentRecord): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadataStateInstallation.js","sourceRoot":"","sources":["metadataStateInstallation.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,8BAA8B,CAC5C,aAAqC,EACrC,MAA+B;IAE/B,aAAa,CAAC,MAAM,GAAG,MAAM,CAAC;IAC9B,aAAa,CAAC,gBAAgB,GAAG,MAAM,CAAC,gBAAgB,IAAI,IAAI,CAAC;AACnE,CAAC","sourcesContent":["import type { ContainerDocumentRecord } from \"../containerPersistence\";\nimport type { ContainerMetadataState } from \"./metadataTypes\";\n\nexport function installContainerMetadataRecord(\n metadataState: ContainerMetadataState,\n record: ContainerDocumentRecord,\n): void {\n metadataState.record = record;\n metadataState.pullContinuation = record.pullContinuation ?? null;\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { encodeVersionVector, exportAllUpdates, exportFullHistorySnapshot, importSnapshot, importUpdates, satisfiesVersionVector, } from "
|
|
2
|
-
import { createContainerMetadataDocument, getDefaultContainerName, readContainerMetadataValue, } from "
|
|
1
|
+
import { encodeVersionVector, exportAllUpdates, exportFullHistorySnapshot, importSnapshot, importUpdates, satisfiesVersionVector, } from "../../../internal/loro/index.js";
|
|
2
|
+
import { createContainerMetadataDocument, getDefaultContainerName, readContainerMetadataValue, } from "../../../data/containers/containerMetadataDocument.js";
|
|
3
|
+
import { projectionGeneration } from "../projectionGeneration.js";
|
|
3
4
|
import { metadataSyncSecurityContextMatches } from "./metadataSyncSettlement.js";
|
|
4
|
-
import { projectionGeneration } from "./projectionGeneration.js";
|
|
5
5
|
function mergeConcurrentMetadataRecord(liveRecord, candidateRecord) {
|
|
6
6
|
if (metadataSyncSecurityContextMatches(liveRecord, candidateRecord)) {
|
|
7
7
|
return liveRecord;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadataStateIsolation.js","sourceRoot":"","sources":["metadataStateIsolation.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n encodeVersionVector,\n exportAllUpdates,\n exportFullHistorySnapshot,\n importSnapshot,\n importUpdates,\n satisfiesVersionVector,\n} from \"@tearleads/loro\";\nimport {\n createContainerMetadataDocument,\n getDefaultContainerName,\n readContainerMetadataValue,\n} from \"../../../data/containers/containerMetadataDocument\";\nimport { projectionGeneration } from \"../projectionGeneration\";\nimport { metadataSyncSecurityContextMatches } from \"./metadataSyncSettlement\";\nimport type { ContainerMetadataState } from \"./metadataTypes\";\n\nexport interface DetachedContainerMetadataState extends ContainerMetadataState {\n readonly detachedSource: {\n readonly metadataVersion: string;\n /** The live state's `writerProjectionGeneration` when it was detached. */\n readonly writerProjectionGeneration: number;\n };\n}\n\ninterface DetachedContainerMetadataInstallOptions {\n readonly candidateRecord?: ContainerMetadataState[\"record\"];\n readonly preserveConcurrentMetadataEdit?: boolean;\n}\n\nfunction mergeConcurrentMetadataRecord(\n liveRecord: ContainerMetadataState[\"record\"],\n candidateRecord: ContainerMetadataState[\"record\"],\n): ContainerMetadataState[\"record\"] {\n if (metadataSyncSecurityContextMatches(liveRecord, candidateRecord)) {\n return liveRecord;\n }\n\n // The live document owns the concurrent CRDT frontier, but the candidate\n // owns the newly committed remote identity. Carry only the fields that\n // describe the live CRDT history across that identity boundary.\n return {\n ...candidateRecord,\n metadataUpdates: liveRecord.metadataUpdates,\n snapshotEndVersion: liveRecord.snapshotEndVersion,\n ...(liveRecord.pendingBaseVersion === undefined\n ? {}\n : { pendingBaseVersion: liveRecord.pendingBaseVersion }),\n };\n}\n\n/**\n * Gives an asynchronous sync pass its own mutable metadata projection. Durable\n * settlement can then repair or replace the candidate without changing the\n * live store until the caller has rechecked its lifecycle generation.\n */\nexport async function createDetachedContainerMetadataState(\n metadataState: ContainerMetadataState,\n options: {\n /**\n * The live generation captured when the surrounding operation began, for\n * callers that awaited (a request, a policy warm-up) before detaching.\n */\n readonly writerProjectionGeneration?: number | undefined;\n } = {},\n): Promise<DetachedContainerMetadataState> {\n const doc = await createContainerMetadataDocument(metadataState.container.id);\n importSnapshot(doc, exportFullHistorySnapshot(metadataState.doc));\n return {\n ...metadataState,\n container: { ...metadataState.container },\n detachedSource: {\n metadataVersion: encodeVersionVector(metadataState.doc),\n writerProjectionGeneration:\n options.writerProjectionGeneration ??\n projectionGeneration(metadataState),\n },\n doc,\n record: { ...metadataState.record },\n };\n}\n\nexport function installDetachedContainerMetadataState(\n target: ContainerMetadataState,\n candidate: DetachedContainerMetadataState,\n options: DetachedContainerMetadataInstallOptions = {},\n): void {\n const candidateRecord = options.candidateRecord ?? candidate.record;\n const liveMetadataVersion = encodeVersionVector(target.doc);\n const candidateMetadataVersion = encodeVersionVector(candidate.doc);\n const liveRecord = target.record;\n const livePullContinuation = target.pullContinuation;\n const preserveConcurrentLiveMetadata =\n options.preserveConcurrentMetadataEdit === true &&\n liveMetadataVersion !== candidate.detachedSource.metadataVersion &&\n !satisfiesVersionVector(candidateMetadataVersion, liveMetadataVersion);\n const installedRecord = preserveConcurrentLiveMetadata\n ? mergeConcurrentMetadataRecord(liveRecord, candidateRecord)\n : candidateRecord;\n\n if (preserveConcurrentLiveMetadata) {\n importUpdates(target.doc, [exportAllUpdates(candidate.doc)]);\n const metadata = readContainerMetadataValue(\n target.doc,\n getDefaultContainerName(candidate.container.parentId),\n );\n target.container = {\n ...candidate.container,\n icon: metadata.icon,\n name: metadata.name,\n };\n } else {\n target.container = candidate.container;\n target.doc = candidate.doc;\n }\n // A hint invalidated the live projections while this candidate was out;\n // its copy may cite a pre-hint manifest, so the live slot stays as the hint\n // left it and the next metadata write fetches a fresh projection.\n if (\n projectionGeneration(target) ===\n candidate.detachedSource.writerProjectionGeneration\n )\n target.metadataWriterProjection = candidate.metadataWriterProjection;\n target.pullContinuation = preserveConcurrentLiveMetadata\n ? metadataSyncSecurityContextMatches(liveRecord, candidateRecord)\n ? livePullContinuation\n : (candidateRecord.pullContinuation ?? null)\n : (candidateRecord.pullContinuation ?? null);\n target.record = installedRecord;\n target.rekeyOnlyPassCount = candidate.rekeyOnlyPassCount;\n}\n"]}
|
package/workflows/container-contents/{metadataSyncErrors.js → metadata/metadataSyncErrors.js}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { isDocumentSyncUpdateIsolationError } from "
|
|
2
|
-
import { isKeyingVerificationError, reportKeyingVerificationErrorInCauseChain, } from "
|
|
3
|
-
import { isPrincipalPolicyNotCachedError } from "
|
|
1
|
+
import { isDocumentSyncUpdateIsolationError } from "../../../data/documents/shared/documentSyncUpdateIsolation.js";
|
|
2
|
+
import { isKeyingVerificationError, reportKeyingVerificationErrorInCauseChain, } from "../../../data/keyingProjectionVerification/error.js";
|
|
3
|
+
import { isPrincipalPolicyNotCachedError } from "../../../data/keyingProjectionVerification/principalPolicyVerification.js";
|
|
4
4
|
function isStaleContainerMetadataSecurityStateError(error) {
|
|
5
5
|
// Signed-state verification failures are terminal integrity incidents, even
|
|
6
6
|
// when their diagnostic message resembles an ordinary stale-key condition.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadataSyncErrors.js","sourceRoot":"","sources":["metadataSyncErrors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kCAAkC,EAAE,MAAM,4DAA4D,CAAC;AAChH,OAAO,EACL,yBAAyB,EACzB,yCAAyC,GAC1C,MAAM,kDAAkD,CAAC;AAC1D,OAAO,EAAE,+BAA+B,EAAE,MAAM,wEAAwE,CAAC;AAGzH,SAAS,0CAA0C,CAAC,KAAc;IAChE,4EAA4E;IAC5E,2EAA2E;IAC3E,IAAI,yBAAyB,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACnD,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IAE5D,OAAO,CACL,OAAO,CAAC,UAAU,CAChB,gEAAgE,CACjE;QACD,OAAO,CAAC,UAAU,CAAC,6CAA6C,CAAC;QACjE,OAAO,CAAC,UAAU,CAAC,sCAAsC,CAAC;QAC1D,OAAO,CAAC,UAAU,CAAC,iDAAiD,CAAC;QACrE,OAAO,CAAC,UAAU,CAAC,gCAAgC,CAAC;QACpD,OAAO,KAAK,oCAAoC;QAChD,OAAO,KAAK,4CAA4C,CACzD,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iCAAiC,CAAC,KAUvD;IACC,IAAI,kCAAkC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QACpD,MAAM,yCAAyC,CAC7C,KAAK,CAAC,KAAK,EACX,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,sBAAsB,EACzC;YACE,QAAQ,EAAE,KAAK,CAAC,WAAW;YAC3B,UAAU,EAAE,WAAW;YACvB,SAAS,EAAE,yBAAyB;YACpC,cAAc,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc;SAClD,CACF,CAAC;QACF,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CACpB,iEAAiE,KAAK,CAAC,WAAW,kEAAkE,CACrJ,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,0CAA0C,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5D,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CACpB,kDAAkD,KAAK,CAAC,WAAW,6CAA6C,CACjH,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,6EAA6E;IAC7E,6EAA6E;IAC7E,IAAI,+BAA+B,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QACjD,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CACpB,kDAAkD,KAAK,CAAC,WAAW,2DAA2D,CAC/H,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,KAAK,CAAC,KAAK,CAAC;AACpB,CAAC","sourcesContent":["import { isDocumentSyncUpdateIsolationError } from \"../../../data/documents/shared/documentSyncUpdateIsolation\";\nimport {\n isKeyingVerificationError,\n reportKeyingVerificationErrorInCauseChain,\n} from \"../../../data/keyingProjectionVerification/error\";\nimport { isPrincipalPolicyNotCachedError } from \"../../../data/keyingProjectionVerification/principalPolicyVerification\";\nimport type { SecurityIncidentReporter } from \"../../../data/shared/securityIncidents\";\n\nfunction isStaleContainerMetadataSecurityStateError(error: unknown): boolean {\n // Signed-state verification failures are terminal integrity incidents, even\n // when their diagnostic message resembles an ordinary stale-key condition.\n if (isKeyingVerificationError(error)) return false;\n const message = error instanceof Error ? error.message : \"\";\n\n return (\n message.startsWith(\n \"Document authorizing container KEK path could not be unwrapped\",\n ) ||\n message.startsWith(\"Document content key could not be unwrapped\") ||\n message.startsWith(\"Document content-key bundle is stale\") ||\n message.startsWith(\"Document content-key re-wrap KEK is unavailable\") ||\n message.startsWith(\"Document stale-bundle recovery\") ||\n message === \"Document sync target hash mismatch\" ||\n message === \"Document sync content-key targets mismatch\"\n );\n}\n\nexport async function deferRecoverableMetadataSyncError(input: {\n containerId: string;\n error: unknown;\n runtime: {\n auth: { organizationId: string | null };\n util: {\n log: (message: string) => void;\n reportSecurityIncident: SecurityIncidentReporter;\n };\n };\n}): Promise<null> {\n if (isDocumentSyncUpdateIsolationError(input.error)) {\n await reportKeyingVerificationErrorInCauseChain(\n input.error,\n input.runtime.util.reportSecurityIncident,\n {\n objectId: input.containerId,\n objectKind: \"container\",\n operation: \"container.metadata.sync\",\n organizationId: input.runtime.auth.organizationId,\n },\n );\n input.runtime.util.log(\n `Container contents: quarantined incoming metadata updates for ${input.containerId}; deferred this container without blocking later metadata syncs.`,\n );\n return null;\n }\n\n if (isStaleContainerMetadataSecurityStateError(input.error)) {\n input.runtime.util.log(\n `Container contents: deferred metadata sync for ${input.containerId} because its content-key targets are stale.`,\n );\n return null;\n }\n\n // A cold principal-policy cache is transient: warming already ran and failed\n // within this attempt. Keep the needing-sync state set for the next trigger.\n if (isPrincipalPolicyNotCachedError(input.error)) {\n input.runtime.util.log(\n `Container contents: deferred metadata sync for ${input.containerId} because a referenced principal policy is not cached yet.`,\n );\n return null;\n }\n\n throw input.error;\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { DocumentSyncPullContinuation } from "
|
|
2
|
-
import type { ContainerDocumentRecord as DocumentRecord } from "
|
|
1
|
+
import type { DocumentSyncPullContinuation } from "../../../data/documents/shared/syncPagination.js";
|
|
2
|
+
import type { ContainerDocumentRecord as DocumentRecord } from "../containerPersistence.js";
|
|
3
3
|
import type { ContainerMetadataState } from "./metadataTypes.js";
|
|
4
4
|
export interface ExpectedContainerMetadataSyncState {
|
|
5
5
|
pullContinuation: DocumentSyncPullContinuation | null;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { base64ToBytes } from "
|
|
2
|
-
import { importUpdates } from "
|
|
3
|
-
import { createContainerMetadataDocument } from "
|
|
1
|
+
import { base64ToBytes } from "../../../internal/encoding/index.js";
|
|
2
|
+
import { importUpdates } from "../../../internal/loro/index.js";
|
|
3
|
+
import { createContainerMetadataDocument } from "../../../data/containers/containerMetadataDocument.js";
|
|
4
4
|
export function sameNullableMetadataValue(left, right) {
|
|
5
5
|
return (left ?? null) === (right ?? null);
|
|
6
6
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadataSyncSettlement.js","sourceRoot":"","sources":["metadataSyncSettlement.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,+BAA+B,EAAE,MAAM,oDAAoD,CAAC;AAUrG,MAAM,UAAU,yBAAyB,CACvC,IAA+B,EAC/B,KAAgC;IAEhC,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,kCAAkC,CAChD,OAA8B,EAC9B,QAAwB;IAExB,OAAO,CACL,OAAO,KAAK,IAAI;QAChB,OAAO,CAAC,EAAE,KAAK,QAAQ,CAAC,EAAE;QAC1B,OAAO,CAAC,UAAU,KAAK,QAAQ,CAAC,UAAU;QAC1C,OAAO,CAAC,WAAW,KAAK,QAAQ,CAAC,WAAW;QAC5C,yBAAyB,CACvB,OAAO,CAAC,eAAe,EACvB,QAAQ,CAAC,eAAe,CACzB;QACD,yBAAyB,CACvB,OAAO,CAAC,gBAAgB,EACxB,QAAQ,CAAC,gBAAgB,CAC1B;QACD,yBAAyB,CACvB,OAAO,CAAC,kBAAkB,EAC1B,QAAQ,CAAC,kBAAkB,CAC5B;QACD,yBAAyB,CACvB,OAAO,CAAC,sBAAsB,EAC9B,QAAQ,CAAC,sBAAsB,CAChC,CACF,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iCAAiC,CAAC,KAGvD;IACC,MAAM,cAAc,GAAG,MAAM,+BAA+B,CAC1D,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,CACjC,CAAC;IACF,IAAI,KAAK,CAAC,aAAa,EAAE,eAAe,EAAE,CAAC;QACzC,aAAa,CAAC,cAAc,EAAE;YAC5B,aAAa,CAAC,KAAK,CAAC,aAAa,CAAC,eAAe,CAAC;SACnD,CAAC,CAAC;IACL,CAAC;IACD,KAAK,CAAC,aAAa,CAAC,GAAG,GAAG,cAAc,CAAC;IACzC,KAAK,CAAC,aAAa,CAAC,wBAAwB,GAAG,IAAI,CAAC;AACtD,CAAC","sourcesContent":["import { base64ToBytes } from \"@tearleads/encoding\";\nimport { importUpdates } from \"@tearleads/loro\";\nimport { createContainerMetadataDocument } from \"../../../data/containers/containerMetadataDocument\";\nimport type { DocumentSyncPullContinuation } from \"../../../data/documents/shared/syncPagination\";\nimport type { ContainerDocumentRecord as DocumentRecord } from \"../containerPersistence\";\nimport type { ContainerMetadataState } from \"./metadataTypes\";\n\nexport interface ExpectedContainerMetadataSyncState {\n pullContinuation: DocumentSyncPullContinuation | null;\n record: DocumentRecord;\n}\n\nexport function sameNullableMetadataValue(\n left: string | null | undefined,\n right: string | null | undefined,\n): boolean {\n return (left ?? null) === (right ?? null);\n}\n\nexport function metadataSyncSecurityContextMatches(\n current: DocumentRecord | null,\n expected: DocumentRecord,\n): boolean {\n return (\n current !== null &&\n current.id === expected.id &&\n current.documentId === expected.documentId &&\n current.accessEpoch === expected.accessEpoch &&\n sameNullableMetadataValue(\n current.accessStateHash,\n expected.accessStateHash,\n ) &&\n sameNullableMetadataValue(\n current.contentKeyBundle,\n expected.contentKeyBundle,\n ) &&\n sameNullableMetadataValue(\n current.documentKekTargets,\n expected.documentKekTargets,\n ) &&\n sameNullableMetadataValue(\n current.documentManifestBundle,\n expected.documentManifestBundle,\n )\n );\n}\n\nexport async function replaceSupersededMetadataIdentity(input: {\n durableRecord: DocumentRecord | null;\n metadataState: ContainerMetadataState;\n}): Promise<void> {\n const replacementDoc = await createContainerMetadataDocument(\n input.metadataState.container.id,\n );\n if (input.durableRecord?.metadataUpdates) {\n importUpdates(replacementDoc, [\n base64ToBytes(input.durableRecord.metadataUpdates),\n ]);\n }\n input.metadataState.doc = replacementDoc;\n input.metadataState.metadataWriterProjection = null;\n}\n"]}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { DocumentWriterProjectionResponse } from "
|
|
2
|
-
import type { ContainerMetadataDocument } from "
|
|
3
|
-
import type { DocumentSyncPullContinuation } from "
|
|
4
|
-
import type { ContainerMetadataRecord } from "
|
|
5
|
-
import type { ContainerRecord } from "
|
|
1
|
+
import type { DocumentWriterProjectionResponse } from "../../../internal/validators/response/index.js";
|
|
2
|
+
import type { ContainerMetadataDocument } from "../../../data/containers/containerMetadataDocument.js";
|
|
3
|
+
import type { DocumentSyncPullContinuation } from "../../../data/documents/shared/syncPagination.js";
|
|
4
|
+
import type { ContainerMetadataRecord } from "../../../data/persistence/container-contents/containerContentsPersistence.js";
|
|
5
|
+
import type { ContainerRecord } from "../../../data/persistence/containers/containerPersistence.js";
|
|
6
6
|
export interface ContainerMetadataState {
|
|
7
7
|
container: ContainerRecord;
|
|
8
8
|
doc: ContainerMetadataDocument;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadataTypes.js","sourceRoot":"","sources":["metadataTypes.ts"],"names":[],"mappings":"","sourcesContent":["import type { DocumentWriterProjectionResponse } from \"@tearleads/validators/response\";\nimport type { ContainerMetadataDocument } from \"../../../data/containers/containerMetadataDocument\";\nimport type { DocumentSyncPullContinuation } from \"../../../data/documents/shared/syncPagination\";\nimport type { ContainerMetadataRecord } from \"../../../data/persistence/container-contents/containerContentsPersistence\";\nimport type { ContainerRecord } from \"../../../data/persistence/containers/containerPersistence\";\n\nexport interface ContainerMetadataState {\n container: ContainerRecord;\n doc: ContainerMetadataDocument;\n metadataWriterProjection?:\n | DocumentWriterProjectionResponse\n | null\n | undefined;\n /** See `ContainerState.writerProjectionGeneration`; shared by both caches. */\n writerProjectionGeneration?: number | undefined;\n /** Durable continuation mirrored from the metadata document record. */\n pullContinuation?: DocumentSyncPullContinuation | null | undefined;\n record: ContainerMetadataRecord;\n /**\n * Consecutive completed sync passes that re-keyed conflicted pending updates\n * without settling anything; bounds the rekey-driven follow-up sync. See\n * shouldReArmAfterOutgoingSettlement.\n */\n rekeyOnlyPassCount?: number | undefined;\n}\n\nexport interface ContainerMetadataPatch {\n accessEpoch: number;\n accessStateHash: string | null;\n effectiveAccessLevel: ContainerRecord[\"effectiveAccessLevel\"];\n documentId: string | null;\n icon: string | null;\n lastCommitLsn: string | null;\n metadataDocumentId: string | null;\n systemSlot: ContainerRecord[\"systemSlot\"];\n metadataUpdates: string;\n name: string;\n organizationId: string;\n parentId: string | null;\n pullContinuation: DocumentSyncPullContinuation | null;\n contentKeyBundle: string | null;\n documentKekTargets: string | null;\n documentManifestBundle: string | null;\n}\n\nexport interface PersistedContainerMetadataState {\n container: ContainerRecord;\n createIntentSettled?: true;\n moveIntentSettled?: true;\n mutationSuperseded?: true;\n pullContinuationSuperseded?: true;\n record: ContainerMetadataRecord;\n syncIdentitySuperseded?: true;\n}\n\nexport interface SyncedContainerMetadataState\n extends PersistedContainerMetadataState {\n shouldRequestFollowupSync: boolean;\n}\n\nexport interface MissingContainerMetadataState {\n missing: true;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aggregation.js","sourceRoot":"","sources":["aggregation.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n PendingWriteQueueItem,\n PendingWriteQueueItemStatus,\n PendingWriteQueueObjectKind,\n PendingWriteQueueOperation,\n PendingWriteQueueOperationKind,\n PendingWriteQueueOperationStatus,\n} from \"../pendingWritesTypes\";\n\nexport type PendingWriteCandidateInclusion =\n | \"always\"\n | \"unless-item-covered\"\n | \"unless-operation-covered\";\n\nexport interface PendingWriteCandidate {\n readonly byteLength: number;\n readonly containerId: string | null;\n readonly count: number;\n readonly createdAt: string | null;\n readonly inclusion: PendingWriteCandidateInclusion;\n readonly kind: PendingWriteQueueOperationKind;\n readonly lastAttemptedAt: string | null;\n readonly lastError: string | null;\n readonly localId: string;\n readonly name: string | null;\n readonly namespace: string | null;\n readonly objectKind: PendingWriteQueueObjectKind;\n readonly organizationId: string | null;\n readonly remoteId: string | null;\n readonly status: PendingWriteQueueOperationStatus;\n readonly targetContainerId: string | null;\n readonly updatedAt: string | null;\n}\n\ninterface PendingWriteItemBuilder {\n containerId: string | null;\n localId: string;\n name: string | null;\n namespace: string | null;\n objectKind: PendingWriteQueueObjectKind;\n operations: PendingWriteQueueOperation[];\n organizationId: string | null;\n remoteId: string | null;\n}\n\nconst INCLUSION_RANK: Record<PendingWriteCandidateInclusion, number> = {\n always: 0,\n \"unless-operation-covered\": 1,\n \"unless-item-covered\": 2,\n};\n\nconst OPERATION_RANK: Record<PendingWriteQueueOperationKind, number> = {\n create: 0,\n move: 1,\n update: 2,\n \"deferred-update\": 3,\n attachment: 4,\n // Diagnostic-only: a refused read-only revalidation, never local data.\n revalidation: 5,\n};\n\nconst OBJECT_RANK: Record<PendingWriteQueueObjectKind, number> = {\n container: 0,\n document: 1,\n unknown: 2,\n};\n\nfunction candidateKey(candidate: PendingWriteCandidate): string {\n return [\n candidate.objectKind,\n candidate.namespace ?? \"\",\n candidate.localId,\n ].join(\"\\0\");\n}\n\nfunction createItemBuilder(\n candidate: PendingWriteCandidate,\n): PendingWriteItemBuilder {\n return {\n containerId: candidate.containerId,\n localId: candidate.localId,\n name: candidate.name,\n namespace: candidate.namespace,\n objectKind: candidate.objectKind,\n operations: [],\n organizationId: candidate.organizationId,\n remoteId: candidate.remoteId,\n };\n}\n\nfunction mergeItemMetadata(\n item: PendingWriteItemBuilder,\n candidate: PendingWriteCandidate,\n): void {\n item.containerId ??= candidate.containerId;\n item.name ??= candidate.name;\n item.organizationId ??= candidate.organizationId;\n item.remoteId ??= candidate.remoteId;\n}\n\nfunction shouldIncludeCandidate(\n item: PendingWriteItemBuilder | undefined,\n candidate: PendingWriteCandidate,\n): boolean {\n if (candidate.inclusion === \"always\") {\n return true;\n }\n if (candidate.inclusion === \"unless-item-covered\") {\n return !item || item.operations.length === 0;\n }\n return !item?.operations.some(\n (operation) => operation.kind === candidate.kind,\n );\n}\n\nfunction operationFromCandidate(\n candidate: PendingWriteCandidate,\n): PendingWriteQueueOperation {\n return {\n byteLength: candidate.byteLength,\n count: candidate.count,\n createdAt: candidate.createdAt,\n kind: candidate.kind,\n lastAttemptedAt: candidate.lastAttemptedAt,\n lastError: candidate.lastError,\n status: candidate.status,\n targetContainerId: candidate.targetContainerId,\n updatedAt: candidate.updatedAt,\n };\n}\n\nfunction earliestTimestamp(\n operations: ReadonlyArray<PendingWriteQueueOperation>,\n): string | null {\n const timestamps = operations.flatMap((operation) =>\n operation.createdAt ? [operation.createdAt] : [],\n );\n return timestamps.length > 0 ? (timestamps.sort()[0] ?? null) : null;\n}\n\nfunction latestTimestamp(\n operations: ReadonlyArray<PendingWriteQueueOperation>,\n): string | null {\n const timestamps = operations.flatMap((operation) => {\n const timestamp = operation.updatedAt ?? operation.createdAt;\n return timestamp ? [timestamp] : [];\n });\n return timestamps.length > 0 ? (timestamps.sort().at(-1) ?? null) : null;\n}\n\nfunction resolveItemStatus(\n operations: ReadonlyArray<PendingWriteQueueOperation>,\n): PendingWriteQueueItemStatus {\n if (operations.some((operation) => operation.status === \"blocked\")) {\n return \"blocked\";\n }\n if (operations.some((operation) => operation.lastError !== null)) {\n return \"error\";\n }\n return \"pending\";\n}\n\nfunction compareOperations(\n left: PendingWriteQueueOperation,\n right: PendingWriteQueueOperation,\n): number {\n return (\n OPERATION_RANK[left.kind] - OPERATION_RANK[right.kind] ||\n (left.createdAt ?? \"\").localeCompare(right.createdAt ?? \"\")\n );\n}\n\nfunction compareItems(\n left: PendingWriteQueueItem,\n right: PendingWriteQueueItem,\n): number {\n const leftTimestamp = left.createdAt ?? left.updatedAt;\n const rightTimestamp = right.createdAt ?? right.updatedAt;\n if (leftTimestamp !== rightTimestamp) {\n if (leftTimestamp === null) return 1;\n if (rightTimestamp === null) return -1;\n return leftTimestamp.localeCompare(rightTimestamp);\n }\n return (\n OBJECT_RANK[left.objectKind] - OBJECT_RANK[right.objectKind] ||\n (left.namespace ?? \"\").localeCompare(right.namespace ?? \"\") ||\n left.localId.localeCompare(right.localId)\n );\n}\n\nexport function groupPendingWriteCandidates(\n candidates: ReadonlyArray<PendingWriteCandidate>,\n): PendingWriteQueueItem[] {\n const itemsByKey = new Map<string, PendingWriteItemBuilder>();\n const orderedCandidates = [...candidates].sort(\n (left, right) =>\n INCLUSION_RANK[left.inclusion] - INCLUSION_RANK[right.inclusion],\n );\n\n for (const candidate of orderedCandidates) {\n const key = candidateKey(candidate);\n const existing = itemsByKey.get(key);\n if (existing) {\n mergeItemMetadata(existing, candidate);\n }\n if (!shouldIncludeCandidate(existing, candidate)) {\n continue;\n }\n const item = existing ?? createItemBuilder(candidate);\n item.operations.push(operationFromCandidate(candidate));\n itemsByKey.set(key, item);\n }\n\n return Array.from(itemsByKey.values(), (item): PendingWriteQueueItem => {\n const operations = [...item.operations].sort(compareOperations);\n return {\n containerId: item.containerId,\n createdAt: earliestTimestamp(operations),\n localId: item.localId,\n name: item.name,\n namespace: item.namespace,\n objectKind: item.objectKind,\n operations,\n organizationId: item.organizationId,\n remoteId: item.remoteId,\n status: resolveItemStatus(operations),\n updatedAt: latestTimestamp(operations),\n };\n }).sort(compareItems);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"aggregation.js","sourceRoot":"","sources":["aggregation.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n PendingWriteQueueItem,\n PendingWriteQueueItemStatus,\n PendingWriteQueueObjectKind,\n PendingWriteQueueOperation,\n PendingWriteQueueOperationKind,\n PendingWriteQueueOperationStatus,\n} from \"./pendingWritesTypes\";\n\nexport type PendingWriteCandidateInclusion =\n | \"always\"\n | \"unless-item-covered\"\n | \"unless-operation-covered\";\n\nexport interface PendingWriteCandidate {\n readonly byteLength: number;\n readonly containerId: string | null;\n readonly count: number;\n readonly createdAt: string | null;\n readonly inclusion: PendingWriteCandidateInclusion;\n readonly kind: PendingWriteQueueOperationKind;\n readonly lastAttemptedAt: string | null;\n readonly lastError: string | null;\n readonly localId: string;\n readonly name: string | null;\n readonly namespace: string | null;\n readonly objectKind: PendingWriteQueueObjectKind;\n readonly organizationId: string | null;\n readonly remoteId: string | null;\n readonly status: PendingWriteQueueOperationStatus;\n readonly targetContainerId: string | null;\n readonly updatedAt: string | null;\n}\n\ninterface PendingWriteItemBuilder {\n containerId: string | null;\n localId: string;\n name: string | null;\n namespace: string | null;\n objectKind: PendingWriteQueueObjectKind;\n operations: PendingWriteQueueOperation[];\n organizationId: string | null;\n remoteId: string | null;\n}\n\nconst INCLUSION_RANK: Record<PendingWriteCandidateInclusion, number> = {\n always: 0,\n \"unless-operation-covered\": 1,\n \"unless-item-covered\": 2,\n};\n\nconst OPERATION_RANK: Record<PendingWriteQueueOperationKind, number> = {\n create: 0,\n move: 1,\n update: 2,\n \"deferred-update\": 3,\n attachment: 4,\n // Diagnostic-only: a refused read-only revalidation, never local data.\n revalidation: 5,\n};\n\nconst OBJECT_RANK: Record<PendingWriteQueueObjectKind, number> = {\n container: 0,\n document: 1,\n unknown: 2,\n};\n\nfunction candidateKey(candidate: PendingWriteCandidate): string {\n return [\n candidate.objectKind,\n candidate.namespace ?? \"\",\n candidate.localId,\n ].join(\"\\0\");\n}\n\nfunction createItemBuilder(\n candidate: PendingWriteCandidate,\n): PendingWriteItemBuilder {\n return {\n containerId: candidate.containerId,\n localId: candidate.localId,\n name: candidate.name,\n namespace: candidate.namespace,\n objectKind: candidate.objectKind,\n operations: [],\n organizationId: candidate.organizationId,\n remoteId: candidate.remoteId,\n };\n}\n\nfunction mergeItemMetadata(\n item: PendingWriteItemBuilder,\n candidate: PendingWriteCandidate,\n): void {\n item.containerId ??= candidate.containerId;\n item.name ??= candidate.name;\n item.organizationId ??= candidate.organizationId;\n item.remoteId ??= candidate.remoteId;\n}\n\nfunction shouldIncludeCandidate(\n item: PendingWriteItemBuilder | undefined,\n candidate: PendingWriteCandidate,\n): boolean {\n if (candidate.inclusion === \"always\") {\n return true;\n }\n if (candidate.inclusion === \"unless-item-covered\") {\n return !item || item.operations.length === 0;\n }\n return !item?.operations.some(\n (operation) => operation.kind === candidate.kind,\n );\n}\n\nfunction operationFromCandidate(\n candidate: PendingWriteCandidate,\n): PendingWriteQueueOperation {\n return {\n byteLength: candidate.byteLength,\n count: candidate.count,\n createdAt: candidate.createdAt,\n kind: candidate.kind,\n lastAttemptedAt: candidate.lastAttemptedAt,\n lastError: candidate.lastError,\n status: candidate.status,\n targetContainerId: candidate.targetContainerId,\n updatedAt: candidate.updatedAt,\n };\n}\n\nfunction earliestTimestamp(\n operations: ReadonlyArray<PendingWriteQueueOperation>,\n): string | null {\n const timestamps = operations.flatMap((operation) =>\n operation.createdAt ? [operation.createdAt] : [],\n );\n return timestamps.length > 0 ? (timestamps.sort()[0] ?? null) : null;\n}\n\nfunction latestTimestamp(\n operations: ReadonlyArray<PendingWriteQueueOperation>,\n): string | null {\n const timestamps = operations.flatMap((operation) => {\n const timestamp = operation.updatedAt ?? operation.createdAt;\n return timestamp ? [timestamp] : [];\n });\n return timestamps.length > 0 ? (timestamps.sort().at(-1) ?? null) : null;\n}\n\nfunction resolveItemStatus(\n operations: ReadonlyArray<PendingWriteQueueOperation>,\n): PendingWriteQueueItemStatus {\n if (operations.some((operation) => operation.status === \"blocked\")) {\n return \"blocked\";\n }\n if (operations.some((operation) => operation.lastError !== null)) {\n return \"error\";\n }\n return \"pending\";\n}\n\nfunction compareOperations(\n left: PendingWriteQueueOperation,\n right: PendingWriteQueueOperation,\n): number {\n return (\n OPERATION_RANK[left.kind] - OPERATION_RANK[right.kind] ||\n (left.createdAt ?? \"\").localeCompare(right.createdAt ?? \"\")\n );\n}\n\nfunction compareItems(\n left: PendingWriteQueueItem,\n right: PendingWriteQueueItem,\n): number {\n const leftTimestamp = left.createdAt ?? left.updatedAt;\n const rightTimestamp = right.createdAt ?? right.updatedAt;\n if (leftTimestamp !== rightTimestamp) {\n if (leftTimestamp === null) return 1;\n if (rightTimestamp === null) return -1;\n return leftTimestamp.localeCompare(rightTimestamp);\n }\n return (\n OBJECT_RANK[left.objectKind] - OBJECT_RANK[right.objectKind] ||\n (left.namespace ?? \"\").localeCompare(right.namespace ?? \"\") ||\n left.localId.localeCompare(right.localId)\n );\n}\n\nexport function groupPendingWriteCandidates(\n candidates: ReadonlyArray<PendingWriteCandidate>,\n): PendingWriteQueueItem[] {\n const itemsByKey = new Map<string, PendingWriteItemBuilder>();\n const orderedCandidates = [...candidates].sort(\n (left, right) =>\n INCLUSION_RANK[left.inclusion] - INCLUSION_RANK[right.inclusion],\n );\n\n for (const candidate of orderedCandidates) {\n const key = candidateKey(candidate);\n const existing = itemsByKey.get(key);\n if (existing) {\n mergeItemMetadata(existing, candidate);\n }\n if (!shouldIncludeCandidate(existing, candidate)) {\n continue;\n }\n const item = existing ?? createItemBuilder(candidate);\n item.operations.push(operationFromCandidate(candidate));\n itemsByKey.set(key, item);\n }\n\n return Array.from(itemsByKey.values(), (item): PendingWriteQueueItem => {\n const operations = [...item.operations].sort(compareOperations);\n return {\n containerId: item.containerId,\n createdAt: earliestTimestamp(operations),\n localId: item.localId,\n name: item.name,\n namespace: item.namespace,\n objectKind: item.objectKind,\n operations,\n organizationId: item.organizationId,\n remoteId: item.remoteId,\n status: resolveItemStatus(operations),\n updatedAt: latestTimestamp(operations),\n };\n }).sort(compareItems);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deferredTails.js","sourceRoot":"","sources":["deferredTails.ts"],"names":[],"mappings":"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","sourcesContent":["import { mergeVersionVectors, satisfiesVersionVector } from \"@tearleads/loro\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport {\n getContainerDisplayNameSql,\n getContainerOrganizationAttributionSql,\n} from \"../documentQueries/sql\";\nimport type { PendingWriteQueueObjectKind } from \"../pendingWritesTypes\";\nimport type { PendingWriteCandidate } from \"./aggregation\";\nimport { readString } from \"./rowReaders\";\n\n// Deliberately never loads document content: the diagnostic listing runs\n// repeatedly while sync drains, and materializing every content blob would\n// make the scan O(total document content). `snapshot_end_version` is the\n// write-time-derived end version vector of the persisted content.\nconst DEFERRED_TAIL_CANDIDATE_SQL = `\n SELECT\n stored.app_kind AS app_kind,\n stored.local_id AS local_id,\n stored.document_id AS stored_remote_id,\n stored.snapshot_end_version AS snapshot_end_version,\n stored.pending_base_version AS pending_base_version,\n stored.updated_at AS updated_at,\n (\n SELECT pending.partial_end_version_vector\n FROM document_history_updates pending\n WHERE pending.app_kind = stored.app_kind\n AND pending.local_id = stored.local_id\n AND pending.update_id IS NOT NULL\n ORDER BY pending.created_at DESC, pending.rowid DESC\n LIMIT 1\n ) AS latest_pending_end_version,\n document_projection.title AS document_name,\n document_projection.container_id AS document_container_id,\n ${getContainerOrganizationAttributionSql({\n containerAlias: \"document_container\",\n projectionAlias: \"document_projection\",\n })} AS document_organization_id,\n CASE\n WHEN metadata_container.server_created_at IS NULL THEN NULL\n ELSE metadata_container.id\n END AS container_remote_id,\n ${getContainerDisplayNameSql(\"metadata_container\")} AS container_name,\n metadata_container.id AS metadata_container_id,\n NULLIF(metadata_container.organization_id, '') AS metadata_organization_id,\n stored.sync_failure_message AS failure_message,\n stored.sync_failure_attempted_at AS failure_attempted_at\n FROM documents stored\n LEFT JOIN document_projection\n ON stored.app_kind = 'documents'\n AND document_projection.local_id = stored.local_id\n LEFT JOIN containers document_container\n ON document_container.id = document_projection.container_id\n LEFT JOIN containers metadata_container\n ON stored.app_kind = 'container-metadata'\n AND metadata_container.id = stored.local_id\n WHERE stored.snapshot_end_version <> ''\n -- Dormant retained metadata (row 4, access_revoked) has no containers\n -- row; keep it out of deferred-tail candidates until re-attach, matching\n -- the pending-write sources guard.\n AND (stored.app_kind <> 'container-metadata'\n OR metadata_container.id IS NOT NULL)\n AND (\n stored.pending_base_version IS NOT NULL\n OR EXISTS (\n SELECT 1\n FROM document_history_updates pending\n WHERE pending.app_kind = stored.app_kind\n AND pending.local_id = stored.local_id\n AND pending.update_id IS NOT NULL\n )\n )\n`;\n\nfunction hasUncoveredTail(input: {\n currentVersion: string;\n latestPendingEndVersion: string | null;\n pendingBaseVersion: string | null;\n}): boolean {\n const coverageVersions = [\n input.latestPendingEndVersion,\n input.pendingBaseVersion,\n ].filter((value): value is string => value !== null);\n const validCoverageVersions: string[] = [];\n for (const coverageVersion of coverageVersions) {\n try {\n validCoverageVersions.push(mergeVersionVectors([coverageVersion]));\n } catch {\n // Corrupt coverage must not make the diagnostic claim an uncovered write.\n return false;\n }\n }\n if (validCoverageVersions.length === 0) {\n return false;\n }\n\n try {\n const mergedCoverage = mergeVersionVectors(validCoverageVersions);\n return !satisfiesVersionVector(mergedCoverage, input.currentVersion);\n } catch {\n // Corrupt coverage must not make the diagnostic claim an uncovered write.\n return false;\n }\n}\n\nfunction getObjectKind(appKind: string): PendingWriteQueueObjectKind {\n if (appKind === \"documents\") return \"document\";\n if (appKind === \"container-metadata\") return \"container\";\n return \"unknown\";\n}\n\nfunction mapDeferredTailCandidate(\n row: Record<string, unknown>,\n): PendingWriteCandidate | null {\n const appKind = readString(row, \"app_kind\");\n const localId = readString(row, \"local_id\");\n const currentVersion = readString(row, \"snapshot_end_version\");\n if (!appKind || !localId || !currentVersion) {\n return null;\n }\n if (\n !hasUncoveredTail({\n currentVersion,\n latestPendingEndVersion: readString(row, \"latest_pending_end_version\"),\n pendingBaseVersion: readString(row, \"pending_base_version\"),\n })\n ) {\n return null;\n }\n\n const objectKind = getObjectKind(appKind);\n const updatedAt = readString(row, \"updated_at\");\n return {\n byteLength: 0,\n containerId:\n objectKind === \"container\"\n ? readString(row, \"metadata_container_id\")\n : objectKind === \"document\"\n ? readString(row, \"document_container_id\")\n : null,\n count: 1,\n createdAt: updatedAt,\n inclusion: \"always\",\n kind: \"deferred-update\",\n // Carry the scope's recorded sync failure so a covering deferred-update\n // candidate never hides the diagnostic a suppressed failure-only item\n // would have shown.\n lastAttemptedAt: readString(row, \"failure_attempted_at\"),\n lastError: readString(row, \"failure_message\"),\n localId,\n name:\n objectKind === \"container\"\n ? readString(row, \"container_name\")\n : objectKind === \"document\"\n ? readString(row, \"document_name\")\n : null,\n namespace: objectKind === \"unknown\" ? appKind : null,\n objectKind,\n organizationId:\n objectKind === \"container\"\n ? readString(row, \"metadata_organization_id\")\n : objectKind === \"document\"\n ? readString(row, \"document_organization_id\")\n : null,\n remoteId:\n objectKind === \"container\"\n ? readString(row, \"container_remote_id\")\n : readString(row, \"stored_remote_id\"),\n status: \"pending\",\n targetContainerId: null,\n updatedAt,\n };\n}\n\nexport async function listDeferredPendingWriteCandidates(\n execSql: ExecSql,\n): Promise<PendingWriteCandidate[]> {\n const rows = await execSql(DEFERRED_TAIL_CANDIDATE_SQL);\n return rows.flatMap((row) => {\n const candidate = mapDeferredTailCandidate(row);\n return candidate ? [candidate] : [];\n });\n}\n\nconst DEFERRED_TAIL_SCOPE_SQL = `\n SELECT\n stored.snapshot_end_version AS snapshot_end_version,\n stored.pending_base_version AS pending_base_version,\n (\n SELECT pending.partial_end_version_vector\n FROM document_history_updates pending\n WHERE pending.app_kind = stored.app_kind\n AND pending.local_id = stored.local_id\n AND pending.update_id IS NOT NULL\n ORDER BY pending.created_at DESC, pending.rowid DESC\n LIMIT 1\n ) AS latest_pending_end_version\n FROM documents stored\n WHERE stored.app_kind = ? AND stored.local_id = ?\n AND stored.snapshot_end_version <> ''\n -- Dormant retained metadata (row 4, access_revoked) has no containers\n -- row; it is not queued work until re-attach, matching the candidate\n -- scan's guard.\n AND (stored.app_kind <> 'container-metadata'\n OR EXISTS (SELECT 1 FROM containers WHERE containers.id = stored.local_id))\n LIMIT 1\n`;\n\n/**\n * Whether this one scope has a deferred write: durable-tail content ahead of\n * its covered frontier, possibly with no queued update rows at all. The same\n * coverage check as the candidate scan, narrowed to a single scope, so\n * \"queued work\" classifications agree with the item the panel rendered.\n */\nexport async function hasDeferredTailScopeWork(\n execSql: ExecSql,\n scope: { appKind: string; localId: string },\n): Promise<boolean> {\n const rows = await execSql(DEFERRED_TAIL_SCOPE_SQL, [\n scope.appKind,\n scope.localId,\n ]);\n const row = rows[0];\n if (!row) {\n return false;\n }\n const currentVersion = readString(row, \"snapshot_end_version\");\n if (!currentVersion) {\n return false;\n }\n return hasUncoveredTail({\n currentVersion,\n latestPendingEndVersion: readString(row, \"latest_pending_end_version\"),\n pendingBaseVersion: readString(row, \"pending_base_version\"),\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"deferredTails.js","sourceRoot":"","sources":["deferredTails.ts"],"names":[],"mappings":"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","sourcesContent":["import { mergeVersionVectors, satisfiesVersionVector } from \"@tearleads/loro\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport {\n getContainerDisplayNameSql,\n getContainerOrganizationAttributionSql,\n} from \"../documentQueries/sql\";\nimport type { PendingWriteCandidate } from \"./aggregation\";\nimport type { PendingWriteQueueObjectKind } from \"./pendingWritesTypes\";\nimport { readString } from \"./rowReaders\";\n\n// Deliberately never loads document content: the diagnostic listing runs\n// repeatedly while sync drains, and materializing every content blob would\n// make the scan O(total document content). `snapshot_end_version` is the\n// write-time-derived end version vector of the persisted content.\nconst DEFERRED_TAIL_CANDIDATE_SQL = `\n SELECT\n stored.app_kind AS app_kind,\n stored.local_id AS local_id,\n stored.document_id AS stored_remote_id,\n stored.snapshot_end_version AS snapshot_end_version,\n stored.pending_base_version AS pending_base_version,\n stored.updated_at AS updated_at,\n (\n SELECT pending.partial_end_version_vector\n FROM document_history_updates pending\n WHERE pending.app_kind = stored.app_kind\n AND pending.local_id = stored.local_id\n AND pending.update_id IS NOT NULL\n ORDER BY pending.created_at DESC, pending.rowid DESC\n LIMIT 1\n ) AS latest_pending_end_version,\n document_projection.title AS document_name,\n document_projection.container_id AS document_container_id,\n ${getContainerOrganizationAttributionSql({\n containerAlias: \"document_container\",\n projectionAlias: \"document_projection\",\n })} AS document_organization_id,\n CASE\n WHEN metadata_container.server_created_at IS NULL THEN NULL\n ELSE metadata_container.id\n END AS container_remote_id,\n ${getContainerDisplayNameSql(\"metadata_container\")} AS container_name,\n metadata_container.id AS metadata_container_id,\n NULLIF(metadata_container.organization_id, '') AS metadata_organization_id,\n stored.sync_failure_message AS failure_message,\n stored.sync_failure_attempted_at AS failure_attempted_at\n FROM documents stored\n LEFT JOIN document_projection\n ON stored.app_kind = 'documents'\n AND document_projection.local_id = stored.local_id\n LEFT JOIN containers document_container\n ON document_container.id = document_projection.container_id\n LEFT JOIN containers metadata_container\n ON stored.app_kind = 'container-metadata'\n AND metadata_container.id = stored.local_id\n WHERE stored.snapshot_end_version <> ''\n -- Dormant retained metadata (row 4, access_revoked) has no containers\n -- row; keep it out of deferred-tail candidates until re-attach, matching\n -- the pending-write sources guard.\n AND (stored.app_kind <> 'container-metadata'\n OR metadata_container.id IS NOT NULL)\n AND (\n stored.pending_base_version IS NOT NULL\n OR EXISTS (\n SELECT 1\n FROM document_history_updates pending\n WHERE pending.app_kind = stored.app_kind\n AND pending.local_id = stored.local_id\n AND pending.update_id IS NOT NULL\n )\n )\n`;\n\nfunction hasUncoveredTail(input: {\n currentVersion: string;\n latestPendingEndVersion: string | null;\n pendingBaseVersion: string | null;\n}): boolean {\n const coverageVersions = [\n input.latestPendingEndVersion,\n input.pendingBaseVersion,\n ].filter((value): value is string => value !== null);\n const validCoverageVersions: string[] = [];\n for (const coverageVersion of coverageVersions) {\n try {\n validCoverageVersions.push(mergeVersionVectors([coverageVersion]));\n } catch {\n // Corrupt coverage must not make the diagnostic claim an uncovered write.\n return false;\n }\n }\n if (validCoverageVersions.length === 0) {\n return false;\n }\n\n try {\n const mergedCoverage = mergeVersionVectors(validCoverageVersions);\n return !satisfiesVersionVector(mergedCoverage, input.currentVersion);\n } catch {\n // Corrupt coverage must not make the diagnostic claim an uncovered write.\n return false;\n }\n}\n\nfunction getObjectKind(appKind: string): PendingWriteQueueObjectKind {\n if (appKind === \"documents\") return \"document\";\n if (appKind === \"container-metadata\") return \"container\";\n return \"unknown\";\n}\n\nfunction mapDeferredTailCandidate(\n row: Record<string, unknown>,\n): PendingWriteCandidate | null {\n const appKind = readString(row, \"app_kind\");\n const localId = readString(row, \"local_id\");\n const currentVersion = readString(row, \"snapshot_end_version\");\n if (!appKind || !localId || !currentVersion) {\n return null;\n }\n if (\n !hasUncoveredTail({\n currentVersion,\n latestPendingEndVersion: readString(row, \"latest_pending_end_version\"),\n pendingBaseVersion: readString(row, \"pending_base_version\"),\n })\n ) {\n return null;\n }\n\n const objectKind = getObjectKind(appKind);\n const updatedAt = readString(row, \"updated_at\");\n return {\n byteLength: 0,\n containerId:\n objectKind === \"container\"\n ? readString(row, \"metadata_container_id\")\n : objectKind === \"document\"\n ? readString(row, \"document_container_id\")\n : null,\n count: 1,\n createdAt: updatedAt,\n inclusion: \"always\",\n kind: \"deferred-update\",\n // Carry the scope's recorded sync failure so a covering deferred-update\n // candidate never hides the diagnostic a suppressed failure-only item\n // would have shown.\n lastAttemptedAt: readString(row, \"failure_attempted_at\"),\n lastError: readString(row, \"failure_message\"),\n localId,\n name:\n objectKind === \"container\"\n ? readString(row, \"container_name\")\n : objectKind === \"document\"\n ? readString(row, \"document_name\")\n : null,\n namespace: objectKind === \"unknown\" ? appKind : null,\n objectKind,\n organizationId:\n objectKind === \"container\"\n ? readString(row, \"metadata_organization_id\")\n : objectKind === \"document\"\n ? readString(row, \"document_organization_id\")\n : null,\n remoteId:\n objectKind === \"container\"\n ? readString(row, \"container_remote_id\")\n : readString(row, \"stored_remote_id\"),\n status: \"pending\",\n targetContainerId: null,\n updatedAt,\n };\n}\n\nexport async function listDeferredPendingWriteCandidates(\n execSql: ExecSql,\n): Promise<PendingWriteCandidate[]> {\n const rows = await execSql(DEFERRED_TAIL_CANDIDATE_SQL);\n return rows.flatMap((row) => {\n const candidate = mapDeferredTailCandidate(row);\n return candidate ? [candidate] : [];\n });\n}\n\nconst DEFERRED_TAIL_SCOPE_SQL = `\n SELECT\n stored.snapshot_end_version AS snapshot_end_version,\n stored.pending_base_version AS pending_base_version,\n (\n SELECT pending.partial_end_version_vector\n FROM document_history_updates pending\n WHERE pending.app_kind = stored.app_kind\n AND pending.local_id = stored.local_id\n AND pending.update_id IS NOT NULL\n ORDER BY pending.created_at DESC, pending.rowid DESC\n LIMIT 1\n ) AS latest_pending_end_version\n FROM documents stored\n WHERE stored.app_kind = ? AND stored.local_id = ?\n AND stored.snapshot_end_version <> ''\n -- Dormant retained metadata (row 4, access_revoked) has no containers\n -- row; it is not queued work until re-attach, matching the candidate\n -- scan's guard.\n AND (stored.app_kind <> 'container-metadata'\n OR EXISTS (SELECT 1 FROM containers WHERE containers.id = stored.local_id))\n LIMIT 1\n`;\n\n/**\n * Whether this one scope has a deferred write: durable-tail content ahead of\n * its covered frontier, possibly with no queued update rows at all. The same\n * coverage check as the candidate scan, narrowed to a single scope, so\n * \"queued work\" classifications agree with the item the panel rendered.\n */\nexport async function hasDeferredTailScopeWork(\n execSql: ExecSql,\n scope: { appKind: string; localId: string },\n): Promise<boolean> {\n const rows = await execSql(DEFERRED_TAIL_SCOPE_SQL, [\n scope.appKind,\n scope.localId,\n ]);\n const row = rows[0];\n if (!row) {\n return false;\n }\n const currentVersion = readString(row, \"snapshot_end_version\");\n if (!currentVersion) {\n return false;\n }\n return hasUncoveredTail({\n currentVersion,\n latestPendingEndVersion: readString(row, \"latest_pending_end_version\"),\n pendingBaseVersion: readString(row, \"pending_base_version\"),\n });\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ExecSql } from "
|
|
1
|
+
import type { ExecSql } from "../../../data/sqlite/sqlSchema.js";
|
|
2
2
|
import type { PendingWriteQueueItem } from "./pendingWritesTypes.js";
|
|
3
3
|
export type { PendingWriteQueueItem, PendingWriteQueueItemStatus, PendingWriteQueueObjectKind, PendingWriteQueueOperation, PendingWriteQueueOperationKind, PendingWriteQueueOperationStatus, } from "./pendingWritesTypes.js";
|
|
4
4
|
/**
|