@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.
- package/README.md +83 -0
- package/dist/cache/cache.memory.d.ts +0 -1
- package/dist/cache/cache.memory.js +0 -1
- package/dist/cache/index.d.ts +0 -1
- package/dist/cache/index.js +0 -1
- package/dist/database/database.core.d.ts +20 -7
- package/dist/database/database.core.js +8 -6
- package/dist/database/index.d.ts +0 -1
- package/dist/database/index.js +0 -1
- package/dist/databaseClient/databaseClient.core.d.ts +30 -15
- package/dist/databaseClient/databaseClient.core.js +19 -3
- package/dist/databaseClient/databaseClient.errors.d.ts +19 -2
- package/dist/databaseClient/databaseClient.errors.js +8 -1
- package/dist/databaseClient/databaseClient.logger.d.ts +0 -1
- package/dist/databaseClient/databaseClient.logger.js +0 -1
- package/dist/databaseClient/databaseClient.type.d.ts +52 -0
- package/dist/databaseClient/databaseClient.type.js +11 -0
- package/dist/databaseClient/index.d.ts +2 -3
- package/dist/databaseClient/index.js +1 -2
- package/dist/databaseConnection/databaseConnection.manager.d.ts +0 -1
- package/dist/databaseConnection/databaseConnection.manager.js +0 -1
- package/dist/databaseConnection/index.d.ts +0 -1
- package/dist/databaseConnection/index.js +0 -1
- package/dist/databaseType/databaseType.type.d.ts +6 -5
- package/dist/databaseType/databaseType.type.js +0 -1
- package/dist/databaseType/index.d.ts +0 -1
- package/dist/databaseType/index.js +0 -1
- package/dist/health/health.check.d.ts +0 -1
- package/dist/health/health.check.js +0 -1
- package/dist/health/index.d.ts +0 -1
- package/dist/health/index.js +0 -1
- package/dist/index.d.ts +3 -4
- package/dist/index.js +2 -3
- package/dist/locks/index.d.ts +0 -1
- package/dist/locks/index.js +0 -1
- package/dist/locks/locks.core.d.ts +8 -7
- package/dist/locks/locks.core.js +2 -1
- package/dist/migration/index.d.ts +0 -1
- package/dist/migration/index.js +0 -1
- package/dist/migration/migration.dialect.d.ts +0 -1
- package/dist/migration/migration.dialect.js +0 -1
- package/dist/migration/migration.helpers.d.ts +4 -4
- package/dist/migration/migration.helpers.js +4 -1
- package/dist/migration/migration.runner.d.ts +16 -5
- package/dist/migration/migration.runner.js +69 -17
- package/dist/migration/migration.types.d.ts +20 -6
- package/dist/migration/migration.types.js +0 -1
- package/dist/pagination/index.d.ts +1 -1
- package/dist/pagination/index.js +1 -1
- package/dist/pagination/pagination.core.d.ts +0 -1
- package/dist/pagination/pagination.core.js +0 -1
- package/dist/pagination/pagination.cursorError.d.ts +0 -1
- package/dist/pagination/pagination.cursorError.js +0 -1
- package/dist/pagination/pagination.keyset.d.ts +12 -1
- package/dist/pagination/pagination.keyset.js +15 -3
- package/dist/pagination/pagination.keysetDirection.d.ts +0 -1
- package/dist/pagination/pagination.keysetDirection.js +0 -1
- package/dist/pagination/pagination.keysetValue.d.ts +37 -0
- package/dist/pagination/pagination.keysetValue.js +55 -0
- package/dist/queryBuilder/index.d.ts +0 -1
- package/dist/queryBuilder/index.js +0 -1
- package/dist/queryBuilder/queryBuilder.core.d.ts +0 -1
- package/dist/queryBuilder/queryBuilder.core.js +0 -1
- package/dist/queryBuilder/queryBuilder.factory.d.ts +0 -1
- package/dist/queryBuilder/queryBuilder.factory.js +0 -1
- package/dist/queryBuilder/queryBuilder.filter.d.ts +0 -1
- package/dist/queryBuilder/queryBuilder.filter.js +0 -1
- package/dist/queryBuilder/queryBuilder.prisma.d.ts +0 -1
- package/dist/queryBuilder/queryBuilder.prisma.js +0 -1
- package/dist/queryBuilder/queryBuilder.type.d.ts +0 -1
- package/dist/queryBuilder/queryBuilder.type.js +0 -1
- package/dist/relations/index.d.ts +0 -1
- package/dist/relations/index.js +0 -1
- package/dist/relations/relations.definition.d.ts +0 -1
- package/dist/relations/relations.definition.js +0 -1
- package/dist/repository/index.d.ts +1 -2
- package/dist/repository/index.js +0 -1
- package/dist/repository/repository.base.d.ts +27 -1
- package/dist/repository/repository.base.js +13 -2
- package/dist/repository/repository.delegate.d.ts +0 -1
- package/dist/repository/repository.delegate.js +0 -1
- package/dist/repository/repository.errors.d.ts +3 -1
- package/dist/repository/repository.errors.js +17 -2
- package/dist/seed/index.d.ts +0 -1
- package/dist/seed/index.js +0 -1
- package/dist/seed/seed.runner.d.ts +14 -12
- package/dist/seed/seed.runner.js +0 -1
- package/dist/transaction/index.d.ts +0 -1
- package/dist/transaction/index.js +0 -1
- package/dist/transaction/transaction.backoff.d.ts +0 -1
- package/dist/transaction/transaction.backoff.js +0 -1
- package/dist/transaction/transaction.core.d.ts +27 -11
- package/dist/transaction/transaction.core.js +11 -2
- package/dist/unitOfWork/index.d.ts +0 -1
- package/dist/unitOfWork/index.js +0 -1
- package/dist/unitOfWork/unitOfWork.core.d.ts +12 -11
- package/dist/unitOfWork/unitOfWork.core.js +0 -1
- 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
|
package/dist/locks/index.d.ts
CHANGED
|
@@ -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
|
package/dist/locks/index.js
CHANGED
|
@@ -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:
|
|
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:
|
|
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
|
package/dist/locks/locks.core.js
CHANGED
|
@@ -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
|
package/dist/migration/index.js
CHANGED
|
@@ -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
|
|
@@ -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
|
|
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
|
|
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 =
|
|
73
|
-
await this.
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
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
|
|
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
|
-
|
|
185
|
-
|
|
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 (!
|
|
224
|
+
if (!step)
|
|
188
225
|
break;
|
|
189
|
-
|
|
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:
|
|
20
|
+
readonly up: (database: TTransaction) => Promise<void>;
|
|
18
21
|
/**
|
|
19
22
|
* Reverts the migration.
|
|
20
23
|
*/
|
|
21
|
-
readonly down?: (database:
|
|
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
|
|
@@ -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
|
-
|
|
10
|
+
export { isDateCursorValue, keysetStrictFilter, keysetTieFilter, nextMillisecond, } from "./pagination.keysetValue.js";
|
package/dist/pagination/index.js
CHANGED
|
@@ -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
|
-
|
|
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
|
|
@@ -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
|
|
@@ -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]:
|
|
52
|
+
[previous.field]: keysetTieFilter(cursor[previous.field]),
|
|
46
53
|
}));
|
|
47
54
|
conditions.push({
|
|
48
|
-
[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
|