@tearleads/client-sdk 0.1.44 → 0.1.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/data/persistence/container-contents/containerContentsPersistence.js +2 -3
  2. package/data/persistence/container-contents/containerContentsPersistence.js.map +1 -1
  3. package/data/persistence/container-contents/containerCreateIntentSettlement.js +16 -16
  4. package/data/persistence/container-contents/containerCreateIntentSettlement.js.map +1 -1
  5. package/data/persistence/container-contents/containerDeletionPersistence.js +5 -11
  6. package/data/persistence/container-contents/containerDeletionPersistence.js.map +1 -1
  7. package/data/persistence/container-contents/containerDocumentReassignment.js +13 -13
  8. package/data/persistence/container-contents/containerDocumentReassignment.js.map +1 -1
  9. package/data/persistence/container-contents/containerHydrationPersistence.js +7 -4
  10. package/data/persistence/container-contents/containerHydrationPersistence.js.map +1 -1
  11. package/data/persistence/container-contents/containerIntentPersistence.js +43 -42
  12. package/data/persistence/container-contents/containerIntentPersistence.js.map +1 -1
  13. package/data/persistence/container-contents/containerMetadataMutationPersistence.js +15 -20
  14. package/data/persistence/container-contents/containerMetadataMutationPersistence.js.map +1 -1
  15. package/data/persistence/container-contents/containerMoveAbandonPersistence.js +1 -6
  16. package/data/persistence/container-contents/containerMoveAbandonPersistence.js.map +1 -1
  17. package/data/persistence/container-contents/containerMoveIntentRows.js +9 -8
  18. package/data/persistence/container-contents/containerMoveIntentRows.js.map +1 -1
  19. package/data/persistence/container-contents/containerReconcilePersistence.js +4 -8
  20. package/data/persistence/container-contents/containerReconcilePersistence.js.map +1 -1
  21. package/data/persistence/container-contents/containerRecoveryPersistence.js +20 -19
  22. package/data/persistence/container-contents/containerRecoveryPersistence.js.map +1 -1
  23. package/data/persistence/container-contents/containerRemovalWork.js +10 -10
  24. package/data/persistence/container-contents/containerRemovalWork.js.map +1 -1
  25. package/data/persistence/container-contents/containerStructuralRepair.js +21 -44
  26. package/data/persistence/container-contents/containerStructuralRepair.js.map +1 -1
  27. package/data/persistence/container-contents/documentLinkRemovalRepair.js +12 -11
  28. package/data/persistence/container-contents/documentLinkRemovalRepair.js.map +1 -1
  29. package/data/persistence/container-contents/documentMoveIntentPersistence.js +53 -28
  30. package/data/persistence/container-contents/documentMoveIntentPersistence.js.map +1 -1
  31. package/data/persistence/container-contents/documentPlacementIntentEnqueue.js +9 -8
  32. package/data/persistence/container-contents/documentPlacementIntentEnqueue.js.map +1 -1
  33. package/data/persistence/container-contents/documentPurgePlacement.js +6 -6
  34. package/data/persistence/container-contents/documentPurgePlacement.js.map +1 -1
  35. package/data/persistence/container-contents/dormantContainerMetadata.js +1 -5
  36. package/data/persistence/container-contents/dormantContainerMetadata.js.map +1 -1
  37. package/data/persistence/container-contents/pendingContainerCreate.js +5 -5
  38. package/data/persistence/container-contents/pendingContainerCreate.js.map +1 -1
  39. package/data/persistence/containers/containerPersistence.js +10 -27
  40. package/data/persistence/containers/containerPersistence.js.map +1 -1
  41. package/data/persistence/containers/documentContainerProjectionPersistence.js +2 -2
  42. package/data/persistence/containers/documentContainerProjectionPersistence.js.map +1 -1
  43. package/data/persistence/containers/documentPlacement.js +10 -10
  44. package/data/persistence/containers/documentPlacement.js.map +1 -1
  45. package/data/persistence/documents/internal/discardDocument.js +5 -5
  46. package/data/persistence/documents/internal/discardDocument.js.map +1 -1
  47. package/data/persistence/documents/internal/documentDeletionPersistence.js +7 -9
  48. package/data/persistence/documents/internal/documentDeletionPersistence.js.map +1 -1
  49. package/data/persistence/documents/internal/documentMutationPersistence.js +6 -8
  50. package/data/persistence/documents/internal/documentMutationPersistence.js.map +1 -1
  51. package/data/persistence/documents/internal/ensureDocumentsSchema.js +2 -2
  52. package/data/persistence/documents/internal/ensureDocumentsSchema.js.map +1 -1
  53. package/data/persistence/documents/internal/orphanSideRows.js +3 -22
  54. package/data/persistence/documents/internal/orphanSideRows.js.map +1 -1
  55. package/data/persistence/organizations/organizationDataUsagePersistence.js +31 -64
  56. package/data/persistence/organizations/organizationDataUsagePersistence.js.map +1 -1
  57. package/data/persistence/organizations/organizationReadModelPurge.js +1 -5
  58. package/data/persistence/organizations/organizationReadModelPurge.js.map +1 -1
  59. package/data/persistence/principalCurrentAcknowledgementPersistence.js +24 -17
  60. package/data/persistence/principalCurrentAcknowledgementPersistence.js.map +1 -1
  61. package/data/persistence/principalHistoryIncompleteRetention.js +3 -9
  62. package/data/persistence/principalHistoryIncompleteRetention.js.map +1 -1
  63. package/data/persistence/principalHistoryStagePersistence.d.ts +3 -9
  64. package/data/persistence/principalHistoryStagePersistence.js +15 -25
  65. package/data/persistence/principalHistoryStagePersistence.js.map +1 -1
  66. package/data/persistence/principalHistoryStageRetention.js +16 -15
  67. package/data/persistence/principalHistoryStageRetention.js.map +1 -1
  68. package/data/persistence/principalHistoryUnpublishedRetention.js +6 -13
  69. package/data/persistence/principalHistoryUnpublishedRetention.js.map +1 -1
  70. package/data/sqlite/containerSchema.d.ts +84 -180
  71. package/data/sqlite/containerSchema.js +14 -23
  72. package/data/sqlite/containerSchema.js.map +1 -1
  73. package/data/sqlite/documentPlacementIntentSchema.js +3 -50
  74. package/data/sqlite/documentPlacementIntentSchema.js.map +1 -1
  75. package/data/sqlite/documentSyncFailurePersistence.d.ts +16 -6
  76. package/data/sqlite/documentSyncFailurePersistence.js +44 -54
  77. package/data/sqlite/documentSyncFailurePersistence.js.map +1 -1
  78. package/data/sqlite/{documentPlacementIntentSchema.d.ts → localIntentSchema.d.ts} +162 -88
  79. package/data/sqlite/localIntentSchema.js +90 -0
  80. package/data/sqlite/localIntentSchema.js.map +1 -0
  81. package/data/sqlite/organizationDataUsageSchema.js +11 -17
  82. package/data/sqlite/organizationDataUsageSchema.js.map +1 -1
  83. package/data/sqlite/principalHistoryRetentionSchema.js +0 -15
  84. package/data/sqlite/principalHistoryRetentionSchema.js.map +1 -1
  85. package/data/sqlite/principalHistoryStageSchema.d.ts +44 -2
  86. package/data/sqlite/principalHistoryStageSchema.js +14 -2
  87. package/data/sqlite/principalHistoryStageSchema.js.map +1 -1
  88. package/data/sqlite/schema.d.ts +947 -2112
  89. package/data/sqlite/schema.js +26 -134
  90. package/data/sqlite/schema.js.map +1 -1
  91. package/package.json +1 -1
  92. package/workflows/container-contents/documentPriming.js +6 -10
  93. package/workflows/container-contents/documentPriming.js.map +1 -1
  94. package/workflows/container-contents/documentQueries/sql.js +11 -10
  95. package/workflows/container-contents/documentQueries/sql.js.map +1 -1
  96. package/workflows/container-contents/documentQueries.js +2 -2
  97. package/workflows/container-contents/documentQueries.js.map +1 -1
  98. package/workflows/container-contents/pendingDownloads.js +2 -5
  99. package/workflows/container-contents/pendingDownloads.js.map +1 -1
  100. package/workflows/container-contents/pendingWrites/deferredTails.js +3 -11
  101. package/workflows/container-contents/pendingWrites/deferredTails.js.map +1 -1
  102. package/workflows/container-contents/pendingWrites/sources.js +56 -80
  103. package/workflows/container-contents/pendingWrites/sources.js.map +1 -1
  104. package/workflows/container-contents/pendingWrites.js +6 -4
  105. package/workflows/container-contents/pendingWrites.js.map +1 -1
  106. package/workflows/container-contents/remoteContainerState.js +2 -1
  107. package/workflows/container-contents/remoteContainerState.js.map +1 -1
  108. package/workflows/sync/remoteReset.js +16 -23
  109. package/workflows/sync/remoteReset.js.map +1 -1
  110. package/workflows/sync/remoteResetPrincipalScope.js +1 -2
  111. package/workflows/sync/remoteResetPrincipalScope.js.map +1 -1
  112. package/workflows/sync/remoteResetScope.js +15 -8
  113. package/workflows/sync/remoteResetScope.js.map +1 -1
@@ -1,3 +1,4 @@
1
+ import { LOCAL_INTENT_LANES } from "../../../data/sqlite/schema.js";
1
2
  import { getOrphanedDocumentWhereSql } from "../orphanedDocumentSql.js";
2
3
  import { hydratedProjectionSql } from "./hydrationSql.js";
3
4
  // Keep each IN clause below SQLite's historical 999 bind-parameter limit.
@@ -56,8 +57,8 @@ export function getContainerContentsDocumentPendingStateCtes() {
56
57
  )
57
58
  `;
58
59
  }
59
- export function getContainerDisplayNameSql(aliases) {
60
- return `COALESCE(${aliases.projectionAlias}.display_name, CASE WHEN ${aliases.containerAlias}.parent_id IS NULL THEN '/' ELSE 'Untitled' END)`;
60
+ export function getContainerDisplayNameSql(containerAlias) {
61
+ return `COALESCE(${containerAlias}.display_name, CASE WHEN ${containerAlias}.parent_id IS NULL THEN '/' ELSE 'Untitled' END)`;
61
62
  }
62
63
  /**
63
64
  * Display attribution for an object reached through a container: the
@@ -74,7 +75,7 @@ function getContainerContentsContainerSystemSlotFilter(counts) {
74
75
  }
75
76
  if (counts.visibleForeignSystemContainerNameCount > 0) {
76
77
  const visibleSystemNameBindMarkers = Array.from({ length: counts.visibleForeignSystemContainerNameCount }, () => "?").join(", ");
77
- clauses.push(`(c.organization_id != '' AND c.organization_id != ? AND ${getContainerDisplayNameSql({ containerAlias: "c", projectionAlias: "cp" })} IN (${visibleSystemNameBindMarkers}))`);
78
+ clauses.push(`(c.organization_id != '' AND c.organization_id != ? AND ${getContainerDisplayNameSql("c")} IN (${visibleSystemNameBindMarkers}))`);
78
79
  }
79
80
  return `(${clauses.join(" OR ")})`;
80
81
  }
@@ -107,12 +108,13 @@ export function getContainerContentsContainerItemsBaseSql(visibleSystemSlotCount
107
108
  ),
108
109
  pending_container_create_intents AS (
109
110
  SELECT
110
- container_id,
111
+ subject_id AS container_id,
111
112
  MAX(last_error) AS last_error
112
- FROM container_create_intents
113
- WHERE intent_type = 'container.create'
113
+ FROM local_intents
114
+ WHERE lane = '${LOCAL_INTENT_LANES.containerCreate}'
115
+ AND intent_type = 'container.create'
114
116
  AND sync_status = 'pending'
115
- GROUP BY container_id
117
+ GROUP BY subject_id
116
118
  ),
117
119
  container_items AS (
118
120
  SELECT
@@ -125,17 +127,16 @@ export function getContainerContentsContainerItemsBaseSql(visibleSystemSlotCount
125
127
  c.local_updated_at AS local_updated_at,
126
128
  c.server_created_at AS server_created_at,
127
129
  c.server_updated_at AS server_updated_at,
128
- cp.icon AS icon,
130
+ c.icon AS icon,
129
131
  COALESCE(container_updates.pending_update_count, 0) AS pending_update_count,
130
132
  0 AS pending_attachment_count,
131
133
  0 AS pending_attachment_bytes,
132
134
  create_intent.last_error AS sync_last_error,
133
- ${getContainerDisplayNameSql({ containerAlias: "c", projectionAlias: "cp" })} AS name,
135
+ ${getContainerDisplayNameSql("c")} AS name,
134
136
  'folder' AS type_sort,
135
137
  COALESCE(c.server_created_at, c.local_created_at) AS created_at,
136
138
  COALESCE(c.server_updated_at, c.local_updated_at) AS updated_at
137
139
  FROM containers c
138
- LEFT JOIN container_projection cp ON cp.container_id = c.id
139
140
  LEFT JOIN container_metadata_pending_update_counts container_updates
140
141
  ON container_updates.local_id = c.id
141
142
  LEFT JOIN pending_container_create_intents create_intent
@@ -1 +1 @@
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_history_updates\n WHERE app_kind = 'documents' AND update_id IS NOT NULL\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_history_updates\n WHERE app_kind = 'container-metadata' AND update_id IS NOT NULL\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"]}
1
+ {"version":3,"file":"sql.js","sourceRoot":"","sources":["sql.ts"],"names":[],"mappings":"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","sourcesContent":["import { LOCAL_INTENT_LANES } from \"../../../data/sqlite/schema\";\nimport { 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_history_updates\n WHERE app_kind = 'documents' AND update_id IS NOT NULL\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(containerAlias: string): string {\n return `COALESCE(${containerAlias}.display_name, CASE WHEN ${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(\"c\")} 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_history_updates\n WHERE app_kind = 'container-metadata' AND update_id IS NOT NULL\n GROUP BY local_id\n ),\n pending_container_create_intents AS (\n SELECT\n subject_id AS container_id,\n MAX(last_error) AS last_error\n FROM local_intents\n WHERE lane = '${LOCAL_INTENT_LANES.containerCreate}'\n AND intent_type = 'container.create'\n AND sync_status = 'pending'\n GROUP BY subject_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 c.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(\"c\")} 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_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,7 +3,7 @@ import { ensureContainerTables } from "../../data/persistence/containers/contain
3
3
  import { containerContentsSyncLane, sqlContainerSyncWatermarkPersistence, } from "../../data/persistence/containers/containerSyncWatermarkPersistence.js";
4
4
  import { sqlDocumentContainerProjectionPersistence } from "../../data/persistence/containers/documentContainerProjectionPersistence.js";
5
5
  import { applyContainerDocumentTombstones as applyPersistedContainerDocumentTombstones, sqlDocumentsPersistence, upsertDiscoveredDocuments, } from "../../data/persistence/documents/documentsPersistence.js";
6
- import { containerCreateIntentTables } from "../../data/sqlite/schema.js";
6
+ import { localIntentTables } from "../../data/sqlite/schema.js";
7
7
  import { ensureSqlTables } from "../../data/sqlite/sqlSchema.js";
8
8
  import { hydratedProjectionSql } from "./documentQueries/hydrationSql.js";
9
9
  import { mapContainerContentsDocumentSummaryRow, mapContainerContentsDocumentSyncStateRow, mapContainerDocumentSidebarRow, mapContainerItemRow, readContainerContentsContainerItemCount, } from "./documentQueries/rows.js";
@@ -15,7 +15,7 @@ import { listPendingWrites, resetPendingWriteRetryState, } from "./pendingWrites
15
15
  async function listContainerItemWindow(execSql, input) {
16
16
  await ensureContainerTables(execSql);
17
17
  await sqlDocumentsPersistence.ensureSchema(execSql);
18
- await ensureSqlTables(execSql, containerCreateIntentTables);
18
+ await ensureSqlTables(execSql, localIntentTables);
19
19
  const limit = getContainerItemWindowLimit(input.limit);
20
20
  const offset = clampContainerItemWindowValue(input.offset);
21
21
  const visibleSystemSlots = Array.from(new Set(input.visibleSystemSlots ?? []));
@@ -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 { 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"]}
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 { localIntentTables } 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, localIntentTables);\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"]}
@@ -9,18 +9,15 @@ export async function listPendingDownloads(execSql) {
9
9
  SELECT stored.local_id, stored.document_id, stored.app_kind,
10
10
  CASE WHEN ${emptyContentFrontierSql("stored")} THEN NULL
11
11
  WHEN stored.app_kind = 'documents' THEN d.title
12
- ELSE c.display_name END AS title,
12
+ ELSE folder.display_name END AS title,
13
13
  CASE WHEN ${emptyContentFrontierSql("stored")} THEN 'initial'
14
14
  ELSE 'continuation' END AS reason,
15
- failure.message AS last_error
15
+ stored.sync_failure_message AS last_error
16
16
  FROM documents stored
17
17
  LEFT JOIN document_projection d ON stored.app_kind = 'documents'
18
18
  AND d.local_id = stored.local_id
19
19
  LEFT JOIN containers folder ON stored.app_kind = 'container-metadata'
20
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
21
  WHERE stored.document_id IS NOT NULL
25
22
  AND (${emptyContentFrontierSql("stored")} OR stored.pull_continuation IS NOT NULL)
26
23
  AND ((stored.app_kind = 'documents' AND d.local_id IS NOT NULL)
@@ -1 +1 @@
1
- {"version":3,"file":"pendingDownloads.js","sourceRoot":"","sources":["pendingDownloads.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,wDAAwD,CAAC;AAC/F,OAAO,EAAE,uBAAuB,EAAE,MAAM,uDAAuD,CAAC;AAEhG,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAYzE,4EAA4E;AAC5E,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,OAAgB;IAEhB,MAAM,qBAAqB,CAAC,OAAO,CAAC,CAAC;IACrC,MAAM,uBAAuB,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;IACpD,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC;;kBAEX,uBAAuB,CAAC,QAAQ,CAAC;;;kBAGjC,uBAAuB,CAAC,QAAQ,CAAC;;;;;;;;;;;;aAYtC,uBAAuB,CAAC,QAAQ,CAAC;;;;GAI3C,CAAC,CAAC;IACH,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;QAC1B,MAAM,EACJ,QAAQ,EAAE,OAAO,EACjB,WAAW,EAAE,UAAU,EACvB,QAAQ,EAAE,OAAO,EACjB,KAAK,EACL,MAAM,EACN,UAAU,EAAE,SAAS,GACtB,GAAG,GAAG,CAAC;QACR,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,UAAU,KAAK,QAAQ;YAC/D,OAAO,EAAE,CAAC;QACZ,MAAM,IAAI,GAA6B;YACrC,OAAO;YACP,UAAU;YACV,UAAU,EAAE,OAAO,KAAK,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW;YAC9D,KAAK,EAAE,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI;YAC/C,MAAM,EAAE,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,cAAc;YACzD,SAAS,EAAE,OAAO,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI;SAC5D,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC;IAChB,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { ensureContainerTables } from \"../../data/persistence/containers/containerPersistence\";\nimport { sqlDocumentsPersistence } from \"../../data/persistence/documents/documentsPersistence\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport { emptyContentFrontierSql } from \"./documentQueries/hydrationSql\";\n\nexport interface PendingDownloadQueueItem {\n localId: string;\n documentId: string;\n objectKind: \"document\" | \"container\";\n /** Null until content supplies a reliable title and type. */\n title: string | null;\n reason: \"initial\" | \"continuation\";\n lastError: string | null;\n}\n\n/** Durable, already-discovered content pulls, including folder metadata. */\nexport async function listPendingDownloads(\n execSql: ExecSql,\n): Promise<ReadonlyArray<PendingDownloadQueueItem>> {\n await ensureContainerTables(execSql);\n await sqlDocumentsPersistence.ensureSchema(execSql);\n const rows = await execSql(`\n SELECT stored.local_id, stored.document_id, stored.app_kind,\n CASE WHEN ${emptyContentFrontierSql(\"stored\")} THEN NULL\n WHEN stored.app_kind = 'documents' THEN d.title\n ELSE c.display_name END AS title,\n CASE WHEN ${emptyContentFrontierSql(\"stored\")} THEN 'initial'\n ELSE 'continuation' END AS reason,\n failure.message AS last_error\n FROM documents stored\n LEFT JOIN document_projection d ON stored.app_kind = 'documents'\n AND d.local_id = stored.local_id\n LEFT JOIN containers folder ON stored.app_kind = 'container-metadata'\n AND folder.id = stored.local_id\n LEFT JOIN container_projection c ON c.container_id = folder.id\n LEFT JOIN document_sync_failures failure ON failure.app_kind = stored.app_kind\n AND failure.local_id = stored.local_id\n WHERE stored.document_id IS NOT NULL\n AND (${emptyContentFrontierSql(\"stored\")} OR stored.pull_continuation IS NOT NULL)\n AND ((stored.app_kind = 'documents' AND d.local_id IS NOT NULL)\n OR (stored.app_kind = 'container-metadata' AND folder.id IS NOT NULL))\n ORDER BY stored.updated_at, stored.app_kind, stored.local_id\n `);\n return rows.flatMap((row) => {\n const {\n local_id: localId,\n document_id: documentId,\n app_kind: appKind,\n title,\n reason,\n last_error: lastError,\n } = row;\n if (typeof localId !== \"string\" || typeof documentId !== \"string\")\n return [];\n const item: PendingDownloadQueueItem = {\n localId,\n documentId,\n objectKind: appKind === \"documents\" ? \"document\" : \"container\",\n title: typeof title === \"string\" ? title : null,\n reason: reason === \"initial\" ? \"initial\" : \"continuation\",\n lastError: typeof lastError === \"string\" ? lastError : null,\n };\n return [item];\n });\n}\n"]}
1
+ {"version":3,"file":"pendingDownloads.js","sourceRoot":"","sources":["pendingDownloads.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,wDAAwD,CAAC;AAC/F,OAAO,EAAE,uBAAuB,EAAE,MAAM,uDAAuD,CAAC;AAEhG,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAYzE,4EAA4E;AAC5E,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,OAAgB;IAEhB,MAAM,qBAAqB,CAAC,OAAO,CAAC,CAAC;IACrC,MAAM,uBAAuB,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;IACpD,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC;;kBAEX,uBAAuB,CAAC,QAAQ,CAAC;;;kBAGjC,uBAAuB,CAAC,QAAQ,CAAC;;;;;;;;;aAStC,uBAAuB,CAAC,QAAQ,CAAC;;;;GAI3C,CAAC,CAAC;IACH,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;QAC1B,MAAM,EACJ,QAAQ,EAAE,OAAO,EACjB,WAAW,EAAE,UAAU,EACvB,QAAQ,EAAE,OAAO,EACjB,KAAK,EACL,MAAM,EACN,UAAU,EAAE,SAAS,GACtB,GAAG,GAAG,CAAC;QACR,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,UAAU,KAAK,QAAQ;YAC/D,OAAO,EAAE,CAAC;QACZ,MAAM,IAAI,GAA6B;YACrC,OAAO;YACP,UAAU;YACV,UAAU,EAAE,OAAO,KAAK,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW;YAC9D,KAAK,EAAE,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI;YAC/C,MAAM,EAAE,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,cAAc;YACzD,SAAS,EAAE,OAAO,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI;SAC5D,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC;IAChB,CAAC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { ensureContainerTables } from \"../../data/persistence/containers/containerPersistence\";\nimport { sqlDocumentsPersistence } from \"../../data/persistence/documents/documentsPersistence\";\nimport type { ExecSql } from \"../../data/sqlite/sqlSchema\";\nimport { emptyContentFrontierSql } from \"./documentQueries/hydrationSql\";\n\nexport interface PendingDownloadQueueItem {\n localId: string;\n documentId: string;\n objectKind: \"document\" | \"container\";\n /** Null until content supplies a reliable title and type. */\n title: string | null;\n reason: \"initial\" | \"continuation\";\n lastError: string | null;\n}\n\n/** Durable, already-discovered content pulls, including folder metadata. */\nexport async function listPendingDownloads(\n execSql: ExecSql,\n): Promise<ReadonlyArray<PendingDownloadQueueItem>> {\n await ensureContainerTables(execSql);\n await sqlDocumentsPersistence.ensureSchema(execSql);\n const rows = await execSql(`\n SELECT stored.local_id, stored.document_id, stored.app_kind,\n CASE WHEN ${emptyContentFrontierSql(\"stored\")} THEN NULL\n WHEN stored.app_kind = 'documents' THEN d.title\n ELSE folder.display_name END AS title,\n CASE WHEN ${emptyContentFrontierSql(\"stored\")} THEN 'initial'\n ELSE 'continuation' END AS reason,\n stored.sync_failure_message AS last_error\n FROM documents stored\n LEFT JOIN document_projection d ON stored.app_kind = 'documents'\n AND d.local_id = stored.local_id\n LEFT JOIN containers folder ON stored.app_kind = 'container-metadata'\n AND folder.id = stored.local_id\n WHERE stored.document_id IS NOT NULL\n AND (${emptyContentFrontierSql(\"stored\")} OR stored.pull_continuation IS NOT NULL)\n AND ((stored.app_kind = 'documents' AND d.local_id IS NOT NULL)\n OR (stored.app_kind = 'container-metadata' AND folder.id IS NOT NULL))\n ORDER BY stored.updated_at, stored.app_kind, stored.local_id\n `);\n return rows.flatMap((row) => {\n const {\n local_id: localId,\n document_id: documentId,\n app_kind: appKind,\n title,\n reason,\n last_error: lastError,\n } = row;\n if (typeof localId !== \"string\" || typeof documentId !== \"string\")\n return [];\n const item: PendingDownloadQueueItem = {\n localId,\n documentId,\n objectKind: appKind === \"documents\" ? \"document\" : \"container\",\n title: typeof title === \"string\" ? title : null,\n reason: reason === \"initial\" ? \"initial\" : \"continuation\",\n lastError: typeof lastError === \"string\" ? lastError : null,\n };\n return [item];\n });\n}\n"]}
@@ -32,14 +32,11 @@ const DEFERRED_TAIL_CANDIDATE_SQL = `
32
32
  WHEN metadata_container.server_created_at IS NULL THEN NULL
33
33
  ELSE metadata_container.id
34
34
  END AS container_remote_id,
35
- ${getContainerDisplayNameSql({
36
- containerAlias: "metadata_container",
37
- projectionAlias: "container_projection",
38
- })} AS container_name,
35
+ ${getContainerDisplayNameSql("metadata_container")} AS container_name,
39
36
  metadata_container.id AS metadata_container_id,
40
37
  NULLIF(metadata_container.organization_id, '') AS metadata_organization_id,
41
- failure.message AS failure_message,
42
- failure.attempted_at AS failure_attempted_at
38
+ stored.sync_failure_message AS failure_message,
39
+ stored.sync_failure_attempted_at AS failure_attempted_at
43
40
  FROM documents stored
44
41
  LEFT JOIN document_projection
45
42
  ON stored.app_kind = 'documents'
@@ -49,11 +46,6 @@ const DEFERRED_TAIL_CANDIDATE_SQL = `
49
46
  LEFT JOIN containers metadata_container
50
47
  ON stored.app_kind = 'container-metadata'
51
48
  AND metadata_container.id = stored.local_id
52
- LEFT JOIN container_projection
53
- ON container_projection.container_id = metadata_container.id
54
- LEFT JOIN document_sync_failures failure
55
- ON failure.app_kind = stored.app_kind
56
- AND failure.local_id = stored.local_id
57
49
  WHERE stored.snapshot_end_version <> ''
58
50
  -- Dormant retained metadata (row 4, access_revoked) has no containers
59
51
  -- row; keep it out of deferred-tail candidates until re-attach, matching
@@ -1 +1 @@
1
- {"version":3,"file":"deferredTails.js","sourceRoot":"","sources":["deferredTails.ts"],"names":[],"mappings":"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","sourcesContent":["import { mergeVersionVectors, satisfiesVersionVector } from \"@tearleads/loro\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport {\n getContainerDisplayNameSql,\n getContainerOrganizationAttributionSql,\n} from \"../documentQueries/sql\";\nimport type { PendingWriteQueueObjectKind } from \"../pendingWritesTypes\";\nimport type { PendingWriteCandidate } from \"./aggregation\";\nimport { readString } from \"./rowReaders\";\n\n// Deliberately never loads document content: the diagnostic listing runs\n// repeatedly while sync drains, and materializing every content blob would\n// make the scan O(total document content). `snapshot_end_version` is the\n// write-time-derived end version vector of the persisted content.\nconst DEFERRED_TAIL_CANDIDATE_SQL = `\n SELECT\n stored.app_kind AS app_kind,\n stored.local_id AS local_id,\n stored.document_id AS stored_remote_id,\n stored.snapshot_end_version AS snapshot_end_version,\n stored.pending_base_version AS pending_base_version,\n stored.updated_at AS updated_at,\n (\n SELECT pending.partial_end_version_vector\n FROM document_history_updates pending\n WHERE pending.app_kind = stored.app_kind\n AND pending.local_id = stored.local_id\n AND pending.update_id IS NOT NULL\n ORDER BY pending.created_at DESC, pending.rowid DESC\n LIMIT 1\n ) AS latest_pending_end_version,\n document_projection.title AS document_name,\n document_projection.container_id AS document_container_id,\n ${getContainerOrganizationAttributionSql({\n containerAlias: \"document_container\",\n projectionAlias: \"document_projection\",\n })} AS document_organization_id,\n CASE\n WHEN metadata_container.server_created_at IS NULL THEN NULL\n ELSE metadata_container.id\n END AS container_remote_id,\n ${getContainerDisplayNameSql({\n containerAlias: \"metadata_container\",\n projectionAlias: \"container_projection\",\n })} AS container_name,\n metadata_container.id AS metadata_container_id,\n NULLIF(metadata_container.organization_id, '') AS metadata_organization_id,\n failure.message AS failure_message,\n failure.attempted_at AS failure_attempted_at\n FROM documents stored\n LEFT JOIN document_projection\n ON stored.app_kind = 'documents'\n AND document_projection.local_id = stored.local_id\n LEFT JOIN containers document_container\n ON document_container.id = document_projection.container_id\n LEFT JOIN containers metadata_container\n ON stored.app_kind = 'container-metadata'\n AND metadata_container.id = stored.local_id\n LEFT JOIN container_projection\n ON container_projection.container_id = metadata_container.id\n LEFT JOIN document_sync_failures failure\n ON failure.app_kind = stored.app_kind\n AND failure.local_id = stored.local_id\n WHERE stored.snapshot_end_version <> ''\n -- Dormant retained metadata (row 4, access_revoked) has no containers\n -- row; keep it out of deferred-tail candidates until re-attach, matching\n -- the pending-write sources guard.\n AND (stored.app_kind <> 'container-metadata'\n OR metadata_container.id IS NOT NULL)\n AND (\n stored.pending_base_version IS NOT NULL\n OR EXISTS (\n SELECT 1\n FROM document_history_updates pending\n WHERE pending.app_kind = stored.app_kind\n AND pending.local_id = stored.local_id\n AND pending.update_id IS NOT NULL\n )\n )\n`;\n\nfunction hasUncoveredTail(input: {\n currentVersion: string;\n latestPendingEndVersion: string | null;\n pendingBaseVersion: string | null;\n}): boolean {\n const coverageVersions = [\n input.latestPendingEndVersion,\n input.pendingBaseVersion,\n ].filter((value): value is string => value !== null);\n const validCoverageVersions: string[] = [];\n for (const coverageVersion of coverageVersions) {\n try {\n validCoverageVersions.push(mergeVersionVectors([coverageVersion]));\n } catch {\n // Corrupt coverage must not make the diagnostic claim an uncovered write.\n return false;\n }\n }\n if (validCoverageVersions.length === 0) {\n return false;\n }\n\n try {\n const mergedCoverage = mergeVersionVectors(validCoverageVersions);\n return !satisfiesVersionVector(mergedCoverage, input.currentVersion);\n } catch {\n // Corrupt coverage must not make the diagnostic claim an uncovered write.\n return false;\n }\n}\n\nfunction getObjectKind(appKind: string): PendingWriteQueueObjectKind {\n if (appKind === \"documents\") return \"document\";\n if (appKind === \"container-metadata\") return \"container\";\n return \"unknown\";\n}\n\nfunction mapDeferredTailCandidate(\n row: Record<string, unknown>,\n): PendingWriteCandidate | null {\n const appKind = readString(row, \"app_kind\");\n const localId = readString(row, \"local_id\");\n const currentVersion = readString(row, \"snapshot_end_version\");\n if (!appKind || !localId || !currentVersion) {\n return null;\n }\n if (\n !hasUncoveredTail({\n currentVersion,\n latestPendingEndVersion: readString(row, \"latest_pending_end_version\"),\n pendingBaseVersion: readString(row, \"pending_base_version\"),\n })\n ) {\n return null;\n }\n\n const objectKind = getObjectKind(appKind);\n const updatedAt = readString(row, \"updated_at\");\n return {\n byteLength: 0,\n containerId:\n objectKind === \"container\"\n ? readString(row, \"metadata_container_id\")\n : objectKind === \"document\"\n ? readString(row, \"document_container_id\")\n : null,\n count: 1,\n createdAt: updatedAt,\n inclusion: \"always\",\n kind: \"deferred-update\",\n // Carry the scope's recorded sync failure so a covering deferred-update\n // candidate never hides the diagnostic a suppressed failure-only item\n // would have shown.\n lastAttemptedAt: readString(row, \"failure_attempted_at\"),\n lastError: readString(row, \"failure_message\"),\n localId,\n name:\n objectKind === \"container\"\n ? readString(row, \"container_name\")\n : objectKind === \"document\"\n ? readString(row, \"document_name\")\n : null,\n namespace: objectKind === \"unknown\" ? appKind : null,\n objectKind,\n organizationId:\n objectKind === \"container\"\n ? readString(row, \"metadata_organization_id\")\n : objectKind === \"document\"\n ? readString(row, \"document_organization_id\")\n : null,\n remoteId:\n objectKind === \"container\"\n ? readString(row, \"container_remote_id\")\n : readString(row, \"stored_remote_id\"),\n status: \"pending\",\n targetContainerId: null,\n updatedAt,\n };\n}\n\nexport async function listDeferredPendingWriteCandidates(\n execSql: ExecSql,\n): Promise<PendingWriteCandidate[]> {\n const rows = await execSql(DEFERRED_TAIL_CANDIDATE_SQL);\n return rows.flatMap((row) => {\n const candidate = mapDeferredTailCandidate(row);\n return candidate ? [candidate] : [];\n });\n}\n\nconst DEFERRED_TAIL_SCOPE_SQL = `\n SELECT\n stored.snapshot_end_version AS snapshot_end_version,\n stored.pending_base_version AS pending_base_version,\n (\n SELECT pending.partial_end_version_vector\n FROM document_history_updates pending\n WHERE pending.app_kind = stored.app_kind\n AND pending.local_id = stored.local_id\n AND pending.update_id IS NOT NULL\n ORDER BY pending.created_at DESC, pending.rowid DESC\n LIMIT 1\n ) AS latest_pending_end_version\n FROM documents stored\n WHERE stored.app_kind = ? AND stored.local_id = ?\n AND stored.snapshot_end_version <> ''\n -- Dormant retained metadata (row 4, access_revoked) has no containers\n -- row; it is not queued work until re-attach, matching the candidate\n -- scan's guard.\n AND (stored.app_kind <> 'container-metadata'\n OR EXISTS (SELECT 1 FROM containers WHERE containers.id = stored.local_id))\n LIMIT 1\n`;\n\n/**\n * Whether this one scope has a deferred write: durable-tail content ahead of\n * its covered frontier, possibly with no queued update rows at all. The same\n * coverage check as the candidate scan, narrowed to a single scope, so\n * \"queued work\" classifications agree with the item the panel rendered.\n */\nexport async function hasDeferredTailScopeWork(\n execSql: ExecSql,\n scope: { appKind: string; localId: string },\n): Promise<boolean> {\n const rows = await execSql(DEFERRED_TAIL_SCOPE_SQL, [\n scope.appKind,\n scope.localId,\n ]);\n const row = rows[0];\n if (!row) {\n return false;\n }\n const currentVersion = readString(row, \"snapshot_end_version\");\n if (!currentVersion) {\n return false;\n }\n return hasUncoveredTail({\n currentVersion,\n latestPendingEndVersion: readString(row, \"latest_pending_end_version\"),\n pendingBaseVersion: readString(row, \"pending_base_version\"),\n });\n}\n"]}
1
+ {"version":3,"file":"deferredTails.js","sourceRoot":"","sources":["deferredTails.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAE9E,OAAO,EACL,0BAA0B,EAC1B,sCAAsC,GACvC,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,yEAAyE;AACzE,2EAA2E;AAC3E,yEAAyE;AACzE,kEAAkE;AAClE,MAAM,2BAA2B,GAAG;;;;;;;;;;;;;;;;;;;MAmB9B,sCAAsC,CAAC;IACvC,cAAc,EAAE,oBAAoB;IACpC,eAAe,EAAE,qBAAqB;CACvC,CAAC;;;;;MAKA,0BAA0B,CAAC,oBAAoB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8BrD,CAAC;AAEF,SAAS,gBAAgB,CAAC,KAIzB;IACC,MAAM,gBAAgB,GAAG;QACvB,KAAK,CAAC,uBAAuB;QAC7B,KAAK,CAAC,kBAAkB;KACzB,CAAC,MAAM,CAAC,CAAC,KAAK,EAAmB,EAAE,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC;IACrD,MAAM,qBAAqB,GAAa,EAAE,CAAC;IAC3C,KAAK,MAAM,eAAe,IAAI,gBAAgB,EAAE,CAAC;QAC/C,IAAI,CAAC;YACH,qBAAqB,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QACrE,CAAC;QAAC,MAAM,CAAC;YACP,0EAA0E;YAC1E,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,IAAI,qBAAqB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC;QACH,MAAM,cAAc,GAAG,mBAAmB,CAAC,qBAAqB,CAAC,CAAC;QAClE,OAAO,CAAC,sBAAsB,CAAC,cAAc,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC;IACvE,CAAC;IAAC,MAAM,CAAC;QACP,0EAA0E;QAC1E,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,OAAe;IACpC,IAAI,OAAO,KAAK,WAAW;QAAE,OAAO,UAAU,CAAC;IAC/C,IAAI,OAAO,KAAK,oBAAoB;QAAE,OAAO,WAAW,CAAC;IACzD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,wBAAwB,CAC/B,GAA4B;IAE5B,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAC5C,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IAC5C,MAAM,cAAc,GAAG,UAAU,CAAC,GAAG,EAAE,sBAAsB,CAAC,CAAC;IAC/D,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,IAAI,CAAC,cAAc,EAAE,CAAC;QAC5C,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IACE,CAAC,gBAAgB,CAAC;QAChB,cAAc;QACd,uBAAuB,EAAE,UAAU,CAAC,GAAG,EAAE,4BAA4B,CAAC;QACtE,kBAAkB,EAAE,UAAU,CAAC,GAAG,EAAE,sBAAsB,CAAC;KAC5D,CAAC,EACF,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,UAAU,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;IAC1C,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IAChD,OAAO;QACL,UAAU,EAAE,CAAC;QACb,WAAW,EACT,UAAU,KAAK,WAAW;YACxB,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,uBAAuB,CAAC;YAC1C,CAAC,CAAC,UAAU,KAAK,UAAU;gBACzB,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,uBAAuB,CAAC;gBAC1C,CAAC,CAAC,IAAI;QACZ,KAAK,EAAE,CAAC;QACR,SAAS,EAAE,SAAS;QACpB,SAAS,EAAE,QAAQ;QACnB,IAAI,EAAE,iBAAiB;QACvB,wEAAwE;QACxE,sEAAsE;QACtE,oBAAoB;QACpB,eAAe,EAAE,UAAU,CAAC,GAAG,EAAE,sBAAsB,CAAC;QACxD,SAAS,EAAE,UAAU,CAAC,GAAG,EAAE,iBAAiB,CAAC;QAC7C,OAAO;QACP,IAAI,EACF,UAAU,KAAK,WAAW;YACxB,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,gBAAgB,CAAC;YACnC,CAAC,CAAC,UAAU,KAAK,UAAU;gBACzB,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,eAAe,CAAC;gBAClC,CAAC,CAAC,IAAI;QACZ,SAAS,EAAE,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI;QACpD,UAAU;QACV,cAAc,EACZ,UAAU,KAAK,WAAW;YACxB,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,0BAA0B,CAAC;YAC7C,CAAC,CAAC,UAAU,KAAK,UAAU;gBACzB,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,0BAA0B,CAAC;gBAC7C,CAAC,CAAC,IAAI;QACZ,QAAQ,EACN,UAAU,KAAK,WAAW;YACxB,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,qBAAqB,CAAC;YACxC,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,kBAAkB,CAAC;QACzC,MAAM,EAAE,SAAS;QACjB,iBAAiB,EAAE,IAAI;QACvB,SAAS;KACV,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kCAAkC,CACtD,OAAgB;IAEhB,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,2BAA2B,CAAC,CAAC;IACxD,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;QAC1B,MAAM,SAAS,GAAG,wBAAwB,CAAC,GAAG,CAAC,CAAC;QAChD,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACtC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,uBAAuB,GAAG;;;;;;;;;;;;;;;;;;;;;;CAsB/B,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,OAAgB,EAChB,KAA2C;IAE3C,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,uBAAuB,EAAE;QAClD,KAAK,CAAC,OAAO;QACb,KAAK,CAAC,OAAO;KACd,CAAC,CAAC;IACH,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,cAAc,GAAG,UAAU,CAAC,GAAG,EAAE,sBAAsB,CAAC,CAAC;IAC/D,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,gBAAgB,CAAC;QACtB,cAAc;QACd,uBAAuB,EAAE,UAAU,CAAC,GAAG,EAAE,4BAA4B,CAAC;QACtE,kBAAkB,EAAE,UAAU,CAAC,GAAG,EAAE,sBAAsB,CAAC;KAC5D,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { mergeVersionVectors, satisfiesVersionVector } from \"@tearleads/loro\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport {\n getContainerDisplayNameSql,\n getContainerOrganizationAttributionSql,\n} from \"../documentQueries/sql\";\nimport type { PendingWriteQueueObjectKind } from \"../pendingWritesTypes\";\nimport type { PendingWriteCandidate } from \"./aggregation\";\nimport { readString } from \"./rowReaders\";\n\n// Deliberately never loads document content: the diagnostic listing runs\n// repeatedly while sync drains, and materializing every content blob would\n// make the scan O(total document content). `snapshot_end_version` is the\n// write-time-derived end version vector of the persisted content.\nconst DEFERRED_TAIL_CANDIDATE_SQL = `\n SELECT\n stored.app_kind AS app_kind,\n stored.local_id AS local_id,\n stored.document_id AS stored_remote_id,\n stored.snapshot_end_version AS snapshot_end_version,\n stored.pending_base_version AS pending_base_version,\n stored.updated_at AS updated_at,\n (\n SELECT pending.partial_end_version_vector\n FROM document_history_updates pending\n WHERE pending.app_kind = stored.app_kind\n AND pending.local_id = stored.local_id\n AND pending.update_id IS NOT NULL\n ORDER BY pending.created_at DESC, pending.rowid DESC\n LIMIT 1\n ) AS latest_pending_end_version,\n document_projection.title AS document_name,\n document_projection.container_id AS document_container_id,\n ${getContainerOrganizationAttributionSql({\n containerAlias: \"document_container\",\n projectionAlias: \"document_projection\",\n })} AS document_organization_id,\n CASE\n WHEN metadata_container.server_created_at IS NULL THEN NULL\n ELSE metadata_container.id\n END AS container_remote_id,\n ${getContainerDisplayNameSql(\"metadata_container\")} AS container_name,\n metadata_container.id AS metadata_container_id,\n NULLIF(metadata_container.organization_id, '') AS metadata_organization_id,\n stored.sync_failure_message AS failure_message,\n stored.sync_failure_attempted_at AS failure_attempted_at\n FROM documents stored\n LEFT JOIN document_projection\n ON stored.app_kind = 'documents'\n AND document_projection.local_id = stored.local_id\n LEFT JOIN containers document_container\n ON document_container.id = document_projection.container_id\n LEFT JOIN containers metadata_container\n ON stored.app_kind = 'container-metadata'\n AND metadata_container.id = stored.local_id\n WHERE stored.snapshot_end_version <> ''\n -- Dormant retained metadata (row 4, access_revoked) has no containers\n -- row; keep it out of deferred-tail candidates until re-attach, matching\n -- the pending-write sources guard.\n AND (stored.app_kind <> 'container-metadata'\n OR metadata_container.id IS NOT NULL)\n AND (\n stored.pending_base_version IS NOT NULL\n OR EXISTS (\n SELECT 1\n FROM document_history_updates pending\n WHERE pending.app_kind = stored.app_kind\n AND pending.local_id = stored.local_id\n AND pending.update_id IS NOT NULL\n )\n )\n`;\n\nfunction hasUncoveredTail(input: {\n currentVersion: string;\n latestPendingEndVersion: string | null;\n pendingBaseVersion: string | null;\n}): boolean {\n const coverageVersions = [\n input.latestPendingEndVersion,\n input.pendingBaseVersion,\n ].filter((value): value is string => value !== null);\n const validCoverageVersions: string[] = [];\n for (const coverageVersion of coverageVersions) {\n try {\n validCoverageVersions.push(mergeVersionVectors([coverageVersion]));\n } catch {\n // Corrupt coverage must not make the diagnostic claim an uncovered write.\n return false;\n }\n }\n if (validCoverageVersions.length === 0) {\n return false;\n }\n\n try {\n const mergedCoverage = mergeVersionVectors(validCoverageVersions);\n return !satisfiesVersionVector(mergedCoverage, input.currentVersion);\n } catch {\n // Corrupt coverage must not make the diagnostic claim an uncovered write.\n return false;\n }\n}\n\nfunction getObjectKind(appKind: string): PendingWriteQueueObjectKind {\n if (appKind === \"documents\") return \"document\";\n if (appKind === \"container-metadata\") return \"container\";\n return \"unknown\";\n}\n\nfunction mapDeferredTailCandidate(\n row: Record<string, unknown>,\n): PendingWriteCandidate | null {\n const appKind = readString(row, \"app_kind\");\n const localId = readString(row, \"local_id\");\n const currentVersion = readString(row, \"snapshot_end_version\");\n if (!appKind || !localId || !currentVersion) {\n return null;\n }\n if (\n !hasUncoveredTail({\n currentVersion,\n latestPendingEndVersion: readString(row, \"latest_pending_end_version\"),\n pendingBaseVersion: readString(row, \"pending_base_version\"),\n })\n ) {\n return null;\n }\n\n const objectKind = getObjectKind(appKind);\n const updatedAt = readString(row, \"updated_at\");\n return {\n byteLength: 0,\n containerId:\n objectKind === \"container\"\n ? readString(row, \"metadata_container_id\")\n : objectKind === \"document\"\n ? readString(row, \"document_container_id\")\n : null,\n count: 1,\n createdAt: updatedAt,\n inclusion: \"always\",\n kind: \"deferred-update\",\n // Carry the scope's recorded sync failure so a covering deferred-update\n // candidate never hides the diagnostic a suppressed failure-only item\n // would have shown.\n lastAttemptedAt: readString(row, \"failure_attempted_at\"),\n lastError: readString(row, \"failure_message\"),\n localId,\n name:\n objectKind === \"container\"\n ? readString(row, \"container_name\")\n : objectKind === \"document\"\n ? readString(row, \"document_name\")\n : null,\n namespace: objectKind === \"unknown\" ? appKind : null,\n objectKind,\n organizationId:\n objectKind === \"container\"\n ? readString(row, \"metadata_organization_id\")\n : objectKind === \"document\"\n ? readString(row, \"document_organization_id\")\n : null,\n remoteId:\n objectKind === \"container\"\n ? readString(row, \"container_remote_id\")\n : readString(row, \"stored_remote_id\"),\n status: \"pending\",\n targetContainerId: null,\n updatedAt,\n };\n}\n\nexport async function listDeferredPendingWriteCandidates(\n execSql: ExecSql,\n): Promise<PendingWriteCandidate[]> {\n const rows = await execSql(DEFERRED_TAIL_CANDIDATE_SQL);\n return rows.flatMap((row) => {\n const candidate = mapDeferredTailCandidate(row);\n return candidate ? [candidate] : [];\n });\n}\n\nconst DEFERRED_TAIL_SCOPE_SQL = `\n SELECT\n stored.snapshot_end_version AS snapshot_end_version,\n stored.pending_base_version AS pending_base_version,\n (\n SELECT pending.partial_end_version_vector\n FROM document_history_updates pending\n WHERE pending.app_kind = stored.app_kind\n AND pending.local_id = stored.local_id\n AND pending.update_id IS NOT NULL\n ORDER BY pending.created_at DESC, pending.rowid DESC\n LIMIT 1\n ) AS latest_pending_end_version\n FROM documents stored\n WHERE stored.app_kind = ? AND stored.local_id = ?\n AND stored.snapshot_end_version <> ''\n -- Dormant retained metadata (row 4, access_revoked) has no containers\n -- row; it is not queued work until re-attach, matching the candidate\n -- scan's guard.\n AND (stored.app_kind <> 'container-metadata'\n OR EXISTS (SELECT 1 FROM containers WHERE containers.id = stored.local_id))\n LIMIT 1\n`;\n\n/**\n * Whether this one scope has a deferred write: durable-tail content ahead of\n * its covered frontier, possibly with no queued update rows at all. The same\n * coverage check as the candidate scan, narrowed to a single scope, so\n * \"queued work\" classifications agree with the item the panel rendered.\n */\nexport async function hasDeferredTailScopeWork(\n execSql: ExecSql,\n scope: { appKind: string; localId: string },\n): Promise<boolean> {\n const rows = await execSql(DEFERRED_TAIL_SCOPE_SQL, [\n scope.appKind,\n scope.localId,\n ]);\n const row = rows[0];\n if (!row) {\n return false;\n }\n const currentVersion = readString(row, \"snapshot_end_version\");\n if (!currentVersion) {\n return false;\n }\n return hasUncoveredTail({\n currentVersion,\n latestPendingEndVersion: readString(row, \"latest_pending_end_version\"),\n pendingBaseVersion: readString(row, \"pending_base_version\"),\n });\n}\n"]}