@classytic/mongokit 3.40.1 → 3.42.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/dist/{PaginationEngine-CfT2Cxkj.mjs → PaginationEngine-DZnkbSrr.mjs} +4 -4
- package/dist/{Repository-CYhSC9ut.mjs → Repository-DlhPbXlG.mjs} +5 -5
- package/dist/better-auth/index.mjs +1 -1
- package/dist/{create-repository-BYyWzLbt.mjs → create-repository-Bg0H5rte.mjs} +2 -2
- package/dist/index.d.mts +15 -1
- package/dist/index.mjs +7 -7
- package/dist/outbox/index.mjs +1 -1
- package/dist/pagination/PaginationEngine.mjs +1 -1
- package/dist/plugins/index.mjs +48 -17
- package/dist/sync/index.d.mts +22 -1
- package/dist/sync/index.mjs +237 -62
- package/dist/testkit/index.mjs +1 -1
- package/dist/{timestamp.plugin-zfdLYZiO.mjs → timestamp.plugin-DvZlnKEc.mjs} +1 -1
- package/dist/{transaction-BrRYtH_b.mjs → transaction-DmiB4k2P.mjs} +28 -1
- package/dist/{validation-chain.plugin-CHUHWMtk.mjs → validation-chain.plugin-D1WsGCYr.mjs} +2 -2
- package/package.json +4 -4
|
@@ -1049,11 +1049,11 @@ var PaginationEngine = class {
|
|
|
1049
1049
|
const sanitizedLimit = validateLimit(limit, this.config);
|
|
1050
1050
|
const skip = calculateSkip(sanitizedPage, sanitizedLimit);
|
|
1051
1051
|
assertOffsetWithinCap(skip, this.config.maxOffset);
|
|
1052
|
-
let query = this.Model.find(filters);
|
|
1052
|
+
let query = this.Model.find(filters).lean(lean);
|
|
1053
1053
|
if (select) query = query.select(select);
|
|
1054
1054
|
if (populate && (Array.isArray(populate) ? populate.length : populate)) query = query.populate(populate);
|
|
1055
1055
|
if (sort) query = query.sort(withIdTiebreak(sort));
|
|
1056
|
-
query = query.skip(skip).limit(sanitizedLimit + 1)
|
|
1056
|
+
query = query.skip(skip).limit(sanitizedLimit + 1);
|
|
1057
1057
|
if (collation) query = query.collation(collation);
|
|
1058
1058
|
if (session) query = query.session(session);
|
|
1059
1059
|
if (hint) query = query.hint(hint);
|
|
@@ -1206,10 +1206,10 @@ var PaginationEngine = class {
|
|
|
1206
1206
|
const scope = cursorScope(this.Model.collection.collectionName, filters, collation);
|
|
1207
1207
|
if (cursor) query = resolveCursorFilter(cursor, normalizedSort, this.config.cursorVersion, query, this.config.minCursorVersion, querySort, scope, this.config.cursorSecret);
|
|
1208
1208
|
const effectiveSelect = ensureKeysetSelectIncludesCursorFields(select, normalizedSort);
|
|
1209
|
-
let mongoQuery = this.Model.find(query);
|
|
1209
|
+
let mongoQuery = this.Model.find(query).lean(lean);
|
|
1210
1210
|
if (effectiveSelect) mongoQuery = mongoQuery.select(effectiveSelect);
|
|
1211
1211
|
if (populate && (Array.isArray(populate) ? populate.length : populate)) mongoQuery = mongoQuery.populate(populate);
|
|
1212
|
-
mongoQuery = mongoQuery.sort(querySort).limit(sanitizedLimit + 1)
|
|
1212
|
+
mongoQuery = mongoQuery.sort(querySort).limit(sanitizedLimit + 1);
|
|
1213
1213
|
if (collation) mongoQuery = mongoQuery.collation(collation);
|
|
1214
1214
|
if (session) mongoQuery = mongoQuery.session(session);
|
|
1215
1215
|
if (hint) mongoQuery = mongoQuery.hint(hint);
|
|
@@ -4,8 +4,8 @@ import { _ as SHORTHAND_OPS, a as count, b as create, c as getByQuery, d as dele
|
|
|
4
4
|
import { n as warn } from "./logger-K7dPmu2U.mjs";
|
|
5
5
|
import { n as isDuplicateKeyError, r as parseDuplicateKeyError, t as createError } from "./error-BuByZwKU.mjs";
|
|
6
6
|
import { i as applyToQuery, n as applyCursorTimeoutMode, r as applyToAggregate, u as resolveQueryOptions } from "./query-defaults-BxUcSOoF.mjs";
|
|
7
|
-
import {
|
|
8
|
-
import { _ as resolveCursorSecrets, d as withGroupTiebreak, f as withIdTiebreak, g as attachSignature, i as validateKeysetSort, l as assertOffsetWithinCap, n as getPrimaryField, o as encodeCursor, s as resolveCursorFilter, t as PaginationEngine, u as cursorScope, v as verifySignature } from "./PaginationEngine-
|
|
7
|
+
import { o as withTransaction, p as resolveMongoCapabilities, s as createTxBoundRepo } from "./transaction-DmiB4k2P.mjs";
|
|
8
|
+
import { _ as resolveCursorSecrets, d as withGroupTiebreak, f as withIdTiebreak, g as attachSignature, i as validateKeysetSort, l as assertOffsetWithinCap, n as getPrimaryField, o as encodeCursor, s as resolveCursorFilter, t as PaginationEngine, u as cursorScope, v as verifySignature } from "./PaginationEngine-DZnkbSrr.mjs";
|
|
9
9
|
import { calculateTotalPages } from "./pagination/utils/limits.mjs";
|
|
10
10
|
import { hasNearOperator, rewriteNearForCount } from "./query/primitives/geo.mjs";
|
|
11
11
|
import { a as scopeJoins, r as markGoverned } from "./join-scope-DSAznE8E.mjs";
|
|
@@ -4711,9 +4711,9 @@ var Repository = class extends RepositoryBase {
|
|
|
4711
4711
|
const appendLookupStages$2 = (pipeline) => appendLookupStages(pipeline, lookups, projection, isKeyset && sort ? this._parseSort(sort) : void 0);
|
|
4712
4712
|
if (isKeyset && sort) {
|
|
4713
4713
|
const parsedSort = this._parseSort(sort);
|
|
4714
|
-
const { validateKeysetSort } = await import("./PaginationEngine-
|
|
4715
|
-
const { encodeCursor, resolveCursorFilter } = await import("./PaginationEngine-
|
|
4716
|
-
const { getPrimaryField } = await import("./PaginationEngine-
|
|
4714
|
+
const { validateKeysetSort } = await import("./PaginationEngine-DZnkbSrr.mjs").then((n) => n.r);
|
|
4715
|
+
const { encodeCursor, resolveCursorFilter } = await import("./PaginationEngine-DZnkbSrr.mjs").then((n) => n.a);
|
|
4716
|
+
const { getPrimaryField } = await import("./PaginationEngine-DZnkbSrr.mjs").then((n) => n.r);
|
|
4717
4717
|
const normalizedSort = validateKeysetSort(parsedSort, this._pagination.config.strictKeysetSortFields);
|
|
4718
4718
|
const cursorVersion = this._pagination.config.cursorVersion ?? 1;
|
|
4719
4719
|
const minCursorVersion = this._pagination.config.minCursorVersion ?? 1;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as Repository } from "../Repository-
|
|
1
|
+
import { n as Repository } from "../Repository-DlhPbXlG.mjs";
|
|
2
2
|
import { n as createMongooseAdapter } from "../adapter-CkMoMF83.mjs";
|
|
3
3
|
import { asReadOnlyRepo } from "@classytic/repo-core/repository";
|
|
4
4
|
import { pluralizeBetterAuthCollection, resolveBetterAuthCollections } from "@classytic/repo-core/better-auth";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as Repository } from "./Repository-
|
|
2
|
-
import { b as auditLogPlugin, g as cachePlugin, i as multiTenantPlugin, l as customIdPlugin, n as softDeletePlugin, t as timestampPlugin, v as auditTrailPlugin } from "./timestamp.plugin-
|
|
1
|
+
import { n as Repository } from "./Repository-DlhPbXlG.mjs";
|
|
2
|
+
import { b as auditLogPlugin, g as cachePlugin, i as multiTenantPlugin, l as customIdPlugin, n as softDeletePlugin, t as timestampPlugin, v as auditTrailPlugin } from "./timestamp.plugin-DvZlnKEc.mjs";
|
|
3
3
|
import { n as batchOperationsPlugin, t as methodRegistryPlugin } from "./method-registry.plugin-C63pGn1d.mjs";
|
|
4
4
|
//#region src/create-repository.ts
|
|
5
5
|
function isLoggerAudit(value) {
|
package/dist/index.d.mts
CHANGED
|
@@ -782,6 +782,20 @@ interface SessionStarter {
|
|
|
782
782
|
* ```
|
|
783
783
|
*/
|
|
784
784
|
declare function withTransaction<T>(connection: SessionStarter, callback: (session: ClientSession) => Promise<T>, options?: WithTransactionOptions): Promise<T>;
|
|
785
|
+
declare const TRANSACTION_ERROR_CODES: {
|
|
786
|
+
/** The session lacks a method the transaction loop drives (a partial or wrapped fake). */
|
|
787
|
+
readonly SESSION_INCOMPLETE: "mongokit.transaction.session_incomplete";
|
|
788
|
+
};
|
|
789
|
+
/**
|
|
790
|
+
* The driver's convenient-transaction algorithm (start → callback → commit, label-based retry,
|
|
791
|
+
* jittered backoff, a deadline), run here so the driver never attaches a session `timeoutContext`:
|
|
792
|
+
* with one, every legacy bulk write (`insertMany`, `bulkWrite`) in the transaction is refused once
|
|
793
|
+
* the client carries `timeoutMS` (driver <= 7.7: the bulk path re-resolves the inherited client
|
|
794
|
+
* `timeoutMS` as a per-op one). Each operation keeps its own per-op CSOT budget instead.
|
|
795
|
+
* Deadline: `transactionOptions.timeoutMS`, else the client's `timeoutMS`, else 120 s (as the driver).
|
|
796
|
+
* Pinned by `tests/integration/csot-transaction-matrix.test.ts`.
|
|
797
|
+
*/
|
|
798
|
+
declare function runTransaction<T>(session: ClientSession, callback: (session: ClientSession) => Promise<T>, transactionOptions?: ConvenientTransactionOptions): Promise<T>;
|
|
785
799
|
/**
|
|
786
800
|
* Multi-repo transactional batch — every repo in `repos` becomes a
|
|
787
801
|
* session-bound proxy inside the callback. Eliminates the per-call
|
|
@@ -1102,4 +1116,4 @@ declare function createOptionsExtractor<TCtx extends Record<string, unknown>>(fi
|
|
|
1102
1116
|
*/
|
|
1103
1117
|
declare function systemContext(extra?: SessionOptions): SessionOptions;
|
|
1104
1118
|
//#endregion
|
|
1105
|
-
export { ALL_OPERATIONS, type AggregateCallOptions, type AggregateDefaults, type AggregateHelpersMethods, type AggregateOptions, type AggregatePaginationOptions, AggregationBuilder, type AggregationPlan, type SortOrder as AggregationSortOrder, type SortSpec as AggregationSortSpec, type AllPluginMethods, type AnyDocument, type AnyModel, type AppendOnlyPluginOptions, type AuditConfig, type AuditEntry, type AuditOperation, type AuditQueryOptions, type AuditQueryResult, type AuditTrailMethods, type AuditTrailMode, type AuditTrailOptions, AuditTrailQuery, type AuditTrailQueryOptions, type BasePaginationOptions, type BatchOperationsMethods, type BulkWriteOptions, type BulkWriteResult, type CacheAdapter, type CacheOperationOptions, type CacheOptions, type CacheableOptions, type CapabilityConnectionLike, type CapabilityProbeOptions, type CapabilityResolution, type CascadeOptions, type CascadePurgeReferencesOptions, type CascadeRelation, type CollationOptions, type CollectionRWLike, type CollectionScopeRule, type CommandKind, type ConvenientTransactionOptions, type CountMemoKey, type CountStrategy, type CreateErrorOptions, type CreateInput, type CreateManyFailure, type CreateManyPartial, type CreateManyPartialError, type CreateOptions, type CreateRepositoryConfig, type CrudSchemasFramework, type CursorPayload, type CursorSecret, type CustomIdOptions, type DateSequentialIdOptions, type DecodedCursor, type DeepPartial, type DefineModelOptions, type DeleteResult, type DocField, type ElasticSearchOptions, type EnsureAuditTrailReadyOptions, type EventHandlers, type EventPayload, type EventPhase, type ExistingModelPolicy, type FieldPreset, type FieldType, type FilterQuery, type FindOneAndUpdateOptions, type GetAllParams, type GetByIdsOptions, type GroupResult, type GroupSpec, HOOK_PRIORITY, type HookMode, type IdGenerator, type IdempotencyClaim, type IdempotencyStoreMethods, type IdempotencyStorePluginOptions, type ImmutableClaimView, type ImmutableStatesPluginOptions, type InferDocument, type InferRawDoc, JOIN_ERROR_CODES, type KeysOfType, type KeysetPaginationOptions, type KeysetSourceOptions, type LeaseMethods, type LeasePluginOptions, type Logger, type LoggerConfig, LookupBuilder, type LookupOptions, type LookupPopulateOptions, type LookupPopulateResult, MONGOKIT_CAPABILITIES, MONGOKIT_PLUGIN_NAMES, MUTATING_OPERATIONS, type Middleware, type MiddlewareContext, type MinMaxResult, type MinimalRepoView, type ModelBlueprint, ModelCollisionError, type ModelSpec, type MongoKitPluginName, type MongoOperationsMethods, type MongoOperatorUpdate, type MongoRepoCapabilities, type MongokitPageExtras, type MultiTenantOptions, type NonNullableFields, OP_REGISTRY, type ObjectId, type ObservabilityOptions, type OffsetPaginationOptions, type OperationDescriptor, type OperationMetric, type OperationOptions, type OperationType, PAGINATION_ERROR_CODES, type PaginationConfig, type PaginationDefaults, PaginationEngine, type ParseDuplicateKeyOptions, type ParsedQuery, type PartialBy, type PerCallQueryOptions, type Plugin, type PluginFunction, type PluginType, type PolicyKey, type PopulateOption, type PopulateSpec, type PrefixedIdOptions, type PrioritizedHook, type ProjectionSpec, type PurgeMode, type PurgeableRepoLike, QUERY_DEFAULTS_ERROR_CODES, type QueryDefaults, QueryParser, type QueryParserOptions, type QuerySchema, READ_OPERATIONS, type ReadConcernLevel, type ReadOptions, type ReadPreferenceType, type ReferencePurgeResult, type ReferenceRelation, type RepoScope, Repository, Repository as default, type RepositoryCacheHandle, type RepositoryCachePluginOptions, type RepositoryContext, type RepositoryEvent, type RepositoryInstance, type RepositoryOperation, type RepositoryOptions, type RepositoryPluginName, type RequiredBy, type ResolvedQueryOptions, type SchemaLike, type SearchMode, type SelectSpec, type SequentialIdOptions, type SessionOptions, type SessionStarter, type SoftDeleteFilterMode, type SoftDeleteMethods, type SoftDeleteOptions, type SoftDeleteRepository, type SortDirection, type SortSpec$1 as SortSpec, type Strict, type SubdocumentMethods, type TenantContext, type TenantStore, type TransactionSupport, type TransitionMachine, type UpdateManyResult, type UpdateOptions, type UpdatePatch, type UpdateWithValidationResult, type UserContext, type ValidationChainOptions, type ValidatorDefinition, type ValueType, type VectorSearchOptions, type WithPlugins, type WithTransactionOptions, type WriteConcernSpec, index_d_exports as actions, adminBypass, aggregateHelpersPlugin, appendOnlyPlugin, assertQueryDefaultsConfigured, auditLogPlugin, auditTrailPlugin, autoInject, batchOperationsPlugin, batchTransaction, blockIf, buildCrudSchemasFromModel, buildCrudSchemasFromMongooseSchema, cachePlugin, capabilitiesForSupport, cascadePlugin, cascadePurgeReferences, classifyHelloReply, compileFilterToMongo, configureAggregateDefaults, configureLogger, configurePaginationDefaults, configureQueryDefaults, createError, createFieldPreset, createMemoryCache, createOptionsExtractor, createRepository, createTenantContext, customIdPlugin, dateSequentialId, declareCollectionScope, declareTenantContextKey, defineModel, defineModels, elasticSearchPlugin, ensureAuditTrailReady, ensureSequenceAtLeast, fieldFilterPlugin, filterResponseData, forwardScope, getFieldsForUser, getMongooseProjection, getNextSequence, getPaginationDefaults, getQueryDefaults, idVariants, idempotencyStorePlugin, immutableField, immutableStatesPlugin, isCreateManyPartialError, isDuplicateKeyError, isModelRegistered, isTransactionUnsupported, keysetSource, leasePlugin, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, operationsByPolicyKey, parseDuplicateKeyError, prefixedId, probeMongoCapabilities, readSequence, repoOptionsFromCtx, requireField, resetCapabilityProbeCache, resetPaginationDefaults, resetQueryDefaults, resolveMongoCapabilities, resolveQueryOptions, resolveTransactionSupport, sequentialId, softDeletePlugin, subdocumentPlugin, supportsTransactions, systemContext, tenantContextKeysOf, timestampPlugin, toPlain, transactionResolutionOf, uniqueField, validationChainPlugin, withTransaction };
|
|
1119
|
+
export { ALL_OPERATIONS, type AggregateCallOptions, type AggregateDefaults, type AggregateHelpersMethods, type AggregateOptions, type AggregatePaginationOptions, AggregationBuilder, type AggregationPlan, type SortOrder as AggregationSortOrder, type SortSpec as AggregationSortSpec, type AllPluginMethods, type AnyDocument, type AnyModel, type AppendOnlyPluginOptions, type AuditConfig, type AuditEntry, type AuditOperation, type AuditQueryOptions, type AuditQueryResult, type AuditTrailMethods, type AuditTrailMode, type AuditTrailOptions, AuditTrailQuery, type AuditTrailQueryOptions, type BasePaginationOptions, type BatchOperationsMethods, type BulkWriteOptions, type BulkWriteResult, type CacheAdapter, type CacheOperationOptions, type CacheOptions, type CacheableOptions, type CapabilityConnectionLike, type CapabilityProbeOptions, type CapabilityResolution, type CascadeOptions, type CascadePurgeReferencesOptions, type CascadeRelation, type CollationOptions, type CollectionRWLike, type CollectionScopeRule, type CommandKind, type ConvenientTransactionOptions, type CountMemoKey, type CountStrategy, type CreateErrorOptions, type CreateInput, type CreateManyFailure, type CreateManyPartial, type CreateManyPartialError, type CreateOptions, type CreateRepositoryConfig, type CrudSchemasFramework, type CursorPayload, type CursorSecret, type CustomIdOptions, type DateSequentialIdOptions, type DecodedCursor, type DeepPartial, type DefineModelOptions, type DeleteResult, type DocField, type ElasticSearchOptions, type EnsureAuditTrailReadyOptions, type EventHandlers, type EventPayload, type EventPhase, type ExistingModelPolicy, type FieldPreset, type FieldType, type FilterQuery, type FindOneAndUpdateOptions, type GetAllParams, type GetByIdsOptions, type GroupResult, type GroupSpec, HOOK_PRIORITY, type HookMode, type IdGenerator, type IdempotencyClaim, type IdempotencyStoreMethods, type IdempotencyStorePluginOptions, type ImmutableClaimView, type ImmutableStatesPluginOptions, type InferDocument, type InferRawDoc, JOIN_ERROR_CODES, type KeysOfType, type KeysetPaginationOptions, type KeysetSourceOptions, type LeaseMethods, type LeasePluginOptions, type Logger, type LoggerConfig, LookupBuilder, type LookupOptions, type LookupPopulateOptions, type LookupPopulateResult, MONGOKIT_CAPABILITIES, MONGOKIT_PLUGIN_NAMES, MUTATING_OPERATIONS, type Middleware, type MiddlewareContext, type MinMaxResult, type MinimalRepoView, type ModelBlueprint, ModelCollisionError, type ModelSpec, type MongoKitPluginName, type MongoOperationsMethods, type MongoOperatorUpdate, type MongoRepoCapabilities, type MongokitPageExtras, type MultiTenantOptions, type NonNullableFields, OP_REGISTRY, type ObjectId, type ObservabilityOptions, type OffsetPaginationOptions, type OperationDescriptor, type OperationMetric, type OperationOptions, type OperationType, PAGINATION_ERROR_CODES, type PaginationConfig, type PaginationDefaults, PaginationEngine, type ParseDuplicateKeyOptions, type ParsedQuery, type PartialBy, type PerCallQueryOptions, type Plugin, type PluginFunction, type PluginType, type PolicyKey, type PopulateOption, type PopulateSpec, type PrefixedIdOptions, type PrioritizedHook, type ProjectionSpec, type PurgeMode, type PurgeableRepoLike, QUERY_DEFAULTS_ERROR_CODES, type QueryDefaults, QueryParser, type QueryParserOptions, type QuerySchema, READ_OPERATIONS, type ReadConcernLevel, type ReadOptions, type ReadPreferenceType, type ReferencePurgeResult, type ReferenceRelation, type RepoScope, Repository, Repository as default, type RepositoryCacheHandle, type RepositoryCachePluginOptions, type RepositoryContext, type RepositoryEvent, type RepositoryInstance, type RepositoryOperation, type RepositoryOptions, type RepositoryPluginName, type RequiredBy, type ResolvedQueryOptions, type SchemaLike, type SearchMode, type SelectSpec, type SequentialIdOptions, type SessionOptions, type SessionStarter, type SoftDeleteFilterMode, type SoftDeleteMethods, type SoftDeleteOptions, type SoftDeleteRepository, type SortDirection, type SortSpec$1 as SortSpec, type Strict, type SubdocumentMethods, TRANSACTION_ERROR_CODES, type TenantContext, type TenantStore, type TransactionSupport, type TransitionMachine, type UpdateManyResult, type UpdateOptions, type UpdatePatch, type UpdateWithValidationResult, type UserContext, type ValidationChainOptions, type ValidatorDefinition, type ValueType, type VectorSearchOptions, type WithPlugins, type WithTransactionOptions, type WriteConcernSpec, index_d_exports as actions, adminBypass, aggregateHelpersPlugin, appendOnlyPlugin, assertQueryDefaultsConfigured, auditLogPlugin, auditTrailPlugin, autoInject, batchOperationsPlugin, batchTransaction, blockIf, buildCrudSchemasFromModel, buildCrudSchemasFromMongooseSchema, cachePlugin, capabilitiesForSupport, cascadePlugin, cascadePurgeReferences, classifyHelloReply, compileFilterToMongo, configureAggregateDefaults, configureLogger, configurePaginationDefaults, configureQueryDefaults, createError, createFieldPreset, createMemoryCache, createOptionsExtractor, createRepository, createTenantContext, customIdPlugin, dateSequentialId, declareCollectionScope, declareTenantContextKey, defineModel, defineModels, elasticSearchPlugin, ensureAuditTrailReady, ensureSequenceAtLeast, fieldFilterPlugin, filterResponseData, forwardScope, getFieldsForUser, getMongooseProjection, getNextSequence, getPaginationDefaults, getQueryDefaults, idVariants, idempotencyStorePlugin, immutableField, immutableStatesPlugin, isCreateManyPartialError, isDuplicateKeyError, isModelRegistered, isTransactionUnsupported, keysetSource, leasePlugin, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, operationsByPolicyKey, parseDuplicateKeyError, prefixedId, probeMongoCapabilities, readSequence, repoOptionsFromCtx, requireField, resetCapabilityProbeCache, resetPaginationDefaults, resetQueryDefaults, resolveMongoCapabilities, resolveQueryOptions, resolveTransactionSupport, runTransaction, sequentialId, softDeletePlugin, subdocumentPlugin, supportsTransactions, systemContext, tenantContextKeysOf, timestampPlugin, toPlain, transactionResolutionOf, uniqueField, validationChainPlugin, withTransaction };
|
package/dist/index.mjs
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { n as idVariants } from "./id-resolution-BqDrk0S2.mjs";
|
|
2
|
-
import { a as MUTATING_OPERATIONS, c as operationsByPolicyKey, i as ALL_OPERATIONS, l as createMongoPurgePort, n as Repository, o as OP_REGISTRY, r as AggregationBuilder, s as READ_OPERATIONS, t as HOOK_PRIORITY } from "./Repository-
|
|
2
|
+
import { a as MUTATING_OPERATIONS, c as operationsByPolicyKey, i as ALL_OPERATIONS, l as createMongoPurgePort, n as Repository, o as OP_REGISTRY, r as AggregationBuilder, s as READ_OPERATIONS, t as HOOK_PRIORITY } from "./Repository-DlhPbXlG.mjs";
|
|
3
3
|
import { C as isCreateManyPartialError, g as LookupBuilder, v as compileFilterToMongo } from "./update-WgeAUJ_I.mjs";
|
|
4
4
|
import { n as warn, t as configureLogger } from "./logger-K7dPmu2U.mjs";
|
|
5
5
|
import { n as isDuplicateKeyError, r as parseDuplicateKeyError, t as createError } from "./error-BuByZwKU.mjs";
|
|
6
6
|
import { a as assertQueryDefaultsConfigured, c as getQueryDefaults, l as resetQueryDefaults, o as configureAggregateDefaults, s as configureQueryDefaults, t as QUERY_DEFAULTS_ERROR_CODES, u as resolveQueryOptions } from "./query-defaults-BxUcSOoF.mjs";
|
|
7
7
|
import { t as actions_exports } from "./actions/index.mjs";
|
|
8
|
-
import { c as
|
|
9
|
-
import { _ as AuditTrailQuery, a as declareTenantContextKey, b as auditLogPlugin, c as tenantContextKeysOf, d as ensureSequenceAtLeast, f as getNextSequence, g as cachePlugin, h as sequentialId, i as multiTenantPlugin, l as customIdPlugin, m as readSequence, n as softDeletePlugin, o as forwardScope, p as prefixedId, r as adminBypass, s as isScopeKey, t as timestampPlugin, u as dateSequentialId, v as auditTrailPlugin, y as ensureAuditTrailReady } from "./timestamp.plugin-
|
|
8
|
+
import { a as supportsTransactions, c as MONGOKIT_CAPABILITIES, d as probeMongoCapabilities, f as resetCapabilityProbeCache, h as transactionResolutionOf, i as runTransaction, l as capabilitiesForSupport, m as resolveTransactionSupport, n as batchTransaction, o as withTransaction, p as resolveMongoCapabilities, r as isTransactionUnsupported, t as TRANSACTION_ERROR_CODES, u as classifyHelloReply } from "./transaction-DmiB4k2P.mjs";
|
|
9
|
+
import { _ as AuditTrailQuery, a as declareTenantContextKey, b as auditLogPlugin, c as tenantContextKeysOf, d as ensureSequenceAtLeast, f as getNextSequence, g as cachePlugin, h as sequentialId, i as multiTenantPlugin, l as customIdPlugin, m as readSequence, n as softDeletePlugin, o as forwardScope, p as prefixedId, r as adminBypass, s as isScopeKey, t as timestampPlugin, u as dateSequentialId, v as auditTrailPlugin, y as ensureAuditTrailReady } from "./timestamp.plugin-DvZlnKEc.mjs";
|
|
10
10
|
import { n as batchOperationsPlugin, t as methodRegistryPlugin } from "./method-registry.plugin-C63pGn1d.mjs";
|
|
11
|
-
import { c as PAGINATION_ERROR_CODES, h as resetPaginationDefaults, m as getPaginationDefaults, p as configurePaginationDefaults, t as PaginationEngine } from "./PaginationEngine-
|
|
11
|
+
import { c as PAGINATION_ERROR_CODES, h as resetPaginationDefaults, m as getPaginationDefaults, p as configurePaginationDefaults, t as PaginationEngine } from "./PaginationEngine-DZnkbSrr.mjs";
|
|
12
12
|
import { GEO_OPERATORS, parseGeoFilter } from "./query/primitives/geo.mjs";
|
|
13
13
|
import { n as declareCollectionScope, t as JOIN_ERROR_CODES } from "./join-scope-DSAznE8E.mjs";
|
|
14
|
-
import { t as createRepository } from "./create-repository-
|
|
14
|
+
import { t as createRepository } from "./create-repository-Bg0H5rte.mjs";
|
|
15
15
|
import { n as defineModel, r as isModelRegistered, t as ModelCollisionError } from "./model-registry-ClKtWiHa.mjs";
|
|
16
|
-
import { _ as cascadePlugin, a as uniqueField, c as subdocumentPlugin, d as mongoOperationsPlugin, f as leasePlugin, g as elasticSearchPlugin, h as fieldFilterPlugin, i as requireField, l as observabilityPlugin, m as idempotencyStorePlugin, n as blockIf, o as validationChainPlugin, p as immutableStatesPlugin, r as immutableField, s as createTenantContext, t as autoInject, u as MONGOKIT_PLUGIN_NAMES, v as appendOnlyPlugin, y as aggregateHelpersPlugin } from "./validation-chain.plugin-
|
|
16
|
+
import { _ as cascadePlugin, a as uniqueField, c as subdocumentPlugin, d as mongoOperationsPlugin, f as leasePlugin, g as elasticSearchPlugin, h as fieldFilterPlugin, i as requireField, l as observabilityPlugin, m as idempotencyStorePlugin, n as blockIf, o as validationChainPlugin, p as immutableStatesPlugin, r as immutableField, s as createTenantContext, t as autoInject, u as MONGOKIT_PLUGIN_NAMES, v as appendOnlyPlugin, y as aggregateHelpersPlugin } from "./validation-chain.plugin-D1WsGCYr.mjs";
|
|
17
17
|
import { i as getMongooseProjection, n as filterResponseData, r as getFieldsForUser, t as createFieldPreset } from "./field-selection-FSQFLpsU.mjs";
|
|
18
18
|
import { buildFieldTypeMap, coerceHeuristic } from "./query/primitives/coercion.mjs";
|
|
19
19
|
import { extractSchemaIndexes } from "./query/primitives/indexes.mjs";
|
|
@@ -1437,4 +1437,4 @@ function systemContext(extra) {
|
|
|
1437
1437
|
*/
|
|
1438
1438
|
var src_default = Repository;
|
|
1439
1439
|
//#endregion
|
|
1440
|
-
export { ALL_OPERATIONS, AggregationBuilder, AuditTrailQuery, HOOK_PRIORITY, JOIN_ERROR_CODES, LookupBuilder, MONGOKIT_CAPABILITIES, MONGOKIT_PLUGIN_NAMES, MUTATING_OPERATIONS, ModelCollisionError, OP_REGISTRY, PAGINATION_ERROR_CODES, PaginationEngine, QUERY_DEFAULTS_ERROR_CODES, QueryParser, READ_OPERATIONS, Repository, actions_exports as actions, adminBypass, aggregateHelpersPlugin, appendOnlyPlugin, assertQueryDefaultsConfigured, auditLogPlugin, auditTrailPlugin, autoInject, batchOperationsPlugin, batchTransaction, blockIf, buildCrudSchemasFromModel, buildCrudSchemasFromMongooseSchema, cachePlugin, capabilitiesForSupport, cascadePlugin, cascadePurgeReferences, classifyHelloReply, compileFilterToMongo, configureAggregateDefaults, configureLogger, configurePaginationDefaults, configureQueryDefaults, createError, createFieldPreset, createMemoryCache, createOptionsExtractor, createRepository, createTenantContext, customIdPlugin, dateSequentialId, declareCollectionScope, declareTenantContextKey, src_default as default, defineModel, defineModels, elasticSearchPlugin, ensureAuditTrailReady, ensureSequenceAtLeast, fieldFilterPlugin, filterResponseData, forwardScope, getFieldsForUser, getMongooseProjection, getNextSequence, getPaginationDefaults, getQueryDefaults, idVariants, idempotencyStorePlugin, immutableField, immutableStatesPlugin, isCreateManyPartialError, isDuplicateKeyError, isModelRegistered, isTransactionUnsupported, keysetSource, leasePlugin, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, operationsByPolicyKey, parseDuplicateKeyError, prefixedId, probeMongoCapabilities, readSequence, repoOptionsFromCtx, requireField, resetCapabilityProbeCache, resetPaginationDefaults, resetQueryDefaults, resolveMongoCapabilities, resolveQueryOptions, resolveTransactionSupport, sequentialId, softDeletePlugin, subdocumentPlugin, supportsTransactions, systemContext, tenantContextKeysOf, timestampPlugin, toPlain, transactionResolutionOf, uniqueField, validationChainPlugin, withTransaction };
|
|
1440
|
+
export { ALL_OPERATIONS, AggregationBuilder, AuditTrailQuery, HOOK_PRIORITY, JOIN_ERROR_CODES, LookupBuilder, MONGOKIT_CAPABILITIES, MONGOKIT_PLUGIN_NAMES, MUTATING_OPERATIONS, ModelCollisionError, OP_REGISTRY, PAGINATION_ERROR_CODES, PaginationEngine, QUERY_DEFAULTS_ERROR_CODES, QueryParser, READ_OPERATIONS, Repository, TRANSACTION_ERROR_CODES, actions_exports as actions, adminBypass, aggregateHelpersPlugin, appendOnlyPlugin, assertQueryDefaultsConfigured, auditLogPlugin, auditTrailPlugin, autoInject, batchOperationsPlugin, batchTransaction, blockIf, buildCrudSchemasFromModel, buildCrudSchemasFromMongooseSchema, cachePlugin, capabilitiesForSupport, cascadePlugin, cascadePurgeReferences, classifyHelloReply, compileFilterToMongo, configureAggregateDefaults, configureLogger, configurePaginationDefaults, configureQueryDefaults, createError, createFieldPreset, createMemoryCache, createOptionsExtractor, createRepository, createTenantContext, customIdPlugin, dateSequentialId, declareCollectionScope, declareTenantContextKey, src_default as default, defineModel, defineModels, elasticSearchPlugin, ensureAuditTrailReady, ensureSequenceAtLeast, fieldFilterPlugin, filterResponseData, forwardScope, getFieldsForUser, getMongooseProjection, getNextSequence, getPaginationDefaults, getQueryDefaults, idVariants, idempotencyStorePlugin, immutableField, immutableStatesPlugin, isCreateManyPartialError, isDuplicateKeyError, isModelRegistered, isTransactionUnsupported, keysetSource, leasePlugin, methodRegistryPlugin, mongoOperationsPlugin, multiTenantPlugin, observabilityPlugin, operationsByPolicyKey, parseDuplicateKeyError, prefixedId, probeMongoCapabilities, readSequence, repoOptionsFromCtx, requireField, resetCapabilityProbeCache, resetPaginationDefaults, resetQueryDefaults, resolveMongoCapabilities, resolveQueryOptions, resolveTransactionSupport, runTransaction, sequentialId, softDeletePlugin, subdocumentPlugin, supportsTransactions, systemContext, tenantContextKeysOf, timestampPlugin, toPlain, transactionResolutionOf, uniqueField, validationChainPlugin, withTransaction };
|
package/dist/outbox/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as Repository } from "../Repository-
|
|
1
|
+
import { n as Repository } from "../Repository-DlhPbXlG.mjs";
|
|
2
2
|
import { n as batchOperationsPlugin, t as methodRegistryPlugin } from "../method-registry.plugin-C63pGn1d.mjs";
|
|
3
3
|
import { Schema } from "mongoose";
|
|
4
4
|
//#region src/outbox/index.ts
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as PaginationEngine } from "../PaginationEngine-
|
|
1
|
+
import { t as PaginationEngine } from "../PaginationEngine-DZnkbSrr.mjs";
|
|
2
2
|
export { PaginationEngine };
|
package/dist/plugins/index.mjs
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import { _ as AuditTrailQuery, b as auditLogPlugin, f as getNextSequence, g as cachePlugin, h as sequentialId, i as multiTenantPlugin, l as customIdPlugin, n as softDeletePlugin, p as prefixedId, t as timestampPlugin, u as dateSequentialId, v as auditTrailPlugin, y as ensureAuditTrailReady } from "../timestamp.plugin-
|
|
1
|
+
import { _ as AuditTrailQuery, b as auditLogPlugin, f as getNextSequence, g as cachePlugin, h as sequentialId, i as multiTenantPlugin, l as customIdPlugin, n as softDeletePlugin, p as prefixedId, t as timestampPlugin, u as dateSequentialId, v as auditTrailPlugin, y as ensureAuditTrailReady } from "../timestamp.plugin-DvZlnKEc.mjs";
|
|
2
2
|
import { n as batchOperationsPlugin, t as methodRegistryPlugin } from "../method-registry.plugin-C63pGn1d.mjs";
|
|
3
|
-
import { _ as cascadePlugin, a as uniqueField, c as subdocumentPlugin, d as mongoOperationsPlugin, f as leasePlugin, g as elasticSearchPlugin, h as fieldFilterPlugin, i as requireField, l as observabilityPlugin, m as idempotencyStorePlugin, n as blockIf, o as validationChainPlugin, p as immutableStatesPlugin, r as immutableField, s as createTenantContext, t as autoInject, u as MONGOKIT_PLUGIN_NAMES, v as appendOnlyPlugin, y as aggregateHelpersPlugin } from "../validation-chain.plugin-
|
|
3
|
+
import { _ as cascadePlugin, a as uniqueField, c as subdocumentPlugin, d as mongoOperationsPlugin, f as leasePlugin, g as elasticSearchPlugin, h as fieldFilterPlugin, i as requireField, l as observabilityPlugin, m as idempotencyStorePlugin, n as blockIf, o as validationChainPlugin, p as immutableStatesPlugin, r as immutableField, s as createTenantContext, t as autoInject, u as MONGOKIT_PLUGIN_NAMES, v as appendOnlyPlugin, y as aggregateHelpersPlugin } from "../validation-chain.plugin-D1WsGCYr.mjs";
|
|
4
4
|
//#region src/plugins/change-log.plugin.ts
|
|
5
5
|
const PLUGIN_NAME = "changeLog";
|
|
6
6
|
/** Marks a repository already captured: the store and scope it writes to. */
|
|
7
7
|
const CAPTURED = Symbol.for("mongokit.changeLog.capture");
|
|
8
8
|
/** Where `before:updateMany` / `before:deleteMany` leave the ids they matched for the after hook. */
|
|
9
9
|
const MATCHED_IDS = Symbol("changeLog.matchedIds");
|
|
10
|
+
/** Ids per `$in` when a many-document write is read back. */
|
|
11
|
+
const READ_BACK_CHUNK = 5e3;
|
|
10
12
|
function isSkipped(context) {
|
|
11
13
|
const list = context.skipPlugins;
|
|
12
14
|
return Array.isArray(list) && list.includes(PLUGIN_NAME);
|
|
@@ -29,29 +31,34 @@ function changeLogPlugin(options) {
|
|
|
29
31
|
return raw === void 0 || raw === null ? void 0 : String(raw);
|
|
30
32
|
};
|
|
31
33
|
const appendOptions = (context) => context.session !== void 0 ? { session: context.session } : void 0;
|
|
34
|
+
/** `stage` when the store offers it (no cursor wait under deferred sequencing); the contract's `append` otherwise. */
|
|
35
|
+
const recordChange = (entry, context) => {
|
|
36
|
+
const staging = store.stage;
|
|
37
|
+
return staging ? staging.call(store, entry, appendOptions(context)) : store.append(entry, appendOptions(context));
|
|
38
|
+
};
|
|
32
39
|
const upsert = async (doc, context) => {
|
|
33
40
|
const record = toRecord(doc);
|
|
34
41
|
if (!record || record._id === void 0) return;
|
|
35
42
|
const tenantId = tenantOf(record, context);
|
|
36
|
-
await
|
|
43
|
+
await recordChange({
|
|
37
44
|
scope,
|
|
38
45
|
docId: String(record._id),
|
|
39
46
|
op: "upsert",
|
|
40
47
|
version: versionOf(record),
|
|
41
48
|
doc: project ? project(record) : record,
|
|
42
49
|
...tenantId !== void 0 ? { tenantId } : {}
|
|
43
|
-
},
|
|
50
|
+
}, context);
|
|
44
51
|
};
|
|
45
52
|
const tombstone = async (docId, context) => {
|
|
46
53
|
if (docId === void 0 || docId === null) return;
|
|
47
54
|
const tenantId = tenantOf(null, context);
|
|
48
|
-
await
|
|
55
|
+
await recordChange({
|
|
49
56
|
scope,
|
|
50
57
|
docId: String(docId),
|
|
51
58
|
op: "delete",
|
|
52
59
|
version: 0,
|
|
53
60
|
...tenantId !== void 0 ? { tenantId } : {}
|
|
54
|
-
},
|
|
61
|
+
}, context);
|
|
55
62
|
};
|
|
56
63
|
return {
|
|
57
64
|
name: PLUGIN_NAME,
|
|
@@ -72,6 +79,22 @@ function changeLogPlugin(options) {
|
|
|
72
79
|
if (context.session !== void 0) query.session(context.session);
|
|
73
80
|
return query.exec();
|
|
74
81
|
};
|
|
82
|
+
/** A write's result is the feed row only when it is the whole post-image, as a plain object. */
|
|
83
|
+
const isWholePostImage = (result, context) => {
|
|
84
|
+
if (!result || typeof result !== "object") return false;
|
|
85
|
+
if (typeof result.toObject === "function") return false;
|
|
86
|
+
const c = context;
|
|
87
|
+
return !c.select && !c.projection && !c.populate && c.returnDocument !== "before";
|
|
88
|
+
};
|
|
89
|
+
/** `upsert` from the result the write returned; a narrowed result is re-read by id (one read, that verb only). */
|
|
90
|
+
const captureResult = async (result, context) => {
|
|
91
|
+
const id = toRecord(result)?._id;
|
|
92
|
+
if (id === void 0) return;
|
|
93
|
+
if (isWholePostImage(result, context)) return upsert(result, context);
|
|
94
|
+
const doc = await reread(id, context);
|
|
95
|
+
if (doc) await upsert(doc, context);
|
|
96
|
+
else await tombstone(id, context);
|
|
97
|
+
};
|
|
75
98
|
const matchingIds = async (context, filter) => {
|
|
76
99
|
const query = repo.Model.find(filter ?? {}).select({ _id: 1 }).lean();
|
|
77
100
|
if (context.session !== void 0) query.session(context.session);
|
|
@@ -85,29 +108,37 @@ function changeLogPlugin(options) {
|
|
|
85
108
|
for (const doc of result) await upsert(doc, context);
|
|
86
109
|
});
|
|
87
110
|
repo.on("after:update", async ({ context, result }) => {
|
|
88
|
-
if (
|
|
111
|
+
if (isSkipped(context) || !result) return;
|
|
112
|
+
const c = context;
|
|
113
|
+
if (c.select || c.projection || c.populate) await captureResult(result, context);
|
|
114
|
+
else await upsert(result, context);
|
|
115
|
+
});
|
|
116
|
+
repo.on("after:getOrCreate", async ({ context, result }) => {
|
|
117
|
+
const doc = result?.doc;
|
|
118
|
+
if (!isSkipped(context) && doc) await upsert(doc, context);
|
|
89
119
|
});
|
|
90
120
|
for (const op of [
|
|
91
121
|
"claim",
|
|
92
122
|
"claimVersion",
|
|
93
123
|
"findOneAndUpdate",
|
|
94
|
-
"getOrCreate",
|
|
95
124
|
"restore"
|
|
96
125
|
]) repo.on(`after:${op}`, async ({ context, result }) => {
|
|
97
|
-
if (isSkipped(context))
|
|
98
|
-
const id = toRecord(result)?._id;
|
|
99
|
-
if (id === void 0) return;
|
|
100
|
-
const doc = await reread(id, context);
|
|
101
|
-
if (doc) await upsert(doc, context);
|
|
102
|
-
else await tombstone(id, context);
|
|
126
|
+
if (!isSkipped(context)) await captureResult(result, context);
|
|
103
127
|
});
|
|
104
128
|
for (const op of ["updateMany", "deleteMany"]) repo.on(`before:${op}`, async (context) => {
|
|
105
129
|
if (!isSkipped(context)) context[MATCHED_IDS] = await matchingIds(context, context.query);
|
|
106
130
|
});
|
|
107
|
-
/** Each
|
|
131
|
+
/** Each target as an upsert, or a tombstone where it is gone — read back in batches, not one query per id. */
|
|
108
132
|
const capture = async (ids, context) => {
|
|
109
|
-
|
|
110
|
-
|
|
133
|
+
const wanted = ids.filter((id) => id !== void 0 && id !== null);
|
|
134
|
+
const found = /* @__PURE__ */ new Map();
|
|
135
|
+
for (let i = 0; i < wanted.length; i += READ_BACK_CHUNK) {
|
|
136
|
+
const query = repo.Model.find({ _id: { $in: wanted.slice(i, i + READ_BACK_CHUNK) } }).lean();
|
|
137
|
+
if (context.session !== void 0) query.session(context.session);
|
|
138
|
+
for (const doc of await query.exec()) found.set(String(doc._id), doc);
|
|
139
|
+
}
|
|
140
|
+
for (const id of wanted) {
|
|
141
|
+
const doc = found.get(String(id));
|
|
111
142
|
if (doc) await upsert(doc, context);
|
|
112
143
|
else await tombstone(id, context);
|
|
113
144
|
}
|
package/dist/sync/index.d.mts
CHANGED
|
@@ -1,15 +1,26 @@
|
|
|
1
1
|
import { ClientSession, Connection, Model } from "mongoose";
|
|
2
|
-
import { ChangeLogStore, CommandStreamStore, CommandStreamTx } from "@classytic/repo-core/sync";
|
|
2
|
+
import { ChangeLogAppendOptions, ChangeLogStore, CommandStreamStore, CommandStreamTx } from "@classytic/repo-core/sync";
|
|
3
3
|
//#region src/sync/index.d.ts
|
|
4
4
|
interface ChangeLogModelOptions {
|
|
5
5
|
/** Entries collection. Default `sync_changes`; its counter lives in `<collection>_counter`. */
|
|
6
6
|
collection?: string;
|
|
7
7
|
/** Mongoose model name prefix. Default `SyncChange`. Must be unique per connection. */
|
|
8
8
|
modelName?: string;
|
|
9
|
+
/**
|
|
10
|
+
* When an entry gets its cursor. `'in-transaction'` (default): from the counter, inside the writer's transaction —
|
|
11
|
+
* every writer serialises on that one document and overlapping transactions abort and retry. `'deferred'`: the
|
|
12
|
+
* writer stages the entry (`<collection>_pending`, no counter); a single leased sequencer numbers COMMITTED
|
|
13
|
+
* entries before every read. A cursor is only ever given to a committed entry and is above every cursor given
|
|
14
|
+
* before, so no reader can checkpoint past an entry that appears later.
|
|
15
|
+
*/
|
|
16
|
+
sequencing?: 'in-transaction' | 'deferred';
|
|
9
17
|
}
|
|
10
18
|
interface ChangeLogModels {
|
|
11
19
|
entries: Model<Record<string, unknown>>;
|
|
12
20
|
counter: Model<Record<string, unknown>>;
|
|
21
|
+
/** Staged, not-yet-numbered entries — present only under `sequencing: 'deferred'`. */
|
|
22
|
+
pending?: Model<Record<string, unknown>>;
|
|
23
|
+
sequencing: 'in-transaction' | 'deferred';
|
|
13
24
|
/** The counter document's id (one feed per entries collection). */
|
|
14
25
|
feed: string;
|
|
15
26
|
}
|
|
@@ -26,6 +37,16 @@ interface MongoChangeLogStore extends ChangeLogStore {
|
|
|
26
37
|
}): Promise<{
|
|
27
38
|
removed: number;
|
|
28
39
|
}>;
|
|
40
|
+
/**
|
|
41
|
+
* Number every staged entry (deferred sequencing; a no-op otherwise). Reads call it first; a scheduler may too.
|
|
42
|
+
* Returns how many it numbered, or `null` when another sequencer holds the lease.
|
|
43
|
+
*/
|
|
44
|
+
sequencePending(): Promise<number | null>;
|
|
45
|
+
/**
|
|
46
|
+
* Record a change WITHOUT waiting for its cursor (deferred sequencing): the next read numbers it. For writers that
|
|
47
|
+
* never use the cursor (`changeLogPlugin`). Under in-transaction sequencing it is `append`.
|
|
48
|
+
*/
|
|
49
|
+
stage(entry: Parameters<ChangeLogStore['append']>[0], options?: ChangeLogAppendOptions): Promise<void>;
|
|
29
50
|
}
|
|
30
51
|
declare function createChangeLogStore(models: ChangeLogModels): MongoChangeLogStore;
|
|
31
52
|
interface CommandStreamModelOptions {
|
package/dist/sync/index.mjs
CHANGED
|
@@ -1,77 +1,133 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Schema } from "mongoose";
|
|
1
|
+
import { o as withTransaction } from "../transaction-DmiB4k2P.mjs";
|
|
2
|
+
import { Schema, Types } from "mongoose";
|
|
3
3
|
//#region src/sync/index.ts
|
|
4
4
|
function createChangeLogModels(connection, options = {}) {
|
|
5
|
-
const { collection = "sync_changes", modelName = "SyncChange" } = options;
|
|
5
|
+
const { collection = "sync_changes", modelName = "SyncChange", sequencing = "in-transaction" } = options;
|
|
6
6
|
const entriesName = modelName;
|
|
7
7
|
const counterName = `${modelName}Counter`;
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
scope: {
|
|
16
|
-
type: String,
|
|
17
|
-
required: true
|
|
18
|
-
},
|
|
19
|
-
docId: {
|
|
20
|
-
type: String,
|
|
21
|
-
required: true
|
|
22
|
-
},
|
|
23
|
-
op: {
|
|
24
|
-
type: String,
|
|
25
|
-
enum: ["upsert", "delete"],
|
|
26
|
-
required: true
|
|
27
|
-
},
|
|
28
|
-
version: {
|
|
29
|
-
type: Number,
|
|
30
|
-
required: true
|
|
31
|
-
},
|
|
32
|
-
doc: { type: Schema.Types.Mixed },
|
|
33
|
-
tenantId: { type: String },
|
|
34
|
-
at: {
|
|
35
|
-
type: Date,
|
|
36
|
-
required: true
|
|
37
|
-
}
|
|
38
|
-
}, {
|
|
39
|
-
collection,
|
|
40
|
-
versionKey: false,
|
|
41
|
-
minimize: false
|
|
42
|
-
});
|
|
43
|
-
schema.index({ seq: 1 }, {
|
|
44
|
-
unique: true,
|
|
45
|
-
name: "feed_order"
|
|
46
|
-
});
|
|
47
|
-
schema.index({
|
|
48
|
-
tenantId: 1,
|
|
49
|
-
scope: 1,
|
|
50
|
-
seq: 1
|
|
51
|
-
}, { name: "tenant_scope_feed" });
|
|
52
|
-
schema.index({
|
|
53
|
-
scope: 1,
|
|
54
|
-
docId: 1,
|
|
55
|
-
seq: 1
|
|
56
|
-
}, { name: "doc_versions" });
|
|
57
|
-
return schema;
|
|
58
|
-
})()),
|
|
59
|
-
counter: connection.models[counterName] ?? connection.model(counterName, new Schema({
|
|
60
|
-
_id: {
|
|
8
|
+
const entries = connection.models[entriesName] ?? connection.model(entriesName, (() => {
|
|
9
|
+
const schema = new Schema({
|
|
10
|
+
seq: {
|
|
11
|
+
type: Number,
|
|
12
|
+
required: true
|
|
13
|
+
},
|
|
14
|
+
scope: {
|
|
61
15
|
type: String,
|
|
62
16
|
required: true
|
|
63
17
|
},
|
|
64
|
-
|
|
18
|
+
docId: {
|
|
19
|
+
type: String,
|
|
20
|
+
required: true
|
|
21
|
+
},
|
|
22
|
+
op: {
|
|
23
|
+
type: String,
|
|
24
|
+
enum: ["upsert", "delete"],
|
|
25
|
+
required: true
|
|
26
|
+
},
|
|
27
|
+
version: {
|
|
65
28
|
type: Number,
|
|
66
29
|
required: true
|
|
67
|
-
}
|
|
30
|
+
},
|
|
31
|
+
doc: { type: Schema.Types.Mixed },
|
|
32
|
+
tenantId: { type: String },
|
|
33
|
+
at: {
|
|
34
|
+
type: Date,
|
|
35
|
+
required: true
|
|
36
|
+
},
|
|
37
|
+
/** The staged row this entry was numbered from (deferred sequencing) — the sequencer's idempotency key. */
|
|
38
|
+
pendingId: { type: String }
|
|
68
39
|
}, {
|
|
69
|
-
collection
|
|
70
|
-
versionKey: false
|
|
71
|
-
|
|
40
|
+
collection,
|
|
41
|
+
versionKey: false,
|
|
42
|
+
minimize: false
|
|
43
|
+
});
|
|
44
|
+
schema.index({ seq: 1 }, {
|
|
45
|
+
unique: true,
|
|
46
|
+
name: "feed_order"
|
|
47
|
+
});
|
|
48
|
+
schema.index({ pendingId: 1 }, {
|
|
49
|
+
unique: true,
|
|
50
|
+
name: "sequenced_from",
|
|
51
|
+
partialFilterExpression: { pendingId: { $gte: "" } }
|
|
52
|
+
});
|
|
53
|
+
schema.index({
|
|
54
|
+
tenantId: 1,
|
|
55
|
+
scope: 1,
|
|
56
|
+
seq: 1
|
|
57
|
+
}, { name: "tenant_scope_feed" });
|
|
58
|
+
schema.index({
|
|
59
|
+
scope: 1,
|
|
60
|
+
docId: 1,
|
|
61
|
+
seq: 1
|
|
62
|
+
}, { name: "doc_versions" });
|
|
63
|
+
return schema;
|
|
64
|
+
})());
|
|
65
|
+
const counter = connection.models[counterName] ?? connection.model(counterName, new Schema({
|
|
66
|
+
_id: {
|
|
67
|
+
type: String,
|
|
68
|
+
required: true
|
|
69
|
+
},
|
|
70
|
+
seq: {
|
|
71
|
+
type: Number,
|
|
72
|
+
required: true
|
|
73
|
+
},
|
|
74
|
+
/** The deferred sequencer's lease. */
|
|
75
|
+
lockUntil: { type: Date },
|
|
76
|
+
lockBy: { type: String }
|
|
77
|
+
}, {
|
|
78
|
+
collection: `${collection}_counter`,
|
|
79
|
+
versionKey: false
|
|
80
|
+
}));
|
|
81
|
+
const pendingName = `${modelName}Pending`;
|
|
82
|
+
const pending = sequencing === "deferred" ? connection.models[pendingName] ?? connection.model(pendingName, new Schema({
|
|
83
|
+
scope: {
|
|
84
|
+
type: String,
|
|
85
|
+
required: true
|
|
86
|
+
},
|
|
87
|
+
docId: {
|
|
88
|
+
type: String,
|
|
89
|
+
required: true
|
|
90
|
+
},
|
|
91
|
+
op: {
|
|
92
|
+
type: String,
|
|
93
|
+
enum: ["upsert", "delete"],
|
|
94
|
+
required: true
|
|
95
|
+
},
|
|
96
|
+
version: {
|
|
97
|
+
type: Number,
|
|
98
|
+
required: true
|
|
99
|
+
},
|
|
100
|
+
doc: { type: Schema.Types.Mixed },
|
|
101
|
+
tenantId: { type: String },
|
|
102
|
+
at: {
|
|
103
|
+
type: Date,
|
|
104
|
+
required: true
|
|
105
|
+
}
|
|
106
|
+
}, {
|
|
107
|
+
collection: `${collection}_pending`,
|
|
108
|
+
versionKey: false,
|
|
109
|
+
minimize: false
|
|
110
|
+
})) : void 0;
|
|
111
|
+
return {
|
|
112
|
+
entries,
|
|
113
|
+
counter,
|
|
114
|
+
...pending ? { pending } : {},
|
|
115
|
+
sequencing,
|
|
72
116
|
feed: collection
|
|
73
117
|
};
|
|
74
118
|
}
|
|
119
|
+
/** A change as staged under deferred sequencing — the feed row without its `seq`. */
|
|
120
|
+
function stagedRow(entry, at) {
|
|
121
|
+
return {
|
|
122
|
+
scope: entry.scope,
|
|
123
|
+
docId: entry.docId,
|
|
124
|
+
op: entry.op,
|
|
125
|
+
version: entry.version,
|
|
126
|
+
...entry.op === "upsert" && entry.doc !== void 0 ? { doc: entry.doc } : {},
|
|
127
|
+
...entry.tenantId !== void 0 ? { tenantId: entry.tenantId } : {},
|
|
128
|
+
at
|
|
129
|
+
};
|
|
130
|
+
}
|
|
75
131
|
/** Fixed-width, so the opaque cursor also sorts as text. */
|
|
76
132
|
const toCursor = (seq) => String(seq).padStart(16, "0");
|
|
77
133
|
const fromCursor = (cursor) => {
|
|
@@ -81,8 +137,96 @@ const fromCursor = (cursor) => {
|
|
|
81
137
|
return seq;
|
|
82
138
|
};
|
|
83
139
|
const DEFAULT_LIMIT = 500;
|
|
140
|
+
/** How long one sequencer holds the lease — far above one batch, so a live holder never loses it mid-batch. */
|
|
141
|
+
const SEQUENCER_LEASE_MS = 3e4;
|
|
142
|
+
const SEQUENCER_BATCH = 500;
|
|
84
143
|
function createChangeLogStore(models) {
|
|
85
|
-
const { entries, counter, feed } = models;
|
|
144
|
+
const { entries, counter, feed, pending } = models;
|
|
145
|
+
const deferred = models.sequencing === "deferred" && pending !== void 0;
|
|
146
|
+
/**
|
|
147
|
+
* One pass under the lease: committed staged rows → the feed, in staging order, numbered above everything.
|
|
148
|
+
* Nothing staged costs ONE read. A crash mid-pass is converged by the next one: an entry already in the feed is
|
|
149
|
+
* recognised by its unique `pendingId`, and a stale counter is caught by the unique `seq` index.
|
|
150
|
+
*/
|
|
151
|
+
const sequencePending = async () => {
|
|
152
|
+
if (!deferred || !pending) return 0;
|
|
153
|
+
if (!await pending.exists({}).exec()) return 0;
|
|
154
|
+
const token = new Types.ObjectId().toString();
|
|
155
|
+
const unlocked = {
|
|
156
|
+
_id: feed,
|
|
157
|
+
$or: [
|
|
158
|
+
{ lockUntil: { $exists: false } },
|
|
159
|
+
{ lockUntil: null },
|
|
160
|
+
{ lockUntil: { $lt: /* @__PURE__ */ new Date() } }
|
|
161
|
+
]
|
|
162
|
+
};
|
|
163
|
+
const takeLease = () => counter.findOneAndUpdate(unlocked, { $set: {
|
|
164
|
+
lockUntil: new Date(Date.now() + SEQUENCER_LEASE_MS),
|
|
165
|
+
lockBy: token
|
|
166
|
+
} }, {
|
|
167
|
+
returnDocument: "after",
|
|
168
|
+
lean: true
|
|
169
|
+
}).exec();
|
|
170
|
+
let lease = await takeLease();
|
|
171
|
+
if (!lease) {
|
|
172
|
+
if (await counter.exists({ _id: feed }).exec()) return null;
|
|
173
|
+
await counter.create([{
|
|
174
|
+
_id: feed,
|
|
175
|
+
seq: 0
|
|
176
|
+
}]).catch((err) => {
|
|
177
|
+
if (err.code !== 11e3) throw err;
|
|
178
|
+
});
|
|
179
|
+
lease = await takeLease();
|
|
180
|
+
if (!lease) return null;
|
|
181
|
+
}
|
|
182
|
+
let seq = lease.seq ?? 0;
|
|
183
|
+
let numbered = 0;
|
|
184
|
+
try {
|
|
185
|
+
for (;;) {
|
|
186
|
+
const rows = await pending.find({}).sort({ _id: 1 }).limit(SEQUENCER_BATCH).lean().exec();
|
|
187
|
+
if (rows.length === 0) break;
|
|
188
|
+
const build = (from, list) => list.map((r, i) => {
|
|
189
|
+
const { _id, ...rest } = r;
|
|
190
|
+
return {
|
|
191
|
+
...rest,
|
|
192
|
+
seq: from + i + 1,
|
|
193
|
+
pendingId: String(_id)
|
|
194
|
+
};
|
|
195
|
+
});
|
|
196
|
+
try {
|
|
197
|
+
await entries.insertMany(build(seq, rows), { ordered: true });
|
|
198
|
+
seq += rows.length;
|
|
199
|
+
numbered += rows.length;
|
|
200
|
+
} catch (err) {
|
|
201
|
+
if (err.code !== 11e3) throw err;
|
|
202
|
+
const placed = new Set((await entries.find({ pendingId: { $in: rows.map((r) => String(r._id)) } }).select({ pendingId: 1 }).lean().exec()).map((e) => e.pendingId));
|
|
203
|
+
const fresh = rows.filter((r) => !placed.has(String(r._id)));
|
|
204
|
+
const top = await entries.findOne({}).sort({ seq: -1 }).select({ seq: 1 }).lean().exec();
|
|
205
|
+
seq = Math.max(seq, top?.seq ?? 0);
|
|
206
|
+
if (fresh.length > 0) {
|
|
207
|
+
await entries.insertMany(build(seq, fresh), { ordered: true });
|
|
208
|
+
seq += fresh.length;
|
|
209
|
+
numbered += fresh.length;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
await counter.updateOne({
|
|
213
|
+
_id: feed,
|
|
214
|
+
lockBy: token
|
|
215
|
+
}, { $max: { seq } }).exec();
|
|
216
|
+
await pending.deleteMany({ _id: { $in: rows.map((r) => r._id) } }).exec();
|
|
217
|
+
if (rows.length < SEQUENCER_BATCH) break;
|
|
218
|
+
}
|
|
219
|
+
} finally {
|
|
220
|
+
await counter.updateOne({
|
|
221
|
+
_id: feed,
|
|
222
|
+
lockBy: token
|
|
223
|
+
}, { $set: {
|
|
224
|
+
lockUntil: null,
|
|
225
|
+
lockBy: null
|
|
226
|
+
} }).exec();
|
|
227
|
+
}
|
|
228
|
+
return numbered;
|
|
229
|
+
};
|
|
86
230
|
const sessionOf = (options) => options?.session ? { session: options.session } : {};
|
|
87
231
|
const filterOf = (after, options = {}) => {
|
|
88
232
|
const { tenantId, scopes, sharedScopes } = options;
|
|
@@ -104,8 +248,37 @@ function createChangeLogStore(models) {
|
|
|
104
248
|
cursor: toCursor(row.seq)
|
|
105
249
|
});
|
|
106
250
|
return {
|
|
251
|
+
sequencePending,
|
|
252
|
+
async stage(entry, options) {
|
|
253
|
+
if (!deferred || !pending) {
|
|
254
|
+
await this.append(entry, options);
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
await pending.create([stagedRow(entry, /* @__PURE__ */ new Date())], sessionOf(options));
|
|
258
|
+
},
|
|
107
259
|
async append(entry, options) {
|
|
108
260
|
const session = sessionOf(options);
|
|
261
|
+
if (deferred && pending) {
|
|
262
|
+
const at = /* @__PURE__ */ new Date();
|
|
263
|
+
const [staged] = await pending.create([stagedRow(entry, at)], session);
|
|
264
|
+
if (options?.session) return {
|
|
265
|
+
...entry,
|
|
266
|
+
at,
|
|
267
|
+
cursor: ""
|
|
268
|
+
};
|
|
269
|
+
const stagedId = String(staged?._id);
|
|
270
|
+
for (let attempt = 0; attempt < 50; attempt++) {
|
|
271
|
+
await sequencePending();
|
|
272
|
+
const at2 = await entries.findOne({ pendingId: stagedId }).select({ seq: 1 }).lean().exec();
|
|
273
|
+
if (typeof at2?.seq === "number") return {
|
|
274
|
+
...entry,
|
|
275
|
+
at,
|
|
276
|
+
cursor: toCursor(at2.seq)
|
|
277
|
+
};
|
|
278
|
+
await new Promise((r) => setTimeout(r, 20));
|
|
279
|
+
}
|
|
280
|
+
throw new Error(`[mongokit:sync] staged entry ${stagedId} was not sequenced — a sequencer lease is stuck`);
|
|
281
|
+
}
|
|
109
282
|
const seq = (await counter.findOneAndUpdate({ _id: feed }, { $inc: { seq: 1 } }, {
|
|
110
283
|
upsert: true,
|
|
111
284
|
returnDocument: "after",
|
|
@@ -130,6 +303,7 @@ function createChangeLogStore(models) {
|
|
|
130
303
|
};
|
|
131
304
|
},
|
|
132
305
|
async since(cursor, options = {}) {
|
|
306
|
+
if (deferred) await sequencePending();
|
|
133
307
|
const limit = options.limit ?? DEFAULT_LIMIT;
|
|
134
308
|
const rows = await entries.find(filterOf(fromCursor(cursor), options)).sort({ seq: 1 }).limit(limit + 1).lean().exec();
|
|
135
309
|
const page = rows.slice(0, limit).map(toEntry);
|
|
@@ -141,6 +315,7 @@ function createChangeLogStore(models) {
|
|
|
141
315
|
};
|
|
142
316
|
},
|
|
143
317
|
async latestCursor(options = {}) {
|
|
318
|
+
if (deferred) await sequencePending();
|
|
144
319
|
const row = await entries.findOne(filterOf(0, options)).sort({ seq: -1 }).select({ seq: 1 }).lean().exec();
|
|
145
320
|
return row?.seq ? toCursor(row.seq) : "";
|
|
146
321
|
},
|
package/dist/testkit/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as createRepository } from "../create-repository-
|
|
1
|
+
import { t as createRepository } from "../create-repository-Bg0H5rte.mjs";
|
|
2
2
|
import { createConnection } from "mongoose";
|
|
3
3
|
//#region src/testkit/query-plan.ts
|
|
4
4
|
const PLANNABLE = /* @__PURE__ */ new Set([
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as ALL_OPERATIONS, o as OP_REGISTRY, t as HOOK_PRIORITY } from "./Repository-
|
|
1
|
+
import { i as ALL_OPERATIONS, o as OP_REGISTRY, t as HOOK_PRIORITY } from "./Repository-DlhPbXlG.mjs";
|
|
2
2
|
import { n as warn } from "./logger-K7dPmu2U.mjs";
|
|
3
3
|
import { n as declareCollectionScope } from "./join-scope-DSAznE8E.mjs";
|
|
4
4
|
import { throwIfAborted, withRetry } from "@classytic/repo-core/repository";
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { t as createError } from "./error-BuByZwKU.mjs";
|
|
1
2
|
import { d as setTransactionDeadline } from "./query-defaults-BxUcSOoF.mjs";
|
|
2
3
|
import mongoose from "mongoose";
|
|
3
4
|
import { setTimeout as setTimeout$1 } from "node:timers/promises";
|
|
@@ -436,6 +437,12 @@ function createTxBoundRepo(outer, session) {
|
|
|
436
437
|
*/
|
|
437
438
|
async function withTransaction(connection, callback, options = {}) {
|
|
438
439
|
const session = await connection.startSession();
|
|
440
|
+
try {
|
|
441
|
+
assertSessionSurface(session, [...DRIVEN, "endSession"]);
|
|
442
|
+
} catch (err) {
|
|
443
|
+
if (typeof session.endSession === "function") await session.endSession();
|
|
444
|
+
throw err;
|
|
445
|
+
}
|
|
439
446
|
try {
|
|
440
447
|
return await runTransaction(session, callback, options.transactionOptions);
|
|
441
448
|
} catch (error) {
|
|
@@ -449,6 +456,25 @@ async function withTransaction(connection, callback, options = {}) {
|
|
|
449
456
|
await session.endSession();
|
|
450
457
|
}
|
|
451
458
|
}
|
|
459
|
+
const TRANSACTION_ERROR_CODES = {
|
|
460
|
+
/** The session lacks a method the transaction loop drives (a partial or wrapped fake). */
|
|
461
|
+
SESSION_INCOMPLETE: "mongokit.transaction.session_incomplete" };
|
|
462
|
+
const DRIVEN = [
|
|
463
|
+
"startTransaction",
|
|
464
|
+
"commitTransaction",
|
|
465
|
+
"abortTransaction",
|
|
466
|
+
"inTransaction"
|
|
467
|
+
];
|
|
468
|
+
/** Refuse, with the missing names, a session that cannot be driven, before calling anything on it. */
|
|
469
|
+
function assertSessionSurface(session, required) {
|
|
470
|
+
const s = session ?? {};
|
|
471
|
+
const missing = required.filter((name) => typeof s[name] !== "function");
|
|
472
|
+
if (missing.length === 0) return;
|
|
473
|
+
throw createError(500, `[mongokit] the transaction session lacks ${missing.join(", ")}; pass a driver ClientSession`, {
|
|
474
|
+
code: TRANSACTION_ERROR_CODES.SESSION_INCOMPLETE,
|
|
475
|
+
meta: { missing }
|
|
476
|
+
});
|
|
477
|
+
}
|
|
452
478
|
const MAX_TRANSACTION_TIMEOUT_MS = 12e4;
|
|
453
479
|
const BACKOFF_INITIAL_MS = 5;
|
|
454
480
|
const BACKOFF_MAX_MS = 500;
|
|
@@ -478,6 +504,7 @@ function timeoutError(cause, csot) {
|
|
|
478
504
|
* Pinned by `tests/integration/csot-transaction-matrix.test.ts`.
|
|
479
505
|
*/
|
|
480
506
|
async function runTransaction(session, callback, transactionOptions = {}) {
|
|
507
|
+
assertSessionSurface(session, DRIVEN);
|
|
481
508
|
const { timeoutMS: explicitTimeout, ...startOptions } = transactionOptions;
|
|
482
509
|
const clientTimeout = session.timeoutMS;
|
|
483
510
|
const timeoutMS = explicitTimeout ?? clientTimeout;
|
|
@@ -652,4 +679,4 @@ function supportsTransactions(connection) {
|
|
|
652
679
|
return resolveTransactionSupport(connection) !== "no";
|
|
653
680
|
}
|
|
654
681
|
//#endregion
|
|
655
|
-
export {
|
|
682
|
+
export { supportsTransactions as a, MONGOKIT_CAPABILITIES as c, probeMongoCapabilities as d, resetCapabilityProbeCache as f, transactionResolutionOf as h, runTransaction as i, capabilitiesForSupport as l, resolveTransactionSupport as m, batchTransaction as n, withTransaction as o, resolveMongoCapabilities as p, isTransactionUnsupported as r, createTxBoundRepo as s, TRANSACTION_ERROR_CODES as t, classifyHelloReply as u };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { n as collectIds, r as idChunks, t as DEFAULT_ID_CHUNK } from "./id-chunks-BmAwsqNk.mjs";
|
|
2
|
-
import { i as ALL_OPERATIONS, o as OP_REGISTRY } from "./Repository-
|
|
2
|
+
import { i as ALL_OPERATIONS, o as OP_REGISTRY } from "./Repository-DlhPbXlG.mjs";
|
|
3
3
|
import { w as upsert } from "./update-WgeAUJ_I.mjs";
|
|
4
4
|
import { n as warn } from "./logger-K7dPmu2U.mjs";
|
|
5
5
|
import { t as createError } from "./error-BuByZwKU.mjs";
|
|
6
|
-
import { c as tenantContextKeysOf, o as forwardScope } from "./timestamp.plugin-
|
|
6
|
+
import { c as tenantContextKeysOf, o as forwardScope } from "./timestamp.plugin-DvZlnKEc.mjs";
|
|
7
7
|
import { r as getFieldsForUser } from "./field-selection-FSQFLpsU.mjs";
|
|
8
8
|
import mongoose from "mongoose";
|
|
9
9
|
import { HOOK_PRIORITY } from "@classytic/repo-core/hooks";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@classytic/mongokit",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.42.0",
|
|
4
4
|
"description": "Production-grade MongoDB repositories - smart pagination, events, and plugins. Built on @classytic/repo-core.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -148,7 +148,7 @@
|
|
|
148
148
|
"peerDependencies": {
|
|
149
149
|
"@classytic/repo-core": ">=0.31.0",
|
|
150
150
|
"mongodb-memory-server": ">=10.4.3",
|
|
151
|
-
"mongoose": ">=9.
|
|
151
|
+
"mongoose": ">=9.11.0"
|
|
152
152
|
},
|
|
153
153
|
"peerDependenciesMeta": {
|
|
154
154
|
"mongodb-memory-server": {
|
|
@@ -199,7 +199,7 @@
|
|
|
199
199
|
"@better-auth/mongo-adapter": "^1.6.29",
|
|
200
200
|
"@biomejs/biome": "^2.5.8",
|
|
201
201
|
"@classytic/dev-tools": "^0.2.0",
|
|
202
|
-
"@classytic/repo-core": "^0.31.
|
|
202
|
+
"@classytic/repo-core": "^0.31.1",
|
|
203
203
|
"@types/node": "^26.2.0",
|
|
204
204
|
"@vitest/coverage-v8": "^4.1.10",
|
|
205
205
|
"ajv": "^8.20.0",
|
|
@@ -210,7 +210,7 @@
|
|
|
210
210
|
"knip": "^6.32.2",
|
|
211
211
|
"mongodb": "^7.5.0",
|
|
212
212
|
"mongodb-memory-server": "^11.2.0",
|
|
213
|
-
"mongoose": "^9.
|
|
213
|
+
"mongoose": "^9.11.1",
|
|
214
214
|
"publint": "^0.3.23",
|
|
215
215
|
"tsdown": "^0.22.14",
|
|
216
216
|
"typescript": "~5.9.3",
|