@tearleads/client-sdk 0.1.113 → 0.1.115

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 (66) hide show
  1. package/data/persistence/container-contents/containerContentsPersistence.js +3 -8
  2. package/data/persistence/container-contents/containerContentsPersistence.js.map +1 -1
  3. package/data/persistence/container-contents/containerHydrationPersistence.js +15 -5
  4. package/data/persistence/container-contents/containerHydrationPersistence.js.map +1 -1
  5. package/data/persistence/container-contents/containerMetadataMutationPersistence.js +8 -2
  6. package/data/persistence/container-contents/containerMetadataMutationPersistence.js.map +1 -1
  7. package/data/persistence/container-contents/containerMetadataRows.js +34 -2
  8. package/data/persistence/container-contents/containerMetadataRows.js.map +1 -1
  9. package/data/persistence/container-contents/containerPersistence.d.ts +231 -0
  10. package/data/persistence/container-contents/containerPersistence.js +20 -16
  11. package/data/persistence/container-contents/containerPersistence.js.map +1 -1
  12. package/data/persistence/container-contents/containerRecoveryPersistence.js +167 -51
  13. package/data/persistence/container-contents/containerRecoveryPersistence.js.map +1 -1
  14. package/data/persistence/container-contents/documentContainerProjectionPersistence.js +56 -19
  15. package/data/persistence/container-contents/documentContainerProjectionPersistence.js.map +1 -1
  16. package/data/persistence/container-contents/documentMoveIntentPersistence.js +29 -5
  17. package/data/persistence/container-contents/documentMoveIntentPersistence.js.map +1 -1
  18. package/data/persistence/container-contents/documentPlacement.js +24 -5
  19. package/data/persistence/container-contents/documentPlacement.js.map +1 -1
  20. package/data/persistence/container-contents/documentPlacementIntentEnqueue.js +1 -1
  21. package/data/persistence/container-contents/documentPlacementIntentEnqueue.js.map +1 -1
  22. package/data/persistence/documents/containerDocumentTombstoneHoldsPersistence.js +1 -1
  23. package/data/persistence/documents/containerDocumentTombstoneHoldsPersistence.js.map +1 -1
  24. package/data/persistence/documents/documentDiscoveryEvidencePersistence.js +43 -35
  25. package/data/persistence/documents/documentDiscoveryEvidencePersistence.js.map +1 -1
  26. package/data/persistence/documents/documentsPersistence.js +4 -58
  27. package/data/persistence/documents/documentsPersistence.js.map +1 -1
  28. package/data/persistence/documents/internal/containerDocumentTombstoneHolds.js +15 -11
  29. package/data/persistence/documents/internal/containerDocumentTombstoneHolds.js.map +1 -1
  30. package/data/persistence/documents/internal/containerDocumentTombstones.js +87 -35
  31. package/data/persistence/documents/internal/containerDocumentTombstones.js.map +1 -1
  32. package/data/persistence/documents/internal/discoveredDocumentPlacement.js +5 -2
  33. package/data/persistence/documents/internal/discoveredDocumentPlacement.js.map +1 -1
  34. package/data/persistence/documents/internal/discoveredDocumentUpsert.js +174 -0
  35. package/data/persistence/documents/internal/discoveredDocumentUpsert.js.map +1 -0
  36. package/data/persistence/documents/internal/documentMutationPersistence.js +15 -15
  37. package/data/persistence/documents/internal/documentMutationPersistence.js.map +1 -1
  38. package/data/persistence/documents/internal/documentRows.js +122 -11
  39. package/data/persistence/documents/internal/documentRows.js.map +1 -1
  40. package/data/persistence/documents/internal/rowQueryPersistence.js +70 -27
  41. package/data/persistence/documents/internal/rowQueryPersistence.js.map +1 -1
  42. package/data/persistence/documents/records/documentHistoryPersistence.js +17 -11
  43. package/data/persistence/documents/records/documentHistoryPersistence.js.map +1 -1
  44. package/data/persistence/documents/records/documentRecordPersistence.d.ts +5 -0
  45. package/data/persistence/documents/records/documentRecordPersistence.js +41 -6
  46. package/data/persistence/documents/records/documentRecordPersistence.js.map +1 -1
  47. package/data/persistence/documents/records/index.d.ts +1 -1
  48. package/data/persistence/documents/records/index.js +1 -1
  49. package/data/persistence/documents/records/index.js.map +1 -1
  50. package/data/persistence/keyingCheckpoints/documentPurgeCheckpointPersistence.d.ts +2 -0
  51. package/data/persistence/keyingCheckpoints/documentPurgeCheckpointPersistence.js +17 -1
  52. package/data/persistence/keyingCheckpoints/documentPurgeCheckpointPersistence.js.map +1 -1
  53. package/package.json +1 -1
  54. package/workflows/container-contents/documentQueries/index.js +21 -6
  55. package/workflows/container-contents/documentQueries/index.js.map +1 -1
  56. package/workflows/container-contents/remoteReset/containerRemoteReset.js +12 -7
  57. package/workflows/container-contents/remoteReset/containerRemoteReset.js.map +1 -1
  58. package/workflows/documents/documentMutationCommit.js +11 -12
  59. package/workflows/documents/documentMutationCommit.js.map +1 -1
  60. package/workflows/documents/documentMutationPreparation.d.ts +1 -0
  61. package/workflows/documents/documentMutationPreparation.js +1 -0
  62. package/workflows/documents/documentMutationPreparation.js.map +1 -1
  63. package/workflows/documents/documentPersistGuards.js +24 -0
  64. package/workflows/documents/documentPersistGuards.js.map +1 -1
  65. package/workflows/documents/remoteReset/documentRemoteReset.js +31 -18
  66. package/workflows/documents/remoteReset/documentRemoteReset.js.map +1 -1
@@ -1,4 +1,4 @@
1
- import { and, eq, inArray, or } from "drizzle-orm";
1
+ import { and, eq, inArray, or, sql } from "drizzle-orm";
2
2
  import { queuedUpdateRow, unqueueDocumentScopesInTransaction, } from "../../../data/persistence/documents/records/documentPendingUpdatePersistence.js";
3
3
  import { CLEARED_DOCUMENT_SYNC_FAILURE } from "../../../data/persistence/documents/records/documentSyncFailurePersistence.js";
4
4
  import { documentAttachmentBlobProjection, documentHistoryUpdates, documentPendingAttachments, documentProjection, documents, } from "../../../data/sqlite/schema/index.js";
@@ -71,24 +71,37 @@ export async function clearDocumentRowsForRemoteReset(input) {
71
71
  */
72
72
  export async function resetDocumentServerIdentity(input) {
73
73
  const { now, tx } = input;
74
+ const localIdsByAppKind = new Map();
74
75
  for (const row of input.documentRows) {
75
- await tx
76
- .update(documents)
77
- .set({
78
- accessEpoch: 1,
79
- accessStateHash: null,
80
- contentKeyBundle: null,
81
- documentId: null,
82
- documentKekTargets: null,
83
- documentManifestBundle: null,
84
- lastCommitLsn: null,
85
- pullContinuation: null,
86
- recoveryDocumentId: row.documentId ?? row.recoveryDocumentId,
87
- ...CLEARED_DOCUMENT_SYNC_FAILURE,
88
- updatedAt: now,
89
- })
90
- .where(and(eq(documents.appKind, row.appKind), eq(documents.localId, row.localId)))
91
- .run();
76
+ const localIds = localIdsByAppKind.get(row.appKind);
77
+ if (localIds)
78
+ localIds.push(row.localId);
79
+ else
80
+ localIdsByAppKind.set(row.appKind, [row.localId]);
81
+ }
82
+ // One update per batch: SQLite evaluates every SET value against the old
83
+ // row, so COALESCE keeps the id being cleared (or the earlier recovery id)
84
+ // per row; no earlier reset step writes either column.
85
+ for (const [appKind, localIds] of localIdsByAppKind) {
86
+ for (const localIdBatch of remoteResetBatches(localIds)) {
87
+ await tx
88
+ .update(documents)
89
+ .set({
90
+ accessEpoch: 1,
91
+ accessStateHash: null,
92
+ contentKeyBundle: null,
93
+ documentId: null,
94
+ documentKekTargets: null,
95
+ documentManifestBundle: null,
96
+ lastCommitLsn: null,
97
+ pullContinuation: null,
98
+ recoveryDocumentId: sql `coalesce(${documents.documentId}, ${documents.recoveryDocumentId})`,
99
+ ...CLEARED_DOCUMENT_SYNC_FAILURE,
100
+ updatedAt: now,
101
+ })
102
+ .where(and(eq(documents.appKind, appKind), inArray(documents.localId, localIdBatch)))
103
+ .run();
104
+ }
92
105
  }
93
106
  for (const localIdBatch of remoteResetBatches(input.documentLocalIds)) {
94
107
  await tx
@@ -1 +1 @@
1
- {"version":3,"file":"documentRemoteReset.js","sourceRoot":"","sources":["documentRemoteReset.ts"],"names":[],"mappings":"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","sourcesContent":["import { and, eq, inArray, or } from \"drizzle-orm\";\nimport {\n queuedUpdateRow,\n unqueueDocumentScopesInTransaction,\n} from \"../../../data/persistence/documents/records/documentPendingUpdatePersistence\";\nimport { CLEARED_DOCUMENT_SYNC_FAILURE } from \"../../../data/persistence/documents/records/documentSyncFailurePersistence\";\nimport {\n documentAttachmentBlobProjection,\n documentHistoryUpdates,\n documentPendingAttachments,\n documentProjection,\n documents,\n} from \"../../../data/sqlite/schema\";\nimport { remoteResetBatches } from \"../../../data/sqlite/sqliteBindBudget\";\nimport type { ClientSQLiteTransactionScope } from \"../../../data/sqlite/sqlitePersistenceRuntime\";\nimport { clearResetPendingAttachments } from \"./remoteResetAttachments\";\nimport type {\n ResetAttachmentUpload,\n ResetDocumentScope,\n ResetDocumentUpdate,\n} from \"./remoteResetPlans\";\n\n// Document Store's part of a remote reset. The sync remote reset calls these in\n// one transaction: it forgets what the server held for the organization's\n// documents, strips their server identity, and queues their local history and\n// attachments to be published again.\nexport { clearDocumentDiscoveryEvidenceOnRemoteReset } from \"../../../data/persistence/documents/documentDiscoveryReset\";\nexport {\n buildResetPlans,\n type ResetAttachmentUpload,\n type ResetDocumentUpdate,\n} from \"./remoteResetPlans\";\n\nexport interface ResetDocumentRow extends ResetDocumentScope {\n readonly documentId: string | null;\n readonly recoveryDocumentId: string | null;\n}\n\ninterface DocumentPlacementRow {\n readonly containerId: string;\n readonly documentId: string;\n}\n\n/**\n * The documents a reset covers: metadata documents of its folders, documents\n * projected into the organization or its folders, and documents placed in them.\n */\nexport async function loadDocumentResetScope(input: {\n containerIds: readonly string[];\n organizationId: string;\n placementRows: readonly DocumentPlacementRow[];\n tx: ClientSQLiteTransactionScope;\n}): Promise<{\n documentLocalIds: string[];\n documentRows: ResetDocumentRow[];\n oldDocumentIds: string[];\n}> {\n const { organizationId, tx } = input;\n const containerIdSet = new Set(input.containerIds);\n const [allDocuments, projectionRows] = await Promise.all([\n tx\n .select({\n appKind: documents.appKind,\n documentId: documents.documentId,\n localId: documents.localId,\n recoveryDocumentId: documents.recoveryDocumentId,\n })\n .from(documents),\n tx.select().from(documentProjection),\n ]);\n const linkedDocumentIds = new Set(\n input.placementRows\n .filter((row) => containerIdSet.has(row.containerId))\n .map((row) => row.documentId),\n );\n const projectedLocalIds = new Set(\n projectionRows\n .filter(\n (row) =>\n (row.containerId !== null && containerIdSet.has(row.containerId)) ||\n row.organizationId === organizationId ||\n (row.documentId !== null && linkedDocumentIds.has(row.documentId)),\n )\n .flatMap((row) => (row.localId ? [row.localId] : [])),\n );\n const documentRows = allDocuments.filter(\n (row) =>\n (row.appKind === \"container-metadata\" &&\n containerIdSet.has(row.localId)) ||\n (row.appKind === \"documents\" && projectedLocalIds.has(row.localId)) ||\n (row.documentId !== null && linkedDocumentIds.has(row.documentId)),\n );\n return {\n documentLocalIds: [\n ...new Set(\n documentRows\n .filter((row) => row.appKind === \"documents\")\n .map((row) => row.localId),\n ),\n ],\n documentRows,\n oldDocumentIds: [\n ...new Set(\n documentRows.flatMap((row) => (row.documentId ? [row.documentId] : [])),\n ),\n ],\n };\n}\n\n/** Clears pending attachments (keeping re-queued bytes) and queued updates. */\nexport async function clearDocumentRowsForRemoteReset(input: {\n attachmentUploads: readonly ResetAttachmentUpload[];\n documentLocalIds: readonly string[];\n documentRows: readonly ResetDocumentRow[];\n tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n const { tx } = input;\n await clearResetPendingAttachments({\n attachmentUploads: input.attachmentUploads,\n documentLocalIds: input.documentLocalIds,\n tx,\n });\n // Sync failures clear with the document columns in resetDocumentServerIdentity.\n for (const documentBatch of remoteResetBatches(input.documentRows)) {\n await unqueueDocumentScopesInTransaction(tx, documentBatch);\n }\n}\n\n/**\n * Drops each document's server id, keys, manifest, and sync position, keeping\n * the old id for recovery, and moves its projection to `organizationId`.\n */\nexport async function resetDocumentServerIdentity(input: {\n documentLocalIds: readonly string[];\n documentRows: readonly ResetDocumentRow[];\n now: string;\n organizationId: string;\n tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n const { now, tx } = input;\n for (const row of input.documentRows) {\n await tx\n .update(documents)\n .set({\n accessEpoch: 1,\n accessStateHash: null,\n contentKeyBundle: null,\n documentId: null,\n documentKekTargets: null,\n documentManifestBundle: null,\n lastCommitLsn: null,\n pullContinuation: null,\n recoveryDocumentId: row.documentId ?? row.recoveryDocumentId,\n ...CLEARED_DOCUMENT_SYNC_FAILURE,\n updatedAt: now,\n })\n .where(\n and(\n eq(documents.appKind, row.appKind),\n eq(documents.localId, row.localId),\n ),\n )\n .run();\n }\n for (const localIdBatch of remoteResetBatches(input.documentLocalIds)) {\n await tx\n .update(documentProjection)\n .set({\n documentId: null,\n organizationId: input.organizationId,\n })\n .where(inArray(documentProjection.localId, localIdBatch))\n .run();\n }\n}\n\n/** Queues each document's rebuilt local history as one outbox update. */\nexport async function queueDocumentRepublishForRemoteReset(input: {\n documentUpdates: readonly ResetDocumentUpdate[];\n now: string;\n tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n for (const updateBatch of remoteResetBatches(input.documentUpdates)) {\n await input.tx\n .insert(documentHistoryUpdates)\n .values(\n updateBatch.map((update) =>\n queuedUpdateRow({\n createdAt: input.now,\n origin: \"outbox\",\n pendingUpdate: update,\n scope: update,\n updateId: crypto.randomUUID(),\n }),\n ),\n )\n .run();\n }\n}\n\n/** Queues the attachments the documents still advertise for upload. */\nexport async function queueAttachmentReuploadsForRemoteReset(input: {\n attachmentUploads: readonly ResetAttachmentUpload[];\n now: string;\n tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n for (const attachmentBatch of remoteResetBatches(input.attachmentUploads)) {\n await input.tx\n .insert(documentPendingAttachments)\n .values(\n attachmentBatch.map((attachment) => ({\n ...attachment,\n createdAt: input.now,\n })),\n )\n .run();\n await input.tx\n .delete(documentAttachmentBlobProjection)\n .where(\n or(\n ...attachmentBatch.map((attachment) =>\n and(\n eq(documentAttachmentBlobProjection.localId, attachment.localId),\n eq(documentAttachmentBlobProjection.slotId, attachment.slotId),\n ),\n ),\n ),\n )\n .run();\n }\n}\n"]}
1
+ {"version":3,"file":"documentRemoteReset.js","sourceRoot":"","sources":["documentRemoteReset.ts"],"names":[],"mappings":"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","sourcesContent":["import { and, eq, inArray, or, sql } from \"drizzle-orm\";\nimport {\n queuedUpdateRow,\n unqueueDocumentScopesInTransaction,\n} from \"../../../data/persistence/documents/records/documentPendingUpdatePersistence\";\nimport { CLEARED_DOCUMENT_SYNC_FAILURE } from \"../../../data/persistence/documents/records/documentSyncFailurePersistence\";\nimport {\n documentAttachmentBlobProjection,\n documentHistoryUpdates,\n documentPendingAttachments,\n documentProjection,\n documents,\n} from \"../../../data/sqlite/schema\";\nimport { remoteResetBatches } from \"../../../data/sqlite/sqliteBindBudget\";\nimport type { ClientSQLiteTransactionScope } from \"../../../data/sqlite/sqlitePersistenceRuntime\";\nimport { clearResetPendingAttachments } from \"./remoteResetAttachments\";\nimport type {\n ResetAttachmentUpload,\n ResetDocumentScope,\n ResetDocumentUpdate,\n} from \"./remoteResetPlans\";\n\n// Document Store's part of a remote reset. The sync remote reset calls these in\n// one transaction: it forgets what the server held for the organization's\n// documents, strips their server identity, and queues their local history and\n// attachments to be published again.\nexport { clearDocumentDiscoveryEvidenceOnRemoteReset } from \"../../../data/persistence/documents/documentDiscoveryReset\";\nexport {\n buildResetPlans,\n type ResetAttachmentUpload,\n type ResetDocumentUpdate,\n} from \"./remoteResetPlans\";\n\nexport interface ResetDocumentRow extends ResetDocumentScope {\n readonly documentId: string | null;\n readonly recoveryDocumentId: string | null;\n}\n\ninterface DocumentPlacementRow {\n readonly containerId: string;\n readonly documentId: string;\n}\n\n/**\n * The documents a reset covers: metadata documents of its folders, documents\n * projected into the organization or its folders, and documents placed in them.\n */\nexport async function loadDocumentResetScope(input: {\n containerIds: readonly string[];\n organizationId: string;\n placementRows: readonly DocumentPlacementRow[];\n tx: ClientSQLiteTransactionScope;\n}): Promise<{\n documentLocalIds: string[];\n documentRows: ResetDocumentRow[];\n oldDocumentIds: string[];\n}> {\n const { organizationId, tx } = input;\n const containerIdSet = new Set(input.containerIds);\n const [allDocuments, projectionRows] = await Promise.all([\n tx\n .select({\n appKind: documents.appKind,\n documentId: documents.documentId,\n localId: documents.localId,\n recoveryDocumentId: documents.recoveryDocumentId,\n })\n .from(documents),\n tx.select().from(documentProjection),\n ]);\n const linkedDocumentIds = new Set(\n input.placementRows\n .filter((row) => containerIdSet.has(row.containerId))\n .map((row) => row.documentId),\n );\n const projectedLocalIds = new Set(\n projectionRows\n .filter(\n (row) =>\n (row.containerId !== null && containerIdSet.has(row.containerId)) ||\n row.organizationId === organizationId ||\n (row.documentId !== null && linkedDocumentIds.has(row.documentId)),\n )\n .flatMap((row) => (row.localId ? [row.localId] : [])),\n );\n const documentRows = allDocuments.filter(\n (row) =>\n (row.appKind === \"container-metadata\" &&\n containerIdSet.has(row.localId)) ||\n (row.appKind === \"documents\" && projectedLocalIds.has(row.localId)) ||\n (row.documentId !== null && linkedDocumentIds.has(row.documentId)),\n );\n return {\n documentLocalIds: [\n ...new Set(\n documentRows\n .filter((row) => row.appKind === \"documents\")\n .map((row) => row.localId),\n ),\n ],\n documentRows,\n oldDocumentIds: [\n ...new Set(\n documentRows.flatMap((row) => (row.documentId ? [row.documentId] : [])),\n ),\n ],\n };\n}\n\n/** Clears pending attachments (keeping re-queued bytes) and queued updates. */\nexport async function clearDocumentRowsForRemoteReset(input: {\n attachmentUploads: readonly ResetAttachmentUpload[];\n documentLocalIds: readonly string[];\n documentRows: readonly ResetDocumentRow[];\n tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n const { tx } = input;\n await clearResetPendingAttachments({\n attachmentUploads: input.attachmentUploads,\n documentLocalIds: input.documentLocalIds,\n tx,\n });\n // Sync failures clear with the document columns in resetDocumentServerIdentity.\n for (const documentBatch of remoteResetBatches(input.documentRows)) {\n await unqueueDocumentScopesInTransaction(tx, documentBatch);\n }\n}\n\n/**\n * Drops each document's server id, keys, manifest, and sync position, keeping\n * the old id for recovery, and moves its projection to `organizationId`.\n */\nexport async function resetDocumentServerIdentity(input: {\n documentLocalIds: readonly string[];\n documentRows: readonly ResetDocumentRow[];\n now: string;\n organizationId: string;\n tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n const { now, tx } = input;\n const localIdsByAppKind = new Map<string, string[]>();\n for (const row of input.documentRows) {\n const localIds = localIdsByAppKind.get(row.appKind);\n if (localIds) localIds.push(row.localId);\n else localIdsByAppKind.set(row.appKind, [row.localId]);\n }\n // One update per batch: SQLite evaluates every SET value against the old\n // row, so COALESCE keeps the id being cleared (or the earlier recovery id)\n // per row; no earlier reset step writes either column.\n for (const [appKind, localIds] of localIdsByAppKind) {\n for (const localIdBatch of remoteResetBatches(localIds)) {\n await tx\n .update(documents)\n .set({\n accessEpoch: 1,\n accessStateHash: null,\n contentKeyBundle: null,\n documentId: null,\n documentKekTargets: null,\n documentManifestBundle: null,\n lastCommitLsn: null,\n pullContinuation: null,\n recoveryDocumentId: sql`coalesce(${documents.documentId}, ${documents.recoveryDocumentId})`,\n ...CLEARED_DOCUMENT_SYNC_FAILURE,\n updatedAt: now,\n })\n .where(\n and(\n eq(documents.appKind, appKind),\n inArray(documents.localId, localIdBatch),\n ),\n )\n .run();\n }\n }\n for (const localIdBatch of remoteResetBatches(input.documentLocalIds)) {\n await tx\n .update(documentProjection)\n .set({\n documentId: null,\n organizationId: input.organizationId,\n })\n .where(inArray(documentProjection.localId, localIdBatch))\n .run();\n }\n}\n\n/** Queues each document's rebuilt local history as one outbox update. */\nexport async function queueDocumentRepublishForRemoteReset(input: {\n documentUpdates: readonly ResetDocumentUpdate[];\n now: string;\n tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n for (const updateBatch of remoteResetBatches(input.documentUpdates)) {\n await input.tx\n .insert(documentHistoryUpdates)\n .values(\n updateBatch.map((update) =>\n queuedUpdateRow({\n createdAt: input.now,\n origin: \"outbox\",\n pendingUpdate: update,\n scope: update,\n updateId: crypto.randomUUID(),\n }),\n ),\n )\n .run();\n }\n}\n\n/** Queues the attachments the documents still advertise for upload. */\nexport async function queueAttachmentReuploadsForRemoteReset(input: {\n attachmentUploads: readonly ResetAttachmentUpload[];\n now: string;\n tx: ClientSQLiteTransactionScope;\n}): Promise<void> {\n for (const attachmentBatch of remoteResetBatches(input.attachmentUploads)) {\n await input.tx\n .insert(documentPendingAttachments)\n .values(\n attachmentBatch.map((attachment) => ({\n ...attachment,\n createdAt: input.now,\n })),\n )\n .run();\n await input.tx\n .delete(documentAttachmentBlobProjection)\n .where(\n or(\n ...attachmentBatch.map((attachment) =>\n and(\n eq(documentAttachmentBlobProjection.localId, attachment.localId),\n eq(documentAttachmentBlobProjection.slotId, attachment.slotId),\n ),\n ),\n ),\n )\n .run();\n }\n}\n"]}