@tearleads/client-sdk 0.1.29 → 0.1.31
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client/Tearleads.d.ts +5 -0
- package/client/Tearleads.js +10 -2
- package/client/Tearleads.js.map +1 -1
- package/index.d.ts +2 -1
- package/index.js +4 -0
- package/index.js.map +1 -1
- package/internal/api-client/ApiClient.d.ts +2 -1
- package/internal/api-client/ApiClient.js +2 -2
- package/internal/api-client/ApiClient.js.map +1 -1
- package/internal/api-client/apiRequestMetrics.d.ts +38 -0
- package/internal/api-client/apiRequestMetrics.js +97 -0
- package/internal/api-client/apiRequestMetrics.js.map +1 -0
- package/internal/api-client/apiRequestRuntime.d.ts +3 -1
- package/internal/api-client/apiRequestRuntime.js +9 -7
- package/internal/api-client/apiRequestRuntime.js.map +1 -1
- package/internal/api-client/index.d.ts +1 -0
- package/internal/api-client/index.js +1 -0
- package/internal/api-client/index.js.map +1 -1
- package/internal/api-client/measureApiRequest.js +31 -0
- package/internal/api-client/measureApiRequest.js.map +1 -0
- package/package.json +1 -1
- package/stores/container-contents/state.js +1 -0
- package/stores/container-contents/state.js.map +1 -1
- package/stores/container-contents/types.d.ts +2 -0
- package/stores/container-contents/types.js.map +1 -1
- package/stores/container-contents/utils.js +10 -0
- package/stores/container-contents/utils.js.map +1 -1
- package/stores/documents/documentStore/syncFinalize.js +7 -3
- package/stores/documents/documentStore/syncFinalize.js.map +1 -1
- package/workflows/container-contents/documentQueries/hydrationSql.js +16 -0
- package/workflows/container-contents/documentQueries/hydrationSql.js.map +1 -0
- package/workflows/container-contents/documentQueries/sql.js +16 -7
- package/workflows/container-contents/documentQueries/sql.js.map +1 -1
- package/workflows/container-contents/documentQueries.d.ts +6 -1
- package/workflows/container-contents/documentQueries.js +15 -8
- package/workflows/container-contents/documentQueries.js.map +1 -1
- package/workflows/container-contents/index.d.ts +1 -0
- package/workflows/container-contents/index.js.map +1 -1
- package/workflows/container-contents/pendingDownloads.d.ts +12 -0
- package/workflows/container-contents/pendingDownloads.js +45 -0
- package/workflows/container-contents/pendingDownloads.js.map +1 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"syncFinalize.js","sourceRoot":"","sources":["syncFinalize.ts"],"names":[],"mappings":"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","sourcesContent":["import { bytesToBase64 } from \"@tearleads/encoding\";\nimport {\n encodeVersionVector,\n getImportBlobMetadata,\n mergeVersionVectors,\n} from \"@tearleads/loro\";\nimport { readPullContinuation } from \"../../../data/documents/shared/syncPagination\";\nimport {\n type DocumentRecord,\n settleOutgoingPassAndDecideReArm,\n shouldClearDocumentSyncFailureAfterPass,\n} from \"../../../workflows/documents\";\nimport { requestDocumentStoreSync } from \"../registry\";\nimport { hydrateAttachmentBlobs } from \"./attachmentHydration\";\nimport { chainIdentityWrite } from \"./identityWriteChain\";\nimport { publishPersistedDocument, saveDocumentRecord } from \"./persistence\";\nimport { logRevalidationApplied as logApplied } from \"./remoteRevalidationTelemetry\";\nimport type {\n DocumentState,\n DocumentStoreState,\n DocumentSyncAttempt,\n SaveDocumentRecordOptions,\n} from \"./state\";\nimport {\n discardPreRegisteredUpdateIds,\n discardUnacceptedPreRegisteredUpdateIds,\n} from \"./syncAcceptedUpdateIds\";\nimport {\n type DocumentStoreSyncGeneration,\n isDocumentStoreSyncGenerationCurrent,\n} from \"./syncGeneration\";\nimport { clearConsumedRemoteUpdateSignal } from \"./syncRemoteSignals\";\nimport {\n applyIncomingSyncedUpdates,\n documentSyncContextMatches,\n importSyncedDocumentUpdates,\n} from \"./syncUpdateImport\";\nimport { extendDocumentVersionCoverage } from \"./versionCoverage\";\nimport { installDocumentWriterProjection } from \"./writerProjectionGeneration\";\n\nfunction documentWriterProjectionMatchesSyncResponse(\n writerProjection: NonNullable<\n DocumentSyncAttempt[\"synced\"][\"writerProjection\"]\n >,\n synced: DocumentSyncAttempt[\"synced\"],\n): boolean {\n return (\n writerProjection.contentKeyBundle.contentKeyEpoch ===\n synced.response.contentKeyBundle.contentKeyEpoch &&\n writerProjection.contentKeyBundle.linkSetManifestHash ===\n synced.response.contentKeyBundle.linkSetManifestHash &&\n writerProjection.contentKeyBundle.targetHash ===\n synced.response.contentKeyBundle.targetHash &&\n writerProjection.documentKekTargets.linkSetManifestHash ===\n synced.response.documentKekTargets.linkSetManifestHash &&\n writerProjection.documentKekTargets.documentKeyTargetHash ===\n synced.response.documentKekTargets.documentKeyTargetHash\n );\n}\n\nfunction resolveSyncedDocumentWriterProjection(\n state: DocumentStoreState,\n synced: DocumentSyncAttempt[\"synced\"],\n) {\n const writerProjection =\n synced.writerProjection ??\n (state.writerProjection?.documentId === synced.plan.documentId\n ? state.writerProjection\n : null);\n return writerProjection &&\n documentWriterProjectionMatchesSyncResponse(writerProjection, synced)\n ? writerProjection\n : null;\n}\n\n/**\n * Durable-history tail: append pulled updates BEFORE the record persist so\n * the tail stays a superset of what the snapshot covers (duplicates are\n * idempotent by op identity; a crash between the writes can only leave the\n * safe superset).\n */\nfunction pulledHistoryUpdates(synced: DocumentSyncAttempt[\"synced\"]): string[] {\n return synced.decryptedUpdates.map((update) =>\n bytesToBase64(update.updateData),\n );\n}\n\n/**\n * The frontier a finalize persist may publish: the stored frontier advanced\n * by exactly the pulled updates just appended to the durable tail — never the\n * live document's version, which can transiently include an in-flight local\n * edit whose durable row has not landed yet.\n */\nfunction coveredSyncFrontier(\n state: DocumentStoreState,\n currentRecord: DocumentRecord,\n synced: DocumentSyncAttempt[\"synced\"],\n): { snapshotEndVersion: string } | Record<string, never> {\n if (synced.decryptedUpdates.length === 0) {\n return {};\n }\n const liveFrontier = (state.record ?? currentRecord).snapshotEndVersion;\n return {\n snapshotEndVersion: mergeVersionVectors([\n ...(liveFrontier.length > 0 ? [liveFrontier] : []),\n ...synced.decryptedUpdates.map(\n (update) =>\n getImportBlobMetadata(update.updateData).partialEndVersionVector,\n ),\n ]),\n };\n}\n\nfunction documentSyncSaveOptions(\n syncAttempt: DocumentSyncAttempt,\n): SaveDocumentRecordOptions {\n return {\n acceptedPendingUpdateIds: syncAttempt.synced.settledPendingUpdateIds,\n clearSyncFailure: shouldClearDocumentSyncFailureAfterPass(\n syncAttempt.synced,\n syncAttempt.outgoingUpdateCount,\n ),\n expectedSyncState: {\n pullContinuation: syncAttempt.consumedPullContinuation,\n record: syncAttempt.requestRecord,\n },\n historyUpdateOrigin: \"remote\",\n historyUpdates: pulledHistoryUpdates(syncAttempt.synced),\n preserveSnapshotStructuredFields: true,\n preserveSnapshotText: true,\n };\n}\n\nasync function persistSyncedDocument(\n state: DocumentStoreState,\n currentDoc: DocumentState,\n currentRecord: DocumentRecord,\n syncAttempt: DocumentSyncAttempt,\n generation: DocumentStoreSyncGeneration,\n) {\n const { synced } = syncAttempt;\n const updates = synced.decryptedUpdates;\n const candidate = currentDoc.fork();\n const previousDocumentId = state.record?.documentId ?? null;\n const options = documentSyncSaveOptions(syncAttempt);\n const isCurrent = () =>\n isDocumentStoreSyncGenerationCurrent(state, generation);\n try {\n importSyncedDocumentUpdates(candidate, updates);\n if (state.pendingBaseVersion === null) {\n throw new Error(\"Document sync requires an initialized pending base\");\n }\n const persisted = await saveDocumentRecord(\n state,\n candidate,\n {\n ...synced.persistedState,\n lastCommitLsn:\n synced.response.commitLsn ?? currentRecord.lastCommitLsn ?? null,\n pullContinuation: readPullContinuation(synced.response),\n ...coveredSyncFrontier(state, currentRecord, synced),\n },\n {\n ...options,\n pendingBaseVersionOverride: extendDocumentVersionCoverage({\n baseVersion: state.pendingBaseVersion,\n documentVersion: encodeVersionVector(candidate),\n spans: updates,\n }),\n },\n generation,\n );\n if (\n persisted &&\n isCurrent() &&\n !persisted.pullContinuationSuperseded &&\n !persisted.syncIdentitySuperseded\n ) {\n // Publish a remote edit only once its history and continuation commit.\n // Importing earlier lets a losing CAS expose text that the next local\n // write authors against an older, reloaded CRDT history.\n // The durable CAS already checked the request's complete context. The\n // successful row is now live, so publication uses that committed context\n // (which may contain refreshed keying metadata) and the same generation.\n applyIncomingSyncedUpdates(\n state,\n currentDoc,\n persisted.record,\n syncAttempt,\n generation,\n );\n }\n return await publishPersistedDocument(\n state,\n currentDoc,\n persisted,\n previousDocumentId,\n options,\n isCurrent,\n );\n } finally {\n candidate.free();\n }\n}\n\nexport function shouldReArmDocumentSync(\n state: DocumentStoreState,\n syncAttempt: DocumentSyncAttempt,\n): boolean {\n const { synced } = syncAttempt;\n const shouldReArmOutgoing = settleOutgoingPassAndDecideReArm(state, {\n exhaustedPendingUpdateCount: synced.exhaustedPendingUpdateCount,\n outgoingUpdateCount: syncAttempt.outgoingUpdateCount,\n rekeyedUpdateCount: synced.rekeyedPendingUpdateIds.length,\n settledUpdateCount: synced.settledPendingUpdateIds.length,\n acceptedRecoveryBaseline: synced.acceptedRecoveryBaseline,\n });\n return (\n synced.hasDeferredPendingUpdates ||\n synced.hasIncompletePull ||\n shouldReArmOutgoing\n );\n}\n\nexport async function finalizeDocumentSync(\n state: DocumentStoreState,\n currentDoc: DocumentState,\n currentRecord: DocumentRecord,\n syncAttempt: DocumentSyncAttempt,\n consumedRemoteUpdateSignalSeq: number,\n generation: DocumentStoreSyncGeneration,\n sentUpdateIds: readonly string[],\n wasRemoteProbe: boolean,\n): Promise<DocumentRecord> {\n const { synced } = syncAttempt;\n if (!isDocumentStoreSyncGenerationCurrent(state, generation)) {\n discardPreRegisteredUpdateIds(state, sentUpdateIds);\n requestDocumentStoreSync(state);\n return state.record ?? currentRecord;\n }\n\n // The sent IDs were pre-registered as self-authored before the network call so\n // the redis echo can never beat us. Reconcile against what the server actually\n // accepted: an ID we sent but the server did not accept will never be echoed,\n // so drop it to keep locallyAcceptedUpdateIds from leaking. Accepted IDs (a\n // subset of what we sent) stay registered until their echo consumes them.\n discardUnacceptedPreRegisteredUpdateIds(\n state,\n sentUpdateIds,\n synced.response.acceptedOutgoingUpdateIds,\n );\n // Persist on the identity-write chain: synced.persistedState carries this\n // pass's documentId, so it would clobber a relink that landed mid-pass. If\n // the identity moved, the response describes the OLD document — skip every\n // response-derived in-memory mutation and let the new identity's own sync\n // pass take over.\n let responseApplied = false;\n const { record: nextRecord } = await chainIdentityWrite(state, async () => {\n const liveRecord = state.record;\n if (\n !isDocumentStoreSyncGenerationCurrent(state, generation) ||\n !documentSyncContextMatches(\n liveRecord,\n currentRecord,\n synced.plan.documentId,\n )\n ) {\n return { record: liveRecord ?? currentRecord };\n }\n\n installDocumentWriterProjection(\n state,\n resolveSyncedDocumentWriterProjection(state, synced),\n syncAttempt.writerProjectionGeneration,\n );\n const persisted = await persistSyncedDocument(\n state,\n currentDoc,\n currentRecord,\n syncAttempt,\n generation,\n );\n if (\n !persisted ||\n !isDocumentStoreSyncGenerationCurrent(state, generation)\n ) {\n return { record: state.record ?? currentRecord };\n }\n\n state.pullContinuation = persisted.record.pullContinuation ?? null;\n if (persisted.pullContinuationSuperseded) {\n state.writerProjection = null;\n }\n // A CAS loss means neither this response's acknowledgements nor its\n // continuation were committed. Keep the pass unapplied so its signals and\n // accepted-id registrations cannot be cleared without a follow-up.\n responseApplied = !persisted.pullContinuationSuperseded;\n return persisted;\n });\n if (!responseApplied) {\n discardPreRegisteredUpdateIds(state, sentUpdateIds);\n requestDocumentStoreSync(state);\n return nextRecord;\n }\n\n if (!isDocumentStoreSyncGenerationCurrent(state, generation)) {\n discardPreRegisteredUpdateIds(state, sentUpdateIds);\n requestDocumentStoreSync(state);\n return state.record ?? nextRecord;\n }\n\n // A bounded pull request owns the whole page chain. Completing the signal on\n // an intermediate page would let a failed/null continuation pass report the\n // original request as successful even though the server frontier was never\n // drained.\n if (!synced.hasIncompletePull) {\n clearConsumedRemoteUpdateSignal(state, consumedRemoteUpdateSignalSeq);\n }\n\n if (shouldReArmDocumentSync(state, syncAttempt)) {\n requestDocumentStoreSync(state);\n }\n\n await hydrateAttachmentBlobs(state, currentDoc, nextRecord, generation);\n logApplied(state, currentDoc, synced.decryptedUpdates.length, wasRemoteProbe);\n return nextRecord;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"syncFinalize.js","sourceRoot":"","sources":["syncFinalize.ts"],"names":[],"mappings":"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","sourcesContent":["import { bytesToBase64 } from \"@tearleads/encoding\";\nimport {\n emptyVersionVector,\n encodeVersionVector,\n getImportBlobMetadata,\n mergeVersionVectors,\n} from \"@tearleads/loro\";\nimport { readPullContinuation } from \"../../../data/documents/shared/syncPagination\";\nimport {\n type DocumentRecord,\n settleOutgoingPassAndDecideReArm,\n shouldClearDocumentSyncFailureAfterPass,\n} from \"../../../workflows/documents\";\nimport { requestDocumentStoreSync } from \"../registry\";\nimport { hydrateAttachmentBlobs } from \"./attachmentHydration\";\nimport { chainIdentityWrite } from \"./identityWriteChain\";\nimport { publishPersistedDocument, saveDocumentRecord } from \"./persistence\";\nimport { logRevalidationApplied as logApplied } from \"./remoteRevalidationTelemetry\";\nimport type {\n DocumentState,\n DocumentStoreState,\n DocumentSyncAttempt,\n SaveDocumentRecordOptions,\n} from \"./state\";\nimport {\n discardPreRegisteredUpdateIds,\n discardUnacceptedPreRegisteredUpdateIds,\n} from \"./syncAcceptedUpdateIds\";\nimport {\n type DocumentStoreSyncGeneration,\n isDocumentStoreSyncGenerationCurrent,\n} from \"./syncGeneration\";\nimport { clearConsumedRemoteUpdateSignal } from \"./syncRemoteSignals\";\nimport {\n applyIncomingSyncedUpdates,\n documentSyncContextMatches,\n importSyncedDocumentUpdates,\n} from \"./syncUpdateImport\";\nimport { extendDocumentVersionCoverage } from \"./versionCoverage\";\nimport { installDocumentWriterProjection } from \"./writerProjectionGeneration\";\n\nfunction documentWriterProjectionMatchesSyncResponse(\n writerProjection: NonNullable<\n DocumentSyncAttempt[\"synced\"][\"writerProjection\"]\n >,\n synced: DocumentSyncAttempt[\"synced\"],\n): boolean {\n return (\n writerProjection.contentKeyBundle.contentKeyEpoch ===\n synced.response.contentKeyBundle.contentKeyEpoch &&\n writerProjection.contentKeyBundle.linkSetManifestHash ===\n synced.response.contentKeyBundle.linkSetManifestHash &&\n writerProjection.contentKeyBundle.targetHash ===\n synced.response.contentKeyBundle.targetHash &&\n writerProjection.documentKekTargets.linkSetManifestHash ===\n synced.response.documentKekTargets.linkSetManifestHash &&\n writerProjection.documentKekTargets.documentKeyTargetHash ===\n synced.response.documentKekTargets.documentKeyTargetHash\n );\n}\n\nfunction resolveSyncedDocumentWriterProjection(\n state: DocumentStoreState,\n synced: DocumentSyncAttempt[\"synced\"],\n) {\n const writerProjection =\n synced.writerProjection ??\n (state.writerProjection?.documentId === synced.plan.documentId\n ? state.writerProjection\n : null);\n return writerProjection &&\n documentWriterProjectionMatchesSyncResponse(writerProjection, synced)\n ? writerProjection\n : null;\n}\n\n/**\n * Durable-history tail: append pulled updates BEFORE the record persist so\n * the tail stays a superset of what the snapshot covers (duplicates are\n * idempotent by op identity; a crash between the writes can only leave the\n * safe superset).\n */\nfunction pulledHistoryUpdates(synced: DocumentSyncAttempt[\"synced\"]): string[] {\n return synced.decryptedUpdates.map((update) =>\n bytesToBase64(update.updateData),\n );\n}\n\n/**\n * The frontier a finalize persist may publish: the stored frontier advanced\n * by exactly the pulled updates just appended to the durable tail — never the\n * live document's version, which can transiently include an in-flight local\n * edit whose durable row has not landed yet.\n */\nfunction coveredSyncFrontier(\n state: DocumentStoreState,\n currentRecord: DocumentRecord,\n synced: DocumentSyncAttempt[\"synced\"],\n): { snapshotEndVersion: string } | Record<string, never> {\n const liveFrontier = (state.record ?? currentRecord).snapshotEndVersion;\n if (synced.decryptedUpdates.length === 0) {\n // A completed empty pull distinguishes a real blank note from discovery.\n // An intermediate page cannot establish that no content exists yet.\n return liveFrontier === \"\" && !synced.hasIncompletePull\n ? { snapshotEndVersion: emptyVersionVector() }\n : {};\n }\n return {\n snapshotEndVersion: mergeVersionVectors([\n ...(liveFrontier.length > 0 ? [liveFrontier] : []),\n ...synced.decryptedUpdates.map(\n (update) =>\n getImportBlobMetadata(update.updateData).partialEndVersionVector,\n ),\n ]),\n };\n}\n\nfunction documentSyncSaveOptions(\n syncAttempt: DocumentSyncAttempt,\n): SaveDocumentRecordOptions {\n return {\n acceptedPendingUpdateIds: syncAttempt.synced.settledPendingUpdateIds,\n clearSyncFailure: shouldClearDocumentSyncFailureAfterPass(\n syncAttempt.synced,\n syncAttempt.outgoingUpdateCount,\n ),\n expectedSyncState: {\n pullContinuation: syncAttempt.consumedPullContinuation,\n record: syncAttempt.requestRecord,\n },\n historyUpdateOrigin: \"remote\",\n historyUpdates: pulledHistoryUpdates(syncAttempt.synced),\n preserveSnapshotStructuredFields: true,\n preserveSnapshotText: true,\n };\n}\n\nasync function persistSyncedDocument(\n state: DocumentStoreState,\n currentDoc: DocumentState,\n currentRecord: DocumentRecord,\n syncAttempt: DocumentSyncAttempt,\n generation: DocumentStoreSyncGeneration,\n) {\n const { synced } = syncAttempt;\n const updates = synced.decryptedUpdates;\n const candidate = currentDoc.fork();\n const previousDocumentId = state.record?.documentId ?? null;\n const options = documentSyncSaveOptions(syncAttempt);\n const isCurrent = () =>\n isDocumentStoreSyncGenerationCurrent(state, generation);\n try {\n importSyncedDocumentUpdates(candidate, updates);\n if (state.pendingBaseVersion === null) {\n throw new Error(\"Document sync requires an initialized pending base\");\n }\n const persisted = await saveDocumentRecord(\n state,\n candidate,\n {\n ...synced.persistedState,\n lastCommitLsn:\n synced.response.commitLsn ?? currentRecord.lastCommitLsn ?? null,\n pullContinuation: readPullContinuation(synced.response),\n ...coveredSyncFrontier(state, currentRecord, synced),\n },\n {\n ...options,\n pendingBaseVersionOverride: extendDocumentVersionCoverage({\n baseVersion: state.pendingBaseVersion,\n documentVersion: encodeVersionVector(candidate),\n spans: updates,\n }),\n },\n generation,\n );\n if (\n persisted &&\n isCurrent() &&\n !persisted.pullContinuationSuperseded &&\n !persisted.syncIdentitySuperseded\n ) {\n // Publish a remote edit only once its history and continuation commit.\n // Importing earlier lets a losing CAS expose text that the next local\n // write authors against an older, reloaded CRDT history.\n // The durable CAS already checked the request's complete context. The\n // successful row is now live, so publication uses that committed context\n // (which may contain refreshed keying metadata) and the same generation.\n applyIncomingSyncedUpdates(\n state,\n currentDoc,\n persisted.record,\n syncAttempt,\n generation,\n );\n }\n return await publishPersistedDocument(\n state,\n currentDoc,\n persisted,\n previousDocumentId,\n options,\n isCurrent,\n );\n } finally {\n candidate.free();\n }\n}\n\nexport function shouldReArmDocumentSync(\n state: DocumentStoreState,\n syncAttempt: DocumentSyncAttempt,\n): boolean {\n const { synced } = syncAttempt;\n const shouldReArmOutgoing = settleOutgoingPassAndDecideReArm(state, {\n exhaustedPendingUpdateCount: synced.exhaustedPendingUpdateCount,\n outgoingUpdateCount: syncAttempt.outgoingUpdateCount,\n rekeyedUpdateCount: synced.rekeyedPendingUpdateIds.length,\n settledUpdateCount: synced.settledPendingUpdateIds.length,\n acceptedRecoveryBaseline: synced.acceptedRecoveryBaseline,\n });\n return (\n synced.hasDeferredPendingUpdates ||\n synced.hasIncompletePull ||\n shouldReArmOutgoing\n );\n}\n\nexport async function finalizeDocumentSync(\n state: DocumentStoreState,\n currentDoc: DocumentState,\n currentRecord: DocumentRecord,\n syncAttempt: DocumentSyncAttempt,\n consumedRemoteUpdateSignalSeq: number,\n generation: DocumentStoreSyncGeneration,\n sentUpdateIds: readonly string[],\n wasRemoteProbe: boolean,\n): Promise<DocumentRecord> {\n const { synced } = syncAttempt;\n if (!isDocumentStoreSyncGenerationCurrent(state, generation)) {\n discardPreRegisteredUpdateIds(state, sentUpdateIds);\n requestDocumentStoreSync(state);\n return state.record ?? currentRecord;\n }\n\n // The sent IDs were pre-registered as self-authored before the network call so\n // the redis echo can never beat us. Reconcile against what the server actually\n // accepted: an ID we sent but the server did not accept will never be echoed,\n // so drop it to keep locallyAcceptedUpdateIds from leaking. Accepted IDs (a\n // subset of what we sent) stay registered until their echo consumes them.\n discardUnacceptedPreRegisteredUpdateIds(\n state,\n sentUpdateIds,\n synced.response.acceptedOutgoingUpdateIds,\n );\n // Persist on the identity-write chain: synced.persistedState carries this\n // pass's documentId, so it would clobber a relink that landed mid-pass. If\n // the identity moved, the response describes the OLD document — skip every\n // response-derived in-memory mutation and let the new identity's own sync\n // pass take over.\n let responseApplied = false;\n const { record: nextRecord } = await chainIdentityWrite(state, async () => {\n const liveRecord = state.record;\n if (\n !isDocumentStoreSyncGenerationCurrent(state, generation) ||\n !documentSyncContextMatches(\n liveRecord,\n currentRecord,\n synced.plan.documentId,\n )\n ) {\n return { record: liveRecord ?? currentRecord };\n }\n\n installDocumentWriterProjection(\n state,\n resolveSyncedDocumentWriterProjection(state, synced),\n syncAttempt.writerProjectionGeneration,\n );\n const persisted = await persistSyncedDocument(\n state,\n currentDoc,\n currentRecord,\n syncAttempt,\n generation,\n );\n if (\n !persisted ||\n !isDocumentStoreSyncGenerationCurrent(state, generation)\n ) {\n return { record: state.record ?? currentRecord };\n }\n\n state.pullContinuation = persisted.record.pullContinuation ?? null;\n if (persisted.pullContinuationSuperseded) {\n state.writerProjection = null;\n }\n // A CAS loss means neither this response's acknowledgements nor its\n // continuation were committed. Keep the pass unapplied so its signals and\n // accepted-id registrations cannot be cleared without a follow-up.\n responseApplied = !persisted.pullContinuationSuperseded;\n return persisted;\n });\n if (!responseApplied) {\n discardPreRegisteredUpdateIds(state, sentUpdateIds);\n requestDocumentStoreSync(state);\n return nextRecord;\n }\n\n if (!isDocumentStoreSyncGenerationCurrent(state, generation)) {\n discardPreRegisteredUpdateIds(state, sentUpdateIds);\n requestDocumentStoreSync(state);\n return state.record ?? nextRecord;\n }\n\n // A bounded pull request owns the whole page chain. Completing the signal on\n // an intermediate page would let a failed/null continuation pass report the\n // original request as successful even though the server frontier was never\n // drained.\n if (!synced.hasIncompletePull) {\n clearConsumedRemoteUpdateSignal(state, consumedRemoteUpdateSignalSeq);\n }\n\n if (shouldReArmDocumentSync(state, syncAttempt)) {\n requestDocumentStoreSync(state);\n }\n\n await hydrateAttachmentBlobs(state, currentDoc, nextRecord, generation);\n logApplied(state, currentDoc, synced.decryptedUpdates.length, wasRemoteProbe);\n return nextRecord;\n}\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { emptyVersionVector } from "../../../internal/loro/index.js";
|
|
2
|
+
// Discovery persists a shell before its first content pull. Keep those rows
|
|
3
|
+
// available to sync, but out of Explorer's selectable, paginated projections.
|
|
4
|
+
export function emptyContentFrontierSql(alias) {
|
|
5
|
+
return `(${alias}.snapshot_end_version = '' OR (${alias}.app_kind = 'container-metadata' AND ${alias}.snapshot_end_version = '${emptyVersionVector()}'))`;
|
|
6
|
+
}
|
|
7
|
+
export function hydratedProjectionSql(localId, appKind) {
|
|
8
|
+
return `NOT EXISTS (
|
|
9
|
+
SELECT 1 FROM documents hydration
|
|
10
|
+
WHERE hydration.app_kind = '${appKind}'
|
|
11
|
+
AND hydration.local_id = ${localId}
|
|
12
|
+
AND hydration.document_id IS NOT NULL
|
|
13
|
+
AND ${emptyContentFrontierSql("hydration")}
|
|
14
|
+
)`;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=hydrationSql.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hydrationSql.js","sourceRoot":"","sources":["hydrationSql.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErD,4EAA4E;AAC5E,8EAA8E;AAC9E,MAAM,UAAU,uBAAuB,CAAC,KAAa;IACnD,OAAO,IAAI,KAAK,kCAAkC,KAAK,wCAAwC,KAAK,4BAA4B,kBAAkB,EAAE,KAAK,CAAC;AAC5J,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,OAAe,EACf,OAA2C;IAE3C,OAAO;;kCAEyB,OAAO;iCACR,OAAO;;YAE5B,uBAAuB,CAAC,WAAW,CAAC;IAC5C,CAAC;AACL,CAAC","sourcesContent":["import { emptyVersionVector } from \"@tearleads/loro\";\n\n// Discovery persists a shell before its first content pull. Keep those rows\n// available to sync, but out of Explorer's selectable, paginated projections.\nexport function emptyContentFrontierSql(alias: string): string {\n return `(${alias}.snapshot_end_version = '' OR (${alias}.app_kind = 'container-metadata' AND ${alias}.snapshot_end_version = '${emptyVersionVector()}'))`;\n}\n\nexport function hydratedProjectionSql(\n localId: string,\n appKind: \"documents\" | \"container-metadata\",\n): string {\n return `NOT EXISTS (\n SELECT 1 FROM documents hydration\n WHERE hydration.app_kind = '${appKind}'\n AND hydration.local_id = ${localId}\n AND hydration.document_id IS NOT NULL\n AND ${emptyContentFrontierSql(\"hydration\")}\n )`;\n}\n"]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getOrphanedDocumentWhereSql } from "../orphanedDocumentSql.js";
|
|
2
|
+
import { hydratedProjectionSql } from "./hydrationSql.js";
|
|
2
3
|
// Keep each IN clause below SQLite's historical 999 bind-parameter limit.
|
|
3
4
|
const CONTAINER_DOCUMENT_SQL_ID_BATCH_SIZE = 500;
|
|
4
5
|
const MAX_CONTAINER_ITEM_WINDOW_LIMIT = 200;
|
|
@@ -140,6 +141,7 @@ export function getContainerContentsContainerItemsBaseSql(visibleSystemSlotCount
|
|
|
140
141
|
LEFT JOIN pending_container_create_intents create_intent
|
|
141
142
|
ON create_intent.container_id = c.id
|
|
142
143
|
WHERE c.parent_id = ?
|
|
144
|
+
AND ${hydratedProjectionSql("c.id", "container-metadata")}
|
|
143
145
|
AND ${getContainerContentsContainerSystemSlotFilter({
|
|
144
146
|
visibleForeignSystemContainerNameCount,
|
|
145
147
|
visibleSystemSlotCount,
|
|
@@ -171,7 +173,8 @@ export function getContainerContentsContainerItemsBaseSql(visibleSystemSlotCount
|
|
|
171
173
|
ON document_updates.local_id = d.local_id
|
|
172
174
|
LEFT JOIN document_pending_attachment_counts document_attachments
|
|
173
175
|
ON document_attachments.local_id = d.local_id
|
|
174
|
-
WHERE
|
|
176
|
+
WHERE ${hydratedProjectionSql("d.local_id", "documents")}
|
|
177
|
+
AND d.container_id = ?${getHeldPlacementExclusionSql("d.document_id", "d.container_id")}
|
|
175
178
|
|
|
176
179
|
UNION ALL
|
|
177
180
|
|
|
@@ -200,7 +203,8 @@ export function getContainerContentsContainerItemsBaseSql(visibleSystemSlotCount
|
|
|
200
203
|
ON document_updates.local_id = d.local_id
|
|
201
204
|
LEFT JOIN document_pending_attachment_counts document_attachments
|
|
202
205
|
ON document_attachments.local_id = d.local_id
|
|
203
|
-
WHERE
|
|
206
|
+
WHERE ${hydratedProjectionSql("d.local_id", "documents")}
|
|
207
|
+
AND linked.container_id = ?
|
|
204
208
|
AND (
|
|
205
209
|
d.container_id IS NULL
|
|
206
210
|
OR d.container_id != linked.container_id
|
|
@@ -229,7 +233,8 @@ export function getContainerContentsDocumentRowsBaseSql() {
|
|
|
229
233
|
ON document_updates.local_id = d.local_id
|
|
230
234
|
LEFT JOIN document_pending_attachment_counts document_attachments
|
|
231
235
|
ON document_attachments.local_id = d.local_id
|
|
232
|
-
WHERE
|
|
236
|
+
WHERE ${hydratedProjectionSql("d.local_id", "documents")}
|
|
237
|
+
AND d.container_id = ?${getHeldPlacementExclusionSql("d.document_id", "d.container_id")}
|
|
233
238
|
|
|
234
239
|
UNION ALL
|
|
235
240
|
|
|
@@ -249,7 +254,8 @@ export function getContainerContentsDocumentRowsBaseSql() {
|
|
|
249
254
|
ON document_updates.local_id = d.local_id
|
|
250
255
|
LEFT JOIN document_pending_attachment_counts document_attachments
|
|
251
256
|
ON document_attachments.local_id = d.local_id
|
|
252
|
-
WHERE
|
|
257
|
+
WHERE ${hydratedProjectionSql("d.local_id", "documents")}
|
|
258
|
+
AND linked.container_id = ?
|
|
253
259
|
AND (
|
|
254
260
|
d.container_id IS NULL
|
|
255
261
|
OR d.container_id != linked.container_id
|
|
@@ -287,7 +293,8 @@ export function getOrphanedDocumentItemsBaseSql() {
|
|
|
287
293
|
ON document_updates.local_id = d.local_id
|
|
288
294
|
LEFT JOIN document_pending_attachment_counts document_attachments
|
|
289
295
|
ON document_attachments.local_id = d.local_id
|
|
290
|
-
WHERE ${
|
|
296
|
+
WHERE ${hydratedProjectionSql("d.local_id", "documents")}
|
|
297
|
+
AND ${getOrphanedDocumentWhereSql({
|
|
291
298
|
documentIdSql: "d.document_id",
|
|
292
299
|
projectionAlias: "d",
|
|
293
300
|
})}
|
|
@@ -314,7 +321,8 @@ export function getOrphanedDocumentRowsBaseSql() {
|
|
|
314
321
|
ON document_updates.local_id = d.local_id
|
|
315
322
|
LEFT JOIN document_pending_attachment_counts document_attachments
|
|
316
323
|
ON document_attachments.local_id = d.local_id
|
|
317
|
-
WHERE ${
|
|
324
|
+
WHERE ${hydratedProjectionSql("d.local_id", "documents")}
|
|
325
|
+
AND ${getOrphanedDocumentWhereSql({
|
|
318
326
|
documentIdSql: "d.document_id",
|
|
319
327
|
projectionAlias: "d",
|
|
320
328
|
})}
|
|
@@ -324,7 +332,8 @@ export function getOrphanedDocumentExistsSql() {
|
|
|
324
332
|
return `
|
|
325
333
|
SELECT 1
|
|
326
334
|
FROM document_projection d
|
|
327
|
-
WHERE ${
|
|
335
|
+
WHERE ${hydratedProjectionSql("d.local_id", "documents")}
|
|
336
|
+
AND ${getOrphanedDocumentWhereSql({
|
|
328
337
|
documentIdSql: "d.document_id",
|
|
329
338
|
projectionAlias: "d",
|
|
330
339
|
})}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sql.js","sourceRoot":"","sources":["sql.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAC;AAGrE,0EAA0E;AAC1E,MAAM,oCAAoC,GAAG,GAAG,CAAC;AACjD,MAAM,+BAA+B,GAAG,GAAG,CAAC;AAC5C,MAAM,2CAA2C,GAAG,GAAG,CAAC;AAExD,MAAM,UAAU,iCAAiC,CAC/C,MAA6B;IAE7B,MAAM,OAAO,GAAe,EAAE,CAAC;IAE/B,KACE,IAAI,KAAK,GAAG,CAAC,EACb,KAAK,GAAG,MAAM,CAAC,MAAM,EACrB,KAAK,IAAI,oCAAoC,EAC7C,CAAC;QACD,OAAO,CAAC,IAAI,CACV,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG,oCAAoC,CAAC,CAClE,CAAC;IACJ,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,6BAA6B,CAAC,KAAa;IACzD,OAAO,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,KAAa;IACvD,OAAO,IAAI,CAAC,GAAG,CACb,+BAA+B,EAC/B,6BAA6B,CAAC,KAAK,CAAC,CACrC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,sCAAsC,CAAC,KAAa;IAClE,OAAO,IAAI,CAAC,GAAG,CACb,2CAA2C,EAC3C,6BAA6B,CAAC,KAAK,CAAC,CACrC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,wCAAwC,CACtD,IAAuB;IAEvB,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;IAE7D,IAAI,IAAI,CAAC,GAAG,KAAK,MAAM,EAAE,CAAC;QACxB,OAAO,4BAA4B,SAAS,4DAA4D,CAAC;IAC3G,CAAC;IAED,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,sCAAsC,SAAS,wCAAwC,CAAC;IACjG,CAAC;IAED,IAAI,IAAI,CAAC,GAAG,KAAK,UAAU,EAAE,CAAC;QAC5B,OAAO,sCAAsC,SAAS,wCAAwC,CAAC;IACjG,CAAC;IAED,IAAI,IAAI,CAAC,GAAG,KAAK,MAAM,EAAE,CAAC;QACxB,OAAO,2CAA2C,SAAS,6CAA6C,CAAC;IAC3G,CAAC;IAED,OAAO,wFAAwF,CAAC;AAClG,CAAC;AAED,MAAM,UAAU,4CAA4C;IAC1D,OAAO;;;;;;;;;;;;;;;;;GAiBN,CAAC;AACJ,CAAC;AAOD,MAAM,UAAU,0BAA0B,CAAC,OAG1C;IACC,OAAO,YAAY,OAAO,CAAC,eAAe,4BAA4B,OAAO,CAAC,cAAc,kDAAkD,CAAC;AACjJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sCAAsC,CAAC,OAGtD;IACC,OAAO,mBAAmB,OAAO,CAAC,cAAc,iCAAiC,OAAO,CAAC,eAAe,wBAAwB,CAAC;AACnI,CAAC;AAED,SAAS,6CAA6C,CACpD,MAAmC;IAEnC,MAAM,OAAO,GAAG,CAAC,uBAAuB,CAAC,CAAC;IAE1C,IAAI,MAAM,CAAC,sBAAsB,GAAG,CAAC,EAAE,CAAC;QACtC,MAAM,4BAA4B,GAAG,KAAK,CAAC,IAAI,CAC7C,EAAE,MAAM,EAAE,MAAM,CAAC,sBAAsB,EAAE,EACzC,GAAG,EAAE,CAAC,GAAG,CACV,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,qBAAqB,4BAA4B,GAAG,CAAC,CAAC;IACrE,CAAC;IAED,IAAI,MAAM,CAAC,sCAAsC,GAAG,CAAC,EAAE,CAAC;QACtD,MAAM,4BAA4B,GAAG,KAAK,CAAC,IAAI,CAC7C,EAAE,MAAM,EAAE,MAAM,CAAC,sCAAsC,EAAE,EACzD,GAAG,EAAE,CAAC,GAAG,CACV,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACb,OAAO,CAAC,IAAI,CACV,2DAA2D,0BAA0B,CAAC,EAAE,cAAc,EAAE,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC,QAAQ,4BAA4B,IAAI,CAC9K,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC;AACrC,CAAC;AAED;;;;;GAKG;AACH,SAAS,4BAA4B,CACnC,aAAqB,EACrB,cAAsB;IAEtB,OAAO;;;;qCAI4B,aAAa;sCACZ,cAAc;;UAE1C,CAAC;AACX,CAAC;AAED,MAAM,UAAU,yCAAyC,CACvD,sBAAsB,GAAG,CAAC,EAC1B,sCAAsC,GAAG,CAAC;IAE1C,OAAO;WACE,4CAA4C,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAkC/C,0BAA0B,CAAC,EAAE,cAAc,EAAE,GAAG,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC;;;;;;;;;;;cAWtE,6CAA6C,CAAC;QAClD,sCAAsC;QACtC,sBAAsB;KACvB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCA4BsB,4BAA4B,CAAC,eAAe,EAAE,gBAAgB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAiCpF,4BAA4B,CAAC,oBAAoB,EAAE,qBAAqB,CAAC;;;;GAIjF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,uCAAuC;IACrD,OAAO;WACE,4CAA4C,EAAE;;;;;;;;;;;;;;;;;gCAiBzB,4BAA4B,CAAC,eAAe,EAAE,gBAAgB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;WAwBpF,4BAA4B,CAAC,oBAAoB,EAAE,qBAAqB,CAAC;;;;GAIjF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,+BAA+B;IAC7C,OAAO;WACE,4CAA4C,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;cA0B3C,2BAA2B,CAAC;QAClC,aAAa,EAAE,eAAe;QAC9B,eAAe,EAAE,GAAG;KACrB,CAAC;;;;GAIL,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,8BAA8B;IAC5C,OAAO;WACE,4CAA4C,EAAE;;;;;;;;;;;;;;;;YAgB7C,2BAA2B,CAAC;QAClC,aAAa,EAAE,eAAe;QAC9B,eAAe,EAAE,GAAG;KACrB,CAAC;GACH,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,4BAA4B;IAC1C,OAAO;;;YAGG,2BAA2B,CAAC;QAClC,aAAa,EAAE,eAAe;QAC9B,eAAe,EAAE,GAAG;KACrB,CAAC;;GAEH,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mDAAmD;IACjE,OAAO,iFAAiF,CAAC;AAC3F,CAAC","sourcesContent":["import { getOrphanedDocumentWhereSql } from \"../orphanedDocumentSql\";\nimport type { ContainerItemSort } from \"./types\";\n\n// Keep each IN clause below SQLite's historical 999 bind-parameter limit.\nconst CONTAINER_DOCUMENT_SQL_ID_BATCH_SIZE = 500;\nconst MAX_CONTAINER_ITEM_WINDOW_LIMIT = 200;\nconst MAX_CONTAINER_DOCUMENT_SIDEBAR_WINDOW_LIMIT = 200;\n\nexport function listContainerContentsSqlIdBatches(\n values: ReadonlyArray<string>,\n): ReadonlyArray<ReadonlyArray<string>> {\n const batches: string[][] = [];\n\n for (\n let index = 0;\n index < values.length;\n index += CONTAINER_DOCUMENT_SQL_ID_BATCH_SIZE\n ) {\n batches.push(\n values.slice(index, index + CONTAINER_DOCUMENT_SQL_ID_BATCH_SIZE),\n );\n }\n\n return batches;\n}\n\nexport function clampContainerItemWindowValue(value: number): number {\n return Number.isFinite(value) ? Math.max(0, Math.floor(value)) : 0;\n}\n\nexport function getContainerItemWindowLimit(limit: number): number {\n return Math.min(\n MAX_CONTAINER_ITEM_WINDOW_LIMIT,\n clampContainerItemWindowValue(limit),\n );\n}\n\nexport function getContainerDocumentSidebarWindowLimit(limit: number): number {\n return Math.min(\n MAX_CONTAINER_DOCUMENT_SIDEBAR_WINDOW_LIMIT,\n clampContainerItemWindowValue(limit),\n );\n}\n\nexport function getContainerContentsContainerItemOrderBy(\n sort: ContainerItemSort,\n): string {\n const direction = sort.direction === \"desc\" ? \"DESC\" : \"ASC\";\n\n if (sort.key === \"type\") {\n return `type_sort COLLATE NOCASE ${direction}, name COLLATE NOCASE ASC, item_kind_sort ASC, item_id ASC`;\n }\n\n if (sort.key === \"created\") {\n return `created_at IS NULL ASC, created_at ${direction}, name COLLATE NOCASE ASC, item_id ASC`;\n }\n\n if (sort.key === \"modified\") {\n return `updated_at IS NULL ASC, updated_at ${direction}, name COLLATE NOCASE ASC, item_id ASC`;\n }\n\n if (sort.key === \"name\") {\n return `item_kind_sort ASC, name COLLATE NOCASE ${direction}, type_sort COLLATE NOCASE ASC, item_id ASC`;\n }\n\n return \"item_kind_sort ASC, name COLLATE NOCASE ASC, type_sort COLLATE NOCASE ASC, item_id ASC\";\n}\n\nexport function getContainerContentsDocumentPendingStateCtes(): string {\n return `\n document_pending_update_counts AS (\n SELECT\n local_id,\n COUNT(*) AS pending_update_count\n FROM document_pending_updates\n WHERE app_kind = 'documents'\n GROUP BY local_id\n ),\n document_pending_attachment_counts AS (\n SELECT\n local_id,\n COUNT(*) AS pending_attachment_count,\n COALESCE(SUM(byte_length), 0) AS pending_attachment_bytes\n FROM document_pending_attachments\n GROUP BY local_id\n )\n `;\n}\n\ninterface ContainerSystemFilterCounts {\n visibleForeignSystemContainerNameCount: number;\n visibleSystemSlotCount: number;\n}\n\nexport function getContainerDisplayNameSql(aliases: {\n containerAlias: string;\n projectionAlias: string;\n}): string {\n return `COALESCE(${aliases.projectionAlias}.display_name, CASE WHEN ${aliases.containerAlias}.parent_id IS NULL THEN '/' ELSE 'Untitled' END)`;\n}\n\n/**\n * Display attribution for an object reached through a container: the\n * container's organization when attached, else the projection row's own.\n */\nexport function getContainerOrganizationAttributionSql(aliases: {\n containerAlias: string;\n projectionAlias: string;\n}): string {\n return `COALESCE(NULLIF(${aliases.containerAlias}.organization_id, ''), NULLIF(${aliases.projectionAlias}.organization_id, ''))`;\n}\n\nfunction getContainerContentsContainerSystemSlotFilter(\n counts: ContainerSystemFilterCounts,\n): string {\n const clauses = [\"c.system_slot IS NULL\"];\n\n if (counts.visibleSystemSlotCount > 0) {\n const visibleSystemSlotBindMarkers = Array.from(\n { length: counts.visibleSystemSlotCount },\n () => \"?\",\n ).join(\", \");\n clauses.push(`c.system_slot IN (${visibleSystemSlotBindMarkers})`);\n }\n\n if (counts.visibleForeignSystemContainerNameCount > 0) {\n const visibleSystemNameBindMarkers = Array.from(\n { length: counts.visibleForeignSystemContainerNameCount },\n () => \"?\",\n ).join(\", \");\n clauses.push(\n `(c.organization_id != '' AND c.organization_id != ? AND ${getContainerDisplayNameSql({ containerAlias: \"c\", projectionAlias: \"cp\" })} IN (${visibleSystemNameBindMarkers}))`,\n );\n }\n\n return `(${clauses.join(\" OR \")})`;\n}\n\n/**\n * A `(document, container)` placement under a tombstone hold is hidden from\n * container views: the server said the document left the container, but the\n * signed head that would prove it is not yet available, so the row is kept\n * and hidden rather than deleted (`container_document_tombstone_holds`).\n */\nfunction getHeldPlacementExclusionSql(\n documentIdSql: string,\n containerIdSql: string,\n): string {\n return `\n AND NOT EXISTS (\n SELECT 1\n FROM container_document_tombstone_holds hold\n WHERE hold.document_id = ${documentIdSql}\n AND hold.container_id = ${containerIdSql}\n AND hold.hidden = 1\n )`;\n}\n\nexport function getContainerContentsContainerItemsBaseSql(\n visibleSystemSlotCount = 0,\n visibleForeignSystemContainerNameCount = 0,\n): string {\n return `\n WITH ${getContainerContentsDocumentPendingStateCtes()},\n container_metadata_pending_update_counts AS (\n SELECT\n local_id,\n COUNT(*) AS pending_update_count\n FROM document_pending_updates\n WHERE app_kind = 'container-metadata'\n GROUP BY local_id\n ),\n pending_container_create_intents AS (\n SELECT\n container_id,\n MAX(last_error) AS last_error\n FROM container_create_intents\n WHERE intent_type = 'container.create'\n AND sync_status = 'pending'\n GROUP BY container_id\n ),\n container_items AS (\n SELECT\n 'container' AS item_kind,\n 0 AS item_kind_sort,\n c.id AS item_id,\n NULL AS document_id,\n NULL AS document_kind,\n c.metadata_document_id AS metadata_document_id,\n c.local_updated_at AS local_updated_at,\n c.server_created_at AS server_created_at,\n c.server_updated_at AS server_updated_at,\n cp.icon AS icon,\n COALESCE(container_updates.pending_update_count, 0) AS pending_update_count,\n 0 AS pending_attachment_count,\n 0 AS pending_attachment_bytes,\n create_intent.last_error AS sync_last_error,\n ${getContainerDisplayNameSql({ containerAlias: \"c\", projectionAlias: \"cp\" })} AS name,\n 'folder' AS type_sort,\n COALESCE(c.server_created_at, c.local_created_at) AS created_at,\n COALESCE(c.server_updated_at, c.local_updated_at) AS updated_at\n FROM containers c\n LEFT JOIN container_projection cp ON cp.container_id = c.id\n LEFT JOIN container_metadata_pending_update_counts container_updates\n ON container_updates.local_id = c.id\n LEFT JOIN pending_container_create_intents create_intent\n ON create_intent.container_id = c.id\n WHERE c.parent_id = ?\n AND ${getContainerContentsContainerSystemSlotFilter({\n visibleForeignSystemContainerNameCount,\n visibleSystemSlotCount,\n })}\n\n UNION ALL\n\n SELECT\n 'document' AS item_kind,\n 1 AS item_kind_sort,\n d.local_id AS item_id,\n d.document_id AS document_id,\n d.document_kind AS document_kind,\n NULL AS metadata_document_id,\n NULL AS local_updated_at,\n NULL AS server_created_at,\n NULL AS server_updated_at,\n NULL AS icon,\n COALESCE(document_updates.pending_update_count, 0) AS pending_update_count,\n COALESCE(document_attachments.pending_attachment_count, 0) AS pending_attachment_count,\n COALESCE(document_attachments.pending_attachment_bytes, 0) AS pending_attachment_bytes,\n NULL AS sync_last_error,\n d.title AS name,\n d.document_kind AS type_sort,\n d.updated_at AS created_at,\n d.updated_at AS updated_at\n FROM document_projection d\n LEFT JOIN document_pending_update_counts document_updates\n ON document_updates.local_id = d.local_id\n LEFT JOIN document_pending_attachment_counts document_attachments\n ON document_attachments.local_id = d.local_id\n WHERE d.container_id = ?${getHeldPlacementExclusionSql(\"d.document_id\", \"d.container_id\")}\n\n UNION ALL\n\n SELECT\n 'document' AS item_kind,\n 1 AS item_kind_sort,\n d.local_id AS item_id,\n d.document_id AS document_id,\n d.document_kind AS document_kind,\n NULL AS metadata_document_id,\n NULL AS local_updated_at,\n NULL AS server_created_at,\n NULL AS server_updated_at,\n NULL AS icon,\n COALESCE(document_updates.pending_update_count, 0) AS pending_update_count,\n COALESCE(document_attachments.pending_attachment_count, 0) AS pending_attachment_count,\n COALESCE(document_attachments.pending_attachment_bytes, 0) AS pending_attachment_bytes,\n NULL AS sync_last_error,\n d.title AS name,\n d.document_kind AS type_sort,\n d.updated_at AS created_at,\n d.updated_at AS updated_at\n FROM document_container_projection linked\n INNER JOIN document_projection d ON d.document_id = linked.document_id\n LEFT JOIN document_pending_update_counts document_updates\n ON document_updates.local_id = d.local_id\n LEFT JOIN document_pending_attachment_counts document_attachments\n ON document_attachments.local_id = d.local_id\n WHERE linked.container_id = ?\n AND (\n d.container_id IS NULL\n OR d.container_id != linked.container_id\n )${getHeldPlacementExclusionSql(\"linked.document_id\", \"linked.container_id\")}\n )\n SELECT *\n FROM container_items\n `;\n}\n\nexport function getContainerContentsDocumentRowsBaseSql(): string {\n return `\n WITH ${getContainerContentsDocumentPendingStateCtes()},\n container_documents AS (\n SELECT\n d.local_id AS local_id,\n d.document_id AS document_id,\n d.container_id AS container_id,\n d.document_kind AS document_kind,\n COALESCE(document_updates.pending_update_count, 0) AS pending_update_count,\n COALESCE(document_attachments.pending_attachment_count, 0) AS pending_attachment_count,\n COALESCE(document_attachments.pending_attachment_bytes, 0) AS pending_attachment_bytes,\n d.title AS title,\n d.updated_at AS updated_at\n FROM document_projection d\n LEFT JOIN document_pending_update_counts document_updates\n ON document_updates.local_id = d.local_id\n LEFT JOIN document_pending_attachment_counts document_attachments\n ON document_attachments.local_id = d.local_id\n WHERE d.container_id = ?${getHeldPlacementExclusionSql(\"d.document_id\", \"d.container_id\")}\n\n UNION ALL\n\n SELECT\n d.local_id AS local_id,\n d.document_id AS document_id,\n linked.container_id AS container_id,\n d.document_kind AS document_kind,\n COALESCE(document_updates.pending_update_count, 0) AS pending_update_count,\n COALESCE(document_attachments.pending_attachment_count, 0) AS pending_attachment_count,\n COALESCE(document_attachments.pending_attachment_bytes, 0) AS pending_attachment_bytes,\n d.title AS title,\n d.updated_at AS updated_at\n FROM document_container_projection linked\n INNER JOIN document_projection d ON d.document_id = linked.document_id\n LEFT JOIN document_pending_update_counts document_updates\n ON document_updates.local_id = d.local_id\n LEFT JOIN document_pending_attachment_counts document_attachments\n ON document_attachments.local_id = d.local_id\n WHERE linked.container_id = ?\n AND (\n d.container_id IS NULL\n OR d.container_id != linked.container_id\n )${getHeldPlacementExclusionSql(\"linked.document_id\", \"linked.container_id\")}\n )\n SELECT *\n FROM container_documents\n `;\n}\n\nexport function getOrphanedDocumentItemsBaseSql(): string {\n return `\n WITH ${getContainerContentsDocumentPendingStateCtes()},\n orphaned_document_items AS (\n SELECT\n 'document' AS item_kind,\n 1 AS item_kind_sort,\n d.local_id AS item_id,\n d.document_id AS document_id,\n d.document_kind AS document_kind,\n NULL AS metadata_document_id,\n NULL AS local_updated_at,\n NULL AS server_created_at,\n NULL AS server_updated_at,\n NULL AS icon,\n COALESCE(document_updates.pending_update_count, 0) AS pending_update_count,\n COALESCE(document_attachments.pending_attachment_count, 0) AS pending_attachment_count,\n COALESCE(document_attachments.pending_attachment_bytes, 0) AS pending_attachment_bytes,\n NULL AS sync_last_error,\n d.title AS name,\n d.document_kind AS type_sort,\n d.updated_at AS created_at,\n d.updated_at AS updated_at\n FROM document_projection d\n LEFT JOIN document_pending_update_counts document_updates\n ON document_updates.local_id = d.local_id\n LEFT JOIN document_pending_attachment_counts document_attachments\n ON document_attachments.local_id = d.local_id\n WHERE ${getOrphanedDocumentWhereSql({\n documentIdSql: \"d.document_id\",\n projectionAlias: \"d\",\n })}\n )\n SELECT *\n FROM orphaned_document_items\n `;\n}\n\nexport function getOrphanedDocumentRowsBaseSql(): string {\n return `\n WITH ${getContainerContentsDocumentPendingStateCtes()}\n SELECT\n d.local_id AS local_id,\n d.document_id AS document_id,\n d.container_id AS container_id,\n d.document_kind AS document_kind,\n COALESCE(document_updates.pending_update_count, 0) AS pending_update_count,\n COALESCE(document_attachments.pending_attachment_count, 0) AS pending_attachment_count,\n COALESCE(document_attachments.pending_attachment_bytes, 0) AS pending_attachment_bytes,\n d.title AS title,\n d.updated_at AS updated_at\n FROM document_projection d\n LEFT JOIN document_pending_update_counts document_updates\n ON document_updates.local_id = d.local_id\n LEFT JOIN document_pending_attachment_counts document_attachments\n ON document_attachments.local_id = d.local_id\n WHERE ${getOrphanedDocumentWhereSql({\n documentIdSql: \"d.document_id\",\n projectionAlias: \"d\",\n })}\n `;\n}\n\nexport function getOrphanedDocumentExistsSql(): string {\n return `\n SELECT 1\n FROM document_projection d\n WHERE ${getOrphanedDocumentWhereSql({\n documentIdSql: \"d.document_id\",\n projectionAlias: \"d\",\n })}\n LIMIT 1\n `;\n}\n\nexport function getContainerContentsContainerDocumentSidebarOrderBy(): string {\n return \"updated_at IS NULL ASC, updated_at DESC, title COLLATE NOCASE ASC, local_id ASC\";\n}\n"]}
|
|
1
|
+
{"version":3,"file":"sql.js","sourceRoot":"","sources":["sql.ts"],"names":[],"mappings":"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","sourcesContent":["import { getOrphanedDocumentWhereSql } from \"../orphanedDocumentSql\";\nimport { hydratedProjectionSql } from \"./hydrationSql\";\nimport type { ContainerItemSort } from \"./types\";\n\n// Keep each IN clause below SQLite's historical 999 bind-parameter limit.\nconst CONTAINER_DOCUMENT_SQL_ID_BATCH_SIZE = 500;\nconst MAX_CONTAINER_ITEM_WINDOW_LIMIT = 200;\nconst MAX_CONTAINER_DOCUMENT_SIDEBAR_WINDOW_LIMIT = 200;\n\nexport function listContainerContentsSqlIdBatches(\n values: ReadonlyArray<string>,\n): ReadonlyArray<ReadonlyArray<string>> {\n const batches: string[][] = [];\n\n for (\n let index = 0;\n index < values.length;\n index += CONTAINER_DOCUMENT_SQL_ID_BATCH_SIZE\n ) {\n batches.push(\n values.slice(index, index + CONTAINER_DOCUMENT_SQL_ID_BATCH_SIZE),\n );\n }\n\n return batches;\n}\n\nexport function clampContainerItemWindowValue(value: number): number {\n return Number.isFinite(value) ? Math.max(0, Math.floor(value)) : 0;\n}\n\nexport function getContainerItemWindowLimit(limit: number): number {\n return Math.min(\n MAX_CONTAINER_ITEM_WINDOW_LIMIT,\n clampContainerItemWindowValue(limit),\n );\n}\n\nexport function getContainerDocumentSidebarWindowLimit(limit: number): number {\n return Math.min(\n MAX_CONTAINER_DOCUMENT_SIDEBAR_WINDOW_LIMIT,\n clampContainerItemWindowValue(limit),\n );\n}\n\nexport function getContainerContentsContainerItemOrderBy(\n sort: ContainerItemSort,\n): string {\n const direction = sort.direction === \"desc\" ? \"DESC\" : \"ASC\";\n\n if (sort.key === \"type\") {\n return `type_sort COLLATE NOCASE ${direction}, name COLLATE NOCASE ASC, item_kind_sort ASC, item_id ASC`;\n }\n\n if (sort.key === \"created\") {\n return `created_at IS NULL ASC, created_at ${direction}, name COLLATE NOCASE ASC, item_id ASC`;\n }\n\n if (sort.key === \"modified\") {\n return `updated_at IS NULL ASC, updated_at ${direction}, name COLLATE NOCASE ASC, item_id ASC`;\n }\n\n if (sort.key === \"name\") {\n return `item_kind_sort ASC, name COLLATE NOCASE ${direction}, type_sort COLLATE NOCASE ASC, item_id ASC`;\n }\n\n return \"item_kind_sort ASC, name COLLATE NOCASE ASC, type_sort COLLATE NOCASE ASC, item_id ASC\";\n}\n\nexport function getContainerContentsDocumentPendingStateCtes(): string {\n return `\n document_pending_update_counts AS (\n SELECT\n local_id,\n COUNT(*) AS pending_update_count\n FROM document_pending_updates\n WHERE app_kind = 'documents'\n GROUP BY local_id\n ),\n document_pending_attachment_counts AS (\n SELECT\n local_id,\n COUNT(*) AS pending_attachment_count,\n COALESCE(SUM(byte_length), 0) AS pending_attachment_bytes\n FROM document_pending_attachments\n GROUP BY local_id\n )\n `;\n}\n\ninterface ContainerSystemFilterCounts {\n visibleForeignSystemContainerNameCount: number;\n visibleSystemSlotCount: number;\n}\n\nexport function getContainerDisplayNameSql(aliases: {\n containerAlias: string;\n projectionAlias: string;\n}): string {\n return `COALESCE(${aliases.projectionAlias}.display_name, CASE WHEN ${aliases.containerAlias}.parent_id IS NULL THEN '/' ELSE 'Untitled' END)`;\n}\n\n/**\n * Display attribution for an object reached through a container: the\n * container's organization when attached, else the projection row's own.\n */\nexport function getContainerOrganizationAttributionSql(aliases: {\n containerAlias: string;\n projectionAlias: string;\n}): string {\n return `COALESCE(NULLIF(${aliases.containerAlias}.organization_id, ''), NULLIF(${aliases.projectionAlias}.organization_id, ''))`;\n}\n\nfunction getContainerContentsContainerSystemSlotFilter(\n counts: ContainerSystemFilterCounts,\n): string {\n const clauses = [\"c.system_slot IS NULL\"];\n\n if (counts.visibleSystemSlotCount > 0) {\n const visibleSystemSlotBindMarkers = Array.from(\n { length: counts.visibleSystemSlotCount },\n () => \"?\",\n ).join(\", \");\n clauses.push(`c.system_slot IN (${visibleSystemSlotBindMarkers})`);\n }\n\n if (counts.visibleForeignSystemContainerNameCount > 0) {\n const visibleSystemNameBindMarkers = Array.from(\n { length: counts.visibleForeignSystemContainerNameCount },\n () => \"?\",\n ).join(\", \");\n clauses.push(\n `(c.organization_id != '' AND c.organization_id != ? AND ${getContainerDisplayNameSql({ containerAlias: \"c\", projectionAlias: \"cp\" })} IN (${visibleSystemNameBindMarkers}))`,\n );\n }\n\n return `(${clauses.join(\" OR \")})`;\n}\n\n/**\n * A `(document, container)` placement under a tombstone hold is hidden from\n * container views: the server said the document left the container, but the\n * signed head that would prove it is not yet available, so the row is kept\n * and hidden rather than deleted (`container_document_tombstone_holds`).\n */\nfunction getHeldPlacementExclusionSql(\n documentIdSql: string,\n containerIdSql: string,\n): string {\n return `\n AND NOT EXISTS (\n SELECT 1\n FROM container_document_tombstone_holds hold\n WHERE hold.document_id = ${documentIdSql}\n AND hold.container_id = ${containerIdSql}\n AND hold.hidden = 1\n )`;\n}\n\nexport function getContainerContentsContainerItemsBaseSql(\n visibleSystemSlotCount = 0,\n visibleForeignSystemContainerNameCount = 0,\n): string {\n return `\n WITH ${getContainerContentsDocumentPendingStateCtes()},\n container_metadata_pending_update_counts AS (\n SELECT\n local_id,\n COUNT(*) AS pending_update_count\n FROM document_pending_updates\n WHERE app_kind = 'container-metadata'\n GROUP BY local_id\n ),\n pending_container_create_intents AS (\n SELECT\n container_id,\n MAX(last_error) AS last_error\n FROM container_create_intents\n WHERE intent_type = 'container.create'\n AND sync_status = 'pending'\n GROUP BY container_id\n ),\n container_items AS (\n SELECT\n 'container' AS item_kind,\n 0 AS item_kind_sort,\n c.id AS item_id,\n NULL AS document_id,\n NULL AS document_kind,\n c.metadata_document_id AS metadata_document_id,\n c.local_updated_at AS local_updated_at,\n c.server_created_at AS server_created_at,\n c.server_updated_at AS server_updated_at,\n cp.icon AS icon,\n COALESCE(container_updates.pending_update_count, 0) AS pending_update_count,\n 0 AS pending_attachment_count,\n 0 AS pending_attachment_bytes,\n create_intent.last_error AS sync_last_error,\n ${getContainerDisplayNameSql({ containerAlias: \"c\", projectionAlias: \"cp\" })} AS name,\n 'folder' AS type_sort,\n COALESCE(c.server_created_at, c.local_created_at) AS created_at,\n COALESCE(c.server_updated_at, c.local_updated_at) AS updated_at\n FROM containers c\n LEFT JOIN container_projection cp ON cp.container_id = c.id\n LEFT JOIN container_metadata_pending_update_counts container_updates\n ON container_updates.local_id = c.id\n LEFT JOIN pending_container_create_intents create_intent\n ON create_intent.container_id = c.id\n WHERE c.parent_id = ?\n AND ${hydratedProjectionSql(\"c.id\", \"container-metadata\")}\n AND ${getContainerContentsContainerSystemSlotFilter({\n visibleForeignSystemContainerNameCount,\n visibleSystemSlotCount,\n })}\n\n UNION ALL\n\n SELECT\n 'document' AS item_kind,\n 1 AS item_kind_sort,\n d.local_id AS item_id,\n d.document_id AS document_id,\n d.document_kind AS document_kind,\n NULL AS metadata_document_id,\n NULL AS local_updated_at,\n NULL AS server_created_at,\n NULL AS server_updated_at,\n NULL AS icon,\n COALESCE(document_updates.pending_update_count, 0) AS pending_update_count,\n COALESCE(document_attachments.pending_attachment_count, 0) AS pending_attachment_count,\n COALESCE(document_attachments.pending_attachment_bytes, 0) AS pending_attachment_bytes,\n NULL AS sync_last_error,\n d.title AS name,\n d.document_kind AS type_sort,\n d.updated_at AS created_at,\n d.updated_at AS updated_at\n FROM document_projection d\n LEFT JOIN document_pending_update_counts document_updates\n ON document_updates.local_id = d.local_id\n LEFT JOIN document_pending_attachment_counts document_attachments\n ON document_attachments.local_id = d.local_id\n WHERE ${hydratedProjectionSql(\"d.local_id\", \"documents\")}\n AND d.container_id = ?${getHeldPlacementExclusionSql(\"d.document_id\", \"d.container_id\")}\n\n UNION ALL\n\n SELECT\n 'document' AS item_kind,\n 1 AS item_kind_sort,\n d.local_id AS item_id,\n d.document_id AS document_id,\n d.document_kind AS document_kind,\n NULL AS metadata_document_id,\n NULL AS local_updated_at,\n NULL AS server_created_at,\n NULL AS server_updated_at,\n NULL AS icon,\n COALESCE(document_updates.pending_update_count, 0) AS pending_update_count,\n COALESCE(document_attachments.pending_attachment_count, 0) AS pending_attachment_count,\n COALESCE(document_attachments.pending_attachment_bytes, 0) AS pending_attachment_bytes,\n NULL AS sync_last_error,\n d.title AS name,\n d.document_kind AS type_sort,\n d.updated_at AS created_at,\n d.updated_at AS updated_at\n FROM document_container_projection linked\n INNER JOIN document_projection d ON d.document_id = linked.document_id\n LEFT JOIN document_pending_update_counts document_updates\n ON document_updates.local_id = d.local_id\n LEFT JOIN document_pending_attachment_counts document_attachments\n ON document_attachments.local_id = d.local_id\n WHERE ${hydratedProjectionSql(\"d.local_id\", \"documents\")}\n AND linked.container_id = ?\n AND (\n d.container_id IS NULL\n OR d.container_id != linked.container_id\n )${getHeldPlacementExclusionSql(\"linked.document_id\", \"linked.container_id\")}\n )\n SELECT *\n FROM container_items\n `;\n}\n\nexport function getContainerContentsDocumentRowsBaseSql(): string {\n return `\n WITH ${getContainerContentsDocumentPendingStateCtes()},\n container_documents AS (\n SELECT\n d.local_id AS local_id,\n d.document_id AS document_id,\n d.container_id AS container_id,\n d.document_kind AS document_kind,\n COALESCE(document_updates.pending_update_count, 0) AS pending_update_count,\n COALESCE(document_attachments.pending_attachment_count, 0) AS pending_attachment_count,\n COALESCE(document_attachments.pending_attachment_bytes, 0) AS pending_attachment_bytes,\n d.title AS title,\n d.updated_at AS updated_at\n FROM document_projection d\n LEFT JOIN document_pending_update_counts document_updates\n ON document_updates.local_id = d.local_id\n LEFT JOIN document_pending_attachment_counts document_attachments\n ON document_attachments.local_id = d.local_id\n WHERE ${hydratedProjectionSql(\"d.local_id\", \"documents\")}\n AND d.container_id = ?${getHeldPlacementExclusionSql(\"d.document_id\", \"d.container_id\")}\n\n UNION ALL\n\n SELECT\n d.local_id AS local_id,\n d.document_id AS document_id,\n linked.container_id AS container_id,\n d.document_kind AS document_kind,\n COALESCE(document_updates.pending_update_count, 0) AS pending_update_count,\n COALESCE(document_attachments.pending_attachment_count, 0) AS pending_attachment_count,\n COALESCE(document_attachments.pending_attachment_bytes, 0) AS pending_attachment_bytes,\n d.title AS title,\n d.updated_at AS updated_at\n FROM document_container_projection linked\n INNER JOIN document_projection d ON d.document_id = linked.document_id\n LEFT JOIN document_pending_update_counts document_updates\n ON document_updates.local_id = d.local_id\n LEFT JOIN document_pending_attachment_counts document_attachments\n ON document_attachments.local_id = d.local_id\n WHERE ${hydratedProjectionSql(\"d.local_id\", \"documents\")}\n AND linked.container_id = ?\n AND (\n d.container_id IS NULL\n OR d.container_id != linked.container_id\n )${getHeldPlacementExclusionSql(\"linked.document_id\", \"linked.container_id\")}\n )\n SELECT *\n FROM container_documents\n `;\n}\n\nexport function getOrphanedDocumentItemsBaseSql(): string {\n return `\n WITH ${getContainerContentsDocumentPendingStateCtes()},\n orphaned_document_items AS (\n SELECT\n 'document' AS item_kind,\n 1 AS item_kind_sort,\n d.local_id AS item_id,\n d.document_id AS document_id,\n d.document_kind AS document_kind,\n NULL AS metadata_document_id,\n NULL AS local_updated_at,\n NULL AS server_created_at,\n NULL AS server_updated_at,\n NULL AS icon,\n COALESCE(document_updates.pending_update_count, 0) AS pending_update_count,\n COALESCE(document_attachments.pending_attachment_count, 0) AS pending_attachment_count,\n COALESCE(document_attachments.pending_attachment_bytes, 0) AS pending_attachment_bytes,\n NULL AS sync_last_error,\n d.title AS name,\n d.document_kind AS type_sort,\n d.updated_at AS created_at,\n d.updated_at AS updated_at\n FROM document_projection d\n LEFT JOIN document_pending_update_counts document_updates\n ON document_updates.local_id = d.local_id\n LEFT JOIN document_pending_attachment_counts document_attachments\n ON document_attachments.local_id = d.local_id\n WHERE ${hydratedProjectionSql(\"d.local_id\", \"documents\")}\n AND ${getOrphanedDocumentWhereSql({\n documentIdSql: \"d.document_id\",\n projectionAlias: \"d\",\n })}\n )\n SELECT *\n FROM orphaned_document_items\n `;\n}\n\nexport function getOrphanedDocumentRowsBaseSql(): string {\n return `\n WITH ${getContainerContentsDocumentPendingStateCtes()}\n SELECT\n d.local_id AS local_id,\n d.document_id AS document_id,\n d.container_id AS container_id,\n d.document_kind AS document_kind,\n COALESCE(document_updates.pending_update_count, 0) AS pending_update_count,\n COALESCE(document_attachments.pending_attachment_count, 0) AS pending_attachment_count,\n COALESCE(document_attachments.pending_attachment_bytes, 0) AS pending_attachment_bytes,\n d.title AS title,\n d.updated_at AS updated_at\n FROM document_projection d\n LEFT JOIN document_pending_update_counts document_updates\n ON document_updates.local_id = d.local_id\n LEFT JOIN document_pending_attachment_counts document_attachments\n ON document_attachments.local_id = d.local_id\n WHERE ${hydratedProjectionSql(\"d.local_id\", \"documents\")}\n AND ${getOrphanedDocumentWhereSql({\n documentIdSql: \"d.document_id\",\n projectionAlias: \"d\",\n })}\n `;\n}\n\nexport function getOrphanedDocumentExistsSql(): string {\n return `\n SELECT 1\n FROM document_projection d\n WHERE ${hydratedProjectionSql(\"d.local_id\", \"documents\")}\n AND ${getOrphanedDocumentWhereSql({\n documentIdSql: \"d.document_id\",\n projectionAlias: \"d\",\n })}\n LIMIT 1\n `;\n}\n\nexport function getContainerContentsContainerDocumentSidebarOrderBy(): string {\n return \"updated_at IS NULL ASC, updated_at DESC, title COLLATE NOCASE ASC, local_id ASC\";\n}\n"]}
|
|
@@ -3,6 +3,7 @@ import type { SyncWatermark } from "../../internal/validators/response/index.js"
|
|
|
3
3
|
import type { DiscoveredDocumentInput, DocumentSummary } from "../../data/documents/documentSummary.js";
|
|
4
4
|
import type { ContainerDocumentLinkInput, ContainerDocumentQueriesRuntime, ContainerDocumentSidebarWindow, ContainerDocumentTombstone, ContainerItemSort, ContainerItemWindow } from "./documentQueries/types.js";
|
|
5
5
|
import { type RecoveryFolder } from "./folderRecovery.js";
|
|
6
|
+
import { type PendingDownloadQueueItem } from "./pendingDownloads.js";
|
|
6
7
|
import { type PendingWriteQueueItem } from "./pendingWrites.js";
|
|
7
8
|
import type { ContainerDocumentObjectSyncState } from "./syncState.js";
|
|
8
9
|
export type { ContainerDocumentLinkInput, ContainerDocumentSidebarRow, ContainerDocumentTombstone, ContainerItemRow, ContainerItemSort, ContainerItemSortDirection, ContainerItemSortKey, } from "./documentQueries/types.js";
|
|
@@ -37,13 +38,17 @@ export interface ContainerDocumentQueries {
|
|
|
37
38
|
}): Promise<ContainerDocumentSidebarWindow>;
|
|
38
39
|
listContainerItemWindow(input: ListContainerItemWindowInput): Promise<ContainerItemWindow>;
|
|
39
40
|
loadDocumentSyncState(localId: string): Promise<ContainerDocumentObjectSyncState | null>;
|
|
40
|
-
loadDocumentSummary(localId: string
|
|
41
|
+
loadDocumentSummary(localId: string, options?: {
|
|
42
|
+
requireHydrated?: boolean;
|
|
43
|
+
}): Promise<DocumentSummary | null>;
|
|
41
44
|
loadOrphanedDocumentSummary(input: {
|
|
45
|
+
requireHydrated?: boolean;
|
|
42
46
|
currentOrganizationId: string | null;
|
|
43
47
|
localId: string;
|
|
44
48
|
}): Promise<DocumentSummary | null>;
|
|
45
49
|
loadContainerDocumentWatermark(containerId: string): Promise<SyncWatermark | null>;
|
|
46
50
|
listLinkedContainerIdsByDocumentIds(documentIds: ReadonlyArray<string>): Promise<ReadonlyMap<string, ReadonlyArray<string>>>;
|
|
51
|
+
listPendingDownloads(): Promise<ReadonlyArray<PendingDownloadQueueItem>>;
|
|
47
52
|
listPendingWrites(): Promise<ReadonlyArray<PendingWriteQueueItem>>;
|
|
48
53
|
retryPendingWriteItem(input: {
|
|
49
54
|
localId: string;
|
|
@@ -5,10 +5,12 @@ import { sqlDocumentContainerProjectionPersistence } from "../../data/persistenc
|
|
|
5
5
|
import { applyContainerDocumentTombstones as applyPersistedContainerDocumentTombstones, sqlDocumentsPersistence, upsertDiscoveredDocuments, } from "../../data/persistence/documents/documentsPersistence.js";
|
|
6
6
|
import { containerCreateIntentTables } from "../../data/sqlite/schema.js";
|
|
7
7
|
import { ensureSqlTables } from "../../data/sqlite/sqlSchema.js";
|
|
8
|
+
import { hydratedProjectionSql } from "./documentQueries/hydrationSql.js";
|
|
8
9
|
import { mapContainerContentsDocumentSummaryRow, mapContainerContentsDocumentSyncStateRow, mapContainerDocumentSidebarRow, mapContainerItemRow, readContainerContentsContainerItemCount, } from "./documentQueries/rows.js";
|
|
9
10
|
import { clampContainerItemWindowValue, getContainerContentsContainerDocumentSidebarOrderBy, getContainerContentsContainerItemOrderBy, getContainerContentsContainerItemsBaseSql, getContainerContentsDocumentPendingStateCtes, getContainerContentsDocumentRowsBaseSql, getContainerDocumentSidebarWindowLimit, getContainerItemWindowLimit, getOrphanedDocumentExistsSql, getOrphanedDocumentItemsBaseSql, getOrphanedDocumentRowsBaseSql, listContainerContentsSqlIdBatches, } from "./documentQueries/sql.js";
|
|
10
11
|
import { createFolderRecoveryQueries, } from "./folderRecovery.js";
|
|
11
12
|
import { getOrphanedDocumentQueryBind, getOrphanedDocumentWhereSql, } from "./orphanedDocumentSql.js";
|
|
13
|
+
import { listPendingDownloads, } from "./pendingDownloads.js";
|
|
12
14
|
import { listPendingWrites, resetPendingWriteRetryState, } from "./pendingWrites.js";
|
|
13
15
|
async function listContainerItemWindow(execSql, input) {
|
|
14
16
|
await ensureContainerTables(execSql);
|
|
@@ -98,16 +100,18 @@ async function queryContainerContentsDocumentSummary(execSql, localId, scope) {
|
|
|
98
100
|
`, [localId, ...scope.bind]);
|
|
99
101
|
return mapContainerContentsDocumentSummaryRow(rows[0] ?? {});
|
|
100
102
|
}
|
|
101
|
-
function loadContainerContentsDocumentSummary(execSql, localId) {
|
|
103
|
+
function loadContainerContentsDocumentSummary(execSql, localId, requireHydrated) {
|
|
102
104
|
return queryContainerContentsDocumentSummary(execSql, localId, {
|
|
103
105
|
bind: [],
|
|
104
|
-
whereSql:
|
|
106
|
+
whereSql: requireHydrated
|
|
107
|
+
? `AND ${hydratedProjectionSql("d.local_id", "documents")}`
|
|
108
|
+
: "",
|
|
105
109
|
});
|
|
106
110
|
}
|
|
107
|
-
function loadContainerContentsOrphanedDocumentSummary(execSql, localId, currentOrganizationId) {
|
|
111
|
+
function loadContainerContentsOrphanedDocumentSummary(execSql, localId, currentOrganizationId, requireHydrated) {
|
|
108
112
|
return queryContainerContentsDocumentSummary(execSql, localId, {
|
|
109
113
|
bind: getOrphanedDocumentQueryBind(currentOrganizationId),
|
|
110
|
-
whereSql: `AND ${getOrphanedDocumentWhereSql({
|
|
114
|
+
whereSql: `${requireHydrated ? `AND ${hydratedProjectionSql("d.local_id", "documents")}` : ""} AND ${getOrphanedDocumentWhereSql({
|
|
111
115
|
documentIdSql: "d.document_id",
|
|
112
116
|
projectionAlias: "d",
|
|
113
117
|
})}`,
|
|
@@ -173,11 +177,11 @@ export function createContainerDocumentQueriesFromRuntime(runtime) {
|
|
|
173
177
|
loadDocumentSyncState(localId) {
|
|
174
178
|
return loadContainerContentsDocumentSyncState(execSql, localId);
|
|
175
179
|
},
|
|
176
|
-
loadDocumentSummary(localId) {
|
|
177
|
-
return loadContainerContentsDocumentSummary(execSql, localId);
|
|
180
|
+
loadDocumentSummary(localId, options) {
|
|
181
|
+
return loadContainerContentsDocumentSummary(execSql, localId, options?.requireHydrated ?? false);
|
|
178
182
|
},
|
|
179
|
-
loadOrphanedDocumentSummary({ currentOrganizationId, localId }) {
|
|
180
|
-
return loadContainerContentsOrphanedDocumentSummary(execSql, localId, currentOrganizationId);
|
|
183
|
+
loadOrphanedDocumentSummary({ currentOrganizationId, localId, requireHydrated = false, }) {
|
|
184
|
+
return loadContainerContentsOrphanedDocumentSummary(execSql, localId, currentOrganizationId, requireHydrated);
|
|
181
185
|
},
|
|
182
186
|
loadContainerDocumentWatermark(containerId) {
|
|
183
187
|
return sqlContainerSyncWatermarkPersistence.loadWatermark(execSql, containerContentsSyncLane(containerId));
|
|
@@ -185,6 +189,9 @@ export function createContainerDocumentQueriesFromRuntime(runtime) {
|
|
|
185
189
|
listLinkedContainerIdsByDocumentIds(documentIds) {
|
|
186
190
|
return listContainerContentsLinkedContainerIdsByDocumentIds(execSql, documentIds);
|
|
187
191
|
},
|
|
192
|
+
listPendingDownloads() {
|
|
193
|
+
return listPendingDownloads(execSql);
|
|
194
|
+
},
|
|
188
195
|
listPendingWrites() {
|
|
189
196
|
return listPendingWrites(execSql);
|
|
190
197
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"documentQueries.js","sourceRoot":"","sources":["documentQueries.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContainerSystemSlot } from \"@tearleads/validators/containerSystemSlot\";\nimport type { SyncWatermark } from \"@tearleads/validators/response\";\nimport type {\n DiscoveredDocumentInput,\n DocumentSummary,\n} from \"../../data/documents/documentSummary\";\nimport {\n hasRetainedContainerMetadata,\n listRecoveryFolderMoveIds,\n} from \"../../data/persistence/container-contents/containerRecoveryPersistence\";\nimport { ensureContainerTables } from \"../../data/persistence/containers/containerPersistence\";\nimport {\n containerContentsSyncLane,\n sqlContainerSyncWatermarkPersistence,\n} from \"../../data/persistence/containers/containerSyncWatermarkPersistence\";\nimport { sqlDocumentContainerProjectionPersistence } from \"../../data/persistence/containers/documentContainerProjectionPersistence\";\nimport {\n applyContainerDocumentTombstones as applyPersistedContainerDocumentTombstones,\n sqlDocumentsPersistence,\n upsertDiscoveredDocuments,\n} from \"../../data/persistence/documents/documentsPersistence\";\nimport { containerCreateIntentTables } from \"../../data/sqlite/schema\";\nimport { type ExecSql, ensureSqlTables } from \"../../data/sqlite/sqlSchema\";\nimport {\n mapContainerContentsDocumentSummaryRow,\n mapContainerContentsDocumentSyncStateRow,\n mapContainerDocumentSidebarRow,\n mapContainerItemRow,\n readContainerContentsContainerItemCount,\n} from \"./documentQueries/rows\";\nimport {\n clampContainerItemWindowValue,\n getContainerContentsContainerDocumentSidebarOrderBy,\n getContainerContentsContainerItemOrderBy,\n getContainerContentsContainerItemsBaseSql,\n getContainerContentsDocumentPendingStateCtes,\n getContainerContentsDocumentRowsBaseSql,\n getContainerDocumentSidebarWindowLimit,\n getContainerItemWindowLimit,\n getOrphanedDocumentExistsSql,\n getOrphanedDocumentItemsBaseSql,\n getOrphanedDocumentRowsBaseSql,\n listContainerContentsSqlIdBatches,\n} from \"./documentQueries/sql\";\nimport type {\n ContainerDocumentLinkInput,\n ContainerDocumentQueriesRuntime,\n ContainerDocumentSidebarWindow,\n ContainerDocumentTombstone,\n ContainerItemSort,\n ContainerItemWindow,\n} from \"./documentQueries/types\";\nimport {\n createFolderRecoveryQueries,\n type RecoveryFolder,\n} from \"./folderRecovery\";\nimport {\n getOrphanedDocumentQueryBind,\n getOrphanedDocumentWhereSql,\n} from \"./orphanedDocumentSql\";\nimport {\n listPendingWrites,\n type PendingWriteQueueItem,\n resetPendingWriteRetryState,\n} from \"./pendingWrites\";\nimport type { ContainerDocumentObjectSyncState } from \"./syncState\";\n\nexport type {\n ContainerDocumentLinkInput,\n ContainerDocumentSidebarRow,\n ContainerDocumentTombstone,\n ContainerItemRow,\n ContainerItemSort,\n ContainerItemSortDirection,\n ContainerItemSortKey,\n} from \"./documentQueries/types\";\n\ninterface ListContainerItemWindowInput {\n /** Null selects the virtual orphaned-documents recovery collection. */\n containerId: string | null;\n currentOrganizationId?: string | null | undefined;\n limit: number;\n offset: number;\n sort: ContainerItemSort;\n visibleForeignSystemContainerNames?: ReadonlyArray<string> | undefined;\n visibleSystemSlots?: ReadonlyArray<ContainerSystemSlot> | undefined;\n}\n\nexport interface ContainerDocumentQueries {\n listRecoveryFolderMoveIds(input: {\n currentOrganizationId: string | null;\n }): Promise<string[]>;\n listRecoveryFolders(input: {\n currentOrganizationId: string | null;\n }): Promise<RecoveryFolder[]>;\n discardRecoveryFolder(\n input: Pick<RecoveryFolder, \"containerId\" | \"organizationId\" | \"revision\">,\n ): Promise<boolean>;\n applyContainerDocumentTombstones(\n tombstones: ReadonlyArray<ContainerDocumentTombstone>,\n ): Promise<ReadonlyArray<DocumentSummary>>;\n hasOrphanedDocuments(input: {\n currentOrganizationId: string | null;\n }): Promise<boolean>;\n listContainerDocumentSidebarWindow(input: {\n /** Null selects the virtual orphaned-documents recovery collection. */\n containerId: string | null;\n currentOrganizationId?: string | null | undefined;\n limit: number;\n offset: number;\n }): Promise<ContainerDocumentSidebarWindow>;\n listContainerItemWindow(\n input: ListContainerItemWindowInput,\n ): Promise<ContainerItemWindow>;\n loadDocumentSyncState(\n localId: string,\n ): Promise<ContainerDocumentObjectSyncState | null>;\n loadDocumentSummary(localId: string): Promise<DocumentSummary | null>;\n loadOrphanedDocumentSummary(input: {\n currentOrganizationId: string | null;\n localId: string;\n }): Promise<DocumentSummary | null>;\n loadContainerDocumentWatermark(\n containerId: string,\n ): Promise<SyncWatermark | null>;\n listLinkedContainerIdsByDocumentIds(\n documentIds: ReadonlyArray<string>,\n ): Promise<ReadonlyMap<string, ReadonlyArray<string>>>;\n listPendingWrites(): Promise<ReadonlyArray<PendingWriteQueueItem>>;\n retryPendingWriteItem(input: {\n localId: string;\n namespace: string | null;\n objectKind: PendingWriteQueueItem[\"objectKind\"];\n }): Promise<void>;\n replaceDocumentLinksBatch(\n inputs: ReadonlyArray<ContainerDocumentLinkInput>,\n ): Promise<void>;\n saveContainerDocumentWatermark(\n containerId: string,\n watermark: SyncWatermark,\n ): Promise<void>;\n upsertDiscoveredDocuments(\n inputs: ReadonlyArray<DiscoveredDocumentInput>,\n ): Promise<ReadonlyArray<DocumentSummary>>;\n}\n\nasync function listContainerItemWindow(\n execSql: ExecSql,\n input: ListContainerItemWindowInput,\n): Promise<ContainerItemWindow> {\n await ensureContainerTables(execSql);\n await sqlDocumentsPersistence.ensureSchema(execSql);\n await ensureSqlTables(execSql, containerCreateIntentTables);\n\n const limit = getContainerItemWindowLimit(input.limit);\n const offset = clampContainerItemWindowValue(input.offset);\n const visibleSystemSlots = Array.from(\n new Set(input.visibleSystemSlots ?? []),\n );\n const currentOrganizationId = input.currentOrganizationId || null;\n const visibleForeignSystemContainerNames = currentOrganizationId\n ? Array.from(new Set(input.visibleForeignSystemContainerNames ?? []))\n : [];\n const orphaned = input.containerId === null;\n const bind = orphaned\n ? getOrphanedDocumentQueryBind(input.currentOrganizationId)\n : [\n input.containerId,\n ...visibleSystemSlots,\n ...(visibleForeignSystemContainerNames.length > 0\n ? [currentOrganizationId, ...visibleForeignSystemContainerNames]\n : []),\n input.containerId,\n input.containerId,\n ];\n const baseSql = orphaned\n ? getOrphanedDocumentItemsBaseSql()\n : getContainerContentsContainerItemsBaseSql(\n visibleSystemSlots.length,\n visibleForeignSystemContainerNames.length,\n );\n const countRows = await execSql(\n `SELECT COUNT(*) AS total_count FROM (${baseSql})`,\n bind,\n );\n const totalCount = readContainerContentsContainerItemCount(\n countRows[0] ?? {},\n );\n\n if (limit === 0 || offset >= totalCount) {\n return { rows: [], totalCount };\n }\n\n const rows = await execSql(\n `${baseSql} ORDER BY ${getContainerContentsContainerItemOrderBy(input.sort)} LIMIT ? OFFSET ?`,\n [...bind, limit, offset],\n );\n\n return {\n rows: rows.map((row) => mapContainerItemRow(input.containerId, row)),\n totalCount,\n };\n}\n\nasync function hasOrphanedDocuments(\n execSql: ExecSql,\n currentOrganizationId: string | null,\n): Promise<boolean> {\n await sqlDocumentsPersistence.ensureSchema(execSql);\n const rows = await execSql(\n getOrphanedDocumentExistsSql(),\n getOrphanedDocumentQueryBind(currentOrganizationId),\n );\n return (\n rows.length > 0 ||\n (await hasRetainedContainerMetadata(execSql, currentOrganizationId)) ||\n (await listRecoveryFolderMoveIds(execSql, currentOrganizationId)).length > 0\n );\n}\n\nasync function listContainerDocumentSidebarWindow(\n execSql: ExecSql,\n input: {\n containerId: string | null;\n currentOrganizationId?: string | null | undefined;\n limit: number;\n offset: number;\n },\n): Promise<ContainerDocumentSidebarWindow> {\n await sqlDocumentsPersistence.ensureSchema(execSql);\n\n const limit = getContainerDocumentSidebarWindowLimit(input.limit);\n const offset = clampContainerItemWindowValue(input.offset);\n const orphaned = input.containerId === null;\n const bind = orphaned\n ? getOrphanedDocumentQueryBind(input.currentOrganizationId)\n : [input.containerId, input.containerId];\n const baseSql = orphaned\n ? getOrphanedDocumentRowsBaseSql()\n : getContainerContentsDocumentRowsBaseSql();\n const countRows = await execSql(\n `SELECT COUNT(*) AS total_count FROM (${baseSql})`,\n bind,\n );\n const totalCount = readContainerContentsContainerItemCount(\n countRows[0] ?? {},\n );\n\n if (limit === 0 || offset >= totalCount) {\n return { rows: [], totalCount };\n }\n\n const rows = await execSql(\n `${baseSql} ORDER BY ${getContainerContentsContainerDocumentSidebarOrderBy()} LIMIT ? OFFSET ?`,\n [...bind, limit, offset],\n );\n\n return {\n rows: rows.map(mapContainerDocumentSidebarRow),\n totalCount,\n };\n}\n\nasync function queryContainerContentsDocumentSummary(\n execSql: ExecSql,\n localId: string,\n scope: { bind: ReadonlyArray<string | null>; whereSql: string },\n): Promise<DocumentSummary | null> {\n await sqlDocumentsPersistence.ensureSchema(execSql);\n\n const rows = await execSql(\n `\n SELECT\n d.local_id AS local_id,\n d.document_id AS document_id,\n d.container_id AS container_id,\n d.document_kind AS document_kind,\n d.title AS title,\n d.updated_at AS updated_at,\n stored.access_state_hash AS access_state_hash,\n stored.effective_access_level AS effective_access_level\n FROM document_projection d\n LEFT JOIN documents stored\n ON stored.app_kind = 'documents'\n AND stored.local_id = d.local_id\n WHERE d.local_id = ?\n ${scope.whereSql}\n LIMIT 1\n `,\n [localId, ...scope.bind],\n );\n\n return mapContainerContentsDocumentSummaryRow(rows[0] ?? {});\n}\n\nfunction loadContainerContentsDocumentSummary(\n execSql: ExecSql,\n localId: string,\n): Promise<DocumentSummary | null> {\n return queryContainerContentsDocumentSummary(execSql, localId, {\n bind: [],\n whereSql: \"\",\n });\n}\n\nfunction loadContainerContentsOrphanedDocumentSummary(\n execSql: ExecSql,\n localId: string,\n currentOrganizationId: string | null,\n): Promise<DocumentSummary | null> {\n return queryContainerContentsDocumentSummary(execSql, localId, {\n bind: getOrphanedDocumentQueryBind(currentOrganizationId),\n whereSql: `AND ${getOrphanedDocumentWhereSql({\n documentIdSql: \"d.document_id\",\n projectionAlias: \"d\",\n })}`,\n });\n}\n\nasync function loadContainerContentsDocumentSyncState(\n execSql: ExecSql,\n localId: string,\n): Promise<ContainerDocumentObjectSyncState | null> {\n await sqlDocumentsPersistence.ensureSchema(execSql);\n\n const rows = await execSql(\n `\n WITH ${getContainerContentsDocumentPendingStateCtes()}\n SELECT\n d.document_id AS document_id,\n COALESCE(document_updates.pending_update_count, 0) AS pending_update_count,\n COALESCE(document_attachments.pending_attachment_count, 0) AS pending_attachment_count,\n COALESCE(document_attachments.pending_attachment_bytes, 0) AS pending_attachment_bytes,\n NULL AS sync_last_error\n FROM document_projection d\n LEFT JOIN document_pending_update_counts document_updates\n ON document_updates.local_id = d.local_id\n LEFT JOIN document_pending_attachment_counts document_attachments\n ON document_attachments.local_id = d.local_id\n WHERE d.local_id = ?\n LIMIT 1\n `,\n [localId],\n );\n const [row] = rows;\n if (!row) {\n return null;\n }\n\n return mapContainerContentsDocumentSyncStateRow(row);\n}\n\nasync function listContainerContentsLinkedContainerIdsByDocumentIds(\n execSql: ExecSql,\n documentIds: ReadonlyArray<string>,\n): Promise<ReadonlyMap<string, ReadonlyArray<string>>> {\n const uniqueDocumentIds = Array.from(new Set(documentIds));\n if (uniqueDocumentIds.length === 0) {\n return new Map();\n }\n\n const linkedContainerIdsByDocumentId = new Map<string, string[]>();\n for (const documentId of uniqueDocumentIds) {\n linkedContainerIdsByDocumentId.set(documentId, []);\n }\n\n for (const documentIdBatch of listContainerContentsSqlIdBatches(\n uniqueDocumentIds,\n )) {\n const batchLinkedContainerIdsByDocumentId =\n await sqlDocumentContainerProjectionPersistence.listLinkedContainerIdsByDocumentIds(\n execSql,\n documentIdBatch,\n );\n for (const [\n documentId,\n linkedContainerIds,\n ] of batchLinkedContainerIdsByDocumentId.entries()) {\n linkedContainerIdsByDocumentId.set(\n documentId,\n Array.from(linkedContainerIds),\n );\n }\n }\n\n return linkedContainerIdsByDocumentId;\n}\n\nexport function createContainerDocumentQueriesFromRuntime(\n runtime: ContainerDocumentQueriesRuntime,\n): ContainerDocumentQueries {\n const execSql = runtime.infra.execSql;\n return {\n ...createFolderRecoveryQueries(execSql),\n applyContainerDocumentTombstones(tombstones) {\n return applyPersistedContainerDocumentTombstones(execSql, tombstones);\n },\n hasOrphanedDocuments({ currentOrganizationId }) {\n return hasOrphanedDocuments(execSql, currentOrganizationId);\n },\n listContainerDocumentSidebarWindow(input) {\n return listContainerDocumentSidebarWindow(execSql, input);\n },\n listContainerItemWindow(input) {\n return listContainerItemWindow(execSql, input);\n },\n loadDocumentSyncState(localId) {\n return loadContainerContentsDocumentSyncState(execSql, localId);\n },\n loadDocumentSummary(localId) {\n return loadContainerContentsDocumentSummary(execSql, localId);\n },\n loadOrphanedDocumentSummary({ currentOrganizationId, localId }) {\n return loadContainerContentsOrphanedDocumentSummary(\n execSql,\n localId,\n currentOrganizationId,\n );\n },\n loadContainerDocumentWatermark(containerId) {\n return sqlContainerSyncWatermarkPersistence.loadWatermark(\n execSql,\n containerContentsSyncLane(containerId),\n );\n },\n listLinkedContainerIdsByDocumentIds(documentIds) {\n return listContainerContentsLinkedContainerIdsByDocumentIds(\n execSql,\n documentIds,\n );\n },\n listPendingWrites() {\n return listPendingWrites(execSql);\n },\n retryPendingWriteItem(input) {\n return resetPendingWriteRetryState(execSql, input);\n },\n replaceDocumentLinksBatch(inputs) {\n return sqlDocumentContainerProjectionPersistence.replaceDocumentLinksBatch(\n execSql,\n inputs,\n );\n },\n async saveContainerDocumentWatermark(containerId, watermark) {\n await sqlContainerSyncWatermarkPersistence.saveWatermark(\n execSql,\n containerContentsSyncLane(containerId),\n watermark,\n );\n },\n upsertDiscoveredDocuments(inputs) {\n return upsertDiscoveredDocuments(execSql, inputs);\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"documentQueries.js","sourceRoot":"","sources":["documentQueries.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContainerSystemSlot } from \"@tearleads/validators/containerSystemSlot\";\nimport type { SyncWatermark } from \"@tearleads/validators/response\";\nimport type {\n DiscoveredDocumentInput,\n DocumentSummary,\n} from \"../../data/documents/documentSummary\";\nimport {\n hasRetainedContainerMetadata,\n listRecoveryFolderMoveIds,\n} from \"../../data/persistence/container-contents/containerRecoveryPersistence\";\nimport { ensureContainerTables } from \"../../data/persistence/containers/containerPersistence\";\nimport {\n containerContentsSyncLane,\n sqlContainerSyncWatermarkPersistence,\n} from \"../../data/persistence/containers/containerSyncWatermarkPersistence\";\nimport { sqlDocumentContainerProjectionPersistence } from \"../../data/persistence/containers/documentContainerProjectionPersistence\";\nimport {\n applyContainerDocumentTombstones as applyPersistedContainerDocumentTombstones,\n sqlDocumentsPersistence,\n upsertDiscoveredDocuments,\n} from \"../../data/persistence/documents/documentsPersistence\";\nimport { containerCreateIntentTables } from \"../../data/sqlite/schema\";\nimport { type ExecSql, ensureSqlTables } from \"../../data/sqlite/sqlSchema\";\nimport { hydratedProjectionSql } from \"./documentQueries/hydrationSql\";\nimport {\n mapContainerContentsDocumentSummaryRow,\n mapContainerContentsDocumentSyncStateRow,\n mapContainerDocumentSidebarRow,\n mapContainerItemRow,\n readContainerContentsContainerItemCount,\n} from \"./documentQueries/rows\";\nimport {\n clampContainerItemWindowValue,\n getContainerContentsContainerDocumentSidebarOrderBy,\n getContainerContentsContainerItemOrderBy,\n getContainerContentsContainerItemsBaseSql,\n getContainerContentsDocumentPendingStateCtes,\n getContainerContentsDocumentRowsBaseSql,\n getContainerDocumentSidebarWindowLimit,\n getContainerItemWindowLimit,\n getOrphanedDocumentExistsSql,\n getOrphanedDocumentItemsBaseSql,\n getOrphanedDocumentRowsBaseSql,\n listContainerContentsSqlIdBatches,\n} from \"./documentQueries/sql\";\nimport type {\n ContainerDocumentLinkInput,\n ContainerDocumentQueriesRuntime,\n ContainerDocumentSidebarWindow,\n ContainerDocumentTombstone,\n ContainerItemSort,\n ContainerItemWindow,\n} from \"./documentQueries/types\";\nimport {\n createFolderRecoveryQueries,\n type RecoveryFolder,\n} from \"./folderRecovery\";\nimport {\n getOrphanedDocumentQueryBind,\n getOrphanedDocumentWhereSql,\n} from \"./orphanedDocumentSql\";\nimport {\n listPendingDownloads,\n type PendingDownloadQueueItem,\n} from \"./pendingDownloads\";\nimport {\n listPendingWrites,\n type PendingWriteQueueItem,\n resetPendingWriteRetryState,\n} from \"./pendingWrites\";\nimport type { ContainerDocumentObjectSyncState } from \"./syncState\";\n\nexport type {\n ContainerDocumentLinkInput,\n ContainerDocumentSidebarRow,\n ContainerDocumentTombstone,\n ContainerItemRow,\n ContainerItemSort,\n ContainerItemSortDirection,\n ContainerItemSortKey,\n} from \"./documentQueries/types\";\n\ninterface ListContainerItemWindowInput {\n /** Null selects the virtual orphaned-documents recovery collection. */\n containerId: string | null;\n currentOrganizationId?: string | null | undefined;\n limit: number;\n offset: number;\n sort: ContainerItemSort;\n visibleForeignSystemContainerNames?: ReadonlyArray<string> | undefined;\n visibleSystemSlots?: ReadonlyArray<ContainerSystemSlot> | undefined;\n}\n\nexport interface ContainerDocumentQueries {\n listRecoveryFolderMoveIds(input: {\n currentOrganizationId: string | null;\n }): Promise<string[]>;\n listRecoveryFolders(input: {\n currentOrganizationId: string | null;\n }): Promise<RecoveryFolder[]>;\n discardRecoveryFolder(\n input: Pick<RecoveryFolder, \"containerId\" | \"organizationId\" | \"revision\">,\n ): Promise<boolean>;\n applyContainerDocumentTombstones(\n tombstones: ReadonlyArray<ContainerDocumentTombstone>,\n ): Promise<ReadonlyArray<DocumentSummary>>;\n hasOrphanedDocuments(input: {\n currentOrganizationId: string | null;\n }): Promise<boolean>;\n listContainerDocumentSidebarWindow(input: {\n /** Null selects the virtual orphaned-documents recovery collection. */\n containerId: string | null;\n currentOrganizationId?: string | null | undefined;\n limit: number;\n offset: number;\n }): Promise<ContainerDocumentSidebarWindow>;\n listContainerItemWindow(\n input: ListContainerItemWindowInput,\n ): Promise<ContainerItemWindow>;\n loadDocumentSyncState(\n localId: string,\n ): Promise<ContainerDocumentObjectSyncState | null>;\n loadDocumentSummary(\n localId: string,\n options?: { requireHydrated?: boolean },\n ): Promise<DocumentSummary | null>;\n loadOrphanedDocumentSummary(input: {\n requireHydrated?: boolean;\n currentOrganizationId: string | null;\n localId: string;\n }): Promise<DocumentSummary | null>;\n loadContainerDocumentWatermark(\n containerId: string,\n ): Promise<SyncWatermark | null>;\n listLinkedContainerIdsByDocumentIds(\n documentIds: ReadonlyArray<string>,\n ): Promise<ReadonlyMap<string, ReadonlyArray<string>>>;\n listPendingDownloads(): Promise<ReadonlyArray<PendingDownloadQueueItem>>;\n listPendingWrites(): Promise<ReadonlyArray<PendingWriteQueueItem>>;\n retryPendingWriteItem(input: {\n localId: string;\n namespace: string | null;\n objectKind: PendingWriteQueueItem[\"objectKind\"];\n }): Promise<void>;\n replaceDocumentLinksBatch(\n inputs: ReadonlyArray<ContainerDocumentLinkInput>,\n ): Promise<void>;\n saveContainerDocumentWatermark(\n containerId: string,\n watermark: SyncWatermark,\n ): Promise<void>;\n upsertDiscoveredDocuments(\n inputs: ReadonlyArray<DiscoveredDocumentInput>,\n ): Promise<ReadonlyArray<DocumentSummary>>;\n}\n\nasync function listContainerItemWindow(\n execSql: ExecSql,\n input: ListContainerItemWindowInput,\n): Promise<ContainerItemWindow> {\n await ensureContainerTables(execSql);\n await sqlDocumentsPersistence.ensureSchema(execSql);\n await ensureSqlTables(execSql, containerCreateIntentTables);\n\n const limit = getContainerItemWindowLimit(input.limit);\n const offset = clampContainerItemWindowValue(input.offset);\n const visibleSystemSlots = Array.from(\n new Set(input.visibleSystemSlots ?? []),\n );\n const currentOrganizationId = input.currentOrganizationId || null;\n const visibleForeignSystemContainerNames = currentOrganizationId\n ? Array.from(new Set(input.visibleForeignSystemContainerNames ?? []))\n : [];\n const orphaned = input.containerId === null;\n const bind = orphaned\n ? getOrphanedDocumentQueryBind(input.currentOrganizationId)\n : [\n input.containerId,\n ...visibleSystemSlots,\n ...(visibleForeignSystemContainerNames.length > 0\n ? [currentOrganizationId, ...visibleForeignSystemContainerNames]\n : []),\n input.containerId,\n input.containerId,\n ];\n const baseSql = orphaned\n ? getOrphanedDocumentItemsBaseSql()\n : getContainerContentsContainerItemsBaseSql(\n visibleSystemSlots.length,\n visibleForeignSystemContainerNames.length,\n );\n const countRows = await execSql(\n `SELECT COUNT(*) AS total_count FROM (${baseSql})`,\n bind,\n );\n const totalCount = readContainerContentsContainerItemCount(\n countRows[0] ?? {},\n );\n\n if (limit === 0 || offset >= totalCount) {\n return { rows: [], totalCount };\n }\n\n const rows = await execSql(\n `${baseSql} ORDER BY ${getContainerContentsContainerItemOrderBy(input.sort)} LIMIT ? OFFSET ?`,\n [...bind, limit, offset],\n );\n\n return {\n rows: rows.map((row) => mapContainerItemRow(input.containerId, row)),\n totalCount,\n };\n}\n\nasync function hasOrphanedDocuments(\n execSql: ExecSql,\n currentOrganizationId: string | null,\n): Promise<boolean> {\n await sqlDocumentsPersistence.ensureSchema(execSql);\n const rows = await execSql(\n getOrphanedDocumentExistsSql(),\n getOrphanedDocumentQueryBind(currentOrganizationId),\n );\n return (\n rows.length > 0 ||\n (await hasRetainedContainerMetadata(execSql, currentOrganizationId)) ||\n (await listRecoveryFolderMoveIds(execSql, currentOrganizationId)).length > 0\n );\n}\n\nasync function listContainerDocumentSidebarWindow(\n execSql: ExecSql,\n input: {\n containerId: string | null;\n currentOrganizationId?: string | null | undefined;\n limit: number;\n offset: number;\n },\n): Promise<ContainerDocumentSidebarWindow> {\n await sqlDocumentsPersistence.ensureSchema(execSql);\n\n const limit = getContainerDocumentSidebarWindowLimit(input.limit);\n const offset = clampContainerItemWindowValue(input.offset);\n const orphaned = input.containerId === null;\n const bind = orphaned\n ? getOrphanedDocumentQueryBind(input.currentOrganizationId)\n : [input.containerId, input.containerId];\n const baseSql = orphaned\n ? getOrphanedDocumentRowsBaseSql()\n : getContainerContentsDocumentRowsBaseSql();\n const countRows = await execSql(\n `SELECT COUNT(*) AS total_count FROM (${baseSql})`,\n bind,\n );\n const totalCount = readContainerContentsContainerItemCount(\n countRows[0] ?? {},\n );\n\n if (limit === 0 || offset >= totalCount) {\n return { rows: [], totalCount };\n }\n\n const rows = await execSql(\n `${baseSql} ORDER BY ${getContainerContentsContainerDocumentSidebarOrderBy()} LIMIT ? OFFSET ?`,\n [...bind, limit, offset],\n );\n\n return {\n rows: rows.map(mapContainerDocumentSidebarRow),\n totalCount,\n };\n}\n\nasync function queryContainerContentsDocumentSummary(\n execSql: ExecSql,\n localId: string,\n scope: { bind: ReadonlyArray<string | null>; whereSql: string },\n): Promise<DocumentSummary | null> {\n await sqlDocumentsPersistence.ensureSchema(execSql);\n\n const rows = await execSql(\n `\n SELECT\n d.local_id AS local_id,\n d.document_id AS document_id,\n d.container_id AS container_id,\n d.document_kind AS document_kind,\n d.title AS title,\n d.updated_at AS updated_at,\n stored.access_state_hash AS access_state_hash,\n stored.effective_access_level AS effective_access_level\n FROM document_projection d\n LEFT JOIN documents stored\n ON stored.app_kind = 'documents'\n AND stored.local_id = d.local_id\n WHERE d.local_id = ?\n ${scope.whereSql}\n LIMIT 1\n `,\n [localId, ...scope.bind],\n );\n\n return mapContainerContentsDocumentSummaryRow(rows[0] ?? {});\n}\n\nfunction loadContainerContentsDocumentSummary(\n execSql: ExecSql,\n localId: string,\n requireHydrated: boolean,\n): Promise<DocumentSummary | null> {\n return queryContainerContentsDocumentSummary(execSql, localId, {\n bind: [],\n whereSql: requireHydrated\n ? `AND ${hydratedProjectionSql(\"d.local_id\", \"documents\")}`\n : \"\",\n });\n}\n\nfunction loadContainerContentsOrphanedDocumentSummary(\n execSql: ExecSql,\n localId: string,\n currentOrganizationId: string | null,\n requireHydrated: boolean,\n): Promise<DocumentSummary | null> {\n return queryContainerContentsDocumentSummary(execSql, localId, {\n bind: getOrphanedDocumentQueryBind(currentOrganizationId),\n whereSql: `${requireHydrated ? `AND ${hydratedProjectionSql(\"d.local_id\", \"documents\")}` : \"\"} AND ${getOrphanedDocumentWhereSql(\n {\n documentIdSql: \"d.document_id\",\n projectionAlias: \"d\",\n },\n )}`,\n });\n}\n\nasync function loadContainerContentsDocumentSyncState(\n execSql: ExecSql,\n localId: string,\n): Promise<ContainerDocumentObjectSyncState | null> {\n await sqlDocumentsPersistence.ensureSchema(execSql);\n\n const rows = await execSql(\n `\n WITH ${getContainerContentsDocumentPendingStateCtes()}\n SELECT\n d.document_id AS document_id,\n COALESCE(document_updates.pending_update_count, 0) AS pending_update_count,\n COALESCE(document_attachments.pending_attachment_count, 0) AS pending_attachment_count,\n COALESCE(document_attachments.pending_attachment_bytes, 0) AS pending_attachment_bytes,\n NULL AS sync_last_error\n FROM document_projection d\n LEFT JOIN document_pending_update_counts document_updates\n ON document_updates.local_id = d.local_id\n LEFT JOIN document_pending_attachment_counts document_attachments\n ON document_attachments.local_id = d.local_id\n WHERE d.local_id = ?\n LIMIT 1\n `,\n [localId],\n );\n const [row] = rows;\n if (!row) {\n return null;\n }\n\n return mapContainerContentsDocumentSyncStateRow(row);\n}\n\nasync function listContainerContentsLinkedContainerIdsByDocumentIds(\n execSql: ExecSql,\n documentIds: ReadonlyArray<string>,\n): Promise<ReadonlyMap<string, ReadonlyArray<string>>> {\n const uniqueDocumentIds = Array.from(new Set(documentIds));\n if (uniqueDocumentIds.length === 0) {\n return new Map();\n }\n\n const linkedContainerIdsByDocumentId = new Map<string, string[]>();\n for (const documentId of uniqueDocumentIds) {\n linkedContainerIdsByDocumentId.set(documentId, []);\n }\n\n for (const documentIdBatch of listContainerContentsSqlIdBatches(\n uniqueDocumentIds,\n )) {\n const batchLinkedContainerIdsByDocumentId =\n await sqlDocumentContainerProjectionPersistence.listLinkedContainerIdsByDocumentIds(\n execSql,\n documentIdBatch,\n );\n for (const [\n documentId,\n linkedContainerIds,\n ] of batchLinkedContainerIdsByDocumentId.entries()) {\n linkedContainerIdsByDocumentId.set(\n documentId,\n Array.from(linkedContainerIds),\n );\n }\n }\n\n return linkedContainerIdsByDocumentId;\n}\n\nexport function createContainerDocumentQueriesFromRuntime(\n runtime: ContainerDocumentQueriesRuntime,\n): ContainerDocumentQueries {\n const execSql = runtime.infra.execSql;\n return {\n ...createFolderRecoveryQueries(execSql),\n applyContainerDocumentTombstones(tombstones) {\n return applyPersistedContainerDocumentTombstones(execSql, tombstones);\n },\n hasOrphanedDocuments({ currentOrganizationId }) {\n return hasOrphanedDocuments(execSql, currentOrganizationId);\n },\n listContainerDocumentSidebarWindow(input) {\n return listContainerDocumentSidebarWindow(execSql, input);\n },\n listContainerItemWindow(input) {\n return listContainerItemWindow(execSql, input);\n },\n loadDocumentSyncState(localId) {\n return loadContainerContentsDocumentSyncState(execSql, localId);\n },\n loadDocumentSummary(localId, options) {\n return loadContainerContentsDocumentSummary(\n execSql,\n localId,\n options?.requireHydrated ?? false,\n );\n },\n loadOrphanedDocumentSummary({\n currentOrganizationId,\n localId,\n requireHydrated = false,\n }) {\n return loadContainerContentsOrphanedDocumentSummary(\n execSql,\n localId,\n currentOrganizationId,\n requireHydrated,\n );\n },\n loadContainerDocumentWatermark(containerId) {\n return sqlContainerSyncWatermarkPersistence.loadWatermark(\n execSql,\n containerContentsSyncLane(containerId),\n );\n },\n listLinkedContainerIdsByDocumentIds(documentIds) {\n return listContainerContentsLinkedContainerIdsByDocumentIds(\n execSql,\n documentIds,\n );\n },\n listPendingDownloads() {\n return listPendingDownloads(execSql);\n },\n listPendingWrites() {\n return listPendingWrites(execSql);\n },\n retryPendingWriteItem(input) {\n return resetPendingWriteRetryState(execSql, input);\n },\n replaceDocumentLinksBatch(inputs) {\n return sqlDocumentContainerProjectionPersistence.replaceDocumentLinksBatch(\n execSql,\n inputs,\n );\n },\n async saveContainerDocumentWatermark(containerId, watermark) {\n await sqlContainerSyncWatermarkPersistence.saveWatermark(\n execSql,\n containerContentsSyncLane(containerId),\n watermark,\n );\n },\n upsertDiscoveredDocuments(inputs) {\n return upsertDiscoveredDocuments(execSql, inputs);\n },\n };\n}\n"]}
|
|
@@ -12,6 +12,7 @@ export { type ContainerDocumentLinkInput, type ContainerDocumentQueries, type Co
|
|
|
12
12
|
export { activateDocumentLink, addDocumentLink, canMutateDocumentLink, canMutateLocalDocumentLink, type DocumentStructuralMutationHost, type MergeDocumentSummary, moveDocumentLink, moveLocalDocumentLink, removeDocumentLink, type SetLinkedContainerIdsForDocument, } from "./documentStructure.js";
|
|
13
13
|
export type { RecoveryFolder } from "./folderRecovery.js";
|
|
14
14
|
export { type ContainerMetadataPatch, hasContainerMetadataDocumentUpdateEvent, persistContainerMetadataStateFromRuntime, renameContainerMetadataStateFromRuntime, syncContainerMetadataState, } from "./metadata.js";
|
|
15
|
+
export type { PendingDownloadQueueItem } from "./pendingDownloads.js";
|
|
15
16
|
export { listPendingWrites, type PendingWriteQueueItem, type PendingWriteQueueItemStatus, type PendingWriteQueueObjectKind, type PendingWriteQueueOperation, type PendingWriteQueueOperationKind, type PendingWriteQueueOperationStatus, } from "./pendingWrites.js";
|
|
16
17
|
export { type ContainerContentsProjectionUserKeyResolver, createContainerContentsDocumentProjectionUserKeyResolver, createContainerContentsProjectionUserKeyResolver, didContainerContentsProjectionKeyRuntimeChange, } from "./projectionKeys.js";
|
|
17
18
|
export { type ContainerContentsRootAdopter, type ContainerContentsRootAdoptionInput, type ContainerContentsStoreWorkflowRuntime, type ContainerContentsWorkflowRuntime, type ContainerContentsWorkflowRuntimeAuth, type ContainerContentsWorkflowRuntimeCrypto, type ContainerContentsWorkflowRuntimeGroups, type ContainerContentsWorkflowRuntimeInfra, type ContainerContentsWorkflowRuntimeInput, type ContainerContentsWorkflowRuntimeInputGroups, type ContainerContentsWorkflowRuntimeState, type ContainerContentsWorkflowRuntimeUtil, createContainerContentsDocumentsRuntime, createContainerContentsStoreWorkflowRuntime, createContainerContentsWorkflowRuntime, } from "./runtime.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,0CAA0C,EAC1C,uBAAuB,EACvB,0BAA0B,EAC1B,2BAA2B,GAC5B,MAAM,iDAAiD,CAAC;AACzD,OAAO,EACL,0BAA0B,EAC1B,0BAA0B,GAC3B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EASL,YAAY,GACb,MAAM,YAAY,CAAC;AACpB,OAAO,EAQL,iBAAiB,GAClB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAEL,+BAA+B,EAC/B,6BAA6B,EAC7B,mCAAmC,EACnC,0BAA0B,EAC1B,0BAA0B,GAC3B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAGL,6BAA6B,GAC9B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,iCAAiC,EACjC,kCAAkC,EAElC,mCAAmC,GACpC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAQL,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,6BAA6B,EAC7B,8BAA8B,EAC9B,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,2BAA2B,EAC3B,4BAA4B,GAC7B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EASL,yCAAyC,GAC1C,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,oBAAoB,EACpB,eAAe,EACf,qBAAqB,EACrB,0BAA0B,EAG1B,gBAAgB,EAChB,qBAAqB,EACrB,kBAAkB,GAEnB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAEL,uCAAuC,EACvC,wCAAwC,EACxC,uCAAuC,EACvC,0BAA0B,GAC3B,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,0CAA0C,EAC1C,uBAAuB,EACvB,0BAA0B,EAC1B,2BAA2B,GAC5B,MAAM,iDAAiD,CAAC;AACzD,OAAO,EACL,0BAA0B,EAC1B,0BAA0B,GAC3B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EASL,YAAY,GACb,MAAM,YAAY,CAAC;AACpB,OAAO,EAQL,iBAAiB,GAClB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAEL,+BAA+B,EAC/B,6BAA6B,EAC7B,mCAAmC,EACnC,0BAA0B,EAC1B,0BAA0B,GAC3B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAGL,6BAA6B,GAC9B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,iCAAiC,EACjC,kCAAkC,EAElC,mCAAmC,GACpC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAQL,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,6BAA6B,EAC7B,8BAA8B,EAC9B,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,2BAA2B,EAC3B,4BAA4B,GAC7B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EASL,yCAAyC,GAC1C,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,oBAAoB,EACpB,eAAe,EACf,qBAAqB,EACrB,0BAA0B,EAG1B,gBAAgB,EAChB,qBAAqB,EACrB,kBAAkB,GAEnB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAEL,uCAAuC,EACvC,wCAAwC,EACxC,uCAAuC,EACvC,0BAA0B,GAC3B,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,iBAAiB,GAOlB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAEL,wDAAwD,EACxD,gDAAgD,EAChD,8CAA8C,GAC/C,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAaL,uCAAuC,EACvC,2CAA2C,EAC3C,sCAAsC,GACvC,MAAM,WAAW,CAAC;AAKnB,OAAO,EACL,sCAAsC,EACtC,sCAAsC,GACvC,MAAM,aAAa,CAAC;AACrB,OAAO,EAEL,yBAAyB,GAC1B,MAAM,cAAc,CAAC","sourcesContent":["export {\n type ContainerMetadataDocument,\n createInitializedContainerMetadataDocument,\n getDefaultContainerName,\n readContainerMetadataValue,\n writeContainerMetadataValue,\n} from \"../../data/containers/containerMetadataDocument\";\nexport {\n didRegainSyncPrerequisites,\n isDatabaseUnavailableError,\n} from \"../../data/sync/syncCoordinator\";\nexport {\n type BlobInfo,\n type BlobInfoAttachmentKind,\n type BlobInfoDocumentReference,\n type BlobInfoInput,\n type BlobInfoList,\n type BlobInfoSort,\n type BlobInfoSortDirection,\n type BlobInfoSortKey,\n listBlobInfo,\n} from \"./blobInfo\";\nexport {\n type ContainerInfo,\n type ContainerInfoGrant,\n type ContainerInfoGrantRow,\n type ContainerInfoPathEntry,\n type ContainerInfoRemoteMode,\n type ContainerInfoSecurityDetails,\n type ContainerShareAccessLevel,\n loadContainerInfo,\n} from \"./containerInfo\";\nexport {\n type ContainerSyncWatermarkLane,\n createContainerContentsSyncLane,\n createContainerParentSyncLane,\n defaultContainerContentsPersistence,\n loadContainerSyncWatermark,\n saveContainerSyncWatermark,\n} from \"./containerPersistence\";\nexport {\n type DocumentAttributionRangesInput,\n type DocumentAttributionRangesPage,\n loadDocumentAttributionRanges,\n} from \"./documentAttributionRanges\";\nexport {\n discoverContainerDocumentsFromApi,\n hasUndiscoveredDocumentUpdateEvent,\n type RefreshAllContainerDocumentsFromApiOptions,\n refreshAllContainerDocumentsFromApi,\n} from \"./documentDiscovery\";\nexport {\n type DocumentInfo,\n type DocumentInfoAttachment,\n type DocumentInfoAuthorizingContainerPath,\n type DocumentInfoLocalDetails,\n type DocumentInfoRemoteAttachmentBinding,\n type DocumentInfoRemoteDetails,\n type DocumentInfoRemoteMode,\n loadDocumentInfo,\n} from \"./documentInfo\";\nexport {\n initializeDocumentLinksSchema,\n listDocumentLinkedContainerIds,\n replaceDocumentLinks,\n} from \"./documentLinks\";\nexport {\n purgeLocalContainerDocument,\n purgeRemoteContainerDocument,\n} from \"./documentPurge\";\nexport {\n type ContainerDocumentLinkInput,\n type ContainerDocumentQueries,\n type ContainerDocumentSidebarRow,\n type ContainerDocumentTombstone,\n type ContainerItemRow,\n type ContainerItemSort,\n type ContainerItemSortDirection,\n type ContainerItemSortKey,\n createContainerDocumentQueriesFromRuntime,\n} from \"./documentQueries\";\nexport {\n activateDocumentLink,\n addDocumentLink,\n canMutateDocumentLink,\n canMutateLocalDocumentLink,\n type DocumentStructuralMutationHost,\n type MergeDocumentSummary,\n moveDocumentLink,\n moveLocalDocumentLink,\n removeDocumentLink,\n type SetLinkedContainerIdsForDocument,\n} from \"./documentStructure\";\nexport type { RecoveryFolder } from \"./folderRecovery\";\nexport {\n type ContainerMetadataPatch,\n hasContainerMetadataDocumentUpdateEvent,\n persistContainerMetadataStateFromRuntime,\n renameContainerMetadataStateFromRuntime,\n syncContainerMetadataState,\n} from \"./metadata\";\nexport type { PendingDownloadQueueItem } from \"./pendingDownloads\";\nexport {\n listPendingWrites,\n type PendingWriteQueueItem,\n type PendingWriteQueueItemStatus,\n type PendingWriteQueueObjectKind,\n type PendingWriteQueueOperation,\n type PendingWriteQueueOperationKind,\n type PendingWriteQueueOperationStatus,\n} from \"./pendingWrites\";\nexport {\n type ContainerContentsProjectionUserKeyResolver,\n createContainerContentsDocumentProjectionUserKeyResolver,\n createContainerContentsProjectionUserKeyResolver,\n didContainerContentsProjectionKeyRuntimeChange,\n} from \"./projectionKeys\";\nexport {\n type ContainerContentsRootAdopter,\n type ContainerContentsRootAdoptionInput,\n type ContainerContentsStoreWorkflowRuntime,\n type ContainerContentsWorkflowRuntime,\n type ContainerContentsWorkflowRuntimeAuth,\n type ContainerContentsWorkflowRuntimeCrypto,\n type ContainerContentsWorkflowRuntimeGroups,\n type ContainerContentsWorkflowRuntimeInfra,\n type ContainerContentsWorkflowRuntimeInput,\n type ContainerContentsWorkflowRuntimeInputGroups,\n type ContainerContentsWorkflowRuntimeState,\n type ContainerContentsWorkflowRuntimeUtil,\n createContainerContentsDocumentsRuntime,\n createContainerContentsStoreWorkflowRuntime,\n createContainerContentsWorkflowRuntime,\n} from \"./runtime\";\nexport type {\n ContainerDocumentObjectSyncState,\n ContainerDocumentObjectSyncStatus,\n} from \"./syncState\";\nexport {\n createContainerDocumentObjectSyncState,\n syncedContainerDocumentObjectSyncState,\n} from \"./syncState\";\nexport {\n type ContainerSystemSlotDefinition,\n deriveContainerSystemSlot,\n} from \"./systemSlot\";\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ExecSql } from "../../data/sqlite/sqlSchema.js";
|
|
2
|
+
export interface PendingDownloadQueueItem {
|
|
3
|
+
localId: string;
|
|
4
|
+
documentId: string;
|
|
5
|
+
objectKind: "document" | "container";
|
|
6
|
+
/** Null until content supplies a reliable title and type. */
|
|
7
|
+
title: string | null;
|
|
8
|
+
reason: "initial" | "continuation";
|
|
9
|
+
lastError: string | null;
|
|
10
|
+
}
|
|
11
|
+
/** Durable, already-discovered content pulls, including folder metadata. */
|
|
12
|
+
export declare function listPendingDownloads(execSql: ExecSql): Promise<ReadonlyArray<PendingDownloadQueueItem>>;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { ensureContainerTables } from "../../data/persistence/containers/containerPersistence.js";
|
|
2
|
+
import { sqlDocumentsPersistence } from "../../data/persistence/documents/documentsPersistence.js";
|
|
3
|
+
import { emptyContentFrontierSql } from "./documentQueries/hydrationSql.js";
|
|
4
|
+
/** Durable, already-discovered content pulls, including folder metadata. */
|
|
5
|
+
export async function listPendingDownloads(execSql) {
|
|
6
|
+
await ensureContainerTables(execSql);
|
|
7
|
+
await sqlDocumentsPersistence.ensureSchema(execSql);
|
|
8
|
+
const rows = await execSql(`
|
|
9
|
+
SELECT stored.local_id, stored.document_id, stored.app_kind,
|
|
10
|
+
CASE WHEN ${emptyContentFrontierSql("stored")} THEN NULL
|
|
11
|
+
WHEN stored.app_kind = 'documents' THEN d.title
|
|
12
|
+
ELSE c.display_name END AS title,
|
|
13
|
+
CASE WHEN ${emptyContentFrontierSql("stored")} THEN 'initial'
|
|
14
|
+
ELSE 'continuation' END AS reason,
|
|
15
|
+
failure.message AS last_error
|
|
16
|
+
FROM documents stored
|
|
17
|
+
LEFT JOIN document_projection d ON stored.app_kind = 'documents'
|
|
18
|
+
AND d.local_id = stored.local_id
|
|
19
|
+
LEFT JOIN containers folder ON stored.app_kind = 'container-metadata'
|
|
20
|
+
AND folder.id = stored.local_id
|
|
21
|
+
LEFT JOIN container_projection c ON c.container_id = folder.id
|
|
22
|
+
LEFT JOIN document_sync_failures failure ON failure.app_kind = stored.app_kind
|
|
23
|
+
AND failure.local_id = stored.local_id
|
|
24
|
+
WHERE stored.document_id IS NOT NULL
|
|
25
|
+
AND (${emptyContentFrontierSql("stored")} OR stored.pull_continuation IS NOT NULL)
|
|
26
|
+
AND ((stored.app_kind = 'documents' AND d.local_id IS NOT NULL)
|
|
27
|
+
OR (stored.app_kind = 'container-metadata' AND folder.id IS NOT NULL))
|
|
28
|
+
ORDER BY stored.updated_at, stored.app_kind, stored.local_id
|
|
29
|
+
`);
|
|
30
|
+
return rows.flatMap((row) => {
|
|
31
|
+
const { local_id: localId, document_id: documentId, app_kind: appKind, title, reason, last_error: lastError, } = row;
|
|
32
|
+
if (typeof localId !== "string" || typeof documentId !== "string")
|
|
33
|
+
return [];
|
|
34
|
+
const item = {
|
|
35
|
+
localId,
|
|
36
|
+
documentId,
|
|
37
|
+
objectKind: appKind === "documents" ? "document" : "container",
|
|
38
|
+
title: typeof title === "string" ? title : null,
|
|
39
|
+
reason: reason === "initial" ? "initial" : "continuation",
|
|
40
|
+
lastError: typeof lastError === "string" ? lastError : null,
|
|
41
|
+
};
|
|
42
|
+
return [item];
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=pendingDownloads.js.map
|