@zudojs/database 1.3.2 → 1.5.0

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 (98) hide show
  1. package/README.md +83 -0
  2. package/dist/cache/cache.memory.d.ts +0 -1
  3. package/dist/cache/cache.memory.js +0 -1
  4. package/dist/cache/index.d.ts +0 -1
  5. package/dist/cache/index.js +0 -1
  6. package/dist/database/database.core.d.ts +20 -7
  7. package/dist/database/database.core.js +8 -6
  8. package/dist/database/index.d.ts +0 -1
  9. package/dist/database/index.js +0 -1
  10. package/dist/databaseClient/databaseClient.core.d.ts +30 -15
  11. package/dist/databaseClient/databaseClient.core.js +19 -3
  12. package/dist/databaseClient/databaseClient.errors.d.ts +19 -2
  13. package/dist/databaseClient/databaseClient.errors.js +8 -1
  14. package/dist/databaseClient/databaseClient.logger.d.ts +0 -1
  15. package/dist/databaseClient/databaseClient.logger.js +0 -1
  16. package/dist/databaseClient/databaseClient.type.d.ts +52 -0
  17. package/dist/databaseClient/databaseClient.type.js +11 -0
  18. package/dist/databaseClient/index.d.ts +2 -3
  19. package/dist/databaseClient/index.js +1 -2
  20. package/dist/databaseConnection/databaseConnection.manager.d.ts +0 -1
  21. package/dist/databaseConnection/databaseConnection.manager.js +0 -1
  22. package/dist/databaseConnection/index.d.ts +0 -1
  23. package/dist/databaseConnection/index.js +0 -1
  24. package/dist/databaseType/databaseType.type.d.ts +6 -5
  25. package/dist/databaseType/databaseType.type.js +0 -1
  26. package/dist/databaseType/index.d.ts +0 -1
  27. package/dist/databaseType/index.js +0 -1
  28. package/dist/health/health.check.d.ts +0 -1
  29. package/dist/health/health.check.js +0 -1
  30. package/dist/health/index.d.ts +0 -1
  31. package/dist/health/index.js +0 -1
  32. package/dist/index.d.ts +3 -4
  33. package/dist/index.js +2 -3
  34. package/dist/locks/index.d.ts +0 -1
  35. package/dist/locks/index.js +0 -1
  36. package/dist/locks/locks.core.d.ts +8 -7
  37. package/dist/locks/locks.core.js +2 -1
  38. package/dist/migration/index.d.ts +0 -1
  39. package/dist/migration/index.js +0 -1
  40. package/dist/migration/migration.dialect.d.ts +0 -1
  41. package/dist/migration/migration.dialect.js +0 -1
  42. package/dist/migration/migration.helpers.d.ts +4 -4
  43. package/dist/migration/migration.helpers.js +4 -1
  44. package/dist/migration/migration.runner.d.ts +16 -5
  45. package/dist/migration/migration.runner.js +69 -17
  46. package/dist/migration/migration.types.d.ts +20 -6
  47. package/dist/migration/migration.types.js +0 -1
  48. package/dist/pagination/index.d.ts +1 -1
  49. package/dist/pagination/index.js +1 -1
  50. package/dist/pagination/pagination.core.d.ts +0 -1
  51. package/dist/pagination/pagination.core.js +0 -1
  52. package/dist/pagination/pagination.cursorError.d.ts +0 -1
  53. package/dist/pagination/pagination.cursorError.js +0 -1
  54. package/dist/pagination/pagination.keyset.d.ts +12 -1
  55. package/dist/pagination/pagination.keyset.js +15 -3
  56. package/dist/pagination/pagination.keysetDirection.d.ts +0 -1
  57. package/dist/pagination/pagination.keysetDirection.js +0 -1
  58. package/dist/pagination/pagination.keysetValue.d.ts +37 -0
  59. package/dist/pagination/pagination.keysetValue.js +55 -0
  60. package/dist/queryBuilder/index.d.ts +0 -1
  61. package/dist/queryBuilder/index.js +0 -1
  62. package/dist/queryBuilder/queryBuilder.core.d.ts +0 -1
  63. package/dist/queryBuilder/queryBuilder.core.js +0 -1
  64. package/dist/queryBuilder/queryBuilder.factory.d.ts +0 -1
  65. package/dist/queryBuilder/queryBuilder.factory.js +0 -1
  66. package/dist/queryBuilder/queryBuilder.filter.d.ts +0 -1
  67. package/dist/queryBuilder/queryBuilder.filter.js +0 -1
  68. package/dist/queryBuilder/queryBuilder.prisma.d.ts +0 -1
  69. package/dist/queryBuilder/queryBuilder.prisma.js +0 -1
  70. package/dist/queryBuilder/queryBuilder.type.d.ts +0 -1
  71. package/dist/queryBuilder/queryBuilder.type.js +0 -1
  72. package/dist/relations/index.d.ts +0 -1
  73. package/dist/relations/index.js +0 -1
  74. package/dist/relations/relations.definition.d.ts +0 -1
  75. package/dist/relations/relations.definition.js +0 -1
  76. package/dist/repository/index.d.ts +1 -2
  77. package/dist/repository/index.js +0 -1
  78. package/dist/repository/repository.base.d.ts +27 -1
  79. package/dist/repository/repository.base.js +13 -2
  80. package/dist/repository/repository.delegate.d.ts +0 -1
  81. package/dist/repository/repository.delegate.js +0 -1
  82. package/dist/repository/repository.errors.d.ts +3 -1
  83. package/dist/repository/repository.errors.js +17 -2
  84. package/dist/seed/index.d.ts +0 -1
  85. package/dist/seed/index.js +0 -1
  86. package/dist/seed/seed.runner.d.ts +14 -12
  87. package/dist/seed/seed.runner.js +0 -1
  88. package/dist/transaction/index.d.ts +0 -1
  89. package/dist/transaction/index.js +0 -1
  90. package/dist/transaction/transaction.backoff.d.ts +0 -1
  91. package/dist/transaction/transaction.backoff.js +0 -1
  92. package/dist/transaction/transaction.core.d.ts +27 -11
  93. package/dist/transaction/transaction.core.js +11 -2
  94. package/dist/unitOfWork/index.d.ts +0 -1
  95. package/dist/unitOfWork/index.js +0 -1
  96. package/dist/unitOfWork/unitOfWork.core.d.ts +12 -11
  97. package/dist/unitOfWork/unitOfWork.core.js +0 -1
  98. package/package.json +4 -4
package/dist/index.d.ts CHANGED
@@ -18,19 +18,18 @@
18
18
  */
19
19
  export type { DatabaseOperationOptions, DatabaseStatus, TransactionIsolationLevel, DatabaseOperation, DatabaseConnectionOptions, DatabaseClientHealth, DatabaseHealth as DatabaseHealthInfo, TransactionOptions, TransactionCallback, Repository, SoftDeletableRepository, PaginationInput, PaginationMeta, PaginatedResult, SortDirection, SortInput, QueryOptions, DatabaseEntity, SoftDeletableEntity, AuditableEntity, DatabaseErrorInfo, DatabaseLogger, } from "./databaseType/index.js";
20
20
  export { noopDatabaseLogger } from "./databaseType/index.js";
21
- export { DatabaseClient, DatabaseAbortError, createDatabaseClient, buildPrismaTransactionOptions, createAbortError, raceAbort, throwIfAborted, SUPPORTED_ISOLATION_LEVELS, normalizeDatabaseError, withDatabaseErrorMetadata, isPrismaError, isRetryableTransactionError, isConflictError, isNotFoundError, getDatabaseErrorCode, getDatabaseErrorKind, isDatabaseErrorLike, isNonDatabaseBaseError, toDatabaseErrorInfo, RETRYABLE_DATABASE_CODES, type DatabaseClientOptions, type DatabaseTransactionContext, type PrismaClientLike, type PrismaDriverAdapterLike, type PrismaQueryEvent, type PrismaTransactionOptions, type RawQueryOptions, type DatabaseErrorKind, type NormalizeDatabaseErrorOptions, type PrismaErrorLike, } from "./databaseClient/index.js";
21
+ export { DatabaseClient, DatabaseAbortError, createDatabaseClient, buildPrismaTransactionOptions, createAbortError, raceAbort, throwIfAborted, SUPPORTED_ISOLATION_LEVELS, normalizeDatabaseError, withDatabaseErrorMetadata, isPrismaError, isRetryableTransactionError, isConflictError, isNotFoundError, getPrismaCodeMapping, getDatabaseErrorCode, getDatabaseErrorKind, isDatabaseErrorLike, isNonDatabaseBaseError, toDatabaseErrorInfo, RETRYABLE_DATABASE_CODES, type DatabaseClientOptions, type DatabaseTransactionContext, type PrismaClientLike, type PrismaDriverAdapterLike, type PrismaQueryEvent, type PrismaTransactionOptions, type PrismaSqlLike, type RawQueryOptions, type TransactionClientOf, type DatabaseErrorKind, type NormalizeDatabaseErrorOptions, type PrismaErrorLike, type PrismaCodeMapping, } from "./databaseClient/index.js";
22
22
  export { DatabaseConnectionManager, createConnectionManager, type DatabaseConnectionEvent, type DatabaseConnectionListener, type DatabaseConnectionEventDetails, type DatabaseConnectionManagerOptions, type DatabaseReconnectOptions, } from "./databaseConnection/index.js";
23
23
  export { Database, createDatabase, getDatabase, connectDatabase, disconnectDatabase, resetDatabase, } from "./database/index.js";
24
- export { BaseRepository, mapRepositoryError, isPrismaErrorLike, toDatabaseOperation, type RepositoryDelegate, type RepositoryDelegateOperations, type BaseRepositoryOptions, type SoftDeleteOptions, type CursorQueryOptions, type TransactionClientLike, type RepositoryOperation, type RepositoryErrorContext, } from "./repository/index.js";
24
+ export { BaseRepository, mapRepositoryError, isPrismaErrorLike, toDatabaseOperation, type RepositoryDelegate, type RepositoryDelegateOperations, type BaseRepositoryOptions, type SoftDeleteOptions, type CreateCursorOptions, type CursorQueryOptions, type TransactionClientLike, type RepositoryOperation, type RepositoryErrorContext, } from "./repository/index.js";
25
25
  export { TransactionManager, createTransactionManager, withTransaction, withTransactionRetry, createTransactionContext, createTransactionId, getTransactionContextFromError, isTransactionActive, isTransactionCommitted, isTransactionFailed, type TransactionStatus, type TransactionContext, type TransactionOutcome, type TransactionRetryOptions, type ManagedTransactionOptions, } from "./transaction/index.js";
26
26
  export { DatabaseUnitOfWork, createUnitOfWork, executeUnitOfWork, type UnitOfWork, type UnitOfWorkOptions, } from "./unitOfWork/index.js";
27
27
  export { QueryBuilder, createQueryBuilder, toPrismaWhere, toPrismaArgs, toPrismaOrderBy, toPrismaSelect, toPrismaSkipTake, type QueryCondition, type QueryFilter, type QueryOperator, type RelationOperator, type QueryBuilderState, type PrismaWhere, type PrismaQueryArgs, type ToPrismaArgsOptions, } from "./queryBuilder/index.js";
28
28
  export { equals, notEquals, inList, notInList, lessThan, lessThanOrEqual, greaterThan, greaterThanOrEqual, contains, startsWith, endsWith, isNull, isNotNull, and, or, not, condition, allOf, anyOf, fromObject, dateRange, oneOf, noneOf, optionalEquals, optionalContains, hasConditions, flattenAnd, cloneFilter, between, matchesPattern, isEmpty, isNotEmpty, dateOnly, isBefore, isAfter, isBetween, notCondition, relational, } from "./queryBuilder/index.js";
29
- export { normalizePagination, normalizePage, normalizeLimit, calculateOffset, calculateTotalPages, createPaginationMeta, createPaginatedResult, getNextPage, getPreviousPage, isValidPage, getItemRange, paginateCollection, encodeCursor, decodeCursor, validateCursorPayload, decodeKeysetCursor, buildKeysetWhere, createKeysetCursor, createKeysetPage, KEYSET_BACKWARD_KEY, getKeysetDirection, reverseKeysetSort, keysetFetchSort, createInvalidCursorError, normalizeCursorPagination, createCursorPaginationMeta, createCursorPaginatedResult, DEFAULT_PAGE, DEFAULT_LIMIT, MAX_LIMIT, type NormalizedPagination, type CursorPaginationInput, type CursorPaginationMeta, type CursorPaginatedResult, type CursorPayload, type EncodeCursorOptions, type DecodeCursorOptions, type KeysetPageOptions, type KeysetWhere, type KeysetDirection, type InvalidCursorReason, } from "./pagination/index.js";
29
+ export { normalizePagination, normalizePage, normalizeLimit, calculateOffset, calculateTotalPages, createPaginationMeta, createPaginatedResult, getNextPage, getPreviousPage, isValidPage, getItemRange, paginateCollection, encodeCursor, decodeCursor, validateCursorPayload, decodeKeysetCursor, buildKeysetWhere, createKeysetCursor, createKeysetPage, KEYSET_BACKWARD_KEY, getKeysetDirection, reverseKeysetSort, keysetFetchSort, createInvalidCursorError, isDateCursorValue, keysetStrictFilter, keysetTieFilter, nextMillisecond, normalizeCursorPagination, createCursorPaginationMeta, createCursorPaginatedResult, DEFAULT_PAGE, DEFAULT_LIMIT, MAX_LIMIT, type NormalizedPagination, type CursorPaginationInput, type CursorPaginationMeta, type CursorPaginatedResult, type CursorPayload, type EncodeCursorOptions, type DecodeCursorOptions, type KeysetPageOptions, type KeysetWhere, type KeysetDirection, type InvalidCursorReason, } from "./pagination/index.js";
30
30
  export { oneToOne, oneToMany, manyToOne, manyToMany, includeRelation, includeRelations, RelationRegistry, createRelationRegistry, validateRelation, validateInclude, toPrismaInclude, DEFAULT_INCLUDE_DEPTH, isRelationType, isCollectionRelation, isSingleRelation, type RelationDefinition, type RelationType, type RelationLoadOptions, type RelationInclude, type ToPrismaIncludeOptions, } from "./relations/index.js";
31
31
  export { DatabaseLockManager, createLockManager, acquireAdvisoryLock, lockRow, buildLockClause, normalizeAdvisoryKey, normalizeAdvisoryKeyPair, resolveLockTransactionOptions, type DatabaseLockMode, type DatabaseLockOptions, type DatabaseLockResult, } from "./locks/index.js";
32
32
  export { MemoryDatabaseCache, createDatabaseCache, createCacheKey, escapeCachePart, serializeCachePart, getOrSet, invalidateByPrefix, CACHE_KEY_SEPARATOR, type CacheEntry, type CacheOptions, type MemoryCacheOptions, type CacheStats, type DatabaseCache, } from "./cache/index.js";
33
33
  export { MigrationRunner, createMigrationRunner, normalizeMigrations, validateMigration, getLatestVersion, getCurrentVersion, DEFAULT_MIGRATION_TABLE, DEFAULT_MIGRATION_LOCK, SQL_IDENTIFIER_PATTERN, validateIdentifier, validateLockKey, quoteIdentifier, hashLockKey, fnv1a64, getSqlDialect, isSqlDialectName, UnsupportedDialectError, DEFAULT_SQL_DIALECT, type Migration, type MigrationRecord, type MigrationResult, type MigrationStatus, type MigrationRunnerOptions, type RunnerTransactionOptions, type SqlDialect, type SqlDialectName, } from "./migration/index.js";
34
34
  export { SeedRunner, createSeedRunner, normalizeSeeds, validateSeed, DEFAULT_SEED_TABLE, DEFAULT_SEED_LOCK, type Seed, type SeedRecord, type SeedResult, type SeedStatus, type SeedRunnerOptions, } from "./seed/index.js";
35
35
  export { checkDatabaseHealth, checkDatabaseReadiness, assertDatabaseHealth, isDatabaseHealthy, getHealthCheckCause, DatabaseUnhealthyError, DEFAULT_HEALTH_TIMEOUT_MS, type DatabaseHealthStatus, type DatabaseHealth, type DatabaseHealthOptions, type DatabaseReadiness, } from "./health/index.js";
36
- //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -18,7 +18,7 @@
18
18
  */
19
19
  export { noopDatabaseLogger } from "./databaseType/index.js";
20
20
  // Client
21
- export { DatabaseClient, DatabaseAbortError, createDatabaseClient, buildPrismaTransactionOptions, createAbortError, raceAbort, throwIfAborted, SUPPORTED_ISOLATION_LEVELS, normalizeDatabaseError, withDatabaseErrorMetadata, isPrismaError, isRetryableTransactionError, isConflictError, isNotFoundError, getDatabaseErrorCode, getDatabaseErrorKind, isDatabaseErrorLike, isNonDatabaseBaseError, toDatabaseErrorInfo, RETRYABLE_DATABASE_CODES, } from "./databaseClient/index.js";
21
+ export { DatabaseClient, DatabaseAbortError, createDatabaseClient, buildPrismaTransactionOptions, createAbortError, raceAbort, throwIfAborted, SUPPORTED_ISOLATION_LEVELS, normalizeDatabaseError, withDatabaseErrorMetadata, isPrismaError, isRetryableTransactionError, isConflictError, isNotFoundError, getPrismaCodeMapping, getDatabaseErrorCode, getDatabaseErrorKind, isDatabaseErrorLike, isNonDatabaseBaseError, toDatabaseErrorInfo, RETRYABLE_DATABASE_CODES, } from "./databaseClient/index.js";
22
22
  // Connection
23
23
  export { DatabaseConnectionManager, createConnectionManager, } from "./databaseConnection/index.js";
24
24
  // Database facade
@@ -33,7 +33,7 @@ export { DatabaseUnitOfWork, createUnitOfWork, executeUnitOfWork, } from "./unit
33
33
  export { QueryBuilder, createQueryBuilder, toPrismaWhere, toPrismaArgs, toPrismaOrderBy, toPrismaSelect, toPrismaSkipTake, } from "./queryBuilder/index.js";
34
34
  export { equals, notEquals, inList, notInList, lessThan, lessThanOrEqual, greaterThan, greaterThanOrEqual, contains, startsWith, endsWith, isNull, isNotNull, and, or, not, condition, allOf, anyOf, fromObject, dateRange, oneOf, noneOf, optionalEquals, optionalContains, hasConditions, flattenAnd, cloneFilter, between, matchesPattern, isEmpty, isNotEmpty, dateOnly, isBefore, isAfter, isBetween, notCondition, relational, } from "./queryBuilder/index.js";
35
35
  // Pagination
36
- export { normalizePagination, normalizePage, normalizeLimit, calculateOffset, calculateTotalPages, createPaginationMeta, createPaginatedResult, getNextPage, getPreviousPage, isValidPage, getItemRange, paginateCollection, encodeCursor, decodeCursor, validateCursorPayload, decodeKeysetCursor, buildKeysetWhere, createKeysetCursor, createKeysetPage, KEYSET_BACKWARD_KEY, getKeysetDirection, reverseKeysetSort, keysetFetchSort, createInvalidCursorError, normalizeCursorPagination, createCursorPaginationMeta, createCursorPaginatedResult, DEFAULT_PAGE, DEFAULT_LIMIT, MAX_LIMIT, } from "./pagination/index.js";
36
+ export { normalizePagination, normalizePage, normalizeLimit, calculateOffset, calculateTotalPages, createPaginationMeta, createPaginatedResult, getNextPage, getPreviousPage, isValidPage, getItemRange, paginateCollection, encodeCursor, decodeCursor, validateCursorPayload, decodeKeysetCursor, buildKeysetWhere, createKeysetCursor, createKeysetPage, KEYSET_BACKWARD_KEY, getKeysetDirection, reverseKeysetSort, keysetFetchSort, createInvalidCursorError, isDateCursorValue, keysetStrictFilter, keysetTieFilter, nextMillisecond, normalizeCursorPagination, createCursorPaginationMeta, createCursorPaginatedResult, DEFAULT_PAGE, DEFAULT_LIMIT, MAX_LIMIT, } from "./pagination/index.js";
37
37
  // Relations
38
38
  export { oneToOne, oneToMany, manyToOne, manyToMany, includeRelation, includeRelations, RelationRegistry, createRelationRegistry, validateRelation, validateInclude, toPrismaInclude, DEFAULT_INCLUDE_DEPTH, isRelationType, isCollectionRelation, isSingleRelation, } from "./relations/index.js";
39
39
  // Locks
@@ -46,4 +46,3 @@ export { MigrationRunner, createMigrationRunner, normalizeMigrations, validateMi
46
46
  export { SeedRunner, createSeedRunner, normalizeSeeds, validateSeed, DEFAULT_SEED_TABLE, DEFAULT_SEED_LOCK, } from "./seed/index.js";
47
47
  // Health
48
48
  export { checkDatabaseHealth, checkDatabaseReadiness, assertDatabaseHealth, isDatabaseHealthy, getHealthCheckCause, DatabaseUnhealthyError, DEFAULT_HEALTH_TIMEOUT_MS, } from "./health/index.js";
49
- //# sourceMappingURL=index.js.map
@@ -4,4 +4,3 @@
4
4
  * Advisory and row-level database locking (PostgreSQL).
5
5
  */
6
6
  export { DatabaseLockManager, createLockManager, acquireAdvisoryLock, lockRow, buildLockClause, normalizeAdvisoryKey, normalizeAdvisoryKeyPair, resolveLockTransactionOptions, type DatabaseLockMode, type DatabaseLockOptions, type DatabaseLockResult, } from "./locks.core.js";
7
- //# sourceMappingURL=index.d.ts.map
@@ -4,4 +4,3 @@
4
4
  * Advisory and row-level database locking (PostgreSQL).
5
5
  */
6
6
  export { DatabaseLockManager, createLockManager, acquireAdvisoryLock, lockRow, buildLockClause, normalizeAdvisoryKey, normalizeAdvisoryKeyPair, resolveLockTransactionOptions, } from "./locks.core.js";
7
- //# sourceMappingURL=index.js.map
@@ -62,31 +62,33 @@ export interface DatabaseLockResult {
62
62
  * Application-level lock abstraction for PostgreSQL.
63
63
  *
64
64
  * Locks are acquired inside a transaction and released when it ends.
65
+ * `TTransaction` is the transaction client handed to callbacks, taken from
66
+ * the database client.
65
67
  */
66
- export declare class DatabaseLockManager {
68
+ export declare class DatabaseLockManager<TTransaction extends DatabaseTransactionContext = DatabaseTransactionContext> {
67
69
  private readonly client;
68
- constructor(client: DatabaseClient);
70
+ constructor(client: DatabaseClient<TTransaction>);
69
71
  /**
70
72
  * Executes work inside a transaction after acquiring a PostgreSQL
71
73
  * advisory transaction lock.
72
74
  */
73
- withAdvisoryLock<TResult>(lockKey: string, callback: (transaction: DatabaseTransactionContext) => Promise<TResult>, options?: DatabaseLockOptions): Promise<TResult>;
75
+ withAdvisoryLock<TResult>(lockKey: string, callback: (transaction: TTransaction) => Promise<TResult>, options?: DatabaseLockOptions): Promise<TResult>;
74
76
  /**
75
77
  * Acquires a row-level lock and executes work while holding it.
76
78
  *
77
79
  * @throws {DatabaseError} when the row does not exist or was skipped
78
80
  * because another transaction holds it (`skipLocked`).
79
81
  */
80
- withRowLock<TResult>(tableName: string, id: string | number, callback: (transaction: DatabaseTransactionContext) => Promise<TResult>, options?: DatabaseLockOptions): Promise<TResult>;
82
+ withRowLock<TResult>(tableName: string, id: string | number, callback: (transaction: TTransaction) => Promise<TResult>, options?: DatabaseLockOptions): Promise<TResult>;
81
83
  /**
82
84
  * Returns the underlying database client.
83
85
  */
84
- getClient(): DatabaseClient;
86
+ getClient(): DatabaseClient<TTransaction>;
85
87
  }
86
88
  /**
87
89
  * Creates a lock manager.
88
90
  */
89
- export declare function createLockManager(client: DatabaseClient): DatabaseLockManager;
91
+ export declare function createLockManager<TTransaction extends DatabaseTransactionContext = DatabaseTransactionContext>(client: DatabaseClient<TTransaction>): DatabaseLockManager<TTransaction>;
90
92
  /**
91
93
  * Acquires a PostgreSQL advisory transaction lock.
92
94
  *
@@ -129,4 +131,3 @@ export declare function normalizeAdvisoryKeyPair(namespace: string, lockKey: str
129
131
  * than `timeoutMs`.
130
132
  */
131
133
  export declare function resolveLockTransactionOptions(options?: DatabaseLockOptions): TransactionOptions | undefined;
132
- //# sourceMappingURL=locks.core.d.ts.map
@@ -5,6 +5,8 @@ import { fnv1a64, hashLockKey, SQL_IDENTIFIER_PATTERN, } from "../migration/migr
5
5
  * Application-level lock abstraction for PostgreSQL.
6
6
  *
7
7
  * Locks are acquired inside a transaction and released when it ends.
8
+ * `TTransaction` is the transaction client handed to callbacks, taken from
9
+ * the database client.
8
10
  */
9
11
  export class DatabaseLockManager {
10
12
  client;
@@ -266,4 +268,3 @@ function validateId(id) {
266
268
  throw new TypeError("A database identifier must be a string or number.");
267
269
  }
268
270
  }
269
- //# sourceMappingURL=locks.core.js.map
@@ -6,4 +6,3 @@
6
6
  export { MigrationRunner, createMigrationRunner, normalizeMigrations, validateMigration, getLatestVersion, getCurrentVersion, DEFAULT_MIGRATION_TABLE, DEFAULT_MIGRATION_LOCK, type Migration, type MigrationRecord, type MigrationResult, type MigrationStatus, type MigrationRunnerOptions, type RunnerTransactionOptions, } from "./migration.runner.js";
7
7
  export { SQL_IDENTIFIER_PATTERN, validateIdentifier, validateLockKey, quoteIdentifier, hashLockKey, fnv1a64, FNV1A_64_OFFSET_BASIS, FNV1A_64_PRIME, } from "./migration.helpers.js";
8
8
  export { getSqlDialect, isSqlDialectName, UnsupportedDialectError, DEFAULT_SQL_DIALECT, type SqlDialect, type SqlDialectName, } from "./migration.dialect.js";
9
- //# sourceMappingURL=index.d.ts.map
@@ -6,4 +6,3 @@
6
6
  export { MigrationRunner, createMigrationRunner, normalizeMigrations, validateMigration, getLatestVersion, getCurrentVersion, DEFAULT_MIGRATION_TABLE, DEFAULT_MIGRATION_LOCK, } from "./migration.runner.js";
7
7
  export { SQL_IDENTIFIER_PATTERN, validateIdentifier, validateLockKey, quoteIdentifier, hashLockKey, fnv1a64, FNV1A_64_OFFSET_BASIS, FNV1A_64_PRIME, } from "./migration.helpers.js";
8
8
  export { getSqlDialect, isSqlDialectName, UnsupportedDialectError, DEFAULT_SQL_DIALECT, } from "./migration.dialect.js";
9
- //# sourceMappingURL=index.js.map
@@ -62,4 +62,3 @@ export declare function isSqlDialectName(value: unknown): value is SqlDialectNam
62
62
  * @throws {TypeError} for unknown dialect names.
63
63
  */
64
64
  export declare function getSqlDialect(name?: SqlDialectName): SqlDialect;
65
- //# sourceMappingURL=migration.dialect.d.ts.map
@@ -60,4 +60,3 @@ export function getSqlDialect(name = DEFAULT_SQL_DIALECT) {
60
60
  }
61
61
  throw new TypeError(`Unknown SQL dialect: "${String(name)}".`);
62
62
  }
63
- //# sourceMappingURL=migration.dialect.js.map
@@ -1,3 +1,4 @@
1
+ import type { DatabaseTransactionContext } from "../databaseClient/databaseClient.type.js";
1
2
  import type { Migration, MigrationRecord } from "./migration.types.js";
2
3
  /**
3
4
  * Default migration table.
@@ -14,15 +15,15 @@ export declare const SQL_IDENTIFIER_PATTERN: RegExp;
14
15
  /**
15
16
  * Normalizes and validates migrations.
16
17
  */
17
- export declare function normalizeMigrations(migrations: readonly Migration[]): readonly Migration[];
18
+ export declare function normalizeMigrations<TTransaction extends DatabaseTransactionContext = DatabaseTransactionContext>(migrations: readonly Migration<TTransaction>[]): readonly Migration<TTransaction>[];
18
19
  /**
19
20
  * Validates one migration.
20
21
  */
21
- export declare function validateMigration(migration: Migration): void;
22
+ export declare function validateMigration<TTransaction extends DatabaseTransactionContext = DatabaseTransactionContext>(migration: Migration<TTransaction>): void;
22
23
  /**
23
24
  * Returns the highest registered migration version.
24
25
  */
25
- export declare function getLatestVersion(migrations: readonly Migration[]): number;
26
+ export declare function getLatestVersion(migrations: readonly Pick<Migration, "version">[]): number;
26
27
  /**
27
28
  * Returns the highest applied migration version.
28
29
  */
@@ -62,4 +63,3 @@ export declare function fnv1a64(value: string): bigint;
62
63
  * Suitable as the single `bigint` argument of `pg_advisory_xact_lock`.
63
64
  */
64
65
  export declare function hashLockKey(value: string): bigint;
65
- //# sourceMappingURL=migration.helpers.d.ts.map
@@ -58,6 +58,10 @@ export function validateMigration(migration) {
58
58
  if (migration.down !== undefined && typeof migration.down !== "function") {
59
59
  throw new TypeError(`Migration "${migration.name}" has an invalid down function.`);
60
60
  }
61
+ if (migration.transaction !== undefined &&
62
+ typeof migration.transaction !== "boolean") {
63
+ throw new TypeError(`Migration "${migration.name}" has an invalid transaction flag.`);
64
+ }
61
65
  }
62
66
  /**
63
67
  * Returns the highest registered migration version.
@@ -138,4 +142,3 @@ export function fnv1a64(value) {
138
142
  export function hashLockKey(value) {
139
143
  return BigInt.asIntN(64, fnv1a64(value));
140
144
  }
141
- //# sourceMappingURL=migration.helpers.js.map
@@ -9,7 +9,7 @@ export { DEFAULT_MIGRATION_TABLE, DEFAULT_MIGRATION_LOCK, normalizeMigrations, g
9
9
  * lock before deciding what to execute, so two runners started together
10
10
  * never apply or revert the same migration twice.
11
11
  */
12
- export declare class MigrationRunner {
12
+ export declare class MigrationRunner<TTransaction extends DatabaseTransactionContext = DatabaseTransactionContext> {
13
13
  private readonly client;
14
14
  private readonly migrations;
15
15
  private readonly tableName;
@@ -17,15 +17,23 @@ export declare class MigrationRunner {
17
17
  private readonly dialect;
18
18
  private readonly transactionOptions;
19
19
  private readonly perItemTransaction;
20
- constructor(client: DatabaseClient, migrations: readonly Migration[], options?: MigrationRunnerOptions);
20
+ constructor(client: DatabaseClient<TTransaction>, migrations: readonly Migration<TTransaction>[], options?: MigrationRunnerOptions);
21
21
  /**
22
22
  * Returns the migration status without executing anything.
23
23
  */
24
- status(): Promise<MigrationStatus>;
24
+ status(): Promise<MigrationStatus<TTransaction>>;
25
25
  /**
26
26
  * Applies every pending migration in version order.
27
27
  */
28
28
  migrate(): Promise<MigrationResult>;
29
+ /**
30
+ * Applies a `transaction: false` migration: the applied check and the
31
+ * history record run in short transactions under the advisory lock, the
32
+ * body runs on the root client outside any transaction.
33
+ */
34
+ private applyDetached;
35
+ /** The root Prisma client, handed to migrations that opt out of a transaction. */
36
+ private rootClient;
29
37
  /**
30
38
  * Alias of {@link migrate}.
31
39
  */
@@ -58,7 +66,11 @@ export declare class MigrationRunner {
58
66
  */
59
67
  getHistory(): Promise<readonly MigrationRecord[]>;
60
68
  private rollbackSteps;
69
+ /** Reverts a `transaction: false` migration; see {@link applyDetached}. */
70
+ private revertDetached;
61
71
  private revertRecord;
72
+ private requireRollback;
73
+ private runDown;
62
74
  private computePending;
63
75
  private buildTransactionOptions;
64
76
  private executor;
@@ -71,5 +83,4 @@ export declare class MigrationRunner {
71
83
  /**
72
84
  * Creates a migration runner.
73
85
  */
74
- export declare function createMigrationRunner(client: DatabaseClient, migrations: readonly Migration[], options?: MigrationRunnerOptions): MigrationRunner;
75
- //# sourceMappingURL=migration.runner.d.ts.map
86
+ export declare function createMigrationRunner<TTransaction extends DatabaseTransactionContext = DatabaseTransactionContext>(client: DatabaseClient<TTransaction>, migrations: readonly Migration<TTransaction>[], options?: MigrationRunnerOptions): MigrationRunner<TTransaction>;
@@ -31,6 +31,10 @@ export class MigrationRunner {
31
31
  this.perItemTransaction = options.perItemTransaction ?? true;
32
32
  validateIdentifier(this.tableName, "migration table name");
33
33
  validateLockKey(this.lockKey, "migration lock key");
34
+ const detached = this.migrations.find((m) => m.transaction === false);
35
+ if (detached && !this.perItemTransaction) {
36
+ throw this.migrationError(`Migration "${detached.name}" sets transaction: false, which requires perItemTransaction: true.`, { metadata: { version: detached.version, name: detached.name } });
37
+ }
34
38
  }
35
39
  /**
36
40
  * Returns the migration status without executing anything.
@@ -69,16 +73,18 @@ export class MigrationRunner {
69
73
  return { applied: newlyApplied, skipped };
70
74
  }
71
75
  for (const migration of pending) {
72
- const outcome = await this.client.transaction(async (transaction) => {
73
- await this.acquireMigrationLock(transaction);
74
- const applied = await this.getAppliedMigrations(transaction);
75
- const existing = applied.find((r) => r.version === migration.version);
76
- if (existing)
77
- return { record: existing, skipped: true };
78
- await this.executeMigration(transaction, migration);
79
- const record = await this.recordMigration(transaction, migration);
80
- return { record, skipped: false };
81
- }, this.buildTransactionOptions());
76
+ const outcome = migration.transaction === false
77
+ ? await this.applyDetached(migration)
78
+ : await this.client.transaction(async (transaction) => {
79
+ await this.acquireMigrationLock(transaction);
80
+ const applied = await this.getAppliedMigrations(transaction);
81
+ const existing = applied.find((r) => r.version === migration.version);
82
+ if (existing)
83
+ return { record: existing, skipped: true };
84
+ await this.executeMigration(transaction, migration);
85
+ const record = await this.recordMigration(transaction, migration);
86
+ return { record, skipped: false };
87
+ }, this.buildTransactionOptions());
82
88
  if (outcome.skipped)
83
89
  skipped.push(outcome.record);
84
90
  else
@@ -86,6 +92,32 @@ export class MigrationRunner {
86
92
  }
87
93
  return { applied: newlyApplied, skipped };
88
94
  }
95
+ /**
96
+ * Applies a `transaction: false` migration: the applied check and the
97
+ * history record run in short transactions under the advisory lock, the
98
+ * body runs on the root client outside any transaction.
99
+ */
100
+ async applyDetached(migration) {
101
+ const existing = await this.client.transaction(async (transaction) => {
102
+ await this.acquireMigrationLock(transaction);
103
+ const applied = await this.getAppliedMigrations(transaction);
104
+ return applied.find((r) => r.version === migration.version);
105
+ }, this.buildTransactionOptions());
106
+ if (existing)
107
+ return { record: existing, skipped: true };
108
+ await this.executeMigration(this.rootClient(), migration);
109
+ const record = await this.client.transaction(async (transaction) => {
110
+ await this.acquireMigrationLock(transaction);
111
+ const applied = await this.getAppliedMigrations(transaction);
112
+ return (applied.find((r) => r.version === migration.version) ??
113
+ (await this.recordMigration(transaction, migration)));
114
+ }, this.buildTransactionOptions());
115
+ return { record, skipped: false };
116
+ }
117
+ /** The root Prisma client, handed to migrations that opt out of a transaction. */
118
+ rootClient() {
119
+ return this.client.getPrisma();
120
+ }
89
121
  /**
90
122
  * Alias of {@link migrate}.
91
123
  */
@@ -175,22 +207,41 @@ export class MigrationRunner {
175
207
  return rolledBack;
176
208
  }
177
209
  while (rolledBack.length < limit) {
178
- const record = await this.client.transaction(async (transaction) => {
210
+ const step = await this.client.transaction(async (transaction) => {
179
211
  await this.acquireMigrationLock(transaction);
180
212
  const applied = await this.getAppliedMigrations(transaction);
181
213
  const latest = applied[applied.length - 1];
182
214
  if (!latest)
183
215
  return null;
184
- await this.revertRecord(transaction, latest);
185
- return latest;
216
+ const migration = this.requireRollback(latest);
217
+ if (migration.transaction === false) {
218
+ return { record: latest, detached: true };
219
+ }
220
+ await this.runDown(transaction, migration);
221
+ await this.deleteMigrationRecord(transaction, latest.version);
222
+ return { record: latest, detached: false };
186
223
  }, this.buildTransactionOptions());
187
- if (!record)
224
+ if (!step)
188
225
  break;
189
- rolledBack.push(record);
226
+ if (step.detached)
227
+ await this.revertDetached(step.record);
228
+ rolledBack.push(step.record);
190
229
  }
191
230
  return rolledBack;
192
231
  }
232
+ /** Reverts a `transaction: false` migration; see {@link applyDetached}. */
233
+ async revertDetached(record) {
234
+ await this.runDown(this.rootClient(), this.requireRollback(record));
235
+ await this.client.transaction(async (transaction) => {
236
+ await this.acquireMigrationLock(transaction);
237
+ await this.deleteMigrationRecord(transaction, record.version);
238
+ }, this.buildTransactionOptions());
239
+ }
193
240
  async revertRecord(transaction, record) {
241
+ await this.runDown(transaction, this.requireRollback(record));
242
+ await this.deleteMigrationRecord(transaction, record.version);
243
+ }
244
+ requireRollback(record) {
194
245
  const migration = this.migrations.find((m) => m.version === record.version);
195
246
  if (!migration) {
196
247
  throw this.migrationError(`Migration "${record.name}" is recorded as applied but is not registered.`, { metadata: { version: record.version } });
@@ -198,6 +249,9 @@ export class MigrationRunner {
198
249
  if (!migration.down) {
199
250
  throw this.migrationError(`Migration "${migration.name}" does not define a rollback operation.`, { metadata: { version: migration.version } });
200
251
  }
252
+ return migration;
253
+ }
254
+ async runDown(transaction, migration) {
201
255
  try {
202
256
  await migration.down(transaction);
203
257
  }
@@ -207,7 +261,6 @@ export class MigrationRunner {
207
261
  metadata: { version: migration.version, name: migration.name },
208
262
  });
209
263
  }
210
- await this.deleteMigrationRecord(transaction, migration.version);
211
264
  }
212
265
  computePending(applied) {
213
266
  const versions = new Set(applied.map((record) => record.version));
@@ -294,4 +347,3 @@ function hasVersion(records, version) {
294
347
  export function createMigrationRunner(client, migrations, options) {
295
348
  return new MigrationRunner(client, migrations, options);
296
349
  }
297
- //# sourceMappingURL=migration.runner.js.map
@@ -7,18 +7,33 @@ import type { SqlDialectName } from "./migration.dialect.js";
7
7
  * Each migration must have a unique, monotonically ordered version. The
8
8
  * version is stored in a BIGINT column, so timestamp-style versions such as
9
9
  * `20260908120000` are supported up to `Number.MAX_SAFE_INTEGER`.
10
+ *
11
+ * `TTransaction` is the transaction client handed to `up` and `down`;
12
+ * `createMigrationRunner` infers it from the database client.
10
13
  */
11
- export interface Migration {
14
+ export interface Migration<TTransaction extends DatabaseTransactionContext = DatabaseTransactionContext> {
12
15
  readonly version: number;
13
16
  readonly name: string;
14
17
  /**
15
18
  * Applies the migration.
16
19
  */
17
- readonly up: (database: DatabaseTransactionContext) => Promise<void>;
20
+ readonly up: (database: TTransaction) => Promise<void>;
18
21
  /**
19
22
  * Reverts the migration.
20
23
  */
21
- readonly down?: (database: DatabaseTransactionContext) => Promise<void>;
24
+ readonly down?: (database: TTransaction) => Promise<void>;
25
+ /**
26
+ * When `false`, `up` and `down` run outside a transaction, on the root
27
+ * client, which is what statements such as `CREATE INDEX CONCURRENTLY`
28
+ * or `ALTER TYPE ... ADD VALUE` require. Defaults to `true`.
29
+ *
30
+ * The applied check and the history record still happen inside short
31
+ * transactions under the advisory lock, but the lock is released while
32
+ * the body runs, so make such a migration idempotent (`IF NOT EXISTS`)
33
+ * to tolerate a second runner started at the same moment. Requires
34
+ * `perItemTransaction` (the default); a batch runner refuses it.
35
+ */
36
+ readonly transaction?: boolean;
22
37
  }
23
38
  /**
24
39
  * Persisted migration record.
@@ -38,10 +53,10 @@ export interface MigrationResult {
38
53
  /**
39
54
  * Migration status.
40
55
  */
41
- export interface MigrationStatus {
56
+ export interface MigrationStatus<TTransaction extends DatabaseTransactionContext = DatabaseTransactionContext> {
42
57
  readonly currentVersion: number;
43
58
  readonly latestVersion: number;
44
- readonly pending: readonly Migration[];
59
+ readonly pending: readonly Migration<TTransaction>[];
45
60
  readonly applied: readonly MigrationRecord[];
46
61
  }
47
62
  /**
@@ -82,4 +97,3 @@ export interface MigrationRunnerOptions {
82
97
  */
83
98
  readonly perItemTransaction?: boolean;
84
99
  }
85
- //# sourceMappingURL=migration.types.d.ts.map
@@ -1,2 +1 @@
1
1
  export {};
2
- //# sourceMappingURL=migration.types.js.map
@@ -7,4 +7,4 @@ export { normalizePagination, normalizePage, normalizeLimit, calculateOffset, ca
7
7
  export { decodeKeysetCursor, buildKeysetWhere, createKeysetCursor, createKeysetPage, type KeysetPageOptions, type KeysetWhere, } from "./pagination.keyset.js";
8
8
  export { KEYSET_BACKWARD_KEY, getKeysetDirection, reverseKeysetSort, keysetFetchSort, type KeysetDirection, } from "./pagination.keysetDirection.js";
9
9
  export { createInvalidCursorError, type InvalidCursorReason, } from "./pagination.cursorError.js";
10
- //# sourceMappingURL=index.d.ts.map
10
+ export { isDateCursorValue, keysetStrictFilter, keysetTieFilter, nextMillisecond, } from "./pagination.keysetValue.js";
@@ -7,4 +7,4 @@ export { normalizePagination, normalizePage, normalizeLimit, calculateOffset, ca
7
7
  export { decodeKeysetCursor, buildKeysetWhere, createKeysetCursor, createKeysetPage, } from "./pagination.keyset.js";
8
8
  export { KEYSET_BACKWARD_KEY, getKeysetDirection, reverseKeysetSort, keysetFetchSort, } from "./pagination.keysetDirection.js";
9
9
  export { createInvalidCursorError, } from "./pagination.cursorError.js";
10
- //# sourceMappingURL=index.js.map
10
+ export { isDateCursorValue, keysetStrictFilter, keysetTieFilter, nextMillisecond, } from "./pagination.keysetValue.js";
@@ -164,4 +164,3 @@ export declare function decodeCursor<T = unknown>(cursor: string, options?: Deco
164
164
  * restricted to the allowed fields.
165
165
  */
166
166
  export declare function validateCursorPayload(value: unknown, allowedFields: readonly string[]): asserts value is CursorPayload;
167
- //# sourceMappingURL=pagination.core.d.ts.map
@@ -279,4 +279,3 @@ function validateSecret(secret) {
279
279
  throw new TypeError("A cursor secret must be a non-empty string.");
280
280
  }
281
281
  }
282
- //# sourceMappingURL=pagination.core.js.map
@@ -14,4 +14,3 @@ export type InvalidCursorReason = "cursor_required" | "cursor_signature" | "curs
14
14
  * failure is kept only as the non-exposed `cause`.
15
15
  */
16
16
  export declare function createInvalidCursorError(message: string, reason: InvalidCursorReason, cause?: unknown): ValidationError;
17
- //# sourceMappingURL=pagination.cursorError.d.ts.map
@@ -14,4 +14,3 @@ export function createInvalidCursorError(message, reason, cause) {
14
14
  ...(cause !== undefined ? { cause } : {}),
15
15
  });
16
16
  }
17
- //# sourceMappingURL=pagination.cursorError.js.map
@@ -49,11 +49,23 @@ export declare function decodeKeysetCursor<TField extends string = string>(curso
49
49
  *
50
50
  * For a sort of `[a asc, b desc]` the forward result is
51
51
  * `OR: [{ a: { gt: A } }, { AND: [{ a: A }, { b: { lt: B } }] }]`.
52
+ *
53
+ * A value encoded from a `Date` is compared as its millisecond bucket
54
+ * (`gte C, lt C + 1ms` for a tie; `lt C` / `gte C + 1ms` for the strict
55
+ * part), so rows created in the same millisecond as the cursor row on a
56
+ * microsecond-precision column fall through to the next sort field
57
+ * instead of being skipped. See `pagination.keysetValue.ts`.
52
58
  */
53
59
  export declare function buildKeysetWhere<TField extends string = string>(cursor: CursorPayload, sort: readonly SortInput<TField>[]): KeysetWhere;
54
60
  /**
55
61
  * Derives the cursor payload for a row from the sort fields. A
56
62
  * `"backward"` cursor selects the rows before `row` instead of after it.
63
+ *
64
+ * `sort` must be the exact sort the page is fetched and decoded with.
65
+ * `BaseRepository#paginateCursor` appends the id field as a tiebreaker, so
66
+ * a cursor for a repository page must include it: use
67
+ * `repository.createCursor(row, { sort })`, which does, rather than this
68
+ * helper with the bare sort.
57
69
  */
58
70
  export declare function createKeysetCursor<TField extends string = string>(row: Readonly<Record<string, unknown>>, sort: readonly SortInput<TField>[], secret?: string, direction?: KeysetDirection): string;
59
71
  /**
@@ -69,4 +81,3 @@ export declare function createKeysetCursor<TField extends string = string>(row:
69
81
  * non-empty page, and `previousCursor` only when more rows precede it.
70
82
  */
71
83
  export declare function createKeysetPage<TEntity extends Readonly<Record<string, unknown>>, TField extends string = string>(rows: readonly TEntity[], options: KeysetPageOptions<TField>): CursorPaginatedResult<TEntity>;
72
- //# sourceMappingURL=pagination.keyset.d.ts.map
@@ -1,6 +1,7 @@
1
1
  import { createCursorPaginatedResult, decodeCursor, encodeCursor, normalizeLimit, } from "./pagination.core.js";
2
2
  import { createInvalidCursorError } from "./pagination.cursorError.js";
3
3
  import { KEYSET_BACKWARD_KEY, getKeysetDirection, reverseKeysetSort, } from "./pagination.keysetDirection.js";
4
+ import { keysetStrictFilter, keysetTieFilter } from "./pagination.keysetValue.js";
4
5
  /**
5
6
  * Decodes and validates a keyset cursor against the sort definition.
6
7
  *
@@ -32,6 +33,12 @@ export function decodeKeysetCursor(cursor, sort, secret) {
32
33
  *
33
34
  * For a sort of `[a asc, b desc]` the forward result is
34
35
  * `OR: [{ a: { gt: A } }, { AND: [{ a: A }, { b: { lt: B } }] }]`.
36
+ *
37
+ * A value encoded from a `Date` is compared as its millisecond bucket
38
+ * (`gte C, lt C + 1ms` for a tie; `lt C` / `gte C + 1ms` for the strict
39
+ * part), so rows created in the same millisecond as the cursor row on a
40
+ * microsecond-precision column fall through to the next sort field
41
+ * instead of being skipped. See `pagination.keysetValue.ts`.
35
42
  */
36
43
  export function buildKeysetWhere(cursor, sort) {
37
44
  validateSort(sort);
@@ -42,10 +49,10 @@ export function buildKeysetWhere(cursor, sort) {
42
49
  const conditions = effective
43
50
  .slice(0, index)
44
51
  .map((previous) => ({
45
- [previous.field]: { equals: cursor[previous.field] },
52
+ [previous.field]: keysetTieFilter(cursor[previous.field]),
46
53
  }));
47
54
  conditions.push({
48
- [entry.field]: { [comparison]: cursor[entry.field] },
55
+ [entry.field]: keysetStrictFilter(cursor[entry.field], comparison),
49
56
  });
50
57
  branches.push(conditions.length === 1 ? conditions[0] : { AND: conditions });
51
58
  });
@@ -54,6 +61,12 @@ export function buildKeysetWhere(cursor, sort) {
54
61
  /**
55
62
  * Derives the cursor payload for a row from the sort fields. A
56
63
  * `"backward"` cursor selects the rows before `row` instead of after it.
64
+ *
65
+ * `sort` must be the exact sort the page is fetched and decoded with.
66
+ * `BaseRepository#paginateCursor` appends the id field as a tiebreaker, so
67
+ * a cursor for a repository page must include it: use
68
+ * `repository.createCursor(row, { sort })`, which does, rather than this
69
+ * helper with the bare sort.
57
70
  */
58
71
  export function createKeysetCursor(row, sort, secret, direction = "forward") {
59
72
  validateSort(sort);
@@ -133,4 +146,3 @@ function validateSort(sort) {
133
146
  seen.add(entry.field);
134
147
  }
135
148
  }
136
- //# sourceMappingURL=pagination.keyset.js.map
@@ -26,4 +26,3 @@ export declare function reverseKeysetSort<TField extends string>(sort: readonly
26
26
  * the requested sort going forward, the reversed sort going backward.
27
27
  */
28
28
  export declare function keysetFetchSort<TField extends string>(sort: readonly SortInput<TField>[], direction: KeysetDirection): readonly SortInput<TField>[];
29
- //# sourceMappingURL=pagination.keysetDirection.d.ts.map
@@ -27,4 +27,3 @@ export function reverseKeysetSort(sort) {
27
27
  export function keysetFetchSort(sort, direction) {
28
28
  return direction === "backward" ? reverseKeysetSort(sort) : sort;
29
29
  }
30
- //# sourceMappingURL=pagination.keysetDirection.js.map