@tearleads/client-sdk 0.1.30 → 0.1.32
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/index.d.ts +1 -1
- package/index.js.map +1 -1
- package/internal/api-client/operationTransportFactory.js +1 -0
- package/internal/api-client/operationTransportFactory.js.map +1 -1
- package/internal/api-client/routes/blobs/get.d.ts +6 -1
- package/internal/api-client/routes/blobs/get.js +98 -2
- package/internal/api-client/routes/blobs/get.js.map +1 -1
- package/internal/validators/operation/blobDownloads.d.ts +163 -0
- package/internal/validators/operation/blobDownloads.js +43 -0
- package/internal/validators/operation/blobDownloads.js.map +1 -0
- package/internal/validators/operation/index.d.ts +1 -0
- package/internal/validators/operation/index.js +1 -0
- package/internal/validators/operation/index.js.map +1 -1
- package/internal/validators/operation/registry.d.ts +2 -0
- package/internal/validators/operation/registry.js +2 -0
- package/internal/validators/operation/registry.js.map +1 -1
- package/package.json +1 -1
- package/stores/container-contents/state.js +1 -0
- package/stores/container-contents/state.js.map +1 -1
- package/stores/container-contents/types.d.ts +2 -0
- package/stores/container-contents/types.js.map +1 -1
- package/stores/container-contents/utils.js +10 -0
- package/stores/container-contents/utils.js.map +1 -1
- package/stores/documents/documentStore/syncFinalize.js +7 -3
- package/stores/documents/documentStore/syncFinalize.js.map +1 -1
- package/workflows/container-contents/documentQueries/hydrationSql.js +16 -0
- package/workflows/container-contents/documentQueries/hydrationSql.js.map +1 -0
- package/workflows/container-contents/documentQueries/sql.js +16 -7
- package/workflows/container-contents/documentQueries/sql.js.map +1 -1
- package/workflows/container-contents/documentQueries.d.ts +6 -1
- package/workflows/container-contents/documentQueries.js +15 -8
- package/workflows/container-contents/documentQueries.js.map +1 -1
- package/workflows/container-contents/index.d.ts +1 -0
- package/workflows/container-contents/index.js.map +1 -1
- package/workflows/container-contents/pendingDownloads.d.ts +12 -0
- package/workflows/container-contents/pendingDownloads.js +45 -0
- package/workflows/container-contents/pendingDownloads.js.map +1 -0
|
@@ -2,6 +2,7 @@ import { bindBlobAttachmentOperation, detachBlobAttachmentOperation, listDocumen
|
|
|
2
2
|
import { challengeOperation, destroySessionOperation, listSessionsOperation, logoutOperation, registerOperation, userIdentityOperation, verifyOperation, webSocketTicketOperation } from "./auth.js";
|
|
3
3
|
import { receiveRevenueCatWebhookOperation, receiveStripeWebhookOperation } from "./billingWebhooks.js";
|
|
4
4
|
import { getBlobBytesOperation, uploadMultipartBlobPartBytesOperation } from "./blobBytes.js";
|
|
5
|
+
import { getBlobDownloadOperation } from "./blobDownloads.js";
|
|
5
6
|
import { createContainerOperation, createContainerWithMetadataDocumentOperation, deleteContainerOperation, moveContainerOperation, reciteContainerOperation, rekeyContainerOperation, revokeContainerOperation, shareContainerOperation } from "./containerMutations.js";
|
|
6
7
|
import { getContainerKekLogOperation, listContainerDocumentsOperation, listContainerParentLanesOperation } from "./containerReads.js";
|
|
7
8
|
import { getContainerReplacementAuthorizationsOperation } from "./containerReplacement.js";
|
|
@@ -31,6 +32,7 @@ export declare const protocolOperations: readonly [
|
|
|
31
32
|
typeof verifyOperation,
|
|
32
33
|
typeof webSocketTicketOperation,
|
|
33
34
|
typeof getBlobBytesOperation,
|
|
35
|
+
typeof getBlobDownloadOperation,
|
|
34
36
|
typeof receiveRevenueCatWebhookOperation,
|
|
35
37
|
typeof receiveStripeWebhookOperation,
|
|
36
38
|
typeof bindBlobAttachmentOperation,
|
|
@@ -2,6 +2,7 @@ import { bindBlobAttachmentOperation, detachBlobAttachmentOperation, listDocumen
|
|
|
2
2
|
import { challengeOperation, destroySessionOperation, listSessionsOperation, logoutOperation, registerOperation, userIdentityOperation, verifyOperation, webSocketTicketOperation, } from "./auth.js";
|
|
3
3
|
import { receiveRevenueCatWebhookOperation, receiveStripeWebhookOperation, } from "./billingWebhooks.js";
|
|
4
4
|
import { getBlobBytesOperation, uploadMultipartBlobPartBytesOperation, } from "./blobBytes.js";
|
|
5
|
+
import { getBlobDownloadOperation } from "./blobDownloads.js";
|
|
5
6
|
import { createContainerOperation, createContainerWithMetadataDocumentOperation, deleteContainerOperation, moveContainerOperation, reciteContainerOperation, rekeyContainerOperation, revokeContainerOperation, shareContainerOperation, } from "./containerMutations.js";
|
|
6
7
|
import { getContainerKekLogOperation, listContainerDocumentsOperation, listContainerParentLanesOperation, } from "./containerReads.js";
|
|
7
8
|
import { getContainerReplacementAuthorizationsOperation } from "./containerReplacement.js";
|
|
@@ -33,6 +34,7 @@ export const protocolOperations = [
|
|
|
33
34
|
verifyOperation,
|
|
34
35
|
webSocketTicketOperation,
|
|
35
36
|
getBlobBytesOperation,
|
|
37
|
+
getBlobDownloadOperation,
|
|
36
38
|
receiveRevenueCatWebhookOperation,
|
|
37
39
|
receiveStripeWebhookOperation,
|
|
38
40
|
bindBlobAttachmentOperation,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["registry.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n bindBlobAttachmentOperation,\n detachBlobAttachmentOperation,\n listDocumentAttachmentsOperation,\n} from \"./attachments\";\nimport {\n challengeOperation,\n destroySessionOperation,\n listSessionsOperation,\n logoutOperation,\n registerOperation,\n userIdentityOperation,\n verifyOperation,\n webSocketTicketOperation,\n} from \"./auth\";\nimport {\n receiveRevenueCatWebhookOperation,\n receiveStripeWebhookOperation,\n} from \"./billingWebhooks\";\nimport {\n getBlobBytesOperation,\n uploadMultipartBlobPartBytesOperation,\n} from \"./blobBytes\";\nimport {\n createContainerOperation,\n createContainerWithMetadataDocumentOperation,\n deleteContainerOperation,\n moveContainerOperation,\n reciteContainerOperation,\n rekeyContainerOperation,\n revokeContainerOperation,\n shareContainerOperation,\n} from \"./containerMutations\";\nimport {\n getContainerKekLogOperation,\n listContainerDocumentsOperation,\n listContainerParentLanesOperation,\n} from \"./containerReads\";\nimport { getContainerReplacementAuthorizationsOperation } from \"./containerReplacement\";\nimport {\n getDocumentAttributionOperation,\n listDocumentAttributionRangesOperation,\n} from \"./documentAttribution\";\nimport {\n createDocumentOperation,\n getDocumentPurgeProofOperation,\n linkDocumentOperation,\n purgeDocumentOperation,\n unlinkDocumentOperation,\n} from \"./documentMutations\";\nimport { documentSyncOperation } from \"./documentSync\";\nimport { getHealthOperation } from \"./health\";\nimport {\n completeMultipartBlobStageOperation,\n getMultipartBlobStageOperation,\n initiateMultipartBlobStageOperation,\n} from \"./multipartBlobs\";\nimport {\n claimNativeOrganizationSubscriptionOperation,\n getOrganizationBillingHistoryOperation,\n getOrganizationBillingManagementUrlOperation,\n getOrganizationBillingOperation,\n getOrganizationNativePurchaseEligibilityOperation,\n startOrganizationTrialOperation,\n} from \"./organizationBilling\";\nimport { getOrganizationPolicyHistoryOperation } from \"./organizationPolicyHistory\";\nimport {\n createOrganizationGroupOperation,\n createOrganizationOperation,\n deleteOrganizationGroupOperation,\n getOrganizationDataUsageOperation,\n getOrganizationReadModelOperation,\n listOrganizationGroupMembersOperation,\n updateOrganizationProfileOperation,\n updateOrganizationRosterEntryOperation,\n} from \"./organizations\";\nimport {\n commitOrganizationGroupPolicyOperation,\n getPrincipalPolicyOperation,\n putPrincipalPolicyOperation,\n} from \"./principals\";\nimport { getProjectionPolicyHistoryOperation } from \"./projectionPolicyHistory\";\nimport {\n getRootIdentityOperation,\n listRootIdentitiesOperation,\n listRootIdentityOrganizationsOperation,\n} from \"./root\";\nimport {\n getRootOrganizationDataUsageOperation,\n getRootOrganizationOperation,\n listRootDataUsageReportOperation,\n listRootOrganizationIdentitiesOperation,\n listRootOrganizationsOperation,\n} from \"./rootOrganizations\";\nimport {\n cancelStripeSubscriptionOperation,\n createStripeCheckoutOperation,\n createStripeCheckoutSessionOperation,\n createStripePortalOperation,\n getStripeCheckoutOptionsOperation,\n} from \"./stripeCheckout\";\nimport {\n getContainerWriterProjectionOperation,\n getDocumentWriterProjectionOperation,\n} from \"./writerProjections\";\n\n// Name each imported operation type instead of expanding every Zod schema in\n// the emitted declaration; the exact readonly tuple and runtime order stay intact.\nexport const protocolOperations: readonly [\n typeof getContainerReplacementAuthorizationsOperation,\n typeof getHealthOperation,\n typeof challengeOperation,\n typeof destroySessionOperation,\n typeof listSessionsOperation,\n typeof logoutOperation,\n typeof registerOperation,\n typeof userIdentityOperation,\n typeof verifyOperation,\n typeof webSocketTicketOperation,\n typeof getBlobBytesOperation,\n typeof receiveRevenueCatWebhookOperation,\n typeof receiveStripeWebhookOperation,\n typeof bindBlobAttachmentOperation,\n typeof detachBlobAttachmentOperation,\n typeof initiateMultipartBlobStageOperation,\n typeof getMultipartBlobStageOperation,\n typeof completeMultipartBlobStageOperation,\n typeof uploadMultipartBlobPartBytesOperation,\n typeof listDocumentAttachmentsOperation,\n typeof getDocumentAttributionOperation,\n typeof listDocumentAttributionRangesOperation,\n typeof createDocumentOperation,\n typeof getDocumentPurgeProofOperation,\n typeof linkDocumentOperation,\n typeof purgeDocumentOperation,\n typeof unlinkDocumentOperation,\n typeof getContainerKekLogOperation,\n typeof listContainerDocumentsOperation,\n typeof listContainerParentLanesOperation,\n typeof createContainerOperation,\n typeof createContainerWithMetadataDocumentOperation,\n typeof deleteContainerOperation,\n typeof moveContainerOperation,\n typeof reciteContainerOperation,\n typeof rekeyContainerOperation,\n typeof revokeContainerOperation,\n typeof shareContainerOperation,\n typeof getContainerWriterProjectionOperation,\n typeof getDocumentWriterProjectionOperation,\n typeof createOrganizationOperation,\n typeof getOrganizationBillingOperation,\n typeof getOrganizationBillingHistoryOperation,\n typeof getOrganizationBillingManagementUrlOperation,\n typeof getOrganizationNativePurchaseEligibilityOperation,\n typeof claimNativeOrganizationSubscriptionOperation,\n typeof startOrganizationTrialOperation,\n typeof getStripeCheckoutOptionsOperation,\n typeof createStripeCheckoutOperation,\n typeof createStripeCheckoutSessionOperation,\n typeof createStripePortalOperation,\n typeof cancelStripeSubscriptionOperation,\n typeof getOrganizationDataUsageOperation,\n typeof getOrganizationReadModelOperation,\n typeof getOrganizationPolicyHistoryOperation,\n typeof createOrganizationGroupOperation,\n typeof deleteOrganizationGroupOperation,\n typeof listOrganizationGroupMembersOperation,\n typeof updateOrganizationProfileOperation,\n typeof updateOrganizationRosterEntryOperation,\n typeof getPrincipalPolicyOperation,\n typeof getProjectionPolicyHistoryOperation,\n typeof commitOrganizationGroupPolicyOperation,\n typeof putPrincipalPolicyOperation,\n typeof listRootIdentitiesOperation,\n typeof listRootOrganizationsOperation,\n typeof getRootOrganizationDataUsageOperation,\n typeof listRootDataUsageReportOperation,\n typeof getRootOrganizationOperation,\n typeof listRootOrganizationIdentitiesOperation,\n typeof getRootIdentityOperation,\n typeof listRootIdentityOrganizationsOperation,\n typeof documentSyncOperation,\n] = [\n getContainerReplacementAuthorizationsOperation,\n getHealthOperation,\n challengeOperation,\n destroySessionOperation,\n listSessionsOperation,\n logoutOperation,\n registerOperation,\n userIdentityOperation,\n verifyOperation,\n webSocketTicketOperation,\n getBlobBytesOperation,\n receiveRevenueCatWebhookOperation,\n receiveStripeWebhookOperation,\n bindBlobAttachmentOperation,\n detachBlobAttachmentOperation,\n initiateMultipartBlobStageOperation,\n getMultipartBlobStageOperation,\n completeMultipartBlobStageOperation,\n uploadMultipartBlobPartBytesOperation,\n listDocumentAttachmentsOperation,\n getDocumentAttributionOperation,\n listDocumentAttributionRangesOperation,\n createDocumentOperation,\n getDocumentPurgeProofOperation,\n linkDocumentOperation,\n purgeDocumentOperation,\n unlinkDocumentOperation,\n getContainerKekLogOperation,\n listContainerDocumentsOperation,\n listContainerParentLanesOperation,\n createContainerOperation,\n createContainerWithMetadataDocumentOperation,\n deleteContainerOperation,\n moveContainerOperation,\n reciteContainerOperation,\n rekeyContainerOperation,\n revokeContainerOperation,\n shareContainerOperation,\n getContainerWriterProjectionOperation,\n getDocumentWriterProjectionOperation,\n createOrganizationOperation,\n getOrganizationBillingOperation,\n getOrganizationBillingHistoryOperation,\n getOrganizationBillingManagementUrlOperation,\n getOrganizationNativePurchaseEligibilityOperation,\n claimNativeOrganizationSubscriptionOperation,\n startOrganizationTrialOperation,\n getStripeCheckoutOptionsOperation,\n createStripeCheckoutOperation,\n createStripeCheckoutSessionOperation,\n createStripePortalOperation,\n cancelStripeSubscriptionOperation,\n getOrganizationDataUsageOperation,\n getOrganizationReadModelOperation,\n getOrganizationPolicyHistoryOperation,\n createOrganizationGroupOperation,\n deleteOrganizationGroupOperation,\n listOrganizationGroupMembersOperation,\n updateOrganizationProfileOperation,\n updateOrganizationRosterEntryOperation,\n getPrincipalPolicyOperation,\n getProjectionPolicyHistoryOperation,\n commitOrganizationGroupPolicyOperation,\n putPrincipalPolicyOperation,\n listRootIdentitiesOperation,\n listRootOrganizationsOperation,\n getRootOrganizationDataUsageOperation,\n listRootDataUsageReportOperation,\n getRootOrganizationOperation,\n listRootOrganizationIdentitiesOperation,\n getRootIdentityOperation,\n listRootIdentityOrganizationsOperation,\n documentSyncOperation,\n];\n"]}
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["registry.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n bindBlobAttachmentOperation,\n detachBlobAttachmentOperation,\n listDocumentAttachmentsOperation,\n} from \"./attachments\";\nimport {\n challengeOperation,\n destroySessionOperation,\n listSessionsOperation,\n logoutOperation,\n registerOperation,\n userIdentityOperation,\n verifyOperation,\n webSocketTicketOperation,\n} from \"./auth\";\nimport {\n receiveRevenueCatWebhookOperation,\n receiveStripeWebhookOperation,\n} from \"./billingWebhooks\";\nimport {\n getBlobBytesOperation,\n uploadMultipartBlobPartBytesOperation,\n} from \"./blobBytes\";\nimport { getBlobDownloadOperation } from \"./blobDownloads\";\nimport {\n createContainerOperation,\n createContainerWithMetadataDocumentOperation,\n deleteContainerOperation,\n moveContainerOperation,\n reciteContainerOperation,\n rekeyContainerOperation,\n revokeContainerOperation,\n shareContainerOperation,\n} from \"./containerMutations\";\nimport {\n getContainerKekLogOperation,\n listContainerDocumentsOperation,\n listContainerParentLanesOperation,\n} from \"./containerReads\";\nimport { getContainerReplacementAuthorizationsOperation } from \"./containerReplacement\";\nimport {\n getDocumentAttributionOperation,\n listDocumentAttributionRangesOperation,\n} from \"./documentAttribution\";\nimport {\n createDocumentOperation,\n getDocumentPurgeProofOperation,\n linkDocumentOperation,\n purgeDocumentOperation,\n unlinkDocumentOperation,\n} from \"./documentMutations\";\nimport { documentSyncOperation } from \"./documentSync\";\nimport { getHealthOperation } from \"./health\";\nimport {\n completeMultipartBlobStageOperation,\n getMultipartBlobStageOperation,\n initiateMultipartBlobStageOperation,\n} from \"./multipartBlobs\";\nimport {\n claimNativeOrganizationSubscriptionOperation,\n getOrganizationBillingHistoryOperation,\n getOrganizationBillingManagementUrlOperation,\n getOrganizationBillingOperation,\n getOrganizationNativePurchaseEligibilityOperation,\n startOrganizationTrialOperation,\n} from \"./organizationBilling\";\nimport { getOrganizationPolicyHistoryOperation } from \"./organizationPolicyHistory\";\nimport {\n createOrganizationGroupOperation,\n createOrganizationOperation,\n deleteOrganizationGroupOperation,\n getOrganizationDataUsageOperation,\n getOrganizationReadModelOperation,\n listOrganizationGroupMembersOperation,\n updateOrganizationProfileOperation,\n updateOrganizationRosterEntryOperation,\n} from \"./organizations\";\nimport {\n commitOrganizationGroupPolicyOperation,\n getPrincipalPolicyOperation,\n putPrincipalPolicyOperation,\n} from \"./principals\";\nimport { getProjectionPolicyHistoryOperation } from \"./projectionPolicyHistory\";\nimport {\n getRootIdentityOperation,\n listRootIdentitiesOperation,\n listRootIdentityOrganizationsOperation,\n} from \"./root\";\nimport {\n getRootOrganizationDataUsageOperation,\n getRootOrganizationOperation,\n listRootDataUsageReportOperation,\n listRootOrganizationIdentitiesOperation,\n listRootOrganizationsOperation,\n} from \"./rootOrganizations\";\nimport {\n cancelStripeSubscriptionOperation,\n createStripeCheckoutOperation,\n createStripeCheckoutSessionOperation,\n createStripePortalOperation,\n getStripeCheckoutOptionsOperation,\n} from \"./stripeCheckout\";\nimport {\n getContainerWriterProjectionOperation,\n getDocumentWriterProjectionOperation,\n} from \"./writerProjections\";\n\n// Name each imported operation type instead of expanding every Zod schema in\n// the emitted declaration; the exact readonly tuple and runtime order stay intact.\nexport const protocolOperations: readonly [\n typeof getContainerReplacementAuthorizationsOperation,\n typeof getHealthOperation,\n typeof challengeOperation,\n typeof destroySessionOperation,\n typeof listSessionsOperation,\n typeof logoutOperation,\n typeof registerOperation,\n typeof userIdentityOperation,\n typeof verifyOperation,\n typeof webSocketTicketOperation,\n typeof getBlobBytesOperation,\n typeof getBlobDownloadOperation,\n typeof receiveRevenueCatWebhookOperation,\n typeof receiveStripeWebhookOperation,\n typeof bindBlobAttachmentOperation,\n typeof detachBlobAttachmentOperation,\n typeof initiateMultipartBlobStageOperation,\n typeof getMultipartBlobStageOperation,\n typeof completeMultipartBlobStageOperation,\n typeof uploadMultipartBlobPartBytesOperation,\n typeof listDocumentAttachmentsOperation,\n typeof getDocumentAttributionOperation,\n typeof listDocumentAttributionRangesOperation,\n typeof createDocumentOperation,\n typeof getDocumentPurgeProofOperation,\n typeof linkDocumentOperation,\n typeof purgeDocumentOperation,\n typeof unlinkDocumentOperation,\n typeof getContainerKekLogOperation,\n typeof listContainerDocumentsOperation,\n typeof listContainerParentLanesOperation,\n typeof createContainerOperation,\n typeof createContainerWithMetadataDocumentOperation,\n typeof deleteContainerOperation,\n typeof moveContainerOperation,\n typeof reciteContainerOperation,\n typeof rekeyContainerOperation,\n typeof revokeContainerOperation,\n typeof shareContainerOperation,\n typeof getContainerWriterProjectionOperation,\n typeof getDocumentWriterProjectionOperation,\n typeof createOrganizationOperation,\n typeof getOrganizationBillingOperation,\n typeof getOrganizationBillingHistoryOperation,\n typeof getOrganizationBillingManagementUrlOperation,\n typeof getOrganizationNativePurchaseEligibilityOperation,\n typeof claimNativeOrganizationSubscriptionOperation,\n typeof startOrganizationTrialOperation,\n typeof getStripeCheckoutOptionsOperation,\n typeof createStripeCheckoutOperation,\n typeof createStripeCheckoutSessionOperation,\n typeof createStripePortalOperation,\n typeof cancelStripeSubscriptionOperation,\n typeof getOrganizationDataUsageOperation,\n typeof getOrganizationReadModelOperation,\n typeof getOrganizationPolicyHistoryOperation,\n typeof createOrganizationGroupOperation,\n typeof deleteOrganizationGroupOperation,\n typeof listOrganizationGroupMembersOperation,\n typeof updateOrganizationProfileOperation,\n typeof updateOrganizationRosterEntryOperation,\n typeof getPrincipalPolicyOperation,\n typeof getProjectionPolicyHistoryOperation,\n typeof commitOrganizationGroupPolicyOperation,\n typeof putPrincipalPolicyOperation,\n typeof listRootIdentitiesOperation,\n typeof listRootOrganizationsOperation,\n typeof getRootOrganizationDataUsageOperation,\n typeof listRootDataUsageReportOperation,\n typeof getRootOrganizationOperation,\n typeof listRootOrganizationIdentitiesOperation,\n typeof getRootIdentityOperation,\n typeof listRootIdentityOrganizationsOperation,\n typeof documentSyncOperation,\n] = [\n getContainerReplacementAuthorizationsOperation,\n getHealthOperation,\n challengeOperation,\n destroySessionOperation,\n listSessionsOperation,\n logoutOperation,\n registerOperation,\n userIdentityOperation,\n verifyOperation,\n webSocketTicketOperation,\n getBlobBytesOperation,\n getBlobDownloadOperation,\n receiveRevenueCatWebhookOperation,\n receiveStripeWebhookOperation,\n bindBlobAttachmentOperation,\n detachBlobAttachmentOperation,\n initiateMultipartBlobStageOperation,\n getMultipartBlobStageOperation,\n completeMultipartBlobStageOperation,\n uploadMultipartBlobPartBytesOperation,\n listDocumentAttachmentsOperation,\n getDocumentAttributionOperation,\n listDocumentAttributionRangesOperation,\n createDocumentOperation,\n getDocumentPurgeProofOperation,\n linkDocumentOperation,\n purgeDocumentOperation,\n unlinkDocumentOperation,\n getContainerKekLogOperation,\n listContainerDocumentsOperation,\n listContainerParentLanesOperation,\n createContainerOperation,\n createContainerWithMetadataDocumentOperation,\n deleteContainerOperation,\n moveContainerOperation,\n reciteContainerOperation,\n rekeyContainerOperation,\n revokeContainerOperation,\n shareContainerOperation,\n getContainerWriterProjectionOperation,\n getDocumentWriterProjectionOperation,\n createOrganizationOperation,\n getOrganizationBillingOperation,\n getOrganizationBillingHistoryOperation,\n getOrganizationBillingManagementUrlOperation,\n getOrganizationNativePurchaseEligibilityOperation,\n claimNativeOrganizationSubscriptionOperation,\n startOrganizationTrialOperation,\n getStripeCheckoutOptionsOperation,\n createStripeCheckoutOperation,\n createStripeCheckoutSessionOperation,\n createStripePortalOperation,\n cancelStripeSubscriptionOperation,\n getOrganizationDataUsageOperation,\n getOrganizationReadModelOperation,\n getOrganizationPolicyHistoryOperation,\n createOrganizationGroupOperation,\n deleteOrganizationGroupOperation,\n listOrganizationGroupMembersOperation,\n updateOrganizationProfileOperation,\n updateOrganizationRosterEntryOperation,\n getPrincipalPolicyOperation,\n getProjectionPolicyHistoryOperation,\n commitOrganizationGroupPolicyOperation,\n putPrincipalPolicyOperation,\n listRootIdentitiesOperation,\n listRootOrganizationsOperation,\n getRootOrganizationDataUsageOperation,\n listRootDataUsageReportOperation,\n getRootOrganizationOperation,\n listRootOrganizationIdentitiesOperation,\n getRootIdentityOperation,\n listRootIdentityOrganizationsOperation,\n documentSyncOperation,\n];\n"]}
|
package/package.json
CHANGED
|
@@ -23,6 +23,7 @@ function areSnapshotNodesEqual(left, right) {
|
|
|
23
23
|
leftNode.icon === rightNode.icon &&
|
|
24
24
|
leftNode.kind === rightNode.kind &&
|
|
25
25
|
leftNode.metadataDocumentId === rightNode.metadataDocumentId &&
|
|
26
|
+
leftNode.metadataReady === rightNode.metadataReady &&
|
|
26
27
|
leftNode.name === rightNode.name &&
|
|
27
28
|
leftNode.organizationId === rightNode.organizationId &&
|
|
28
29
|
leftNode.parentId === rightNode.parentId &&
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.js","sourceRoot":"","sources":["state.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContainerContentsPersistence } from \"../../workflows/container-contents/containerPersistence\";\nimport {\n createContainerContentsProjectionUserKeyResolver,\n didContainerContentsProjectionKeyRuntimeChange,\n} from \"../../workflows/container-contents/projectionKeys\";\nimport { didRegainSyncPrerequisites } from \"../../workflows/container-contents/syncLane\";\nimport { ContainerStateMap } from \"./containerStateMap\";\nimport type {\n ContainerContentsStoreRuntime,\n ContainerContentsStoreSyncAgent,\n} from \"./syncAgentTypes\";\nimport type {\n ContainerContentsSnapshot,\n ContainerContentsStoreState,\n ContainerNode,\n} from \"./types\";\nimport { getSnapshotNodes } from \"./utils\";\nimport { didContainerWriteRuntimeChange } from \"./writeGeneration\";\n\nfunction areSyncStatesEqual(\n left: ContainerNode[\"syncState\"],\n right: ContainerNode[\"syncState\"],\n): boolean {\n return (\n left.lastError === right.lastError &&\n left.pendingAttachmentBytes === right.pendingAttachmentBytes &&\n left.pendingAttachmentCount === right.pendingAttachmentCount &&\n left.pendingUpdateCount === right.pendingUpdateCount &&\n left.status === right.status\n );\n}\n\nfunction areSnapshotNodesEqual(\n left: ReadonlyArray<ContainerNode>,\n right: ReadonlyArray<ContainerNode>,\n): boolean {\n if (left.length !== right.length) {\n return false;\n }\n\n return left.every((leftNode, index) => {\n const rightNode = right[index];\n return (\n rightNode !== undefined &&\n leftNode.createdAt === rightNode.createdAt &&\n leftNode.effectiveAccessLevel === rightNode.effectiveAccessLevel &&\n leftNode.id === rightNode.id &&\n leftNode.icon === rightNode.icon &&\n leftNode.kind === rightNode.kind &&\n leftNode.metadataDocumentId === rightNode.metadataDocumentId &&\n leftNode.name === rightNode.name &&\n leftNode.organizationId === rightNode.organizationId &&\n leftNode.parentId === rightNode.parentId &&\n areSyncStatesEqual(leftNode.syncState, rightNode.syncState) &&\n leftNode.systemSlot === rightNode.systemSlot &&\n leftNode.updatedAt === rightNode.updatedAt\n );\n });\n}\n\nfunction didStructuralRuntimeChange(\n previousRuntime: ContainerContentsStoreRuntime,\n nextRuntime: ContainerContentsStoreRuntime,\n): boolean {\n // Structural sync also depends on connectivity and event delivery. Local\n // writes use only the identity and storage checks shared below.\n return (\n didContainerWriteRuntimeChange(previousRuntime, nextRuntime) ||\n previousRuntime.state.online !== nextRuntime.state.online ||\n previousRuntime.state.peerScope !== nextRuntime.state.peerScope ||\n previousRuntime.state.serverEventsConnectionGeneration !==\n nextRuntime.state.serverEventsConnectionGeneration ||\n previousRuntime.util.isRemoteSyncBlocked !==\n nextRuntime.util.isRemoteSyncBlocked\n );\n}\n\nexport function createContainerContentsStoreState(\n initialRuntime: ContainerContentsStoreRuntime,\n persistence: ContainerContentsPersistence,\n logLabel?: string | undefined,\n): ContainerContentsStoreState {\n return {\n containersById: new ContainerStateMap(),\n containerParentIdsNeedingHydration: new Set(),\n documentStoresNeedPriming: true,\n initializeGeneration: null,\n initializePromise: null,\n initialized: false,\n localContainerRefreshPromise: null,\n localContainerRefreshGeneration: null,\n localContainerRefreshStructuralGeneration: null,\n localContainersNeedRefresh: false,\n lifecycleGeneration: 0,\n lastEventCount: 0,\n listeners: new Set(),\n locallyAcceptedMetadataUpdateIds: new Set(),\n logLabel,\n metadataDocumentIdsNeedingSync: new Set(),\n metadataSyncSignalSeqById: new Map(),\n persistence,\n remoteHydrationPromise: null,\n remoteHydrationGeneration: null,\n remoteHydrationStructuralGeneration: null,\n remoteReconnectRefreshPending: false,\n resolveProjectionUserKey:\n createContainerContentsProjectionUserKeyResolver(initialRuntime),\n rootLaneHydrated: false,\n runtime: initialRuntime,\n snapshot: {\n nodes: [],\n ready: false,\n },\n syncLane: null,\n structuralGeneration: 0,\n writeGeneration: 0,\n writeChain: Promise.resolve<ContainerNode | null>(null),\n };\n}\n\nfunction emitContainerContentsStore(state: ContainerContentsStoreState) {\n for (const listener of state.listeners) {\n listener();\n }\n}\n\nfunction setContainerContentsSnapshot(\n state: ContainerContentsStoreState,\n next: ContainerContentsSnapshot,\n) {\n if (\n next.ready === state.snapshot.ready &&\n areSnapshotNodesEqual(next.nodes, state.snapshot.nodes)\n ) {\n return;\n }\n\n state.snapshot = next;\n emitContainerContentsStore(state);\n}\n\nexport function updateContainerContentsSnapshot(\n state: ContainerContentsStoreState,\n) {\n setContainerContentsSnapshot(state, {\n nodes: getSnapshotNodes(state.containersById),\n ready: true,\n });\n}\n\nfunction resetContainerContentsStore(state: ContainerContentsStoreState) {\n state.lifecycleGeneration += 1;\n state.containersById = new ContainerStateMap();\n state.containerParentIdsNeedingHydration = new Set();\n state.documentStoresNeedPriming = true;\n state.initialized = false;\n state.localContainersNeedRefresh = false;\n // Runtime events are snapshots, not a destructive queue. A replacement\n // executor or persistence adapter has not observed any of them, even when\n // their effects were already applied to the previous database. Replay the\n // snapshot after replacement initialization rebuilds metadata identities.\n state.lastEventCount = 0;\n // Accepted-echo suppression state must not survive a reset: after a\n // database loss the tree rehydrates from remote, and a retained id would\n // suppress the next matching remote update signal. Mirrors\n // clearDocumentStoreState in the document store lane.\n state.locallyAcceptedMetadataUpdateIds = new Set();\n state.metadataDocumentIdsNeedingSync = new Set();\n state.metadataSyncSignalSeqById = new Map();\n state.rootLaneHydrated = false;\n state.writeChain = Promise.resolve<ContainerNode | null>(null);\n setContainerContentsSnapshot(state, {\n nodes: [],\n ready: false,\n });\n}\n\nexport function subscribeToContainerContentsStore(\n state: ContainerContentsStoreState,\n listener: () => void,\n) {\n state.listeners.add(listener);\n return () => state.listeners.delete(listener);\n}\n\nexport function updateContainerContentsStoreRuntime(\n state: ContainerContentsStoreState,\n nextRuntime: ContainerContentsStoreRuntime,\n syncAgent: ContainerContentsStoreSyncAgent,\n) {\n const previousRuntime = state.runtime;\n const runtimeReplaced = didStructuralRuntimeChange(\n previousRuntime,\n nextRuntime,\n );\n if (didContainerWriteRuntimeChange(previousRuntime, nextRuntime)) {\n state.writeGeneration += 1;\n }\n const executorReplaced =\n previousRuntime.infra.execSql !== nextRuntime.infra.execSql;\n const serverEventsConnectionChanged =\n previousRuntime.state.serverEventsConnectionGeneration !==\n nextRuntime.state.serverEventsConnectionGeneration;\n if (runtimeReplaced) {\n state.structuralGeneration += 1;\n state.localContainersNeedRefresh = true;\n }\n const contextChanged =\n previousRuntime.auth.organizationId !== nextRuntime.auth.organizationId ||\n previousRuntime.state.containerId !== nextRuntime.state.containerId;\n if (\n didContainerContentsProjectionKeyRuntimeChange(previousRuntime, nextRuntime)\n ) {\n state.resolveProjectionUserKey =\n createContainerContentsProjectionUserKeyResolver(nextRuntime);\n }\n state.runtime = nextRuntime;\n if (serverEventsConnectionChanged) {\n state.remoteReconnectRefreshPending = true;\n }\n\n if (nextRuntime.infra.dbStatus !== \"ready\") {\n if (state.snapshot.ready || state.initialized || state.initializePromise) {\n resetContainerContentsStore(state);\n }\n return;\n }\n\n if (executorReplaced) {\n // The in-memory tree and lane markers belong to the previous executor.\n // Rebuild them from the replacement database before any remote sync can\n // observe or persist the old database's state.\n resetContainerContentsStore(state);\n syncAgent.ensureInitialized();\n syncAgent.handleRemoteEvents();\n return;\n }\n\n // Gaining authentication within a domain scope does not change identity\n // (the scope is keyed on the signing fingerprint), so the locally-loaded\n // tree stays valid. Reconcile it in place instead of resetting — resetting\n // here is what blanked Explorer and forced a re-read on first open after\n // register. Identity/storage changes are handled by scope rotation and the\n // dbStatus-loss branch above.\n if (\n state.snapshot.ready &&\n (contextChanged || didRegainSyncPrerequisites(previousRuntime, nextRuntime))\n ) {\n state.localContainersNeedRefresh = true;\n state.documentStoresNeedPriming = true;\n void syncAgent.refreshLocalContainers();\n // The refresh alone does not run the sync lane; schedule it so newly\n // eligible documents (e.g. this organization's orphans) prime now.\n syncAgent.scheduleSync();\n }\n\n syncAgent.ensureInitialized();\n\n syncAgent.handleRemoteEvents();\n\n if (runtimeReplaced) {\n void syncAgent.refreshLocalContainers();\n syncAgent.scheduleSync();\n }\n\n consumePendingContainerContentsReconnectRefresh(state, syncAgent.refresh);\n\n if (\n state.snapshot.ready &&\n didRegainSyncPrerequisites(previousRuntime, nextRuntime)\n ) {\n // A pass blocked by missing prerequisites consumes its lane request before\n // returning early. Re-arm it directly when they return even if hydration\n // finds no remote delta; this also primes unopened document stores.\n syncAgent.scheduleSync();\n syncAgent.scheduleRemoteHydration();\n }\n}\n\nexport function consumePendingContainerContentsReconnectRefresh(\n state: {\n remoteReconnectRefreshPending: boolean;\n snapshot: { ready: boolean };\n },\n refresh: () => Promise<boolean>,\n): void {\n if (!state.snapshot.ready || !state.remoteReconnectRefreshPending) return;\n state.remoteReconnectRefreshPending = false;\n void refresh().then(\n (refreshed) => {\n if (!refreshed) state.remoteReconnectRefreshPending = true;\n },\n () => {\n state.remoteReconnectRefreshPending = true;\n },\n );\n}\n\nexport function updateContainerContentsStorePersistence(\n state: ContainerContentsStoreState,\n nextPersistence: ContainerContentsPersistence,\n syncAgent: ContainerContentsStoreSyncAgent,\n): void {\n if (state.persistence === nextPersistence) {\n return;\n }\n state.persistence = nextPersistence;\n state.structuralGeneration += 1;\n state.writeGeneration += 1;\n // Persistence replacement changes the authoritative local data source even\n // when the SQLite executor itself is stable. Clear storage-backed state and\n // let initialization load the replacement before scheduling remote work.\n resetContainerContentsStore(state);\n syncAgent.ensureInitialized();\n}\n"]}
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["state.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContainerContentsPersistence } from \"../../workflows/container-contents/containerPersistence\";\nimport {\n createContainerContentsProjectionUserKeyResolver,\n didContainerContentsProjectionKeyRuntimeChange,\n} from \"../../workflows/container-contents/projectionKeys\";\nimport { didRegainSyncPrerequisites } from \"../../workflows/container-contents/syncLane\";\nimport { ContainerStateMap } from \"./containerStateMap\";\nimport type {\n ContainerContentsStoreRuntime,\n ContainerContentsStoreSyncAgent,\n} from \"./syncAgentTypes\";\nimport type {\n ContainerContentsSnapshot,\n ContainerContentsStoreState,\n ContainerNode,\n} from \"./types\";\nimport { getSnapshotNodes } from \"./utils\";\nimport { didContainerWriteRuntimeChange } from \"./writeGeneration\";\n\nfunction areSyncStatesEqual(\n left: ContainerNode[\"syncState\"],\n right: ContainerNode[\"syncState\"],\n): boolean {\n return (\n left.lastError === right.lastError &&\n left.pendingAttachmentBytes === right.pendingAttachmentBytes &&\n left.pendingAttachmentCount === right.pendingAttachmentCount &&\n left.pendingUpdateCount === right.pendingUpdateCount &&\n left.status === right.status\n );\n}\n\nfunction areSnapshotNodesEqual(\n left: ReadonlyArray<ContainerNode>,\n right: ReadonlyArray<ContainerNode>,\n): boolean {\n if (left.length !== right.length) {\n return false;\n }\n\n return left.every((leftNode, index) => {\n const rightNode = right[index];\n return (\n rightNode !== undefined &&\n leftNode.createdAt === rightNode.createdAt &&\n leftNode.effectiveAccessLevel === rightNode.effectiveAccessLevel &&\n leftNode.id === rightNode.id &&\n leftNode.icon === rightNode.icon &&\n leftNode.kind === rightNode.kind &&\n leftNode.metadataDocumentId === rightNode.metadataDocumentId &&\n leftNode.metadataReady === rightNode.metadataReady &&\n leftNode.name === rightNode.name &&\n leftNode.organizationId === rightNode.organizationId &&\n leftNode.parentId === rightNode.parentId &&\n areSyncStatesEqual(leftNode.syncState, rightNode.syncState) &&\n leftNode.systemSlot === rightNode.systemSlot &&\n leftNode.updatedAt === rightNode.updatedAt\n );\n });\n}\n\nfunction didStructuralRuntimeChange(\n previousRuntime: ContainerContentsStoreRuntime,\n nextRuntime: ContainerContentsStoreRuntime,\n): boolean {\n // Structural sync also depends on connectivity and event delivery. Local\n // writes use only the identity and storage checks shared below.\n return (\n didContainerWriteRuntimeChange(previousRuntime, nextRuntime) ||\n previousRuntime.state.online !== nextRuntime.state.online ||\n previousRuntime.state.peerScope !== nextRuntime.state.peerScope ||\n previousRuntime.state.serverEventsConnectionGeneration !==\n nextRuntime.state.serverEventsConnectionGeneration ||\n previousRuntime.util.isRemoteSyncBlocked !==\n nextRuntime.util.isRemoteSyncBlocked\n );\n}\n\nexport function createContainerContentsStoreState(\n initialRuntime: ContainerContentsStoreRuntime,\n persistence: ContainerContentsPersistence,\n logLabel?: string | undefined,\n): ContainerContentsStoreState {\n return {\n containersById: new ContainerStateMap(),\n containerParentIdsNeedingHydration: new Set(),\n documentStoresNeedPriming: true,\n initializeGeneration: null,\n initializePromise: null,\n initialized: false,\n localContainerRefreshPromise: null,\n localContainerRefreshGeneration: null,\n localContainerRefreshStructuralGeneration: null,\n localContainersNeedRefresh: false,\n lifecycleGeneration: 0,\n lastEventCount: 0,\n listeners: new Set(),\n locallyAcceptedMetadataUpdateIds: new Set(),\n logLabel,\n metadataDocumentIdsNeedingSync: new Set(),\n metadataSyncSignalSeqById: new Map(),\n persistence,\n remoteHydrationPromise: null,\n remoteHydrationGeneration: null,\n remoteHydrationStructuralGeneration: null,\n remoteReconnectRefreshPending: false,\n resolveProjectionUserKey:\n createContainerContentsProjectionUserKeyResolver(initialRuntime),\n rootLaneHydrated: false,\n runtime: initialRuntime,\n snapshot: {\n nodes: [],\n ready: false,\n },\n syncLane: null,\n structuralGeneration: 0,\n writeGeneration: 0,\n writeChain: Promise.resolve<ContainerNode | null>(null),\n };\n}\n\nfunction emitContainerContentsStore(state: ContainerContentsStoreState) {\n for (const listener of state.listeners) {\n listener();\n }\n}\n\nfunction setContainerContentsSnapshot(\n state: ContainerContentsStoreState,\n next: ContainerContentsSnapshot,\n) {\n if (\n next.ready === state.snapshot.ready &&\n areSnapshotNodesEqual(next.nodes, state.snapshot.nodes)\n ) {\n return;\n }\n\n state.snapshot = next;\n emitContainerContentsStore(state);\n}\n\nexport function updateContainerContentsSnapshot(\n state: ContainerContentsStoreState,\n) {\n setContainerContentsSnapshot(state, {\n nodes: getSnapshotNodes(state.containersById),\n ready: true,\n });\n}\n\nfunction resetContainerContentsStore(state: ContainerContentsStoreState) {\n state.lifecycleGeneration += 1;\n state.containersById = new ContainerStateMap();\n state.containerParentIdsNeedingHydration = new Set();\n state.documentStoresNeedPriming = true;\n state.initialized = false;\n state.localContainersNeedRefresh = false;\n // Runtime events are snapshots, not a destructive queue. A replacement\n // executor or persistence adapter has not observed any of them, even when\n // their effects were already applied to the previous database. Replay the\n // snapshot after replacement initialization rebuilds metadata identities.\n state.lastEventCount = 0;\n // Accepted-echo suppression state must not survive a reset: after a\n // database loss the tree rehydrates from remote, and a retained id would\n // suppress the next matching remote update signal. Mirrors\n // clearDocumentStoreState in the document store lane.\n state.locallyAcceptedMetadataUpdateIds = new Set();\n state.metadataDocumentIdsNeedingSync = new Set();\n state.metadataSyncSignalSeqById = new Map();\n state.rootLaneHydrated = false;\n state.writeChain = Promise.resolve<ContainerNode | null>(null);\n setContainerContentsSnapshot(state, {\n nodes: [],\n ready: false,\n });\n}\n\nexport function subscribeToContainerContentsStore(\n state: ContainerContentsStoreState,\n listener: () => void,\n) {\n state.listeners.add(listener);\n return () => state.listeners.delete(listener);\n}\n\nexport function updateContainerContentsStoreRuntime(\n state: ContainerContentsStoreState,\n nextRuntime: ContainerContentsStoreRuntime,\n syncAgent: ContainerContentsStoreSyncAgent,\n) {\n const previousRuntime = state.runtime;\n const runtimeReplaced = didStructuralRuntimeChange(\n previousRuntime,\n nextRuntime,\n );\n if (didContainerWriteRuntimeChange(previousRuntime, nextRuntime)) {\n state.writeGeneration += 1;\n }\n const executorReplaced =\n previousRuntime.infra.execSql !== nextRuntime.infra.execSql;\n const serverEventsConnectionChanged =\n previousRuntime.state.serverEventsConnectionGeneration !==\n nextRuntime.state.serverEventsConnectionGeneration;\n if (runtimeReplaced) {\n state.structuralGeneration += 1;\n state.localContainersNeedRefresh = true;\n }\n const contextChanged =\n previousRuntime.auth.organizationId !== nextRuntime.auth.organizationId ||\n previousRuntime.state.containerId !== nextRuntime.state.containerId;\n if (\n didContainerContentsProjectionKeyRuntimeChange(previousRuntime, nextRuntime)\n ) {\n state.resolveProjectionUserKey =\n createContainerContentsProjectionUserKeyResolver(nextRuntime);\n }\n state.runtime = nextRuntime;\n if (serverEventsConnectionChanged) {\n state.remoteReconnectRefreshPending = true;\n }\n\n if (nextRuntime.infra.dbStatus !== \"ready\") {\n if (state.snapshot.ready || state.initialized || state.initializePromise) {\n resetContainerContentsStore(state);\n }\n return;\n }\n\n if (executorReplaced) {\n // The in-memory tree and lane markers belong to the previous executor.\n // Rebuild them from the replacement database before any remote sync can\n // observe or persist the old database's state.\n resetContainerContentsStore(state);\n syncAgent.ensureInitialized();\n syncAgent.handleRemoteEvents();\n return;\n }\n\n // Gaining authentication within a domain scope does not change identity\n // (the scope is keyed on the signing fingerprint), so the locally-loaded\n // tree stays valid. Reconcile it in place instead of resetting — resetting\n // here is what blanked Explorer and forced a re-read on first open after\n // register. Identity/storage changes are handled by scope rotation and the\n // dbStatus-loss branch above.\n if (\n state.snapshot.ready &&\n (contextChanged || didRegainSyncPrerequisites(previousRuntime, nextRuntime))\n ) {\n state.localContainersNeedRefresh = true;\n state.documentStoresNeedPriming = true;\n void syncAgent.refreshLocalContainers();\n // The refresh alone does not run the sync lane; schedule it so newly\n // eligible documents (e.g. this organization's orphans) prime now.\n syncAgent.scheduleSync();\n }\n\n syncAgent.ensureInitialized();\n\n syncAgent.handleRemoteEvents();\n\n if (runtimeReplaced) {\n void syncAgent.refreshLocalContainers();\n syncAgent.scheduleSync();\n }\n\n consumePendingContainerContentsReconnectRefresh(state, syncAgent.refresh);\n\n if (\n state.snapshot.ready &&\n didRegainSyncPrerequisites(previousRuntime, nextRuntime)\n ) {\n // A pass blocked by missing prerequisites consumes its lane request before\n // returning early. Re-arm it directly when they return even if hydration\n // finds no remote delta; this also primes unopened document stores.\n syncAgent.scheduleSync();\n syncAgent.scheduleRemoteHydration();\n }\n}\n\nexport function consumePendingContainerContentsReconnectRefresh(\n state: {\n remoteReconnectRefreshPending: boolean;\n snapshot: { ready: boolean };\n },\n refresh: () => Promise<boolean>,\n): void {\n if (!state.snapshot.ready || !state.remoteReconnectRefreshPending) return;\n state.remoteReconnectRefreshPending = false;\n void refresh().then(\n (refreshed) => {\n if (!refreshed) state.remoteReconnectRefreshPending = true;\n },\n () => {\n state.remoteReconnectRefreshPending = true;\n },\n );\n}\n\nexport function updateContainerContentsStorePersistence(\n state: ContainerContentsStoreState,\n nextPersistence: ContainerContentsPersistence,\n syncAgent: ContainerContentsStoreSyncAgent,\n): void {\n if (state.persistence === nextPersistence) {\n return;\n }\n state.persistence = nextPersistence;\n state.structuralGeneration += 1;\n state.writeGeneration += 1;\n // Persistence replacement changes the authoritative local data source even\n // when the SQLite executor itself is stable. Clear storage-backed state and\n // let initialization load the replacement before scheduling remote work.\n resetContainerContentsStore(state);\n syncAgent.ensureInitialized();\n}\n"]}
|
|
@@ -17,6 +17,8 @@ export interface ContainerNode {
|
|
|
17
17
|
id: string;
|
|
18
18
|
icon?: string | null;
|
|
19
19
|
metadataDocumentId?: string | null;
|
|
20
|
+
/** False while a discovered remote folder has no local metadata content. */
|
|
21
|
+
metadataReady?: boolean;
|
|
20
22
|
organizationId: string;
|
|
21
23
|
name: string;
|
|
22
24
|
parentId: string | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n ContainerAccessLevel,\n ReferencedPrincipalHead,\n} from \"@tearleads/crypto\";\nimport type { ContainerSystemSlot } from \"@tearleads/validators/containerSystemSlot\";\nimport type { ContainerWriterProjectionResponse } from \"@tearleads/validators/response\";\nimport type { PurgeOptions } from \"../../workflows/container-contents/container-state/purgeProgress\";\nimport type { ContainerContentsPersistence } from \"../../workflows/container-contents/containerPersistence\";\nimport type { ContainerDocumentObjectSyncState } from \"../../workflows/container-contents/syncState\";\nimport type {\n ContainerContentsStoreRuntime,\n ContainerContentsStoreSyncState,\n RefreshRootLaneOptions,\n} from \"./syncAgentTypes\";\n\n// Reuse the canonical access-level union from the crypto layer (the same source\n// `ContainerShareAccessLevel` chains to) rather than re-spelling the literals,\n// so the two can't drift.\nexport type ContainerContentsShareAccessLevel = ContainerAccessLevel;\n\nexport interface ContainerContentsStoreOptions {\n logLabel?: string | undefined;\n persistence?: ContainerContentsPersistence | undefined;\n}\n\nexport interface ContainerNode {\n systemSlot?: ContainerSystemSlot | null;\n createdAt?: string | null;\n effectiveAccessLevel?: ContainerAccessLevel | undefined;\n id: string;\n icon?: string | null;\n metadataDocumentId?: string | null;\n organizationId: string;\n name: string;\n parentId: string | null;\n syncState: ContainerDocumentObjectSyncState;\n kind: \"container\";\n updatedAt?: string | null;\n}\n\n// The store surface exposed through context: the snapshot fields plus the\n// store's mutation/refresh methods, spelled as a Pick so the two can't drift.\nexport type ContainerContentsContextValue = ContainerContentsSnapshot &\n Pick<\n ContainerContentsStore,\n | \"createChild\"\n | \"deleteContainer\"\n | \"emptyTrash\"\n | \"ensureSystemContainer\"\n | \"moveContainer\"\n | \"purgeContainer\"\n | \"refresh\"\n | \"refreshRootLane\"\n | \"renameContainer\"\n | \"requestSync\"\n | \"setContainerIcon\"\n | \"shareWithGroup\"\n | \"shareWithUser\"\n >;\n\nexport interface ContainerContentsSnapshot {\n nodes: ReadonlyArray<ContainerNode>;\n ready: boolean;\n}\n\nexport type ContainerGroupRewrapPreparation =\n | {\n status: \"not-granted\";\n }\n | {\n isCurrent(\n expectedGroupHead: ReferencedPrincipalHead,\n expectedContainerId: string,\n expectedOrganizationId: string,\n ): Promise<boolean>;\n rewrap(): Promise<boolean>;\n status: \"prepared\";\n };\n\n/**\n * Shared per-scope container tree and mutation store.\n *\n * Ordinary metadata/topology writes (`createChild`, `moveContainer`,\n * `renameContainer`, and `setContainerIcon`) commit to local persistence and\n * update subscribers before their queued remote sync converges. Destructive\n * and access-control operations retain their explicit remote-authority gates.\n */\nexport interface ContainerContentsStore {\n createChild: (\n parentId: string,\n name: string,\n ) => Promise<ContainerNode | null>;\n deleteContainer: (containerId: string) => Promise<boolean>;\n ensureSystemContainer: (\n systemSlot: ContainerSystemSlot,\n name: string,\n options?: EnsureSystemContainerOptions | undefined,\n ) => Promise<ContainerNode | null>;\n moveContainer: (\n containerId: string,\n parentId: string,\n ) => Promise<ContainerNode | null>;\n purgeContainer: (\n containerId: string,\n options?: PurgeOptions,\n ) => Promise<boolean>;\n emptyTrash: (\n trashContainerId: string,\n options?: PurgeOptions,\n ) => Promise<boolean>;\n // `options.requireExistingGrant` gates the preparation check only. The\n // prepared `rewrap` is always grant-preserving: it re-wraps a signed grant\n // and never mints one, so it carries no chosen group name, and it throws\n // (rather than healing through a policy mutation) when the container\n // manifest grants the group but the verified policy has no matching grant.\n prepareGroupRewrap: (\n containerId: string,\n groupId: string,\n accessLevel: ContainerContentsShareAccessLevel,\n options?: { requireExistingGrant?: boolean } | undefined,\n ) => Promise<ContainerGroupRewrapPreparation | null>;\n refresh: () => Promise<boolean>;\n refreshRootLane: (options?: RefreshRootLaneOptions) => Promise<boolean>;\n // Re-read root-lane containers from local SQLite into the snapshot with NO\n // server round-trip. Surfaces a just-persisted container — e.g. the Trash bin\n // that registration/org-creation provisioned server-side and wrote to SQLite\n // via persistRegistrationBootstrap — instantly, instead of waiting for the\n // remote root-lane pull. Idempotent with a later remote pull: the merge is\n // keyed by container id, so the pull reconciles in place rather than duplicating.\n refreshLocalContainers: () => Promise<void>;\n requestSync: () => void;\n renameContainer: (\n containerId: string,\n name: string,\n ) => Promise<ContainerNode | null>;\n setContainerIcon: (\n containerId: string,\n icon: string | null,\n ) => Promise<ContainerNode | null>;\n shareWithGroup: (\n containerId: string,\n groupId: string,\n accessLevel: ContainerContentsShareAccessLevel,\n options: {\n /**\n * The display name the group was chosen by. Required: the share fails\n * closed if the verified group policy commits a different name. Signed\n * names are unique within an organization by construction (enforced at\n * group creation), so the target's own name identifies it.\n */\n expectedGroupName: string;\n },\n ) => Promise<boolean>;\n shareWithUser: (containerId: string, userId: string) => Promise<boolean>;\n getCachedContainerWriterProjection: (\n containerId: string,\n ) => ContainerWriterProjectionResponse | null;\n getSnapshot: () => ContainerContentsSnapshot;\n subscribe: (listener: () => void) => () => void;\n updateRuntime: (runtime: ContainerContentsStoreRuntime) => void;\n}\n\nexport interface EnsureSystemContainerOptions {\n icon?: string | null | undefined;\n skipAdvancedManagedRoot?: boolean | undefined;\n // For local-first bootstrap paths where slow remote I/O must not block the\n // caller from creating the deterministic local system container.\n deferRemoteBootstrap?: boolean | undefined;\n // Create the deterministic local system container without queuing the remote\n // create. A later ensureSystemContainer call without this flag promotes the\n // local slot into the sync queue.\n deferRemoteSync?: boolean | undefined;\n}\n\nexport interface ContainerContentsStoreState\n extends ContainerContentsStoreSyncState {\n listeners: Set<() => void>;\n snapshot: ContainerContentsSnapshot;\n writeChain: Promise<ContainerNode | null>;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n ContainerAccessLevel,\n ReferencedPrincipalHead,\n} from \"@tearleads/crypto\";\nimport type { ContainerSystemSlot } from \"@tearleads/validators/containerSystemSlot\";\nimport type { ContainerWriterProjectionResponse } from \"@tearleads/validators/response\";\nimport type { PurgeOptions } from \"../../workflows/container-contents/container-state/purgeProgress\";\nimport type { ContainerContentsPersistence } from \"../../workflows/container-contents/containerPersistence\";\nimport type { ContainerDocumentObjectSyncState } from \"../../workflows/container-contents/syncState\";\nimport type {\n ContainerContentsStoreRuntime,\n ContainerContentsStoreSyncState,\n RefreshRootLaneOptions,\n} from \"./syncAgentTypes\";\n\n// Reuse the canonical access-level union from the crypto layer (the same source\n// `ContainerShareAccessLevel` chains to) rather than re-spelling the literals,\n// so the two can't drift.\nexport type ContainerContentsShareAccessLevel = ContainerAccessLevel;\n\nexport interface ContainerContentsStoreOptions {\n logLabel?: string | undefined;\n persistence?: ContainerContentsPersistence | undefined;\n}\n\nexport interface ContainerNode {\n systemSlot?: ContainerSystemSlot | null;\n createdAt?: string | null;\n effectiveAccessLevel?: ContainerAccessLevel | undefined;\n id: string;\n icon?: string | null;\n metadataDocumentId?: string | null;\n /** False while a discovered remote folder has no local metadata content. */\n metadataReady?: boolean;\n organizationId: string;\n name: string;\n parentId: string | null;\n syncState: ContainerDocumentObjectSyncState;\n kind: \"container\";\n updatedAt?: string | null;\n}\n\n// The store surface exposed through context: the snapshot fields plus the\n// store's mutation/refresh methods, spelled as a Pick so the two can't drift.\nexport type ContainerContentsContextValue = ContainerContentsSnapshot &\n Pick<\n ContainerContentsStore,\n | \"createChild\"\n | \"deleteContainer\"\n | \"emptyTrash\"\n | \"ensureSystemContainer\"\n | \"moveContainer\"\n | \"purgeContainer\"\n | \"refresh\"\n | \"refreshRootLane\"\n | \"renameContainer\"\n | \"requestSync\"\n | \"setContainerIcon\"\n | \"shareWithGroup\"\n | \"shareWithUser\"\n >;\n\nexport interface ContainerContentsSnapshot {\n nodes: ReadonlyArray<ContainerNode>;\n ready: boolean;\n}\n\nexport type ContainerGroupRewrapPreparation =\n | {\n status: \"not-granted\";\n }\n | {\n isCurrent(\n expectedGroupHead: ReferencedPrincipalHead,\n expectedContainerId: string,\n expectedOrganizationId: string,\n ): Promise<boolean>;\n rewrap(): Promise<boolean>;\n status: \"prepared\";\n };\n\n/**\n * Shared per-scope container tree and mutation store.\n *\n * Ordinary metadata/topology writes (`createChild`, `moveContainer`,\n * `renameContainer`, and `setContainerIcon`) commit to local persistence and\n * update subscribers before their queued remote sync converges. Destructive\n * and access-control operations retain their explicit remote-authority gates.\n */\nexport interface ContainerContentsStore {\n createChild: (\n parentId: string,\n name: string,\n ) => Promise<ContainerNode | null>;\n deleteContainer: (containerId: string) => Promise<boolean>;\n ensureSystemContainer: (\n systemSlot: ContainerSystemSlot,\n name: string,\n options?: EnsureSystemContainerOptions | undefined,\n ) => Promise<ContainerNode | null>;\n moveContainer: (\n containerId: string,\n parentId: string,\n ) => Promise<ContainerNode | null>;\n purgeContainer: (\n containerId: string,\n options?: PurgeOptions,\n ) => Promise<boolean>;\n emptyTrash: (\n trashContainerId: string,\n options?: PurgeOptions,\n ) => Promise<boolean>;\n // `options.requireExistingGrant` gates the preparation check only. The\n // prepared `rewrap` is always grant-preserving: it re-wraps a signed grant\n // and never mints one, so it carries no chosen group name, and it throws\n // (rather than healing through a policy mutation) when the container\n // manifest grants the group but the verified policy has no matching grant.\n prepareGroupRewrap: (\n containerId: string,\n groupId: string,\n accessLevel: ContainerContentsShareAccessLevel,\n options?: { requireExistingGrant?: boolean } | undefined,\n ) => Promise<ContainerGroupRewrapPreparation | null>;\n refresh: () => Promise<boolean>;\n refreshRootLane: (options?: RefreshRootLaneOptions) => Promise<boolean>;\n // Re-read root-lane containers from local SQLite into the snapshot with NO\n // server round-trip. Surfaces a just-persisted container — e.g. the Trash bin\n // that registration/org-creation provisioned server-side and wrote to SQLite\n // via persistRegistrationBootstrap — instantly, instead of waiting for the\n // remote root-lane pull. Idempotent with a later remote pull: the merge is\n // keyed by container id, so the pull reconciles in place rather than duplicating.\n refreshLocalContainers: () => Promise<void>;\n requestSync: () => void;\n renameContainer: (\n containerId: string,\n name: string,\n ) => Promise<ContainerNode | null>;\n setContainerIcon: (\n containerId: string,\n icon: string | null,\n ) => Promise<ContainerNode | null>;\n shareWithGroup: (\n containerId: string,\n groupId: string,\n accessLevel: ContainerContentsShareAccessLevel,\n options: {\n /**\n * The display name the group was chosen by. Required: the share fails\n * closed if the verified group policy commits a different name. Signed\n * names are unique within an organization by construction (enforced at\n * group creation), so the target's own name identifies it.\n */\n expectedGroupName: string;\n },\n ) => Promise<boolean>;\n shareWithUser: (containerId: string, userId: string) => Promise<boolean>;\n getCachedContainerWriterProjection: (\n containerId: string,\n ) => ContainerWriterProjectionResponse | null;\n getSnapshot: () => ContainerContentsSnapshot;\n subscribe: (listener: () => void) => () => void;\n updateRuntime: (runtime: ContainerContentsStoreRuntime) => void;\n}\n\nexport interface EnsureSystemContainerOptions {\n icon?: string | null | undefined;\n skipAdvancedManagedRoot?: boolean | undefined;\n // For local-first bootstrap paths where slow remote I/O must not block the\n // caller from creating the deterministic local system container.\n deferRemoteBootstrap?: boolean | undefined;\n // Create the deterministic local system container without queuing the remote\n // create. A later ensureSystemContainer call without this flag promotes the\n // local slot into the sync queue.\n deferRemoteSync?: boolean | undefined;\n}\n\nexport interface ContainerContentsStoreState\n extends ContainerContentsStoreSyncState {\n listeners: Set<() => void>;\n snapshot: ContainerContentsSnapshot;\n writeChain: Promise<ContainerNode | null>;\n}\n"]}
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import { normalizeEffectiveAccessLevel } from "../../data/accessLevel.js";
|
|
2
2
|
import { createContainerDocumentObjectSyncState } from "../../workflows/container-contents/syncState.js";
|
|
3
|
+
function hasContainerMetadata(containerState) {
|
|
4
|
+
const version = containerState.doc.oplogVersion();
|
|
5
|
+
try {
|
|
6
|
+
return version.length() > 0;
|
|
7
|
+
}
|
|
8
|
+
finally {
|
|
9
|
+
version.free();
|
|
10
|
+
}
|
|
11
|
+
}
|
|
3
12
|
function hasPendingContainerTimestamp(container) {
|
|
4
13
|
const localUpdatedAt = container.localUpdatedAt ?? null;
|
|
5
14
|
const serverUpdatedAt = container.serverUpdatedAt ?? null;
|
|
@@ -15,6 +24,7 @@ export function toContainerNode(containerState) {
|
|
|
15
24
|
id: container.id,
|
|
16
25
|
kind: "container",
|
|
17
26
|
metadataDocumentId: container.metadataDocumentId ?? record.documentId,
|
|
27
|
+
metadataReady: !record.documentId || hasContainerMetadata(containerState),
|
|
18
28
|
name: container.name,
|
|
19
29
|
organizationId: container.organizationId,
|
|
20
30
|
parentId: container.parentId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { normalizeEffectiveAccessLevel } from \"../../data/accessLevel\";\nimport type { ContainerRecord } from \"../../workflows/container-contents/containerPersistence\";\nimport type { ContainerState } from \"../../workflows/container-contents/remoteHydration\";\nimport { createContainerDocumentObjectSyncState } from \"../../workflows/container-contents/syncState\";\nimport type { ContainerNode } from \"./types\";\n\nfunction hasPendingContainerTimestamp(container: ContainerRecord): boolean {\n const localUpdatedAt = container.localUpdatedAt ?? null;\n const serverUpdatedAt = container.serverUpdatedAt ?? null;\n\n return (\n localUpdatedAt !== null &&\n (serverUpdatedAt === null ||\n localUpdatedAt.localeCompare(serverUpdatedAt) > 0)\n );\n}\n\nexport function toContainerNode(containerState: ContainerState): ContainerNode {\n const { container, record } = containerState;\n const systemSlot = container.systemSlot ?? null;\n const node: ContainerNode = {\n effectiveAccessLevel: normalizeEffectiveAccessLevel(\n container.effectiveAccessLevel,\n ),\n id: container.id,\n kind: \"container\",\n metadataDocumentId: container.metadataDocumentId ?? record.documentId,\n name: container.name,\n organizationId: container.organizationId,\n parentId: container.parentId,\n syncState: createContainerDocumentObjectSyncState({\n localOnly:\n !container.serverCreatedAt ||\n !container.metadataDocumentId ||\n !record.documentId,\n pendingUpdateCount: hasPendingContainerTimestamp(container) ? 1 : 0,\n }),\n };\n\n if (systemSlot) {\n node.systemSlot = systemSlot;\n }\n\n if (container.icon) {\n node.icon = container.icon;\n }\n\n if (container.createdAt) {\n node.createdAt = container.createdAt;\n }\n if (container.updatedAt) {\n node.updatedAt = container.updatedAt;\n }\n\n return node;\n}\n\nexport function isContainerInSubtree(\n containersById: ReadonlyMap<string, ContainerState>,\n containerId: string,\n rootContainerId: string,\n): boolean {\n let currentContainerId: string | null = containerId;\n const visitedContainerIds = new Set<string>();\n\n while (currentContainerId !== null) {\n if (currentContainerId === rootContainerId) {\n return true;\n }\n\n if (visitedContainerIds.has(currentContainerId)) {\n return false;\n }\n visitedContainerIds.add(currentContainerId);\n\n const currentContainerState = containersById.get(currentContainerId);\n currentContainerId = currentContainerState?.container.parentId ?? null;\n }\n\n return false;\n}\n\nexport function getSnapshotNodes(\n containersById: ReadonlyMap<string, ContainerState>,\n): ReadonlyArray<ContainerNode> {\n return Array.from(containersById.values(), (containerState) =>\n toContainerNode(containerState),\n ).sort((left, right) =>\n left.name.localeCompare(right.name, undefined, {\n sensitivity: \"base\",\n }),\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { normalizeEffectiveAccessLevel } from \"../../data/accessLevel\";\nimport type { ContainerRecord } from \"../../workflows/container-contents/containerPersistence\";\nimport type { ContainerState } from \"../../workflows/container-contents/remoteHydration\";\nimport { createContainerDocumentObjectSyncState } from \"../../workflows/container-contents/syncState\";\nimport type { ContainerNode } from \"./types\";\n\nfunction hasContainerMetadata(containerState: ContainerState): boolean {\n const version = containerState.doc.oplogVersion();\n try {\n return version.length() > 0;\n } finally {\n version.free();\n }\n}\n\nfunction hasPendingContainerTimestamp(container: ContainerRecord): boolean {\n const localUpdatedAt = container.localUpdatedAt ?? null;\n const serverUpdatedAt = container.serverUpdatedAt ?? null;\n\n return (\n localUpdatedAt !== null &&\n (serverUpdatedAt === null ||\n localUpdatedAt.localeCompare(serverUpdatedAt) > 0)\n );\n}\n\nexport function toContainerNode(containerState: ContainerState): ContainerNode {\n const { container, record } = containerState;\n const systemSlot = container.systemSlot ?? null;\n const node: ContainerNode = {\n effectiveAccessLevel: normalizeEffectiveAccessLevel(\n container.effectiveAccessLevel,\n ),\n id: container.id,\n kind: \"container\",\n metadataDocumentId: container.metadataDocumentId ?? record.documentId,\n metadataReady: !record.documentId || hasContainerMetadata(containerState),\n name: container.name,\n organizationId: container.organizationId,\n parentId: container.parentId,\n syncState: createContainerDocumentObjectSyncState({\n localOnly:\n !container.serverCreatedAt ||\n !container.metadataDocumentId ||\n !record.documentId,\n pendingUpdateCount: hasPendingContainerTimestamp(container) ? 1 : 0,\n }),\n };\n\n if (systemSlot) {\n node.systemSlot = systemSlot;\n }\n\n if (container.icon) {\n node.icon = container.icon;\n }\n\n if (container.createdAt) {\n node.createdAt = container.createdAt;\n }\n if (container.updatedAt) {\n node.updatedAt = container.updatedAt;\n }\n\n return node;\n}\n\nexport function isContainerInSubtree(\n containersById: ReadonlyMap<string, ContainerState>,\n containerId: string,\n rootContainerId: string,\n): boolean {\n let currentContainerId: string | null = containerId;\n const visitedContainerIds = new Set<string>();\n\n while (currentContainerId !== null) {\n if (currentContainerId === rootContainerId) {\n return true;\n }\n\n if (visitedContainerIds.has(currentContainerId)) {\n return false;\n }\n visitedContainerIds.add(currentContainerId);\n\n const currentContainerState = containersById.get(currentContainerId);\n currentContainerId = currentContainerState?.container.parentId ?? null;\n }\n\n return false;\n}\n\nexport function getSnapshotNodes(\n containersById: ReadonlyMap<string, ContainerState>,\n): ReadonlyArray<ContainerNode> {\n return Array.from(containersById.values(), (containerState) =>\n toContainerNode(containerState),\n ).sort((left, right) =>\n left.name.localeCompare(right.name, undefined, {\n sensitivity: \"base\",\n }),\n );\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { bytesToBase64 } from "../../../internal/encoding/index.js";
|
|
2
|
-
import { encodeVersionVector, getImportBlobMetadata, mergeVersionVectors, } from "../../../internal/loro/index.js";
|
|
2
|
+
import { emptyVersionVector, encodeVersionVector, getImportBlobMetadata, mergeVersionVectors, } from "../../../internal/loro/index.js";
|
|
3
3
|
import { readPullContinuation } from "../../../data/documents/shared/syncPagination.js";
|
|
4
4
|
import { settleOutgoingPassAndDecideReArm, shouldClearDocumentSyncFailureAfterPass, } from "../../../workflows/documents/index.js";
|
|
5
5
|
import { requestDocumentStoreSync } from "../registry.js";
|
|
@@ -51,10 +51,14 @@ function pulledHistoryUpdates(synced) {
|
|
|
51
51
|
* edit whose durable row has not landed yet.
|
|
52
52
|
*/
|
|
53
53
|
function coveredSyncFrontier(state, currentRecord, synced) {
|
|
54
|
+
const liveFrontier = (state.record ?? currentRecord).snapshotEndVersion;
|
|
54
55
|
if (synced.decryptedUpdates.length === 0) {
|
|
55
|
-
|
|
56
|
+
// A completed empty pull distinguishes a real blank note from discovery.
|
|
57
|
+
// An intermediate page cannot establish that no content exists yet.
|
|
58
|
+
return liveFrontier === "" && !synced.hasIncompletePull
|
|
59
|
+
? { snapshotEndVersion: emptyVersionVector() }
|
|
60
|
+
: {};
|
|
56
61
|
}
|
|
57
|
-
const liveFrontier = (state.record ?? currentRecord).snapshotEndVersion;
|
|
58
62
|
return {
|
|
59
63
|
snapshotEndVersion: mergeVersionVectors([
|
|
60
64
|
...(liveFrontier.length > 0 ? [liveFrontier] : []),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"syncFinalize.js","sourceRoot":"","sources":["syncFinalize.ts"],"names":[],"mappings":"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","sourcesContent":["import { bytesToBase64 } from \"@tearleads/encoding\";\nimport {\n encodeVersionVector,\n getImportBlobMetadata,\n mergeVersionVectors,\n} from \"@tearleads/loro\";\nimport { readPullContinuation } from \"../../../data/documents/shared/syncPagination\";\nimport {\n type DocumentRecord,\n settleOutgoingPassAndDecideReArm,\n shouldClearDocumentSyncFailureAfterPass,\n} from \"../../../workflows/documents\";\nimport { requestDocumentStoreSync } from \"../registry\";\nimport { hydrateAttachmentBlobs } from \"./attachmentHydration\";\nimport { chainIdentityWrite } from \"./identityWriteChain\";\nimport { publishPersistedDocument, saveDocumentRecord } from \"./persistence\";\nimport { logRevalidationApplied as logApplied } from \"./remoteRevalidationTelemetry\";\nimport type {\n DocumentState,\n DocumentStoreState,\n DocumentSyncAttempt,\n SaveDocumentRecordOptions,\n} from \"./state\";\nimport {\n discardPreRegisteredUpdateIds,\n discardUnacceptedPreRegisteredUpdateIds,\n} from \"./syncAcceptedUpdateIds\";\nimport {\n type DocumentStoreSyncGeneration,\n isDocumentStoreSyncGenerationCurrent,\n} from \"./syncGeneration\";\nimport { clearConsumedRemoteUpdateSignal } from \"./syncRemoteSignals\";\nimport {\n applyIncomingSyncedUpdates,\n documentSyncContextMatches,\n importSyncedDocumentUpdates,\n} from \"./syncUpdateImport\";\nimport { extendDocumentVersionCoverage } from \"./versionCoverage\";\nimport { installDocumentWriterProjection } from \"./writerProjectionGeneration\";\n\nfunction documentWriterProjectionMatchesSyncResponse(\n writerProjection: NonNullable<\n DocumentSyncAttempt[\"synced\"][\"writerProjection\"]\n >,\n synced: DocumentSyncAttempt[\"synced\"],\n): boolean {\n return (\n writerProjection.contentKeyBundle.contentKeyEpoch ===\n synced.response.contentKeyBundle.contentKeyEpoch &&\n writerProjection.contentKeyBundle.linkSetManifestHash ===\n synced.response.contentKeyBundle.linkSetManifestHash &&\n writerProjection.contentKeyBundle.targetHash ===\n synced.response.contentKeyBundle.targetHash &&\n writerProjection.documentKekTargets.linkSetManifestHash ===\n synced.response.documentKekTargets.linkSetManifestHash &&\n writerProjection.documentKekTargets.documentKeyTargetHash ===\n synced.response.documentKekTargets.documentKeyTargetHash\n );\n}\n\nfunction resolveSyncedDocumentWriterProjection(\n state: DocumentStoreState,\n synced: DocumentSyncAttempt[\"synced\"],\n) {\n const writerProjection =\n synced.writerProjection ??\n (state.writerProjection?.documentId === synced.plan.documentId\n ? state.writerProjection\n : null);\n return writerProjection &&\n documentWriterProjectionMatchesSyncResponse(writerProjection, synced)\n ? writerProjection\n : null;\n}\n\n/**\n * Durable-history tail: append pulled updates BEFORE the record persist so\n * the tail stays a superset of what the snapshot covers (duplicates are\n * idempotent by op identity; a crash between the writes can only leave the\n * safe superset).\n */\nfunction pulledHistoryUpdates(synced: DocumentSyncAttempt[\"synced\"]): string[] {\n return synced.decryptedUpdates.map((update) =>\n bytesToBase64(update.updateData),\n );\n}\n\n/**\n * The frontier a finalize persist may publish: the stored frontier advanced\n * by exactly the pulled updates just appended to the durable tail — never the\n * live document's version, which can transiently include an in-flight local\n * edit whose durable row has not landed yet.\n */\nfunction coveredSyncFrontier(\n state: DocumentStoreState,\n currentRecord: DocumentRecord,\n synced: DocumentSyncAttempt[\"synced\"],\n): { snapshotEndVersion: string } | Record<string, never> {\n if (synced.decryptedUpdates.length === 0) {\n return {};\n }\n const liveFrontier = (state.record ?? currentRecord).snapshotEndVersion;\n return {\n snapshotEndVersion: mergeVersionVectors([\n ...(liveFrontier.length > 0 ? [liveFrontier] : []),\n ...synced.decryptedUpdates.map(\n (update) =>\n getImportBlobMetadata(update.updateData).partialEndVersionVector,\n ),\n ]),\n };\n}\n\nfunction documentSyncSaveOptions(\n syncAttempt: DocumentSyncAttempt,\n): SaveDocumentRecordOptions {\n return {\n acceptedPendingUpdateIds: syncAttempt.synced.settledPendingUpdateIds,\n clearSyncFailure: shouldClearDocumentSyncFailureAfterPass(\n syncAttempt.synced,\n syncAttempt.outgoingUpdateCount,\n ),\n expectedSyncState: {\n pullContinuation: syncAttempt.consumedPullContinuation,\n record: syncAttempt.requestRecord,\n },\n historyUpdateOrigin: \"remote\",\n historyUpdates: pulledHistoryUpdates(syncAttempt.synced),\n preserveSnapshotStructuredFields: true,\n preserveSnapshotText: true,\n };\n}\n\nasync function persistSyncedDocument(\n state: DocumentStoreState,\n currentDoc: DocumentState,\n currentRecord: DocumentRecord,\n syncAttempt: DocumentSyncAttempt,\n generation: DocumentStoreSyncGeneration,\n) {\n const { synced } = syncAttempt;\n const updates = synced.decryptedUpdates;\n const candidate = currentDoc.fork();\n const previousDocumentId = state.record?.documentId ?? null;\n const options = documentSyncSaveOptions(syncAttempt);\n const isCurrent = () =>\n isDocumentStoreSyncGenerationCurrent(state, generation);\n try {\n importSyncedDocumentUpdates(candidate, updates);\n if (state.pendingBaseVersion === null) {\n throw new Error(\"Document sync requires an initialized pending base\");\n }\n const persisted = await saveDocumentRecord(\n state,\n candidate,\n {\n ...synced.persistedState,\n lastCommitLsn:\n synced.response.commitLsn ?? currentRecord.lastCommitLsn ?? null,\n pullContinuation: readPullContinuation(synced.response),\n ...coveredSyncFrontier(state, currentRecord, synced),\n },\n {\n ...options,\n pendingBaseVersionOverride: extendDocumentVersionCoverage({\n baseVersion: state.pendingBaseVersion,\n documentVersion: encodeVersionVector(candidate),\n spans: updates,\n }),\n },\n generation,\n );\n if (\n persisted &&\n isCurrent() &&\n !persisted.pullContinuationSuperseded &&\n !persisted.syncIdentitySuperseded\n ) {\n // Publish a remote edit only once its history and continuation commit.\n // Importing earlier lets a losing CAS expose text that the next local\n // write authors against an older, reloaded CRDT history.\n // The durable CAS already checked the request's complete context. The\n // successful row is now live, so publication uses that committed context\n // (which may contain refreshed keying metadata) and the same generation.\n applyIncomingSyncedUpdates(\n state,\n currentDoc,\n persisted.record,\n syncAttempt,\n generation,\n );\n }\n return await publishPersistedDocument(\n state,\n currentDoc,\n persisted,\n previousDocumentId,\n options,\n isCurrent,\n );\n } finally {\n candidate.free();\n }\n}\n\nexport function shouldReArmDocumentSync(\n state: DocumentStoreState,\n syncAttempt: DocumentSyncAttempt,\n): boolean {\n const { synced } = syncAttempt;\n const shouldReArmOutgoing = settleOutgoingPassAndDecideReArm(state, {\n exhaustedPendingUpdateCount: synced.exhaustedPendingUpdateCount,\n outgoingUpdateCount: syncAttempt.outgoingUpdateCount,\n rekeyedUpdateCount: synced.rekeyedPendingUpdateIds.length,\n settledUpdateCount: synced.settledPendingUpdateIds.length,\n acceptedRecoveryBaseline: synced.acceptedRecoveryBaseline,\n });\n return (\n synced.hasDeferredPendingUpdates ||\n synced.hasIncompletePull ||\n shouldReArmOutgoing\n );\n}\n\nexport async function finalizeDocumentSync(\n state: DocumentStoreState,\n currentDoc: DocumentState,\n currentRecord: DocumentRecord,\n syncAttempt: DocumentSyncAttempt,\n consumedRemoteUpdateSignalSeq: number,\n generation: DocumentStoreSyncGeneration,\n sentUpdateIds: readonly string[],\n wasRemoteProbe: boolean,\n): Promise<DocumentRecord> {\n const { synced } = syncAttempt;\n if (!isDocumentStoreSyncGenerationCurrent(state, generation)) {\n discardPreRegisteredUpdateIds(state, sentUpdateIds);\n requestDocumentStoreSync(state);\n return state.record ?? currentRecord;\n }\n\n // The sent IDs were pre-registered as self-authored before the network call so\n // the redis echo can never beat us. Reconcile against what the server actually\n // accepted: an ID we sent but the server did not accept will never be echoed,\n // so drop it to keep locallyAcceptedUpdateIds from leaking. Accepted IDs (a\n // subset of what we sent) stay registered until their echo consumes them.\n discardUnacceptedPreRegisteredUpdateIds(\n state,\n sentUpdateIds,\n synced.response.acceptedOutgoingUpdateIds,\n );\n // Persist on the identity-write chain: synced.persistedState carries this\n // pass's documentId, so it would clobber a relink that landed mid-pass. If\n // the identity moved, the response describes the OLD document — skip every\n // response-derived in-memory mutation and let the new identity's own sync\n // pass take over.\n let responseApplied = false;\n const { record: nextRecord } = await chainIdentityWrite(state, async () => {\n const liveRecord = state.record;\n if (\n !isDocumentStoreSyncGenerationCurrent(state, generation) ||\n !documentSyncContextMatches(\n liveRecord,\n currentRecord,\n synced.plan.documentId,\n )\n ) {\n return { record: liveRecord ?? currentRecord };\n }\n\n installDocumentWriterProjection(\n state,\n resolveSyncedDocumentWriterProjection(state, synced),\n syncAttempt.writerProjectionGeneration,\n );\n const persisted = await persistSyncedDocument(\n state,\n currentDoc,\n currentRecord,\n syncAttempt,\n generation,\n );\n if (\n !persisted ||\n !isDocumentStoreSyncGenerationCurrent(state, generation)\n ) {\n return { record: state.record ?? currentRecord };\n }\n\n state.pullContinuation = persisted.record.pullContinuation ?? null;\n if (persisted.pullContinuationSuperseded) {\n state.writerProjection = null;\n }\n // A CAS loss means neither this response's acknowledgements nor its\n // continuation were committed. Keep the pass unapplied so its signals and\n // accepted-id registrations cannot be cleared without a follow-up.\n responseApplied = !persisted.pullContinuationSuperseded;\n return persisted;\n });\n if (!responseApplied) {\n discardPreRegisteredUpdateIds(state, sentUpdateIds);\n requestDocumentStoreSync(state);\n return nextRecord;\n }\n\n if (!isDocumentStoreSyncGenerationCurrent(state, generation)) {\n discardPreRegisteredUpdateIds(state, sentUpdateIds);\n requestDocumentStoreSync(state);\n return state.record ?? nextRecord;\n }\n\n // A bounded pull request owns the whole page chain. Completing the signal on\n // an intermediate page would let a failed/null continuation pass report the\n // original request as successful even though the server frontier was never\n // drained.\n if (!synced.hasIncompletePull) {\n clearConsumedRemoteUpdateSignal(state, consumedRemoteUpdateSignalSeq);\n }\n\n if (shouldReArmDocumentSync(state, syncAttempt)) {\n requestDocumentStoreSync(state);\n }\n\n await hydrateAttachmentBlobs(state, currentDoc, nextRecord, generation);\n logApplied(state, currentDoc, synced.decryptedUpdates.length, wasRemoteProbe);\n return nextRecord;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"syncFinalize.js","sourceRoot":"","sources":["syncFinalize.ts"],"names":[],"mappings":"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","sourcesContent":["import { bytesToBase64 } from \"@tearleads/encoding\";\nimport {\n emptyVersionVector,\n encodeVersionVector,\n getImportBlobMetadata,\n mergeVersionVectors,\n} from \"@tearleads/loro\";\nimport { readPullContinuation } from \"../../../data/documents/shared/syncPagination\";\nimport {\n type DocumentRecord,\n settleOutgoingPassAndDecideReArm,\n shouldClearDocumentSyncFailureAfterPass,\n} from \"../../../workflows/documents\";\nimport { requestDocumentStoreSync } from \"../registry\";\nimport { hydrateAttachmentBlobs } from \"./attachmentHydration\";\nimport { chainIdentityWrite } from \"./identityWriteChain\";\nimport { publishPersistedDocument, saveDocumentRecord } from \"./persistence\";\nimport { logRevalidationApplied as logApplied } from \"./remoteRevalidationTelemetry\";\nimport type {\n DocumentState,\n DocumentStoreState,\n DocumentSyncAttempt,\n SaveDocumentRecordOptions,\n} from \"./state\";\nimport {\n discardPreRegisteredUpdateIds,\n discardUnacceptedPreRegisteredUpdateIds,\n} from \"./syncAcceptedUpdateIds\";\nimport {\n type DocumentStoreSyncGeneration,\n isDocumentStoreSyncGenerationCurrent,\n} from \"./syncGeneration\";\nimport { clearConsumedRemoteUpdateSignal } from \"./syncRemoteSignals\";\nimport {\n applyIncomingSyncedUpdates,\n documentSyncContextMatches,\n importSyncedDocumentUpdates,\n} from \"./syncUpdateImport\";\nimport { extendDocumentVersionCoverage } from \"./versionCoverage\";\nimport { installDocumentWriterProjection } from \"./writerProjectionGeneration\";\n\nfunction documentWriterProjectionMatchesSyncResponse(\n writerProjection: NonNullable<\n DocumentSyncAttempt[\"synced\"][\"writerProjection\"]\n >,\n synced: DocumentSyncAttempt[\"synced\"],\n): boolean {\n return (\n writerProjection.contentKeyBundle.contentKeyEpoch ===\n synced.response.contentKeyBundle.contentKeyEpoch &&\n writerProjection.contentKeyBundle.linkSetManifestHash ===\n synced.response.contentKeyBundle.linkSetManifestHash &&\n writerProjection.contentKeyBundle.targetHash ===\n synced.response.contentKeyBundle.targetHash &&\n writerProjection.documentKekTargets.linkSetManifestHash ===\n synced.response.documentKekTargets.linkSetManifestHash &&\n writerProjection.documentKekTargets.documentKeyTargetHash ===\n synced.response.documentKekTargets.documentKeyTargetHash\n );\n}\n\nfunction resolveSyncedDocumentWriterProjection(\n state: DocumentStoreState,\n synced: DocumentSyncAttempt[\"synced\"],\n) {\n const writerProjection =\n synced.writerProjection ??\n (state.writerProjection?.documentId === synced.plan.documentId\n ? state.writerProjection\n : null);\n return writerProjection &&\n documentWriterProjectionMatchesSyncResponse(writerProjection, synced)\n ? writerProjection\n : null;\n}\n\n/**\n * Durable-history tail: append pulled updates BEFORE the record persist so\n * the tail stays a superset of what the snapshot covers (duplicates are\n * idempotent by op identity; a crash between the writes can only leave the\n * safe superset).\n */\nfunction pulledHistoryUpdates(synced: DocumentSyncAttempt[\"synced\"]): string[] {\n return synced.decryptedUpdates.map((update) =>\n bytesToBase64(update.updateData),\n );\n}\n\n/**\n * The frontier a finalize persist may publish: the stored frontier advanced\n * by exactly the pulled updates just appended to the durable tail — never the\n * live document's version, which can transiently include an in-flight local\n * edit whose durable row has not landed yet.\n */\nfunction coveredSyncFrontier(\n state: DocumentStoreState,\n currentRecord: DocumentRecord,\n synced: DocumentSyncAttempt[\"synced\"],\n): { snapshotEndVersion: string } | Record<string, never> {\n const liveFrontier = (state.record ?? currentRecord).snapshotEndVersion;\n if (synced.decryptedUpdates.length === 0) {\n // A completed empty pull distinguishes a real blank note from discovery.\n // An intermediate page cannot establish that no content exists yet.\n return liveFrontier === \"\" && !synced.hasIncompletePull\n ? { snapshotEndVersion: emptyVersionVector() }\n : {};\n }\n return {\n snapshotEndVersion: mergeVersionVectors([\n ...(liveFrontier.length > 0 ? [liveFrontier] : []),\n ...synced.decryptedUpdates.map(\n (update) =>\n getImportBlobMetadata(update.updateData).partialEndVersionVector,\n ),\n ]),\n };\n}\n\nfunction documentSyncSaveOptions(\n syncAttempt: DocumentSyncAttempt,\n): SaveDocumentRecordOptions {\n return {\n acceptedPendingUpdateIds: syncAttempt.synced.settledPendingUpdateIds,\n clearSyncFailure: shouldClearDocumentSyncFailureAfterPass(\n syncAttempt.synced,\n syncAttempt.outgoingUpdateCount,\n ),\n expectedSyncState: {\n pullContinuation: syncAttempt.consumedPullContinuation,\n record: syncAttempt.requestRecord,\n },\n historyUpdateOrigin: \"remote\",\n historyUpdates: pulledHistoryUpdates(syncAttempt.synced),\n preserveSnapshotStructuredFields: true,\n preserveSnapshotText: true,\n };\n}\n\nasync function persistSyncedDocument(\n state: DocumentStoreState,\n currentDoc: DocumentState,\n currentRecord: DocumentRecord,\n syncAttempt: DocumentSyncAttempt,\n generation: DocumentStoreSyncGeneration,\n) {\n const { synced } = syncAttempt;\n const updates = synced.decryptedUpdates;\n const candidate = currentDoc.fork();\n const previousDocumentId = state.record?.documentId ?? null;\n const options = documentSyncSaveOptions(syncAttempt);\n const isCurrent = () =>\n isDocumentStoreSyncGenerationCurrent(state, generation);\n try {\n importSyncedDocumentUpdates(candidate, updates);\n if (state.pendingBaseVersion === null) {\n throw new Error(\"Document sync requires an initialized pending base\");\n }\n const persisted = await saveDocumentRecord(\n state,\n candidate,\n {\n ...synced.persistedState,\n lastCommitLsn:\n synced.response.commitLsn ?? currentRecord.lastCommitLsn ?? null,\n pullContinuation: readPullContinuation(synced.response),\n ...coveredSyncFrontier(state, currentRecord, synced),\n },\n {\n ...options,\n pendingBaseVersionOverride: extendDocumentVersionCoverage({\n baseVersion: state.pendingBaseVersion,\n documentVersion: encodeVersionVector(candidate),\n spans: updates,\n }),\n },\n generation,\n );\n if (\n persisted &&\n isCurrent() &&\n !persisted.pullContinuationSuperseded &&\n !persisted.syncIdentitySuperseded\n ) {\n // Publish a remote edit only once its history and continuation commit.\n // Importing earlier lets a losing CAS expose text that the next local\n // write authors against an older, reloaded CRDT history.\n // The durable CAS already checked the request's complete context. The\n // successful row is now live, so publication uses that committed context\n // (which may contain refreshed keying metadata) and the same generation.\n applyIncomingSyncedUpdates(\n state,\n currentDoc,\n persisted.record,\n syncAttempt,\n generation,\n );\n }\n return await publishPersistedDocument(\n state,\n currentDoc,\n persisted,\n previousDocumentId,\n options,\n isCurrent,\n );\n } finally {\n candidate.free();\n }\n}\n\nexport function shouldReArmDocumentSync(\n state: DocumentStoreState,\n syncAttempt: DocumentSyncAttempt,\n): boolean {\n const { synced } = syncAttempt;\n const shouldReArmOutgoing = settleOutgoingPassAndDecideReArm(state, {\n exhaustedPendingUpdateCount: synced.exhaustedPendingUpdateCount,\n outgoingUpdateCount: syncAttempt.outgoingUpdateCount,\n rekeyedUpdateCount: synced.rekeyedPendingUpdateIds.length,\n settledUpdateCount: synced.settledPendingUpdateIds.length,\n acceptedRecoveryBaseline: synced.acceptedRecoveryBaseline,\n });\n return (\n synced.hasDeferredPendingUpdates ||\n synced.hasIncompletePull ||\n shouldReArmOutgoing\n );\n}\n\nexport async function finalizeDocumentSync(\n state: DocumentStoreState,\n currentDoc: DocumentState,\n currentRecord: DocumentRecord,\n syncAttempt: DocumentSyncAttempt,\n consumedRemoteUpdateSignalSeq: number,\n generation: DocumentStoreSyncGeneration,\n sentUpdateIds: readonly string[],\n wasRemoteProbe: boolean,\n): Promise<DocumentRecord> {\n const { synced } = syncAttempt;\n if (!isDocumentStoreSyncGenerationCurrent(state, generation)) {\n discardPreRegisteredUpdateIds(state, sentUpdateIds);\n requestDocumentStoreSync(state);\n return state.record ?? currentRecord;\n }\n\n // The sent IDs were pre-registered as self-authored before the network call so\n // the redis echo can never beat us. Reconcile against what the server actually\n // accepted: an ID we sent but the server did not accept will never be echoed,\n // so drop it to keep locallyAcceptedUpdateIds from leaking. Accepted IDs (a\n // subset of what we sent) stay registered until their echo consumes them.\n discardUnacceptedPreRegisteredUpdateIds(\n state,\n sentUpdateIds,\n synced.response.acceptedOutgoingUpdateIds,\n );\n // Persist on the identity-write chain: synced.persistedState carries this\n // pass's documentId, so it would clobber a relink that landed mid-pass. If\n // the identity moved, the response describes the OLD document — skip every\n // response-derived in-memory mutation and let the new identity's own sync\n // pass take over.\n let responseApplied = false;\n const { record: nextRecord } = await chainIdentityWrite(state, async () => {\n const liveRecord = state.record;\n if (\n !isDocumentStoreSyncGenerationCurrent(state, generation) ||\n !documentSyncContextMatches(\n liveRecord,\n currentRecord,\n synced.plan.documentId,\n )\n ) {\n return { record: liveRecord ?? currentRecord };\n }\n\n installDocumentWriterProjection(\n state,\n resolveSyncedDocumentWriterProjection(state, synced),\n syncAttempt.writerProjectionGeneration,\n );\n const persisted = await persistSyncedDocument(\n state,\n currentDoc,\n currentRecord,\n syncAttempt,\n generation,\n );\n if (\n !persisted ||\n !isDocumentStoreSyncGenerationCurrent(state, generation)\n ) {\n return { record: state.record ?? currentRecord };\n }\n\n state.pullContinuation = persisted.record.pullContinuation ?? null;\n if (persisted.pullContinuationSuperseded) {\n state.writerProjection = null;\n }\n // A CAS loss means neither this response's acknowledgements nor its\n // continuation were committed. Keep the pass unapplied so its signals and\n // accepted-id registrations cannot be cleared without a follow-up.\n responseApplied = !persisted.pullContinuationSuperseded;\n return persisted;\n });\n if (!responseApplied) {\n discardPreRegisteredUpdateIds(state, sentUpdateIds);\n requestDocumentStoreSync(state);\n return nextRecord;\n }\n\n if (!isDocumentStoreSyncGenerationCurrent(state, generation)) {\n discardPreRegisteredUpdateIds(state, sentUpdateIds);\n requestDocumentStoreSync(state);\n return state.record ?? nextRecord;\n }\n\n // A bounded pull request owns the whole page chain. Completing the signal on\n // an intermediate page would let a failed/null continuation pass report the\n // original request as successful even though the server frontier was never\n // drained.\n if (!synced.hasIncompletePull) {\n clearConsumedRemoteUpdateSignal(state, consumedRemoteUpdateSignalSeq);\n }\n\n if (shouldReArmDocumentSync(state, syncAttempt)) {\n requestDocumentStoreSync(state);\n }\n\n await hydrateAttachmentBlobs(state, currentDoc, nextRecord, generation);\n logApplied(state, currentDoc, synced.decryptedUpdates.length, wasRemoteProbe);\n return nextRecord;\n}\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { emptyVersionVector } from "../../../internal/loro/index.js";
|
|
2
|
+
// Discovery persists a shell before its first content pull. Keep those rows
|
|
3
|
+
// available to sync, but out of Explorer's selectable, paginated projections.
|
|
4
|
+
export function emptyContentFrontierSql(alias) {
|
|
5
|
+
return `(${alias}.snapshot_end_version = '' OR (${alias}.app_kind = 'container-metadata' AND ${alias}.snapshot_end_version = '${emptyVersionVector()}'))`;
|
|
6
|
+
}
|
|
7
|
+
export function hydratedProjectionSql(localId, appKind) {
|
|
8
|
+
return `NOT EXISTS (
|
|
9
|
+
SELECT 1 FROM documents hydration
|
|
10
|
+
WHERE hydration.app_kind = '${appKind}'
|
|
11
|
+
AND hydration.local_id = ${localId}
|
|
12
|
+
AND hydration.document_id IS NOT NULL
|
|
13
|
+
AND ${emptyContentFrontierSql("hydration")}
|
|
14
|
+
)`;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=hydrationSql.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hydrationSql.js","sourceRoot":"","sources":["hydrationSql.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErD,4EAA4E;AAC5E,8EAA8E;AAC9E,MAAM,UAAU,uBAAuB,CAAC,KAAa;IACnD,OAAO,IAAI,KAAK,kCAAkC,KAAK,wCAAwC,KAAK,4BAA4B,kBAAkB,EAAE,KAAK,CAAC;AAC5J,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,OAAe,EACf,OAA2C;IAE3C,OAAO;;kCAEyB,OAAO;iCACR,OAAO;;YAE5B,uBAAuB,CAAC,WAAW,CAAC;IAC5C,CAAC;AACL,CAAC","sourcesContent":["import { emptyVersionVector } from \"@tearleads/loro\";\n\n// Discovery persists a shell before its first content pull. Keep those rows\n// available to sync, but out of Explorer's selectable, paginated projections.\nexport function emptyContentFrontierSql(alias: string): string {\n return `(${alias}.snapshot_end_version = '' OR (${alias}.app_kind = 'container-metadata' AND ${alias}.snapshot_end_version = '${emptyVersionVector()}'))`;\n}\n\nexport function hydratedProjectionSql(\n localId: string,\n appKind: \"documents\" | \"container-metadata\",\n): string {\n return `NOT EXISTS (\n SELECT 1 FROM documents hydration\n WHERE hydration.app_kind = '${appKind}'\n AND hydration.local_id = ${localId}\n AND hydration.document_id IS NOT NULL\n AND ${emptyContentFrontierSql(\"hydration\")}\n )`;\n}\n"]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getOrphanedDocumentWhereSql } from "../orphanedDocumentSql.js";
|
|
2
|
+
import { hydratedProjectionSql } from "./hydrationSql.js";
|
|
2
3
|
// Keep each IN clause below SQLite's historical 999 bind-parameter limit.
|
|
3
4
|
const CONTAINER_DOCUMENT_SQL_ID_BATCH_SIZE = 500;
|
|
4
5
|
const MAX_CONTAINER_ITEM_WINDOW_LIMIT = 200;
|
|
@@ -140,6 +141,7 @@ export function getContainerContentsContainerItemsBaseSql(visibleSystemSlotCount
|
|
|
140
141
|
LEFT JOIN pending_container_create_intents create_intent
|
|
141
142
|
ON create_intent.container_id = c.id
|
|
142
143
|
WHERE c.parent_id = ?
|
|
144
|
+
AND ${hydratedProjectionSql("c.id", "container-metadata")}
|
|
143
145
|
AND ${getContainerContentsContainerSystemSlotFilter({
|
|
144
146
|
visibleForeignSystemContainerNameCount,
|
|
145
147
|
visibleSystemSlotCount,
|
|
@@ -171,7 +173,8 @@ export function getContainerContentsContainerItemsBaseSql(visibleSystemSlotCount
|
|
|
171
173
|
ON document_updates.local_id = d.local_id
|
|
172
174
|
LEFT JOIN document_pending_attachment_counts document_attachments
|
|
173
175
|
ON document_attachments.local_id = d.local_id
|
|
174
|
-
WHERE
|
|
176
|
+
WHERE ${hydratedProjectionSql("d.local_id", "documents")}
|
|
177
|
+
AND d.container_id = ?${getHeldPlacementExclusionSql("d.document_id", "d.container_id")}
|
|
175
178
|
|
|
176
179
|
UNION ALL
|
|
177
180
|
|
|
@@ -200,7 +203,8 @@ export function getContainerContentsContainerItemsBaseSql(visibleSystemSlotCount
|
|
|
200
203
|
ON document_updates.local_id = d.local_id
|
|
201
204
|
LEFT JOIN document_pending_attachment_counts document_attachments
|
|
202
205
|
ON document_attachments.local_id = d.local_id
|
|
203
|
-
WHERE
|
|
206
|
+
WHERE ${hydratedProjectionSql("d.local_id", "documents")}
|
|
207
|
+
AND linked.container_id = ?
|
|
204
208
|
AND (
|
|
205
209
|
d.container_id IS NULL
|
|
206
210
|
OR d.container_id != linked.container_id
|
|
@@ -229,7 +233,8 @@ export function getContainerContentsDocumentRowsBaseSql() {
|
|
|
229
233
|
ON document_updates.local_id = d.local_id
|
|
230
234
|
LEFT JOIN document_pending_attachment_counts document_attachments
|
|
231
235
|
ON document_attachments.local_id = d.local_id
|
|
232
|
-
WHERE
|
|
236
|
+
WHERE ${hydratedProjectionSql("d.local_id", "documents")}
|
|
237
|
+
AND d.container_id = ?${getHeldPlacementExclusionSql("d.document_id", "d.container_id")}
|
|
233
238
|
|
|
234
239
|
UNION ALL
|
|
235
240
|
|
|
@@ -249,7 +254,8 @@ export function getContainerContentsDocumentRowsBaseSql() {
|
|
|
249
254
|
ON document_updates.local_id = d.local_id
|
|
250
255
|
LEFT JOIN document_pending_attachment_counts document_attachments
|
|
251
256
|
ON document_attachments.local_id = d.local_id
|
|
252
|
-
WHERE
|
|
257
|
+
WHERE ${hydratedProjectionSql("d.local_id", "documents")}
|
|
258
|
+
AND linked.container_id = ?
|
|
253
259
|
AND (
|
|
254
260
|
d.container_id IS NULL
|
|
255
261
|
OR d.container_id != linked.container_id
|
|
@@ -287,7 +293,8 @@ export function getOrphanedDocumentItemsBaseSql() {
|
|
|
287
293
|
ON document_updates.local_id = d.local_id
|
|
288
294
|
LEFT JOIN document_pending_attachment_counts document_attachments
|
|
289
295
|
ON document_attachments.local_id = d.local_id
|
|
290
|
-
WHERE ${
|
|
296
|
+
WHERE ${hydratedProjectionSql("d.local_id", "documents")}
|
|
297
|
+
AND ${getOrphanedDocumentWhereSql({
|
|
291
298
|
documentIdSql: "d.document_id",
|
|
292
299
|
projectionAlias: "d",
|
|
293
300
|
})}
|
|
@@ -314,7 +321,8 @@ export function getOrphanedDocumentRowsBaseSql() {
|
|
|
314
321
|
ON document_updates.local_id = d.local_id
|
|
315
322
|
LEFT JOIN document_pending_attachment_counts document_attachments
|
|
316
323
|
ON document_attachments.local_id = d.local_id
|
|
317
|
-
WHERE ${
|
|
324
|
+
WHERE ${hydratedProjectionSql("d.local_id", "documents")}
|
|
325
|
+
AND ${getOrphanedDocumentWhereSql({
|
|
318
326
|
documentIdSql: "d.document_id",
|
|
319
327
|
projectionAlias: "d",
|
|
320
328
|
})}
|
|
@@ -324,7 +332,8 @@ export function getOrphanedDocumentExistsSql() {
|
|
|
324
332
|
return `
|
|
325
333
|
SELECT 1
|
|
326
334
|
FROM document_projection d
|
|
327
|
-
WHERE ${
|
|
335
|
+
WHERE ${hydratedProjectionSql("d.local_id", "documents")}
|
|
336
|
+
AND ${getOrphanedDocumentWhereSql({
|
|
328
337
|
documentIdSql: "d.document_id",
|
|
329
338
|
projectionAlias: "d",
|
|
330
339
|
})}
|