@tearleads/client-sdk 0.1.42 → 0.1.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (224) hide show
  1. package/client/containerDocumentDiscovery.js +71 -29
  2. package/client/containerDocumentDiscovery.js.map +1 -1
  3. package/client/deviceFirst.js +4 -5
  4. package/client/deviceFirst.js.map +1 -1
  5. package/data/blobs/transferPool.js +35 -8
  6. package/data/blobs/transferPool.js.map +1 -1
  7. package/data/containers/shared/projection.js +12 -0
  8. package/data/containers/shared/projection.js.map +1 -1
  9. package/data/documents/blob/shared/types.d.ts +2 -3
  10. package/data/documents/blob/shared/types.js.map +1 -1
  11. package/data/documents/shared/events.js +0 -1
  12. package/data/documents/shared/events.js.map +1 -1
  13. package/data/persistence/container-contents/containerContentsPersistence.js +6 -22
  14. package/data/persistence/container-contents/containerContentsPersistence.js.map +1 -1
  15. package/data/persistence/container-contents/containerMetadataMutationPersistence.js +5 -15
  16. package/data/persistence/container-contents/containerMetadataMutationPersistence.js.map +1 -1
  17. package/data/persistence/container-contents/containerPendingUpdatePersistence.js +6 -15
  18. package/data/persistence/container-contents/containerPendingUpdatePersistence.js.map +1 -1
  19. package/data/persistence/container-contents/containerRecoveryPersistence.js +3 -4
  20. package/data/persistence/container-contents/containerRecoveryPersistence.js.map +1 -1
  21. package/data/persistence/container-contents/containerRemovalWork.js +3 -5
  22. package/data/persistence/container-contents/containerRemovalWork.js.map +1 -1
  23. package/data/persistence/container-contents/dormantContainerMetadata.js +1 -5
  24. package/data/persistence/container-contents/dormantContainerMetadata.js.map +1 -1
  25. package/data/persistence/containers/containerSyncWatermarkPersistence.d.ts +11 -3
  26. package/data/persistence/containers/containerSyncWatermarkPersistence.js +46 -58
  27. package/data/persistence/containers/containerSyncWatermarkPersistence.js.map +1 -1
  28. package/data/persistence/documents/documentsPersistence.js +4 -9
  29. package/data/persistence/documents/documentsPersistence.js.map +1 -1
  30. package/data/persistence/documents/internal/discardDocument.js +1 -2
  31. package/data/persistence/documents/internal/discardDocument.js.map +1 -1
  32. package/data/persistence/documents/internal/documentDeletionPersistence.js +1 -2
  33. package/data/persistence/documents/internal/documentDeletionPersistence.js.map +1 -1
  34. package/data/persistence/documents/internal/documentMutationPersistence.js +17 -25
  35. package/data/persistence/documents/internal/documentMutationPersistence.js.map +1 -1
  36. package/data/persistence/documents/internal/orphanSideRows.js +2 -14
  37. package/data/persistence/documents/internal/orphanSideRows.js.map +1 -1
  38. package/data/persistence/documents/internal/syncQueuePersistence.js +3 -3
  39. package/data/persistence/documents/internal/syncQueuePersistence.js.map +1 -1
  40. package/data/sqlite/documentHistoryPersistence.d.ts +9 -3
  41. package/data/sqlite/documentHistoryPersistence.js +31 -8
  42. package/data/sqlite/documentHistoryPersistence.js.map +1 -1
  43. package/data/sqlite/documentPendingUpdatePersistence.d.ts +58 -11
  44. package/data/sqlite/documentPendingUpdatePersistence.js +137 -63
  45. package/data/sqlite/documentPendingUpdatePersistence.js.map +1 -1
  46. package/data/sqlite/documentPersistence.d.ts +1 -1
  47. package/data/sqlite/documentPersistence.js +1 -1
  48. package/data/sqlite/documentPersistence.js.map +1 -1
  49. package/data/sqlite/documentPersistenceTypes.d.ts +2 -2
  50. package/data/sqlite/documentPersistenceTypes.js.map +1 -1
  51. package/data/sqlite/documentRecordPersistence.js +5 -4
  52. package/data/sqlite/documentRecordPersistence.js.map +1 -1
  53. package/data/sqlite/schema.d.ts +167 -517
  54. package/data/sqlite/schema.js +68 -82
  55. package/data/sqlite/schema.js.map +1 -1
  56. package/internal/api-client/ApiClient.d.ts +18 -41
  57. package/internal/api-client/ApiClient.js +9 -14
  58. package/internal/api-client/ApiClient.js.map +1 -1
  59. package/internal/api-client/apiRequestRuntime.d.ts +2 -0
  60. package/internal/api-client/apiRequestRuntime.js +4 -0
  61. package/internal/api-client/apiRequestRuntime.js.map +1 -1
  62. package/internal/api-client/binaryRequestOperationTransport.d.ts +18 -0
  63. package/internal/api-client/index.d.ts +1 -0
  64. package/internal/api-client/index.js +1 -0
  65. package/internal/api-client/index.js.map +1 -1
  66. package/internal/api-client/operationTransportFactory.d.ts +6 -0
  67. package/internal/api-client/requestInternals.js +7 -7
  68. package/internal/api-client/requestInternals.js.map +1 -1
  69. package/internal/api-client/routes/blobs/get.d.ts +7 -0
  70. package/internal/api-client/routes/blobs/get.js.map +1 -1
  71. package/internal/api-client/routes/blobs/multipart.js +1 -11
  72. package/internal/api-client/routes/blobs/multipart.js.map +1 -1
  73. package/internal/api-client/routes/blobs/multipartUpload.d.ts +14 -0
  74. package/internal/api-client/routes/blobs/multipartUpload.js +94 -43
  75. package/internal/api-client/routes/blobs/multipartUpload.js.map +1 -1
  76. package/internal/api-client/routes/containers/reads.d.ts +13 -7
  77. package/internal/api-client/routes/containers/reads.js +36 -15
  78. package/internal/api-client/routes/containers/reads.js.map +1 -1
  79. package/internal/api-client/types.d.ts +1 -5
  80. package/internal/api-client/types.js.map +1 -1
  81. package/internal/validators/containerReadRefinements.js +15 -5
  82. package/internal/validators/containerReadRefinements.js.map +1 -1
  83. package/internal/validators/containerReadSchemas.d.ts +36 -0
  84. package/internal/validators/containerReadSchemas.js +64 -1
  85. package/internal/validators/containerReadSchemas.js.map +1 -1
  86. package/internal/validators/operation/attachments.d.ts +80 -160
  87. package/internal/validators/operation/auth.d.ts +760 -1664
  88. package/internal/validators/operation/blobDownloads.js +1 -1
  89. package/internal/validators/operation/blobDownloads.js.map +1 -1
  90. package/internal/validators/operation/containerMutations.d.ts +416 -856
  91. package/internal/validators/operation/containerReads.d.ts +118 -182
  92. package/internal/validators/operation/containerReads.js +20 -54
  93. package/internal/validators/operation/containerReads.js.map +1 -1
  94. package/internal/validators/operation/documentMutations.d.ts +120 -264
  95. package/internal/validators/operation/documentSync.d.ts +40 -80
  96. package/internal/validators/operation/index.d.ts +2 -2
  97. package/internal/validators/operation/index.js +2 -2
  98. package/internal/validators/operation/index.js.map +1 -1
  99. package/internal/validators/operation/multipartBlobs.d.ts +70 -190
  100. package/internal/validators/operation/multipartBlobs.js +2 -24
  101. package/internal/validators/operation/multipartBlobs.js.map +1 -1
  102. package/internal/validators/operation/multipartPartUploads.d.ts +5 -5
  103. package/internal/validators/operation/multipartPartUploads.js +6 -20
  104. package/internal/validators/operation/multipartPartUploads.js.map +1 -1
  105. package/internal/validators/operation/organizations.d.ts +882 -1906
  106. package/internal/validators/operation/principals.d.ts +120 -240
  107. package/internal/validators/operation/registry.d.ts +3 -4
  108. package/internal/validators/operation/registry.js +3 -4
  109. package/internal/validators/operation/registry.js.map +1 -1
  110. package/internal/validators/request/blob.d.ts +100 -201
  111. package/internal/validators/request/blob.js +6 -13
  112. package/internal/validators/request/blob.js.map +1 -1
  113. package/internal/validators/request/container.d.ts +136 -272
  114. package/internal/validators/request/container.js +16 -10
  115. package/internal/validators/request/container.js.map +1 -1
  116. package/internal/validators/request/containerDocumentLanes.d.ts +23 -0
  117. package/internal/validators/request/containerDocumentLanes.js +23 -0
  118. package/internal/validators/request/containerDocumentLanes.js.map +1 -0
  119. package/internal/validators/request/containerManifestRef.d.ts +54 -0
  120. package/internal/validators/request/containerManifestRef.js +28 -0
  121. package/internal/validators/request/containerManifestRef.js.map +1 -0
  122. package/internal/validators/request/containerMetadata.d.ts +160 -368
  123. package/internal/validators/request/containerParentLanes.js +5 -35
  124. package/internal/validators/request/containerParentLanes.js.map +1 -1
  125. package/internal/validators/request/document.d.ts +100 -245
  126. package/internal/validators/request/document.js +1 -2
  127. package/internal/validators/request/document.js.map +1 -1
  128. package/internal/validators/request/documentSyncSchema.d.ts +42 -109
  129. package/internal/validators/request/documentSyncSchema.js +8 -25
  130. package/internal/validators/request/documentSyncSchema.js.map +1 -1
  131. package/internal/validators/request/index.d.ts +2 -1
  132. package/internal/validators/request/index.js +2 -1
  133. package/internal/validators/request/index.js.map +1 -1
  134. package/internal/validators/request/organization.d.ts +160 -320
  135. package/internal/validators/request/organizationProvisioning.d.ts +2424 -5312
  136. package/internal/validators/request/principal.d.ts +160 -320
  137. package/internal/validators/request/registration.d.ts +760 -1664
  138. package/internal/validators/response/blob.d.ts +48 -27
  139. package/internal/validators/response/blob.js +3 -10
  140. package/internal/validators/response/blob.js.map +1 -1
  141. package/internal/validators/response/containerDocumentLanes.d.ts +82 -0
  142. package/internal/validators/response/containerDocumentLanes.js +35 -0
  143. package/internal/validators/response/containerDocumentLanes.js.map +1 -0
  144. package/internal/validators/response/containerParentLanes.js +3 -15
  145. package/internal/validators/response/containerParentLanes.js.map +1 -1
  146. package/internal/validators/response/index.d.ts +3 -2
  147. package/internal/validators/response/index.js +2 -2
  148. package/internal/validators/response/index.js.map +1 -1
  149. package/internal/validators/util/blob.d.ts +7 -0
  150. package/internal/validators/util/blob.js +7 -0
  151. package/internal/validators/util/blob.js.map +1 -1
  152. package/internal/validators/util/blobTransferSchemas.d.ts +41 -0
  153. package/internal/validators/util/blobTransferSchemas.js +39 -0
  154. package/internal/validators/util/blobTransferSchemas.js.map +1 -0
  155. package/internal/validators/util/containerLimits.d.ts +7 -0
  156. package/internal/validators/util/containerLimits.js +7 -0
  157. package/internal/validators/util/containerLimits.js.map +1 -1
  158. package/internal/validators/util/index.d.ts +2 -1
  159. package/internal/validators/util/index.js +2 -1
  160. package/internal/validators/util/index.js.map +1 -1
  161. package/package.json +1 -1
  162. package/sync/reconciliation/knownContainerSweep.js +57 -54
  163. package/sync/reconciliation/knownContainerSweep.js.map +1 -1
  164. package/sync/reconciliation/reconcileContainer.js +49 -17
  165. package/sync/reconciliation/reconcileContainer.js.map +1 -1
  166. package/sync/reconciliation/service.js +44 -16
  167. package/sync/reconciliation/service.js.map +1 -1
  168. package/sync/reconciliation/serviceTypes.d.ts +23 -2
  169. package/sync/reconciliation/serviceTypes.js.map +1 -1
  170. package/workflows/blobs/multipartFirstParts.js +82 -0
  171. package/workflows/blobs/multipartFirstParts.js.map +1 -0
  172. package/workflows/blobs/multipartStageResolution.js +83 -0
  173. package/workflows/blobs/multipartStageResolution.js.map +1 -0
  174. package/workflows/blobs/multipartUpload.js +45 -89
  175. package/workflows/blobs/multipartUpload.js.map +1 -1
  176. package/workflows/container-contents/containerDocumentListing.js +92 -38
  177. package/workflows/container-contents/containerDocumentListing.js.map +1 -1
  178. package/workflows/container-contents/containerPersistence.d.ts +8 -2
  179. package/workflows/container-contents/containerPersistence.js +6 -7
  180. package/workflows/container-contents/containerPersistence.js.map +1 -1
  181. package/workflows/container-contents/documentDiscovery.d.ts +3 -3
  182. package/workflows/container-contents/documentDiscovery.js +24 -96
  183. package/workflows/container-contents/documentDiscovery.js.map +1 -1
  184. package/workflows/container-contents/documentDiscoveryApply.js +65 -0
  185. package/workflows/container-contents/documentDiscoveryApply.js.map +1 -0
  186. package/workflows/container-contents/documentDiscoveryLanes.js +53 -0
  187. package/workflows/container-contents/documentDiscoveryLanes.js.map +1 -0
  188. package/workflows/container-contents/documentDiscoveryTypes.d.ts +25 -19
  189. package/workflows/container-contents/documentDiscoveryTypes.js.map +1 -1
  190. package/workflows/container-contents/documentPriming.js +2 -1
  191. package/workflows/container-contents/documentPriming.js.map +1 -1
  192. package/workflows/container-contents/documentQueries/sql.js +4 -4
  193. package/workflows/container-contents/documentQueries/sql.js.map +1 -1
  194. package/workflows/container-contents/pendingWrites/deferredTails.js +6 -3
  195. package/workflows/container-contents/pendingWrites/deferredTails.js.map +1 -1
  196. package/workflows/container-contents/pendingWrites/sources.js +2 -1
  197. package/workflows/container-contents/pendingWrites/sources.js.map +1 -1
  198. package/workflows/container-contents/pendingWrites.js +2 -1
  199. package/workflows/container-contents/pendingWrites.js.map +1 -1
  200. package/workflows/container-contents/remoteHydration/laneFetchMarkers.js +11 -17
  201. package/workflows/container-contents/remoteHydration/laneFetchMarkers.js.map +1 -1
  202. package/workflows/containers/child/create.js +3 -3
  203. package/workflows/containers/child/create.js.map +1 -1
  204. package/workflows/containers/child/move.js +2 -2
  205. package/workflows/containers/child/move.js.map +1 -1
  206. package/workflows/containers/child/mutationRequestCore.js +5 -4
  207. package/workflows/containers/child/mutationRequestCore.js.map +1 -1
  208. package/workflows/containers/child/recitePlan.js +3 -2
  209. package/workflows/containers/child/recitePlan.js.map +1 -1
  210. package/workflows/containers/child/sharePlanCore.js +2 -2
  211. package/workflows/containers/child/sharePlanCore.js.map +1 -1
  212. package/workflows/containers/root/create.js +2 -2
  213. package/workflows/containers/root/create.js.map +1 -1
  214. package/workflows/registration/provisioningBootstrapBuilders.d.ts +20 -46
  215. package/workflows/sync/remoteReset.js +9 -9
  216. package/workflows/sync/remoteReset.js.map +1 -1
  217. package/workflows/sync/remoteResetCursorScope.js +10 -18
  218. package/workflows/sync/remoteResetCursorScope.js.map +1 -1
  219. package/workflows/sync/remoteResetPlans.js +6 -3
  220. package/workflows/sync/remoteResetPlans.js.map +1 -1
  221. package/workflows/sync/remoteResetScope.js +4 -11
  222. package/workflows/sync/remoteResetScope.js.map +1 -1
  223. package/internal/validators/operation/blobTransferSchemas.js +0 -11
  224. package/internal/validators/operation/blobTransferSchemas.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"events.js","sourceRoot":"","sources":["events.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n computeAccessEventBodyHash,\n computeAccessEventHash,\n computeAccessManifestHash,\n computeDocumentContentKeyTargetHash,\n type DocumentLinkAccessEventBody,\n type DocumentLinkSetManifestState,\n deriveDocumentLinkSetManifest,\n signAccessEvent,\n type UnsignedAccessEvent,\n} from \"@tearleads/crypto\";\nimport type { ContainerManifestRef } from \"@tearleads/validators/request\";\nimport type { DocumentWriterProjectionResponse } from \"@tearleads/validators/response\";\nimport {\n readCanonicalJson,\n readCanonicalRecord,\n} from \"../../keyingCanonicalJson\";\nimport {\n authorizingContainerPathRefsForLinkSet,\n containerPathRefs,\n deriveDocumentCreateTargets,\n mergeTargetEnvelopes,\n} from \"./projection\";\nimport { sortDocumentTargets, uniqueSortedStrings } from \"./readers\";\nimport type {\n BuildDocumentCreatePlanInput,\n DocumentCreateAuthor,\n DocumentCreatePlan,\n DocumentLinkSetEventPlan,\n DocumentLinkSetMutationBody,\n DocumentLinkSetMutationOperation,\n DocumentLinkSetTargetState,\n} from \"./types\";\n\nexport async function buildDocumentCreatePlan({\n author,\n containerProjection,\n contentKeyEpoch = 1,\n documentId = crypto.randomUUID(),\n eventId = crypto.randomUUID(),\n signedAt = new Date().toISOString(),\n targetEnvelopes,\n}: BuildDocumentCreatePlanInput): Promise<DocumentCreatePlan> {\n // The document belongs to its container's organization, not the author's. A\n // member authoring a document under another org's shared container creates a\n // document owned by that org; the author supplies only the signer identity.\n const organizationId = containerProjection.organizationId;\n\n const targets = deriveDocumentCreateTargets(containerProjection);\n const targetEnvelopesForRequest = mergeTargetEnvelopes(\n targets,\n targetEnvelopes,\n );\n const targetContainerManifestHash = targets[0]?.containerManifestHash;\n const targetContainerId = targets[0]?.containerId;\n if (!targetContainerManifestHash || !targetContainerId) {\n throw new Error(\"Document create target is unavailable\");\n }\n\n const body: DocumentLinkAccessEventBody = {\n blobRewraps: [],\n eventType: \"document.link\",\n containerId: targetContainerId,\n containerManifestHash: targetContainerManifestHash,\n };\n const bodyHash = await computeAccessEventBodyHash(\n readCanonicalJson(body, \"Document create body\"),\n );\n const unsignedEvent: UnsignedAccessEvent = {\n version: 1,\n eventId,\n eventType: \"document.link\",\n objectKind: \"document\",\n objectId: documentId,\n organizationId,\n previousManifestHash: null,\n dependencyManifestHashes: uniqueSortedStrings(\n containerProjection.path.map((bundle) => bundle.manifestHash),\n ),\n bodyHash,\n signerUserId: author.signerUserId,\n signerDeviceId: author.signerDeviceId,\n signerKeyFingerprint: author.signerKeyFingerprint,\n signedAt,\n };\n const event = await signAccessEvent(unsignedEvent, author.signerPrivateKey);\n const eventHash = await computeAccessEventHash(event);\n const state: DocumentLinkSetManifestState = {\n version: 1,\n documentId,\n organizationId,\n epoch: 1,\n previousManifestHash: null,\n eventHash,\n linkedContainerIds: [targetContainerId],\n };\n const manifest = await deriveDocumentLinkSetManifest(state);\n const manifestHash = await computeAccessManifestHash(manifest);\n const targetHash = await computeDocumentContentKeyTargetHash(targets);\n\n return {\n body,\n documentId,\n event,\n eventHash,\n manifest,\n manifestHash,\n request: {\n event: readCanonicalRecord(event, \"Document create event\"),\n body: readCanonicalRecord(body, \"Document create body\"),\n expectedManifestHash: manifestHash,\n manifest: readCanonicalRecord(manifest, \"Document create manifest\"),\n previousManifest: null,\n targetContainerPathRefs: containerPathRefs(containerProjection.path),\n contentKeyBundle: {\n contentKeyEpoch,\n linkSetManifestHash: manifestHash,\n targetHash,\n targets: targetEnvelopesForRequest,\n },\n },\n state,\n targetHash,\n targets: sortDocumentTargets(targets),\n };\n}\n\nexport async function buildDocumentLinkSetEventPlan(input: {\n blobRewraps: DocumentLinkAccessEventBody[\"blobRewraps\"];\n author: DocumentCreateAuthor;\n eventId: string;\n operation: DocumentLinkSetMutationOperation;\n // The document's existing organization (from its manifest). Link/unlink does\n // not change ownership, so the event keeps the document's org, which is the\n // container's org — never the acting member's personal org.\n organizationId: string;\n signedAt: string;\n targetContainerPathRefs: readonly ContainerManifestRef[];\n targetState: DocumentLinkSetTargetState;\n writerProjection: DocumentWriterProjectionResponse;\n}): Promise<DocumentLinkSetEventPlan> {\n const eventType =\n input.operation === \"link\" ? \"document.link\" : \"document.unlink\";\n const body: DocumentLinkSetMutationBody = {\n blobRewraps: input.blobRewraps,\n eventType,\n containerId: input.targetState.target.containerId,\n containerManifestHash: input.targetState.target.containerManifestHash,\n };\n const bodyHash = await computeAccessEventBodyHash(\n readCanonicalJson(body, \"Document link-set body\"),\n );\n const authorizingContainerPathRefs = authorizingContainerPathRefsForLinkSet({\n operation: input.operation,\n targetContainerId: input.targetState.target.containerId,\n writerProjection: input.writerProjection,\n });\n const dependencyManifestHashes = uniqueSortedStrings(\n [\n ...input.targetContainerPathRefs,\n ...authorizingContainerPathRefs.flat(),\n ].map((ref) => ref.manifestHash),\n );\n const unsignedEvent: UnsignedAccessEvent = {\n version: 1,\n eventId: input.eventId,\n eventType,\n objectKind: \"document\",\n objectId: input.writerProjection.documentId,\n organizationId: input.organizationId,\n previousManifestHash: input.writerProjection.documentManifest.manifestHash,\n dependencyManifestHashes,\n bodyHash,\n signerUserId: input.author.signerUserId,\n signerDeviceId: input.author.signerDeviceId,\n signerKeyFingerprint: input.author.signerKeyFingerprint,\n signedAt: input.signedAt,\n };\n const event = await signAccessEvent(\n unsignedEvent,\n input.author.signerPrivateKey,\n );\n const eventHash = await computeAccessEventHash(event);\n\n return {\n authorizingContainerPathRefs,\n body,\n event,\n eventHash,\n };\n}\n"]}
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["events.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,0BAA0B,EAC1B,sBAAsB,EACtB,yBAAyB,EACzB,mCAAmC,EAGnC,6BAA6B,EAC7B,eAAe,GAEhB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EACL,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,sCAAsC,EACtC,iBAAiB,EACjB,2BAA2B,EAC3B,oBAAoB,GACrB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAWrE,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,EAC5C,MAAM,EACN,mBAAmB,EACnB,eAAe,GAAG,CAAC,EACnB,UAAU,GAAG,MAAM,CAAC,UAAU,EAAE,EAChC,OAAO,GAAG,MAAM,CAAC,UAAU,EAAE,EAC7B,QAAQ,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EACnC,eAAe,GACc;IAC7B,4EAA4E;IAC5E,6EAA6E;IAC7E,4EAA4E;IAC5E,MAAM,cAAc,GAAG,mBAAmB,CAAC,cAAc,CAAC;IAE1D,MAAM,OAAO,GAAG,2BAA2B,CAAC,mBAAmB,CAAC,CAAC;IACjE,MAAM,yBAAyB,GAAG,oBAAoB,CACpD,OAAO,EACP,eAAe,CAChB,CAAC;IACF,MAAM,2BAA2B,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,qBAAqB,CAAC;IACtE,MAAM,iBAAiB,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC;IAClD,IAAI,CAAC,2BAA2B,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACvD,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC3D,CAAC;IAED,MAAM,IAAI,GAAgC;QACxC,WAAW,EAAE,EAAE;QACf,SAAS,EAAE,eAAe;QAC1B,WAAW,EAAE,iBAAiB;QAC9B,qBAAqB,EAAE,2BAA2B;KACnD,CAAC;IACF,MAAM,QAAQ,GAAG,MAAM,0BAA0B,CAC/C,iBAAiB,CAAC,IAAI,EAAE,sBAAsB,CAAC,CAChD,CAAC;IACF,MAAM,aAAa,GAAwB;QACzC,OAAO,EAAE,CAAC;QACV,OAAO;QACP,SAAS,EAAE,eAAe;QAC1B,UAAU,EAAE,UAAU;QACtB,QAAQ,EAAE,UAAU;QACpB,cAAc;QACd,oBAAoB,EAAE,IAAI;QAC1B,wBAAwB,EAAE,mBAAmB,CAC3C,mBAAmB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAC9D;QACD,QAAQ;QACR,YAAY,EAAE,MAAM,CAAC,YAAY;QACjC,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,oBAAoB,EAAE,MAAM,CAAC,oBAAoB;QACjD,QAAQ;KACT,CAAC;IACF,MAAM,KAAK,GAAG,MAAM,eAAe,CAAC,aAAa,EAAE,MAAM,CAAC,gBAAgB,CAAC,CAAC;IAC5E,MAAM,SAAS,GAAG,MAAM,sBAAsB,CAAC,KAAK,CAAC,CAAC;IACtD,MAAM,KAAK,GAAiC;QAC1C,OAAO,EAAE,CAAC;QACV,UAAU;QACV,cAAc;QACd,KAAK,EAAE,CAAC;QACR,oBAAoB,EAAE,IAAI;QAC1B,SAAS;QACT,kBAAkB,EAAE,CAAC,iBAAiB,CAAC;KACxC,CAAC;IACF,MAAM,QAAQ,GAAG,MAAM,6BAA6B,CAAC,KAAK,CAAC,CAAC;IAC5D,MAAM,YAAY,GAAG,MAAM,yBAAyB,CAAC,QAAQ,CAAC,CAAC;IAC/D,MAAM,UAAU,GAAG,MAAM,mCAAmC,CAAC,OAAO,CAAC,CAAC;IAEtE,OAAO;QACL,IAAI;QACJ,UAAU;QACV,KAAK;QACL,SAAS;QACT,QAAQ;QACR,YAAY;QACZ,OAAO,EAAE;YACP,KAAK,EAAE,mBAAmB,CAAC,KAAK,EAAE,uBAAuB,CAAC;YAC1D,IAAI,EAAE,mBAAmB,CAAC,IAAI,EAAE,sBAAsB,CAAC;YACvD,oBAAoB,EAAE,YAAY;YAClC,QAAQ,EAAE,mBAAmB,CAAC,QAAQ,EAAE,0BAA0B,CAAC;YACnE,uBAAuB,EAAE,iBAAiB,CAAC,mBAAmB,CAAC,IAAI,CAAC;YACpE,gBAAgB,EAAE;gBAChB,eAAe;gBACf,mBAAmB,EAAE,YAAY;gBACjC,UAAU;gBACV,OAAO,EAAE,yBAAyB;aACnC;SACF;QACD,KAAK;QACL,UAAU;QACV,OAAO,EAAE,mBAAmB,CAAC,OAAO,CAAC;KACtC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,6BAA6B,CAAC,KAanD;IACC,MAAM,SAAS,GACb,KAAK,CAAC,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,iBAAiB,CAAC;IACnE,MAAM,IAAI,GAAgC;QACxC,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,SAAS;QACT,WAAW,EAAE,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,WAAW;QACjD,qBAAqB,EAAE,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,qBAAqB;KACtE,CAAC;IACF,MAAM,QAAQ,GAAG,MAAM,0BAA0B,CAC/C,iBAAiB,CAAC,IAAI,EAAE,wBAAwB,CAAC,CAClD,CAAC;IACF,MAAM,4BAA4B,GAAG,sCAAsC,CAAC;QAC1E,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,iBAAiB,EAAE,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,WAAW;QACvD,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;KACzC,CAAC,CAAC;IACH,MAAM,wBAAwB,GAAG,mBAAmB,CAClD;QACE,GAAG,KAAK,CAAC,uBAAuB;QAChC,GAAG,4BAA4B,CAAC,IAAI,EAAE;KACvC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,YAAY,CAAC,CACjC,CAAC;IACF,MAAM,aAAa,GAAwB;QACzC,OAAO,EAAE,CAAC;QACV,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,SAAS;QACT,UAAU,EAAE,UAAU;QACtB,QAAQ,EAAE,KAAK,CAAC,gBAAgB,CAAC,UAAU;QAC3C,cAAc,EAAE,KAAK,CAAC,cAAc;QACpC,oBAAoB,EAAE,KAAK,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,YAAY;QAC1E,wBAAwB;QACxB,QAAQ;QACR,YAAY,EAAE,KAAK,CAAC,MAAM,CAAC,YAAY;QACvC,cAAc,EAAE,KAAK,CAAC,MAAM,CAAC,cAAc;QAC3C,oBAAoB,EAAE,KAAK,CAAC,MAAM,CAAC,oBAAoB;QACvD,QAAQ,EAAE,KAAK,CAAC,QAAQ;KACzB,CAAC;IACF,MAAM,KAAK,GAAG,MAAM,eAAe,CACjC,aAAa,EACb,KAAK,CAAC,MAAM,CAAC,gBAAgB,CAC9B,CAAC;IACF,MAAM,SAAS,GAAG,MAAM,sBAAsB,CAAC,KAAK,CAAC,CAAC;IAEtD,OAAO;QACL,4BAA4B;QAC5B,IAAI;QACJ,KAAK;QACL,SAAS;KACV,CAAC;AACJ,CAAC","sourcesContent":["import {\n computeAccessEventBodyHash,\n computeAccessEventHash,\n computeAccessManifestHash,\n computeDocumentContentKeyTargetHash,\n type DocumentLinkAccessEventBody,\n type DocumentLinkSetManifestState,\n deriveDocumentLinkSetManifest,\n signAccessEvent,\n type UnsignedAccessEvent,\n} from \"@tearleads/crypto\";\nimport type { ContainerManifestRef } from \"@tearleads/validators/request\";\nimport type { DocumentWriterProjectionResponse } from \"@tearleads/validators/response\";\nimport {\n readCanonicalJson,\n readCanonicalRecord,\n} from \"../../keyingCanonicalJson\";\nimport {\n authorizingContainerPathRefsForLinkSet,\n containerPathRefs,\n deriveDocumentCreateTargets,\n mergeTargetEnvelopes,\n} from \"./projection\";\nimport { sortDocumentTargets, uniqueSortedStrings } from \"./readers\";\nimport type {\n BuildDocumentCreatePlanInput,\n DocumentCreateAuthor,\n DocumentCreatePlan,\n DocumentLinkSetEventPlan,\n DocumentLinkSetMutationBody,\n DocumentLinkSetMutationOperation,\n DocumentLinkSetTargetState,\n} from \"./types\";\n\nexport async function buildDocumentCreatePlan({\n author,\n containerProjection,\n contentKeyEpoch = 1,\n documentId = crypto.randomUUID(),\n eventId = crypto.randomUUID(),\n signedAt = new Date().toISOString(),\n targetEnvelopes,\n}: BuildDocumentCreatePlanInput): Promise<DocumentCreatePlan> {\n // The document belongs to its container's organization, not the author's. A\n // member authoring a document under another org's shared container creates a\n // document owned by that org; the author supplies only the signer identity.\n const organizationId = containerProjection.organizationId;\n\n const targets = deriveDocumentCreateTargets(containerProjection);\n const targetEnvelopesForRequest = mergeTargetEnvelopes(\n targets,\n targetEnvelopes,\n );\n const targetContainerManifestHash = targets[0]?.containerManifestHash;\n const targetContainerId = targets[0]?.containerId;\n if (!targetContainerManifestHash || !targetContainerId) {\n throw new Error(\"Document create target is unavailable\");\n }\n\n const body: DocumentLinkAccessEventBody = {\n blobRewraps: [],\n eventType: \"document.link\",\n containerId: targetContainerId,\n containerManifestHash: targetContainerManifestHash,\n };\n const bodyHash = await computeAccessEventBodyHash(\n readCanonicalJson(body, \"Document create body\"),\n );\n const unsignedEvent: UnsignedAccessEvent = {\n version: 1,\n eventId,\n eventType: \"document.link\",\n objectKind: \"document\",\n objectId: documentId,\n organizationId,\n previousManifestHash: null,\n dependencyManifestHashes: uniqueSortedStrings(\n containerProjection.path.map((bundle) => bundle.manifestHash),\n ),\n bodyHash,\n signerUserId: author.signerUserId,\n signerDeviceId: author.signerDeviceId,\n signerKeyFingerprint: author.signerKeyFingerprint,\n signedAt,\n };\n const event = await signAccessEvent(unsignedEvent, author.signerPrivateKey);\n const eventHash = await computeAccessEventHash(event);\n const state: DocumentLinkSetManifestState = {\n version: 1,\n documentId,\n organizationId,\n epoch: 1,\n previousManifestHash: null,\n eventHash,\n linkedContainerIds: [targetContainerId],\n };\n const manifest = await deriveDocumentLinkSetManifest(state);\n const manifestHash = await computeAccessManifestHash(manifest);\n const targetHash = await computeDocumentContentKeyTargetHash(targets);\n\n return {\n body,\n documentId,\n event,\n eventHash,\n manifest,\n manifestHash,\n request: {\n event: readCanonicalRecord(event, \"Document create event\"),\n body: readCanonicalRecord(body, \"Document create body\"),\n expectedManifestHash: manifestHash,\n manifest: readCanonicalRecord(manifest, \"Document create manifest\"),\n targetContainerPathRefs: containerPathRefs(containerProjection.path),\n contentKeyBundle: {\n contentKeyEpoch,\n linkSetManifestHash: manifestHash,\n targetHash,\n targets: targetEnvelopesForRequest,\n },\n },\n state,\n targetHash,\n targets: sortDocumentTargets(targets),\n };\n}\n\nexport async function buildDocumentLinkSetEventPlan(input: {\n blobRewraps: DocumentLinkAccessEventBody[\"blobRewraps\"];\n author: DocumentCreateAuthor;\n eventId: string;\n operation: DocumentLinkSetMutationOperation;\n // The document's existing organization (from its manifest). Link/unlink does\n // not change ownership, so the event keeps the document's org, which is the\n // container's org — never the acting member's personal org.\n organizationId: string;\n signedAt: string;\n targetContainerPathRefs: readonly ContainerManifestRef[];\n targetState: DocumentLinkSetTargetState;\n writerProjection: DocumentWriterProjectionResponse;\n}): Promise<DocumentLinkSetEventPlan> {\n const eventType =\n input.operation === \"link\" ? \"document.link\" : \"document.unlink\";\n const body: DocumentLinkSetMutationBody = {\n blobRewraps: input.blobRewraps,\n eventType,\n containerId: input.targetState.target.containerId,\n containerManifestHash: input.targetState.target.containerManifestHash,\n };\n const bodyHash = await computeAccessEventBodyHash(\n readCanonicalJson(body, \"Document link-set body\"),\n );\n const authorizingContainerPathRefs = authorizingContainerPathRefsForLinkSet({\n operation: input.operation,\n targetContainerId: input.targetState.target.containerId,\n writerProjection: input.writerProjection,\n });\n const dependencyManifestHashes = uniqueSortedStrings(\n [\n ...input.targetContainerPathRefs,\n ...authorizingContainerPathRefs.flat(),\n ].map((ref) => ref.manifestHash),\n );\n const unsignedEvent: UnsignedAccessEvent = {\n version: 1,\n eventId: input.eventId,\n eventType,\n objectKind: \"document\",\n objectId: input.writerProjection.documentId,\n organizationId: input.organizationId,\n previousManifestHash: input.writerProjection.documentManifest.manifestHash,\n dependencyManifestHashes,\n bodyHash,\n signerUserId: input.author.signerUserId,\n signerDeviceId: input.author.signerDeviceId,\n signerKeyFingerprint: input.author.signerKeyFingerprint,\n signedAt: input.signedAt,\n };\n const event = await signAccessEvent(\n unsignedEvent,\n input.author.signerPrivateKey,\n );\n const eventHash = await computeAccessEventHash(event);\n\n return {\n authorizingContainerPathRefs,\n body,\n event,\n eventHash,\n };\n}\n"]}
@@ -1,12 +1,12 @@
1
- import { and, eq, inArray } from "drizzle-orm";
1
+ import { eq } from "drizzle-orm";
2
+ import { hasQueuedDocumentUpdates, settleQueuedDocumentUpdatesInTransaction, } from "../../sqlite/documentPendingUpdatePersistence.js";
2
3
  import { enqueueDocumentPendingUpdate, ensureDocumentProjectionTables, ensureDocumentTables, } from "../../sqlite/documentPersistence.js";
3
- import { containerCreateIntentTables, containerHydrationTombstones, containerMoveIntentTables, containers, documentContainerProjectionTables, documentPendingUpdates, } from "../../sqlite/schema.js";
4
+ import { containerCreateIntentTables, containerHydrationTombstones, containerMoveIntentTables, containers, documentContainerProjectionTables, } from "../../sqlite/schema.js";
4
5
  import { getClientSQLitePersistenceRuntime, } from "../../sqlite/sqlitePersistenceRuntime.js";
5
6
  import { ensureSqlTables, runOncePerConnection, runSerializedSqlMutation, } from "../../sqlite/sqlSchema.js";
6
7
  import { ensureContainerTables, loadContainerById, loadContainers as loadContainerRecords, } from "../containers/containerPersistence.js";
7
8
  import { sqlContainerSyncWatermarkPersistence } from "../containers/containerSyncWatermarkPersistence.js";
8
9
  import { getLatestTimestamp } from "../latestTimestamp.js";
9
- import { CONTAINER_METADATA_APP_KIND } from "./dormantContainerMetadata.js";
10
10
  import { claimDormantMetadataSweepAttempt, completeDormantMetadataSweepRequest, listDormantMetadataSweepRequests, } from "./dormantMetadataSweep.js";
11
11
  export { CONTAINER_METADATA_APP_KIND } from "./dormantContainerMetadata.js";
12
12
  import { deleteStoredContainers } from "./containerDeletionPersistence.js";
@@ -49,14 +49,6 @@ async function saveStoredContainer(execSql, container, record, options) {
49
49
  return outcome.result ?? container;
50
50
  });
51
51
  }
52
- async function hasPendingContainerMetadataUpdates(input) {
53
- const rows = await input.tx
54
- .select({ id: documentPendingUpdates.id })
55
- .from(documentPendingUpdates)
56
- .where(and(eq(documentPendingUpdates.appKind, CONTAINER_METADATA_APP_KIND), eq(documentPendingUpdates.localId, input.containerId)))
57
- .limit(1);
58
- return rows.length > 0;
59
- }
60
52
  export const sqlContainerContentsPersistence = {
61
53
  ...containerIntentPersistence,
62
54
  ...containerMetadataPullContinuationPersistence,
@@ -166,20 +158,12 @@ export const sqlContainerContentsPersistence = {
166
158
  return saveStoredContainer(execSql, container, record, options);
167
159
  },
168
160
  async saveContainerAndDeletePendingUpdates(execSql, container, record, pendingUpdateIds) {
169
- const uniquePendingUpdateIds = [...new Set(pendingUpdateIds)];
170
161
  return runSerializedSqlMutation(execSql, async (lockedExecSql) => {
171
162
  const localUpdatedAt = new Date().toISOString();
172
163
  return getClientSQLitePersistenceRuntime(lockedExecSql).transaction(async (tx) => {
173
- if (uniquePendingUpdateIds.length > 0) {
174
- await tx
175
- .delete(documentPendingUpdates)
176
- .where(and(eq(documentPendingUpdates.appKind, CONTAINER_METADATA_APP_KIND), eq(documentPendingUpdates.localId, container.id), inArray(documentPendingUpdates.id, uniquePendingUpdateIds)))
177
- .run();
178
- }
179
- const hasRemainingPendingUpdates = await hasPendingContainerMetadataUpdates({
180
- containerId: container.id,
181
- tx,
182
- });
164
+ const scope = getContainerMetadataScope(container.id);
165
+ await settleQueuedDocumentUpdatesInTransaction(tx, scope, pendingUpdateIds);
166
+ const hasRemainingPendingUpdates = await hasQueuedDocumentUpdates(tx, scope);
183
167
  const containerToSave = hasRemainingPendingUpdates
184
168
  ? container
185
169
  : {
@@ -1 +1 @@
1
- {"version":3,"file":"containerContentsPersistence.js","sourceRoot":"","sources":["containerContentsPersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import { and, eq, inArray } from \"drizzle-orm\";\nimport {\n enqueueDocumentPendingUpdate,\n ensureDocumentProjectionTables,\n ensureDocumentTables,\n} from \"../../sqlite/documentPersistence\";\nimport {\n containerCreateIntentTables,\n containerHydrationTombstones,\n containerMoveIntentTables,\n containers,\n documentContainerProjectionTables,\n documentPendingUpdates,\n} from \"../../sqlite/schema\";\nimport {\n type ClientSQLiteTransactionScope,\n getClientSQLitePersistenceRuntime,\n} from \"../../sqlite/sqlitePersistenceRuntime\";\nimport {\n ensureSqlTables,\n runOncePerConnection,\n runSerializedSqlMutation,\n} from \"../../sqlite/sqlSchema\";\nimport {\n ensureContainerTables,\n loadContainerById,\n loadContainers as loadContainerRecords,\n} from \"../containers/containerPersistence\";\nimport { sqlContainerSyncWatermarkPersistence } from \"../containers/containerSyncWatermarkPersistence\";\nimport { getLatestTimestamp } from \"../latestTimestamp\";\nimport { CONTAINER_METADATA_APP_KIND } from \"./dormantContainerMetadata\";\nimport {\n claimDormantMetadataSweepAttempt,\n completeDormantMetadataSweepRequest,\n listDormantMetadataSweepRequests,\n} from \"./dormantMetadataSweep\";\n\nexport type {\n ContainerContentsPersistence,\n ContainerCreateIntentRecord,\n ContainerHydrationTombstone,\n ContainerMetadataRecord,\n ContainerMoveIntentRecord,\n LocalRootDescendantReparentInput,\n StoredContainerState,\n} from \"./containerContentsPersistenceTypes\";\nexport { CONTAINER_METADATA_APP_KIND } from \"./dormantContainerMetadata\";\n\nimport type {\n ContainerContentsPersistence,\n ContainerMetadataRecord,\n SaveContainerOptions,\n SaveContainerWithPendingUpdateOptions,\n} from \"./containerContentsPersistenceTypes\";\nimport { deleteStoredContainers } from \"./containerDeletionPersistence\";\nimport {\n commitStoredHydratedContainer,\n loadStoredHeldContainerBinding,\n} from \"./containerHydrationPersistence\";\nimport { containerIntentPersistence } from \"./containerIntentPersistence\";\nimport {\n commitStoredMetadataMutation,\n settleStoredMetadataPendingUpdates,\n} from \"./containerMetadataMutationPersistence\";\nimport { containerMetadataPullContinuationPersistence } from \"./containerMetadataPullContinuationPersistence\";\nimport {\n getContainerMetadataScope,\n saveContainerContentsContainerRows,\n selectContainerMetadataRecord,\n} from \"./containerMetadataRows\";\nimport { abandonStoredMoveIntentRevision } from \"./containerMoveAbandonPersistence\";\nimport { containerPendingUpdatePersistence } from \"./containerPendingUpdatePersistence\";\nimport { rebindStoredHeldContainer } from \"./containerRebindPersistence\";\nimport { containerReconcilePersistence } from \"./containerReconcilePersistence\";\nimport { isSupersededContainerBinding } from \"./supersededContainerBindings\";\n\nasync function saveStoredContainer(\n execSql: Parameters<ContainerContentsPersistence[\"saveContainer\"]>[0],\n container: Parameters<ContainerContentsPersistence[\"saveContainer\"]>[1],\n record: ContainerMetadataRecord | null,\n options?:\n | SaveContainerOptions\n | SaveContainerWithPendingUpdateOptions\n | undefined,\n) {\n return runSerializedSqlMutation(execSql, async (lockedExecSql) => {\n const localUpdatedAt =\n options?.localUpdatedAt ?? options?.updatedAt ?? new Date().toISOString();\n const runtime = getClientSQLitePersistenceRuntime(lockedExecSql);\n const save = async (tx: ClientSQLiteTransactionScope) => {\n const saved = await saveContainerContentsContainerRows({\n container,\n createIntent: options?.createIntent,\n moveIntent: options?.moveIntent,\n record,\n serverTimestamps: options?.serverTimestamps,\n tx,\n localUpdatedAt,\n });\n if (options && \"pendingUpdate\" in options) {\n await enqueueDocumentPendingUpdate(\n lockedExecSql,\n getContainerMetadataScope(container.id),\n options.pendingUpdate,\n );\n }\n return saved;\n };\n if (!options?.stillCurrent) {\n return runtime.transaction(save);\n }\n const outcome = await runtime.guardedTransaction(\n save,\n options.stillCurrent,\n { behavior: \"immediate\" },\n );\n // Guarded callers recheck the same monotonic generation immediately after\n // this await. Returning the untouched candidate keeps the long-standing\n // non-null save contract while the transaction itself remains rolled back.\n return outcome.result ?? container;\n });\n}\n\nasync function hasPendingContainerMetadataUpdates(input: {\n tx: ClientSQLiteTransactionScope;\n containerId: string;\n}): Promise<boolean> {\n const rows = await input.tx\n .select({ id: documentPendingUpdates.id })\n .from(documentPendingUpdates)\n .where(\n and(\n eq(documentPendingUpdates.appKind, CONTAINER_METADATA_APP_KIND),\n eq(documentPendingUpdates.localId, input.containerId),\n ),\n )\n .limit(1);\n\n return rows.length > 0;\n}\n\nexport const sqlContainerContentsPersistence: ContainerContentsPersistence = {\n ...containerIntentPersistence,\n ...containerMetadataPullContinuationPersistence,\n commitHydratedContainer: commitStoredHydratedContainer,\n commitMetadataMutation: commitStoredMetadataMutation,\n settleAcceptedMetadataPendingUpdates: settleStoredMetadataPendingUpdates,\n listDormantMetadataSweepRequests,\n ...containerPendingUpdatePersistence,\n ...containerReconcilePersistence,\n claimDormantMetadataSweepAttempt,\n completeDormantMetadataSweepRequest,\n async containerExists(execSql, containerId) {\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n const { db } = getClientSQLitePersistenceRuntime(execSql);\n const rows = await db\n .select({ id: containers.id })\n .from(containers)\n .where(eq(containers.id, containerId))\n .limit(1);\n return rows.length > 0;\n },\n async deleteContainer(execSql, containerId, options) {\n await sqlContainerContentsPersistence.deleteContainers(execSql, [\n {\n containerId,\n reason: options?.reason ?? \"deleted\",\n updatedAt: options?.updatedAt ?? new Date().toISOString(),\n },\n ]);\n },\n async deleteContainers(execSql, removals, options) {\n return deleteStoredContainers(execSql, removals, options);\n },\n async ensureSchema(execSql) {\n // Once ensured on this connection, skip the outer mutation lock entirely:\n // ensureSchema runs on every query path, and re-acquiring the lock just to\n // no-op would queue reads behind unrelated writes.\n await runOncePerConnection(execSql, \"ensure:container-contents\", () =>\n runSerializedSqlMutation(execSql, async (lockedExecSql) => {\n await ensureContainerTables(lockedExecSql);\n await ensureDocumentTables(lockedExecSql);\n await ensureSqlTables(lockedExecSql, containerCreateIntentTables);\n await ensureSqlTables(lockedExecSql, containerMoveIntentTables);\n await ensureSqlTables(lockedExecSql, documentContainerProjectionTables);\n await ensureDocumentProjectionTables(lockedExecSql);\n await sqlContainerSyncWatermarkPersistence.ensureSchema(lockedExecSql);\n }),\n );\n },\n async loadHeldContainerBinding(execSql, containerId) {\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n return loadStoredHeldContainerBinding(execSql, containerId);\n },\n async isSupersededContainerBinding(execSql, input) {\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n return isSupersededContainerBinding(execSql, input);\n },\n async abandonMoveIntentRevision(execSql, input) {\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n return abandonStoredMoveIntentRevision(execSql, input);\n },\n async rebindHeldContainer(execSql, input) {\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n return rebindStoredHeldContainer(execSql, input);\n },\n async loadContainerMetadataRecord(execSql, containerId) {\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n return selectContainerMetadataRecord(execSql, containerId);\n },\n async loadContainerHydrationTombstones(execSql) {\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n const { db } = getClientSQLitePersistenceRuntime(execSql);\n const rows = await db\n .select({\n containerId: containerHydrationTombstones.containerId,\n generation: containerHydrationTombstones.generation,\n reason: containerHydrationTombstones.reason,\n updatedAt: containerHydrationTombstones.updatedAt,\n })\n .from(containerHydrationTombstones)\n .where(eq(containerHydrationTombstones.cleared, false));\n return rows.flatMap((row) =>\n row.reason === \"access_revoked\" || row.reason === \"deleted\"\n ? [{ ...row, reason: row.reason }]\n : [],\n );\n },\n async loadContainers(execSql) {\n const containers = await loadContainerRecords(execSql);\n const storedContainers = await Promise.all(\n containers.map(async (container) => ({\n container,\n record: await selectContainerMetadataRecord(execSql, container.id),\n })),\n );\n\n return storedContainers;\n },\n async loadContainerMetadataState(execSql, containerId) {\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n const container = await loadContainerById(execSql, containerId);\n if (!container) {\n return null;\n }\n return {\n container,\n record: await selectContainerMetadataRecord(execSql, containerId),\n };\n },\n async saveContainer(execSql, container, record, options) {\n return saveStoredContainer(execSql, container, record, options);\n },\n async saveContainerWithPendingUpdate(execSql, container, record, options) {\n return saveStoredContainer(execSql, container, record, options);\n },\n async saveContainerAndDeletePendingUpdates(\n execSql,\n container,\n record,\n pendingUpdateIds,\n ) {\n const uniquePendingUpdateIds = [...new Set(pendingUpdateIds)];\n\n return runSerializedSqlMutation(execSql, async (lockedExecSql) => {\n const localUpdatedAt = new Date().toISOString();\n return getClientSQLitePersistenceRuntime(lockedExecSql).transaction(\n async (tx) => {\n if (uniquePendingUpdateIds.length > 0) {\n await tx\n .delete(documentPendingUpdates)\n .where(\n and(\n eq(\n documentPendingUpdates.appKind,\n CONTAINER_METADATA_APP_KIND,\n ),\n eq(documentPendingUpdates.localId, container.id),\n inArray(documentPendingUpdates.id, uniquePendingUpdateIds),\n ),\n )\n .run();\n }\n\n const hasRemainingPendingUpdates =\n await hasPendingContainerMetadataUpdates({\n containerId: container.id,\n tx,\n });\n const containerToSave = hasRemainingPendingUpdates\n ? container\n : {\n ...container,\n serverUpdatedAt: getLatestTimestamp(\n container.serverUpdatedAt,\n localUpdatedAt,\n ),\n };\n\n return saveContainerContentsContainerRows({\n container: containerToSave,\n record,\n tx,\n localUpdatedAt,\n });\n },\n );\n });\n },\n};\n"]}
1
+ {"version":3,"file":"containerContentsPersistence.js","sourceRoot":"","sources":["containerContentsPersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import { eq } from \"drizzle-orm\";\nimport {\n hasQueuedDocumentUpdates,\n settleQueuedDocumentUpdatesInTransaction,\n} from \"../../sqlite/documentPendingUpdatePersistence\";\nimport {\n enqueueDocumentPendingUpdate,\n ensureDocumentProjectionTables,\n ensureDocumentTables,\n} from \"../../sqlite/documentPersistence\";\nimport {\n containerCreateIntentTables,\n containerHydrationTombstones,\n containerMoveIntentTables,\n containers,\n documentContainerProjectionTables,\n} from \"../../sqlite/schema\";\nimport {\n type ClientSQLiteTransactionScope,\n getClientSQLitePersistenceRuntime,\n} from \"../../sqlite/sqlitePersistenceRuntime\";\nimport {\n ensureSqlTables,\n runOncePerConnection,\n runSerializedSqlMutation,\n} from \"../../sqlite/sqlSchema\";\nimport {\n ensureContainerTables,\n loadContainerById,\n loadContainers as loadContainerRecords,\n} from \"../containers/containerPersistence\";\nimport { sqlContainerSyncWatermarkPersistence } from \"../containers/containerSyncWatermarkPersistence\";\nimport { getLatestTimestamp } from \"../latestTimestamp\";\nimport {\n claimDormantMetadataSweepAttempt,\n completeDormantMetadataSweepRequest,\n listDormantMetadataSweepRequests,\n} from \"./dormantMetadataSweep\";\n\nexport type {\n ContainerContentsPersistence,\n ContainerCreateIntentRecord,\n ContainerHydrationTombstone,\n ContainerMetadataRecord,\n ContainerMoveIntentRecord,\n LocalRootDescendantReparentInput,\n StoredContainerState,\n} from \"./containerContentsPersistenceTypes\";\nexport { CONTAINER_METADATA_APP_KIND } from \"./dormantContainerMetadata\";\n\nimport type {\n ContainerContentsPersistence,\n ContainerMetadataRecord,\n SaveContainerOptions,\n SaveContainerWithPendingUpdateOptions,\n} from \"./containerContentsPersistenceTypes\";\nimport { deleteStoredContainers } from \"./containerDeletionPersistence\";\nimport {\n commitStoredHydratedContainer,\n loadStoredHeldContainerBinding,\n} from \"./containerHydrationPersistence\";\nimport { containerIntentPersistence } from \"./containerIntentPersistence\";\nimport {\n commitStoredMetadataMutation,\n settleStoredMetadataPendingUpdates,\n} from \"./containerMetadataMutationPersistence\";\nimport { containerMetadataPullContinuationPersistence } from \"./containerMetadataPullContinuationPersistence\";\nimport {\n getContainerMetadataScope,\n saveContainerContentsContainerRows,\n selectContainerMetadataRecord,\n} from \"./containerMetadataRows\";\nimport { abandonStoredMoveIntentRevision } from \"./containerMoveAbandonPersistence\";\nimport { containerPendingUpdatePersistence } from \"./containerPendingUpdatePersistence\";\nimport { rebindStoredHeldContainer } from \"./containerRebindPersistence\";\nimport { containerReconcilePersistence } from \"./containerReconcilePersistence\";\nimport { isSupersededContainerBinding } from \"./supersededContainerBindings\";\n\nasync function saveStoredContainer(\n execSql: Parameters<ContainerContentsPersistence[\"saveContainer\"]>[0],\n container: Parameters<ContainerContentsPersistence[\"saveContainer\"]>[1],\n record: ContainerMetadataRecord | null,\n options?:\n | SaveContainerOptions\n | SaveContainerWithPendingUpdateOptions\n | undefined,\n) {\n return runSerializedSqlMutation(execSql, async (lockedExecSql) => {\n const localUpdatedAt =\n options?.localUpdatedAt ?? options?.updatedAt ?? new Date().toISOString();\n const runtime = getClientSQLitePersistenceRuntime(lockedExecSql);\n const save = async (tx: ClientSQLiteTransactionScope) => {\n const saved = await saveContainerContentsContainerRows({\n container,\n createIntent: options?.createIntent,\n moveIntent: options?.moveIntent,\n record,\n serverTimestamps: options?.serverTimestamps,\n tx,\n localUpdatedAt,\n });\n if (options && \"pendingUpdate\" in options) {\n await enqueueDocumentPendingUpdate(\n lockedExecSql,\n getContainerMetadataScope(container.id),\n options.pendingUpdate,\n );\n }\n return saved;\n };\n if (!options?.stillCurrent) {\n return runtime.transaction(save);\n }\n const outcome = await runtime.guardedTransaction(\n save,\n options.stillCurrent,\n { behavior: \"immediate\" },\n );\n // Guarded callers recheck the same monotonic generation immediately after\n // this await. Returning the untouched candidate keeps the long-standing\n // non-null save contract while the transaction itself remains rolled back.\n return outcome.result ?? container;\n });\n}\n\nexport const sqlContainerContentsPersistence: ContainerContentsPersistence = {\n ...containerIntentPersistence,\n ...containerMetadataPullContinuationPersistence,\n commitHydratedContainer: commitStoredHydratedContainer,\n commitMetadataMutation: commitStoredMetadataMutation,\n settleAcceptedMetadataPendingUpdates: settleStoredMetadataPendingUpdates,\n listDormantMetadataSweepRequests,\n ...containerPendingUpdatePersistence,\n ...containerReconcilePersistence,\n claimDormantMetadataSweepAttempt,\n completeDormantMetadataSweepRequest,\n async containerExists(execSql, containerId) {\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n const { db } = getClientSQLitePersistenceRuntime(execSql);\n const rows = await db\n .select({ id: containers.id })\n .from(containers)\n .where(eq(containers.id, containerId))\n .limit(1);\n return rows.length > 0;\n },\n async deleteContainer(execSql, containerId, options) {\n await sqlContainerContentsPersistence.deleteContainers(execSql, [\n {\n containerId,\n reason: options?.reason ?? \"deleted\",\n updatedAt: options?.updatedAt ?? new Date().toISOString(),\n },\n ]);\n },\n async deleteContainers(execSql, removals, options) {\n return deleteStoredContainers(execSql, removals, options);\n },\n async ensureSchema(execSql) {\n // Once ensured on this connection, skip the outer mutation lock entirely:\n // ensureSchema runs on every query path, and re-acquiring the lock just to\n // no-op would queue reads behind unrelated writes.\n await runOncePerConnection(execSql, \"ensure:container-contents\", () =>\n runSerializedSqlMutation(execSql, async (lockedExecSql) => {\n await ensureContainerTables(lockedExecSql);\n await ensureDocumentTables(lockedExecSql);\n await ensureSqlTables(lockedExecSql, containerCreateIntentTables);\n await ensureSqlTables(lockedExecSql, containerMoveIntentTables);\n await ensureSqlTables(lockedExecSql, documentContainerProjectionTables);\n await ensureDocumentProjectionTables(lockedExecSql);\n await sqlContainerSyncWatermarkPersistence.ensureSchema(lockedExecSql);\n }),\n );\n },\n async loadHeldContainerBinding(execSql, containerId) {\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n return loadStoredHeldContainerBinding(execSql, containerId);\n },\n async isSupersededContainerBinding(execSql, input) {\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n return isSupersededContainerBinding(execSql, input);\n },\n async abandonMoveIntentRevision(execSql, input) {\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n return abandonStoredMoveIntentRevision(execSql, input);\n },\n async rebindHeldContainer(execSql, input) {\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n return rebindStoredHeldContainer(execSql, input);\n },\n async loadContainerMetadataRecord(execSql, containerId) {\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n return selectContainerMetadataRecord(execSql, containerId);\n },\n async loadContainerHydrationTombstones(execSql) {\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n const { db } = getClientSQLitePersistenceRuntime(execSql);\n const rows = await db\n .select({\n containerId: containerHydrationTombstones.containerId,\n generation: containerHydrationTombstones.generation,\n reason: containerHydrationTombstones.reason,\n updatedAt: containerHydrationTombstones.updatedAt,\n })\n .from(containerHydrationTombstones)\n .where(eq(containerHydrationTombstones.cleared, false));\n return rows.flatMap((row) =>\n row.reason === \"access_revoked\" || row.reason === \"deleted\"\n ? [{ ...row, reason: row.reason }]\n : [],\n );\n },\n async loadContainers(execSql) {\n const containers = await loadContainerRecords(execSql);\n const storedContainers = await Promise.all(\n containers.map(async (container) => ({\n container,\n record: await selectContainerMetadataRecord(execSql, container.id),\n })),\n );\n\n return storedContainers;\n },\n async loadContainerMetadataState(execSql, containerId) {\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n const container = await loadContainerById(execSql, containerId);\n if (!container) {\n return null;\n }\n return {\n container,\n record: await selectContainerMetadataRecord(execSql, containerId),\n };\n },\n async saveContainer(execSql, container, record, options) {\n return saveStoredContainer(execSql, container, record, options);\n },\n async saveContainerWithPendingUpdate(execSql, container, record, options) {\n return saveStoredContainer(execSql, container, record, options);\n },\n async saveContainerAndDeletePendingUpdates(\n execSql,\n container,\n record,\n pendingUpdateIds,\n ) {\n return runSerializedSqlMutation(execSql, async (lockedExecSql) => {\n const localUpdatedAt = new Date().toISOString();\n return getClientSQLitePersistenceRuntime(lockedExecSql).transaction(\n async (tx) => {\n const scope = getContainerMetadataScope(container.id);\n await settleQueuedDocumentUpdatesInTransaction(\n tx,\n scope,\n pendingUpdateIds,\n );\n const hasRemainingPendingUpdates = await hasQueuedDocumentUpdates(\n tx,\n scope,\n );\n const containerToSave = hasRemainingPendingUpdates\n ? container\n : {\n ...container,\n serverUpdatedAt: getLatestTimestamp(\n container.serverUpdatedAt,\n localUpdatedAt,\n ),\n };\n\n return saveContainerContentsContainerRows({\n container: containerToSave,\n record,\n tx,\n localUpdatedAt,\n });\n },\n );\n });\n },\n};\n"]}
@@ -1,8 +1,9 @@
1
- import { and, eq, inArray } from "drizzle-orm";
1
+ import { and, eq } from "drizzle-orm";
2
2
  import { assertHeldContainerBinding, heldContainerBinding, } from "../../containers/containerBinding.js";
3
3
  import { documentSyncPullContinuationsEqual } from "../../documents/shared/pullContinuation.js";
4
+ import { hasQueuedDocumentUpdates, settleQueuedDocumentUpdatesInTransaction, } from "../../sqlite/documentPendingUpdatePersistence.js";
4
5
  import { enqueueDocumentPendingUpdate, } from "../../sqlite/documentPersistence.js";
5
- import { containerCreateIntents, containerMoveIntents, documentPendingUpdates, documentSyncFailures, } from "../../sqlite/schema.js";
6
+ import { containerCreateIntents, containerMoveIntents, documentSyncFailures, } from "../../sqlite/schema.js";
6
7
  import { getClientSQLitePersistenceRuntime, } from "../../sqlite/sqlitePersistenceRuntime.js";
7
8
  import { runSerializedSqlMutation } from "../../sqlite/sqlSchema.js";
8
9
  import { loadContainerById, } from "../containers/containerPersistence.js";
@@ -65,13 +66,7 @@ async function loadStoredContainerState(execSql, containerId) {
65
66
  };
66
67
  }
67
68
  async function deleteAcceptedPendingUpdates(tx, containerId, ids) {
68
- const uniqueIds = [...new Set(ids)];
69
- if (uniqueIds.length === 0)
70
- return;
71
- await tx
72
- .delete(documentPendingUpdates)
73
- .where(and(eq(documentPendingUpdates.appKind, CONTAINER_METADATA_APP_KIND), eq(documentPendingUpdates.localId, containerId), inArray(documentPendingUpdates.id, uniqueIds)))
74
- .run();
69
+ await settleQueuedDocumentUpdatesInTransaction(tx, getContainerMetadataScope(containerId), ids);
75
70
  }
76
71
  async function clearSyncFailure(tx, containerId) {
77
72
  await tx
@@ -80,12 +75,7 @@ async function clearSyncFailure(tx, containerId) {
80
75
  .run();
81
76
  }
82
77
  async function hasPendingUpdates(tx, containerId) {
83
- const rows = await tx
84
- .select({ id: documentPendingUpdates.id })
85
- .from(documentPendingUpdates)
86
- .where(and(eq(documentPendingUpdates.appKind, CONTAINER_METADATA_APP_KIND), eq(documentPendingUpdates.localId, containerId)))
87
- .limit(1);
88
- return rows.length > 0;
78
+ return hasQueuedDocumentUpdates(tx, getContainerMetadataScope(containerId));
89
79
  }
90
80
  async function hasPendingStructuralIntent(tx, containerId) {
91
81
  const pendingCreates = await tx
@@ -1 +1 @@
1
- {"version":3,"file":"containerMetadataMutationPersistence.js","sourceRoot":"","sources":["containerMetadataMutationPersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import { and, eq, inArray } from \"drizzle-orm\";\nimport {\n assertHeldContainerBinding,\n heldContainerBinding,\n} from \"../../containers/containerBinding\";\nimport { documentSyncPullContinuationsEqual } from \"../../documents/shared/pullContinuation\";\nimport {\n enqueueDocumentPendingUpdate,\n type PendingUpdateFields,\n} from \"../../sqlite/documentPersistence\";\nimport {\n containerCreateIntents,\n containerMoveIntents,\n documentPendingUpdates,\n documentSyncFailures,\n} from \"../../sqlite/schema\";\nimport {\n type ClientSQLiteTransactionScope,\n getClientSQLitePersistenceRuntime,\n} from \"../../sqlite/sqlitePersistenceRuntime\";\nimport { runSerializedSqlMutation } from \"../../sqlite/sqlSchema\";\nimport {\n type ContainerRecord,\n loadContainerById,\n} from \"../containers/containerPersistence\";\nimport type {\n ContainerContentsPersistence,\n ContainerMetadataRecord,\n StoredContainerState,\n} from \"./containerContentsPersistenceTypes\";\nimport { settleContainerCreateIntentRevision } from \"./containerCreateIntentSettlement\";\nimport {\n ContainerCreateIntentSupersededError,\n deleteContainerMoveIntentRevision,\n} from \"./containerIntentPersistence\";\nimport {\n getContainerMetadataScope,\n saveContainerContentsContainerRows,\n selectContainerMetadataRecord,\n} from \"./containerMetadataRows\";\nimport { CONTAINER_METADATA_APP_KIND } from \"./dormantContainerMetadata\";\n\nfunction sameNullableValue(\n left: string | null | undefined,\n right: string | null | undefined,\n): boolean {\n return (left ?? null) === (right ?? null);\n}\n\nfunction committedMetadataMutationResult(input: {\n container: ContainerRecord;\n createIntentSettled: boolean;\n moveIntentSettled: boolean;\n}) {\n return {\n committed: true as const,\n container: input.container,\n ...(input.createIntentSettled\n ? { createIntentSettled: true as const }\n : {}),\n ...(input.moveIntentSettled ? { moveIntentSettled: true as const } : {}),\n };\n}\n\nfunction sameMetadataSecurityIdentity(\n current: ContainerMetadataRecord,\n expected: ContainerMetadataRecord,\n): boolean {\n return (\n current.id === expected.id &&\n current.documentId === expected.documentId &&\n current.accessEpoch === expected.accessEpoch &&\n sameNullableValue(current.accessStateHash, expected.accessStateHash) &&\n sameNullableValue(current.contentKeyBundle, expected.contentKeyBundle) &&\n sameNullableValue(\n current.documentKekTargets,\n expected.documentKekTargets,\n ) &&\n sameNullableValue(\n current.documentManifestBundle,\n expected.documentManifestBundle,\n )\n );\n}\n\nfunction sameMetadataRecord(\n current: ContainerMetadataRecord,\n expected: ContainerMetadataRecord,\n): boolean {\n return (\n sameMetadataSecurityIdentity(current, expected) &&\n sameNullableValue(current.lastCommitLsn, expected.lastCommitLsn) &&\n current.metadataUpdates === expected.metadataUpdates &&\n current.snapshotEndVersion === expected.snapshotEndVersion &&\n documentSyncPullContinuationsEqual(\n current.pullContinuation,\n expected.pullContinuation,\n ) &&\n Boolean(current.pullContinuationRecoveryRequired) ===\n Boolean(expected.pullContinuationRecoveryRequired)\n );\n}\n\nfunction sameContainerRecord(\n current: ContainerRecord,\n expected: ContainerRecord,\n): boolean {\n return (\n current.id === expected.id &&\n current.parentId === expected.parentId &&\n current.organizationId === expected.organizationId &&\n current.metadataDocumentId === expected.metadataDocumentId &&\n (current.systemSlot ?? null) === (expected.systemSlot ?? null) &&\n (current.effectiveAccessLevel ?? null) ===\n (expected.effectiveAccessLevel ?? null) &&\n (current.localUpdatedAt ?? null) === (expected.localUpdatedAt ?? null) &&\n (current.serverCreatedAt ?? null) === (expected.serverCreatedAt ?? null) &&\n (current.serverUpdatedAt ?? null) === (expected.serverUpdatedAt ?? null) &&\n current.name === expected.name &&\n (current.icon ?? null) === (expected.icon ?? null)\n );\n}\n\nasync function loadStoredContainerState(\n execSql: Parameters<\n ContainerContentsPersistence[\"loadContainerMetadataState\"]\n >[0],\n containerId: string,\n): Promise<StoredContainerState | null> {\n const container = await loadContainerById(execSql, containerId);\n if (!container) return null;\n return {\n container,\n record: await selectContainerMetadataRecord(execSql, containerId),\n };\n}\n\nasync function deleteAcceptedPendingUpdates(\n tx: ClientSQLiteTransactionScope,\n containerId: string,\n ids: readonly string[],\n): Promise<void> {\n const uniqueIds = [...new Set(ids)];\n if (uniqueIds.length === 0) return;\n await tx\n .delete(documentPendingUpdates)\n .where(\n and(\n eq(documentPendingUpdates.appKind, CONTAINER_METADATA_APP_KIND),\n eq(documentPendingUpdates.localId, containerId),\n inArray(documentPendingUpdates.id, uniqueIds),\n ),\n )\n .run();\n}\n\nasync function clearSyncFailure(\n tx: ClientSQLiteTransactionScope,\n containerId: string,\n): Promise<void> {\n await tx\n .delete(documentSyncFailures)\n .where(\n and(\n eq(documentSyncFailures.appKind, CONTAINER_METADATA_APP_KIND),\n eq(documentSyncFailures.localId, containerId),\n ),\n )\n .run();\n}\n\nasync function hasPendingUpdates(\n tx: ClientSQLiteTransactionScope,\n containerId: string,\n): Promise<boolean> {\n const rows = await tx\n .select({ id: documentPendingUpdates.id })\n .from(documentPendingUpdates)\n .where(\n and(\n eq(documentPendingUpdates.appKind, CONTAINER_METADATA_APP_KIND),\n eq(documentPendingUpdates.localId, containerId),\n ),\n )\n .limit(1);\n return rows.length > 0;\n}\n\nasync function hasPendingStructuralIntent(\n tx: ClientSQLiteTransactionScope,\n containerId: string,\n): Promise<boolean> {\n const pendingCreates = await tx\n .select({ id: containerCreateIntents.id })\n .from(containerCreateIntents)\n .where(\n and(\n eq(containerCreateIntents.containerId, containerId),\n eq(containerCreateIntents.syncStatus, \"pending\"),\n ),\n )\n .limit(1);\n if (pendingCreates.length > 0) return true;\n\n const unsyncedMoves = await tx\n .select({ id: containerMoveIntents.id })\n .from(containerMoveIntents)\n .where(eq(containerMoveIntents.containerId, containerId))\n .limit(1);\n return unsyncedMoves.length > 0;\n}\n\nasync function enqueuePendingUpdate(\n execSql: Parameters<\n ContainerContentsPersistence[\"commitMetadataMutation\"]\n >[0],\n containerId: string,\n pendingUpdate: PendingUpdateFields | undefined,\n): Promise<void> {\n if (!pendingUpdate) return;\n await enqueueDocumentPendingUpdate(\n execSql,\n getContainerMetadataScope(containerId),\n pendingUpdate,\n );\n}\n\ntype CommitMetadataMutationInput = Parameters<\n ContainerContentsPersistence[\"commitMetadataMutation\"]\n>[1];\n\nfunction staleServerMutationResult(\n currentState: StoredContainerState | null,\n input: CommitMetadataMutationInput,\n) {\n const incomingServerUpdatedAt =\n input.saveOptions?.serverTimestamps?.updatedAt;\n const hasOlderContainerTimestamp =\n incomingServerUpdatedAt != null &&\n currentState?.container.serverUpdatedAt != null &&\n currentState.container.serverUpdatedAt > incomingServerUpdatedAt;\n const hasOlderMetadataAccessEpoch =\n currentState?.record != null &&\n currentState.record.documentId === input.record.documentId &&\n currentState.record.accessEpoch > input.record.accessEpoch;\n return currentState?.record &&\n (hasOlderContainerTimestamp || hasOlderMetadataAccessEpoch)\n ? {\n committed: false as const,\n currentState,\n staleServerState: true as const,\n }\n : null;\n}\n\nfunction metadataMutationStateMatches(\n currentState: StoredContainerState | null,\n input: CommitMetadataMutationInput,\n): currentState is StoredContainerState & {\n record: ContainerMetadataRecord;\n} {\n return Boolean(\n currentState?.record &&\n sameContainerRecord(currentState.container, input.expectedContainer) &&\n sameMetadataRecord(currentState.record, input.expectedRecord),\n );\n}\n\nasync function rejectMetadataMutationConflict(input: {\n currentState: StoredContainerState | null;\n mutation: CommitMetadataMutationInput;\n tx: ClientSQLiteTransactionScope;\n}) {\n const { currentState, mutation, tx } = input;\n if (\n currentState?.record &&\n mutation.settleAcceptedPendingOnConflict &&\n sameMetadataSecurityIdentity(currentState.record, mutation.expectedRecord)\n ) {\n await deleteAcceptedPendingUpdates(\n tx,\n mutation.container.id,\n mutation.acceptedPendingUpdateIds,\n );\n }\n return { committed: false as const, currentState };\n}\n\nasync function prepareContainerMutationWrite(input: {\n currentContainer: ContainerRecord;\n mutation: CommitMetadataMutationInput;\n tx: ClientSQLiteTransactionScope;\n}): Promise<{ container: ContainerRecord; localUpdatedAt: string }> {\n const { currentContainer, mutation, tx } = input;\n const requestedLocalUpdatedAt =\n mutation.saveOptions?.localUpdatedAt ??\n mutation.saveOptions?.updatedAt ??\n new Date().toISOString();\n const preserveDurableStructure =\n mutation.preserveDurableStructureWhenPending === true &&\n (await hasPendingStructuralIntent(tx, mutation.container.id));\n // Syncing metadata is not a local edit. Preserve the durable edit clock,\n // including an edit another pane made while this request was in flight.\n const localUpdatedAt =\n preserveDurableStructure || mutation.settleAcceptedPendingOnConflict\n ? (currentContainer.localUpdatedAt ?? requestedLocalUpdatedAt)\n : requestedLocalUpdatedAt;\n const structurallyRebasedContainer = preserveDurableStructure\n ? { ...mutation.container, parentId: currentContainer.parentId }\n : mutation.container;\n const didSettleOutgoing =\n mutation.acceptedPendingUpdateIds.length > 0 &&\n !(await hasPendingUpdates(tx, mutation.container.id)) &&\n !(await hasPendingStructuralIntent(tx, mutation.container.id));\n // Only container responses establish the server's structural clock. A\n // metadata acknowledgement supplies no such timestamp; marking it with our\n // wall clock would make later valid listings appear stale forever.\n return {\n container: structurallyRebasedContainer,\n localUpdatedAt: didSettleOutgoing\n ? (currentContainer.serverUpdatedAt ?? localUpdatedAt)\n : localUpdatedAt,\n };\n}\n\n/** Server acknowledgements and listings cannot rebind a held folder. */\nfunction assertMutationKeepsHeldBinding(\n currentState: StoredContainerState & { record: ContainerMetadataRecord },\n input: CommitMetadataMutationInput,\n): void {\n const recordDocumentIds =\n input.record.documentId === currentState.record.documentId\n ? []\n : [input.record.documentId];\n assertHeldContainerBinding(heldContainerBinding(currentState), {\n organizationId: input.container.organizationId,\n metadataDocumentIds: [\n input.container.metadataDocumentId,\n ...recordDocumentIds,\n ],\n });\n}\n\nexport async function commitStoredMetadataMutation(\n execSql: Parameters<\n ContainerContentsPersistence[\"commitMetadataMutation\"]\n >[0],\n input: Parameters<ContainerContentsPersistence[\"commitMetadataMutation\"]>[1],\n) {\n return runSerializedSqlMutation(execSql, async (lockedExecSql) => {\n const outcome = await getClientSQLitePersistenceRuntime(\n lockedExecSql,\n ).guardedTransaction(\n async (tx) => {\n const currentState = await loadStoredContainerState(\n lockedExecSql,\n input.container.id,\n );\n const staleServerResult = staleServerMutationResult(\n currentState,\n input,\n );\n if (staleServerResult) return staleServerResult;\n if (!metadataMutationStateMatches(currentState, input)) {\n return rejectMetadataMutationConflict({\n currentState,\n mutation: input,\n tx,\n });\n }\n assertMutationKeepsHeldBinding(currentState, input);\n\n await enqueuePendingUpdate(\n lockedExecSql,\n input.container.id,\n input.pendingUpdate,\n );\n await deleteAcceptedPendingUpdates(\n tx,\n input.container.id,\n input.acceptedPendingUpdateIds,\n );\n if (input.clearSyncFailure) {\n await clearSyncFailure(tx, input.container.id);\n }\n const { container, localUpdatedAt } =\n await prepareContainerMutationWrite({\n currentContainer: currentState.container,\n mutation: input,\n tx,\n });\n const savedContainer = await saveContainerContentsContainerRows({\n container,\n createIntent: input.saveOptions?.createIntent,\n localUpdatedAt,\n moveIntent: input.saveOptions?.moveIntent,\n record: input.record,\n serverTimestamps: input.saveOptions?.serverTimestamps,\n tx,\n });\n if (\n input.createIntentSettlement &&\n (await settleContainerCreateIntentRevision({\n ...input.createIntentSettlement,\n tx,\n })) === \"superseded\"\n ) {\n throw new ContainerCreateIntentSupersededError();\n }\n if (input.moveIntentSettlement) {\n if (\n !(await deleteContainerMoveIntentRevision({\n ...input.moveIntentSettlement,\n tx,\n }))\n ) {\n throw new Error(\n \"Container move intent was superseded before local settlement\",\n );\n }\n }\n return committedMetadataMutationResult({\n container: savedContainer,\n createIntentSettled: input.createIntentSettlement !== undefined,\n moveIntentSettled: input.moveIntentSettlement !== undefined,\n });\n },\n () => !input.stillCurrent || input.stillCurrent(),\n { behavior: \"immediate\" },\n );\n if (outcome.committed && outcome.result) {\n return outcome.result;\n }\n return {\n committed: false as const,\n currentState: await loadStoredContainerState(\n lockedExecSql,\n input.container.id,\n ),\n };\n });\n}\n\nexport async function settleStoredMetadataPendingUpdates(\n execSql: Parameters<\n ContainerContentsPersistence[\"settleAcceptedMetadataPendingUpdates\"]\n >[0],\n input: Parameters<\n ContainerContentsPersistence[\"settleAcceptedMetadataPendingUpdates\"]\n >[1],\n) {\n return runSerializedSqlMutation(execSql, async (lockedExecSql) => {\n const outcome = await getClientSQLitePersistenceRuntime(\n lockedExecSql,\n ).guardedTransaction(\n async (tx) => {\n const currentState = await loadStoredContainerState(\n lockedExecSql,\n input.containerId,\n );\n if (\n currentState?.record &&\n sameMetadataSecurityIdentity(\n currentState.record,\n input.expectedRecord,\n )\n ) {\n await deleteAcceptedPendingUpdates(\n tx,\n input.containerId,\n input.pendingUpdateIds,\n );\n }\n return currentState;\n },\n () => !input.stillCurrent || input.stillCurrent(),\n { behavior: \"immediate\" },\n );\n return outcome.committed ? outcome.result : null;\n });\n}\n"]}
1
+ {"version":3,"file":"containerMetadataMutationPersistence.js","sourceRoot":"","sources":["containerMetadataMutationPersistence.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACtC,OAAO,EACL,0BAA0B,EAC1B,oBAAoB,GACrB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,kCAAkC,EAAE,MAAM,yCAAyC,CAAC;AAC7F,OAAO,EACL,wBAAwB,EACxB,wCAAwC,GACzC,MAAM,+CAA+C,CAAC;AACvD,OAAO,EACL,4BAA4B,GAE7B,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAEL,iCAAiC,GAClC,MAAM,uCAAuC,CAAC;AAC/C,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAClE,OAAO,EAEL,iBAAiB,GAClB,MAAM,oCAAoC,CAAC;AAM5C,OAAO,EAAE,mCAAmC,EAAE,MAAM,mCAAmC,CAAC;AACxF,OAAO,EACL,oCAAoC,EACpC,iCAAiC,GAClC,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,yBAAyB,EACzB,kCAAkC,EAClC,6BAA6B,GAC9B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAC;AAEzE,SAAS,iBAAiB,CACxB,IAA+B,EAC/B,KAAgC;IAEhC,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,+BAA+B,CAAC,KAIxC;IACC,OAAO;QACL,SAAS,EAAE,IAAa;QACxB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,GAAG,CAAC,KAAK,CAAC,mBAAmB;YAC3B,CAAC,CAAC,EAAE,mBAAmB,EAAE,IAAa,EAAE;YACxC,CAAC,CAAC,EAAE,CAAC;QACP,GAAG,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,IAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACzE,CAAC;AACJ,CAAC;AAED,SAAS,4BAA4B,CACnC,OAAgC,EAChC,QAAiC;IAEjC,OAAO,CACL,OAAO,CAAC,EAAE,KAAK,QAAQ,CAAC,EAAE;QAC1B,OAAO,CAAC,UAAU,KAAK,QAAQ,CAAC,UAAU;QAC1C,OAAO,CAAC,WAAW,KAAK,QAAQ,CAAC,WAAW;QAC5C,iBAAiB,CAAC,OAAO,CAAC,eAAe,EAAE,QAAQ,CAAC,eAAe,CAAC;QACpE,iBAAiB,CAAC,OAAO,CAAC,gBAAgB,EAAE,QAAQ,CAAC,gBAAgB,CAAC;QACtE,iBAAiB,CACf,OAAO,CAAC,kBAAkB,EAC1B,QAAQ,CAAC,kBAAkB,CAC5B;QACD,iBAAiB,CACf,OAAO,CAAC,sBAAsB,EAC9B,QAAQ,CAAC,sBAAsB,CAChC,CACF,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CACzB,OAAgC,EAChC,QAAiC;IAEjC,OAAO,CACL,4BAA4B,CAAC,OAAO,EAAE,QAAQ,CAAC;QAC/C,iBAAiB,CAAC,OAAO,CAAC,aAAa,EAAE,QAAQ,CAAC,aAAa,CAAC;QAChE,OAAO,CAAC,eAAe,KAAK,QAAQ,CAAC,eAAe;QACpD,OAAO,CAAC,kBAAkB,KAAK,QAAQ,CAAC,kBAAkB;QAC1D,kCAAkC,CAChC,OAAO,CAAC,gBAAgB,EACxB,QAAQ,CAAC,gBAAgB,CAC1B;QACD,OAAO,CAAC,OAAO,CAAC,gCAAgC,CAAC;YAC/C,OAAO,CAAC,QAAQ,CAAC,gCAAgC,CAAC,CACrD,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB,CAC1B,OAAwB,EACxB,QAAyB;IAEzB,OAAO,CACL,OAAO,CAAC,EAAE,KAAK,QAAQ,CAAC,EAAE;QAC1B,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC,QAAQ;QACtC,OAAO,CAAC,cAAc,KAAK,QAAQ,CAAC,cAAc;QAClD,OAAO,CAAC,kBAAkB,KAAK,QAAQ,CAAC,kBAAkB;QAC1D,CAAC,OAAO,CAAC,UAAU,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,IAAI,IAAI,CAAC;QAC9D,CAAC,OAAO,CAAC,oBAAoB,IAAI,IAAI,CAAC;YACpC,CAAC,QAAQ,CAAC,oBAAoB,IAAI,IAAI,CAAC;QACzC,CAAC,OAAO,CAAC,cAAc,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,cAAc,IAAI,IAAI,CAAC;QACtE,CAAC,OAAO,CAAC,eAAe,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,eAAe,IAAI,IAAI,CAAC;QACxE,CAAC,OAAO,CAAC,eAAe,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,eAAe,IAAI,IAAI,CAAC;QACxE,OAAO,CAAC,IAAI,KAAK,QAAQ,CAAC,IAAI;QAC9B,CAAC,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,IAAI,IAAI,CAAC,CACnD,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,wBAAwB,CACrC,OAEI,EACJ,WAAmB;IAEnB,MAAM,SAAS,GAAG,MAAM,iBAAiB,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IAChE,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IAC5B,OAAO;QACL,SAAS;QACT,MAAM,EAAE,MAAM,6BAA6B,CAAC,OAAO,EAAE,WAAW,CAAC;KAClE,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,4BAA4B,CACzC,EAAgC,EAChC,WAAmB,EACnB,GAAsB;IAEtB,MAAM,wCAAwC,CAC5C,EAAE,EACF,yBAAyB,CAAC,WAAW,CAAC,EACtC,GAAG,CACJ,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,gBAAgB,CAC7B,EAAgC,EAChC,WAAmB;IAEnB,MAAM,EAAE;SACL,MAAM,CAAC,oBAAoB,CAAC;SAC5B,KAAK,CACJ,GAAG,CACD,EAAE,CAAC,oBAAoB,CAAC,OAAO,EAAE,2BAA2B,CAAC,EAC7D,EAAE,CAAC,oBAAoB,CAAC,OAAO,EAAE,WAAW,CAAC,CAC9C,CACF;SACA,GAAG,EAAE,CAAC;AACX,CAAC;AAED,KAAK,UAAU,iBAAiB,CAC9B,EAAgC,EAChC,WAAmB;IAEnB,OAAO,wBAAwB,CAAC,EAAE,EAAE,yBAAyB,CAAC,WAAW,CAAC,CAAC,CAAC;AAC9E,CAAC;AAED,KAAK,UAAU,0BAA0B,CACvC,EAAgC,EAChC,WAAmB;IAEnB,MAAM,cAAc,GAAG,MAAM,EAAE;SAC5B,MAAM,CAAC,EAAE,EAAE,EAAE,sBAAsB,CAAC,EAAE,EAAE,CAAC;SACzC,IAAI,CAAC,sBAAsB,CAAC;SAC5B,KAAK,CACJ,GAAG,CACD,EAAE,CAAC,sBAAsB,CAAC,WAAW,EAAE,WAAW,CAAC,EACnD,EAAE,CAAC,sBAAsB,CAAC,UAAU,EAAE,SAAS,CAAC,CACjD,CACF;SACA,KAAK,CAAC,CAAC,CAAC,CAAC;IACZ,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAE3C,MAAM,aAAa,GAAG,MAAM,EAAE;SAC3B,MAAM,CAAC,EAAE,EAAE,EAAE,oBAAoB,CAAC,EAAE,EAAE,CAAC;SACvC,IAAI,CAAC,oBAAoB,CAAC;SAC1B,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;SACxD,KAAK,CAAC,CAAC,CAAC,CAAC;IACZ,OAAO,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC;AAClC,CAAC;AAED,KAAK,UAAU,oBAAoB,CACjC,OAEI,EACJ,WAAmB,EACnB,aAA8C;IAE9C,IAAI,CAAC,aAAa;QAAE,OAAO;IAC3B,MAAM,4BAA4B,CAChC,OAAO,EACP,yBAAyB,CAAC,WAAW,CAAC,EACtC,aAAa,CACd,CAAC;AACJ,CAAC;AAMD,SAAS,yBAAyB,CAChC,YAAyC,EACzC,KAAkC;IAElC,MAAM,uBAAuB,GAC3B,KAAK,CAAC,WAAW,EAAE,gBAAgB,EAAE,SAAS,CAAC;IACjD,MAAM,0BAA0B,GAC9B,uBAAuB,IAAI,IAAI;QAC/B,YAAY,EAAE,SAAS,CAAC,eAAe,IAAI,IAAI;QAC/C,YAAY,CAAC,SAAS,CAAC,eAAe,GAAG,uBAAuB,CAAC;IACnE,MAAM,2BAA2B,GAC/B,YAAY,EAAE,MAAM,IAAI,IAAI;QAC5B,YAAY,CAAC,MAAM,CAAC,UAAU,KAAK,KAAK,CAAC,MAAM,CAAC,UAAU;QAC1D,YAAY,CAAC,MAAM,CAAC,WAAW,GAAG,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC;IAC7D,OAAO,YAAY,EAAE,MAAM;QACzB,CAAC,0BAA0B,IAAI,2BAA2B,CAAC;QAC3D,CAAC,CAAC;YACE,SAAS,EAAE,KAAc;YACzB,YAAY;YACZ,gBAAgB,EAAE,IAAa;SAChC;QACH,CAAC,CAAC,IAAI,CAAC;AACX,CAAC;AAED,SAAS,4BAA4B,CACnC,YAAyC,EACzC,KAAkC;IAIlC,OAAO,OAAO,CACZ,YAAY,EAAE,MAAM;QAClB,mBAAmB,CAAC,YAAY,CAAC,SAAS,EAAE,KAAK,CAAC,iBAAiB,CAAC;QACpE,kBAAkB,CAAC,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC,cAAc,CAAC,CAChE,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,8BAA8B,CAAC,KAI7C;IACC,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,EAAE,EAAE,GAAG,KAAK,CAAC;IAC7C,IACE,YAAY,EAAE,MAAM;QACpB,QAAQ,CAAC,+BAA+B;QACxC,4BAA4B,CAAC,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,cAAc,CAAC,EAC1E,CAAC;QACD,MAAM,4BAA4B,CAChC,EAAE,EACF,QAAQ,CAAC,SAAS,CAAC,EAAE,EACrB,QAAQ,CAAC,wBAAwB,CAClC,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,SAAS,EAAE,KAAc,EAAE,YAAY,EAAE,CAAC;AACrD,CAAC;AAED,KAAK,UAAU,6BAA6B,CAAC,KAI5C;IACC,MAAM,EAAE,gBAAgB,EAAE,QAAQ,EAAE,EAAE,EAAE,GAAG,KAAK,CAAC;IACjD,MAAM,uBAAuB,GAC3B,QAAQ,CAAC,WAAW,EAAE,cAAc;QACpC,QAAQ,CAAC,WAAW,EAAE,SAAS;QAC/B,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC3B,MAAM,wBAAwB,GAC5B,QAAQ,CAAC,mCAAmC,KAAK,IAAI;QACrD,CAAC,MAAM,0BAA0B,CAAC,EAAE,EAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;IAChE,yEAAyE;IACzE,wEAAwE;IACxE,MAAM,cAAc,GAClB,wBAAwB,IAAI,QAAQ,CAAC,+BAA+B;QAClE,CAAC,CAAC,CAAC,gBAAgB,CAAC,cAAc,IAAI,uBAAuB,CAAC;QAC9D,CAAC,CAAC,uBAAuB,CAAC;IAC9B,MAAM,4BAA4B,GAAG,wBAAwB;QAC3D,CAAC,CAAC,EAAE,GAAG,QAAQ,CAAC,SAAS,EAAE,QAAQ,EAAE,gBAAgB,CAAC,QAAQ,EAAE;QAChE,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC;IACvB,MAAM,iBAAiB,GACrB,QAAQ,CAAC,wBAAwB,CAAC,MAAM,GAAG,CAAC;QAC5C,CAAC,CAAC,MAAM,iBAAiB,CAAC,EAAE,EAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QACrD,CAAC,CAAC,MAAM,0BAA0B,CAAC,EAAE,EAAE,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;IACjE,sEAAsE;IACtE,2EAA2E;IAC3E,mEAAmE;IACnE,OAAO;QACL,SAAS,EAAE,4BAA4B;QACvC,cAAc,EAAE,iBAAiB;YAC/B,CAAC,CAAC,CAAC,gBAAgB,CAAC,eAAe,IAAI,cAAc,CAAC;YACtD,CAAC,CAAC,cAAc;KACnB,CAAC;AACJ,CAAC;AAED,wEAAwE;AACxE,SAAS,8BAA8B,CACrC,YAAwE,EACxE,KAAkC;IAElC,MAAM,iBAAiB,GACrB,KAAK,CAAC,MAAM,CAAC,UAAU,KAAK,YAAY,CAAC,MAAM,CAAC,UAAU;QACxD,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAChC,0BAA0B,CAAC,oBAAoB,CAAC,YAAY,CAAC,EAAE;QAC7D,cAAc,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc;QAC9C,mBAAmB,EAAE;YACnB,KAAK,CAAC,SAAS,CAAC,kBAAkB;YAClC,GAAG,iBAAiB;SACrB;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAChD,OAEI,EACJ,KAA4E;IAE5E,OAAO,wBAAwB,CAAC,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,EAAE;QAC/D,MAAM,OAAO,GAAG,MAAM,iCAAiC,CACrD,aAAa,CACd,CAAC,kBAAkB,CAClB,KAAK,EAAE,EAAE,EAAE,EAAE;YACX,MAAM,YAAY,GAAG,MAAM,wBAAwB,CACjD,aAAa,EACb,KAAK,CAAC,SAAS,CAAC,EAAE,CACnB,CAAC;YACF,MAAM,iBAAiB,GAAG,yBAAyB,CACjD,YAAY,EACZ,KAAK,CACN,CAAC;YACF,IAAI,iBAAiB;gBAAE,OAAO,iBAAiB,CAAC;YAChD,IAAI,CAAC,4BAA4B,CAAC,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC;gBACvD,OAAO,8BAA8B,CAAC;oBACpC,YAAY;oBACZ,QAAQ,EAAE,KAAK;oBACf,EAAE;iBACH,CAAC,CAAC;YACL,CAAC;YACD,8BAA8B,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;YAEpD,MAAM,oBAAoB,CACxB,aAAa,EACb,KAAK,CAAC,SAAS,CAAC,EAAE,EAClB,KAAK,CAAC,aAAa,CACpB,CAAC;YACF,MAAM,4BAA4B,CAChC,EAAE,EACF,KAAK,CAAC,SAAS,CAAC,EAAE,EAClB,KAAK,CAAC,wBAAwB,CAC/B,CAAC;YACF,IAAI,KAAK,CAAC,gBAAgB,EAAE,CAAC;gBAC3B,MAAM,gBAAgB,CAAC,EAAE,EAAE,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;YACjD,CAAC;YACD,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,GACjC,MAAM,6BAA6B,CAAC;gBAClC,gBAAgB,EAAE,YAAY,CAAC,SAAS;gBACxC,QAAQ,EAAE,KAAK;gBACf,EAAE;aACH,CAAC,CAAC;YACL,MAAM,cAAc,GAAG,MAAM,kCAAkC,CAAC;gBAC9D,SAAS;gBACT,YAAY,EAAE,KAAK,CAAC,WAAW,EAAE,YAAY;gBAC7C,cAAc;gBACd,UAAU,EAAE,KAAK,CAAC,WAAW,EAAE,UAAU;gBACzC,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,gBAAgB,EAAE,KAAK,CAAC,WAAW,EAAE,gBAAgB;gBACrD,EAAE;aACH,CAAC,CAAC;YACH,IACE,KAAK,CAAC,sBAAsB;gBAC5B,CAAC,MAAM,mCAAmC,CAAC;oBACzC,GAAG,KAAK,CAAC,sBAAsB;oBAC/B,EAAE;iBACH,CAAC,CAAC,KAAK,YAAY,EACpB,CAAC;gBACD,MAAM,IAAI,oCAAoC,EAAE,CAAC;YACnD,CAAC;YACD,IAAI,KAAK,CAAC,oBAAoB,EAAE,CAAC;gBAC/B,IACE,CAAC,CAAC,MAAM,iCAAiC,CAAC;oBACxC,GAAG,KAAK,CAAC,oBAAoB;oBAC7B,EAAE;iBACH,CAAC,CAAC,EACH,CAAC;oBACD,MAAM,IAAI,KAAK,CACb,8DAA8D,CAC/D,CAAC;gBACJ,CAAC;YACH,CAAC;YACD,OAAO,+BAA+B,CAAC;gBACrC,SAAS,EAAE,cAAc;gBACzB,mBAAmB,EAAE,KAAK,CAAC,sBAAsB,KAAK,SAAS;gBAC/D,iBAAiB,EAAE,KAAK,CAAC,oBAAoB,KAAK,SAAS;aAC5D,CAAC,CAAC;QACL,CAAC,EACD,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,YAAY,IAAI,KAAK,CAAC,YAAY,EAAE,EACjD,EAAE,QAAQ,EAAE,WAAW,EAAE,CAC1B,CAAC;QACF,IAAI,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACxC,OAAO,OAAO,CAAC,MAAM,CAAC;QACxB,CAAC;QACD,OAAO;YACL,SAAS,EAAE,KAAc;YACzB,YAAY,EAAE,MAAM,wBAAwB,CAC1C,aAAa,EACb,KAAK,CAAC,SAAS,CAAC,EAAE,CACnB;SACF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kCAAkC,CACtD,OAEI,EACJ,KAEI;IAEJ,OAAO,wBAAwB,CAAC,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,EAAE;QAC/D,MAAM,OAAO,GAAG,MAAM,iCAAiC,CACrD,aAAa,CACd,CAAC,kBAAkB,CAClB,KAAK,EAAE,EAAE,EAAE,EAAE;YACX,MAAM,YAAY,GAAG,MAAM,wBAAwB,CACjD,aAAa,EACb,KAAK,CAAC,WAAW,CAClB,CAAC;YACF,IACE,YAAY,EAAE,MAAM;gBACpB,4BAA4B,CAC1B,YAAY,CAAC,MAAM,EACnB,KAAK,CAAC,cAAc,CACrB,EACD,CAAC;gBACD,MAAM,4BAA4B,CAChC,EAAE,EACF,KAAK,CAAC,WAAW,EACjB,KAAK,CAAC,gBAAgB,CACvB,CAAC;YACJ,CAAC;YACD,OAAO,YAAY,CAAC;QACtB,CAAC,EACD,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,YAAY,IAAI,KAAK,CAAC,YAAY,EAAE,EACjD,EAAE,QAAQ,EAAE,WAAW,EAAE,CAC1B,CAAC;QACF,OAAO,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;IACnD,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { and, eq } from \"drizzle-orm\";\nimport {\n assertHeldContainerBinding,\n heldContainerBinding,\n} from \"../../containers/containerBinding\";\nimport { documentSyncPullContinuationsEqual } from \"../../documents/shared/pullContinuation\";\nimport {\n hasQueuedDocumentUpdates,\n settleQueuedDocumentUpdatesInTransaction,\n} from \"../../sqlite/documentPendingUpdatePersistence\";\nimport {\n enqueueDocumentPendingUpdate,\n type PendingUpdateFields,\n} from \"../../sqlite/documentPersistence\";\nimport {\n containerCreateIntents,\n containerMoveIntents,\n documentSyncFailures,\n} from \"../../sqlite/schema\";\nimport {\n type ClientSQLiteTransactionScope,\n getClientSQLitePersistenceRuntime,\n} from \"../../sqlite/sqlitePersistenceRuntime\";\nimport { runSerializedSqlMutation } from \"../../sqlite/sqlSchema\";\nimport {\n type ContainerRecord,\n loadContainerById,\n} from \"../containers/containerPersistence\";\nimport type {\n ContainerContentsPersistence,\n ContainerMetadataRecord,\n StoredContainerState,\n} from \"./containerContentsPersistenceTypes\";\nimport { settleContainerCreateIntentRevision } from \"./containerCreateIntentSettlement\";\nimport {\n ContainerCreateIntentSupersededError,\n deleteContainerMoveIntentRevision,\n} from \"./containerIntentPersistence\";\nimport {\n getContainerMetadataScope,\n saveContainerContentsContainerRows,\n selectContainerMetadataRecord,\n} from \"./containerMetadataRows\";\nimport { CONTAINER_METADATA_APP_KIND } from \"./dormantContainerMetadata\";\n\nfunction sameNullableValue(\n left: string | null | undefined,\n right: string | null | undefined,\n): boolean {\n return (left ?? null) === (right ?? null);\n}\n\nfunction committedMetadataMutationResult(input: {\n container: ContainerRecord;\n createIntentSettled: boolean;\n moveIntentSettled: boolean;\n}) {\n return {\n committed: true as const,\n container: input.container,\n ...(input.createIntentSettled\n ? { createIntentSettled: true as const }\n : {}),\n ...(input.moveIntentSettled ? { moveIntentSettled: true as const } : {}),\n };\n}\n\nfunction sameMetadataSecurityIdentity(\n current: ContainerMetadataRecord,\n expected: ContainerMetadataRecord,\n): boolean {\n return (\n current.id === expected.id &&\n current.documentId === expected.documentId &&\n current.accessEpoch === expected.accessEpoch &&\n sameNullableValue(current.accessStateHash, expected.accessStateHash) &&\n sameNullableValue(current.contentKeyBundle, expected.contentKeyBundle) &&\n sameNullableValue(\n current.documentKekTargets,\n expected.documentKekTargets,\n ) &&\n sameNullableValue(\n current.documentManifestBundle,\n expected.documentManifestBundle,\n )\n );\n}\n\nfunction sameMetadataRecord(\n current: ContainerMetadataRecord,\n expected: ContainerMetadataRecord,\n): boolean {\n return (\n sameMetadataSecurityIdentity(current, expected) &&\n sameNullableValue(current.lastCommitLsn, expected.lastCommitLsn) &&\n current.metadataUpdates === expected.metadataUpdates &&\n current.snapshotEndVersion === expected.snapshotEndVersion &&\n documentSyncPullContinuationsEqual(\n current.pullContinuation,\n expected.pullContinuation,\n ) &&\n Boolean(current.pullContinuationRecoveryRequired) ===\n Boolean(expected.pullContinuationRecoveryRequired)\n );\n}\n\nfunction sameContainerRecord(\n current: ContainerRecord,\n expected: ContainerRecord,\n): boolean {\n return (\n current.id === expected.id &&\n current.parentId === expected.parentId &&\n current.organizationId === expected.organizationId &&\n current.metadataDocumentId === expected.metadataDocumentId &&\n (current.systemSlot ?? null) === (expected.systemSlot ?? null) &&\n (current.effectiveAccessLevel ?? null) ===\n (expected.effectiveAccessLevel ?? null) &&\n (current.localUpdatedAt ?? null) === (expected.localUpdatedAt ?? null) &&\n (current.serverCreatedAt ?? null) === (expected.serverCreatedAt ?? null) &&\n (current.serverUpdatedAt ?? null) === (expected.serverUpdatedAt ?? null) &&\n current.name === expected.name &&\n (current.icon ?? null) === (expected.icon ?? null)\n );\n}\n\nasync function loadStoredContainerState(\n execSql: Parameters<\n ContainerContentsPersistence[\"loadContainerMetadataState\"]\n >[0],\n containerId: string,\n): Promise<StoredContainerState | null> {\n const container = await loadContainerById(execSql, containerId);\n if (!container) return null;\n return {\n container,\n record: await selectContainerMetadataRecord(execSql, containerId),\n };\n}\n\nasync function deleteAcceptedPendingUpdates(\n tx: ClientSQLiteTransactionScope,\n containerId: string,\n ids: readonly string[],\n): Promise<void> {\n await settleQueuedDocumentUpdatesInTransaction(\n tx,\n getContainerMetadataScope(containerId),\n ids,\n );\n}\n\nasync function clearSyncFailure(\n tx: ClientSQLiteTransactionScope,\n containerId: string,\n): Promise<void> {\n await tx\n .delete(documentSyncFailures)\n .where(\n and(\n eq(documentSyncFailures.appKind, CONTAINER_METADATA_APP_KIND),\n eq(documentSyncFailures.localId, containerId),\n ),\n )\n .run();\n}\n\nasync function hasPendingUpdates(\n tx: ClientSQLiteTransactionScope,\n containerId: string,\n): Promise<boolean> {\n return hasQueuedDocumentUpdates(tx, getContainerMetadataScope(containerId));\n}\n\nasync function hasPendingStructuralIntent(\n tx: ClientSQLiteTransactionScope,\n containerId: string,\n): Promise<boolean> {\n const pendingCreates = await tx\n .select({ id: containerCreateIntents.id })\n .from(containerCreateIntents)\n .where(\n and(\n eq(containerCreateIntents.containerId, containerId),\n eq(containerCreateIntents.syncStatus, \"pending\"),\n ),\n )\n .limit(1);\n if (pendingCreates.length > 0) return true;\n\n const unsyncedMoves = await tx\n .select({ id: containerMoveIntents.id })\n .from(containerMoveIntents)\n .where(eq(containerMoveIntents.containerId, containerId))\n .limit(1);\n return unsyncedMoves.length > 0;\n}\n\nasync function enqueuePendingUpdate(\n execSql: Parameters<\n ContainerContentsPersistence[\"commitMetadataMutation\"]\n >[0],\n containerId: string,\n pendingUpdate: PendingUpdateFields | undefined,\n): Promise<void> {\n if (!pendingUpdate) return;\n await enqueueDocumentPendingUpdate(\n execSql,\n getContainerMetadataScope(containerId),\n pendingUpdate,\n );\n}\n\ntype CommitMetadataMutationInput = Parameters<\n ContainerContentsPersistence[\"commitMetadataMutation\"]\n>[1];\n\nfunction staleServerMutationResult(\n currentState: StoredContainerState | null,\n input: CommitMetadataMutationInput,\n) {\n const incomingServerUpdatedAt =\n input.saveOptions?.serverTimestamps?.updatedAt;\n const hasOlderContainerTimestamp =\n incomingServerUpdatedAt != null &&\n currentState?.container.serverUpdatedAt != null &&\n currentState.container.serverUpdatedAt > incomingServerUpdatedAt;\n const hasOlderMetadataAccessEpoch =\n currentState?.record != null &&\n currentState.record.documentId === input.record.documentId &&\n currentState.record.accessEpoch > input.record.accessEpoch;\n return currentState?.record &&\n (hasOlderContainerTimestamp || hasOlderMetadataAccessEpoch)\n ? {\n committed: false as const,\n currentState,\n staleServerState: true as const,\n }\n : null;\n}\n\nfunction metadataMutationStateMatches(\n currentState: StoredContainerState | null,\n input: CommitMetadataMutationInput,\n): currentState is StoredContainerState & {\n record: ContainerMetadataRecord;\n} {\n return Boolean(\n currentState?.record &&\n sameContainerRecord(currentState.container, input.expectedContainer) &&\n sameMetadataRecord(currentState.record, input.expectedRecord),\n );\n}\n\nasync function rejectMetadataMutationConflict(input: {\n currentState: StoredContainerState | null;\n mutation: CommitMetadataMutationInput;\n tx: ClientSQLiteTransactionScope;\n}) {\n const { currentState, mutation, tx } = input;\n if (\n currentState?.record &&\n mutation.settleAcceptedPendingOnConflict &&\n sameMetadataSecurityIdentity(currentState.record, mutation.expectedRecord)\n ) {\n await deleteAcceptedPendingUpdates(\n tx,\n mutation.container.id,\n mutation.acceptedPendingUpdateIds,\n );\n }\n return { committed: false as const, currentState };\n}\n\nasync function prepareContainerMutationWrite(input: {\n currentContainer: ContainerRecord;\n mutation: CommitMetadataMutationInput;\n tx: ClientSQLiteTransactionScope;\n}): Promise<{ container: ContainerRecord; localUpdatedAt: string }> {\n const { currentContainer, mutation, tx } = input;\n const requestedLocalUpdatedAt =\n mutation.saveOptions?.localUpdatedAt ??\n mutation.saveOptions?.updatedAt ??\n new Date().toISOString();\n const preserveDurableStructure =\n mutation.preserveDurableStructureWhenPending === true &&\n (await hasPendingStructuralIntent(tx, mutation.container.id));\n // Syncing metadata is not a local edit. Preserve the durable edit clock,\n // including an edit another pane made while this request was in flight.\n const localUpdatedAt =\n preserveDurableStructure || mutation.settleAcceptedPendingOnConflict\n ? (currentContainer.localUpdatedAt ?? requestedLocalUpdatedAt)\n : requestedLocalUpdatedAt;\n const structurallyRebasedContainer = preserveDurableStructure\n ? { ...mutation.container, parentId: currentContainer.parentId }\n : mutation.container;\n const didSettleOutgoing =\n mutation.acceptedPendingUpdateIds.length > 0 &&\n !(await hasPendingUpdates(tx, mutation.container.id)) &&\n !(await hasPendingStructuralIntent(tx, mutation.container.id));\n // Only container responses establish the server's structural clock. A\n // metadata acknowledgement supplies no such timestamp; marking it with our\n // wall clock would make later valid listings appear stale forever.\n return {\n container: structurallyRebasedContainer,\n localUpdatedAt: didSettleOutgoing\n ? (currentContainer.serverUpdatedAt ?? localUpdatedAt)\n : localUpdatedAt,\n };\n}\n\n/** Server acknowledgements and listings cannot rebind a held folder. */\nfunction assertMutationKeepsHeldBinding(\n currentState: StoredContainerState & { record: ContainerMetadataRecord },\n input: CommitMetadataMutationInput,\n): void {\n const recordDocumentIds =\n input.record.documentId === currentState.record.documentId\n ? []\n : [input.record.documentId];\n assertHeldContainerBinding(heldContainerBinding(currentState), {\n organizationId: input.container.organizationId,\n metadataDocumentIds: [\n input.container.metadataDocumentId,\n ...recordDocumentIds,\n ],\n });\n}\n\nexport async function commitStoredMetadataMutation(\n execSql: Parameters<\n ContainerContentsPersistence[\"commitMetadataMutation\"]\n >[0],\n input: Parameters<ContainerContentsPersistence[\"commitMetadataMutation\"]>[1],\n) {\n return runSerializedSqlMutation(execSql, async (lockedExecSql) => {\n const outcome = await getClientSQLitePersistenceRuntime(\n lockedExecSql,\n ).guardedTransaction(\n async (tx) => {\n const currentState = await loadStoredContainerState(\n lockedExecSql,\n input.container.id,\n );\n const staleServerResult = staleServerMutationResult(\n currentState,\n input,\n );\n if (staleServerResult) return staleServerResult;\n if (!metadataMutationStateMatches(currentState, input)) {\n return rejectMetadataMutationConflict({\n currentState,\n mutation: input,\n tx,\n });\n }\n assertMutationKeepsHeldBinding(currentState, input);\n\n await enqueuePendingUpdate(\n lockedExecSql,\n input.container.id,\n input.pendingUpdate,\n );\n await deleteAcceptedPendingUpdates(\n tx,\n input.container.id,\n input.acceptedPendingUpdateIds,\n );\n if (input.clearSyncFailure) {\n await clearSyncFailure(tx, input.container.id);\n }\n const { container, localUpdatedAt } =\n await prepareContainerMutationWrite({\n currentContainer: currentState.container,\n mutation: input,\n tx,\n });\n const savedContainer = await saveContainerContentsContainerRows({\n container,\n createIntent: input.saveOptions?.createIntent,\n localUpdatedAt,\n moveIntent: input.saveOptions?.moveIntent,\n record: input.record,\n serverTimestamps: input.saveOptions?.serverTimestamps,\n tx,\n });\n if (\n input.createIntentSettlement &&\n (await settleContainerCreateIntentRevision({\n ...input.createIntentSettlement,\n tx,\n })) === \"superseded\"\n ) {\n throw new ContainerCreateIntentSupersededError();\n }\n if (input.moveIntentSettlement) {\n if (\n !(await deleteContainerMoveIntentRevision({\n ...input.moveIntentSettlement,\n tx,\n }))\n ) {\n throw new Error(\n \"Container move intent was superseded before local settlement\",\n );\n }\n }\n return committedMetadataMutationResult({\n container: savedContainer,\n createIntentSettled: input.createIntentSettlement !== undefined,\n moveIntentSettled: input.moveIntentSettlement !== undefined,\n });\n },\n () => !input.stillCurrent || input.stillCurrent(),\n { behavior: \"immediate\" },\n );\n if (outcome.committed && outcome.result) {\n return outcome.result;\n }\n return {\n committed: false as const,\n currentState: await loadStoredContainerState(\n lockedExecSql,\n input.container.id,\n ),\n };\n });\n}\n\nexport async function settleStoredMetadataPendingUpdates(\n execSql: Parameters<\n ContainerContentsPersistence[\"settleAcceptedMetadataPendingUpdates\"]\n >[0],\n input: Parameters<\n ContainerContentsPersistence[\"settleAcceptedMetadataPendingUpdates\"]\n >[1],\n) {\n return runSerializedSqlMutation(execSql, async (lockedExecSql) => {\n const outcome = await getClientSQLitePersistenceRuntime(\n lockedExecSql,\n ).guardedTransaction(\n async (tx) => {\n const currentState = await loadStoredContainerState(\n lockedExecSql,\n input.containerId,\n );\n if (\n currentState?.record &&\n sameMetadataSecurityIdentity(\n currentState.record,\n input.expectedRecord,\n )\n ) {\n await deleteAcceptedPendingUpdates(\n tx,\n input.containerId,\n input.pendingUpdateIds,\n );\n }\n return currentState;\n },\n () => !input.stillCurrent || input.stillCurrent(),\n { behavior: \"immediate\" },\n );\n return outcome.committed ? outcome.result : null;\n });\n}\n"]}
@@ -1,6 +1,7 @@
1
1
  import { and, asc, eq, inArray, isNotNull } from "drizzle-orm";
2
- import { deleteDocumentPendingUpdate, deleteDocumentPendingUpdates, enqueueDocumentPendingUpdate, listDocumentPendingUpdates, rekeyDocumentPendingUpdate, } from "../../sqlite/documentPersistence.js";
3
- import { documentPendingUpdates, documents } from "../../sqlite/schema.js";
2
+ import { listLocalIdsWithQueuedUpdates } from "../../sqlite/documentPendingUpdatePersistence.js";
3
+ import { enqueueDocumentPendingUpdate, listDocumentPendingUpdates, rekeyDocumentPendingUpdate, settleDocumentPendingUpdate, unqueueDocumentPendingUpdates, } from "../../sqlite/documentPersistence.js";
4
+ import { documents } from "../../sqlite/schema.js";
4
5
  import { getClientSQLitePersistenceRuntime } from "../../sqlite/sqlitePersistenceRuntime.js";
5
6
  import { runSerializedSqlMutation } from "../../sqlite/sqlSchema.js";
6
7
  import { getContainerMetadataScope } from "./containerMetadataRows.js";
@@ -8,12 +9,12 @@ import { CONTAINER_METADATA_APP_KIND } from "./dormantContainerMetadata.js";
8
9
  export const containerPendingUpdatePersistence = {
9
10
  async deletePendingUpdate(execSql, id) {
10
11
  await runSerializedSqlMutation(execSql, async (lockedExecSql) => {
11
- await deleteDocumentPendingUpdate(lockedExecSql, id);
12
+ await settleDocumentPendingUpdate(lockedExecSql, id);
12
13
  });
13
14
  },
14
15
  async deletePendingUpdates(execSql, containerId) {
15
16
  await runSerializedSqlMutation(execSql, async (lockedExecSql) => {
16
- await deleteDocumentPendingUpdates(lockedExecSql, getContainerMetadataScope(containerId));
17
+ await unqueueDocumentPendingUpdates(lockedExecSql, getContainerMetadataScope(containerId));
17
18
  });
18
19
  },
19
20
  async enqueuePendingUpdate(execSql, input) {
@@ -28,17 +29,7 @@ export const containerPendingUpdatePersistence = {
28
29
  return rekeyDocumentPendingUpdate(execSql, id);
29
30
  },
30
31
  async listContainerIdsWithPendingUpdates(execSql, containerIds) {
31
- const uniqueContainerIds = Array.from(new Set(containerIds));
32
- if (uniqueContainerIds.length === 0) {
33
- return [];
34
- }
35
- const { db } = getClientSQLitePersistenceRuntime(execSql);
36
- const rows = await db
37
- .selectDistinct({ containerId: documentPendingUpdates.localId })
38
- .from(documentPendingUpdates)
39
- .where(and(eq(documentPendingUpdates.appKind, CONTAINER_METADATA_APP_KIND), inArray(documentPendingUpdates.localId, uniqueContainerIds)))
40
- .orderBy(asc(documentPendingUpdates.localId));
41
- return rows.map((row) => row.containerId);
32
+ return listLocalIdsWithQueuedUpdates(getClientSQLitePersistenceRuntime(execSql).db, CONTAINER_METADATA_APP_KIND, containerIds);
42
33
  },
43
34
  async listContainerIdsWithPullContinuations(execSql, containerIds) {
44
35
  const uniqueContainerIds = Array.from(new Set(containerIds));
@@ -1 +1 @@
1
- {"version":3,"file":"containerPendingUpdatePersistence.js","sourceRoot":"","sources":["containerPendingUpdatePersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import { and, asc, eq, inArray, isNotNull } from \"drizzle-orm\";\nimport {\n deleteDocumentPendingUpdate,\n deleteDocumentPendingUpdates,\n enqueueDocumentPendingUpdate,\n listDocumentPendingUpdates,\n rekeyDocumentPendingUpdate,\n} from \"../../sqlite/documentPersistence\";\nimport { documentPendingUpdates, documents } from \"../../sqlite/schema\";\nimport { getClientSQLitePersistenceRuntime } from \"../../sqlite/sqlitePersistenceRuntime\";\nimport { runSerializedSqlMutation } from \"../../sqlite/sqlSchema\";\nimport type { ContainerContentsPersistence } from \"./containerContentsPersistenceTypes\";\nimport { getContainerMetadataScope } from \"./containerMetadataRows\";\nimport { CONTAINER_METADATA_APP_KIND } from \"./dormantContainerMetadata\";\n\ntype ContainerPendingUpdatePersistence = Pick<\n ContainerContentsPersistence,\n | \"deletePendingUpdate\"\n | \"deletePendingUpdates\"\n | \"enqueuePendingUpdate\"\n | \"listPendingUpdates\"\n | \"rekeyPendingUpdate\"\n | \"listContainerIdsWithPendingUpdates\"\n | \"listContainerIdsWithPullContinuations\"\n>;\n\nexport const containerPendingUpdatePersistence: ContainerPendingUpdatePersistence =\n {\n async deletePendingUpdate(execSql, id) {\n await runSerializedSqlMutation(execSql, async (lockedExecSql) => {\n await deleteDocumentPendingUpdate(lockedExecSql, id);\n });\n },\n async deletePendingUpdates(execSql, containerId) {\n await runSerializedSqlMutation(execSql, async (lockedExecSql) => {\n await deleteDocumentPendingUpdates(\n lockedExecSql,\n getContainerMetadataScope(containerId),\n );\n });\n },\n async enqueuePendingUpdate(execSql, input) {\n return runSerializedSqlMutation(execSql, async (lockedExecSql) => {\n return enqueueDocumentPendingUpdate(\n lockedExecSql,\n getContainerMetadataScope(input.containerId),\n input,\n );\n });\n },\n async listPendingUpdates(execSql, containerId) {\n return listDocumentPendingUpdates(\n execSql,\n getContainerMetadataScope(containerId),\n );\n },\n async rekeyPendingUpdate(execSql, id) {\n return rekeyDocumentPendingUpdate(execSql, id);\n },\n async listContainerIdsWithPendingUpdates(execSql, containerIds) {\n const uniqueContainerIds = Array.from(new Set(containerIds));\n if (uniqueContainerIds.length === 0) {\n return [];\n }\n\n const { db } = getClientSQLitePersistenceRuntime(execSql);\n const rows = await db\n .selectDistinct({ containerId: documentPendingUpdates.localId })\n .from(documentPendingUpdates)\n .where(\n and(\n eq(documentPendingUpdates.appKind, CONTAINER_METADATA_APP_KIND),\n inArray(documentPendingUpdates.localId, uniqueContainerIds),\n ),\n )\n .orderBy(asc(documentPendingUpdates.localId));\n\n return rows.map((row) => row.containerId);\n },\n async listContainerIdsWithPullContinuations(execSql, containerIds) {\n const uniqueContainerIds = Array.from(new Set(containerIds));\n if (uniqueContainerIds.length === 0) {\n return [];\n }\n\n const { db } = getClientSQLitePersistenceRuntime(execSql);\n const rows = await db\n .select({ containerId: documents.localId })\n .from(documents)\n .where(\n and(\n eq(documents.appKind, CONTAINER_METADATA_APP_KIND),\n inArray(documents.localId, uniqueContainerIds),\n isNotNull(documents.pullContinuation),\n ),\n )\n .orderBy(asc(documents.localId));\n\n return rows.map((row) => row.containerId);\n },\n };\n"]}
1
+ {"version":3,"file":"containerPendingUpdatePersistence.js","sourceRoot":"","sources":["containerPendingUpdatePersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import { and, asc, eq, inArray, isNotNull } from \"drizzle-orm\";\nimport { listLocalIdsWithQueuedUpdates } from \"../../sqlite/documentPendingUpdatePersistence\";\nimport {\n enqueueDocumentPendingUpdate,\n listDocumentPendingUpdates,\n rekeyDocumentPendingUpdate,\n settleDocumentPendingUpdate,\n unqueueDocumentPendingUpdates,\n} from \"../../sqlite/documentPersistence\";\nimport { documents } from \"../../sqlite/schema\";\nimport { getClientSQLitePersistenceRuntime } from \"../../sqlite/sqlitePersistenceRuntime\";\nimport { runSerializedSqlMutation } from \"../../sqlite/sqlSchema\";\nimport type { ContainerContentsPersistence } from \"./containerContentsPersistenceTypes\";\nimport { getContainerMetadataScope } from \"./containerMetadataRows\";\nimport { CONTAINER_METADATA_APP_KIND } from \"./dormantContainerMetadata\";\n\ntype ContainerPendingUpdatePersistence = Pick<\n ContainerContentsPersistence,\n | \"deletePendingUpdate\"\n | \"deletePendingUpdates\"\n | \"enqueuePendingUpdate\"\n | \"listPendingUpdates\"\n | \"rekeyPendingUpdate\"\n | \"listContainerIdsWithPendingUpdates\"\n | \"listContainerIdsWithPullContinuations\"\n>;\n\nexport const containerPendingUpdatePersistence: ContainerPendingUpdatePersistence =\n {\n async deletePendingUpdate(execSql, id) {\n await runSerializedSqlMutation(execSql, async (lockedExecSql) => {\n await settleDocumentPendingUpdate(lockedExecSql, id);\n });\n },\n async deletePendingUpdates(execSql, containerId) {\n await runSerializedSqlMutation(execSql, async (lockedExecSql) => {\n await unqueueDocumentPendingUpdates(\n lockedExecSql,\n getContainerMetadataScope(containerId),\n );\n });\n },\n async enqueuePendingUpdate(execSql, input) {\n return runSerializedSqlMutation(execSql, async (lockedExecSql) => {\n return enqueueDocumentPendingUpdate(\n lockedExecSql,\n getContainerMetadataScope(input.containerId),\n input,\n );\n });\n },\n async listPendingUpdates(execSql, containerId) {\n return listDocumentPendingUpdates(\n execSql,\n getContainerMetadataScope(containerId),\n );\n },\n async rekeyPendingUpdate(execSql, id) {\n return rekeyDocumentPendingUpdate(execSql, id);\n },\n async listContainerIdsWithPendingUpdates(execSql, containerIds) {\n return listLocalIdsWithQueuedUpdates(\n getClientSQLitePersistenceRuntime(execSql).db,\n CONTAINER_METADATA_APP_KIND,\n containerIds,\n );\n },\n async listContainerIdsWithPullContinuations(execSql, containerIds) {\n const uniqueContainerIds = Array.from(new Set(containerIds));\n if (uniqueContainerIds.length === 0) {\n return [];\n }\n\n const { db } = getClientSQLitePersistenceRuntime(execSql);\n const rows = await db\n .select({ containerId: documents.localId })\n .from(documents)\n .where(\n and(\n eq(documents.appKind, CONTAINER_METADATA_APP_KIND),\n inArray(documents.localId, uniqueContainerIds),\n isNotNull(documents.pullContinuation),\n ),\n )\n .orderBy(asc(documents.localId));\n\n return rows.map((row) => row.containerId);\n },\n };\n"]}
@@ -23,10 +23,9 @@ async function recoverySnapshot(execSql, containerId, organizationId) {
23
23
  "document_id, recovery_document_id, recovery_generation, snapshot_end_version, pending_base_version",
24
24
  ],
25
25
  ["document_history_checkpoints", "snapshot, end_version_vector"],
26
- ["document_history_updates", "id, update_data, origin"],
27
26
  [
28
- "document_pending_updates",
29
- "id, update_data, partial_start_version_vector, partial_end_version_vector, source_version_vector",
27
+ "document_history_updates",
28
+ "id, update_data, origin, update_id, partial_start_version_vector, partial_end_version_vector, source_version_vector",
30
29
  ],
31
30
  ]) {
32
31
  metadata.push(await execSql(`SELECT ${columns} FROM ${table} WHERE app_kind = 'container-metadata' AND local_id = ? ORDER BY rowid`, [containerId]));
@@ -41,7 +40,7 @@ async function recoverySnapshot(execSql, containerId, organizationId) {
41
40
  const revision = await toFingerprint(new TextEncoder().encode(JSON.stringify([dormant, metadata, creates, moves, links, targets])));
42
41
  return {
43
42
  revision,
44
- pendingUpdateCount: metadata[3]?.length ?? 0,
43
+ pendingUpdateCount: (metadata[2] ?? []).filter((row) => Reflect.get(row, "update_id") !== null).length,
45
44
  hasStructuralIntent: creates.length + moves.length + links.length > 0,
46
45
  };
47
46
  }
@@ -1 +1 @@
1
- {"version":3,"file":"containerRecoveryPersistence.js","sourceRoot":"","sources":["containerRecoveryPersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import { toFingerprint } from \"@tearleads/crypto\";\nimport { eq } from \"drizzle-orm\";\nimport {\n containerCreateIntents,\n containerMoveIntents,\n documentMoveIntentTables,\n} from \"../../sqlite/schema\";\nimport { getClientSQLitePersistenceRuntime } from \"../../sqlite/sqlitePersistenceRuntime\";\nimport {\n type ExecSql,\n ensureSqlTables,\n runSerializedSqlMutation,\n} from \"../../sqlite/sqlSchema\";\nimport { sqlContainerContentsPersistence } from \"./containerContentsPersistence\";\nimport { recordContainerHydrationTombstones } from \"./containerHydrationPersistence\";\nimport { repairDocumentsForRemovedContainersInTransaction } from \"./containerStructuralRepair\";\nimport { discardLinkIntentsForRemovedContainers } from \"./documentLinkRemovalRepair\";\nimport { deleteContainerMetadataDocumentRowsInTransaction } from \"./dormantContainerMetadata\";\n\n// The token covers all local work the user is agreeing to discard, including\n// shared link intents. A second pane's edit invalidates the confirmation.\nasync function recoverySnapshot(\n execSql: ExecSql,\n containerId: string,\n organizationId: string,\n) {\n const [dormant] = await execSql(\n `SELECT container_id, organization_id FROM dormant_container_metadata\n WHERE container_id = ? AND organization_id = ?\n AND NOT EXISTS (SELECT 1 FROM containers WHERE id = ?)`,\n [containerId, organizationId, containerId],\n );\n if (!dormant) return null;\n const metadata = [];\n for (const [table, columns] of [\n [\n \"documents\",\n \"document_id, recovery_document_id, recovery_generation, snapshot_end_version, pending_base_version\",\n ],\n [\"document_history_checkpoints\", \"snapshot, end_version_vector\"],\n [\"document_history_updates\", \"id, update_data, origin\"],\n [\n \"document_pending_updates\",\n \"id, update_data, partial_start_version_vector, partial_end_version_vector, source_version_vector\",\n ],\n ]) {\n metadata.push(\n await execSql(\n `SELECT ${columns} FROM ${table} WHERE app_kind = 'container-metadata' AND local_id = ? ORDER BY rowid`,\n [containerId],\n ),\n );\n }\n const creates = await execSql(\n \"SELECT id, container_id, parent_container_id, intent_type, remote_container_id, remote_metadata_document_id, remote_metadata_access_state_hash FROM container_create_intents WHERE container_id = ? AND sync_status = 'pending' ORDER BY id\",\n [containerId],\n );\n const moves = await execSql(\n \"SELECT id, container_id, parent_container_id, previous_parent_container_id, intent_type FROM container_move_intents WHERE container_id = ? ORDER BY id\",\n [containerId],\n );\n const links = await execSql(\n `SELECT id, local_id, document_id, target_container_id, source_container_id, replace_linked_containers, intent_type FROM document_move_intents WHERE target_container_id = ? OR id IN\n (SELECT intent_id FROM document_intent_link_targets WHERE container_id = ?) ORDER BY id`,\n [containerId, containerId],\n );\n const targets = await execSql(\n `SELECT intent_id, operation, container_id FROM document_intent_link_targets WHERE intent_id IN\n (SELECT id FROM document_move_intents WHERE target_container_id = ? OR id IN\n (SELECT intent_id FROM document_intent_link_targets WHERE container_id = ?)) ORDER BY intent_id, container_id, operation`,\n [containerId, containerId],\n );\n const revision = await toFingerprint(\n new TextEncoder().encode(\n JSON.stringify([dormant, metadata, creates, moves, links, targets]),\n ),\n );\n return {\n revision,\n pendingUpdateCount: metadata[3]?.length ?? 0,\n hasStructuralIntent: creates.length + moves.length + links.length > 0,\n };\n}\n\nexport async function listRetainedContainerMetadata(\n execSql: ExecSql,\n organizationId: string | null,\n) {\n if (!organizationId) return [];\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n await ensureSqlTables(execSql, documentMoveIntentTables);\n return runSerializedSqlMutation(execSql, async (locked) =>\n getClientSQLitePersistenceRuntime(locked).transaction(async () => {\n const rows = await locked(\n `SELECT container_id FROM dormant_container_metadata\n WHERE organization_id = ? ORDER BY container_id`,\n [organizationId],\n );\n const result = [];\n for (const row of rows) {\n const containerId = String(Reflect.get(row, \"container_id\"));\n const snapshot = await recoverySnapshot(\n locked,\n containerId,\n organizationId,\n );\n if (!snapshot) continue;\n const record =\n await sqlContainerContentsPersistence.loadContainerMetadataRecord(\n locked,\n containerId,\n );\n result.push({\n containerId,\n organizationId,\n ...snapshot,\n metadataUpdates: record?.metadataUpdates ?? \"\",\n });\n }\n return result;\n }),\n );\n}\n\n/** Explicit local discard, never called by remote discovery. */\nexport async function discardRetainedContainerMetadata(\n execSql: ExecSql,\n input: {\n containerId: string;\n organizationId: string;\n revision: string;\n },\n): Promise<boolean> {\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n await ensureSqlTables(execSql, documentMoveIntentTables);\n return runSerializedSqlMutation(execSql, async (locked) =>\n getClientSQLitePersistenceRuntime(locked).transaction(\n async (tx) => {\n const current = await recoverySnapshot(\n locked,\n input.containerId,\n input.organizationId,\n );\n if (!current || current.revision !== input.revision) return false;\n await recordContainerHydrationTombstones({\n tx,\n removals: [\n {\n containerId: input.containerId,\n reason: \"deleted\",\n updatedAt: new Date().toISOString(),\n },\n ],\n });\n await repairDocumentsForRemovedContainersInTransaction({\n tx,\n removals: [\n {\n containerId: input.containerId,\n reason: \"deleted\",\n updatedAt: new Date().toISOString(),\n },\n ],\n });\n await discardLinkIntentsForRemovedContainers({\n tx,\n containerIds: [input.containerId],\n });\n await tx\n .delete(containerCreateIntents)\n .where(eq(containerCreateIntents.containerId, input.containerId))\n .run();\n await tx\n .delete(containerMoveIntents)\n .where(eq(containerMoveIntents.containerId, input.containerId))\n .run();\n await deleteContainerMetadataDocumentRowsInTransaction(tx, [\n input.containerId,\n ]);\n return true;\n },\n { behavior: \"immediate\" },\n ),\n );\n}\n\nexport async function hasRetainedContainerMetadata(\n execSql: ExecSql,\n organizationId: string | null,\n): Promise<boolean> {\n if (!organizationId) return false;\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n const rows = await execSql(\n `SELECT 1 FROM dormant_container_metadata d\n WHERE d.organization_id = ? AND NOT EXISTS (SELECT 1 FROM containers c WHERE c.id = d.container_id) LIMIT 1`,\n [organizationId],\n );\n return rows.length > 0;\n}\n\n/** Existing local folders whose queued move points at an unavailable parent. */\nexport async function listRecoveryFolderMoveIds(\n execSql: ExecSql,\n organizationId: string | null,\n): Promise<string[]> {\n if (!organizationId) return [];\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n const rows = await execSql(\n `SELECT c.id FROM containers c JOIN container_move_intents i\n ON i.container_id = c.id AND i.parent_container_id = c.parent_id\n WHERE c.organization_id = ? AND i.sync_status IN ('pending', 'blocked')\n AND NOT EXISTS (SELECT 1 FROM containers p WHERE p.id = c.parent_id)\n ORDER BY c.id`,\n [organizationId],\n );\n return rows.map((row) => String(Reflect.get(row, \"id\")));\n}\n"]}
1
+ {"version":3,"file":"containerRecoveryPersistence.js","sourceRoot":"","sources":["containerRecoveryPersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import { toFingerprint } from \"@tearleads/crypto\";\nimport { eq } from \"drizzle-orm\";\nimport {\n containerCreateIntents,\n containerMoveIntents,\n documentMoveIntentTables,\n} from \"../../sqlite/schema\";\nimport { getClientSQLitePersistenceRuntime } from \"../../sqlite/sqlitePersistenceRuntime\";\nimport {\n type ExecSql,\n ensureSqlTables,\n runSerializedSqlMutation,\n} from \"../../sqlite/sqlSchema\";\nimport { sqlContainerContentsPersistence } from \"./containerContentsPersistence\";\nimport { recordContainerHydrationTombstones } from \"./containerHydrationPersistence\";\nimport { repairDocumentsForRemovedContainersInTransaction } from \"./containerStructuralRepair\";\nimport { discardLinkIntentsForRemovedContainers } from \"./documentLinkRemovalRepair\";\nimport { deleteContainerMetadataDocumentRowsInTransaction } from \"./dormantContainerMetadata\";\n\n// The token covers all local work the user is agreeing to discard, including\n// shared link intents. A second pane's edit invalidates the confirmation.\nasync function recoverySnapshot(\n execSql: ExecSql,\n containerId: string,\n organizationId: string,\n) {\n const [dormant] = await execSql(\n `SELECT container_id, organization_id FROM dormant_container_metadata\n WHERE container_id = ? AND organization_id = ?\n AND NOT EXISTS (SELECT 1 FROM containers WHERE id = ?)`,\n [containerId, organizationId, containerId],\n );\n if (!dormant) return null;\n const metadata = [];\n for (const [table, columns] of [\n [\n \"documents\",\n \"document_id, recovery_document_id, recovery_generation, snapshot_end_version, pending_base_version\",\n ],\n [\"document_history_checkpoints\", \"snapshot, end_version_vector\"],\n [\n \"document_history_updates\",\n \"id, update_data, origin, update_id, partial_start_version_vector, partial_end_version_vector, source_version_vector\",\n ],\n ]) {\n metadata.push(\n await execSql(\n `SELECT ${columns} FROM ${table} WHERE app_kind = 'container-metadata' AND local_id = ? ORDER BY rowid`,\n [containerId],\n ),\n );\n }\n const creates = await execSql(\n \"SELECT id, container_id, parent_container_id, intent_type, remote_container_id, remote_metadata_document_id, remote_metadata_access_state_hash FROM container_create_intents WHERE container_id = ? AND sync_status = 'pending' ORDER BY id\",\n [containerId],\n );\n const moves = await execSql(\n \"SELECT id, container_id, parent_container_id, previous_parent_container_id, intent_type FROM container_move_intents WHERE container_id = ? ORDER BY id\",\n [containerId],\n );\n const links = await execSql(\n `SELECT id, local_id, document_id, target_container_id, source_container_id, replace_linked_containers, intent_type FROM document_move_intents WHERE target_container_id = ? OR id IN\n (SELECT intent_id FROM document_intent_link_targets WHERE container_id = ?) ORDER BY id`,\n [containerId, containerId],\n );\n const targets = await execSql(\n `SELECT intent_id, operation, container_id FROM document_intent_link_targets WHERE intent_id IN\n (SELECT id FROM document_move_intents WHERE target_container_id = ? OR id IN\n (SELECT intent_id FROM document_intent_link_targets WHERE container_id = ?)) ORDER BY intent_id, container_id, operation`,\n [containerId, containerId],\n );\n const revision = await toFingerprint(\n new TextEncoder().encode(\n JSON.stringify([dormant, metadata, creates, moves, links, targets]),\n ),\n );\n return {\n revision,\n pendingUpdateCount: (metadata[2] ?? []).filter(\n (row) => Reflect.get(row, \"update_id\") !== null,\n ).length,\n hasStructuralIntent: creates.length + moves.length + links.length > 0,\n };\n}\n\nexport async function listRetainedContainerMetadata(\n execSql: ExecSql,\n organizationId: string | null,\n) {\n if (!organizationId) return [];\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n await ensureSqlTables(execSql, documentMoveIntentTables);\n return runSerializedSqlMutation(execSql, async (locked) =>\n getClientSQLitePersistenceRuntime(locked).transaction(async () => {\n const rows = await locked(\n `SELECT container_id FROM dormant_container_metadata\n WHERE organization_id = ? ORDER BY container_id`,\n [organizationId],\n );\n const result = [];\n for (const row of rows) {\n const containerId = String(Reflect.get(row, \"container_id\"));\n const snapshot = await recoverySnapshot(\n locked,\n containerId,\n organizationId,\n );\n if (!snapshot) continue;\n const record =\n await sqlContainerContentsPersistence.loadContainerMetadataRecord(\n locked,\n containerId,\n );\n result.push({\n containerId,\n organizationId,\n ...snapshot,\n metadataUpdates: record?.metadataUpdates ?? \"\",\n });\n }\n return result;\n }),\n );\n}\n\n/** Explicit local discard, never called by remote discovery. */\nexport async function discardRetainedContainerMetadata(\n execSql: ExecSql,\n input: {\n containerId: string;\n organizationId: string;\n revision: string;\n },\n): Promise<boolean> {\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n await ensureSqlTables(execSql, documentMoveIntentTables);\n return runSerializedSqlMutation(execSql, async (locked) =>\n getClientSQLitePersistenceRuntime(locked).transaction(\n async (tx) => {\n const current = await recoverySnapshot(\n locked,\n input.containerId,\n input.organizationId,\n );\n if (!current || current.revision !== input.revision) return false;\n await recordContainerHydrationTombstones({\n tx,\n removals: [\n {\n containerId: input.containerId,\n reason: \"deleted\",\n updatedAt: new Date().toISOString(),\n },\n ],\n });\n await repairDocumentsForRemovedContainersInTransaction({\n tx,\n removals: [\n {\n containerId: input.containerId,\n reason: \"deleted\",\n updatedAt: new Date().toISOString(),\n },\n ],\n });\n await discardLinkIntentsForRemovedContainers({\n tx,\n containerIds: [input.containerId],\n });\n await tx\n .delete(containerCreateIntents)\n .where(eq(containerCreateIntents.containerId, input.containerId))\n .run();\n await tx\n .delete(containerMoveIntents)\n .where(eq(containerMoveIntents.containerId, input.containerId))\n .run();\n await deleteContainerMetadataDocumentRowsInTransaction(tx, [\n input.containerId,\n ]);\n return true;\n },\n { behavior: \"immediate\" },\n ),\n );\n}\n\nexport async function hasRetainedContainerMetadata(\n execSql: ExecSql,\n organizationId: string | null,\n): Promise<boolean> {\n if (!organizationId) return false;\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n const rows = await execSql(\n `SELECT 1 FROM dormant_container_metadata d\n WHERE d.organization_id = ? AND NOT EXISTS (SELECT 1 FROM containers c WHERE c.id = d.container_id) LIMIT 1`,\n [organizationId],\n );\n return rows.length > 0;\n}\n\n/** Existing local folders whose queued move points at an unavailable parent. */\nexport async function listRecoveryFolderMoveIds(\n execSql: ExecSql,\n organizationId: string | null,\n): Promise<string[]> {\n if (!organizationId) return [];\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n const rows = await execSql(\n `SELECT c.id FROM containers c JOIN container_move_intents i\n ON i.container_id = c.id AND i.parent_container_id = c.parent_id\n WHERE c.organization_id = ? AND i.sync_status IN ('pending', 'blocked')\n AND NOT EXISTS (SELECT 1 FROM containers p WHERE p.id = c.parent_id)\n ORDER BY c.id`,\n [organizationId],\n );\n return rows.map((row) => String(Reflect.get(row, \"id\")));\n}\n"]}
@@ -1,12 +1,10 @@
1
1
  import { and, eq, inArray } from "drizzle-orm";
2
+ import { listLocalIdsWithQueuedUpdates } from "../../sqlite/documentPendingUpdatePersistence.js";
2
3
  import { documentIntentLinkTargets } from "../../sqlite/documentPlacementIntentSchema.js";
3
- import { containerCreateIntents, containerMoveIntents, documentMoveIntents, documentPendingUpdates, } from "../../sqlite/schema.js";
4
+ import { containerCreateIntents, containerMoveIntents, documentMoveIntents, } from "../../sqlite/schema.js";
4
5
  /** Only local work makes removed metadata a recovery item; clean cache is disposable. */
5
6
  export async function containerIdsWithRemovalWork(tx, ids) {
6
- const pending = await tx
7
- .select({ id: documentPendingUpdates.localId })
8
- .from(documentPendingUpdates)
9
- .where(and(eq(documentPendingUpdates.appKind, "container-metadata"), inArray(documentPendingUpdates.localId, ids)));
7
+ const pending = (await listLocalIdsWithQueuedUpdates(tx, "container-metadata", ids)).map((id) => ({ id }));
10
8
  const creates = await tx
11
9
  .select({ id: containerCreateIntents.containerId })
12
10
  .from(containerCreateIntents)
@@ -1 +1 @@
1
- {"version":3,"file":"containerRemovalWork.js","sourceRoot":"","sources":["containerRemovalWork.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,yBAAyB,EAAE,MAAM,4CAA4C,CAAC;AACvF,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,qBAAqB,CAAC;AAG7B,yFAAyF;AACzF,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAC/C,EAAgC,EAChC,GAAa;IAEb,MAAM,OAAO,GAAG,MAAM,EAAE;SACrB,MAAM,CAAC,EAAE,EAAE,EAAE,sBAAsB,CAAC,OAAO,EAAE,CAAC;SAC9C,IAAI,CAAC,sBAAsB,CAAC;SAC5B,KAAK,CACJ,GAAG,CACD,EAAE,CAAC,sBAAsB,CAAC,OAAO,EAAE,oBAAoB,CAAC,EACxD,OAAO,CAAC,sBAAsB,CAAC,OAAO,EAAE,GAAG,CAAC,CAC7C,CACF,CAAC;IACJ,MAAM,OAAO,GAAG,MAAM,EAAE;SACrB,MAAM,CAAC,EAAE,EAAE,EAAE,sBAAsB,CAAC,WAAW,EAAE,CAAC;SAClD,IAAI,CAAC,sBAAsB,CAAC;SAC5B,KAAK,CACJ,GAAG,CACD,EAAE,CAAC,sBAAsB,CAAC,UAAU,EAAE,SAAS,CAAC,EAChD,OAAO,CAAC,sBAAsB,CAAC,WAAW,EAAE,GAAG,CAAC,CACjD,CACF,CAAC;IACJ,MAAM,KAAK,GAAG,MAAM,EAAE;SACnB,MAAM,CAAC,EAAE,EAAE,EAAE,oBAAoB,CAAC,WAAW,EAAE,CAAC;SAChD,IAAI,CAAC,oBAAoB,CAAC;SAC1B,KAAK,CACJ,GAAG,CACD,OAAO,CAAC,oBAAoB,CAAC,UAAU,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,EAChE,OAAO,CAAC,oBAAoB,CAAC,WAAW,EAAE,GAAG,CAAC,CAC/C,CACF,CAAC;IACJ,MAAM,UAAU,GAAG,MAAM,EAAE;SACxB,MAAM,CAAC,EAAE,EAAE,EAAE,mBAAmB,CAAC,iBAAiB,EAAE,CAAC;SACrD,IAAI,CAAC,mBAAmB,CAAC;SACzB,KAAK,CAAC,OAAO,CAAC,mBAAmB,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC,CAAC;IAC9D,MAAM,KAAK,GAAG,MAAM,EAAE;SACnB,MAAM,CAAC,EAAE,EAAE,EAAE,yBAAyB,CAAC,WAAW,EAAE,CAAC;SACrD,IAAI,CAAC,yBAAyB,CAAC;SAC/B,KAAK,CAAC,OAAO,CAAC,yBAAyB,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC;IAC9D,OAAO;QACL,GAAG,IAAI,GAAG,CACR,CAAC,GAAG,OAAO,EAAE,GAAG,OAAO,EAAE,GAAG,KAAK,EAAE,GAAG,UAAU,EAAE,GAAG,KAAK,CAAC,CAAC,GAAG,CAC7D,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,CAChB,CACF;KACF,CAAC;AACJ,CAAC","sourcesContent":["import { and, eq, inArray } from \"drizzle-orm\";\nimport { documentIntentLinkTargets } from \"../../sqlite/documentPlacementIntentSchema\";\nimport {\n containerCreateIntents,\n containerMoveIntents,\n documentMoveIntents,\n documentPendingUpdates,\n} from \"../../sqlite/schema\";\nimport type { ClientSQLiteTransactionScope } from \"../../sqlite/sqlitePersistenceRuntime\";\n\n/** Only local work makes removed metadata a recovery item; clean cache is disposable. */\nexport async function containerIdsWithRemovalWork(\n tx: ClientSQLiteTransactionScope,\n ids: string[],\n): Promise<string[]> {\n const pending = await tx\n .select({ id: documentPendingUpdates.localId })\n .from(documentPendingUpdates)\n .where(\n and(\n eq(documentPendingUpdates.appKind, \"container-metadata\"),\n inArray(documentPendingUpdates.localId, ids),\n ),\n );\n const creates = await tx\n .select({ id: containerCreateIntents.containerId })\n .from(containerCreateIntents)\n .where(\n and(\n eq(containerCreateIntents.syncStatus, \"pending\"),\n inArray(containerCreateIntents.containerId, ids),\n ),\n );\n const moves = await tx\n .select({ id: containerMoveIntents.containerId })\n .from(containerMoveIntents)\n .where(\n and(\n inArray(containerMoveIntents.syncStatus, [\"pending\", \"blocked\"]),\n inArray(containerMoveIntents.containerId, ids),\n ),\n );\n const placements = await tx\n .select({ id: documentMoveIntents.targetContainerId })\n .from(documentMoveIntents)\n .where(inArray(documentMoveIntents.targetContainerId, ids));\n const links = await tx\n .select({ id: documentIntentLinkTargets.containerId })\n .from(documentIntentLinkTargets)\n .where(inArray(documentIntentLinkTargets.containerId, ids));\n return [\n ...new Set(\n [...pending, ...creates, ...moves, ...placements, ...links].map(\n (row) => row.id,\n ),\n ),\n ];\n}\n"]}
1
+ {"version":3,"file":"containerRemovalWork.js","sourceRoot":"","sources":["containerRemovalWork.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,6BAA6B,EAAE,MAAM,+CAA+C,CAAC;AAC9F,OAAO,EAAE,yBAAyB,EAAE,MAAM,4CAA4C,CAAC;AACvF,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,qBAAqB,CAAC;AAG7B,yFAAyF;AACzF,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAC/C,EAAgC,EAChC,GAAa;IAEb,MAAM,OAAO,GAAG,CACd,MAAM,6BAA6B,CAAC,EAAE,EAAE,oBAAoB,EAAE,GAAG,CAAC,CACnE,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;IACxB,MAAM,OAAO,GAAG,MAAM,EAAE;SACrB,MAAM,CAAC,EAAE,EAAE,EAAE,sBAAsB,CAAC,WAAW,EAAE,CAAC;SAClD,IAAI,CAAC,sBAAsB,CAAC;SAC5B,KAAK,CACJ,GAAG,CACD,EAAE,CAAC,sBAAsB,CAAC,UAAU,EAAE,SAAS,CAAC,EAChD,OAAO,CAAC,sBAAsB,CAAC,WAAW,EAAE,GAAG,CAAC,CACjD,CACF,CAAC;IACJ,MAAM,KAAK,GAAG,MAAM,EAAE;SACnB,MAAM,CAAC,EAAE,EAAE,EAAE,oBAAoB,CAAC,WAAW,EAAE,CAAC;SAChD,IAAI,CAAC,oBAAoB,CAAC;SAC1B,KAAK,CACJ,GAAG,CACD,OAAO,CAAC,oBAAoB,CAAC,UAAU,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,EAChE,OAAO,CAAC,oBAAoB,CAAC,WAAW,EAAE,GAAG,CAAC,CAC/C,CACF,CAAC;IACJ,MAAM,UAAU,GAAG,MAAM,EAAE;SACxB,MAAM,CAAC,EAAE,EAAE,EAAE,mBAAmB,CAAC,iBAAiB,EAAE,CAAC;SACrD,IAAI,CAAC,mBAAmB,CAAC;SACzB,KAAK,CAAC,OAAO,CAAC,mBAAmB,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC,CAAC;IAC9D,MAAM,KAAK,GAAG,MAAM,EAAE;SACnB,MAAM,CAAC,EAAE,EAAE,EAAE,yBAAyB,CAAC,WAAW,EAAE,CAAC;SACrD,IAAI,CAAC,yBAAyB,CAAC;SAC/B,KAAK,CAAC,OAAO,CAAC,yBAAyB,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC;IAC9D,OAAO;QACL,GAAG,IAAI,GAAG,CACR,CAAC,GAAG,OAAO,EAAE,GAAG,OAAO,EAAE,GAAG,KAAK,EAAE,GAAG,UAAU,EAAE,GAAG,KAAK,CAAC,CAAC,GAAG,CAC7D,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,CAChB,CACF;KACF,CAAC;AACJ,CAAC","sourcesContent":["import { and, eq, inArray } from \"drizzle-orm\";\nimport { listLocalIdsWithQueuedUpdates } from \"../../sqlite/documentPendingUpdatePersistence\";\nimport { documentIntentLinkTargets } from \"../../sqlite/documentPlacementIntentSchema\";\nimport {\n containerCreateIntents,\n containerMoveIntents,\n documentMoveIntents,\n} from \"../../sqlite/schema\";\nimport type { ClientSQLiteTransactionScope } from \"../../sqlite/sqlitePersistenceRuntime\";\n\n/** Only local work makes removed metadata a recovery item; clean cache is disposable. */\nexport async function containerIdsWithRemovalWork(\n tx: ClientSQLiteTransactionScope,\n ids: string[],\n): Promise<string[]> {\n const pending = (\n await listLocalIdsWithQueuedUpdates(tx, \"container-metadata\", ids)\n ).map((id) => ({ id }));\n const creates = await tx\n .select({ id: containerCreateIntents.containerId })\n .from(containerCreateIntents)\n .where(\n and(\n eq(containerCreateIntents.syncStatus, \"pending\"),\n inArray(containerCreateIntents.containerId, ids),\n ),\n );\n const moves = await tx\n .select({ id: containerMoveIntents.containerId })\n .from(containerMoveIntents)\n .where(\n and(\n inArray(containerMoveIntents.syncStatus, [\"pending\", \"blocked\"]),\n inArray(containerMoveIntents.containerId, ids),\n ),\n );\n const placements = await tx\n .select({ id: documentMoveIntents.targetContainerId })\n .from(documentMoveIntents)\n .where(inArray(documentMoveIntents.targetContainerId, ids));\n const links = await tx\n .select({ id: documentIntentLinkTargets.containerId })\n .from(documentIntentLinkTargets)\n .where(inArray(documentIntentLinkTargets.containerId, ids));\n return [\n ...new Set(\n [...pending, ...creates, ...moves, ...placements, ...links].map(\n (row) => row.id,\n ),\n ),\n ];\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import { and, eq, inArray, sql } from "drizzle-orm";
2
- import { documentHistoryCheckpoints, documentHistoryUpdates, documentPendingUpdates, documentSyncFailures, documents, dormantContainerMetadata, } from "../../sqlite/schema.js";
2
+ import { documentHistoryCheckpoints, documentHistoryUpdates, documentSyncFailures, documents, dormantContainerMetadata, } from "../../sqlite/schema.js";
3
3
  export const CONTAINER_METADATA_APP_KIND = "container-metadata";
4
4
  export async function retainDormantContainerMetadataInTransaction(tx, retained) {
5
5
  if (retained.length === 0) {
@@ -44,10 +44,6 @@ export async function deleteContainerMetadataDocumentRowsInTransaction(tx, conta
44
44
  .delete(documentHistoryUpdates)
45
45
  .where(and(eq(documentHistoryUpdates.appKind, CONTAINER_METADATA_APP_KIND), inArray(documentHistoryUpdates.localId, ids)))
46
46
  .run();
47
- await tx
48
- .delete(documentPendingUpdates)
49
- .where(and(eq(documentPendingUpdates.appKind, CONTAINER_METADATA_APP_KIND), inArray(documentPendingUpdates.localId, ids)))
50
- .run();
51
47
  await tx
52
48
  .delete(documentSyncFailures)
53
49
  .where(and(eq(documentSyncFailures.appKind, CONTAINER_METADATA_APP_KIND), inArray(documentSyncFailures.localId, ids)))