@rvoh/dream 2.27.0 → 2.28.1

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 (330) hide show
  1. package/dist/cjs/src/Dream.js +63 -1
  2. package/dist/cjs/src/db/errors.js +4 -0
  3. package/dist/cjs/src/decorators/field/Encrypted.js +12 -0
  4. package/dist/cjs/src/decorators/field/sortable/Sortable.js +43 -118
  5. package/dist/cjs/src/decorators/field/sortable/helpers/acquireSortableScopeLocks.js +38 -0
  6. package/dist/cjs/src/decorators/field/sortable/helpers/acquireStabilizedSortableBatchLocks.js +183 -0
  7. package/dist/cjs/src/decorators/field/sortable/helpers/acquireStabilizedSortableScopeLocks.js +40 -0
  8. package/dist/cjs/src/decorators/field/sortable/helpers/canonicalScopeValue.js +194 -0
  9. package/dist/cjs/src/decorators/field/sortable/helpers/clearCachedSortableValues.js +18 -0
  10. package/dist/cjs/src/decorators/field/sortable/helpers/decrementScopedRecordsGreaterThanPosition.js +9 -9
  11. package/dist/cjs/src/decorators/field/sortable/helpers/filterQueryToInstanceScope.js +20 -0
  12. package/dist/cjs/src/decorators/field/sortable/helpers/filterQueryToScopeValues.js +32 -0
  13. package/dist/cjs/src/decorators/field/sortable/helpers/heldSortableScopeLockKeys.js +34 -0
  14. package/dist/cjs/src/decorators/field/sortable/helpers/performSortableDestroyWork.js +21 -0
  15. package/dist/cjs/src/decorators/field/sortable/helpers/performSortablePositionWork.js +36 -0
  16. package/dist/cjs/src/decorators/field/sortable/helpers/prepareSortableFieldsForDestroy.js +56 -0
  17. package/dist/cjs/src/decorators/field/sortable/helpers/prepareSortableFieldsForSave.js +84 -0
  18. package/dist/cjs/src/decorators/field/sortable/helpers/resortAllRecords.js +186 -29
  19. package/dist/cjs/src/decorators/field/sortable/helpers/setPosition.js +90 -46
  20. package/dist/cjs/src/decorators/field/sortable/helpers/sortableRowCache.js +73 -0
  21. package/dist/cjs/src/decorators/field/sortable/helpers/sortableScopeColumns.js +42 -0
  22. package/dist/cjs/src/decorators/field/sortable/helpers/sortableScopeLockKey.js +99 -0
  23. package/dist/cjs/src/decorators/field/sortable/helpers/sortableScopeLockKeys.js +72 -0
  24. package/dist/cjs/src/decorators/field/sortable/helpers/sortableSnapshot.js +101 -0
  25. package/dist/cjs/src/decorators/field/sortable/helpers/stabilizeSortableScopeLocks.js +86 -0
  26. package/dist/cjs/src/decorators/field/sortable/helpers/validPosition.js +21 -4
  27. package/dist/cjs/src/decorators/field/sortable/hooks/afterSortableDestroy.js +24 -7
  28. package/dist/cjs/src/decorators/field/sortable/hooks/afterSortableUpdate.js +10 -0
  29. package/dist/cjs/src/dream/Query.js +73 -11
  30. package/dist/cjs/src/dream/QueryDriver/Base.js +75 -2
  31. package/dist/cjs/src/dream/QueryDriver/Kysely.js +11 -4
  32. package/dist/cjs/src/dream/QueryDriver/Postgres.js +74 -0
  33. package/dist/cjs/src/dream/internal/destroyDream.js +60 -6
  34. package/dist/cjs/src/dream/internal/saveDream.js +109 -7
  35. package/dist/cjs/src/dream/internal/similarity/SimilarityBuilder.js +19 -4
  36. package/dist/cjs/src/dream/internal/softDeleteDream.js +13 -1
  37. package/dist/cjs/src/dream/internal/undestroyDream.js +56 -8
  38. package/dist/cjs/src/dream-app/index.js +21 -0
  39. package/dist/cjs/src/encrypt/assertNoEncryptedColumnWrites.js +62 -0
  40. package/dist/cjs/src/errors/SortableBatchRequiresTooManyScopeLocks.js +57 -0
  41. package/dist/cjs/src/errors/SortableRequiresAdvisoryTransactionLocks.js +26 -0
  42. package/dist/cjs/src/errors/SortableScopeDidNotStabilize.js +39 -0
  43. package/dist/cjs/src/errors/SortableScopeLockWaitTimedOut.js +50 -0
  44. package/dist/cjs/src/errors/encrypt/CannotSetEncryptedColumnInQueryUpdate.js +31 -0
  45. package/dist/cjs/src/package-exports/errors.js +3 -0
  46. package/dist/esm/src/Dream.js +63 -1
  47. package/dist/esm/src/db/errors.js +4 -0
  48. package/dist/esm/src/decorators/field/Encrypted.js +12 -0
  49. package/dist/esm/src/decorators/field/sortable/Sortable.js +43 -118
  50. package/dist/esm/src/decorators/field/sortable/helpers/acquireSortableScopeLocks.js +38 -0
  51. package/dist/esm/src/decorators/field/sortable/helpers/acquireStabilizedSortableBatchLocks.js +183 -0
  52. package/dist/esm/src/decorators/field/sortable/helpers/acquireStabilizedSortableScopeLocks.js +40 -0
  53. package/dist/esm/src/decorators/field/sortable/helpers/canonicalScopeValue.js +194 -0
  54. package/dist/esm/src/decorators/field/sortable/helpers/clearCachedSortableValues.js +18 -0
  55. package/dist/esm/src/decorators/field/sortable/helpers/decrementScopedRecordsGreaterThanPosition.js +9 -9
  56. package/dist/esm/src/decorators/field/sortable/helpers/filterQueryToInstanceScope.js +20 -0
  57. package/dist/esm/src/decorators/field/sortable/helpers/filterQueryToScopeValues.js +32 -0
  58. package/dist/esm/src/decorators/field/sortable/helpers/heldSortableScopeLockKeys.js +34 -0
  59. package/dist/esm/src/decorators/field/sortable/helpers/performSortableDestroyWork.js +21 -0
  60. package/dist/esm/src/decorators/field/sortable/helpers/performSortablePositionWork.js +36 -0
  61. package/dist/esm/src/decorators/field/sortable/helpers/prepareSortableFieldsForDestroy.js +56 -0
  62. package/dist/esm/src/decorators/field/sortable/helpers/prepareSortableFieldsForSave.js +84 -0
  63. package/dist/esm/src/decorators/field/sortable/helpers/resortAllRecords.js +186 -29
  64. package/dist/esm/src/decorators/field/sortable/helpers/setPosition.js +90 -46
  65. package/dist/esm/src/decorators/field/sortable/helpers/sortableRowCache.js +73 -0
  66. package/dist/esm/src/decorators/field/sortable/helpers/sortableScopeColumns.js +42 -0
  67. package/dist/esm/src/decorators/field/sortable/helpers/sortableScopeLockKey.js +99 -0
  68. package/dist/esm/src/decorators/field/sortable/helpers/sortableScopeLockKeys.js +72 -0
  69. package/dist/esm/src/decorators/field/sortable/helpers/sortableSnapshot.js +101 -0
  70. package/dist/esm/src/decorators/field/sortable/helpers/stabilizeSortableScopeLocks.js +86 -0
  71. package/dist/esm/src/decorators/field/sortable/helpers/validPosition.js +21 -4
  72. package/dist/esm/src/decorators/field/sortable/hooks/afterSortableDestroy.js +24 -7
  73. package/dist/esm/src/decorators/field/sortable/hooks/afterSortableUpdate.js +10 -0
  74. package/dist/esm/src/dream/Query.js +73 -11
  75. package/dist/esm/src/dream/QueryDriver/Base.js +75 -2
  76. package/dist/esm/src/dream/QueryDriver/Kysely.js +11 -4
  77. package/dist/esm/src/dream/QueryDriver/Postgres.js +74 -0
  78. package/dist/esm/src/dream/internal/destroyDream.js +60 -6
  79. package/dist/esm/src/dream/internal/saveDream.js +109 -7
  80. package/dist/esm/src/dream/internal/similarity/SimilarityBuilder.js +19 -4
  81. package/dist/esm/src/dream/internal/softDeleteDream.js +13 -1
  82. package/dist/esm/src/dream/internal/undestroyDream.js +56 -8
  83. package/dist/esm/src/dream-app/index.js +21 -0
  84. package/dist/esm/src/encrypt/assertNoEncryptedColumnWrites.js +62 -0
  85. package/dist/esm/src/errors/SortableBatchRequiresTooManyScopeLocks.js +57 -0
  86. package/dist/esm/src/errors/SortableRequiresAdvisoryTransactionLocks.js +26 -0
  87. package/dist/esm/src/errors/SortableScopeDidNotStabilize.js +39 -0
  88. package/dist/esm/src/errors/SortableScopeLockWaitTimedOut.js +50 -0
  89. package/dist/esm/src/errors/encrypt/CannotSetEncryptedColumnInQueryUpdate.js +31 -0
  90. package/dist/esm/src/package-exports/errors.js +3 -0
  91. package/dist/types/src/Dream.d.ts +56 -0
  92. package/dist/types/src/db/errors.d.ts +2 -0
  93. package/dist/types/src/decorators/field/sortable/Sortable.d.ts +33 -0
  94. package/dist/types/src/decorators/field/sortable/helpers/acquireSortableScopeLocks.d.ts +25 -0
  95. package/dist/types/src/decorators/field/sortable/helpers/acquireStabilizedSortableBatchLocks.d.ts +91 -0
  96. package/dist/types/src/decorators/field/sortable/helpers/acquireStabilizedSortableScopeLocks.d.ts +31 -0
  97. package/dist/types/src/decorators/field/sortable/helpers/canonicalScopeValue.d.ts +85 -0
  98. package/dist/types/src/decorators/field/sortable/helpers/clearCachedSortableValues.d.ts +13 -0
  99. package/dist/types/src/decorators/field/sortable/helpers/decrementScopedRecordsGreaterThanPosition.d.ts +8 -1
  100. package/dist/types/src/decorators/field/sortable/helpers/filterQueryToInstanceScope.d.ts +24 -0
  101. package/dist/types/src/decorators/field/sortable/helpers/filterQueryToScopeValues.d.ts +22 -0
  102. package/dist/types/src/decorators/field/sortable/helpers/heldSortableScopeLockKeys.d.ts +27 -0
  103. package/dist/types/src/decorators/field/sortable/helpers/performSortableDestroyWork.d.ts +14 -0
  104. package/dist/types/src/decorators/field/sortable/helpers/performSortablePositionWork.d.ts +15 -0
  105. package/dist/types/src/decorators/field/sortable/helpers/prepareSortableFieldsForDestroy.d.ts +41 -0
  106. package/dist/types/src/decorators/field/sortable/helpers/prepareSortableFieldsForSave.d.ts +35 -0
  107. package/dist/types/src/decorators/field/sortable/helpers/resortAllRecords.d.ts +32 -0
  108. package/dist/types/src/decorators/field/sortable/helpers/setPosition.d.ts +27 -11
  109. package/dist/types/src/decorators/field/sortable/helpers/sortableRowCache.d.ts +48 -0
  110. package/dist/types/src/decorators/field/sortable/helpers/sortableScopeColumns.d.ts +30 -0
  111. package/dist/types/src/decorators/field/sortable/helpers/sortableScopeLockKey.d.ts +44 -0
  112. package/dist/types/src/decorators/field/sortable/helpers/sortableScopeLockKeys.d.ts +51 -0
  113. package/dist/types/src/decorators/field/sortable/helpers/sortableSnapshot.d.ts +92 -0
  114. package/dist/types/src/decorators/field/sortable/helpers/stabilizeSortableScopeLocks.d.ts +59 -0
  115. package/dist/types/src/decorators/field/sortable/helpers/validPosition.d.ts +14 -2
  116. package/dist/types/src/decorators/field/sortable/hooks/afterSortableCreate.d.ts +1 -1
  117. package/dist/types/src/decorators/field/sortable/hooks/afterSortableDestroy.d.ts +3 -1
  118. package/dist/types/src/decorators/field/sortable/hooks/afterSortableUpdate.d.ts +1 -1
  119. package/dist/types/src/dream/Query.d.ts +47 -9
  120. package/dist/types/src/dream/QueryDriver/Base.d.ts +61 -1
  121. package/dist/types/src/dream/QueryDriver/Kysely.d.ts +6 -2
  122. package/dist/types/src/dream/QueryDriver/Postgres.d.ts +40 -0
  123. package/dist/types/src/dream/internal/softDeleteDream.d.ts +7 -1
  124. package/dist/types/src/dream-app/index.d.ts +18 -2
  125. package/dist/types/src/encrypt/assertNoEncryptedColumnWrites.d.ts +27 -0
  126. package/dist/types/src/errors/SortableBatchRequiresTooManyScopeLocks.d.ts +37 -0
  127. package/dist/types/src/errors/SortableRequiresAdvisoryTransactionLocks.d.ts +13 -0
  128. package/dist/types/src/errors/SortableScopeDidNotStabilize.d.ts +23 -0
  129. package/dist/types/src/errors/SortableScopeLockWaitTimedOut.d.ts +34 -0
  130. package/dist/types/src/errors/encrypt/CannotSetEncryptedColumnInQueryUpdate.d.ts +8 -0
  131. package/dist/types/src/package-exports/errors.d.ts +3 -0
  132. package/docs/assets/hierarchy.js +1 -1
  133. package/docs/assets/navigation.js +1 -1
  134. package/docs/assets/search.js +1 -1
  135. package/docs/classes/db.DreamMigrationHelpers.html +11 -11
  136. package/docs/classes/db.KyselyQueryDriver.html +88 -41
  137. package/docs/classes/db.PostgresQueryDriver.html +82 -42
  138. package/docs/classes/db.QueryDriverBase.html +86 -39
  139. package/docs/classes/errors.CheckConstraintViolation.html +3 -3
  140. package/docs/classes/errors.ColumnOverflow.html +3 -3
  141. package/docs/classes/errors.CreateOrFindByFailedToCreateAndFind.html +3 -3
  142. package/docs/classes/errors.DataIncompatibleWithDatabaseField.html +3 -3
  143. package/docs/classes/errors.DataTypeColumnTypeMismatch.html +3 -3
  144. package/docs/classes/errors.DecryptionError.html +2 -2
  145. package/docs/classes/errors.DecryptionParseError.html +2 -2
  146. package/docs/classes/errors.DecryptionRotationError.html +3 -3
  147. package/docs/classes/errors.GlobalNameNotSet.html +3 -3
  148. package/docs/classes/errors.InvalidCalendarDate.html +2 -2
  149. package/docs/classes/errors.InvalidClockTime.html +2 -2
  150. package/docs/classes/errors.InvalidClockTimeTz.html +2 -2
  151. package/docs/classes/errors.InvalidDateTime.html +2 -2
  152. package/docs/classes/errors.MissingSerializersDefinition.html +3 -3
  153. package/docs/classes/errors.NonLoadedAssociation.html +3 -3
  154. package/docs/classes/errors.NotNullViolation.html +3 -3
  155. package/docs/classes/errors.RecordNotFound.html +3 -3
  156. package/docs/classes/errors.SortableBatchRequiresTooManyScopeLocks.html +61 -0
  157. package/docs/classes/errors.SortableScopeDidNotStabilize.html +48 -0
  158. package/docs/classes/errors.SortableScopeLockWaitTimedOut.html +58 -0
  159. package/docs/classes/errors.ValidationError.html +3 -3
  160. package/docs/classes/index.CalendarDate.html +33 -33
  161. package/docs/classes/index.ClockTime.html +32 -32
  162. package/docs/classes/index.ClockTimeTz.html +35 -35
  163. package/docs/classes/index.DateTime.html +86 -86
  164. package/docs/classes/index.Decorators.html +19 -19
  165. package/docs/classes/index.Dream.html +151 -124
  166. package/docs/classes/index.DreamApp.html +11 -10
  167. package/docs/classes/index.DreamTransaction.html +2 -2
  168. package/docs/classes/index.Env.html +2 -2
  169. package/docs/classes/index.Query.html +124 -98
  170. package/docs/classes/system.CliFileWriter.html +4 -4
  171. package/docs/classes/system.DreamBin.html +2 -2
  172. package/docs/classes/system.DreamCLI.html +7 -7
  173. package/docs/classes/system.DreamImporter.html +2 -2
  174. package/docs/classes/system.DreamLogos.html +2 -2
  175. package/docs/classes/system.DreamSerializerBuilder.html +11 -11
  176. package/docs/classes/system.ObjectSerializerBuilder.html +8 -8
  177. package/docs/classes/system.PathHelpers.html +3 -3
  178. package/docs/classes/utils.Encrypt.html +3 -3
  179. package/docs/classes/utils.Range.html +2 -2
  180. package/docs/functions/db.closeAllDbConnections.html +1 -1
  181. package/docs/functions/db.dreamDbConnections.html +1 -1
  182. package/docs/functions/db.untypedDb.html +1 -1
  183. package/docs/functions/db.validateColumn.html +1 -1
  184. package/docs/functions/db.validateTable.html +1 -1
  185. package/docs/functions/errors.pgErrorType.html +1 -1
  186. package/docs/functions/index.DreamSerializer.html +1 -1
  187. package/docs/functions/index.ObjectSerializer.html +1 -1
  188. package/docs/functions/index.ReplicaSafe.html +1 -1
  189. package/docs/functions/index.STI.html +1 -1
  190. package/docs/functions/index.SoftDelete.html +1 -1
  191. package/docs/functions/utils.camelize.html +1 -1
  192. package/docs/functions/utils.capitalize.html +1 -1
  193. package/docs/functions/utils.cloneDeepSafe.html +1 -1
  194. package/docs/functions/utils.compact.html +1 -1
  195. package/docs/functions/utils.groupBy.html +1 -1
  196. package/docs/functions/utils.hyphenize.html +1 -1
  197. package/docs/functions/utils.intersection.html +1 -1
  198. package/docs/functions/utils.isEmpty.html +1 -1
  199. package/docs/functions/utils.normalizeUnicode.html +1 -1
  200. package/docs/functions/utils.pascalize.html +1 -1
  201. package/docs/functions/utils.percent.html +1 -1
  202. package/docs/functions/utils.range.html +1 -1
  203. package/docs/functions/utils.round.html +1 -1
  204. package/docs/functions/utils.sanitizeString.html +1 -1
  205. package/docs/functions/utils.snakeify.html +1 -1
  206. package/docs/functions/utils.sort.html +2 -2
  207. package/docs/functions/utils.sortBy.html +1 -1
  208. package/docs/functions/utils.sortObjectByKey.html +1 -1
  209. package/docs/functions/utils.sortObjectByValue.html +1 -1
  210. package/docs/functions/utils.uncapitalize.html +1 -1
  211. package/docs/functions/utils.uniq.html +1 -1
  212. package/docs/hierarchy.html +1 -1
  213. package/docs/interfaces/openapi.OpenapiDescription.html +2 -2
  214. package/docs/interfaces/openapi.OpenapiSchemaProperties.html +1 -1
  215. package/docs/interfaces/openapi.OpenapiSchemaPropertiesShorthand.html +1 -1
  216. package/docs/interfaces/openapi.OpenapiTypeFieldObject.html +1 -1
  217. package/docs/interfaces/types.BelongsToStatement.html +2 -2
  218. package/docs/interfaces/types.DecoratorContext.html +2 -2
  219. package/docs/interfaces/types.DreamAppInitOptions.html +2 -2
  220. package/docs/interfaces/types.DreamAppOpts.html +2 -2
  221. package/docs/interfaces/types.DreamDbConfig.html +5 -5
  222. package/docs/interfaces/types.DurationObject.html +2 -2
  223. package/docs/interfaces/types.EncryptOptions.html +2 -2
  224. package/docs/interfaces/types.InternalAnyTypedSerializerRendersMany.html +2 -2
  225. package/docs/interfaces/types.InternalAnyTypedSerializerRendersOne.html +2 -2
  226. package/docs/interfaces/types.SerializerRendererOpts.html +2 -2
  227. package/docs/modules/errors.html +1 -1
  228. package/docs/types/openapi.CommonOpenapiSchemaObjectFields.html +1 -1
  229. package/docs/types/openapi.OpenapiAllTypes.html +1 -1
  230. package/docs/types/openapi.OpenapiFormats.html +1 -1
  231. package/docs/types/openapi.OpenapiNumberFormats.html +1 -1
  232. package/docs/types/openapi.OpenapiPrimitiveBaseTypes.html +1 -1
  233. package/docs/types/openapi.OpenapiPrimitiveTypes.html +1 -1
  234. package/docs/types/openapi.OpenapiSchemaArray.html +1 -1
  235. package/docs/types/openapi.OpenapiSchemaArrayShorthand.html +1 -1
  236. package/docs/types/openapi.OpenapiSchemaBase.html +1 -1
  237. package/docs/types/openapi.OpenapiSchemaBody.html +1 -1
  238. package/docs/types/openapi.OpenapiSchemaBodyShorthand.html +1 -1
  239. package/docs/types/openapi.OpenapiSchemaCommonFields.html +1 -1
  240. package/docs/types/openapi.OpenapiSchemaExpressionAllOf.html +2 -2
  241. package/docs/types/openapi.OpenapiSchemaExpressionAnyOf.html +2 -2
  242. package/docs/types/openapi.OpenapiSchemaExpressionOneOf.html +2 -2
  243. package/docs/types/openapi.OpenapiSchemaExpressionRef.html +2 -2
  244. package/docs/types/openapi.OpenapiSchemaExpressionRefSchemaShorthand.html +2 -2
  245. package/docs/types/openapi.OpenapiSchemaInteger.html +1 -1
  246. package/docs/types/openapi.OpenapiSchemaNull.html +2 -2
  247. package/docs/types/openapi.OpenapiSchemaNumber.html +1 -1
  248. package/docs/types/openapi.OpenapiSchemaObject.html +1 -1
  249. package/docs/types/openapi.OpenapiSchemaObjectAllOf.html +1 -1
  250. package/docs/types/openapi.OpenapiSchemaObjectAllOfShorthand.html +1 -1
  251. package/docs/types/openapi.OpenapiSchemaObjectAnyOf.html +1 -1
  252. package/docs/types/openapi.OpenapiSchemaObjectAnyOfShorthand.html +1 -1
  253. package/docs/types/openapi.OpenapiSchemaObjectBase.html +1 -1
  254. package/docs/types/openapi.OpenapiSchemaObjectBaseShorthand.html +1 -1
  255. package/docs/types/openapi.OpenapiSchemaObjectOneOf.html +1 -1
  256. package/docs/types/openapi.OpenapiSchemaObjectOneOfShorthand.html +1 -1
  257. package/docs/types/openapi.OpenapiSchemaObjectShorthand.html +1 -1
  258. package/docs/types/openapi.OpenapiSchemaPrimitiveGeneric.html +1 -1
  259. package/docs/types/openapi.OpenapiSchemaShorthandExpressionAllOf.html +2 -2
  260. package/docs/types/openapi.OpenapiSchemaShorthandExpressionAnyOf.html +2 -2
  261. package/docs/types/openapi.OpenapiSchemaShorthandExpressionOneOf.html +2 -2
  262. package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializableRef.html +2 -2
  263. package/docs/types/openapi.OpenapiSchemaShorthandExpressionSerializerRef.html +2 -2
  264. package/docs/types/openapi.OpenapiSchemaShorthandPrimitiveGeneric.html +1 -1
  265. package/docs/types/openapi.OpenapiSchemaString.html +1 -1
  266. package/docs/types/openapi.OpenapiShorthandAllTypes.html +1 -1
  267. package/docs/types/openapi.OpenapiShorthandPrimitiveBaseTypes.html +1 -1
  268. package/docs/types/openapi.OpenapiShorthandPrimitiveTypes.html +1 -1
  269. package/docs/types/openapi.OpenapiTypeField.html +1 -1
  270. package/docs/types/system.DreamAppAllowedPackageManagersEnum.html +1 -1
  271. package/docs/types/types.CalendarDateDurationUnit.html +1 -1
  272. package/docs/types/types.CalendarDateObject.html +1 -1
  273. package/docs/types/types.Camelized.html +1 -1
  274. package/docs/types/types.ClockTimeObject.html +1 -1
  275. package/docs/types/types.DbConnectionType.html +1 -1
  276. package/docs/types/types.DbTypes.html +1 -1
  277. package/docs/types/types.DreamAssociationMetadata.html +1 -1
  278. package/docs/types/types.DreamAttributes.html +1 -1
  279. package/docs/types/types.DreamClassAssociationAndStatement.html +1 -1
  280. package/docs/types/types.DreamClassColumn.html +1 -1
  281. package/docs/types/types.DreamColumn.html +1 -1
  282. package/docs/types/types.DreamColumnNames.html +1 -1
  283. package/docs/types/types.DreamLogLevel.html +1 -1
  284. package/docs/types/types.DreamLogger.html +2 -2
  285. package/docs/types/types.DreamModelSerializerType.html +1 -1
  286. package/docs/types/types.DreamOrViewModelClassSerializerKey.html +1 -1
  287. package/docs/types/types.DreamOrViewModelSerializerKey.html +1 -1
  288. package/docs/types/types.DreamParamSafeAttributes.html +1 -1
  289. package/docs/types/types.DreamParamSafeColumnNames.html +1 -1
  290. package/docs/types/types.DreamSerializable.html +1 -1
  291. package/docs/types/types.DreamSerializableArray.html +1 -1
  292. package/docs/types/types.DreamSerializerKey.html +1 -1
  293. package/docs/types/types.DreamSerializers.html +1 -1
  294. package/docs/types/types.DreamVirtualColumns.html +1 -1
  295. package/docs/types/types.DurationUnit.html +1 -1
  296. package/docs/types/types.EncryptAlgorithm.html +1 -1
  297. package/docs/types/types.HasManyStatement.html +1 -1
  298. package/docs/types/types.HasOneStatement.html +1 -1
  299. package/docs/types/types.Hyphenized.html +1 -1
  300. package/docs/types/types.Pascalized.html +1 -1
  301. package/docs/types/types.PrimaryKeyType.html +1 -1
  302. package/docs/types/types.RoundingPrecision.html +1 -1
  303. package/docs/types/types.SerializerCasing.html +1 -1
  304. package/docs/types/types.SimpleObjectSerializerType.html +1 -1
  305. package/docs/types/types.Snakeified.html +1 -1
  306. package/docs/types/types.StrictInterface.html +1 -1
  307. package/docs/types/types.UpdateableAssociationProperties.html +1 -1
  308. package/docs/types/types.UpdateableProperties.html +1 -1
  309. package/docs/types/types.ValidationType.html +1 -1
  310. package/docs/types/types.ViewModel.html +2 -2
  311. package/docs/types/types.ViewModelClass.html +1 -1
  312. package/docs/types/types.WeekdayName.html +1 -1
  313. package/docs/types/types.WhereStatementForDream.html +1 -1
  314. package/docs/types/types.WhereStatementForDreamClass.html +1 -1
  315. package/docs/variables/index.DreamConst.html +1 -1
  316. package/docs/variables/index.ops.html +1 -1
  317. package/docs/variables/openapi.openapiPrimitiveTypes.html +1 -1
  318. package/docs/variables/openapi.openapiShorthandPrimitiveTypes.html +1 -1
  319. package/docs/variables/system.DreamAppAllowedPackageManagersEnumValues.html +1 -1
  320. package/docs/variables/system.primaryKeyTypes.html +1 -1
  321. package/package.json +1 -1
  322. package/dist/cjs/src/decorators/field/sortable/helpers/applySortableScopeToQuery.js +0 -13
  323. package/dist/cjs/src/decorators/field/sortable/helpers/sortableQueryExcludingDream.js +0 -7
  324. package/dist/cjs/src/decorators/field/sortable/hooks/beforeSortableSave.js +0 -41
  325. package/dist/esm/src/decorators/field/sortable/helpers/applySortableScopeToQuery.js +0 -13
  326. package/dist/esm/src/decorators/field/sortable/helpers/sortableQueryExcludingDream.js +0 -7
  327. package/dist/esm/src/decorators/field/sortable/hooks/beforeSortableSave.js +0 -41
  328. package/dist/types/src/decorators/field/sortable/helpers/applySortableScopeToQuery.d.ts +0 -12
  329. package/dist/types/src/decorators/field/sortable/helpers/sortableQueryExcludingDream.d.ts +0 -12
  330. package/dist/types/src/decorators/field/sortable/hooks/beforeSortableSave.d.ts +0 -12
@@ -0,0 +1,85 @@
1
+ import Dream from '../../../../Dream.js';
2
+ /**
3
+ * @internal
4
+ *
5
+ * The canonical text form of one sort-scope value — the thing an advisory lock
6
+ * key and a resort group identity are actually built from.
7
+ *
8
+ * Two writers of the same physical sort scope have to derive the same key, and
9
+ * they do not always hold the value in the same JavaScript shape. A save that
10
+ * has not been written yet holds the *pending* value the caller supplied
11
+ * (`'1.00'`, an uppercase UUID, an object whose keys are in source order),
12
+ * while a snapshot read, a create's post-INSERT read and `resort`'s table read
13
+ * hold the value Postgres *hydrated* (`1`, a lowercase UUID, an object whose
14
+ * keys are in jsonb's own order). Postgres considers those pairs one value;
15
+ * `typeof`-only normalization considers them two, and two keys do not exclude
16
+ * each other.
17
+ *
18
+ * So canonicalization is keyed on the column's runtime `dbType`, and the
19
+ * canonical form of each type is **the form the hydrated value already takes**.
20
+ * That anchoring is what makes this safe to ship without a migration or a
21
+ * coordinated deploy: no key derived from a database-hydrated value moves, and
22
+ * the pending-side keys that do move are exactly the ones that disagree with
23
+ * every hydrated-path writer of the same scope today.
24
+ *
25
+ * The classes handled, and what the hydrated value looks like:
26
+ *
27
+ * - `uuid` — Postgres renders UUIDs lowercase, so the canonical form is
28
+ * lowercase.
29
+ * - `numeric` / `real` / `double precision` — hydrated through
30
+ * `parsePostgresDecimal`, i.e. `parseFloat`, so `'1.00'` and `1` both
31
+ * canonicalize to `'1'`.
32
+ * - `jsonb` — hydrated by `JSON.parse` of jsonb's own output, whose object keys
33
+ * are ordered by key length and then bytewise. Objects are re-emitted in that
34
+ * order, recursively, so property insertion order stops mattering.
35
+ * - `boolean` — hydrated as a JavaScript boolean; Postgres's own input literals
36
+ * (`'t'`, `'yes'`, `'0'`, …) canonicalize to `'true'`/`'false'`.
37
+ * - `date` and the four timestamp/time types — hydrated as `CalendarDate`,
38
+ * `DateTime`, `ClockTime` or `ClockTimeTz`, whose JSON form is the quoted ISO
39
+ * string. Strings are quoted the same way so a pending `'2026-02-07'` and a
40
+ * hydrated `CalendarDate` agree.
41
+ *
42
+ * Everything else — `bigint` and `character varying`, which is to say the
43
+ * foreign keys and text columns nearly every sort scope is made of — is left on
44
+ * the untyped normalization below, unchanged.
45
+ *
46
+ * Two residuals are known and accepted rather than fixed:
47
+ *
48
+ * - **`citext`**: Postgres stores the case a row was written with while
49
+ * comparing case-insensitively, so two rows of one physical scope hydrate to
50
+ * values that differ in case and split the key on their own. Lowercasing
51
+ * would fix the split but would *move* hydrated keys, which is the one thing
52
+ * this design refuses to do.
53
+ * - **Temporal values that agree on the instant but not on the text**: a zone
54
+ * offset or a fractional-second precision that differs from the hydrated
55
+ * rendering still yields a different key. Only the string-vs-object quoting
56
+ * mismatch is canonicalized.
57
+ *
58
+ * Both are over-serialization or a missed exclusion between two *pending*-side
59
+ * writers, never a corrupt position under a key two writers do share.
60
+ *
61
+ * @param dream - the record whose scope column is being canonicalized
62
+ * @param column - the physical database column
63
+ * @param value - the pending or hydrated value held for that column
64
+ * @returns the canonical text form, or `null` for an absent value
65
+ */
66
+ export default function canonicalScopeValue(dream: Dream, column: string, value: unknown): string | null;
67
+ /**
68
+ * @internal
69
+ *
70
+ * The type-blind fallback, and the shape every unrecognized `dbType` keeps:
71
+ * the same foreign key can arrive as a string or a number depending on the path
72
+ * that loaded it, so values are rendered as text and null is kept distinct from
73
+ * every string, including the empty one.
74
+ */
75
+ export declare function untypedScopeValue(value: unknown): string | null;
76
+ /**
77
+ * @internal
78
+ *
79
+ * Postgres's own boolean input literals, lower-cased and trimmed, which a
80
+ * pending value may hold while the hydrated value is a JavaScript boolean.
81
+ * Exported so the spec drives its cases from the sets themselves rather than
82
+ * from a hand-copied list that can silently drift out of step with them.
83
+ */
84
+ export declare const BOOLEAN_TRUE_LITERALS: ReadonlySet<string>;
85
+ export declare const BOOLEAN_FALSE_LITERALS: ReadonlySet<string>;
@@ -1,2 +1,15 @@
1
1
  import Dream from '../../../../Dream.js';
2
+ import { SortableFieldConfig } from '../Sortable.js';
2
3
  export default function clearCachedSortableValues(dream: Dream, positionField: string): void;
4
+ /**
5
+ * @internal
6
+ *
7
+ * Discards both halves of what a save's sortable phase stashes on the
8
+ * instance: the cached values the position work reads, and the snapshot of the
9
+ * row it would have computed its shift against. The position work clears them
10
+ * itself as it consumes them, so this is for the paths where it does not run —
11
+ * the row was already gone when the snapshot read found it, or the save's
12
+ * transaction rolled back — leaving a later save of the same instance to read
13
+ * the row for itself rather than inherit this save's reading of it.
14
+ */
15
+ export declare function clearSortableSaveState(dream: Dream, configs: SortableFieldConfig[]): void;
@@ -1,8 +1,15 @@
1
1
  import Dream from '../../../../Dream.js';
2
2
  import Query from '../../../../dream/Query.js';
3
- export default function decrementPositionForScopedRecordsGreaterThanPosition(position: number, { dream, positionField, query, scope, }: {
3
+ import { SortableSnapshot } from './sortableSnapshot.js';
4
+ export default function decrementPositionForScopedRecordsGreaterThanPosition(position: number, { dream, positionField, query, scope, snapshot, }: {
4
5
  dream: Dream;
5
6
  positionField: string;
6
7
  query: Query<Dream>;
7
8
  scope: string | string[] | undefined;
9
+ /**
10
+ * The destroyed row's real scope values, read before the delete. The scope
11
+ * being compacted is the one the row physically occupied, which is not
12
+ * necessarily the one the instance was loaded from.
13
+ */
14
+ snapshot?: SortableSnapshot | undefined;
8
15
  }): Promise<void>;
@@ -0,0 +1,24 @@
1
+ import Dream from '../../../../Dream.js';
2
+ import Query from '../../../../dream/Query.js';
3
+ /**
4
+ * @internal
5
+ *
6
+ * Narrows a Dream `Query` to one sort scope, **reading the scope values off the
7
+ * in-memory instance**. That is only the scope the row physically occupies when
8
+ * the instance is known to agree with the row — inside a transaction that has
9
+ * just written those values, or on a record read under the scope lock.
10
+ *
11
+ * Where the row may have been moved by another writer, the caller wants
12
+ * `filterQueryToScopeValues` instead, which takes each column's value from the
13
+ * caller (the snapshot read under the lock) rather than from the instance.
14
+ */
15
+ export default function filterQueryToInstanceScope(query: Query<Dream>, dream: Dream, scope?: string | string[]): Query<Dream, Readonly<{
16
+ joinedAssociations: Readonly<[]>;
17
+ rootTableName: string;
18
+ rootTableAlias: string;
19
+ allowPreload: true;
20
+ allowLeftJoinPreload: true;
21
+ allowLimit: true;
22
+ allowOffset: true;
23
+ allowPaginate: true;
24
+ }>>;
@@ -0,0 +1,22 @@
1
+ import { SelectQueryBuilder, UpdateQueryBuilder } from 'kysely';
2
+ import Dream from '../../../../Dream.js';
3
+ /**
4
+ * @internal
5
+ *
6
+ * Narrows a kysely query to one sort scope, taking each scope column's value
7
+ * **from the caller** rather than from the in-memory instance — the snapshot
8
+ * read under the scope lock on the paths that compact a scope a record is
9
+ * leaving, which is not necessarily the scope the instance was loaded from.
10
+ *
11
+ * This is also the one place the null branch lives: a null scope value has to
12
+ * be matched with `is null`, since `column = NULL` is never true and the filter
13
+ * would silently match nothing at all in a null-valued sort scope.
14
+ *
15
+ * The instance-reading sibling is `filterQueryToInstanceScope`.
16
+ *
17
+ * @param dream - the record whose class resolves the scope members to columns
18
+ * @param kyselyQuery - the query to narrow
19
+ * @param whereValueCB - the value to match each scope column against
20
+ * @param scope - the sortable field's scope
21
+ */
22
+ export default function filterQueryToScopeValues<QB extends UpdateQueryBuilder<any, any, any, any> | SelectQueryBuilder<any, any, any>>(dream: Dream, kyselyQuery: QB, whereValueCB: (column: string) => any, scope?: string | string[]): QB;
@@ -0,0 +1,27 @@
1
+ import DreamTransaction from '../../../../dream/DreamTransaction.js';
2
+ /**
3
+ * @internal
4
+ *
5
+ * The sortable scope-lock keys this transaction already holds.
6
+ *
7
+ * Advisory transaction locks are released only when the transaction ends, so a
8
+ * key taken once is held for the rest of it: every later acquisition of that
9
+ * key is a statement whose entire effect is to observe that the transaction
10
+ * already has what it is asking for. Tracking them turns those statements into
11
+ * nothing at all — the per-field acquisition inside the position write, and
12
+ * every per-record acquisition inside a locked batch whose preflight already
13
+ * took the batch's whole key set.
14
+ *
15
+ * Being the transaction's whole ledger is also what lets the locked-batch
16
+ * preflight count its bound cumulatively rather than per batch: how many scope
17
+ * locks one more batch would leave the transaction holding is this set's size
18
+ * plus whatever of the batch's keys is not already in it.
19
+ *
20
+ * Keyed by the transaction object rather than by the connection, which is what
21
+ * makes it correct rather than merely fast: a nested transaction gets its own
22
+ * `DreamTransaction` and therefore its own set, so keys taken inside a
23
+ * subtransaction that rolls back — releasing its locks with it — are never
24
+ * remembered as held by the transaction that outlives it. The entry is
25
+ * discarded with the transaction object.
26
+ */
27
+ export default function heldSortableScopeLockKeys(txn: DreamTransaction<any>): Set<bigint>;
@@ -0,0 +1,14 @@
1
+ import Dream from '../../../../Dream.js';
2
+ import DreamTransaction from '../../../../dream/DreamTransaction.js';
3
+ /**
4
+ * @internal
5
+ *
6
+ * The compaction of a sortable destroy: closes the vacancy each sortable
7
+ * field's sort scope is left with, computed from the snapshot the preparation
8
+ * phase (`prepareSortableFieldsForDestroy`) read before the delete. Called
9
+ * directly from `destroyDream` after the delete and before any user
10
+ * `afterDestroy` hook — never registered as a hook among them — so every
11
+ * after-destroy hook observes the compacted scope regardless of where it was
12
+ * declared, exactly as every after-save hook observes the computed position.
13
+ */
14
+ export default function performSortableDestroyWork(dream: Dream, txn: DreamTransaction<any>): Promise<void>;
@@ -0,0 +1,15 @@
1
+ import Dream from '../../../../Dream.js';
2
+ import DreamTransaction from '../../../../dream/DreamTransaction.js';
3
+ import { SortableFieldConfig } from '../Sortable.js';
4
+ /**
5
+ * @internal
6
+ *
7
+ * The position work of a sortable save: computes each sortable field's real
8
+ * position under the scope lock and writes it. Called directly from
9
+ * `saveDream` after the driver write — never registered as an after-hook — so
10
+ * no user hook code can interleave with it while the scope lock is held, and
11
+ * on a self-opened save it is the last work before COMMIT releases the lock.
12
+ */
13
+ export default function performSortablePositionWork(dream: Dream, txn: DreamTransaction<any>, sortableFieldConfigs: SortableFieldConfig[], { alreadyPersisted }: {
14
+ alreadyPersisted: boolean;
15
+ }): Promise<void>;
@@ -0,0 +1,41 @@
1
+ import Dream from '../../../../Dream.js';
2
+ import DreamTransaction from '../../../../dream/DreamTransaction.js';
3
+ /**
4
+ * @internal
5
+ *
6
+ * The sortable preparation phase of a destroy. Called from `destroyDream` after
7
+ * every user `beforeDestroy` hook has run and before the delete — a phase, not
8
+ * a hook among them — so the operation's whole advisory key set, across every
9
+ * sortable field, is taken in one sorted stabilized acquisition, with one
10
+ * snapshot SELECT covering all fields. Per-field acquisition would take
11
+ * multi-field keys in declaration order, which deadlocks against the paths
12
+ * that acquire sorted.
13
+ *
14
+ * Pre-delete is the only seat available for the snapshot read: on a hard
15
+ * destroy the row is gone afterwards, and a soft destroy nulls the position
16
+ * columns in the same UPDATE as `deletedAt`. The lock is taken around the read
17
+ * so the snapshot cannot be invalidated between the read and the compaction;
18
+ * it is transaction-scoped, and `destroyDream` opens a transaction that spans
19
+ * the delete and the after-destroy hooks, so one acquisition covers both.
20
+ *
21
+ * The per-field compactions (`performSortableDestroyWork`) consume the cached
22
+ * snapshots.
23
+ *
24
+ * @returns false when the snapshot read found no row — this destroy has nothing
25
+ * to vacate, and compacting from the instance's remembered position would
26
+ * shift a scope some other writer has already closed. The delete's own
27
+ * affected-row count is the stronger signal (a writer outside the sortable
28
+ * path can remove the row after this read), so the caller checks both.
29
+ */
30
+ export default function prepareSortableFieldsForDestroy(dream: Dream, txn: DreamTransaction<any>): Promise<boolean>;
31
+ /**
32
+ * @internal
33
+ *
34
+ * Discards what the preparation phase stashed on the instance. The per-field
35
+ * compaction clears its own snapshot as it consumes it, so this
36
+ * exists for the path where that compaction never runs: a destroy that removed
37
+ * nothing leaves the snapshot behind, and a later save or destroy of the same
38
+ * instance would compute its shift from a reading of a row this operation
39
+ * already found gone.
40
+ */
41
+ export declare function clearSortableFieldsForDestroy(dream: Dream): void;
@@ -0,0 +1,35 @@
1
+ import Dream from '../../../../Dream.js';
2
+ import { SortableFieldConfig } from '../Sortable.js';
3
+ export interface SortableCache {
4
+ changingScope: boolean;
5
+ position: number | undefined;
6
+ previousPosition: number | undefined;
7
+ wasNewRecord: boolean;
8
+ }
9
+ /**
10
+ * @internal
11
+ *
12
+ * The sortable preparation phase of a save. Called from `saveDream` after every
13
+ * consumer before-hook has run — a phase, not a hook among them — so the
14
+ * decision is made from the final state of the instance: a position or scope
15
+ * change introduced by a `beforeSave` hook registered after Sortable's gets the
16
+ * same handling as one made before `save` was called, and a cache is never
17
+ * carried over from a state an intervening hook has made stale.
18
+ *
19
+ * For each sortable field this caches the values the position work needs and
20
+ * applies the position sentinel, then returns the fields whose position work
21
+ * this save will perform — the fields that make the save need a transaction of
22
+ * its own, so that the write and the position write that follows it commit
23
+ * together under one scope lock.
24
+ *
25
+ * - every create on a model with sortable fields performs position work;
26
+ * - an update performs it only when the save changes the position or one of the
27
+ * sortable scope columns.
28
+ *
29
+ * A save that skips hooks performs no position work at all, so it needs no
30
+ * transaction.
31
+ */
32
+ export default function prepareSortableFieldsForSave(dream: Dream, { alreadyPersisted, skipHooks }: {
33
+ alreadyPersisted: boolean;
34
+ skipHooks: boolean;
35
+ }): SortableFieldConfig[];
@@ -1,2 +1,34 @@
1
1
  import Dream from '../../../../Dream.js';
2
+ /**
3
+ * @internal
4
+ *
5
+ * Renumbers every sort scope of a model so that each one runs 1..n with no gaps.
6
+ *
7
+ * Four things make this safe to run against a live table:
8
+ *
9
+ * - **A driver that cannot take the scope lock fails before the table is
10
+ * read**, rather than succeeding for whichever scopes happen to be contiguous
11
+ * and throwing on the first one that is not.
12
+ * - **The STI scope is stripped**, exactly as every sortable hook strips it. An
13
+ * STI hierarchy shares one position space, so renumbering one child's rows in
14
+ * isolation would hand them positions its siblings already hold.
15
+ * - **Groups are identified structurally**, by the scope columns' `[column,
16
+ * value]` tuple rather than by joining the values into one string. Joining
17
+ * merges scopes whose values differ only in where a delimiter falls, and
18
+ * merges a null member with an empty-string one; a merged group is two
19
+ * physical sort scopes renumbered as though they were one, and no single lock
20
+ * key covers it.
21
+ * - **Every discovered scope is renumbered under its own scope lock, from a
22
+ * read taken inside that lock.** The unlocked pass below only discovers
23
+ * *which* sort scopes exist; it decides nothing about their contents, because
24
+ * a concurrent create, destroy or raw update between the two reads is
25
+ * precisely the case this exists to repair. Whether a scope needs renumbering
26
+ * at all is decided under the lock.
27
+ *
28
+ * Each scope's transaction is this function's own: `resort` cannot join a
29
+ * transaction the caller owns, and must not be called from inside one. It would
30
+ * wait on a connection of its own for a scope lock the caller's transaction may
31
+ * already hold — a wait no deadlock detector can see, which ends in
32
+ * `SortableScopeLockWaitTimedOut` rather than in progress.
33
+ */
2
34
  export default function resortAllRecords(dreamClass: typeof Dream, positionField: string, scope?: string | string[]): Promise<void>;
@@ -1,20 +1,36 @@
1
- import { SelectQueryBuilder, UpdateQueryBuilder } from 'kysely';
2
1
  import Dream from '../../../../Dream.js';
3
2
  import DreamTransaction from '../../../../dream/DreamTransaction.js';
4
3
  import Query from '../../../../dream/Query.js';
5
- import PostgresQueryDriver from '../../../../dream/QueryDriver/Postgres.js';
6
- import { SortableCache } from '../hooks/beforeSortableSave.js';
7
- interface SortableCacheWithOptionalTransaction extends SortableCache {
4
+ import { SortableCache } from './prepareSortableFieldsForSave.js';
5
+ import { SortableSnapshot } from './sortableSnapshot.js';
6
+ /**
7
+ * @internal
8
+ *
9
+ * Everything one sortable field's position write needs. The transaction is
10
+ * required: every path into `setPosition` runs from
11
+ * `performSortablePositionWork`, which is called by `saveDream` inside the
12
+ * transaction that holds the scope lock, and a position write that opened a
13
+ * transaction of its own would block on a key its own caller holds.
14
+ */
15
+ export interface SortablePositionWrite extends SortableCache {
8
16
  dream: Dream;
9
17
  positionField: string;
10
18
  query: Query<Dream>;
11
19
  scope: string | string[] | undefined;
12
- txn?: DreamTransaction<any> | undefined;
13
- }
14
- export interface SortableCacheWithRequiredTransaction extends SortableCacheWithOptionalTransaction {
15
20
  txn: DreamTransaction<any>;
21
+ /**
22
+ * The record's physical position and sort scope values, read from the row
23
+ * under the scope lock before the driver write. Present on the update path;
24
+ * absent on create, which has no prior row.
25
+ */
26
+ snapshot?: SortableSnapshot | undefined;
27
+ /**
28
+ * The position the record holds in the scope its position is being computed
29
+ * over, where the driver write has replaced it on the row with the position
30
+ * sentinel. Set only for a save that lands in the scope the row already
31
+ * occupies; on every other path the scope's own rows carry their real
32
+ * positions, or the record is joining the scope rather than already in it.
33
+ */
34
+ positionUnderSentinel?: number | undefined;
16
35
  }
17
- export default function setPosition(obj: SortableCacheWithOptionalTransaction): Promise<void>;
18
- export declare function applySortableScopesToQuery<QB extends UpdateQueryBuilder<any, any, any, any> | SelectQueryBuilder<any, any, any>>(dream: Dream, kyselyQuery: QB, whereValueCB: (column: string) => any, scope?: string | string[]): QB;
19
- export declare function getPostgresQueryDriver(connectionName: string): typeof PostgresQueryDriver;
20
- export {};
36
+ export default function setPosition(obj: SortablePositionWrite): Promise<void>;
@@ -0,0 +1,48 @@
1
+ import DreamTransaction from '../../../../dream/DreamTransaction.js';
2
+ /**
3
+ * @internal
4
+ *
5
+ * Stashes rows a locked batch's preflight read under the batch's scope locks,
6
+ * so that the per-record position work that follows does not read them a second
7
+ * time. The preflight reads every candidate's position and sort scope columns
8
+ * to derive the key set; each record's own snapshot read then asks the same
9
+ * question of the same row, in the same transaction, under the same locks.
10
+ *
11
+ * Called once per preflight, with the rows of the pass that converged: an
12
+ * earlier pass read before some of the locks were held, and a preflight that
13
+ * raised holds no lock the rest of the transaction can rely on. The rows are
14
+ * consumed one at a time and the whole entry is dropped by the first position
15
+ * write of the batch, since a compaction moves rows this holds stale positions
16
+ * for — so what it saves is the snapshot reads of the records walked before
17
+ * that first write.
18
+ *
19
+ * @param txn - the batch's transaction
20
+ * @param table - the table the rows came from
21
+ * @param primaryKey - the column the rows are keyed by
22
+ * @param rows - the rows read, carrying at least the position and scope columns
23
+ */
24
+ export declare function cacheSortableRowsReadUnderLock(txn: DreamTransaction<any>, table: string, primaryKey: string, rows: Record<string, unknown>[]): void;
25
+ /**
26
+ * @internal
27
+ *
28
+ * The cached row for one record, removed from the cache as it is handed over.
29
+ *
30
+ * Consuming is destructive because the consumer is a position-mutating
31
+ * operation: it is about to compact or renumber the scope the row sits in, and
32
+ * a second read of the same cached row would see the position the row had
33
+ * before that. {@link invalidateSortableRowCache} covers the same hazard for
34
+ * the *other* records a compaction moves.
35
+ */
36
+ export declare function takeCachedSortableRow(txn: DreamTransaction<any>, table: string, primaryKeyValue: unknown): Record<string, unknown> | undefined;
37
+ /**
38
+ * @internal
39
+ *
40
+ * Discards everything cached for this transaction. Called for two reasons: a
41
+ * position write just moved rows the cache cannot identify — a compaction
42
+ * shifts every row in one sort scope above a position, and the cache holds no
43
+ * index by scope — and the batch the rows were read for has finished, after
44
+ * which they describe nothing the rest of a caller-owned transaction should
45
+ * trust. The records still to be walked read their own rows again, which is
46
+ * what they did before the cache existed.
47
+ */
48
+ export declare function invalidateSortableRowCache(txn: DreamTransaction<any>): void;
@@ -0,0 +1,30 @@
1
+ import Dream from '../../../../Dream.js';
2
+ /**
3
+ * @internal
4
+ *
5
+ * The scope members of a sortable field paired with the database columns they
6
+ * resolve to. A member names either the column itself or the BelongsTo
7
+ * association whose foreign key backs it, and a caller matching incoming
8
+ * attributes needs both spellings; a member that resolves to no column is
9
+ * dropped.
10
+ *
11
+ * Every sortable path resolves its scope columns through this one function, so
12
+ * that a lock key, a snapshot read, a group identity and a scope filter can
13
+ * never disagree about which columns a sort scope is made of.
14
+ */
15
+ export declare function sortableScopeColumnPairs(dream: Dream, scope: string | string[] | undefined): [string, string][];
16
+ /**
17
+ * @internal
18
+ *
19
+ * The database columns a sortable field's scope resolves to.
20
+ */
21
+ export default function sortableScopeColumns(dream: Dream, scope: string | string[] | undefined): string[];
22
+ /**
23
+ * @internal
24
+ *
25
+ * The sort scope as `[column, value]` pairs — the shape a lock key is derived
26
+ * from and a group is identified by. The value for each column comes from the
27
+ * caller, which decides whether it is reading the in-memory instance or a
28
+ * snapshot of the row.
29
+ */
30
+ export declare function sortableScopeValues(dream: Dream, scope: string | string[] | undefined, valueForColumn: (column: string) => unknown): [string, unknown][];
@@ -0,0 +1,44 @@
1
+ import Dream from '../../../../Dream.js';
2
+ /**
3
+ * @internal
4
+ *
5
+ * Derives the advisory lock key that makes one sort scope's position
6
+ * computation exclusive. Every position-mutating path derives it the same way,
7
+ * since two paths that disagree about the key do not exclude each other.
8
+ *
9
+ * The key covers:
10
+ *
11
+ * - the **physical database name**, because Postgres advisory locks are scoped
12
+ * to the cluster rather than to a database. Without it, two unrelated
13
+ * databases in one cluster — including this repo's own parallel test
14
+ * databases — would contend on the same key, and that contention shows up
15
+ * only as writers of unrelated scopes queueing behind each other.
16
+ * - the table and the position field, since a model can declare several
17
+ * sortable fields, each with its own position space.
18
+ * - the scope column values, which are what a "sort scope" actually is.
19
+ *
20
+ * Values are encoded structurally rather than joined into a string, so a null
21
+ * member is distinct from an empty string and no combination of delimiters in
22
+ * one member can be mistaken for a different tuple. They are also canonicalized
23
+ * against the column's database type (`canonicalScopeValue`), so a writer
24
+ * holding a pending JavaScript value and a writer holding the value Postgres
25
+ * hydrated derive one key rather than two.
26
+ *
27
+ * **Scope values are assumed non-adversarial.** The hash is FNV-1a, which is
28
+ * unkeyed: anyone who can choose a scope column's value — where that column
29
+ * holds user-supplied text rather than a foreign key — can compute a value
30
+ * whose key equals another scope's, and share that scope's lock with it. A
31
+ * collision costs contention and never correctness, since a shared lock
32
+ * over-serializes rather than under-locking, and the bounded wait
33
+ * (`sortableScopeLockTimeout`) caps what a deliberate one can achieve at
34
+ * stalls rather than at hangs. A keyed digest would make deliberate collisions
35
+ * expensive, and is not used: changing the derivation would give old and new
36
+ * processes different keys for one scope during a rolling deploy, which is the
37
+ * race this lock exists to eliminate.
38
+ *
39
+ * @param dream - the record whose scope is being locked
40
+ * @param positionField - the sortable position column
41
+ * @param scopeValues - `[column, value]` pairs for the scope being locked
42
+ * @returns a 64-bit signed key
43
+ */
44
+ export default function sortableScopeLockKey(dream: Dream, positionField: string, scopeValues: [string, unknown][]): bigint;
@@ -0,0 +1,51 @@
1
+ import Dream from '../../../../Dream.js';
2
+ import { SortableFieldConfig } from '../Sortable.js';
3
+ import { SortableSnapshots } from './sortableSnapshot.js';
4
+ /**
5
+ * @internal
6
+ *
7
+ * The single key for the scope the record currently occupies — the scope its
8
+ * position is about to be computed within. Used by the position write itself,
9
+ * where the record already carries its final scope values.
10
+ */
11
+ export declare function sortableScopeLockKeyForCurrentScope(dream: Dream, positionField: string, scope: string | string[] | undefined): bigint;
12
+ /**
13
+ * @internal
14
+ *
15
+ * Every key a create's position work needs — one per sortable field, derived
16
+ * from the scope values the row now carries — sorted and deduplicated, so that
17
+ * a multi-sortable-field create acquires in the same global order as every
18
+ * other position-mutating operation. Declaration order cannot serve: the keys
19
+ * hash the runtime scope values, so which field's key sorts first varies from
20
+ * record to record.
21
+ */
22
+ export declare function sortableCurrentScopeLockKeys(dream: Dream, configs: SortableFieldConfig[]): bigint[];
23
+ /**
24
+ * @internal
25
+ *
26
+ * Every key a per-record position-mutating operation needs, sorted and
27
+ * deduplicated. A save that moves a record between sort scopes compacts the
28
+ * scope it leaves and makes room in the scope it enters, so it needs both keys;
29
+ * a save within one scope needs one, and so do a destroy and an undestroy, which
30
+ * write no scope values at all.
31
+ *
32
+ * The *new*-scope key comes from the values being written. The *old*-scope key
33
+ * comes from the database snapshot of the record's physical scope columns when
34
+ * one is available, and only falls back to the instance's pending changes when
35
+ * it is not — which is the case exactly once per save, on the first
36
+ * acquisition, because the snapshot cannot be read until something is locked.
37
+ * The caller closes that window by re-reading under the lock and calling this
38
+ * again with the snapshot; see `acquireStabilizedSortableScopeLocks`.
39
+ *
40
+ * A pending change is only an *old* scope when it has a previous persisted
41
+ * value. A record created earlier in this process reports every column as
42
+ * changed with `was === undefined` (`Dream#changes` compares against the
43
+ * pre-save state), which is not a scope the row was ever in: reading it as one
44
+ * would take a second, bogus lock — and, since every such record produces the
45
+ * same all-null scope tuple, it would be the *same* bogus key for every record
46
+ * in the table, serializing writers that touch unrelated scopes.
47
+ *
48
+ * Either way this must be called *before* the driver write overwrites the
49
+ * record's scope columns.
50
+ */
51
+ export declare function sortableSaveLockKeys(dream: Dream, configs: SortableFieldConfig[], snapshots?: SortableSnapshots): bigint[];